:root {
  /* Antes --bg y --bg-card eran el mismo casi-negro (#0b0b0a) — las tarjetas
     solo se distinguían del fondo por el borde/sombra, y todo se sentía muy
     oscuro en conjunto. Ahora hay tres tonos de gris oscuro bien diferenciados
     en vez de negro puro: fondo < tarjeta < superficie elevada (inputs, hover,
     barra lateral). */
  --bg: #141518;
  --bg-chrome: #0f1013;
  --bg-elevated: #242424;
  --bg-card: #1f2024;
  --accent: #5865F2;
  --accent-hover: #4752c4;
  --accent-soft: rgba(88, 101, 242, 0.12);
  --danger: #da373c;
  --success: #22c55e;
  --text: #f2f3f5;
  --text-bright-muted: #c9cbd3;
  --text-muted: #9a9ca3;
  --text-faint: #6b6d76;
  --border: #202127;
  --border-soft: #16171c;
  --border-strong: #35363f;
  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.24), 0 8px 24px -12px rgba(0, 0, 0, 0.5);
  --font-sans: 'Plus Jakarta Sans', 'Inter', 'Helvetica Neue', Arial, sans-serif;
  --font-mono: 'JetBrains Mono', 'SFMono-Regular', Consolas, monospace;
  /* Curva de easing tipo "ease-out" pronunciada — para hovers y entradas que
     se sientan rápidas al arrancar y frenan suave, en vez del "ease" plano
     por defecto del navegador. */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
}

* { box-sizing: border-box; }

html {
  /* Sin esto, el navegador asume que la página es clara para todo lo que
     dibuja él mismo (no el CSS) — el texto de placeholder de los inputs, el
     color por defecto del scrollbar, etc. — y esas cosas salían en tonos
     oscuros pensados para un fondo blanco, casi invisibles sobre el fondo
     oscuro real del panel. */
  color-scheme: dark;
}

body {
  margin: 0;
  font-family: var(--font-sans);
  background: var(--bg);
  color: var(--text);
  /* Red de seguridad: algún elemento suelto (posicionado absoluto, una caja
     mal dimensionada, etc.) puede terminar más ancho que el viewport y forzar
     un scroll horizontal de toda la página — nunca es intencional acá, así
     que se recorta a nivel body en vez de perseguir cada caso uno por uno.
     Los contenedores que SÍ necesitan scroll horizontal propio (tablas, etc.)
     ya usan su propio overflow-x: auto, así que no los afecta. */
  overflow-x: hidden;
}

input::placeholder, textarea::placeholder { color: var(--text-faint); opacity: 1; }

a { color: inherit; }

/* --- Layout shell --- */
.app-shell { display: flex; min-height: 100vh; }

.sidebar {
  width: 280px;
  flex-shrink: 0;
  background: var(--bg-chrome);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  padding: 18px 10px;
  position: sticky;
  top: 0;
  height: 100vh;
  /* 100vh en el celular se calcula como si la barra de direcciones del
     navegador estuviera siempre oculta — si el navegador la muestra abajo
     (Chrome/Safari en Android/iOS), la barra lateral queda más alta que lo
     que en verdad se ve, y la parte de abajo (los últimos módulos) no hay
     forma de scrollear hasta ahí porque están fuera del viewport real.
     100dvh sí se ajusta a la altura visible de verdad; se declara después
     como mejora progresiva para los navegadores que la soportan. */
  height: 100dvh;
}

/* Logo + servidor + buscador de módulos: bloque fijo de verdad (no
   position:sticky) — es hermano de .sidebar-body, no un elemento adentro de
   su scroll, así que no hay forma de que algo se dibuje "por encima" de él
   al desplazar la lista de módulos. */
.sidebar-header {
  position: relative; flex-shrink: 0;
  background: var(--bg-chrome);
  padding-bottom: 6px;
}
/* Línea sutil que marca dónde termina lo fijo y arranca lo que se
   desplaza — solo aparece una vez que .sidebar-body se scrolleó un poco,
   para no mostrar un borde de más cuando está arriba del todo. */
.sidebar-header::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0;
  height: 1px; background: var(--border-soft);
  opacity: 0; transition: opacity 0.15s ease;
}
.sidebar-header.is-scrolled::after { opacity: 1; }

/* El resto de la navegación: el único que scrollea. Si no entra en lo que
   queda de alto, se desplaza acá adentro en vez de cortarse sin forma de
   llegar a los últimos ítems — el header de arriba nunca se mueve. */
.sidebar-body {
  flex: 1; min-height: 0; overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: var(--border) transparent;
}

.sidebar-brand { display: flex; align-items: center; gap: 12px; padding: 0 6px 18px 6px; text-decoration: none; }
.brand-icon {
  width: 38px; height: 38px; border-radius: 10px;
  background: linear-gradient(135deg, var(--accent), #8b5cf6);
  display: flex; align-items: center; justify-content: center; font-size: 1.1rem;
  flex-shrink: 0; color: white;
}
.brand-icon-img { object-fit: cover; background: none; }
.brand-text { min-width: 0; }
.brand-name { font-weight: 700; font-size: 1rem; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sidebar-brand:hover .brand-name { color: var(--accent); }

.platform-icon { width: 28px; height: 28px; object-fit: contain; flex-shrink: 0; vertical-align: middle; }
.wave-icon { width: 20px; height: 20px; color: #FFFFFF; vertical-align: middle; }
.modules-icon { width: 16px; height: 16px; color: var(--text-muted); }
.modules-toggle:hover .modules-icon { color: var(--text); }

/* --- Selector de color personalizado: cuadro de saturación/brillo + tono + preajustes + hex --- */
.color-picker { position: relative; display: inline-block; }
/* Con la fila compacta (quickPresets), el selector deja de "abrazar" su
   propio contenido y pasa a ocupar el ancho completo de la columna, igual
   que el select/input de arriba — así el borde derecho de la fila siempre
   coincide con el de ellos, sin importar el tamaño de pantalla. Solo afecta
   a esta variante: el selector suelto de siempre sigue siendo inline-block. */
.color-picker:has(.color-picker-quick) { display: block; width: 100%; }
.color-picker-swatch {
  width: 52px; height: 52px; padding: 0; border: 2px solid var(--border); border-radius: 50%;
  cursor: pointer; display: flex; align-items: center; justify-content: center;
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.color-picker-swatch:hover, .color-picker.open .color-picker-swatch { border-color: var(--accent); transform: scale(1.04); }
/* Mismo ícono de anillo de puntos en TODOS lados donde se elige un color
   (ver partials/color-picker.ejs) — acá, en el botón grande de 52px, se ve
   más grande que en la fila compacta de abajo. */
.color-picker-wheel-icon { width: 30px; height: 30px; pointer-events: none; filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.5)); }

/* --- Variante compacta: fila de presets de un clic + el mismo botón redondo
   de siempre (achicado) para abrir el selector completo — ver quickPresets
   en partials/color-picker.ejs. Fondo #17181c IGUAL al de cualquier
   select/input (ver la regla compartida de inputs más abajo en este mismo
   archivo) — antes usaba --bg-elevated y quedaba un tono más claro que el
   resto de los campos del mismo formulario. Sin flex-wrap a propósito: los
   tamaños de abajo están pensados para que 8 presets + el botón entren en
   una sola línea incluso en una columna angosta (~280px). */
.color-picker-quick {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: nowrap; gap: 5px;
  background: #17181c; border: 1px solid var(--border); border-radius: 14px;
  padding: 6px 10px; max-width: 100%;
}
.color-picker-quick .color-picker-preset { width: 22px; height: 22px; }
/* El botón de "más colores" muestra el color YA elegido, igual que el
   grande — mismo formato en todos lados, la única diferencia real es el
   tamaño. Un poco más grande que los puntos de preset (28px vs 22px) para
   que se note que es la acción de "elegir otro", no un color más de la fila. */
.color-picker-swatch-wheel {
  width: 28px; height: 28px; padding: 0; border: 2px solid var(--border); border-radius: 50%;
  cursor: pointer; display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.color-picker-swatch-wheel:hover, .color-picker.open .color-picker-swatch-wheel {
  border-color: var(--accent); transform: scale(1.06);
}
.color-picker-swatch-wheel .color-picker-wheel-icon { width: 18px; height: 18px; }

.color-picker-popover {
  display: none; position: absolute; top: calc(100% + 10px); left: 0; z-index: 60;
  width: 220px; padding: 14px; border-radius: 12px;
  background: var(--bg-card); border: 1px solid var(--border);
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
}
.color-picker.open .color-picker-popover { display: block; }

.color-picker-sb {
  position: relative; width: 100%; height: 130px; border-radius: 8px; margin-bottom: 12px;
  background-image: linear-gradient(to top, #000, rgba(0, 0, 0, 0)), linear-gradient(to right, #fff, rgba(255, 255, 255, 0));
  cursor: crosshair; touch-action: none; overflow: hidden;
}
.color-picker-sb-thumb {
  position: absolute; width: 14px; height: 14px; border-radius: 50%;
  border: 2px solid #fff; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.4), 0 1px 3px rgba(0, 0, 0, 0.5);
  transform: translate(-50%, -50%); pointer-events: none;
}

.color-picker-hue {
  position: relative; width: 100%; height: 14px; border-radius: 7px; margin-bottom: 14px;
  background: linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00);
  cursor: pointer; touch-action: none;
}
.color-picker-hue-thumb {
  position: absolute; top: 50%; width: 18px; height: 18px; border-radius: 50%;
  background: #fff; border: 2px solid #fff; box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.4), 0 1px 3px rgba(0, 0, 0, 0.5);
  transform: translate(-50%, -50%); pointer-events: none;
}

.color-picker-presets { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.color-picker-preset {
  width: 22px; height: 22px; border-radius: 50%; border: 2px solid rgba(255, 255, 255, 0.15);
  cursor: pointer; padding: 0; transition: transform 0.1s ease;
}
.color-picker-preset:hover { transform: scale(1.12); }

.color-picker-hex {
  display: flex; align-items: center; gap: 8px;
  background: var(--bg-elevated); border: 1px solid var(--border); border-radius: 8px; padding: 8px 12px;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.color-picker-hex:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.color-picker-hex-prefix { color: var(--text-faint); font-family: var(--font-mono); font-size: 0.9rem; }
input[type="text"].color-picker-hex-input {
  flex: 1; min-width: 0; width: auto; padding: 0; border: none; background: none; color: var(--text);
  font-family: var(--font-mono); font-size: 0.9rem;
}
input[type="text"].color-picker-hex-input:focus {
  outline: none; border-color: transparent; box-shadow: none;
}

.sidebar-nav { display: flex; flex-direction: column; gap: 4px; margin-top: 8px; }

/* Empuja el contenido de más arriba hacia arriba, dejando el resto del alto
   disponible vacío al fondo del panel. */
.sidebar-spacer { flex: 1; min-height: 24px; }

.main-area { flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 100vh; }

/* --- Marca del bot en la barra superior (login, selección de servidor) --- */
.topbar-brand { display: flex; align-items: center; gap: 10px; text-decoration: none; min-width: 0; }
.topbar-brand-icon {
  width: 38px; height: 38px; border-radius: 10px; object-fit: cover; flex-shrink: 0;
}
.topbar-brand-icon-fallback {
  background: linear-gradient(135deg, var(--accent), #8b5cf6);
  display: flex; align-items: center; justify-content: center; color: white;
}
.topbar-brand-name {
  font-weight: 700; font-size: 1rem; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: color 0.12s ease;
}
.topbar-brand:hover .topbar-brand-name { color: var(--accent); }

.topbar-link {
  position: relative;
  font-size: 0.88rem; font-weight: 600; color: var(--text);
  text-decoration: none; padding: 4px 2px;
  transition: color 0.15s ease;
}
.topbar-link::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: -2px;
  height: 2px;
  background: var(--accent);
  border-radius: 2px;
  transform: scaleX(0);
  transition: transform 0.25s cubic-bezier(0.4, 0, 0.2, 1);
}
.topbar-link:hover { color: var(--accent); }
.topbar-link:hover::after { transform: scaleX(1); }
.topbar-link.active { color: var(--accent); }
.topbar-link.active::after { transform: scaleX(1); }

.topbar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 32px; border-bottom: 1px solid var(--border);
  background: var(--bg-chrome);
  position: sticky; top: 0; z-index: 20;
}
/* Cuando hay nav central (Inicio/Comandos/Utilidades/Panel del bot), usamos
   grid en vez de flex: cada columna tiene su espacio reservado (nunca se
   superponen), y la del medio queda centrada de verdad — a diferencia de
   position:absolute, esto no se rompe en anchos intermedios. */
.topbar.has-center-nav {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  column-gap: 16px;
}
.topbar.has-center-nav .topbar-left { justify-self: start; min-width: 0; overflow: hidden; }
.topbar.has-center-nav .topbar-center-nav { justify-self: center; }
.topbar.has-center-nav .topbar-right { justify-self: end; min-width: 0; overflow: hidden; }

.topbar-right { display: flex; align-items: center; gap: 12px; }
.topbar-left { display: flex; align-items: center; gap: 18px; min-width: 0; }

.lang-switcher { position: relative; }
.lang-switcher-current {
  display: flex; align-items: center; gap: 7px;
  background: none; border: none;
  padding: 4px 2px; cursor: pointer; color: var(--text);
  font-family: var(--font-sans); font-size: 0.82rem; font-weight: 600;
}
.lang-switcher-current:hover .lang-code { color: var(--accent); }
.flag-icon { border-radius: 2px; flex-shrink: 0; display: block; box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08); }
.lang-chevron { width: 14px; height: 14px; color: var(--text-faint); transition: transform 0.15s ease; }
.lang-switcher.open .lang-chevron { transform: rotate(180deg); }

.lang-switcher-dropdown {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 30;
  background: var(--bg-elevated); border: 1px solid var(--border); border-radius: 8px;
  min-width: 130px; padding: 4px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  opacity: 0; transform: translateY(-6px); pointer-events: none;
  transition: opacity 0.15s ease, transform 0.15s ease;
}
.lang-switcher.open .lang-switcher-dropdown { opacity: 1; transform: translateY(0); pointer-events: auto; }
.lang-switcher-option {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px; border-radius: 6px;
  color: var(--text); text-decoration: none; font-size: 0.85rem; font-weight: 500;
}
.lang-switcher-option:hover { background: var(--bg-card); }

.mobile-sidebar-toggle {
  display: none; /* solo aparece en móvil, ver media query */
  align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 8px;
  background: var(--bg-card); border: 1px solid var(--border); color: var(--text-muted);
  cursor: pointer; flex-shrink: 0;
}
.mobile-sidebar-toggle svg { width: 18px; height: 18px; }
.mobile-sidebar-toggle:hover { color: var(--text); border-color: var(--accent); }

/* --- Panel lateral en móvil: se abre como un cajón (drawer) sobre el contenido --- */
.sidebar-close { display: none; }
.sidebar-backdrop {
  display: none; position: fixed; inset: 0; z-index: 299;
  background: rgba(0, 0, 0, 0.55); opacity: 0; transition: opacity 0.2s ease;
}
.sidebar-backdrop.show { display: block; opacity: 1; }
body.sidebar-open { overflow: hidden; }
.topbar-center-nav {
  display: flex; align-items: center; justify-content: center; gap: 28px;
}

/* Ola animada arriba del pie de página, en las páginas públicas — dos capas
   suaves con los mismos colores del degradé de fondo del login (azul/violeta
   del acento + verde), para que se sienta parte del mismo lenguaje visual en
   vez de una franja de color suelta. Cada <svg> dibuja el mismo trazo dos
   veces seguidas (con <use x="1200">) y se anima corriendo exactamente un
   ancho de trazo (translateX -50%, la mitad de su propio ancho renderizado)
   — al llegar ahí el dibujo es idéntico al inicio, así el loop no se nota. */
/* Las dos capas tienen una parte plana en la base del trazo (donde el path
   baja hasta el fondo del viewBox) — sin este degradé, esa parte plana queda
   pegada justo contra el pie de página y se ve como una línea recta. */
.footer-wave {
  position: relative; width: 100%; height: 90px; overflow: hidden; margin-top: 12px;
  -webkit-mask-image: linear-gradient(to bottom, black 0%, black 55%, transparent 100%);
  mask-image: linear-gradient(to bottom, black 0%, black 55%, transparent 100%);
}
.footer-wave-svg { position: absolute; bottom: 0; left: 0; width: 200%; height: 100%; }
.footer-wave-svg-1 { fill: rgba(88, 101, 242, 0.16); animation: footer-wave-scroll 26s linear infinite; }
.footer-wave-svg-2 { fill: rgba(87, 242, 135, 0.10); animation: footer-wave-scroll 38s linear infinite reverse; }
@keyframes footer-wave-scroll {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .footer-wave-svg { animation: none; }
}

/* --- Pie de página (solo en páginas públicas: login, comandos, utilidades) --- */
.site-footer {
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px;
  padding: 24px 32px;
  font-size: 0.82rem; color: var(--text-faint);
}
.site-footer-links { display: flex; gap: 20px; }
.site-footer-links a { color: var(--text-faint); text-decoration: none; }
.site-footer-links a:hover { color: var(--text-muted); text-decoration: underline; }

.status-badge {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--text-muted); background: var(--bg-card); border: 1px solid var(--border);
  padding: 6px 12px; border-radius: 6px;
}
.status-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--success); flex-shrink: 0; }
.status-badge.offline .status-dot { background: var(--danger); }

.user-chip { display: flex; align-items: center; gap: 8px; font-size: 0.9rem; color: var(--text-muted); }
.user-chip img { width: 24px; height: 24px; border-radius: 50%; }

.guild-indicator {
  display: flex; align-items: center; gap: 8px; font-size: 0.88rem; font-weight: 600; color: var(--text-muted);
  max-width: 220px;
}
.guild-indicator img { width: 24px; height: 24px; border-radius: 6px; object-fit: cover; flex-shrink: 0; }
.guild-indicator-fallback {
  width: 24px; height: 24px; border-radius: 6px; flex-shrink: 0;
  background: var(--accent); color: white; font-weight: 700; font-size: 0.72rem;
  display: flex; align-items: center; justify-content: center;
}
.guild-indicator span:last-child { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text); }
.sidebar-guild-indicator {
  max-width: none; padding: 7px 9px; gap: 8px;
  background: var(--bg-card); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 9px;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.15), 0 1px 3px rgba(0, 0, 0, 0.2);
  font-size: 0.88rem; font-weight: 700;
}
.sidebar-guild-indicator img, .sidebar-guild-indicator .guild-indicator-fallback { width: 26px; height: 26px; border-radius: 7px; }
.sidebar-guild-indicator .guild-indicator-fallback { font-size: 0.78rem; }

/* Desplegable para cambiar de servidor desde el sidebar (reemplaza el viejo
   enlace fijo "Mis servidores"): la caja de arriba es el botón que abre/cierra
   un panel con buscador y la lista de los demás servidores administrables. */
.sidebar-guild-switcher { position: relative; margin: 0 0 14px 0; }
.sidebar-guild-trigger { width: 100%; cursor: pointer; appearance: none; font-family: var(--font-sans); }
.sidebar-guild-trigger-text { display: flex; flex-direction: column; align-items: flex-start; gap: 1px; flex: 1; min-width: 0; }
.sidebar-guild-trigger-name { color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.sidebar-guild-trigger-label { font-size: 0.66rem; font-weight: 500; color: var(--text-faint); }
.sidebar-guild-chevron { width: 14px; height: 14px; color: var(--text-faint); flex-shrink: 0; transition: transform 0.15s ease; }
.sidebar-guild-switcher.open .sidebar-guild-chevron { transform: rotate(180deg); }

.sidebar-guild-dropdown {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 30;
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--bg-elevated); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  opacity: 0; transform: translateY(-6px); pointer-events: none;
  transition: opacity 0.15s ease, transform 0.15s ease;
}
.sidebar-guild-switcher.open .sidebar-guild-dropdown { opacity: 1; transform: translateY(0); pointer-events: auto; }
.sidebar-guild-search {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px; border-bottom: 1px solid var(--border); flex-shrink: 0;
}
.sidebar-guild-search svg { width: 16px; height: 16px; color: var(--text-faint); flex-shrink: 0; }
.sidebar-guild-search input {
  flex: 1; min-width: 0; background: none; border: none; outline: none;
  color: var(--text); font-family: var(--font-sans); font-size: 0.85rem;
}
.sidebar-guild-search input::placeholder { color: var(--text-faint); }
.sidebar-guild-list { overflow-y: auto; max-height: 220px; padding: 6px; }
.sidebar-guild-option {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: 8px;
  color: var(--text); text-decoration: none; font-size: 0.85rem; font-weight: 600;
}
.sidebar-guild-option:hover { background: var(--bg-card); }
.sidebar-guild-option.active { background: rgba(88, 101, 242, 0.15); color: var(--accent); }
.sidebar-guild-option img, .sidebar-guild-option .guild-indicator-fallback { width: 24px; height: 24px; border-radius: 6px; flex-shrink: 0; }
.sidebar-guild-option-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sidebar-guild-invite-badge {
  flex-shrink: 0; padding: 2px 8px; border-radius: 6px;
  background: var(--accent-soft); color: var(--accent); font-size: 0.7rem; font-weight: 700;
}
.sidebar-guild-empty { padding: 14px 12px; text-align: center; color: var(--text-faint); font-size: 0.82rem; }

/* Selector de zona horaria (Ajustes → General): mismo patrón de "botón que
   abre un desplegable con buscador" que el de cambiar de servidor de arriba,
   pero de ancho completo para vivir adentro de un formulario normal. */
.tz-select { position: relative; }
.tz-select-trigger {
  width: 100%; display: flex; align-items: center; gap: 10px;
  padding: 10px 14px; background: var(--bg-card); border: 1px solid var(--border-strong); border-radius: 8px;
  color: var(--text); font-family: var(--font-sans); font-size: 0.88rem; font-weight: 600; cursor: pointer;
}
.tz-select-trigger svg:first-child { color: var(--text-faint); flex-shrink: 0; }
.tz-select-trigger-text { flex: 1; min-width: 0; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tz-select-chevron { width: 16px; height: 16px; color: var(--text-faint); flex-shrink: 0; transition: transform 0.15s ease; }
.tz-select.open .tz-select-chevron { transform: rotate(180deg); }
.tz-select-dropdown {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 30;
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--bg-elevated); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  opacity: 0; transform: translateY(-6px); pointer-events: none;
  transition: opacity 0.15s ease, transform 0.15s ease;
}
.tz-select.open .tz-select-dropdown { opacity: 1; transform: translateY(0); pointer-events: auto; }
/* Si no hay lugar debajo (el campo está pegado al fondo de la pantalla), el
   desplegable se abre hacia ARRIBA en vez de empujar la página — ver el
   cálculo de espacio disponible en el <script> de abajo. */
.tz-select.drop-up .tz-select-dropdown { top: auto; bottom: calc(100% + 6px); transform: translateY(6px); }
.tz-select.drop-up.open .tz-select-dropdown { transform: translateY(0); }
.tz-select-search {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 12px; border-bottom: 1px solid var(--border); flex-shrink: 0;
}
.tz-select-search svg { width: 16px; height: 16px; color: var(--text-faint); flex-shrink: 0; }
.tz-select-search input {
  flex: 1; min-width: 0; background: none; border: none; outline: none;
  color: var(--text); font-family: var(--font-sans); font-size: 0.85rem;
}
.tz-select-search input::placeholder { color: var(--text-faint); }
.tz-select-list { overflow-y: auto; max-height: 280px; padding: 6px; scrollbar-width: thin; scrollbar-color: var(--border) transparent; }
.tz-select-option {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border-radius: 8px; cursor: pointer;
  color: var(--text); text-decoration: none; font-size: 0.85rem; font-weight: 600;
}
.tz-select-option::before {
  content: ''; width: 14px; height: 14px; flex-shrink: 0; background-color: var(--text-faint);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v5l3.5 2'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v5l3.5 2'/%3E%3C/svg%3E") center / contain no-repeat;
}
.tz-select-option:hover { background: var(--bg-card); }
.tz-select-option.active { background: rgba(88, 101, 242, 0.15); color: var(--accent); }
.tz-select-option.active::before { background-color: var(--accent); }
.tz-select-empty { padding: 14px 12px; text-align: center; color: var(--text-faint); font-size: 0.82rem; }

/* Botón "Buscar módulos..." de la barra lateral: NO filtra nada en el
   lugar, abre el panel de la paleta de comandos justo debajo (.cmdk-panel,
   más abajo) — igual que el desplegable de cambiar de servidor de arriba,
   no un diálogo centrado en medio de la pantalla. Estilo de input pero es
   un <button>. */
.sidebar-module-search-wrap { position: relative; }
.sidebar-module-search {
  display: flex; align-items: center; gap: 8px; width: 100%;
  margin: 0 0 14px 0; padding: 0 12px; height: 40px;
  background: rgba(255, 255, 255, 0.04); border: 1px solid rgba(255, 255, 255, 0.09); border-radius: 8px;
  font-family: var(--font-sans); cursor: pointer;
  transition: border-color 0.12s ease;
}
.sidebar-module-search:hover, .sidebar-module-search:focus-visible { border-color: var(--accent); }
.sidebar-module-search svg { width: 16px; height: 16px; color: var(--text-faint); opacity: 0.85; flex-shrink: 0; }
.sidebar-module-search-label { flex: 1; min-width: 0; text-align: left; color: var(--text-faint); font-size: 0.85rem; }
.sidebar-module-search-kbd {
  flex-shrink: 0; height: 20px; padding: 0 6px; border-radius: 4px;
  display: inline-flex; align-items: center;
  background: rgba(255, 255, 255, 0.04); border: 1px solid rgba(255, 255, 255, 0.09);
  color: var(--text-faint); font-family: var(--font-mono); font-size: 10px; font-weight: 500;
  opacity: 0.8;
}

/* Paleta de comandos: se despliega pegada debajo del botón de la barra
   lateral, más ancha que la barra (tapa un poco el contenido de al lado,
   a propósito) en vez de ser un diálogo centrado en medio de la pantalla.
   La lista de resultados se arma en JS leyendo los enlaces reales de la
   barra lateral (ver script del sidebar). */
.cmdk-panel {
  display: none; position: absolute; top: calc(100% + 8px); left: 0; z-index: 50;
  width: 340px; max-height: 65vh;
  background: var(--bg-elevated); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5);
  flex-direction: column; overflow: hidden;
}
.cmdk-panel.show { display: flex; }
.cmdk-input-row {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 16px; border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}
.cmdk-input-row svg { width: 18px; height: 18px; color: var(--text-faint); flex-shrink: 0; }
.cmdk-input-row input {
  flex: 1; min-width: 0; background: none; border: none; outline: none;
  color: var(--text); font-family: var(--font-sans); font-size: 0.95rem;
}
.cmdk-input-row input::placeholder { color: var(--text-faint); }
.cmdk-results { overflow-y: auto; padding: 8px; scrollbar-width: thin; scrollbar-color: var(--border) transparent; }
.cmdk-group-label {
  padding: 10px 10px 4px; font-size: 0.68rem; font-weight: 700; color: var(--text-faint);
  text-transform: uppercase; letter-spacing: 0.05em;
}
.cmdk-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px; border-radius: 8px;
  color: var(--text-bright-muted); text-decoration: none; font-size: 0.88rem; font-weight: 500;
  cursor: pointer;
}
.cmdk-item svg { width: 18px; height: 18px; flex-shrink: 0; }
.cmdk-item.active, .cmdk-item:hover { background: rgba(255, 255, 255, 0.06); color: var(--text); }
.cmdk-empty { padding: 30px 12px; text-align: center; color: var(--text-faint); font-size: 0.85rem; }

.container { max-width: 1100px; margin: 0 auto; padding: 40px 32px 80px 32px; flex: 1; width: 100%; }
/* Dentro del panel de un servidor, el contenido no queda centrado con espacio
   vacío de los dos lados, pero tampoco pegado a la barra lateral — mismo aire
   de los dos lados (antes el derecho se quedaba en los 32px de .container,
   bien pegado a la barra de scroll del navegador). */
.container-left { margin: 0; max-width: 1680px; padding-left: 60px; padding-right: 60px; }

/* --- Imagen editable (avatar/banner) con ícono de lápiz superpuesto --- */
.image-edit { position: relative; display: inline-block; }
.image-edit-preview {
  width: 100%; height: 100%;
  border-radius: 50%;
  background-color: var(--bg-elevated);
  background-size: cover;
  background-position: center;
  border: 2px solid var(--border);
}
.image-edit-square .image-edit-preview { border-radius: 12px; }
.image-edit-input {
  position: absolute; inset: 0; width: 100%; height: 100%;
  opacity: 0; cursor: pointer;
}
.image-edit-pencil {
  position: absolute; bottom: -4px; right: -4px;
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--accent); color: white;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; border: 3px solid var(--bg-card);
  transition: background 0.12s ease, transform 0.12s ease;
}
.image-edit-pencil:hover { background: var(--accent-hover); transform: scale(1.08); }

/* --- Módulos: grupos plegables (<details>/<summary> nativo, sin JS) en la
   barra lateral. Empiezan abiertos — el chevron gira al cerrarlos. --- */
.sidebar-section-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  font-family: var(--font-sans);
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--text-bright-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin: 18px 6px 6px 6px;
  cursor: pointer;
  list-style: none;
  user-select: none;
}
.sidebar-section-label::-webkit-details-marker { display: none; }
.sidebar-section-chevron {
  width: 6px; height: 6px; flex-shrink: 0;
  border-right: 1.5px solid var(--text-faint); border-bottom: 1.5px solid var(--text-faint);
  transform: rotate(45deg);
  transition: transform 0.2s var(--ease-out);
}
.sidebar-section[open] > .sidebar-section-label .sidebar-section-chevron { transform: rotate(-135deg); }

.modules-dropdown {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.tab-pill {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-sans);
  font-size: 0.88rem;
  font-weight: 500;
  color: var(--text-bright-muted);
  background: transparent;
  border: none;
  border-left: 2.5px solid transparent;
  border-radius: 6px;
  padding: 8px 10px;
  cursor: pointer;
  text-decoration: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: all 0.12s ease;
}
.tab-pill svg { width: 19px; height: 19px; flex-shrink: 0; }
.tab-pill:hover { color: var(--text); background: rgba(255, 255, 255, 0.04); }
.tab-pill.active {
  color: var(--text);
  font-weight: 700;
  background: rgba(255, 255, 255, 0.09);
}

/* --- Íconos decorativos de la barra superior --- */
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; border-radius: 8px;
  background: transparent; border: 1px solid transparent;
  color: var(--text-muted); cursor: pointer; text-decoration: none;
}
.icon-btn svg { width: 18px; height: 18px; }
.icon-btn:hover { color: var(--text); background: var(--bg-card); }
.icon-btn:disabled { cursor: default; }
.icon-btn-danger { color: var(--danger); border-color: rgba(218, 55, 60, 0.4); }
.icon-btn-danger:hover { background: rgba(218, 55, 60, 0.14); color: var(--danger); border-color: var(--danger); }

/* Solo se muestra la sección activa (comportamiento tipo SPA). La animación
   de entrada usa solo opacity (nada de transform) — un transform en esta
   sección rompería el "position: sticky" de las vistas previas que tiene
   adentro (embed-editor-preview), porque un ancestro transformado se
   convierte en el "containing block" y el sticky deja de pegarse al
   viewport. */
.section { display: none; }
.section.active { display: block; animation: fadeIn 0.15s ease; }
@keyframes fadeIn {
  from { opacity: 0; }
  to { opacity: 1; }
}


/* --- Buttons --- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 10px 20px; border-radius: 8px; border: none;
  background: var(--accent); color: white; font-weight: 600;
  text-decoration: none; cursor: pointer; font-size: 0.9rem;
  font-family: var(--font-sans);
  transition: background 0.2s var(--ease-out), transform 0.2s var(--ease-out), box-shadow 0.2s var(--ease-out);
}
.btn:hover { background: var(--accent-hover); transform: translateY(-1px); box-shadow: 0 6px 18px -4px rgba(88, 101, 242, 0.45); }
.btn:active { transform: translateY(0) scale(0.97); box-shadow: none; }
.btn-small { padding: 9px 18px; font-size: 0.86rem; }

/* Filas de "elegir + Añadir" (rol, canal, streamer...) — antes no tenían
   ningún layout en escritorio (solo existía el ajuste para mobile), así que
   el select/input y el botón quedaban en flujo normal, sin alinear ni
   separar entre sí. */
.inline-form { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* El input/select hereda width:100% por defecto — sin un tope se estira a
   todo el ancho de la tarjeta en vez de quedar proporcional al botón. */
.inline-form input, .inline-form select { flex: 0 1 260px; width: auto; }
/* Los <select> de canal se reemplazan en runtime por un combo de búsqueda
   (.searchable-select, ver layout.ejs) — sin esto, el reemplazo pierde el
   tope de ancho de arriba y vuelve a estirarse a todo lo ancho. */
.inline-form .searchable-select { flex: 0 1 260px; width: auto; }
.inline-form .btn { flex: 0 0 auto; }
.btn-danger { background: transparent; border: 1px solid var(--danger); color: var(--danger); }
.btn-danger:hover { background: var(--danger); color: white; }
.btn-outline { background: transparent; border: 1px solid var(--border-strong); color: var(--text); }
.btn-outline:hover { background: var(--bg-card); border-color: var(--accent); color: var(--text); }
.btn-gray { background: #2A2A28; color: white; gap: 8px; }
.btn-gray:hover { background: #363633; }
.btn-icon { padding: 7px 10px; }
.btn-invite { width: 100%; }
.btn-discard { background: var(--danger); border: none; color: white; }
.btn-discard:hover { background: #c62f33; }
.btn-disabled, .btn:disabled {
  background: var(--bg-elevated) !important;
  color: var(--text-faint) !important;
  border: 1px solid var(--border);
  cursor: not-allowed !important;
  opacity: 0.6;
}

/* Feedback de "enviando" para el botón de submit de CUALQUIER formulario
   (ver layout.ejs, que agrega esta clase al enviarlo) — un spinner que usa
   currentColor, así se ve bien encima de cualquier variante de botón sin
   necesitar saber su paleta (acento, borde, rojo de descartar, etc.). */
.is-submitting { cursor: wait !important; pointer-events: none; }
.btn.is-submitting { position: relative; padding-left: 34px !important; cursor: wait !important; }
.btn.is-submitting::before {
  content: ''; position: absolute; left: 13px; top: 50%; width: 14px; height: 14px;
  margin-top: -7px; border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.3); border-top-color: currentColor;
  animation: btn-submitting-spin 0.7s linear infinite;
}
@keyframes btn-submitting-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .btn.is-submitting::before { animation: none; }
}
.back-link {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--text-muted); text-decoration: none; font-size: 0.85rem;
  margin-bottom: 16px; font-weight: 600; text-align: left;
}
.back-link:hover { color: var(--text); }
/* --- Grid de tarjetas-menú (Moderación, Bienvenida): cuadradas y alineadas --- */
.menu-grid {
  display: grid;
  /* Columnas angostas y del mismo ancho que el alto de la tarjeta — con solo
     4 columnas fijas cada una queda mucho más ancha que alta (rectangular),
     por más que la tarjeta misma pida ser cuadrada. */
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 20px;
  /* Sin esto, el grid estira cada tarjeta a la altura de la más alta de su
     fila (p.ej. una con título de dos líneas), así que unas se veían más
     grandes que otras aunque todas pidieran el mismo aspect-ratio. */
  align-items: start;
}

/* --- Grid de reglas del automod: tarjetas compactas, 3 por fila --- */
.automod-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
}
@media (max-width: 900px) { .automod-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .automod-grid { grid-template-columns: 1fr; } }

.automod-rule-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 14px 16px;
}
.automod-rule-card-title {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  font-size: 0.85rem; font-weight: 600; color: var(--text);
  margin-bottom: 10px;
}
.automod-rule-card-title-text { display: flex; align-items: center; gap: 6px; }
.automod-rule-card select { margin: 0; }

/* Mismo tope de ancho que los campos de embed (560px) — sin esto, el
   select/textarea de cada regla se estira hasta el borde de la tarjeta,
   que ahora es bien ancha (panel-narrow, 1200px). Una sola regla cubre
   las 12 vistas de edición de reglas, en vez de repetirla en cada una. */
.automod-rule-view form, #automod-master-card form,
#mod-command-rules-form, #poll-cmd-rules-form { max-width: 560px; }

.menu-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 20px;
  padding: 20px;
  display: flex;
  flex-direction: column;
  aspect-ratio: 8 / 5;
  position: relative;
  text-decoration: none; color: inherit; cursor: pointer;
  transition: border-color 0.15s ease, transform 0.15s ease, background 0.15s ease;
}
.menu-card:hover { background: var(--bg-elevated); transform: translateY(-2px); }
.menu-card:hover .menu-card-arrow { transform: rotate(-90deg) translateX(3px); }
.menu-card-arrow {
  position: absolute; top: 18px; right: 18px;
  color: var(--text-faint); transform: rotate(-90deg); transition: transform 0.15s ease;
}
.menu-card-icon {
  width: 40px; height: 40px; border-radius: 11px;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg); color: #fff; flex-shrink: 0;
}
.menu-card-icon svg { width: 19px; height: 19px; }
.menu-card-title { font-weight: 700; font-size: 1.02rem; margin-top: 16px; padding-right: 14px; }
.menu-card-desc {
  color: var(--text-muted); font-size: 0.86rem; line-height: 1.45; margin-top: 6px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  /* Reserva el alto de 2 líneas siempre, aunque el texto sea más corto —
     si no, las tarjetas con descripción de una sola línea quedan más bajas
     que sus vecinas y se ve descuadrada la fila entera. */
  min-height: 2.9em;
}
.menu-card .btn { margin-top: 14px; width: 100%; text-align: center; }
.menu-card-single { max-width: 280px; }
.menu-card.is-active .menu-card-icon { color: var(--accent); }
.menu-card-status {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px; line-height: 1;
  margin-top: 16px; padding: 9px 16px; border-radius: 8px; font-size: 0.85rem; font-weight: 600;
  background: var(--bg-elevated); border: 1px solid var(--border-strong); color: var(--text);
  align-self: flex-start; transition: background 0.15s var(--ease-out), border-color 0.15s var(--ease-out), color 0.15s var(--ease-out);
}
.menu-card-status.is-active { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
/* Al pasar el mouse por la tarjeta, el botón "Habilitar" se adelanta a lo
   que pasaría al hacer clic: se pone azul sólido y el "+" cambia por una
   flecha — mismo patrón que MEE6. El de "Activo" se queda como está. */
.menu-card:hover .menu-card-status:not(.is-active) { background: var(--accent); border-color: var(--accent); color: #fff; }
.menu-card-status-icon-hover { display: none; transform: rotate(-90deg); }
.menu-card:hover .menu-card-status-icon-rest { display: none; }
.menu-card:hover .menu-card-status-icon-hover { display: inline-flex; }

/* --- Encabezado de categoría en Inicio (Gestión / Comunidad / Utilidades),
   igual patrón que usan otros bots para agrupar sus módulos por tema. --- */
.module-group-header { margin: 28px 0 14px 0; }
.module-group-header:first-of-type { margin-top: 24px; }
.module-group-title { font-weight: 700; font-size: 1.05rem; color: var(--text); }
.module-group-desc { font-size: 0.86rem; color: var(--text-muted); margin-top: 3px; }

/* --- Inicio: tarjeta "hero" con el ícono/nombre del servidor por arriba de
   sus estadísticas — todo junto en un solo bloque, en vez de sueltas. --- */
.inicio-hero { padding: 22px 24px; }
.inicio-hero-top { display: flex; align-items: center; gap: 16px; margin-bottom: 18px; }
/* Las 4 tarjetas de stats iban con su propio fondo/borde igual que la tarjeta
   que las contiene — se veía como "cajas dentro de una caja". Achatarlas y
   separarlas con una línea en vez de un borde propio se ve mucho más limpio. */
.inicio-hero .stats-grid {
  column-gap: 0;
  row-gap: 16px;
  border-top: 1px solid var(--border-soft);
  padding-top: 18px;
}
.inicio-hero .stat-card {
  background: transparent;
  border: none;
  border-radius: 0;
  padding: 0 20px;
  border-left: 1px solid var(--border-soft);
  transition: background 0.15s ease;
}
.inicio-hero .stat-card:first-child { padding-left: 0; border-left: none; }
.inicio-hero .stat-card:last-child { padding-right: 0; }
/* Mismo tema oscuro/blanco de los íconos de las tarjetas de módulo — acá
   .stat-icon-badge por defecto es azulado y no combina. */
.inicio-hero .stat-icon-badge { background: var(--bg); color: #fff; transition: background 0.15s ease; }
.inicio-hero .stat-card:hover .stat-icon-badge { background: var(--accent); }
.inicio-hero-icon {
  width: 60px; height: 60px; border-radius: 16px; object-fit: cover; flex-shrink: 0;
  background: var(--bg-elevated); border: 1px solid var(--border);
}
.inicio-hero-icon-placeholder {
  display: flex; align-items: center; justify-content: center;
  font-size: 1.5rem; font-weight: 800; color: var(--text-faint);
}
.inicio-hero-name { font-size: 1.25rem; font-weight: 800; color: var(--text); line-height: 1.25; }
.inicio-hero-sub { font-size: 0.84rem; color: var(--text-muted); margin-top: 2px; }

/* --- Hero (login) --- */
.hero { text-align: center; padding: 100px 20px; }
.hero h1 { font-size: 2.3rem; margin-bottom: 12px; }
.hero p { color: var(--text-muted); margin-bottom: 28px; }

/* --- Pantalla de inicio: resplandor centrado en vez de imagen de fondo --- */
.login-bg {
  display: flex; align-items: center; justify-content: center;
  min-height: calc(100vh - 65px);
  position: relative; overflow: hidden;
}
.login-bg::before {
  content: ''; position: absolute; z-index: 0; inset: 0;
  background:
    radial-gradient(560px circle at 50% 32%, rgba(88, 101, 242, 0.18), transparent 65%),
    radial-gradient(420px circle at 78% 68%, rgba(87, 242, 135, 0.10), transparent 65%);
  pointer-events: none;
}
.login-dev-banner {
  display: inline-flex; align-items: center; gap: 8px;
  background: rgba(245, 158, 11, 0.12); border: 1px solid rgba(245, 158, 11, 0.35);
  color: #f59e0b; font-size: 0.82rem; font-weight: 700;
  padding: 7px 16px; border-radius: 6px; margin-bottom: 20px;
}

/* --- Hero centrado (una sola columna). --- */
.login-hero-copy {
  position: relative; z-index: 1; width: 100%; max-width: 620px; margin: 0 auto;
  padding: 56px 20px; text-align: center;
}
.login-hero-copy h1 { font-size: 3.1rem; font-weight: 800; letter-spacing: -0.02em; line-height: 1.08; margin: 0 0 18px; }
.login-hero-copy p { font-size: 1.08rem; color: var(--text-muted); max-width: 460px; margin: 0 auto 34px; line-height: 1.55; }
.login-cta-row { display: flex; align-items: center; justify-content: center; gap: 12px; flex-wrap: wrap; }
.login-cta { padding: 15px 34px; font-size: 1rem; }
.login-cta-secondary { padding: 14px 28px; font-size: 0.96rem; }
@media (max-width: 640px) {
  .login-hero-copy h1 { font-size: 2.1rem; }
  .login-hero-copy p { font-size: 0.95rem; }
}

/* --- Sección de funciones destacadas, debajo del hero: reemplaza la fila
   angosta de íconos+texto por tarjetas con ícono, título y descripción. --- */
.login-features { max-width: 1080px; margin: 0 auto; padding: 8px 32px 80px; position: relative; z-index: 1; }
.login-features-header { text-align: center; margin-bottom: 34px; }
.login-features-header h2 { font-size: 1.5rem; font-weight: 800; margin: 0 0 8px; }
.login-features-header p { font-size: 0.95rem; color: var(--text-muted); margin: 0; }
.login-features-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; }
.login-feature-card {
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 16px;
  padding: 22px 20px; display: flex; flex-direction: column; gap: 12px;
}
.login-feature-card-icon {
  width: 42px; height: 42px; border-radius: 11px;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-elevated); color: var(--text-muted);
}
.login-feature-card-title { font-weight: 700; font-size: 0.98rem; color: var(--text); }
.login-feature-card-desc { font-size: 0.84rem; color: var(--text-muted); line-height: 1.5; }
@media (max-width: 860px) {
  .login-features-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 480px) {
  .login-features-grid { grid-template-columns: 1fr; }
}

/* --- Guild selection --- */
.guild-search-wrap { position: relative; max-width: 420px; margin: 24px 0 20px; }
.guild-search-icon {
  position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
  width: 15px; height: 15px; line-height: 0;
  color: var(--text-faint); display: flex; align-items: center; justify-content: center;
  pointer-events: none;
  z-index: 1;
}
.guild-search-icon svg { width: 100%; height: 100%; }
/* Especificidad (0,2,0) a propósito: le gana a la regla global
   `input[type="text"] { padding: 11px 12px; }` de más abajo en el archivo
   (especificidad (0,1,1)) — sin esto, el padding-left de acá quedaba pisado
   sin importar el valor que se le pusiera. */
.guild-search-wrap .guild-search-input {
  width: 100%; padding: 11px 14px 11px 46px; border-radius: 10px;
  position: relative;
  border: 1px solid var(--border); background: var(--bg-card); color: var(--text);
  font-size: 0.9rem; font-family: var(--font-sans);
  transition: border-color 0.15s var(--ease-out), box-shadow 0.15s var(--ease-out);
}
.guild-search-input:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.guild-search-input::placeholder { color: var(--text-faint); }

.guild-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 16px;
}
.guild-card {
  position: relative;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 14px;
  overflow: hidden;
  color: var(--text);
  text-decoration: none;
  transition: transform 0.2s var(--ease-out), border-color 0.2s var(--ease-out), box-shadow 0.2s var(--ease-out);
}
.guild-card:hover { transform: translateY(-4px); border-color: var(--accent); box-shadow: 0 16px 32px -12px rgba(0, 0, 0, 0.4); }
/* Combina la transición de aparición ([data-reveal]) con las de hover de
   arriba en una sola declaración — si quedaran en reglas separadas, la que
   esté más abajo en el archivo pisa por completo a la otra (transition no
   se combina entre selectores), y el hover se ponía lento o sin animar. */
.guild-card[data-reveal] {
  transition: opacity 0.5s var(--ease-out), transform 0.3s var(--ease-out),
    border-color 0.2s var(--ease-out), box-shadow 0.2s var(--ease-out), background 0.2s var(--ease-out);
}
.guild-card > .guild-card-badge {
  position: absolute; top: 10px; right: 10px; z-index: 2;
  display: inline-flex; align-items: center; gap: 5px;
  background: rgba(0, 0, 0, 0.5); backdrop-filter: blur(4px); color: var(--success);
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.02em;
  padding: 3px 8px; border-radius: 6px;
}
.guild-card > .guild-card-badge .status-dot { width: 6px; height: 6px; }

/* Banner: el mismo ícono del servidor, agrandado y difuminado de fondo */
.guild-card-banner {
  position: relative; height: 72px; background: var(--bg-elevated);
  overflow: hidden;
}
.guild-card-banner::before {
  content: ''; position: absolute; inset: -20px;
  background-image: var(--banner-img); background-size: cover; background-position: center;
  filter: blur(18px) saturate(1.3) brightness(0.7);
  transform: scale(1.15);
}
.guild-card-icon {
  position: relative; z-index: 1;
  width: 56px; height: 56px; border-radius: 50%;
  margin: -28px 0 0 16px; object-fit: cover; flex-shrink: 0;
  border: 3px solid var(--bg-card); display: block;
}
.guild-icon-placeholder.guild-card-icon {
  background: var(--accent); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.3rem; font-weight: 700;
}

.guild-card-body { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 16px 16px; }
.guild-card-info { min-width: 0; display: flex; flex-direction: column; }
.guild-card-name {
  font-weight: 700; font-size: 0.92rem; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.guild-card-role { font-size: 0.78rem; color: var(--text-faint); margin-top: 1px; }
.guild-card-body .btn { flex-shrink: 0; }

.guild-card-add {
  display: flex; flex-direction: column;
  border-style: dashed;
  color: var(--text-muted);
  transition: transform 0.2s var(--ease-out), border-color 0.2s var(--ease-out), background 0.2s var(--ease-out);
}
.guild-card-add:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); transform: translateY(-4px); box-shadow: none; }
.guild-card-add-banner { height: 72px; display: flex; align-items: center; justify-content: center; }
.guild-card-add-icon {
  width: 40px; height: 40px; border-radius: 50%;
  background: transparent; border: 1px solid var(--border);
  display: flex; align-items: center; justify-content: center;
  font-size: 1.5rem; font-weight: 400; color: var(--text-faint);
  transition: border-color 0.2s var(--ease-out), color 0.2s var(--ease-out);
}
.guild-card-add:hover .guild-card-add-icon { border-color: var(--accent); color: var(--accent); }
.guild-card-add-body { justify-content: center; padding: 0 16px 18px; font-size: 0.88rem; font-weight: 600; }

/* --- Page headers --- */
.page-header { margin-bottom: 28px; scroll-margin-top: 90px; }
/* Ancho compartido por las secciones de "lista de paneles" (Tickets,
   Autoroles, Comandos personalizados, Mensaje personalizado, Control de
   canales, Voz temporal, Encuestas): mismo valor en un solo lugar para que
   el encabezado, las pestañas (si las hay), la lista y el formulario de
   crear/editar siempre midan y arranquen igual, sin que cambiarlo signifique
   tocar 20 estilos sueltos. */
.panel-narrow { display: block; width: 100%; max-width: 1200px; margin-left: auto; margin-right: auto; }
.page-header h1 { font-size: 1.9rem; margin: 0 0 8px 0; font-weight: 800; }
.page-header p { color: var(--text-muted); font-size: 0.95rem; line-height: 1.5; margin: 0; max-width: 640px; }

/* Encabezado de un módulo con interruptor: título/descripción a la izquierda,
   estado y switch a la derecha, en la misma fila. */
.page-header.page-header-toggle { display: flex; align-items: flex-start; justify-content: space-between; gap: 20px; flex-wrap: wrap; }
.page-header-text { flex: 1; min-width: 200px; }
.header-toggle { display: flex; align-items: center; gap: 10px; flex-shrink: 0; padding-top: 4px; }
.header-toggle-label { font-size: 0.8rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; color: var(--text-faint); }
.header-toggle:has(input:checked) .header-toggle-label { color: var(--accent); }

/* Variante para las pestañas de plataforma dentro de Alertas sociales, donde
   no hay un <h1> propio, solo el texto de ayuda de esa pestaña. */
.tab-panel-header .hint { max-width: 640px; }

/* --- Section wrapper --- */
.section { margin-bottom: 56px; scroll-margin-top: 90px; }

/* --- Grid layouts --- */
/* Antes usaba "2fr 1fr": en una pantalla ancha, sin ningún techo, esa
   columna se estiraba a cientos de píxeles de más y los inputs de adentro se
   veían gigantes/descompensados — capada con minmax igual que
   .grid-2-embed-preview (hoy .grid-2 solo lo usa Autoroles, que también
   tiene un editor de embed adentro). */
.grid-2 { display: grid; grid-template-columns: minmax(420px, 560px) minmax(360px, 480px); gap: 20px; align-items: start; }
/* Variante de .grid-2 para editores de embed — la columna de vista previa
   necesita más ancho fijo que un 1fr genérico (el embed real ronda los
   520px), si no queda amontonada en pantallas anchas. La columna de campos
   también está capada (antes era "1.4fr", sin techo) para que no se estire
   más de la cuenta en pantallas anchas — todas las tarjetas de esa columna
   (.stack) comparten el mismo ancho ya fijo, en vez de que cada una se
   estire distinto y queden descuadradas entre sí. */
.grid-2-embed-preview { display: grid; grid-template-columns: minmax(420px, 560px) minmax(360px, 480px); gap: 20px; align-items: start; }
/* El breakpoint es por ancho de VENTANA, pero el ancho real disponible acá
   es ventana menos la barra lateral (~260px) — por eso el quiebre a una
   columna pasa bastante antes de que la ventana "se vea angosta" de verdad. */
@media (max-width: 1180px) {
  .grid-2, .grid-2-embed-preview { grid-template-columns: 1fr; }
}
.grid-2-even { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; align-items: start; }
.grid-3-even { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 20px; align-items: start; }

/* Variante de .grid-2-even para cuando las dos tarjetas deben verse del mismo
   alto aunque tengan distinta cantidad de contenido — la más corta se estira
   para igualar a la más alta, en vez de quedar más chica y descompensada. */
.card-grid-stretch { align-items: stretch; }
.card-grid-stretch-form { display: flex; }
.card-grid-stretch-form .card { display: flex; flex-direction: column; width: 100%; }
.card-grid-stretch-form .form-actions { margin-top: auto; }
.stack { display: flex; flex-direction: column; gap: 20px; }
@media (max-width: 860px) {
  .grid-2-even, .grid-3-even { grid-template-columns: 1fr; }
}

/* --- Editor de embed en dos columnas: formulario a la izquierda, vista
   previa pegada a la derecha (se queda visible mientras se scrollea un
   formulario largo, como Discohook) — Bienvenidas, Boost, Tickets, Anuncios,
   Alertas sociales, Roles por panel y Sorteos.

   Dos capas a propósito, y NO las dos con fondo de tarjeta:
   - .embed-editor-preview es un contenedor invisible (sin .card) que se
     ESTIRA (align-items: stretch) para ocupar la misma altura que el
     formulario — así la fila del grid queda pareja.
   - .embed-editor-preview-sticky es la que lleva la clase .card (fondo,
     borde, padding) Y el position:sticky, con su altura natural (la del
     contenido, no estirada) — flota dentro del contenedor invisible de
     arriba. Resultado: la tarjeta visible nunca se ve con un hueco vacío
     abajo, pero el grid sigue parejo y el sticky sigue teniendo margen
     para pegarse mientras se scrollea (si el sticky estuviera en el
     contenedor ya estirado, no tendría margen para moverse y quedaría
     siempre estático — el bug que ya arreglamos una vez). --- */
.embed-editor-layout { display: grid; grid-template-columns: 1fr 680px; gap: 20px; align-items: stretch; }
/* top: 87px, no 20px — la topbar mide ~67px y es sticky con z-index más alto,
   así que con menos que eso el contenido se pegaba por DEBAJO de la topbar
   (technically sticky, pero con el título tapado — se veía como si no
   funcionara). */
.embed-editor-preview-sticky { position: sticky; top: 87px; }
@media (max-width: 900px) {
  .embed-editor-layout { grid-template-columns: 1fr; }
  .embed-editor-preview-sticky { position: static; }
}

/* --- Cards --- */
.card {
  background: var(--bg-card);
  border: 1px solid var(--border-soft);
  border-radius: 14px;
  padding: 24px;
  box-shadow: var(--shadow-card);
  transition: border-color 0.2s var(--ease-out), box-shadow 0.2s var(--ease-out);
}
.card-header {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 18px; gap: 12px;
}
.card-header-title { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 1rem; }
.card-header-icon { font-size: 1.1rem; }

/* Panel de ajustes en filas (Ajustes → General): un solo .card, cada ajuste
   es una fila con la etiqueta+descripción a la izquierda y el control a la
   derecha, separadas por una línea fina — en vez de tarjetas sueltas. */
.settings-panel { padding: 0; overflow: hidden; }
.settings-row { display: grid; grid-template-columns: 260px 1fr; gap: 32px; padding: 26px 28px; border-bottom: 1px solid var(--border-soft); }
.settings-row:last-child { border-bottom: none; }
.settings-row-title { display: flex; align-items: center; gap: 9px; font-weight: 700; font-size: 0.94rem; }
.settings-row-desc { color: var(--text-muted); font-size: 0.84rem; line-height: 1.5; margin-top: 6px; }
.settings-row-control { display: flex; flex-direction: column; gap: 12px; justify-content: center; }
.settings-row-control .inline-form { margin: 0; }
.settings-row-control .form-actions { margin-top: 0; }
/* Los tres controles (select de roles, input de apodo, selector de zona
   horaria) deben verse del mismo ancho entre sí — sin esto, cada uno cae en
   un tope distinto (260px el select "agregar", 100% el input y el tz-select)
   y la tarjeta se ve despareja. El input de apodo y el tz-select son hijos
   DIRECTOS de .settings-row-control (que es una columna flex) — ahí "flex"
   controla la ALTURA (el eje principal de una columna), así que se dejan
   sin flex-grow, si no crecen verticalmente para llenar la fila entera. El
   select de roles en cambio vive adentro de su propio .inline-form (una
   fila flex de un solo elemento), así que ahí "flex" sí es el eje horizontal
   y hace falta para ganarle al tope de 260px que trae por defecto. */
.settings-row-control > input[type="text"],
.settings-row-control > .tz-select {
  width: 100%; max-width: 340px;
}
.settings-row-control .inline-form .searchable-select {
  flex: 1 1 auto; width: 100%; max-width: 340px;
}
@media (max-width: 720px) {
  .settings-row { grid-template-columns: 1fr; gap: 10px; padding: 20px; }
}

/* .card usado como <details> nativo: colapsado por defecto para no competir
   en peso visual con el contenido principal de la sección, pero arriba de
   la página para que se note que existe. Mismo chevron que el de
   leaderboard-side-card, generalizado acá. */
.card-summary { display: flex; align-items: center; justify-content: space-between; gap: 10px; cursor: pointer; list-style: none; }
.card-summary::-webkit-details-marker { display: none; }
.card-summary-title { display: flex; align-items: center; gap: 10px; font-weight: 700; font-size: 1rem; }
.card-summary-chevron {
  width: 7px; height: 7px; flex-shrink: 0;
  border-right: 2px solid var(--text-faint); border-bottom: 2px solid var(--text-faint);
  transform: rotate(45deg); transition: transform 0.2s var(--ease-out);
}
details[open] > .card-summary .card-summary-chevron { transform: rotate(-135deg); }
details.card > .card-summary { margin-bottom: 0; }
details.card[open] > .card-summary { margin-bottom: 18px; padding-bottom: 16px; border-bottom: 1px solid var(--border-soft); }

/* Contador junto al título de una tarjeta colapsable (ej. "Servidores 12") —
   una píldora en vez de "(12)" en el texto, que se sentía viejo. */
.card-summary-count {
  background: var(--bg-elevated); color: var(--text-muted);
  padding: 2px 10px; border-radius: 999px; font-size: 0.78rem; font-weight: 700;
  flex-shrink: 0;
}

/* Buscador simple de un solo <input> — la lupa es el fondo del propio
   input (mismo truco que .tz-select-option::before, más abajo), sin
   envolverlo en ningún div nuevo. Antes el ícono quedaba pegado al borde
   izquierdo; acá 12px de separación + el padding-left que le hace lugar. */
input[type="text"].search-input-icon {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236b6d76' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: 12px center;
  background-size: 16px 16px;
  padding-left: 36px;
}

/* Ventana emergente para "Ver vista previa" — para editores de embed en una
   sola columna (sin la vista previa fija al lado), que la muestran bajo
   demanda en vez de ocupar espacio todo el tiempo. */
.preview-modal-overlay {
  display: none; position: fixed; inset: 0; z-index: 1050;
  background: rgba(0, 0, 0, 0.6);
  align-items: center; justify-content: center; padding: 20px;
}
.preview-modal-overlay.show { display: flex; }
.preview-modal-box {
  position: relative; background: var(--bg-card); border: 1px solid var(--border-soft);
  border-radius: 14px; padding: 24px; box-shadow: var(--shadow-card);
  width: 100%; max-width: 560px; max-height: 85vh; overflow-y: auto;
}
.preview-modal-close {
  position: absolute; top: 14px; right: 14px; background: none; border: none;
  color: var(--text-faint); font-size: 1.5rem; line-height: 1; cursor: pointer;
  padding: 4px; border-radius: 6px; transition: color 0.15s ease, background 0.15s ease;
}
.preview-modal-close:hover { color: var(--text); background: var(--bg-elevated); }

/* Selector de roles "grande" — usado en el modal "Restringir por rol" de
   Voz temporal (ahí es el contenido PRINCIPAL del modal, no un campo más
   entre otros) y en "Roles moderadores" del mismo panel, para que los dos
   se vean del mismo tamaño en vez de que uno quede chico al lado del otro. */
.multi-picker-lg .multi-picker-trigger {
  padding: 14px 16px; font-size: 0.98rem; border-radius: 10px; min-height: 48px;
}
.multi-picker-lg .multi-picker-search {
  padding: 11px 14px; font-size: 0.95rem; min-height: 44px;
}
.multi-picker-lg .multi-picker-dropdown-option {
  padding: 11px 14px; font-size: 0.95rem; gap: 10px;
}
.multi-picker-lg .multi-picker-option-icon { width: 22px; height: 22px; font-size: 1rem; }
.multi-picker-lg .multi-picker-dropdown { max-height: 260px; }
.multi-picker-lg .chip-list.multi-picker-chips .chip { font-size: 0.9rem; padding: 7px 10px 7px 12px; }

@media (max-width: 480px) {
  .preview-modal-overlay { padding: 12px; }
  .preview-modal-box { padding: 18px; max-height: 90vh; }
  #tempvoice-picker-roles .multi-picker-dropdown { max-height: 45vh; }
}

/* Recortar imagen — modal compartido, ver layout.ejs (una sola instancia
   reutilizada por cualquier campo de imagen con data-crop="true"). */
.crop-modal-box { max-width: 720px; }
.crop-modal-title { margin: 0 0 16px 0; font-size: 1.05rem; font-weight: 700; color: var(--text); }
.crop-modal-wrap { position: relative; display: inline-block; max-width: 100%; line-height: 0; border-radius: 8px; overflow: hidden; background: var(--bg-chrome); }
.crop-modal-image { display: block; max-width: 100%; max-height: 55vh; user-select: none; -webkit-user-drag: none; }
.crop-selection {
  position: absolute; border: 2px dashed #fff; cursor: move;
  box-shadow: 0 0 0 9999px rgba(0, 0, 0, 0.55);
  touch-action: none;
}
.crop-handle {
  position: absolute; width: 11px; height: 11px; background: #fff; border: 1px solid rgba(0, 0, 0, 0.35);
  border-radius: 2px; transform: translate(-50%, -50%); touch-action: none;
}
.crop-handle[data-dir="nw"] { left: 0; top: 0; cursor: nwse-resize; }
.crop-handle[data-dir="ne"] { left: 100%; top: 0; cursor: nesw-resize; }
.crop-handle[data-dir="sw"] { left: 0; top: 100%; cursor: nesw-resize; }
.crop-handle[data-dir="se"] { left: 100%; top: 100%; cursor: nwse-resize; }
.crop-handle[data-dir="n"] { left: 50%; top: 0; cursor: ns-resize; }
.crop-handle[data-dir="s"] { left: 50%; top: 100%; cursor: ns-resize; }
.crop-handle[data-dir="e"] { left: 100%; top: 50%; cursor: ew-resize; }
.crop-handle[data-dir="w"] { left: 0; top: 50%; cursor: ew-resize; }
.crop-modal-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 16px; flex-wrap: wrap; }
.crop-modal-actions { display: flex; align-items: center; gap: 10px; }
#crop-modal-square-btn.active { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); }
.crop-modal-hint { margin: 10px 0 0 0; }
.ticket-panel-step-num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 50%; background: var(--accent); color: #fff;
  font-size: 0.78rem; font-weight: 700; flex-shrink: 0;
}
.card-desc { color: var(--text-muted); font-size: 0.88rem; line-height: 1.5; margin: -12px 0 18px 0; }

/* --- Términos / Privacidad --- */
.legal-breadcrumb { display: flex; align-items: center; gap: 8px; font-size: 0.85rem; color: var(--text-faint); margin-bottom: 22px; flex-wrap: wrap; }
.legal-breadcrumb-sep { color: var(--text-faint); }
.legal-breadcrumb-link { color: var(--text-faint); text-decoration: none; }
.legal-breadcrumb-link:hover { color: var(--text-muted); text-decoration: underline; }
.legal-breadcrumb-current { color: var(--text-muted); font-weight: 600; }

.legal-layout { display: grid; grid-template-columns: 220px 1fr; gap: 36px; align-items: start; }
.legal-toc { position: sticky; top: 87px; }
.legal-toc-title {
  font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--text-faint); margin-bottom: 12px;
}
.legal-toc-list { display: flex; flex-direction: column; gap: 1px; border-left: 2px solid var(--border); }
.legal-toc-link {
  display: block; padding: 6px 0 6px 14px; margin-left: -2px; border-left: 2px solid transparent;
  color: var(--text-muted); text-decoration: none; font-size: 0.85rem; line-height: 1.4;
  transition: color 0.15s var(--ease-out), border-color 0.15s var(--ease-out);
}
.legal-toc-link:hover { color: var(--text); }
.legal-toc-link.active { color: var(--accent); border-left-color: var(--accent); font-weight: 600; }

.legal-content { max-width: 720px; }
.legal-content p { color: var(--text-muted); line-height: 1.65; margin: 0 0 16px 0; }
.legal-content h2 { font-size: 1.15rem; margin: 28px 0 10px 0; color: var(--text); scroll-margin-top: 100px; }
.legal-content h2:first-child { margin-top: 0; }
.legal-content ul { margin: 0 0 16px 0; padding-left: 20px; color: var(--text-muted); line-height: 1.65; }
.legal-content li { margin-bottom: 6px; }
.legal-content strong { color: var(--text); }
.legal-content code { font-family: var(--font-mono); font-size: 0.85rem; }
.legal-content em { color: var(--accent); font-style: normal; }

@media (max-width: 900px) {
  .legal-layout { grid-template-columns: 1fr; }
  .legal-toc { display: none; }
}

/* --- Form elements --- */
.field-label {
  display: block; margin: 16px 0 7px 0;
  font-family: var(--font-sans); font-size: 0.72rem; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; color: var(--text);
}
.field-label:first-child { margin-top: 0; }

input[type="text"], input[type="number"], input[type="date"], input[type="time"], input[type="datetime-local"], input[type="email"], input[type="url"], select, textarea {
  width: 100%; padding: 11px 12px; border-radius: 8px; border: 1px solid var(--border-strong);
  background: #17181c; color: var(--text); font-size: 0.9rem;
  font-family: var(--font-sans);
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
/* El ícono del calendario nativo viene apagado/chico por defecto — se agranda
   un poco y se le baja la opacidad en reposo para que combine con el resto
   de íconos del panel en vez de verse pegado sin más. */
input[type="date"]::-webkit-calendar-picker-indicator,
input[type="time"]::-webkit-calendar-picker-indicator,
input[type="datetime-local"]::-webkit-calendar-picker-indicator {
  cursor: pointer; opacity: 0.65; transition: opacity 0.12s ease;
  padding: 2px; border-radius: 4px;
}
input[type="date"]::-webkit-calendar-picker-indicator:hover,
input[type="time"]::-webkit-calendar-picker-indicator:hover,
input[type="datetime-local"]::-webkit-calendar-picker-indicator:hover {
  opacity: 1; background: var(--bg-elevated);
}
textarea {
  font-family: var(--font-mono); font-size: 0.85rem; resize: vertical; max-height: 320px; overflow-y: auto;
  scrollbar-width: thin; scrollbar-color: var(--border) transparent;
}
textarea::-webkit-scrollbar { width: 8px; }
textarea::-webkit-scrollbar-track { background: transparent; }
textarea::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }
textarea::-webkit-scrollbar-thumb:hover { background: var(--text-faint); }
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* El <select> nativo trae su propio relleno interno para la flechita, distinto
   en cada navegador — con el mismo padding que un input igual termina 2px más
   alto (verificado: 42px vs 40px en Chrome/Windows). Se apaga ese estilo nativo
   y se dibuja la flecha a mano para que el alto salga idéntico al de un input. */
select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%236b6d76' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 32px;
}
select[multiple] { padding: 6px; background-image: none; }
select[multiple] option { padding: 8px 10px; border-radius: 4px; }
select[multiple] option:checked { background: var(--accent); color: white; }

/* --- Inputs numéricos compactos (cantidad de ganadores, duración, etc.) --- */
input.input-compact { width: 90px; text-align: center; }
.duration-row { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 16px; }
.duration-row > div { display: flex; flex-direction: column; }
.duration-row .field-label { margin-top: 0; }

.hint { font-size: 0.85rem; line-height: 1.5; color: var(--text-muted); margin-top: 6px; }
.file-upload-error { color: var(--danger); font-weight: 600; }

.utility-list { margin-top: 14px; padding-left: 20px; color: var(--text-muted); font-size: 0.92rem; line-height: 1.7; }
.utility-list li { margin-bottom: 8px; }
.utility-list code { font-family: var(--font-mono); font-size: 0.85rem; color: var(--text); background: var(--bg-elevated); padding: 2px 6px; border-radius: 4px; }

/* --- Aviso de "Configuración guardada" --- */
.toast-success {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%) translateY(20px);
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--bg-elevated);
  border: 1px solid rgba(34, 197, 94, 0.35);
  color: var(--text);
  padding: 12px 20px;
  border-radius: 10px;
  font-size: 0.88rem;
  font-weight: 600;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.4);
  opacity: 0;
  z-index: 1000;
  transition: opacity 0.25s ease, transform 0.25s ease;
}
.toast-success svg { color: var(--success); flex-shrink: 0; }
.toast-success.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* --- Panel: estadísticas del servidor --- */
.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 14px;
}
.stat-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 16px 18px;
  text-align: left;
}
.stat-card-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 16px;
}
.stat-icon-badge {
  width: 30px;
  height: 30px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--accent-soft);
  color: var(--accent);
  flex-shrink: 0;
}
.stat-icon-badge svg { width: 16px; height: 16px; }
.stat-value { font-size: 1.7rem; font-weight: 700; color: var(--text); font-family: var(--font-mono); line-height: 1; }
.stat-label { font-size: 0.82rem; color: var(--text-muted); font-weight: 500; }

/* --- Fila de estadísticas secundarias (compactas, en línea) --- */
.stats-pill-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 24px;
  margin-top: 14px;
  color: var(--text-muted);
  font-size: 0.86rem;
}
.stats-pill { display: flex; align-items: center; gap: 7px; white-space: nowrap; }
.stats-pill svg { width: 15px; height: 15px; color: var(--text-faint); flex-shrink: 0; }
.stats-pill strong { color: var(--text); font-weight: 700; }


/* --- Filas detalladas de "Comandos disponibles" en Moderación — una
   tarjeta por comando, mismo look que .command-item (usado en Tickets,
   Comandos personalizados, etc.), no una lista con separadores. --- */
.mod-command-row {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 14px 16px; background: #1a1b1f; border: 1px solid var(--border-strong);
  border-radius: 12px; transition: border-color 0.15s var(--ease-out), background 0.15s var(--ease-out);
}
.mod-command-row:hover { background: #202126; border-color: rgba(255, 255, 255, 0.16); }

/* Modo de restricción por rol/canal (lista blanca vs. lista negra) — mismo
   patrón que usan MEE6/Dyno para esto. */
/* El formulario entero se limita a un ancho fijo (como MEE6/Dyno) — sin
   esto, el select y los radios se estiran a lo ancho de toda la tarjeta y
   se siente innecesariamente amplio para una lista corta de opciones. */
#mod-command-rules-form { max-width: 480px; }
.mod-permission-mode { display: flex; flex-direction: column; gap: 6px; margin: 6px 0 10px; }
.mod-permission-radio {
  display: flex; align-items: center; gap: 8px; cursor: pointer;
  font-size: 0.88rem; color: var(--text-muted);
}
.mod-permission-radio input[type="radio"] { accent-color: var(--accent); width: 16px; height: 16px; cursor: pointer; }
.mod-permission-radio:has(input:checked) { color: var(--text); }
.mod-command-row-text { min-width: 0; }
.mod-command-row-name { font-family: var(--font-mono); font-weight: 700; color: var(--accent); font-size: 0.92rem; }
.mod-command-row-desc { color: var(--text-muted); font-size: 0.88rem; line-height: 1.5; margin-top: 3px; }
.mod-command-row-usage {
  display: inline-block; margin-top: 6px;
  font-family: var(--font-mono); font-size: 0.78rem; color: var(--text);
  background: var(--bg-elevated); padding: 3px 8px; border-radius: 5px;
}

.bot-status-timestamp { font-family: var(--font-mono); font-size: 0.95rem; color: var(--text); margin-top: 4px; }

/* --- Personalizar bot: editor con vista previa en vivo --- */
.persona-editor {
  display: grid;
  grid-template-columns: auto 1fr 280px;
  gap: 32px;
  align-items: start;
}
.persona-editor-col { min-width: 0; }
.persona-editor-icon-col { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }

.persona-avatar-wrap {
  position: relative; display: block; width: 96px; height: 96px;
  border-radius: 16px; overflow: visible; cursor: pointer;
}
.persona-avatar-img {
  width: 96px; height: 96px; border-radius: 16px; object-fit: cover;
  display: block; background: var(--bg-elevated);
}
.persona-avatar-placeholder { background: var(--bg-elevated); border: 1px dashed var(--border); }
.persona-avatar-edit-btn {
  position: absolute; bottom: -6px; right: -6px;
  width: 30px; height: 30px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent); color: #fff; border: 3px solid var(--bg-card);
}
.persona-avatar-wrap:hover .persona-avatar-edit-btn { background: var(--accent-hover); }
.persona-remove-check { display: flex; align-items: center; gap: 6px; font-size: 0.78rem; color: var(--text-muted); }

.persona-preview-member {
  display: flex; align-items: center; gap: 10px;
  background: var(--bg-elevated); border-radius: 8px; padding: 10px 12px;
}
.persona-preview-avatar-sm { width: 34px; height: 34px; border-radius: 50%; object-fit: cover; }
.persona-preview-name { font-weight: 700; font-size: 0.88rem; color: var(--text); }
.persona-preview-badge {
  display: inline-block; margin-left: 6px; font-size: 0.62rem; font-weight: 700;
  background: var(--accent); color: #fff; padding: 1px 5px; border-radius: 4px;
  vertical-align: middle;
}
.persona-preview-message {
  display: flex; align-items: flex-start; gap: 10px;
  background: var(--bg-elevated); border-radius: 8px; padding: 12px;
}
.persona-preview-avatar-md { width: 40px; height: 40px; border-radius: 50%; object-fit: cover; flex-shrink: 0; }
.persona-preview-msg-text { color: var(--text-muted); font-size: 0.85rem; margin-top: 4px; }

@media (max-width: 900px) {
  .persona-editor { grid-template-columns: 1fr; }
}

/* --- Panel del bot: identidad global + presencia, con vista previa --- */
.persona-avatar-status-wrap { position: relative; display: inline-flex; flex-shrink: 0; }
.persona-status-dot {
  position: absolute; bottom: -2px; right: -2px;
  width: 12px; height: 12px; border-radius: 50%;
  border: 3px solid var(--bg-elevated);
}
.persona-status-dot.status-online { background: #23a55a; }
.persona-status-dot.status-idle { background: #f0b232; }
.persona-status-dot.status-dnd { background: #f23f43; }
.persona-status-dot.status-invisible { background: #80848e; }
.persona-status-dot-lg { width: 16px; height: 16px; border-width: 4px; }

.bot-profile-preview-card { border-radius: 10px; overflow: hidden; background: var(--bg-elevated); }
.bot-profile-preview-banner {
  height: 60px; background: var(--accent) linear-gradient(135deg, var(--accent), var(--accent-hover));
  background-size: cover; background-position: center;
}
.bot-profile-preview-body { padding: 0 14px 14px 14px; }
.bot-profile-preview-avatar-wrap { margin-top: -28px; }
.bot-profile-preview-avatar {
  width: 64px; height: 64px; border-radius: 50%; object-fit: cover;
  border: 4px solid var(--bg-elevated); display: block; background: var(--bg-card);
}
.bot-profile-preview-name { font-weight: 700; font-size: 0.95rem; color: var(--text); margin-top: 8px; }
.bot-profile-preview-tag { font-size: 0.78rem; color: var(--text-faint); font-weight: 500; }
.bot-profile-preview-bio { color: var(--text-muted); font-size: 0.82rem; line-height: 1.4; margin-top: 10px; white-space: pre-line; }
.bot-profile-preview-activity-box {
  margin-top: 10px; background: var(--bg-card); border-radius: 6px; padding: 8px 10px;
}
.bot-profile-preview-activity-label {
  color: var(--text-faint); font-size: 0.66rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.02em;
}
.bot-profile-preview-activity-text { color: var(--text-muted); font-size: 0.82rem; margin-top: 2px; }

.persona-editor-banner-row { grid-column: 1 / -1; }
.bot-banner-upload .file-upload { max-width: none; }
.bot-banner-upload .file-upload-dropzone { max-width: 100%; aspect-ratio: 4 / 1; }
@media (max-width: 900px) {
  .bot-banner-upload .file-upload-dropzone { aspect-ratio: 2.5 / 1; }
}

.activity-row { display: flex; gap: 8px; margin-bottom: 8px; }
.activity-row-type { flex: 0 0 150px; }
.activity-row-text { flex: 1; min-width: 0; }
@media (max-width: 900px) {
  .activity-row { flex-direction: column; }
  .activity-row-type { flex: none; width: 100%; }
}

/* --- Vista previa del mensaje de bienvenida --- */
.welcome-preview-msg {
  display: flex; align-items: flex-start; gap: 12px;
  background: var(--bg-elevated); border-radius: 10px; padding: 14px;
}
/* En los editores WYSIWYG de embed (donde esta burbuja ya NO es una vista
   previa aparte, es el editor en sí) se mezcla con el fondo de la tarjeta
   que la contiene, para que sea el embed (más claro, ver .embed-wysiwyg)
   el que se note como la superficie donde se edita. */
.welcome-preview-msg:has(.embed-wysiwyg) { background: var(--bg-card); }
.welcome-preview-bot-avatar { width: 40px; height: 40px; border-radius: 50%; object-fit: cover; flex-shrink: 0; }
.welcome-preview-text { color: var(--text); font-size: 0.88rem; margin-top: 4px; white-space: pre-wrap; word-break: break-word; }

.ticket-select-preview {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: 10px; padding: 10px 12px; border-radius: 8px; width: 100%;
  background: var(--bg-card); border: 1px solid var(--border); color: var(--text-faint); font-size: 0.88rem;
  cursor: pointer;
}
.ticket-select-preview:hover { border-color: var(--accent); }
.ticket-select-preview-menu {
  margin-top: 4px; padding: 6px; border-radius: 8px; width: 100%;
  background: var(--bg-card); border: 1px solid var(--border);
}
.ticket-select-preview-option { padding: 7px 8px; border-radius: 6px; }
.ticket-select-preview-option:hover { background: var(--bg-elevated); }
.ticket-select-preview-option-name { font-size: 0.85rem; color: var(--text); }
.ticket-select-preview-option-desc { font-size: 0.74rem; color: var(--text-faint); margin-top: 1px; }

.welcome-preview-card {
  position: relative;
  width: 100%; max-width: 480px;
  aspect-ratio: 3 / 1;
  margin-top: 10px;
  border-radius: 8px;
  background-color: #23272A;
  background-size: cover;
  background-position: center;
  overflow: hidden;
}
.welcome-preview-card::before {
  content: ''; position: absolute; inset: 0; background: rgba(0, 0, 0, 0.35);
}
.welcome-preview-avatar {
  position: absolute; top: 33.3%; left: 50%; transform: translate(-50%, -50%);
  width: 14.2%; aspect-ratio: 1 / 1; border-radius: 50%;
  border: 3px solid #fff; object-fit: cover; z-index: 1;
}
.welcome-preview-cardtext {
  position: absolute; top: 68.3%; left: 50%; transform: translate(-50%, -50%);
  width: 90%; text-align: center; z-index: 1;
  font-weight: 800; color: #fff; font-size: 1.05rem;
  letter-spacing: 0.02em; text-shadow: 0 1px 3px rgba(0,0,0,0.5);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.welcome-preview-username {
  position: absolute; top: 81.7%; left: 50%; transform: translate(-50%, -50%);
  width: 90%; text-align: center; z-index: 1;
  color: #dcddde; font-size: 0.72rem;
  text-shadow: 0 1px 3px rgba(0,0,0,0.5);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* --- Emojis favoritos (rank-card-editor.ejs) — un botón "Agregar emoji" abre
   el mismo selector compartido que ya usan los editores de embed (ver
   partials/embed-toolbar.ejs + layout.ejs) apuntando a un <input> auxiliar
   ÚNICO. Ese input necesita seguir siendo real (enfocable) para que el
   selector compartido lo encuentre, así que en vez de esconderlo con
   opacity:0 (que en un elemento de texto termina "estacionado" sobre su
   posición estática y puede superponerse con otros controles cercanos, un
   bug real que pasó acá) se lo saca del todo del área visible con top/left
   bien negativos. Cada emoji elegido queda como una "chip" independiente. */
.rank-card-emoji-offscreen-input { position: absolute; top: -9999px; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.rank-card-emoji-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
.rank-card-emoji-chips:empty { margin-bottom: 0; }
.rank-card-emoji-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 8px 6px 10px; border-radius: 20px; font-size: 1.1rem;
  background: var(--bg-elevated); border: 1px solid var(--border);
}
.rank-card-emoji-chip-remove {
  display: flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 50%; border: none;
  background: var(--bg-card); color: var(--text-muted); font-size: 0.95rem; line-height: 1;
  cursor: pointer;
}
.rank-card-emoji-chip-remove:hover { background: var(--danger, #e74c3c); color: #fff; }
.rank-card-emoji-chip-img { width: 20px; height: 20px; object-fit: contain; vertical-align: middle; }

.content-rule-reaction-emoji { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
.content-rule-reaction-emoji-preview {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 34px; height: 34px; padding: 0 6px; border-radius: 8px; font-size: 1.2rem;
  background: var(--bg-elevated); border: 1px solid var(--border);
}
.content-rule-reaction-emoji-preview:empty::before { content: '—'; color: var(--text-faint); font-size: 0.9rem; }
.content-rule-reaction-emoji-clear[data-empty="1"] { display: none; }

/* Vista previa del banner al subir imagen: mismo tamaño de caja que el resto
   de subidas de imagen del panel (no una franja angosta) pero con "contain"
   en vez de "cover" y sin repetición, así se ve la imagen completa (recortada
   por .file-upload-dropzone antes) sin recortarla ni repetirla en mosaico. */
.rank-card-banner-upload .file-upload-dropzone {
  background-size: contain; background-repeat: no-repeat; background-color: #0b0c0e;
}

/* --- Editor de tarjeta de nivel, versión compacta: la vista previa y todos
   los campos viven en UNA sola tarjeta (preview arriba a todo el ancho, la
   grilla de campos debajo, la barra de acciones al final) en vez de la lista
   larga de campos apilados con <hr> de antes. El título/descripción y los
   dos <p class="hint"> de arriba comparten el mismo ancho que la tarjeta
   (antes quedaban a todo el ancho del contenedor, mientras la tarjeta ya
   tenía su propio max-width — se veían desalineados entre sí). --- */
.rank-card-editor-page { max-width: 620px; margin: 0 auto; }
.rank-card-editor-card {
  max-width: 620px; margin: 0 auto; background: var(--bg-card); border: 1px solid var(--border-soft);
  border-radius: 16px; overflow: hidden; box-shadow: var(--shadow-card);
}
.rank-card-editor-preview-wrap { position: relative; aspect-ratio: 700 / 270; background: var(--bg-elevated); }
.rank-card-editor-preview { display: block; width: 100%; aspect-ratio: 700 / 270; object-fit: cover; }
/* Chip chico flotante en la esquina — NO tapa la vista previa anterior
   mientras se genera la nueva (antes se reemplazaba todo por un cuadro gris
   grande, un parpadeo feo cada vez que cambiabas algo). */
.rank-card-editor-preview-loading {
  position: absolute; top: 10px; right: 10px;
  display: flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 50%;
  background: rgba(0, 0, 0, 0.65);
}
.rank-card-editor-spinner {
  width: 13px; height: 13px; border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, 0.3); border-top-color: #fff;
  animation: rank-card-spin 0.7s linear infinite;
}
@keyframes rank-card-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .rank-card-editor-spinner { animation: none; }
}
/* El error si tapa todo — ahí sí no hay nada útil que mostrar debajo. */
.rank-card-editor-preview-error {
  position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  padding: 20px; text-align: center; background: rgba(0, 0, 0, 0.82);
  color: var(--danger); font-size: 0.85rem;
}
.rank-card-editor-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 14px 16px; padding: 20px;
}
.rank-card-editor-grid .field-label { margin: 0 0 6px 0; }
.rank-card-editor-grid .hint { margin: 4px 0 0 0; }
.rank-card-editor-span-2 { grid-column: 1 / -1; }
/* Mismas proporciones que la tarjeta real (700×270) — antes heredaba el
   16:9 genérico de cualquier subida de imagen del panel, mucho más
   cuadrado que el banner ancho y bajo que en verdad se termina viendo. */
.rank-card-banner-upload .file-upload-dropzone { max-width: 100%; aspect-ratio: 700 / 270; }
.rank-card-editor-overlay-row { display: flex; align-items: center; justify-content: space-between; }
.rank-card-editor-overlay-row .field-label { margin: 0; }
.rank-card-editor-footer {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 20px; border-top: 1px solid var(--border-soft); background: var(--bg-elevated);
}
.rank-card-editor-footer-link { color: var(--accent); font-weight: 600; font-size: 0.86rem; text-decoration: none; }
.rank-card-editor-footer-link:hover { color: var(--accent-hover); }
@media (max-width: 640px) {
  .rank-card-editor-grid { grid-template-columns: 1fr; }
}

/* --- Vista previa tipo "embed" de Discord, para notificaciones --- */
.notif-embed {
  display: flex; gap: 12px;
  margin-top: 10px; max-width: 480px;
  background: #2b2d31; border-left: 4px solid var(--accent);
  border-radius: 4px; padding: 12px 14px;
}
.notif-embed-body { flex: 1; min-width: 0; }
.notif-embed-author { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.notif-embed-author-icon { width: 20px; height: 20px; border-radius: 50%; object-fit: cover; }
.notif-embed-author-name { font-size: 0.8rem; font-weight: 600; color: #fff; }
.notif-embed-title { font-size: 0.9rem; font-weight: 700; color: #fff; margin-bottom: 4px; }
.notif-embed-desc { font-size: 0.82rem; color: #dbdee1; }
.notif-embed-image {
  /* Discord muestra las imágenes de embed con su proporción original (sin
     recortar) — antes esto forzaba un recorte 16:9 con object-fit:cover, que
     cortaba imágenes con otra proporción y la vista previa mentía sobre cómo
     se ve realmente el mensaje. */
  display: block; width: 100%; max-width: 480px; height: auto;
  border-radius: 4px; margin-top: 8px; background: #1e1f22;
}
.notif-embed-thumb { width: 56px; height: 56px; border-radius: 4px; object-fit: cover; flex-shrink: 0; }

/* --- Campos personalizados del embed (name/value, "en línea" = 2-3 por fila) --- */
.notif-embed-fields { display: flex; flex-wrap: wrap; gap: 8px 16px; margin-top: 8px; }
.notif-embed-field { flex: 1 1 100%; min-width: 0; }
.notif-embed-field.is-inline { flex: 1 1 120px; }
.notif-embed-field-name { font-size: 0.8rem; font-weight: 700; color: #fff; margin-bottom: 2px; }
.notif-embed-field-value { font-size: 0.82rem; color: #dbdee1; white-space: pre-wrap; word-break: break-word; }

.discord-msg .notif-embed {
  padding: 16px 18px; border-radius: 6px;
}
.discord-msg .notif-embed-title { font-size: 1.02rem; }
.discord-msg .notif-embed-desc { font-size: 0.92rem; }
.discord-msg .notif-embed-thumb { width: 72px; height: 72px; border-radius: 6px; }

/* --- Vista previa de embed de solo lectura: el editor de verdad son los
   campos separados de la izquierda (Título, Descripción, Color, etc.) — esta
   caja solo refleja en vivo cómo va a quedar, no se escribe directo sobre
   ella (ver .embed-template-box para el campo de descripción editable). --- */
.embed-wysiwyg {
  flex: 1; min-width: 0;
  /* .welcome-preview-msg (la burbuja que lo envuelve) ahora usa --bg-card
     en estos editores (ver más arriba) — el embed va un tono más claro
     para que se note como la superficie donde se edita. */
  background: var(--bg-elevated);
  border-left: 4px solid var(--accent);
  border-radius: 8px;
  padding: 16px 18px;
}
.embed-wysiwyg-header-row { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.embed-wysiwyg-header-icon {
  width: 22px; height: 22px; border-radius: 50%; flex-shrink: 0;
  background: var(--bg-card); border: 1px dashed var(--border-strong);
  display: flex; align-items: center; justify-content: center; cursor: pointer;
  color: var(--text-faint); overflow: hidden;
}
.embed-wysiwyg-header-icon svg { width: 11px; height: 11px; }

.embed-wysiwyg-emoji { width: 20px; height: 20px; vertical-align: -5px; object-fit: contain; }
.embed-chip {
  display: inline-block; background: var(--bg-elevated); color: var(--text);
  border-radius: 4px; padding: 1px 6px; font-size: 0.88em; font-family: var(--font-mono);
  border: 1px solid var(--border-strong);
}

/* Campo de "plantilla del mensaje" como caja de texto propia, con su borde
   — a diferencia de .embed-wysiwyg-desc (que vive DENTRO de la vista previa
   y no necesita borde porque el contorno del embed ya lo delimita), este
   campo está afuera, en la lista de campos separados, así que sí necesita
   verse como un input de verdad. */
.embed-template-box {
  /* Mismo fondo/borde que el resto de los inputs de texto de la app (ver
     regla global de input[type=text] más abajo) — antes usaba --bg-card,
     el mismo color que la tarjeta detrás, y quedaba invisible. */
  background: #17181c; border: 1px solid var(--border-strong); border-radius: 8px;
  padding: 11px 12px; color: var(--text); font-size: 0.9rem; font-family: var(--font-sans);
  line-height: 1.6; min-height: 90px; max-height: 260px; overflow-y: auto;
  outline: none; white-space: pre-wrap; word-break: break-word;
  transition: border-color 0.12s ease;
}
.embed-template-box:focus { border-color: var(--accent); }
.embed-template-box:empty::before { content: attr(data-placeholder); color: var(--text-faint); }

/* Barra de color que atraviesa TODOS los campos del editor (no solo la vista
   previa) — refleja el mismo color que el embed va a tener, para que quede
   claro de un vistazo que todos estos campos arman una sola cosa. */
.embed-form-rail { width: 4px; border-radius: 4px; flex-shrink: 0; }
.embed-template-counter { text-align: right; font-size: 0.72rem; color: var(--text-faint); margin-top: 4px; font-family: var(--font-mono); }

/* Fila "avatar + nombre" para el autor del embed — el ícono va pegado a la
   izquierda del campo de texto, como un avatar de perfil. */
.embed-author-row { display: flex; align-items: center; gap: 10px; }
.embed-author-row input[type="text"] { flex: 1; min-width: 0; }

/* Dropzone chico y cuadrado para el ícono del autor — el genérico es
   rectangular y grande (pensado para imagen/banner), acá conviene uno
   angosto ya que en Discord el ícono del autor es chico y redondo. */
.embed-icon-upload .file-upload-dropzone { width: 40px; max-width: 40px; aspect-ratio: 1 / 1; padding: 0; border-radius: 50%; border: 2px dashed var(--border-strong); }
.embed-icon-upload .file-upload-dropzone-icon { width: 16px; height: 16px; }
.embed-icon-upload .file-upload-dropzone-title,
.embed-icon-upload .file-upload-dropzone-sub { display: none; }
.embed-icon-upload .file-upload-dropzone-remove { width: 16px; height: 16px; }
.embed-icon-upload .hint,
.embed-icon-upload .file-upload-name { display: none; }

/* Dropzone de la miniatura — sin alto fijo: estira para igualar la altura de
   los campos de Autor + Título de al lado (ver el contenedor flex-column en
   dashboard.ejs), en vez de quedar chico con espacio vacío debajo. */
.embed-thumb-upload { flex: 1; display: flex; }
.embed-thumb-upload .file-upload { flex: 1; display: flex; }
.embed-thumb-upload .file-upload-dropzone { width: 100%; max-width: 100%; height: 100%; aspect-ratio: auto; padding: 4px; border-radius: 10px; }
.embed-thumb-upload .file-upload-dropzone-icon { width: 20px; height: 20px; }
.embed-thumb-upload .file-upload-dropzone-title,
.embed-thumb-upload .file-upload-dropzone-sub { display: none; }
.embed-thumb-upload .hint,
.embed-thumb-upload .file-upload-name { display: none; }

.embed-wysiwyg-title { font-size: 1.08rem; font-weight: 800; margin-bottom: 4px; }
/* max-height + scroll como red de seguridad: un embed real de Discord no
   se desborda así, pero si el texto llega a crecer demasiado (pegado,
   duplicado por algún bug, etc.) esto evita que la caja entera se vuelva
   gigante y rompa el layout de la página. */
.embed-wysiwyg-desc { font-size: 0.92rem; color: #dbdee1; line-height: 1.6; min-height: 36px; max-height: 260px; overflow-y: auto; }
.embed-wysiwyg-footer-row { display: flex; align-items: center; gap: 8px; margin-top: 10px; }
.embed-wysiwyg-footer { font-size: 0.78rem; color: var(--text-faint); flex: 1; }

/* --- Encabezado tipo "hero" reutilizable en páginas públicas (Utilidades,
   Mis servidores, Clasificación) --- */
.utilities-page { position: relative; }

/* Encabezado tipo "hero" */
.utilities-hero { margin-bottom: 12px; margin-top: 8px; }
.utilities-hero h1 { font-size: 2.6rem; font-weight: 800; line-height: 1.15; margin: 0 0 14px 0; }
.accent-text { color: var(--accent); }
.utilities-hero p { color: var(--text-muted); font-size: 1.05rem; line-height: 1.6; max-width: 560px; margin: 0; }
.utility-stats-row { display: flex; gap: 32px; margin-top: 32px; flex-wrap: wrap; }
.utility-stat { display: flex; flex-direction: column; }
.utility-stat strong { font-size: 1.6rem; font-weight: 800; color: var(--text); font-family: var(--font-mono); line-height: 1.1; }
.utility-stat span { font-size: 0.82rem; color: var(--text-faint); margin-top: 2px; }
@media (max-width: 640px) {
  .utilities-hero h1 { font-size: 1.9rem; }
  .utility-stats-row { gap: 22px; }
}

/* Grilla de "y también" con el resto de funciones del bot, al final */
.utility-more { margin-top: 8px; padding: 48px 0 8px; border-top: 1px solid var(--border-soft); }
.utility-more-title {
  font-size: 0.78rem; font-weight: 700; color: var(--text-faint);
  text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 20px;
}
.utility-more-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.utility-more-item {
  display: flex; align-items: center; gap: 12px;
  padding: 16px 18px; background: var(--bg-card); border: 1px solid var(--border-soft);
  border-radius: 12px; color: var(--text); font-weight: 600; font-size: 0.9rem;
  transition: transform 0.2s var(--ease-out), border-color 0.2s var(--ease-out);
}
.utility-more-item:hover { transform: translateY(-3px); border-color: var(--border-strong); }
@media (max-width: 720px) { .utility-more-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .utility-more-grid { grid-template-columns: 1fr; } }

/* --- Filas estilo landing (rótulo + título grande + texto a la izquierda,
   vista previa tipo mensaje de Discord a la derecha) --- */
.utility-row {
  display: flex; align-items: center; gap: 40px;
  padding: 36px 0;
}
.utility-row-text { flex: 0 0 40%; min-width: 0; }
.utility-row-preview {
  flex: 1; min-width: 0; display: flex; justify-content: center; align-items: center;
  position: relative; padding: 20px 0;
}
.utility-row-preview::before {
  content: ''; position: absolute; z-index: 0;
  width: 320px; height: 320px; border-radius: 50%;
  background: var(--utility-glow, #5865F2); opacity: 0.16; filter: blur(50px);
  pointer-events: none;
}
.utility-row-preview > * { position: relative; z-index: 1; }
.utility-heading { font-size: 1.7rem; font-weight: 800; line-height: 1.2; margin-bottom: 10px; color: var(--text); }
.utility-row-desc { color: var(--text-muted); font-size: 0.95rem; line-height: 1.6; }
@media (max-width: 860px) {
  .utility-row { flex-direction: column; gap: 20px; padding: 26px 0; }
  .utility-row-text { flex: 1; }
  .utility-row-preview { width: 100%; order: 2 !important; }
  .utility-row-text { order: 1 !important; }
}

.discord-msg {
  display: flex; gap: 14px; width: 100%; max-width: 500px;
  background: #313338; border-radius: 12px; padding: 18px 20px;
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.35);
  transition: transform 0.3s var(--ease-out), box-shadow 0.3s var(--ease-out);
}
.discord-msg:hover { transform: translateY(-5px); box-shadow: 0 22px 50px rgba(0, 0, 0, 0.45); }
.discord-msg-avatar { width: 44px; height: 44px; border-radius: 50%; flex-shrink: 0; object-fit: cover; }
.discord-msg-body { flex: 1; min-width: 0; }
.discord-msg-header { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.discord-msg-name { font-weight: 600; color: #fff; font-size: 1.02rem; }
.discord-msg-verified {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; border-radius: 50%; background: #5865F2; color: #fff; flex-shrink: 0;
}
.discord-msg-verified svg { width: 10px; height: 10px; }
.discord-msg-badge {
  background: #5865F2; color: #fff; font-size: 0.65rem; font-weight: 700;
  padding: 2px 5px; border-radius: 3px; line-height: 1.4;
}
.discord-msg-time { color: #949ba4; font-size: 0.76rem; }
.discord-msg .notif-embed { margin-top: 8px; }
.utility-chat-line {
  display: inline-block;
  background: var(--bg-elevated); border: 1px solid var(--border);
  border-radius: 6px; padding: 5px 10px; margin-bottom: 8px;
  font-family: var(--font-mono); font-size: 0.82rem; color: var(--text-muted);
}
.utility-preview-stack { display: flex; flex-direction: column; align-items: center; width: 100%; max-width: 500px; position: relative; }
.utility-preview-stack::before {
  content: ''; position: absolute; z-index: -1;
  inset: 14px -14px -14px 14px;
  background: var(--bg-elevated); border: 1px solid var(--border-soft);
  border-radius: 14px; transform: rotate(-3deg);
}
.utility-live-badge {
  display: inline-flex; align-items: center; gap: 5px;
  background: #ef4444; color: #fff; font-size: 0.65rem; font-weight: 800;
  letter-spacing: 0.04em; padding: 2px 7px; border-radius: 4px; margin-bottom: 6px;
}
.utility-live-badge .status-dot { background: #fff; }
.utility-embed-gradient {
  background: linear-gradient(135deg, #00E701, #0a5c1f);
}

/* --- Vista previa de la tarjeta de rango (Niveles), en vez de un embed de
   texto genérico — muestra la forma real de lo que /rank genera (avatar con
   anillo de progreso, nivel, barra de XP), no el mensaje de Discord que la
   envuelve. --- */
.utility-rankcard {
  width: 100%; max-width: 460px; padding: 22px 26px; border-radius: 16px;
  background: linear-gradient(120deg, #1c1d22, #232433 60%, #262a45);
  box-shadow: 0 16px 40px rgba(0, 0, 0, 0.4);
  display: flex; align-items: center; gap: 20px;
}
.utility-rankcard-ring-wrap { position: relative; width: 74px; height: 74px; flex-shrink: 0; }
.utility-rankcard-ring { position: absolute; inset: 0; transform: rotate(-90deg); }
.utility-rankcard-avatar {
  position: absolute; inset: 7px; border-radius: 50%; object-fit: cover;
  background: linear-gradient(135deg, var(--accent), #8b5cf6);
}
.utility-rankcard-body { flex: 1; min-width: 0; }
.utility-rankcard-top { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.utility-rankcard-name { font-weight: 800; font-size: 1.15rem; color: #fff; }
.utility-rankcard-level {
  background: rgba(254, 231, 92, 0.18); color: #FEE75C; font-size: 0.7rem; font-weight: 800;
  padding: 3px 9px; border-radius: 999px;
}
.utility-rankcard-bar { height: 9px; border-radius: 999px; background: rgba(255, 255, 255, 0.08); overflow: hidden; }
.utility-rankcard-bar-fill { height: 100%; border-radius: 999px; background: linear-gradient(90deg, #FEE75C, #f5b301); }
.utility-rankcard-meta {
  display: flex; justify-content: space-between; margin-top: 6px;
  font-family: var(--font-mono); font-size: 0.74rem; color: var(--text-muted);
}

/* --- Vista previa de la tarjeta de bienvenida (Bienvenidas): la tarjeta real
   que genera el evento de bienvenida — imagen generada de verdad, no una
   aproximación en CSS. --- */
.utility-welcomecard-image { width: 100%; max-width: 460px; border-radius: 16px; box-shadow: 0 16px 40px rgba(0, 0, 0, 0.4); display: block; }

/* --- Tarjeta "editor + resultado": la vista previa real arriba, y debajo
   (separado por una línea) una franja angosta con 1-2 de los controles
   reales de edición — mismos <select>/<input> del panel real, así heredan
   su estilo sin duplicar CSS, solo que acá no hacen nada (es una vista
   previa, no el editor de verdad). --- */
.utility-editor-card {
  width: 100%; max-width: 460px; background: var(--bg-card); border: 1px solid var(--border-strong);
  border-radius: 16px; overflow: hidden; box-shadow: 0 16px 40px rgba(0, 0, 0, 0.4);
}
.utility-editor-card .utility-rankcard,
.utility-editor-card .utility-welcomecard-image,
.utility-editor-card .utility-rankcard-image { max-width: none; border-radius: 0; box-shadow: none; }
.utility-editor-strip {
  display: flex; gap: 18px; padding: 14px 18px; border-top: 1px solid var(--border-soft);
  background: var(--bg-elevated);
}
.utility-editor-field { display: flex; flex-direction: column; gap: 6px; }
.utility-editor-field.grow { flex: 1; min-width: 0; }
.utility-editor-label { font-size: 0.7rem; font-weight: 700; color: var(--text-faint); text-transform: uppercase; letter-spacing: 0.04em; }
.utility-editor-strip select, .utility-editor-strip input[type="text"] { padding: 7px 10px; font-size: 0.82rem; min-width: 120px; }
.utility-editor-swatches { display: flex; align-items: center; gap: 7px; height: 34px; }
.utility-editor-swatch { width: 20px; height: 20px; border-radius: 50%; border: 2px solid rgba(255, 255, 255, 0.15); flex-shrink: 0; }
.utility-editor-swatch.is-selected { box-shadow: 0 0 0 2px var(--bg-elevated), 0 0 0 4px var(--accent); }

/* --- Botones reales del canal de un ticket ya abierto (Reclamar/Cerrar/
   Guardar — ver ticketFlow.js), mostrados debajo del select de tipos como
   "esto pasa después de elegir uno". --- */
.utility-ticket-buttons { display: flex; gap: 8px; margin-top: 10px; }
.utility-ticket-btn {
  display: inline-flex; align-items: center; padding: 8px 14px; border-radius: 3px;
  font-size: 0.82rem; font-weight: 500; color: #fff;
}
.utility-ticket-btn.claim { background: #248046; }
.utility-ticket-btn.close { background: #da373c; }
.utility-ticket-btn.save { background: #5865F2; }

/* --- Roles por botón/menú: campos que solo aplican a un estilo, y la vista
   previa de los botones/menú (el embed en sí reutiliza .notif-embed) --- */
#role-panel-form.style-buttons .only-select { display: none; }
#role-panel-form.style-select .only-buttons { display: none; }
.role-panel-preview-btn {
  display: inline-block; padding: 8px 16px; border-radius: 4px; color: #fff;
  font-size: 0.85rem; font-weight: 500;
}
.role-panel-preview-select {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 10px 14px; border-radius: 8px; border: 1px solid rgba(255, 255, 255, 0.06);
  background: #2b2d31; color: #b5bac1; font-size: 0.88rem;
  max-width: 480px;
}
.role-panel-preview-select-chevron { flex-shrink: 0; width: 16px; height: 16px; }

/* Checklist de botones del panel de Voz temporal — cada tarjeta es un
   checkbox nativo disfrazado, se resalta con :has() cuando está marcada.
   El checkbox real queda oculto (sr-only) y .tempvoice-feature-check dibuja
   el indicador redondo con su tilde, así no depende del estilo nativo feo
   del navegador. */
.tempvoice-feature-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 10px; margin-top: 10px; max-width: 700px;
}
.tempvoice-feature-item {
  position: relative; display: flex; align-items: center; gap: 10px;
  height: 72px; padding: 10px 34px 10px 12px; box-sizing: border-box;
  background: var(--bg-elevated); border: 1px solid var(--border-soft); border-radius: 12px;
  cursor: pointer;
  transition: border-color 0.15s var(--ease-out), background-color 0.15s var(--ease-out), transform 0.15s var(--ease-out);
}
.tempvoice-feature-item:hover { border-color: var(--border); transform: translateY(-1px); }
.tempvoice-feature-item:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); }
.tempvoice-feature-item input[type="checkbox"] {
  position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0; pointer-events: none;
}
.tempvoice-feature-icon {
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 30px; height: 30px; border-radius: 9px; background: var(--bg-card); font-size: 1rem;
}
.tempvoice-feature-icon img { width: 16px; height: 16px; display: block; }
.tempvoice-feature-item-text { display: flex; flex-direction: column; gap: 2px; font-size: 0.85rem; min-width: 0; }
.tempvoice-feature-item-text strong { font-weight: 600; color: var(--text); }

/* Vista previa del panel de Voz temporal (ventana emergente): imita la
   imagen que arma el bot con canvas (tempVoiceLegendImage.js) — píldoras
   bien redondeadas, todas del mismo ancho, texto en mayúsculas — en vez de
   las píldoras genéricas de .role-panel-preview-btn (pensadas para
   Autoroles/Tickets/etc., con esquinas casi rectas y ancho libre). 5 por
   fila, igual que el ActionRow real de Discord (máximo 5 botones por fila)
   y que la cuadrícula de la imagen del bot. */
.tempvoice-legend-grid {
  display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 8px; margin-top: 10px;
}
.tempvoice-legend-pill {
  display: flex; align-items: center; justify-content: center; gap: 4px;
  background: #313338; color: #fff; font-weight: 700; font-size: 0.56rem;
  line-height: 1.15; text-transform: uppercase; text-align: center;
  padding: 8px 4px; border-radius: 16px; min-height: 40px;
}
.tempvoice-legend-pill span { overflow-wrap: break-word; }
.tempvoice-legend-pill img { width: 14px; height: 14px; flex-shrink: 0; }
.tempvoice-buttons-grid {
  display: grid; grid-template-columns: repeat(5, 40px); gap: 8px; margin-top: 10px;
}
.tempvoice-button-pill {
  display: flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; background: #4e5058; border-radius: 8px;
}
.tempvoice-button-pill img { width: 18px; height: 18px; }
.tempvoice-feature-item-text span {
  color: var(--text-faint); font-size: 0.78rem; line-height: 1.25;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.tempvoice-feature-check {
  position: absolute; top: 12px; right: 12px; width: 18px; height: 18px; flex-shrink: 0;
  border-radius: 50%; border: 1.5px solid var(--border); background: var(--bg-card);
  transition: border-color 0.15s var(--ease-out), background-color 0.15s var(--ease-out);
}
.tempvoice-feature-check::after {
  content: ''; display: block; width: 5px; height: 9px; margin: 3px auto 0 6px;
  border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg) scale(0.5);
  opacity: 0; transition: transform 0.15s var(--ease-out), opacity 0.15s var(--ease-out);
}
.tempvoice-feature-item:has(input:checked) .tempvoice-feature-check { border-color: var(--accent); background: var(--accent); }
.tempvoice-feature-item:has(input:checked) .tempvoice-feature-check::after { opacity: 1; transform: rotate(45deg) scale(1); }

/* Botón "restringir por rol" de cada botón del panel de Voz temporal —
   abajo a la derecha (el círculo de check ya ocupa arriba a la derecha). */
.tempvoice-feature-role-btn {
  position: absolute; bottom: 8px; right: 10px; width: 20px; height: 20px;
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  border-radius: 50%; border: 1.5px solid var(--border-soft); background: var(--bg-card);
  color: var(--text-faint); cursor: pointer; padding: 0;
  transition: border-color 0.15s var(--ease-out), color 0.15s var(--ease-out), background-color 0.15s var(--ease-out);
}
.tempvoice-feature-role-btn:hover { border-color: var(--accent); color: var(--accent); }
.tempvoice-feature-role-btn.has-rule { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }

/* --- Página "Estado" rediseñada --- */
.status-page-title { font-size: 2.2rem; letter-spacing: 0.02em; }
.status-page-subtitle { color: var(--text-bright-muted) !important; }

.status-stats-row {
  display: flex; flex-wrap: wrap; gap: 22px;
  margin-top: 14px; padding: 12px 16px;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 10px;
}
.status-stat { display: flex; flex-direction: column; gap: 2px; min-width: 90px; }
.status-stat-label { font-size: 0.7rem; color: var(--text-faint); font-weight: 600; }
.status-stat-value { font-size: 0.92rem; font-weight: 700; color: var(--text); font-family: var(--font-mono); }

/* --- Pestaña Estadísticas (panel del propietario) — un número protagonista
   (Comandos ejecutados) en vez de que los 4 KPIs compitan por la misma
   atención; ver el mockup "Dirección A" que se armó para esto. --- */
.stats-hero-row { display: grid; grid-template-columns: 1.3fr 1fr; gap: 16px; }
@media (max-width: 720px) { .stats-hero-row { grid-template-columns: 1fr; } }
.stats-hero-card {
  background: linear-gradient(155deg, var(--accent-soft), rgba(88, 101, 242, 0.03) 60%), var(--bg-card);
  border: 1px solid var(--border-soft); border-radius: 14px; padding: 26px 28px; box-shadow: var(--shadow-card);
  display: flex; flex-direction: column; justify-content: space-between;
}
.stats-hero-top { display: flex; align-items: center; justify-content: space-between; }
.stats-hero-icon { width: 38px; height: 38px; border-radius: 10px; background: var(--accent-soft); color: var(--accent); display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.stats-hero-icon svg { width: 20px; height: 20px; }
.stats-hero-label { font-size: 0.86rem; color: var(--text-muted); font-weight: 600; }
.stats-hero-value { font-family: var(--font-mono); font-weight: 800; font-size: 3rem; line-height: 1; color: var(--text); margin-top: 18px; }
.stats-hero-sub { font-size: 0.8rem; color: var(--text-faint); margin-top: 8px; }

.stats-kpi-stack { display: grid; grid-template-rows: repeat(3, 1fr); gap: 10px; }
.stats-kpi-tile { background: var(--bg-card); border: 1px solid var(--border); border-radius: 12px; padding: 14px 16px; display: flex; align-items: center; gap: 12px; }
.stats-kpi-icon { width: 30px; height: 30px; border-radius: 8px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.stats-kpi-icon svg { width: 15px; height: 15px; }
.stats-kpi-value { font-family: var(--font-mono); font-weight: 700; font-size: 1.25rem; color: var(--text); line-height: 1.1; }
.stats-kpi-label { font-size: 0.76rem; color: var(--text-muted); font-weight: 500; }

/* Comandos más usados: columnas (mini gráfico) en vez de barras horizontales
   — se comparan las N de un vistazo, como un mini histograma. overflow-x
   por si hay muchos comandos con nombres largos (hasta 10, ver server.js). */
.cmd-cols-chart { display: flex; align-items: flex-end; gap: 14px; height: 130px; padding-top: 8px; overflow-x: auto; }
.cmd-col-item { flex: 1; min-width: 46px; display: flex; flex-direction: column; align-items: center; justify-content: flex-end; height: 100%; }
.cmd-col-count { font-family: var(--font-mono); font-weight: 700; font-size: 0.78rem; color: var(--text-bright-muted); margin-bottom: 6px; }
.cmd-col-bar { width: 26px; border-radius: 5px 5px 0 0; background: var(--accent); }
.cmd-col-name { font-family: var(--font-mono); font-size: 0.72rem; color: var(--text-faint); margin-top: 8px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 64px; }

/* Adopción de funciones: puntitos (●●○) en vez de barra — con un total de
   servidores chico, un porcentaje con barra se siente más preciso de lo que
   es; los puntos muestran la cantidad real de una. Si hay muchos servidores
   (más de 10), no alcanza el espacio para un punto por cada uno — ahí se
   cae a mostrar solo la fracción en texto (ver el "sc-if" del lado EJS). */
.feature-pip-row { display: flex; align-items: center; gap: 14px; padding: 11px 0; }
.feature-pip-row + .feature-pip-row { border-top: 1px solid var(--border-soft); }
.feature-pip-icon { width: 26px; height: 26px; border-radius: 7px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.feature-pip-icon svg { width: 13px; height: 13px; }
.feature-pip-name { font-size: 0.85rem; font-weight: 600; color: var(--text); flex: 1; min-width: 0; }
.pip-row { display: flex; align-items: center; gap: 6px; }
.pip { width: 11px; height: 11px; border-radius: 50%; border: 1.6px solid var(--border-strong); flex-shrink: 0; }
.pip.filled { background: var(--accent); border-color: var(--accent); }
.feature-pip-frac { font-family: var(--font-mono); font-size: 0.78rem; color: var(--text-faint); width: 40px; text-align: right; flex-shrink: 0; }

/* Moderación + Otros totales: una sola fila de fichas chicas sin borde
   propio — antes eran dos tarjetas separadas con .stat-card repetido. */
.stats-footer-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px; }
.stats-footer-tile { border: 1px solid var(--border-soft); border-radius: 10px; padding: 12px 14px; }
.stats-footer-value { font-family: var(--font-mono); font-weight: 700; font-size: 1.05rem; color: var(--text-bright-muted); }
.stats-footer-label { font-size: 0.72rem; color: var(--text-faint); margin-top: 2px; }

.status-legend {
  display: flex; flex-wrap: wrap; align-items: center; gap: 16px;
  padding: 14px 0; margin-bottom: 18px; border-bottom: 1px solid var(--border);
  font-size: 0.85rem;
}
.status-legend-label { color: var(--text-muted); font-weight: 600; }
.status-legend-item { display: inline-flex; align-items: center; gap: 6px; color: var(--text); font-weight: 600; }

.status-bot-row {
  display: flex; align-items: center; gap: 12px;
  padding: 14px 16px; background: var(--bg-card); border: 1px solid var(--border); border-radius: 10px;
}
.status-bot-avatar { width: 32px; height: 32px; border-radius: 50%; object-fit: cover; }
.status-bot-name { font-weight: 700; color: var(--text); flex: 1; }
.status-badge-inline {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 0.78rem; font-weight: 700; color: var(--text);
  background: var(--bg-elevated); padding: 4px 10px; border-radius: 6px;
}

/* --- Anticrash minimalista --- */
.anticrash-card { border-color: var(--border); margin-top: 24px; }
.anticrash-source-pill {
  display: inline-block; padding: 3px 10px; border-radius: 6px;
  background: rgba(218, 55, 60, 0.12); color: var(--danger);
  font-family: var(--font-mono); font-weight: 600; font-size: 0.78rem;
  white-space: nowrap;
}
#anticrash-table td:nth-child(3) { max-width: 480px; word-break: break-word; }
.hint code { font-family: var(--font-mono); }

/* --- Zona de arrastrar-y-soltar para subir archivos (reemplaza el input nativo, feo por defecto) --- */
.file-input-hidden { position: absolute; width: 1px; height: 1px; opacity: 0; overflow: hidden; }
.file-upload { display: flex; flex-direction: column; align-items: stretch; gap: 8px; }
.file-upload-dropzone {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  width: 100%; max-width: 360px; aspect-ratio: 16 / 9; padding: 20px; border-radius: 10px;
  border: 2px dashed var(--border-strong); background: var(--bg-elevated);
  background-size: cover; background-position: center;
  cursor: pointer; text-align: center; position: relative; overflow: hidden;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}
.file-upload-dropzone:hover, .file-upload-dropzone.dragover {
  border-color: var(--accent); background-color: var(--accent-soft);
}
.file-upload-dropzone-icon {
  display: flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 50%;
  background: var(--bg-card); color: var(--text-muted);
}
.file-upload-dropzone-prompt { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px; }
.file-upload-dropzone-title { font-weight: 700; color: var(--text); font-size: 0.92rem; }
.file-upload-dropzone-sub { font-size: 0.85rem; color: var(--text-faint); }
.file-upload-dropzone-link { color: var(--accent); font-weight: 600; }
.file-upload-dropzone:hover .file-upload-dropzone-link { text-decoration: underline; }
.file-upload-name { font-size: 0.82rem; color: var(--text-muted); font-style: italic; }
.file-upload-name:empty { display: none; }

/* --- Estado "hay imagen": se oculta el texto de arrastre, se oscurece al pasar el mouse y aparece la X --- */
.file-upload-dropzone.has-image { border-style: solid; }
.file-upload-dropzone.has-image .file-upload-dropzone-prompt { display: none; }
.file-upload-dropzone.has-image::before {
  content: ''; position: absolute; inset: 0; background: rgba(0, 0, 0, 0);
  transition: background 0.15s ease; pointer-events: none;
}
.file-upload-dropzone.has-image:hover::before { background: rgba(0, 0, 0, 0.45); }
.file-upload-dropzone-remove {
  display: none; position: absolute; top: 8px; right: 8px; z-index: 2;
  width: 28px; height: 28px; border-radius: 50%; border: none;
  align-items: center; justify-content: center;
  background: rgba(0, 0, 0, 0.65); color: #fff; cursor: pointer;
  opacity: 0; transition: opacity 0.15s ease, background 0.15s ease;
}
.file-upload-dropzone.has-image .file-upload-dropzone-remove { display: flex; }
.file-upload-dropzone.has-image:hover .file-upload-dropzone-remove { opacity: 1; }
.file-upload-dropzone-remove:hover { background: var(--danger, #e74c3c); }

.discord-emoji { width: 20px; height: 20px; vertical-align: middle; object-fit: contain; }
.discord-quote {
  display: block; position: relative; padding-left: 10px; margin: 2px 0;
  border-left: 3px solid var(--text-faint);
  color: var(--text-muted);
}

/* --- Pestañas dentro de una página (Anuncios: Embed clásico/Components V2, Registros: General/Registro de acciones) ---
   overflow-x:auto en vez de que las pestañas se apilen o empujen la página
   entera hacia los costados: cuando hay muchas (ej. una por regla en Control
   de canales) esta fila se vuelve deslizable en vez de romper el layout. */
.panel-tabs {
  display: flex; gap: 8px; margin-bottom: 16px; border-bottom: 1px solid var(--border-soft);
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  /* El scroll sigue funcionando (arrastrar/swipe/rueda) — solo se oculta la
     barra nativa, que se ve fea (con flechitas) y no combina con el resto del diseño. */
  scrollbar-width: none; -ms-overflow-style: none;
  /* overflow-x:auto fuerza a overflow-y a "auto" también (así lo define la
     spec), así que sin este colchón el margin-bottom:-1px del tab activo
     (de más abajo) queda recortado y la barrita de "seleccionado" desaparece. */
  padding-bottom: 3px;
}
.panel-tabs::-webkit-scrollbar { display: none; }
.panel-tab-btn {
  background: none; border: none; color: var(--text-muted); font-family: var(--font-sans);
  font-size: 0.88rem; font-weight: 600; padding: 10px 16px; cursor: pointer;
  border-bottom: 2px solid transparent; margin-bottom: -1px; transition: color 0.12s ease;
  flex-shrink: 0; white-space: nowrap;
  /* Acá también se usa en <a> (leaderboard.ejs), no solo en <button> — sin
     esto el navegador le pone su subrayado de link por defecto, encima del
     borde inferior que ya marca la pestaña activa. */
  text-decoration: none;
}
.panel-tab-btn:hover { color: var(--text); }
.panel-tab-btn.active { color: var(--accent); border-bottom-color: var(--accent); }

/* --- Barra de formato de embeds: negrita/cursiva/subrayado/tachado/código
   (envuelven la selección del textarea con el markdown de Discord) + chips
   de variables clickeables ({user}, {level}, etc. — insertan el texto en el
   cursor). Un solo botón visual, dos comportamientos según lleve data-wrap
   o data-insert (ver el listener delegado en layout.ejs). --- */
.embed-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 8px; }
/* Agrupa los botones por función (formato / insertar) en una cápsula con
   fondo tenue, en vez de una fila plana de cuadrados sueltos — más fácil de
   escanear de un vistazo. Las variables ({user}, {server}...) van aparte,
   ver .embed-toolbar-chip abajo. */
.embed-toolbar-group {
  display: flex; gap: 4px; background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.08); border-radius: 9px; padding: 4px;
}
.embed-toolbar-btn {
  /* Ancho fijo (no min-width + padding horizontal) para que B/I/U/S/</>/@/#/
     emoji formen una fila de cuadrados parejos — antes cada uno crecía
     según el ancho de su propio contenido y quedaban disparejos. */
  width: 32px; height: 32px; padding: 0; border-radius: 6px;
  border: none; background: transparent; color: var(--text);
  cursor: pointer; font-size: 0.9rem; font-family: var(--font-sans); font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center; line-height: 1;
  flex-shrink: 0;
  transition: background 0.15s var(--ease-out), color 0.15s var(--ease-out);
}
.embed-toolbar-btn:hover { background: rgba(255, 255, 255, 0.1); }
.embed-toolbar-btn i { font-style: italic; }
.embed-toolbar-btn u { text-decoration: underline; }
.embed-toolbar-btn s { text-decoration: line-through; }
/* "#" queda ópticamente corrido hacia arriba dentro de su caja centrada
   (es la fuente, no el layout — la caja ya está bien centrada). El "@" de
   al lado usa un ícono SVG (ver partials/icon.ejs) en vez de texto, así
   queda centrado de verdad sin depender de cómo dibuje ese glifo la fuente. */
.embed-toolbar-channel-btn span { display: inline-block; transform: translateY(1px); }
.embed-toolbar-chip {
  width: auto; height: 32px; border-radius: 7px; font-family: var(--font-mono); font-weight: 400; font-size: 0.8rem;
  padding: 0 12px; border: 1px dashed var(--accent); background: var(--accent-soft); color: var(--accent);
}
.embed-toolbar-chip:hover { background: rgba(88, 101, 242, 0.2); }
.embed-toolbar-emoji-btn { font-size: 1.15rem; }

/* --- Selector de emojis compartido (uno solo por página, se reposiciona
   junto al botón que lo abrió — ver openEmojiPicker en layout.ejs).
   position:absolute (no fixed) + colgado directo del <body> por JS, para
   que se mueva junto con el scroll de la página en vez de quedar flotando
   en un lugar fijo de la pantalla. --- */
.emoji-picker {
  position: absolute; z-index: 500; width: 260px; max-height: 340px; overflow-y: auto;
  background: var(--bg-card); border: 1px solid var(--border-strong); border-radius: 10px;
  box-shadow: var(--shadow-card); padding: 12px;
}
.emoji-picker-section-title {
  font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--text-faint); margin: 12px 0 8px;
}
.emoji-picker-section-title:first-child { margin-top: 0; }
.emoji-picker-grid { display: flex; flex-wrap: wrap; gap: 4px; }
.emoji-picker-item {
  width: 32px; height: 32px; border-radius: 6px; border: 1px solid transparent;
  background: transparent; cursor: pointer; font-size: 1.1rem;
  display: flex; align-items: center; justify-content: center;
  transition: background 0.12s var(--ease-out), border-color 0.12s var(--ease-out);
}
.emoji-picker-item:hover { background: var(--bg-elevated); border-color: var(--border); }
.emoji-picker-item img { width: 22px; height: 22px; object-fit: contain; }

/* --- Selector de mención (#canal) — misma idea que el de emojis, como
   lista buscable en vez de grilla --- */
.mention-picker {
  position: absolute; z-index: 500; width: 240px; max-height: 280px;
  background: var(--bg-card); border: 1px solid var(--border-strong); border-radius: 10px;
  box-shadow: var(--shadow-card); padding: 8px; display: flex; flex-direction: column;
}
.mention-picker-search-wrap { position: relative; flex-shrink: 0; margin-bottom: 6px; }
.mention-picker-search-icon {
  position: absolute; left: 9px; top: 50%; transform: translateY(-50%);
  color: var(--text-faint); display: flex; pointer-events: none;
}
/* Especificidad (0,2,0) a propósito: le gana a la regla global
   `input[type="text"] { padding: 11px 12px; }` (especificidad (0,1,1)) que
   si no, pisa el padding-left de acá sin importar el valor que se le ponga
   — mismo problema ya visto con .guild-search-input. */
.mention-picker-search-wrap .mention-picker-search {
  width: 100%; padding: 7px 10px 7px 30px; border-radius: 6px;
  border: 1px solid var(--border-strong); background: var(--bg-elevated); color: var(--text);
  font-size: 0.82rem; font-family: var(--font-sans);
}
.mention-picker-list { overflow-y: auto; display: flex; flex-direction: column; gap: 1px; }
.mention-picker-item {
  display: flex; align-items: center; gap: 9px; width: 100%; text-align: left;
  padding: 6px 8px; border-radius: 6px; border: none; background: transparent;
  color: var(--text); font-size: 0.85rem; cursor: pointer;
  transition: background 0.12s var(--ease-out);
}
.mention-picker-item:hover { background: var(--bg-elevated); }
.mention-picker-item .mention-picker-hash { color: var(--text-faint); flex-shrink: 0; width: 16px; text-align: center; }
.mention-picker-item .mention-picker-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mention-picker-empty { color: var(--text-faint); font-size: 0.8rem; padding: 8px; }

/* --- Toggle switch --- */
.toggle-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.toggle-row-text { flex: 1; }
.toggle-row-title { font-weight: 600; font-size: 0.92rem; display: flex; align-items: center; gap: 8px; }
.toggle-row-desc { color: var(--text-muted); font-size: 0.88rem; line-height: 1.5; margin-top: 3px; }
/* Recuadro para agrupar un .toggle-row (y opcionalmente sus campos
   dependientes) como una unidad visual dentro de una tarjeta — solo el
   borde, sin fondo propio, para no competir con el color de la tarjeta. */
.toggle-row-box { border: 1px solid rgba(255, 255, 255, 0.14); border-radius: 10px; padding: 14px 16px; }
.toggle-row-box .toggle-row { padding: 0; border: none; }
/* Variante con fondo propio, mismo tono que .mod-command-row (la lista de
   comandos de Moderación) — para listas largas de interruptores (ej.
   Registro de acciones) donde cada caja debe distinguirse de la tarjeta
   igual que lo hacen los comandos. */
.toggle-row-box.filled { background: #1a1b1f; border-color: var(--border-strong); }

.toggle { position: relative; display: inline-flex; align-items: center; cursor: pointer; flex-shrink: 0; }
.toggle input { position: absolute; opacity: 0; width: 0; height: 0; }
.toggle .track {
  width: 44px; height: 26px; border-radius: 999px;
  background: var(--bg-elevated); border: 1px solid var(--border-strong);
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.28);
  position: relative;
  transition: background 0.25s var(--ease-out), border-color 0.25s var(--ease-out), box-shadow 0.25s var(--ease-out);
}
.toggle:hover .track { border-color: var(--text-faint); }
.toggle .thumb {
  position: absolute; top: 2px; left: 2px; width: 20px; height: 20px;
  border-radius: 50%; background: #9a9ca6;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
  transition: transform 0.25s var(--ease-out), background 0.25s var(--ease-out), width 0.15s var(--ease-out);
}
.toggle:active .thumb { width: 24px; }
.toggle input:focus-visible + .track { outline: 2px solid var(--accent); outline-offset: 2px; }
.toggle input:checked + .track {
  background: linear-gradient(135deg, var(--accent), var(--accent-hover));
  border-color: var(--accent);
  box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15), 0 0 10px 0 rgba(88, 101, 242, 0.4);
}
.toggle input:checked + .track .thumb { transform: translateX(18px); background: #fff; }
/* Interruptor de solo lectura — refleja el estado de un módulo sin permitir
   tocarlo desde acá (ver Ajustes → Comandos del servidor). */
.toggle:has(input:disabled) { cursor: not-allowed; opacity: 0.55; }
/* Variante compacta, para grillas densas de interruptores (ej. Feature flags). */
.toggle.toggle-small .track { width: 34px; height: 20px; }
.toggle.toggle-small .thumb { width: 14px; height: 14px; }
.toggle.toggle-small input:checked + .track .thumb { transform: translateX(14px); }
.toggle.toggle-small:active .thumb { width: 17px; }

/* --- Grilla de módulos con interruptor global (Estado del bot → Feature flags) --- */
.flags-module-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 10px; }
.flags-module-item {
  display: flex; align-items: center; gap: 10px;
  background: #1a1b1f; border: 1px solid var(--border-strong); border-radius: 10px;
  padding: 10px 12px;
}
.flags-module-icon { display: flex; color: var(--text-muted); flex-shrink: 0; }
.flags-module-label { flex: 1; font-size: 0.88rem; font-weight: 500; }

/* --- Aviso de "módulo apagado" bajo el interruptor principal --- */
.locked-hint {
  display: flex; align-items: center; gap: 10px;
  padding: 14px 18px; border-radius: 14px;
  border: 1px dashed var(--border-strong);
  color: var(--text-muted); font-size: 0.88rem;
}
.locked-hint svg { color: var(--text-faint); flex-shrink: 0; }

/* Aviso cuando el propietario real del bot entra a un servidor sin ser
   miembro (ver ensureGuildAccess en checkAuth.js) — nunca debe sentirse como
   "otro servidor más", para no confundirlo con uno propio por accidente. */
.owner-bypass-banner {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 18px; border-radius: 12px;
  background: rgba(254, 231, 92, 0.1); border: 1px solid rgba(254, 231, 92, 0.35);
  color: #FEE75C; font-size: 0.86rem; font-weight: 600;
  margin-bottom: 16px;
}
.owner-bypass-banner svg { flex-shrink: 0; }

/* --- Command list --- */
.command-list { display: flex; flex-direction: column; gap: 8px; }
/* Listas que pueden crecer mucho (ej. Recompensas por nivel con muchos
   niveles configurados) — sin esto, la tarjeta entera se estira sin límite y
   hay que scrollear toda la página para llegar a lo que sigue debajo. */
.command-list-scroll { max-height: 420px; overflow-y: auto; padding-right: 6px; }
.command-item {
  background: #232429; border: 1px solid var(--border-strong); border-left: 3px solid var(--success);
  border-radius: 12px; padding: 9px 16px; display: flex; align-items: center; justify-content: space-between; gap: 12px;
  transition: border-color 0.15s var(--ease-out), background 0.15s var(--ease-out);
}
.command-item:hover { background: #26272d; border-color: rgba(255, 255, 255, 0.16); }
.command-item-main { min-width: 0; }
.command-name {
  font-family: var(--font-mono); font-weight: 700; font-size: 0.84rem;
  background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 6px;
  padding: 1px 7px; display: inline-block; color: var(--text);
}
.command-response { color: var(--text-muted); font-size: 0.8rem; word-break: break-word; margin-top: 3px; }

/* --- Fila de "panel publicado" (Autoroles, Tickets, Comandos
   personalizados, Mensaje personalizado, Control de canales, Voz
   temporal, Encuestas, Sorteos): ícono del tipo a la izquierda, título +
   subtítulo al centro, acciones como íconos discretos a la derecha — y la
   fila punteada de "crear" va DENTRO de la misma lista, como primer
   elemento, en vez de un botón aparte arriba de la tarjeta. */
.panel-create-row {
  display: flex; align-items: center; gap: 14px; padding: 14px 16px;
  border-radius: 12px; border: 1.5px dashed var(--border-strong); background: transparent;
  color: var(--text-muted); font-family: inherit; cursor: pointer; text-align: left; width: 100%;
  transition: border-color 0.15s var(--ease-out), background 0.15s var(--ease-out);
}
.panel-create-row:hover { background: rgba(88, 101, 242, 0.06); border-color: var(--accent); }
.panel-create-row:disabled { opacity: 0.5; cursor: not-allowed; }
.panel-create-row:disabled:hover { background: transparent; border-color: var(--border-strong); }
.panel-create-row-icon {
  width: 36px; height: 36px; border-radius: 10px; background: rgba(88, 101, 242, 0.12);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0; color: var(--accent);
}
.panel-create-row-label { font-weight: 700; font-size: 0.92rem; color: var(--text); }

.panel-item {
  display: flex; align-items: center; gap: 14px; padding: 14px 16px;
  border-radius: 12px; background: #1a1b1f; border: 1px solid var(--border-strong);
  transition: border-color 0.15s var(--ease-out), background 0.15s var(--ease-out);
}
.panel-item:hover { background: #202126; border-color: rgba(255, 255, 255, 0.16); }
.panel-item-icon {
  width: 36px; height: 36px; border-radius: 10px; background: var(--bg-elevated);
  display: flex; align-items: center; justify-content: center; flex-shrink: 0; color: var(--text-muted);
}
.panel-item-text { min-width: 0; flex: 1; }
.panel-item-name { font-weight: 700; font-size: 0.92rem; color: var(--text); }
.schedule-badge {
  display: inline-flex; align-items: center; margin-left: 6px; padding: 2px 8px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent); font-size: 0.68rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em;
}
.panel-item-desc { font-size: 0.8rem; color: var(--text-muted); margin-top: 2px; word-break: break-word; }
.panel-item-actions { display: flex; align-items: center; gap: 2px; flex-shrink: 0; }
.panel-icon-btn {
  display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px;
  padding: 0; border-radius: 8px; border: none; background: transparent; color: var(--text-muted);
  cursor: pointer; transition: background 0.15s var(--ease-out), color 0.15s var(--ease-out);
}
.panel-icon-btn:hover { background: var(--bg-elevated); color: var(--text); }
.panel-icon-btn.danger { color: var(--danger); opacity: 0.75; }
.panel-icon-btn.danger:hover { background: rgba(218, 55, 60, 0.12); color: var(--danger); opacity: 1; }
.panel-icon-btn svg { transition: transform 0.15s var(--ease-out); }
.panel-icon-btn.expanded svg { transform: rotate(180deg); }

/* --- Variante de .panel-item con una segunda fila colapsable debajo (ej.
   Encuestas: requisitos/resultados) — .panel-item pasa a columna solo
   cuando envuelve una .panel-item-row, así que Autoroles/Tickets/etc. (que
   no la usan) no cambian en nada. --- */
.panel-item:has(.panel-item-row) { flex-direction: column; align-items: stretch; gap: 10px; }
.panel-item-row { display: flex; align-items: center; gap: 14px; }
.panel-item-detail { border-top: 1px solid var(--border); padding-top: 10px; }
.panel-item-detail p.hint:first-child { margin-top: 0; }

/* --- Clasificación pública de niveles (/leaderboard/:guildId) --- */

/* Banner del servidor (real si lo tiene configurado en Discord; si no,
   se usa su ícono difuminado de fondo, mismo patrón que .guild-card-banner)
   con el ícono superpuesto — el avatar va como hermano del banner, no
   metido adentro, porque el banner necesita overflow:hidden para recortar
   su propio fondo difuminado y eso recortaría al avatar si estuviera anidado. */
.leaderboard-hero-banner-wrap { position: relative; margin-bottom: 52px; }
.leaderboard-hero-banner {
  height: 180px; border-radius: 16px; overflow: hidden; position: relative;
  background: linear-gradient(135deg, var(--accent-soft), transparent);
  border: 1px solid var(--border-soft);
}
.leaderboard-hero-banner-blur {
  position: absolute; inset: -20%;
  background-image: var(--banner-img); background-size: cover; background-position: center;
  filter: blur(26px) saturate(1.3) brightness(0.55); transform: scale(1.15);
}
/* El banner real se ve completo (sin recortar) encima del fondo difuminado
   de arriba — antes se estiraba con background-size:cover en una caja bien
   angosta (180px de alto) y quedaba prácticamente todo cortado por arriba/abajo. */
.leaderboard-hero-banner-full {
  position: absolute; inset: 0;
  background-size: contain; background-repeat: no-repeat; background-position: center;
}
.leaderboard-hero-avatar {
  width: 96px; height: 96px; border-radius: 22px; object-fit: cover;
  border: 4px solid var(--bg); background: var(--bg-card);
  position: absolute; left: 50%; bottom: -44px; transform: translateX(-50%);
  box-shadow: var(--shadow-card);
}
.leaderboard-hero-avatar-placeholder {
  display: flex; align-items: center; justify-content: center;
  font-size: 2.2rem; font-weight: 800; color: var(--text-faint);
}
.leaderboard-hero-text { text-align: center; }
.leaderboard-hero-text p { margin-left: auto; margin-right: auto; }
.leaderboard-hero-text .utility-stats-row { justify-content: center; }
.leaderboard-customize-btn { margin-top: 24px; display: inline-flex; }
@media (max-width: 600px) {
  .leaderboard-hero-banner { height: 130px; }
  .leaderboard-hero-avatar { width: 76px; height: 76px; bottom: -34px; }
  .leaderboard-hero-banner-wrap { margin-bottom: 42px; }
}

/* Podio del top 3 */
.leaderboard-podium {
  display: grid; grid-template-columns: repeat(3, 1fr); align-items: end;
  gap: 16px; margin: 8px 0 24px;
}
.podium-item {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 4px; padding: 20px 14px 18px; border-radius: 14px;
  background: var(--bg-card); border: 1px solid var(--border-soft);
  transition: transform 0.2s var(--ease-out); position: relative;
  /* Sin esto, el "white-space: nowrap" de .podium-name obliga a esta columna
     del grid a no encogerse por debajo del ancho completo del nombre (el
     elipsis de .podium-name nunca llega a aplicarse) — con un nombre largo
     eso desborda la columna hacia la derecha, comiéndose el gap con la
     barra lateral aunque el CSS del gap esté bien. */
  min-width: 0;
}
.podium-item:hover { transform: translateY(-3px); }
.podium-avatar { width: 56px; height: 56px; border-radius: 50%; border: 3px solid var(--border); margin-bottom: 4px; }
.podium-position { font-family: var(--font-mono); font-weight: 700; font-size: 0.8rem; color: var(--text-faint); }
.podium-name {
  font-weight: 700; color: var(--text); max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.podium-xp { font-size: 0.8rem; color: var(--text-muted); font-family: var(--font-mono); }
.podium-crown { position: absolute; top: -14px; color: #FFD700; background: var(--bg); border-radius: 50%; padding: 4px; }
.podium-1 { padding-top: 28px; border-color: #FFD700; box-shadow: 0 0 0 1px rgba(255, 215, 0, 0.3), 0 16px 32px -16px rgba(255, 215, 0, 0.35); order: 2; }
.podium-1 .podium-avatar { width: 72px; height: 72px; border-color: #FFD700; }
.podium-2 { border-color: #C0C0C0; order: 1; }
.podium-2 .podium-avatar { border-color: #C0C0C0; }
.podium-3 { border-color: #CD7F32; order: 3; }
.podium-3 .podium-avatar { border-color: #CD7F32; }
/* La fila/puesto de quien mira la página, resaltado para que no se pierda
   buscándose entre 100 personas — outline en vez de box-shadow/border-color
   para no pisar el dorado/plateado/bronce de los puestos 1-3. */
.podium-item-me { background: var(--accent-soft); outline: 2px solid var(--accent); outline-offset: 2px; }
@media (max-width: 600px) {
  .leaderboard-podium { grid-template-columns: 1fr; }
  .podium-1, .podium-2, .podium-3 { order: initial; padding-top: 20px; }
}

.leaderboard-list { display: flex; flex-direction: column; }
.leaderboard-row {
  display: flex; align-items: center; gap: 14px;
  padding: 12px 20px; border-bottom: 1px solid var(--border-soft);
  transition: background 0.15s var(--ease-out);
}
.leaderboard-row:hover { background: var(--bg-elevated); }
.leaderboard-row:last-child { border-bottom: none; }
/* La fila de quien mira la página — para no perderse buscándose entre 100
   personas. padding-left compensado (20px - 3px del borde) para que el
   contenido no se corra respecto a las demás filas. */
.leaderboard-row-me { background: var(--accent-soft); border-left: 3px solid var(--accent); padding-left: 17px; }
.leaderboard-row-me:hover { background: var(--accent-soft); }
.leaderboard-me-badge {
  display: inline-block; margin-left: 4px; padding: 1px 7px; border-radius: 999px;
  background: var(--accent); color: #fff; font-size: 0.68rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.03em; vertical-align: middle;
}
.leaderboard-position {
  width: 28px; height: 28px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; background: #3a3b40; /* fijo (no --bg-elevated): que siga
  distinguiéndose del círculo incluso cuando la fila entera se ilumina al pasar el mouse */
  font-weight: 700; color: #fff; font-family: var(--font-mono); font-size: 0.85rem;
}
.leaderboard-avatar { width: 40px; height: 40px; border-radius: 50%; flex-shrink: 0; }
.leaderboard-name {
  flex: 1; min-width: 0; font-weight: 600; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.leaderboard-xp {
  color: var(--text-faint); font-size: 0.85rem; font-family: var(--font-mono);
  flex-shrink: 0; min-width: 90px; text-align: right;
}
/* Agrupa XP + anillo de nivel. */
.leaderboard-meta { display: flex; align-items: center; gap: 14px; flex-shrink: 0; }
.leaderboard-card { padding: 0; }

/* En celular, directamente se oculta la XP en texto (igual que MEE6) en vez
   de acomodarla — el anillo de nivel ya muestra el nivel Y el progreso (el
   arco), así que no hace falta el número exacto de XP en un espacio tan
   chico. Eso le devuelve al nombre todo el ancho que antes se repartía con
   el texto de XP. La pestaña de Likes NO tiene anillo (no hay "progreso"
   que mostrar), así que ahí sí se deja el número — por eso el selector
   excluye .leaderboard-xp-likes en vez de ocultar la clase entera. */
@media (max-width: 480px) {
  .leaderboard-row { gap: 8px; padding: 10px 12px; }
  .leaderboard-row-me { padding-left: 9px; }
  .leaderboard-position { width: 22px; height: 22px; font-size: 0.72rem; }
  .leaderboard-avatar { width: 30px; height: 30px; }
  .leaderboard-name { font-size: 0.92rem; }
  .leaderboard-xp:not(.leaderboard-xp-likes) { display: none; }
  .leaderboard-xp-likes { font-size: 0.78rem; min-width: 0; }
  .level-ring { width: 34px; height: 34px; }
  .level-ring-value { font-size: 0.74rem; }
}

/* Anillo de progreso circular alrededor del nivel — usado en la lista y en el
   podio (con .level-ring-lg). El SVG arranca girado -90° para que el trazo
   empiece arriba (como reloj) en vez de a la derecha. */
.level-ring { position: relative; width: 36px; height: 36px; flex-shrink: 0; display: inline-flex; align-items: center; justify-content: center; }
.level-ring-lg { width: 46px; height: 46px; }
.level-ring-svg { position: absolute; inset: 0; width: 100%; height: 100%; transform: rotate(-90deg); }
.level-ring-track { fill: none; stroke: var(--border-soft); stroke-width: 3; }
.level-ring-progress { fill: none; stroke-width: 3; stroke-linecap: round; transition: stroke-dashoffset 0.6s var(--ease-out); }
.level-ring-value { position: relative; font-family: var(--font-mono); font-weight: 700; color: var(--text); font-size: 0.76rem; }
.level-ring-lg .level-ring-value { font-size: 0.9rem; }

/* Layout de 2 columnas: clasificación a la izquierda, tarjetas de rango/
   recompensas a la derecha (se apila en una sola columna en mobile). */
.leaderboard-layout { display: grid; grid-template-columns: 1fr 300px; align-items: start; gap: 36px; }
.leaderboard-main { min-width: 0; }
.leaderboard-sidebar { display: flex; flex-direction: column; gap: 16px; }
@media (max-width: 900px) {
  .leaderboard-layout { grid-template-columns: 1fr; }
  /* En una sola columna, la barra lateral (Personalizar tarjeta,
     Recompensas) pasaba a verse DESPUÉS de todo el podio + la lista
     completa — para llegar a "Personalizar tarjeta" en un servidor con
     mucha gente había que scrollear muchísimo. Con order (nada más cambia
     el orden visual, no el del HTML) queda arriba de todo en celular. */
  .leaderboard-sidebar { order: -1; }
}
/* Tarjetas de la barra lateral como <details>/<summary> nativos: se pueden
   colapsar sin JS y el chevron dibujado con ::after deja claro que hay
   contenido editable/expandible debajo, igual que la referencia que pasó
   el usuario. */
.leaderboard-side-card summary {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  font-weight: 700; font-size: 0.95rem; color: var(--text);
  cursor: pointer; list-style: none;
  padding-bottom: 14px; border-bottom: 1px solid var(--border-soft);
}
.leaderboard-side-card summary::-webkit-details-marker { display: none; }
.leaderboard-side-card summary::after {
  content: ''; width: 7px; height: 7px; flex-shrink: 0;
  border-right: 2px solid var(--text-faint); border-bottom: 2px solid var(--text-faint);
  transform: rotate(45deg); transition: transform 0.2s var(--ease-out);
}
.leaderboard-side-card[open] summary::after { transform: rotate(-135deg); }
.leaderboard-side-card-desc { color: var(--text-muted); font-size: 0.82rem; line-height: 1.5; margin: 12px 0 4px; }
.leaderboard-side-card .leaderboard-customize-btn { margin-top: 14px; width: 100%; justify-content: center; }

/* --- Galería de tarjetas (/guilds/:guildId/tarjetas) --- */
.card-gallery-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 18px;
}
.card-gallery-item {
  background: var(--bg-card); border: 1px solid var(--border-soft); border-radius: 14px;
  overflow: hidden; box-shadow: var(--shadow-card);
  transition: border-color 0.2s var(--ease-out), transform 0.2s var(--ease-out);
}
.card-gallery-item:hover { border-color: var(--accent-soft); transform: translateY(-2px); }
.card-gallery-item-self { border-color: var(--accent); }
.card-gallery-img { width: 100%; aspect-ratio: 700 / 270; object-fit: cover; display: block; background: var(--bg-elevated); }
.card-gallery-footer {
  display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 14px;
}
.card-gallery-self-badge {
  font-size: 0.75rem; font-weight: 700; color: var(--accent); background: var(--accent-soft);
  border-radius: 20px; padding: 3px 10px;
}
.card-gallery-like-form { margin-left: auto; }
.card-gallery-like-btn { white-space: nowrap; }
.card-gallery-pagination {
  display: flex; align-items: center; justify-content: center; gap: 16px; margin-top: 24px;
}
.card-gallery-page-label { color: var(--text-muted); font-size: 0.88rem; }

/* Maqueta decorativa de la tarjeta de rango personal (sin datos reales,
   solo para dar contexto visual de qué se está personalizando) */
.rankcard-preview {
  display: flex; align-items: center; gap: 10px;
  background: linear-gradient(135deg, var(--accent-soft), transparent);
  border: 1px solid var(--border-soft); border-radius: 10px; padding: 12px; margin: 4px 0;
}
.rankcard-preview-avatar {
  width: 32px; height: 32px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-card); border: 1px solid var(--border); color: var(--text-faint);
}
.rankcard-preview-bar { flex: 1; height: 8px; border-radius: 999px; background: var(--bg-card); overflow: hidden; }
.rankcard-preview-bar span { display: block; height: 100%; width: 55%; border-radius: 999px; background: linear-gradient(90deg, var(--accent), #9C84EF); }

.leaderboard-rewards-list { display: flex; flex-direction: column; gap: 14px; margin-top: 14px; }
.leaderboard-reward-group { display: flex; flex-direction: column; gap: 6px; }
.leaderboard-reward-level {
  color: var(--text-faint); font-weight: 700; font-size: 0.68rem;
  text-transform: uppercase; letter-spacing: 0.06em;
}
.leaderboard-reward-pill {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px; border-radius: 8px; font-size: 0.85rem; font-weight: 600;
  background: var(--bg-elevated); border: 1px solid var(--border); color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.leaderboard-reward-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; background: var(--accent); }

.command-item-actions { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }

.empty-state { color: var(--text-faint); font-size: 0.88rem; padding: 12px 0; }

/* --- Sub-bloque compacto dentro de una sola tarjeta (ej. Roles protegidos):
   varias listas cortas una debajo de otra, separadas por un título chico y
   una línea, en vez de una tarjeta grande por cada una. --- */
.compact-subsection { padding-top: 18px; margin-top: 18px; border-top: 1px solid var(--border); }
.compact-subsection:first-child { padding-top: 0; margin-top: 0; border-top: none; }
.compact-subsection-title { font-weight: 700; font-size: 0.85rem; display: flex; align-items: center; gap: 6px; margin-bottom: 3px; }
.compact-subsection-desc { color: var(--text-muted); font-size: 0.78rem; line-height: 1.4; margin-bottom: 10px; }
.compact-add-form { display: flex; gap: 8px; margin-bottom: 10px; }
.compact-add-form select { padding: 7px 10px; font-size: 0.82rem; flex: 0 1 260px; width: auto; }
/* Mismo caso que en .inline-form: un <select> de canal acá también se
   reemplaza en runtime por .searchable-select y necesita su propio tope. */
.compact-add-form .searchable-select { flex: 0 1 260px; width: auto; }

.chip-list { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: rgba(88, 101, 242, 0.08); border: 1px solid rgba(88, 101, 242, 0.18); border-radius: 6px;
  padding: 4px 4px 4px 12px; font-size: 0.8rem; font-weight: 600; color: var(--text);
}
.chip form { display: contents; }
.chip-remove {
  display: flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 50%; border: none; padding: 0;
  background: transparent; color: var(--text-faint); cursor: pointer; flex-shrink: 0;
}
.chip-remove:hover { background: var(--danger); color: white; }
.chip-remove svg { width: 11px; height: 11px; }

/* --- Selector de emojis del Starboard: mosaico de "casillas" con el emoji
   grande en vez de chips con texto — cada una lleva su propia X flotando en
   la esquina para sacarla, y al final va la casilla de "+" para agregar más. --- */
.starboard-emoji-list { display: flex; flex-wrap: wrap; gap: 10px; }
.starboard-emoji-tile {
  position: relative; width: 44px; height: 44px; border-radius: 10px;
  background: var(--bg-elevated); border: 1px solid var(--border-strong);
  display: flex; align-items: center; justify-content: center; font-size: 1.3rem;
}
.starboard-emoji-tile img { width: 24px; height: 24px; object-fit: contain; }
.starboard-emoji-tile-remove {
  position: absolute; top: -6px; right: -6px; width: 18px; height: 18px; border-radius: 50%;
  background: var(--danger); color: white; border: 2px solid var(--bg-card); padding: 0;
  display: flex; align-items: center; justify-content: center; cursor: pointer;
}
.starboard-emoji-add-tile {
  width: 44px; height: 44px; border-radius: 10px;
  background: var(--bg-elevated); border: 1px dashed var(--border-strong); color: var(--text-faint);
  display: flex; align-items: center; justify-content: center; cursor: pointer;
  transition: border-color 0.12s ease, color 0.12s ease;
}
.starboard-emoji-add-tile:hover { border-color: var(--accent); color: var(--accent); }

/* --- Stepper numérico (−/campo/+), reusable para cualquier número corto --- */
.stepper { display: inline-flex; align-items: center; gap: 8px; }
.stepper input[type="number"] { width: 64px; text-align: center; }
.stepper input[type="number"]::-webkit-inner-spin-button,
.stepper input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.stepper-btn {
  width: 40px; height: 40px; border-radius: 8px; border: 1px solid var(--border-strong);
  background: var(--bg-elevated); color: var(--text); font-size: 1.1rem; font-weight: 700; line-height: 1;
  display: flex; align-items: center; justify-content: center; cursor: pointer; flex-shrink: 0;
  transition: border-color 0.12s ease, color 0.12s ease;
}
.stepper-btn:hover { border-color: var(--accent); color: var(--accent); }

/* Dropdown propio para elegir rol en un .multi-picker, con color/ícono real
   del rol de Discord — un <select> nativo no puede mostrar eso dentro de
   cada opción (limitación del elemento en todos los navegadores), así que
   este reemplaza visualmente al <select> oculto cuando hay roles con color
   o ícono entre las opciones (ver el script que arma esto en dashboard.ejs;
   si ningún rol trae color/ícono, se deja el <select> nativo tal cual). */
.multi-picker { position: relative; }
/* Envuelve select+botón+desplegable, SEPARADO de la fila de chips ya
   elegidos (ver el JS que arma esto) — así "top: 100%" del desplegable se
   calcula contra la altura del botón nada más, no contra el picker entero
   (que crece con cada chip agregado). */
.multi-picker-control { position: relative; }
.multi-picker-trigger {
  width: 100%; padding: 11px 12px; border-radius: 8px; border: 1px solid var(--border-strong);
  background: #17181c; color: var(--text-faint); font-size: 0.9rem; cursor: pointer;
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.multi-picker-trigger::after {
  content: ''; width: 10px; height: 6px; flex-shrink: 0;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%236b6d76' stroke-width='1.5' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") no-repeat center;
}
.multi-picker-trigger:hover, .multi-picker-trigger.is-open { border-color: var(--accent); }
.multi-picker-trigger.is-disabled { opacity: 0.5; cursor: not-allowed; }
.multi-picker-dropdown {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 20;
  background: #17181c; border: 1px solid var(--border-strong); border-radius: 8px;
  padding: 6px; max-height: 320px; display: flex; flex-direction: column;
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.45);
}
/* Cuando el campo está pegado al borde inferior de la pantalla (ver
   openDropdown en dashboard.ejs), se abre para ARRIBA en vez de para abajo
   — si no, el desplegable estira la altura de toda la página hacia abajo y
   el foco automático del buscador fuerza un scroll brusco para alcanzarlo. */
.multi-picker-dropdown.multi-picker-dropdown-up { top: auto; bottom: calc(100% + 4px); }
/* Buscador arriba del dropdown — filtra las filas de abajo al escribir, algo
   que un <select> nativo no puede hacer (solo salta a la primera opción que
   empiece con la letra tocada, nada de coincidencia parcial). */
.multi-picker-search {
  width: 100%; padding: 8px 10px; margin-bottom: 6px; flex-shrink: 0;
  border-radius: 6px; border: 1px solid var(--border-strong);
  background: var(--bg-elevated); color: var(--text); font-size: 0.85rem;
}
.multi-picker-search:focus { outline: none; border-color: var(--accent); }
.multi-picker-dropdown-rows { overflow-y: auto; }
.multi-picker-dropdown-option {
  display: flex; align-items: center; gap: 8px; padding: 8px 10px; border-radius: 6px;
  cursor: pointer; font-size: 0.88rem; color: var(--text);
}
.multi-picker-dropdown-option:hover, .multi-picker-dropdown-option.is-active { background: var(--bg-elevated); }
.multi-picker-option-icon {
  width: 18px; height: 18px; border-radius: 50%; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center; font-size: 0.85rem; line-height: 1;
}
.multi-picker-dropdown-empty { padding: 8px 10px; font-size: 0.85rem; color: var(--text-faint); }

/* --- Editor incremental de botones/opciones (Comandos personalizados y
   Autoroles): nada de filas vacías pre-creadas — se agrega de a un botón con
   un disparador fantasma, se completa en un panel compacto, y queda como
   píldora en la lista. --- */
.button-chip-list { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; margin-bottom: 10px; }
.button-chip { display: inline-flex; align-items: center; gap: 4px; }
/* La píldora en sí imita el botón real de Discord: fondo sólido según su
   estilo (primario/secundario/éxito/peligro/enlace), texto blanco, emoji +
   etiqueta — para que se vea tal cual quedará en el mensaje. */
.button-chip-preview {
  display: inline-flex; align-items: center; gap: 6px;
  border-radius: 8px; padding: 8px 14px; font-size: 0.85rem; font-weight: 500;
  color: #fff; cursor: pointer; border: none;
}
.button-chip-emoji { line-height: 1; display: inline-flex; align-items: center; }
.button-chip-emoji img { width: 18px; height: 18px; display: block; }
.button-chip-link-icon { opacity: 0.8; font-size: 0.8rem; }
.button-chip-move {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border: 1px solid var(--border-strong); background: var(--bg-card);
  color: var(--text-muted); cursor: pointer; border-radius: 6px; padding: 0; font-size: 0.65rem; flex-shrink: 0;
}
.button-chip-move:hover { background: var(--border-strong); color: var(--text); }
.button-chip-edit, .button-chip-remove {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; border: 1px solid var(--border-strong); background: var(--bg-card);
  color: var(--text-muted); cursor: pointer; border-radius: 6px; padding: 0; flex-shrink: 0;
}
.button-chip-edit:hover { background: var(--border-strong); color: var(--text); }
.button-chip-edit img { width: 13px; height: 13px; object-fit: contain; }
.button-chip-remove { color: var(--danger); }
.button-chip-remove:hover { background: var(--danger); color: #fff; border-color: var(--danger); }

.button-emoji-picker-btn {
  width: 44px; height: 40px; flex: 0 0 44px; border-radius: 8px;
  border: 1px solid var(--border-strong); background: var(--bg-card); color: var(--text-muted);
  font-size: 1.1rem; cursor: pointer; display: flex; align-items: center; justify-content: center;
  transition: border-color 0.15s var(--ease-out), color 0.15s var(--ease-out);
}
.button-emoji-picker-btn:hover { border-color: var(--accent); color: var(--text); }
.button-emoji-picker-btn img { width: 20px; height: 20px; display: block; }

.button-add-trigger {
  display: flex; align-items: center; gap: 8px; width: 100%;
  border: 1px dashed var(--border-strong); border-radius: 10px; background: transparent;
  color: var(--text-muted); padding: 12px 14px; font-size: 0.9rem; font-weight: 600;
  cursor: pointer; transition: border-color 0.15s var(--ease-out), color 0.15s var(--ease-out);
}
.button-add-trigger:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.button-add-trigger:disabled { opacity: 0.5; cursor: not-allowed; }
.button-add-trigger-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 50%; border: 1px solid currentColor; flex-shrink: 0;
}

.button-editor-panel {
  margin-top: 10px; background: var(--bg-elevated); border: 1px solid var(--border); border-radius: 10px;
  padding: 14px;
}
.button-editor-panel-title {
  font-family: var(--font-mono); font-size: 0.7rem; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--text-faint); margin-bottom: 10px;
}
.button-editor-panel-row { display: flex; gap: 8px; margin-bottom: 10px; flex-wrap: wrap; }
.button-editor-panel-emoji { flex: 0 0 44px; padding: 0; text-align: center; }
.button-editor-panel-label { font-size: 0.72rem; color: var(--text-faint); margin-bottom: 4px; display: block; }
.button-editor-panel-error { color: var(--danger); font-size: 0.8rem; margin: -2px 0 10px; }
.button-editor-panel-actions { display: flex; gap: 8px; justify-content: flex-start; margin-top: 4px; }

/* --- Botón "?" de ayuda contextual junto a una etiqueta de campo — usado en
   Control de canales para explicar el modo elegido sin ocupar espacio fijo
   en pantalla (aparece al pasar el mouse o al tocarlo en mobile). --- */
.field-label-row { display: flex; align-items: center; gap: 6px; margin-top: 14px; }
.field-label-row .field-label { margin: 0; }
.field-help {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 50%; flex-shrink: 0;
  background: transparent; border: none; padding: 0; color: var(--danger); cursor: help;
  position: relative;
}
.field-help-tooltip {
  position: absolute; bottom: calc(100% + 9px); left: 50%; transform: translateX(-50%) translateY(4px);
  background: #111214; color: var(--text); border: 1px solid var(--border-strong);
  border-radius: 8px; padding: 8px 11px; font-size: 0.78rem; font-weight: 400; line-height: 1.35;
  /* min() en vez de un max-width fijo: en pantallas angostas (celular) 230px
     puede ser más ancho que el propio viewport, y como está centrado sobre
     un botón de 20px, se saldría por uno de los dos costados. */
  width: max-content; max-width: min(230px, calc(100vw - 56px)); text-align: left; box-shadow: var(--shadow-card);
  opacity: 0; visibility: hidden; transition: opacity .12s ease, transform .12s ease;
  pointer-events: none; z-index: 30;
}
.field-help-tooltip::after {
  content: ''; position: absolute; top: 100%; left: 50%; transform: translateX(-50%);
  border: 5px solid transparent; border-top-color: #111214;
}
.field-help:hover .field-help-tooltip, .field-help.active .field-help-tooltip {
  opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0); pointer-events: auto;
}
/* En celular el "?" suele estar cerca del borde izquierdo de la tarjeta (los
   campos son angostos ahí) — centrado, la burbuja se sale por la izquierda.
   Se alinea a la izquierda del botón en vez de centrarla, así siempre crece
   hacia la derecha, que es donde sobra espacio. */
@media (max-width: 600px) {
  .field-help-tooltip { left: 0; transform: translateY(4px); max-width: min(220px, calc(100vw - 64px)); }
  .field-help-tooltip::after { left: 10px; transform: none; }
  .field-help:hover .field-help-tooltip, .field-help.active .field-help-tooltip { transform: translateY(0); }
}

/* --- Control de canales: campos más angostos (no necesitan el ancho de la
   tarjeta entera) y bloques condicionales (timeout/dar-rol) que solo se
   muestran para su modo correspondiente. --- */
#control-canales input[type="text"], #control-canales input[type="number"], #control-canales select {
  max-width: 320px;
}
/* El select del multi-picker (canales/roles) necesita la regla repetida acá
   con su propia clase — vive dentro de un .multi-picker que se reusa en
   otras secciones del panel, así que no alcanza con el selector de arriba. */
#control-canales .multi-picker-select { max-width: 320px; }
.content-rule-conditional-field { display: none; }
.content-rule-conditional-field.active { display: block; }
/* En celular, 320px puede ser más ancho que la tarjeta disponible (ej. un
   iPhone SE deja ~300px libres) — se vuelve a ancho completo. El !important
   es necesario porque el select/multi-picker de Control de canales llevan
   ese máximo puesto como estilo inline (ver content-rule-fields.ejs). */
@media (max-width: 520px) {
  #control-canales input[type="text"], #control-canales input[type="number"], #control-canales select,
  #control-canales .multi-picker, #control-canales .multi-picker-select {
    max-width: 100% !important;
  }
}
/* --- Registro de actividad (auditoría) --- */
.audit-card-header {
  width: 100%; display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  padding: 24px; background: none; border: none; cursor: pointer; text-align: left; font: inherit; color: inherit;
}
.audit-collapse-chevron {
  flex-shrink: 0; display: flex; color: var(--text-muted); margin-top: 2px;
  transform: rotate(180deg); transition: transform 0.2s var(--ease-out);
}
.audit-card.collapsed .audit-collapse-chevron { transform: rotate(0deg); }
.audit-card-body { border-top: 1px solid var(--border); }
.audit-card.collapsed .audit-card-body { display: none; }

/* Lista compacta de "Salud de módulos" (Estado → Diagnóstico) — puntito de
   estado en vez de una tarjeta con ícono por fila, para que quepan varios
   módulos sin tanto scroll. */
.diag-poller-grid { display: grid; grid-template-columns: 1fr 1fr; column-gap: 24px; }
@media (max-width: 640px) { .diag-poller-grid { grid-template-columns: 1fr; } }
.diag-poller-row { display: flex; align-items: center; gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--border); }
.diag-poller-row:last-child { border-bottom: none; }
.diag-poller-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; background: var(--success); }
.diag-poller-dot.stale { background: var(--danger); }
.diag-poller-label { color: var(--text); font-size: 0.82rem; font-weight: 500; flex: 1; min-width: 0; }
.diag-poller-time { color: var(--text-faint); font-size: 0.78rem; flex-shrink: 0; }
.diag-poller-time.stale { color: var(--danger); }

.audit-table-wrap { overflow-x: auto; }
.audit-table { width: 100%; min-width: 560px; border-collapse: collapse; font-size: 0.88rem; }
.audit-table th { padding: 0; border-bottom: 1px solid var(--border); }
.audit-table td { padding: 14px 20px; border-bottom: 1px solid var(--border); color: var(--text-muted); vertical-align: middle; }
.audit-table tbody tr:last-child td { border-bottom: none; }
.audit-table tbody tr { transition: background 0.15s var(--ease-out); }
.audit-table tbody tr:hover { background: var(--bg-elevated); }
.audit-th-actions { width: 44px; }

.audit-sort-btn {
  display: flex; align-items: center; gap: 6px; width: 100%;
  padding: 16px 20px; background: none; border: none; cursor: pointer; font: inherit;
  color: var(--text); font-size: 0.85rem; white-space: nowrap;
}
.audit-sort-btn:hover { color: var(--accent); }

/* Antes era un solo carácter "↕/↑/↓" que se intercambiaba por JS — se
   reemplaza por dos triangulitos apilados (uno arriba, uno abajo) dibujados
   con el truco del border, así se ve de una sola vez cuál de los dos está
   activo en vez de tener que leer un glifo ambiguo. */
.audit-sort-icons { display: inline-flex; flex-direction: column; gap: 3px; margin-left: 1px; }
.audit-sort-arrow {
  width: 0; height: 0; border-left: 4px solid transparent; border-right: 4px solid transparent;
  opacity: 0.4; transition: opacity 0.12s ease, border-color 0.12s ease;
}
.audit-sort-arrow-up { border-bottom: 5px solid var(--text-faint); }
.audit-sort-arrow-down { border-top: 5px solid var(--text-faint); }
.audit-sort-arrow.active { opacity: 1; }
.audit-sort-arrow-up.active { border-bottom-color: var(--accent); }
.audit-sort-arrow-down.active { border-top-color: var(--accent); }

.audit-user-pill {
  display: inline-block; padding: 3px 10px; border-radius: 6px;
  background: var(--accent-soft); color: var(--accent); font-weight: 600; font-size: 0.85rem;
}
.audit-row-copy-btn {
  display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 8px; border: none; background: none;
  color: var(--text-faint); cursor: pointer; transition: background 0.15s var(--ease-out), color 0.15s var(--ease-out);
}
.audit-row-copy-btn:hover { background: var(--bg-card); color: var(--text); }

.audit-pagination {
  display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap;
  padding: 16px 20px; font-size: 0.85rem; color: var(--text-muted);
}
.audit-rows-per-page { display: flex; align-items: center; gap: 8px; }
/* padding-right amplio a propósito: el <select> ya trae su flecha dibujada
   a mano (ver la regla base "select") en right:12px — con el padding chico
   que tenía antes (10px), el número y esa flecha quedaban pegados/encimados. */
.audit-rows-per-page select { width: auto; min-width: 64px; padding: 6px 30px 6px 10px; font-size: 0.85rem; }
.audit-page-controls { display: flex; align-items: center; gap: 6px; }
.audit-page-btn {
  width: 28px; height: 28px; display: flex; align-items: center; justify-content: center;
  border-radius: 6px; border: 1px solid var(--border); background: var(--bg-card);
  color: var(--text-muted); cursor: pointer; font-size: 0.9rem; transition: background 0.15s var(--ease-out), color 0.15s var(--ease-out);
}
.audit-page-btn:hover:not(:disabled) { background: var(--bg-elevated); color: var(--text); }
.audit-page-btn:disabled { opacity: 0.4; cursor: default; }

/* --- Footer action bar --- */
.form-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 20px; }

.ui-icon { vertical-align: middle; flex-shrink: 0; }

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

/* --- Página de Comandos --- */
.commands-layout { display: grid; grid-template-columns: 200px 1fr; gap: 20px; align-items: start; margin-top: 24px; }
.commands-categories { display: flex; flex-direction: column; gap: 4px; }
.commands-category-btn {
  text-align: left;
  padding: 12px 14px;
  border-radius: 8px;
  border: none;
  background: var(--bg-card);
  color: var(--text-muted);
  font-weight: 600;
  font-size: 0.9rem;
  cursor: pointer;
  transition: background 0.18s var(--ease-out), color 0.18s var(--ease-out), transform 0.18s var(--ease-out);
}
.commands-category-btn:hover { color: var(--text); background: var(--bg-elevated); transform: translateX(3px); }
.commands-category-btn.active { background: var(--accent); color: white; transform: translateX(0); }

.commands-table-card { padding: 0; overflow: hidden; }
.commands-table-wrap { overflow-x: auto; }
.commands-table { width: 100%; min-width: 640px; border-collapse: collapse; font-size: 0.88rem; }
.commands-table th {
  text-align: left; padding: 16px 20px; color: var(--text);
  font-size: 0.85rem; border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
.commands-table td { padding: 16px 20px; border-bottom: 1px solid var(--border); color: var(--text-muted); vertical-align: top; }
.commands-table tr:last-child td { border-bottom: none; }
.commands-table tbody tr { transition: background 0.15s var(--ease-out); }
.commands-table tbody tr:hover { background: var(--bg-elevated); }
.commands-name { font-family: var(--font-mono); color: var(--accent); font-weight: 700; }
.commands-table td code {
  font-family: var(--font-mono); font-size: 0.82rem; color: var(--text);
  background: var(--bg-elevated); padding: 3px 7px; border-radius: 5px; white-space: nowrap;
}

code { background: var(--bg-elevated); padding: 2px 6px; border-radius: 4px; font-family: var(--font-mono); }

/* ============================================================
   RESPONSIVE: tablets y móviles
   ============================================================ */
/* La grilla de 3 columnas del header público (marca / nav central / acciones)
   reserva un ancho fijo ("auto") para el nav central sin importar qué tan
   angostas queden las columnas de los costados — en un servidor con nombre
   largo (badge "Panel conectado" incluido) o un usuario con nombre largo,
   esas columnas empiezan a superponerse con el nav bastante antes de los
   768px del breakpoint "móvil" de más abajo. Este breakpoint aparte SOLO
   adelanta el quiebre a una fila propia del nav (no toca padding/tamaños de
   letra, que siguen recién en 768px) para no afectar el header del panel de
   un servidor (que no usa esta grilla de 3 columnas). */
@media (max-width: 900px) {
  .topbar.has-center-nav {
    display: flex; flex-wrap: wrap; justify-content: space-between; row-gap: 8px;
  }
  .topbar.has-center-nav .topbar-left { order: 1; justify-self: initial; }
  .topbar.has-center-nav .topbar-right { order: 2; justify-self: initial; }
  .topbar.has-center-nav .topbar-center-nav {
    order: 3; justify-self: initial; flex-basis: 100%;
    padding-top: 8px; border-top: 1px solid var(--border);
  }
}
@media (max-width: 768px) {
  /* La barra lateral (solo existe dentro del panel de un servidor) se
     convierte en un cajón (drawer) que se desliza desde la izquierda por
     encima del contenido, en vez de un bloque apilado arriba de todo. */
  .app-shell { flex-direction: column; }
  .sidebar {
    position: fixed; top: 0; left: 0; z-index: 300;
    width: min(300px, 82vw); height: 100vh; height: 100dvh;
    padding: 20px 16px;
    border-right: 1px solid var(--border);
    box-shadow: 16px 0 40px rgba(0, 0, 0, 0.5);
    transform: translateX(-100%);
    transition: transform 0.25s ease;
  }
  .sidebar.mobile-open { transform: translateX(0); }
  .sidebar-close {
    display: flex; align-items: center; justify-content: center;
    position: absolute; top: 16px; right: 16px;
    width: 30px; height: 30px; border-radius: 8px;
    background: var(--bg-card); border: 1px solid var(--border); color: var(--text-muted);
    cursor: pointer;
  }
  .sidebar-close svg { width: 16px; height: 16px; }
  .sidebar-close:hover { color: var(--text); border-color: var(--accent); }

  .topbar {
    padding: 12px 14px;
  }
  .mobile-sidebar-toggle { display: flex; }
  .user-chip span { display: none; } /* solo se ve el avatar, ahorra espacio */
  .topbar-link { padding: 6px 8px; font-size: 0.8rem; }
  .topbar-brand-name { max-width: 42vw; }
  .topbar-right { gap: 10px; }
  .topbar-right .btn-gray { padding: 7px 10px; font-size: 0.78rem; white-space: nowrap; }
  .topbar-center-nav { gap: 16px; font-size: 0.8rem; }

  .container { padding: 24px 16px 60px 16px; }
  .page-header h1 { font-size: 1.5rem; }
  .page-header p { max-width: 100%; }
  .page-header.page-header-toggle { flex-direction: column; align-items: stretch; gap: 12px; }
  .header-toggle { padding-top: 0; }

  .hero { padding: 60px 16px; }
  .hero h1 { font-size: 1.7rem; }

  .card { padding: 18px; }

  /* Filas de "añadir" (rol, tipo, streamer...) se apilan en vez de quedar apretadas */
  .inline-form { flex-direction: column; align-items: stretch; }
  .inline-form select, .inline-form input { width: 100%; }
  .inline-form .btn { width: 100%; }
  .button-editor-panel-row { flex-direction: column; align-items: stretch; }
  .button-editor-panel-emoji { flex: 1; }

  /* Los ítems de listas (roles, comandos, streamers) se apilan para que los botones no queden pegados al texto */
  .command-item { flex-direction: column; align-items: stretch; }
  .command-item-actions { justify-content: flex-end; }

  /* Fila de servidor (Estado → Servidores): a diferencia del resto de
     .panel-item-actions (siempre íconos chicos, ej. Autoroles/Tickets), acá
     son 3 botones de texto ("Ver config"/"Salir"/"Lista negra") que no
     entran junto al ícono + nombre del servidor en una pantalla angosta —
     pasan a su propia fila debajo, envolviendo si hace falta. Se apunta con
     :has() (no una clase nueva) para no tocar los .panel-item con botones
     de ícono, que ya andan bien en una sola fila. */
  .panel-item-row:has(.panel-item-actions .btn) { flex-wrap: wrap; }
  .panel-item-row:has(.panel-item-actions .btn) .panel-item-actions {
    flex-basis: 100%; flex-wrap: wrap; justify-content: flex-end; gap: 6px; margin-top: 8px;
  }

  /* Botones de guardar/descartar a todo el ancho, más fáciles de tocar */
  .form-actions { flex-direction: column-reverse; }
  .form-actions .btn { width: 100%; }

  .toggle-row { gap: 10px; }

  .guild-grid { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
  .stats-grid { grid-template-columns: repeat(2, 1fr); }
  .stat-card { padding: 14px; }
  .inicio-hero .stat-card:nth-child(2n+1) { border-left: none; padding-left: 0; }
  .inicio-hero .stat-card:nth-child(2n) { padding-right: 0; }
  .stats-pill-row { gap: 8px 18px; justify-content: flex-start; }

  .commands-layout { grid-template-columns: 1fr; }
  .commands-categories { flex-direction: row; overflow-x: auto; }
  .commands-table td, .commands-table th { padding: 12px 14px; }
}

@media (max-width: 480px) {
  .menu-card { min-height: unset; }
  .icon-btn-optional { display: none; } /* ya no queda ninguno, se deja por compatibilidad */
  .status-badge-text { display: none; } /* solo el punto verde, ahorra espacio */
  .status-badge { padding: 6px; }
  .status-badge { font-size: 0.65rem; padding: 4px 9px; }

  /* La tabla de Comandos se apila como tarjetas en vez de depender del
     scroll horizontal (que en el celular no se nota que se puede hacer). */
  .commands-table, .commands-table thead, .commands-table tbody, .commands-table tr, .commands-table td {
    display: block;
    width: 100%;
  }
  .commands-table { min-width: 0; }
  .commands-table thead { display: none; }
  .commands-table tr {
    padding: 14px 16px;
    border-bottom: 1px solid var(--border);
  }
  .commands-table td { padding: 4px 0; border-bottom: none; }
  .commands-table td::before {
    content: attr(data-label);
    display: block;
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-faint);
    margin-bottom: 3px;
  }
  .commands-table td code { white-space: normal; word-break: break-word; }
}

/* --- Selector de canal con búsqueda (reemplaza los <select> de canales por
   uno con caja de texto para filtrar escribiendo — ver el script en layout.ejs
   que los detecta automáticamente, sin tocar cada formulario) --- */
.searchable-select { position: relative; width: 100%; }
.searchable-select-control {
  display: flex; align-items: center; gap: 2px; cursor: pointer;
  padding: 10px 8px 10px 12px; border-radius: 8px; border: 1px solid var(--border-strong);
  background: #17181c; transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.searchable-select-control:focus-within {
  border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft);
}
.searchable-select-control:focus-within .searchable-select-toggle { color: var(--text); }
.searchable-select-icon-static {
  flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  color: var(--text-faint); margin-right: 2px;
}
/* El <input> de adentro es, para el navegador, un input[type="text"] normal,
   así que la regla genérica de inputs (línea ~571) le gana en especificidad y
   le mete su propio borde/fondo/padding — hace falta "input." (no solo la
   clase) para empatar esa especificidad y que gane por ir después en el
   archivo. Así el input queda siempre sin borde ni fondo propios y nunca
   cambia de color (ni al pasar el mouse ni al enfocar) — todo el resaltado
   visual vive únicamente en .searchable-select-control de arriba. */
input.searchable-select-input, input.searchable-select-input:focus, input.searchable-select-input:hover {
  flex: 1; min-width: 0; width: auto; border: none; background: none; outline: none;
  box-shadow: none; border-radius: 0;
  color: var(--text); font-size: 0.9rem; font-family: var(--font-sans);
  padding: 0; cursor: pointer;
}
.searchable-select-input::placeholder { color: var(--text-faint); }
.searchable-select-clear, .searchable-select-toggle {
  flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border: none; background: none; padding: 0;
  color: var(--text-faint); cursor: pointer; border-radius: 5px;
}
.searchable-select-clear:hover, .searchable-select-toggle:hover { color: var(--text); background: var(--bg-card); }
.searchable-select-toggle { margin-left: 6px; border-left: 1px solid var(--border); }
.searchable-select-toggle svg { transition: transform 0.12s ease; }
.searchable-select.open .searchable-select-toggle svg { transform: rotate(180deg); }
.searchable-select-panel {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 30;
  background: var(--bg-card); border: 1px solid var(--border); border-radius: 8px;
  box-shadow: var(--shadow-card); max-height: 240px; overflow-y: auto; padding: 6px;
  scrollbar-width: thin; scrollbar-color: var(--border) transparent;
}
.searchable-select-panel::-webkit-scrollbar { width: 8px; }
.searchable-select-panel::-webkit-scrollbar-track { background: transparent; }
.searchable-select-panel::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }
.searchable-select-panel::-webkit-scrollbar-thumb:hover { background: var(--text-faint); }
.searchable-select-option {
  padding: 8px 10px; border-radius: 6px; font-size: 0.88rem; color: var(--text);
  cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.searchable-select-option.active, .searchable-select-option:hover { background: var(--bg-elevated); }
.searchable-select-option.selected { font-weight: 600; }
.searchable-select-empty { padding: 10px; font-size: 0.85rem; color: var(--text-faint); text-align: center; }

/* --- Selector de fuente (Bienvenidas/Despedidas/Personalizar tarjeta) —
   mismo componente de arriba, pero el disparador cerrado es un botón con el
   nombre de la fuente elegida (no una caja de texto editable), y el panel
   trae su propia caja de búsqueda separada — como el selector de fuentes de
   Canva que pidió el usuario de referencia. --- */
.searchable-select-font .searchable-select-icon {
  flex-shrink: 0; display: flex; align-items: center; justify-content: center;
  width: 18px; font-family: Georgia, 'Times New Roman', serif; font-size: 0.95rem;
  font-weight: 600; color: var(--text-faint);
}
button.searchable-select-trigger {
  font: inherit; color: var(--text); text-align: left; width: 100%;
  appearance: none; -webkit-appearance: none;
}
.searchable-select-value {
  flex: 1; min-width: 0; font-size: 0.9rem; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap;
}
.searchable-select-font .searchable-select-panel {
  max-height: 250px; display: flex; flex-direction: column; padding: 8px; overflow: hidden;
}
/* El "display: flex" de arriba le gana al [hidden] del navegador (una regla
   con "display" propio siempre le gana a la del user-agent, sin importar el
   atributo) — sin esto el panel queda visible y tapando lo que hay debajo
   incluso cuando panel.hidden = true en JS. */
.searchable-select-font .searchable-select-panel[hidden] { display: none; }
.searchable-select-search-wrap {
  position: relative; flex-shrink: 0; padding-bottom: 8px; margin-bottom: 6px;
  border-bottom: 1px solid var(--border);
}
.searchable-select-search-icon {
  position: absolute; left: 10px; top: 0; bottom: 8px; display: flex; align-items: center;
  color: var(--text-faint); pointer-events: none;
}
.searchable-select-search-wrap input.searchable-select-input {
  display: block; width: 100%; border: 1px solid var(--border-strong); border-radius: 6px;
  padding: 7px 10px 7px 30px; background: #101114; color: var(--text); font-size: 0.85rem;
  font-family: var(--font-sans); outline: none; cursor: text;
}
.searchable-select-search-wrap input.searchable-select-input:focus {
  border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft);
}
.searchable-select-search-wrap input.searchable-select-input::placeholder { color: var(--text-faint); }
.searchable-select-options {
  flex: 1; min-height: 0; overflow-y: auto;
  scrollbar-width: thin; scrollbar-color: var(--border) transparent;
}
.searchable-select-options::-webkit-scrollbar { width: 8px; }
.searchable-select-options::-webkit-scrollbar-track { background: transparent; }
.searchable-select-options::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }
.searchable-select-options::-webkit-scrollbar-thumb:hover { background: var(--text-faint); }
.searchable-select-font .searchable-select-option {
  display: flex; align-items: center; gap: 8px;
}
.searchable-select-font .searchable-select-option .searchable-select-icon { color: var(--text-muted); }

/* --- Entrada suave (fade + slide) al aparecer en pantalla — Inicio,
   Comandos y Utilidades. Ver el observer en layout.ejs. --- */
[data-reveal] {
  opacity: 0; transform: translateY(16px);
  transition: opacity 0.7s var(--ease-out), transform 0.7s var(--ease-out);
}
[data-reveal].is-revealed { opacity: 1; transform: translateY(0); }
