/* ============================================================
   Tipografía AUTO-ALOJADA. La CSP del panel es estricta
   (style-src 'self'), así que una hoja de Google Fonts se queda
   bloqueada y el panel acaba con la fuente del sistema. Este es
   un woff2 VARIABLE: un único archivo de 32 KB cubre del peso
   100 al 900. Subset 'latin' (U+0000-00FF), que incluye todos
   los acentos y los signos ¿¡ del español.
   ============================================================ */
@font-face {
  font-family: 'Outfit';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url("/static/fonts/outfit-var.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* Brutalist / Industrial Tech Palette */
  --bg: #09090b;
  --surface: rgba(18, 18, 20, 0.65);
  --surface-solid: rgba(24, 24, 27, 0.85);
  --text: #f4f4f5;
  --text-muted: #a1a1aa;
  
  --border: #27272a;
  --border-hover: #52525b;
  
  --primary: #ffffff;
  --primary-hover: #e4e4e7;
  --primary-bg: #27272a;
  --on-primary: #000000;
  
  --accent: #518cff; /* NAXcord official accent */
  /* Soft edges */
  --radius: 16px;
  --radius-btn: 12px;

  /* Grosor del borde de las superficies (tarjetas, paneles, barra superior).
     Ver la regla agrupada más abajo: con 1px las esquinas redondeadas salen
     más apagadas que los tramos rectos. */
  --border-w: 2px;

  /* Alto real de la barra superior fija (.rail) y su margen. El hueco que
     reserva <body> se calcula a partir de aquí para que no haya que cuadrar
     dos números a mano cada vez que cambia el alto de la barra. */
  --rail-h: 72px;
  --rail-gap: 16px;

  /* Global Animations */
  --transition-bounce: 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
  --transition-smooth: 0.2s ease-out;
}

@keyframes slide-up-fade {
  from { opacity: 0; transform: translateY(20px) scale(0.98); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

*, *::before, *::after { box-sizing: border-box; }

body {
  font-family: 'Outfit', system-ui, -apple-system, sans-serif;
  background-color: var(--bg);
  color: var(--text);
  margin: 0;
  /* Hueco para la barra fija: su margen superior + su alto + aire por debajo. */
  padding: calc(var(--rail-gap) + var(--rail-h) + 16px) 0 32px 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  -webkit-font-smoothing: antialiased;
  
  /* Prominent structural grid */
  background-image: 
    linear-gradient(var(--border) 1px, transparent 1px),
    linear-gradient(90deg, var(--border) 1px, transparent 1px);
  background-size: 40px 40px;
  background-position: center top;
  background-attachment: fixed;
  overscroll-behavior: none;
}

main {
  /* Panel central: un rectángulo VISIBLE (borde + esquinas) centrado en la
     ventana, con la cuadrícula del fondo alrededor. Ocupa el 92% del ancho
     disponible con un tope para monitores muy anchos. */
  width: 92%;
  max-width: 1600px;
  margin: 0 auto;
  padding: 40px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  animation: slide-up-fade var(--transition-bounce) both;
}

/* Dentro de un servidor tampoco se pinta la cuadrícula del fondo: como el panel
   ocupa toda la pantalla, sólo asomaría en las franjas de arriba y abajo y se
   leería como un resto suelto, no como la textura que sí funciona en la portada.
   Se cuelga de main.wide para no tener que marcar cada página por separado. */
body:has(main.wide) { background-image: none; }

/* Dentro de un servidor (/cfg y /metrics) el panel ocupa TODA la pantalla: con
   la navegación lateral más los formularios no sobra ancho, y el marco centrado
   al 92% dejaba una franja de cuadrícula a los lados que aquí no aporta nada.
   La portada sí conserva el rectángulo centrado. */
main.wide {
  width: 100%;
  max-width: none;
  margin: 0;
  /* Sin marco: ocupando todo el ancho y con el mismo fondo que el <body>, el
     borde no delimitaba nada, sólo dejaba una raya suelta entre la barra
     superior y el nombre del servidor. La barra ya se separa sola (tiene su
     propio borde y su sombra). */
  border: none;
  border-radius: 0;
  /* Márgenes laterales PROPORCIONALES a la ventana en vez de los 40px fijos que
     heredaba de <main>. Con vw el aire crece en un monitor ancho y se encoge en
     uno estrecho, en vez de robar siempre lo mismo. Los topes del clamp evitan
     los dos extremos: pegado al borde en móvil, y una franja enorme al alejar
     el zoom. Arriba, menos aire que el panel de la portada (la barra fija ya
     reserva su hueco); abajo, cero: el hueco para la barra de guardado lo pone
     .cfg-main, y aquí solo sería espacio muerto. */
  padding: 16px clamp(20px, 2.5vw, 64px) 0;
}
/* Ese padding-bottom de 32px de <body> también sobra dentro de un servidor: el
   panel llega hasta abajo y el scroll vive dentro de sus columnas. */
body:has(main.wide) { padding-bottom: 16px; }

/* El contenido ocupa TODO el ancho que le deja el panel. Antes había un tope de
   1700px centrado, puesto porque al alejar el zoom el viewport CSS se ensancha y
   una hoja escrita en px fijos deja al contenido pegado a la izquierda con un
   vacío a la derecha. El tope tapaba el síntoma y regalaba dos franjas muertas a
   los lados en cualquier monitor de más de 1700px CSS (a zoom 100% en un 1080p ya
   se pierden 110px por lado). La solución de verdad es que las piezas crezcan:
   los gutters son vw (arriba), la columna de secciones es vw (más abajo) y las
   rejillas de ajustes son auto-fit, así que al ensanchar añaden columnas en vez
   de estirar una sola. Así se aprovecha la pantalla a cualquier zoom.

   width: 100% es obligatorio desde que main.wide es un contenedor flex en
   columna: los márgenes automáticos del eje transversal desactivan el estirado
   por defecto, y sin esto la cabecera y el layout de dos columnas se encogían al
   ancho de su contenido. */
main.wide > * {
  width: 100%;
  max-width: none;
}

/* ============================================================
   LA PAGINA DE CONFIGURACION NO HACE SCROLL: LO HACEN SUS PANELES
   La columna de secciones era 'sticky': subia con la pagina hasta
   toparse con la barra de arriba y solo entonces se quedaba quieta,
   asi que la caja entera se movia en cada rueda de raton. Aqui la
   ventana deja de desplazarse (la barra superior y el nombre del
   servidor quedan siempre fijos) y el scroll pasa a vivir DENTRO de
   cada panel: la lista de secciones se desplaza por dentro cuando no
   cabe, y los ajustes se desplazan por su lado. La caja lateral ya
   no se mueve nunca de su sitio.
   Se desactiva por debajo de 980px, donde la navegacion pasa a ser
   una tira horizontal y el scroll de pagina de siempre es lo correcto.
   ============================================================ */
@media (min-width: 981px) {
  body:has(main.wide) { height: 100vh; overflow: hidden; }
  main.wide { display: flex; flex-direction: column; height: 100%; min-height: 0; }
  /* El layout de dos columnas se come todo el alto que sobra. */
  main.wide > .cfg-layout { flex: 1; min-height: 0; }
}

/* Typography */
h1, h2, h3 { color: var(--text); font-weight: 600; margin: 0; letter-spacing: -0.03em; }
h1 { font-size: 3rem; }
h2 { font-size: 1.5rem; margin: 40px 0 24px; text-transform: uppercase; border-bottom: 2px solid var(--border); padding-bottom: 8px;}
h3 { font-size: 1rem; text-transform: uppercase; letter-spacing: 0.05em; }
p { color: var(--text-muted); line-height: 1.5; margin: 0 0 16px; font-weight: 400; }

/* Buttons */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 0 24px;
  height: 48px;
  border-radius: var(--radius-btn);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  border: 1px solid transparent;

  cursor: pointer;
  transition: transform var(--transition-smooth), background-color var(--transition-smooth), border-color var(--transition-smooth), color var(--transition-smooth), box-shadow var(--transition-smooth);
  text-transform: uppercase;
  letter-spacing: 0.1em;
}
.btn:active { transform: scale(0.96); }
.btn-primary { 
  background-color: var(--primary); 
  color: var(--on-primary); 
  border: 1px solid var(--primary);
}
.btn-primary:hover { 
  background-color: var(--bg); 
  color: var(--primary); 
}
.btn-secondary { background-color: var(--surface); color: var(--text); border-color: var(--border); }
.btn-secondary:hover { border-color: var(--primary); background-color: var(--primary-bg); }
.btn-ghost { color: var(--text-muted); background: transparent; border: 1px solid transparent; }
.btn-ghost:hover { color: var(--text); border-color: var(--border); background-color: var(--surface); }
.btn-danger { background-color: transparent; color: #ef4444; border-color: #ef4444; }
.btn-danger:hover { background-color: #ef4444; color: #fff; }
.btn:disabled { opacity: 0.5; cursor: default; transform: none; }

/* ============================================================
   FOCO DE TECLADO. Los inputs llevan outline:none y sólo cambiaban
   de borde, y los botones/pestañas no tenían nada: recorrer el
   panel con Tab era completamente invisible. :focus-visible sólo
   se activa con teclado, así que el ratón no ve ningún anillo.
   ============================================================ */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-btn);
}

/* Sidebar Rail */
.rail {
  position: fixed;
  left: var(--rail-gap); top: var(--rail-gap); right: var(--rail-gap);
  height: var(--rail-h);
  border-radius: 24px;
  background: var(--surface-solid);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid var(--border);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
  display: flex; flex-direction: row; align-items: center;
  padding: 0 24px;
  z-index: 50;
}
.rail-logo { display: flex; align-items: center; transition: transform var(--transition-bounce); }
.rail-logo:hover { transform: scale(1.05); }
.rail-logo:active { transform: scale(0.95); }
.rail-logo-img { width: 56px; height: 56px; object-fit: contain; }
.rail-sep { width: 1px; height: 32px; background: var(--border); margin: 0 20px; }
.rail-list { display: flex; flex-direction: row; gap: 16px; height: 100%; align-items: center; flex: 1; overflow-x: auto; overflow-y: hidden; }
.rail-item { width: 48px; height: 48px; border-radius: var(--radius-btn); display: flex; align-items: center; justify-content: center; text-decoration: none; position: relative; flex-shrink: 0; transition: transform var(--transition-bounce); }
.rail-icon { width: 48px; height: 48px; border-radius: var(--radius-btn); display: flex; align-items: center; justify-content: center; color: var(--text-muted); background: transparent; border: 1px solid transparent; overflow: hidden; transition: all var(--transition-smooth); pointer-events: none; }
.rail-icon.fallback { font-size: 16px; font-weight: 600; font-family: monospace; }
.rail-item:hover { transform: translateY(-2px); }
.rail-item:active { transform: scale(0.92); }
.rail-item:hover .rail-icon { border-color: var(--border); color: var(--text); background: var(--surface); box-shadow: 0 4px 12px rgba(0,0,0,0.2); }
.rail-item.active .rail-icon { border-color: var(--accent); color: var(--text); background: rgba(81, 140, 255, 0.1); box-shadow: inset 0 0 10px rgba(81, 140, 255, 0.2); }
.rail-icon img { width: 100%; height: 100%; object-fit: cover; }

/* Zona derecha del rail (menú de ajustes). Antes se maquetaba con un atributo
   style="" desde sidebar.js; vive aquí para que el layout sea editable en un
   solo sitio. */
.rail-bottom { display: flex; flex-direction: row; gap: 16px; margin-left: 24px; align-items: center; }
.rail-menu-wrap { position: relative; }
.rail-btn { border: none; background: transparent; cursor: pointer; padding: 0; }

@keyframes save-pop {
  from { opacity: 0; transform: translateY(20px) scale(0.95); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

/* Tooltip */
.rail-tip {
  position: absolute; top: 64px; left: 50%; transform: translateX(-50%);
  background: var(--text); color: var(--bg);
  border: 1px solid var(--text);
  padding: 6px 12px;
  font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.1em;
  white-space: nowrap;
  border-radius: var(--radius-btn);
  display: none;
  pointer-events: none;
  z-index: 100;
}
.rail-item:hover .rail-tip { display: block; }

/* Hero */
.hero { text-align: center; padding: 60px 40px; display: flex; flex-direction: column; align-items: center; background: var(--surface); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border: 1px solid var(--border); margin-bottom: 40px; border-radius: var(--radius); }
.hero-header { display: flex; align-items: center; justify-content: center; gap: 12px; margin-bottom: 24px; }
.hero-logo-img { width: 48px; height: 48px; }
.hero-sep { font-size: 3rem; color: var(--border-hover); font-weight: 300; user-select: none; margin-top: -6px; }
.hero-title { margin: 0; color: var(--text); font-size: 3rem; }
.hero-sub { max-width: 600px; font-size: 1rem; color: var(--text-muted); font-family: monospace; }
.hero-actions { display: flex; gap: 16px; margin-top: 32px; }

/* Secciones de la portada (home.js las pinta pero no tenían ninguna regla, así
   que dependían del margen por defecto del <h2>). */
.block { margin-bottom: 40px; }
.block:last-child { margin-bottom: 0; }
.block-title { margin-top: 0; }

/* Grid / Features */
.features { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 16px; }
.feature {
  background: var(--surface);
  border: 1px solid var(--border);
  padding: 32px;
  border-radius: var(--radius);
  display: flex; flex-direction: column;
  transition: transform var(--transition-smooth), border-color var(--transition-smooth), background var(--transition-smooth), box-shadow var(--transition-smooth);
}
.feature:hover { border-color: var(--text); background: var(--surface-solid); transform: translateY(-4px); box-shadow: 0 8px 24px rgba(0,0,0,0.2); }
.feature:active { transform: scale(0.98); }
.feature-ic {
  width: 40px; height: 40px;
  background: var(--bg); color: var(--text);
  border: 1px solid var(--border);
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--radius-btn);
  margin-bottom: 20px;
}
.feature:hover .feature-ic { border-color: var(--text); background: var(--text); color: var(--bg); }
.feature-ic span { font-size: 20px; }
.feature h3 { margin-bottom: 8px; font-size: 1rem; }
.feature p { margin: 0; font-size: 0.85rem; color: var(--text-muted); font-family: monospace; }

/* Guild Cards */
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 16px; }
.guild-card {
  display: flex; align-items: center; gap: 16px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 16px 20px;
  text-decoration: none;
  transition: transform var(--transition-smooth), border-color var(--transition-smooth), background var(--transition-smooth), box-shadow var(--transition-smooth);
}
.guild-card:hover { border-color: var(--text); background: var(--surface-solid); transform: translateY(-4px); box-shadow: 0 8px 24px rgba(0,0,0,0.2); }
.guild-card:active { transform: scale(0.98); }
.gicon-fallback {
  width: 48px; height: 48px;
  background: var(--bg); color: var(--text-muted);
  display: flex; align-items: center; justify-content: center;
  font-size: 16px; font-weight: 600; border: 1px solid var(--border);
  font-family: monospace;
  border-radius: var(--radius-btn);
  transition: all var(--transition-smooth);
}
.guild-card:hover .gicon-fallback { color: var(--bg); background: var(--text); border-color: var(--text); }
.gicon { width: 48px; height: 48px; border: 1px solid var(--border); object-fit: cover; filter: grayscale(100%); transition: all var(--transition-smooth); border-radius: var(--radius-btn); }
.guild-card:hover .gicon { filter: grayscale(0%); border-color: var(--text); }
.gc-text strong { display: block; color: var(--text); font-size: 1rem; margin-bottom: 4px; font-weight: 600; text-transform: uppercase; }
.gc-text .muted { font-size: 0.75rem; color: var(--text-muted); font-family: monospace; text-transform: uppercase; letter-spacing: 0.1em; margin: 0; }
.guild-card:hover .gc-text .muted { color: var(--text); }

/* Config Forms & Cards */
header { display: flex; align-items: center; gap: 24px; margin-bottom: 40px; border-bottom: 2px solid var(--border); padding-bottom: 24px; background: var(--bg); }
header .gicon { width: 56px; height: 56px; border: 1px solid var(--border); filter: grayscale(100%); }
header h1 { font-size: 1.5rem; }
header .htext { display: flex; flex-direction: column; gap: 4px; }
header .muted { font-family: monospace; font-size: 0.8rem; letter-spacing: 0.1em; }
header .logout { margin-left: auto; background: var(--bg); padding: 8px 16px; text-decoration: none; color: var(--text-muted); font-weight: 600; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.1em; border: 1px solid var(--border); border-radius: var(--radius-btn); }
header .logout:hover { color: var(--bg); background: var(--text); border-color: var(--text); }

.card {
  background: var(--surface);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  transition: transform var(--transition-smooth), border-color var(--transition-smooth), box-shadow var(--transition-smooth);
}
.card.plugin:hover { border-color: var(--accent); box-shadow: 0 8px 24px rgba(81, 140, 255, 0.08); transform: translateY(-2px); }
.plugin-head { padding: 20px 24px; display: flex; justify-content: space-between; align-items: center; background: rgba(9, 9, 11, 0.4); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); border-bottom: 1px solid var(--border); }
.plugin-title h2 { margin: 0 0 4px; font-size: 1.1rem; border: none; padding: 0; }
.plugin-title p { margin: 0; font-size: 0.85rem; color: var(--text-muted); font-family: monospace; }
/* Los ajustes se reparten en COLUMNAS en cuanto hay sitio, en lugar de estirar
   un único campo a lo ancho de la pantalla. Es lo que se rompía al quitar zoom:
   el viewport CSS se ensancha y el selector de rol llegaba a medir 3400px.
   'auto-fit' + minmax reparte solo, sin necesidad de un breakpoint por tamaño.
   El min(100%, …) evita que la columna mínima desborde en móviles estrechos. */
.plugin-body {
  padding: 24px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
  column-gap: 28px;
  align-items: start;
}
/* Lo que necesita la fila entera: encabezados de sección, la rejilla de logs,
   el editor de embeds, el editor de tipos de ticket, las listas de casillas, el
   selector con botón «Publicar panel» y los tres paneles de datos (histórico de
   tickets, métricas y respuestas de formularios), que en una sola columna salen
   estrujados y con las fechas partidas en tres líneas. */
.plugin-body > h3.section,
.plugin-body > .grid,
.plugin-body > .emb-root,
.plugin-body > p,
.plugin-body > .tt-field,
.plugin-body > .field:has(.multiselect-container),
.plugin-body > .emb-field,
.plugin-body > .tk-dash,
.plugin-body > .metrics-dash,
.plugin-body > .fr-list,
.plugin-body > .gw-new,
.plugin-body > .gw-list,
.plugin-body > .field:has(.panel-pub) { grid-column: 1 / -1; }

/* Ningún control crece más allá de lo legible por mucho ancho que sobre: una
   línea de texto de 3000px no se lee, y un desplegable tampoco se usa mejor. */
.cfg-main select,
.cfg-main .cfg-input,
.cfg-main .cfg-textarea,
.cfg-main .multiselect-container { max-width: 720px; }
.card.plugin.off .plugin-head { background: var(--surface); }
.card.plugin.off .plugin-body { display: none; }

/* La raya separadora de la cabecera sólo tiene sentido si debajo hay un cuerpo
   que separar. Cuando no lo hay —tarjetas que son sólo cabecera, como la del
   idioma, o cualquier plugin apagado, que oculta su cuerpo— quedaba pegada al
   borde inferior de la tarjeta: abajo se veían 3px de líneas (1 gris + 2 del
   borde) donde arriba sólo hay 2. */
.card.plugin.off .plugin-head,
.card.plugin:not(:has(.plugin-body)) .plugin-head {
  border-bottom: none;
}

h3.section { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.15em; color: var(--text-muted); margin: 0 0 20px; font-weight: 700; font-family: monospace; border-bottom: 1px dashed var(--border); padding-bottom: 8px; }

/* Inputs */
.field { margin-bottom: 24px; }
.lbl { display: block; font-weight: 600; margin-bottom: 8px; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--text-muted); font-family: monospace; }
input.num, select {
  width: 100%; height: 48px; padding: 0 16px;
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-btn);
  color: var(--text); font-family: monospace; font-size: 0.9rem;
  outline: none; appearance: none;
  transition: background var(--transition-smooth), border-color var(--transition-smooth), box-shadow var(--transition-smooth);
}
input.num { width: 140px; }
input.num:focus, select:focus { border-color: var(--text); background: var(--surface-solid); box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.1); }
select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24' width='24' fill='%23a1a1aa'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; padding-right: 40px;
}
select option { background: var(--surface-solid); color: var(--text); }

/* ============================================================
   Panel de configuración: navegación LATERAL + contenido.
   Antes eran 13 pestañas en una fila con flex-wrap: dos filas en
   escritorio y siete en móvil, así que había que bajar media
   pantalla antes de ver un solo ajuste. En columna caben las 13 a
   la vez y sobra sitio para el punto de estado de cada plugin.
   ============================================================ */
/* La columna de secciones y la separación crecen con la ventana en vez de
   quedarse en 260px/28px fijos: al alejar el zoom, lo que sobra va al formulario
   (que es quien sabe usarlo, con sus rejillas auto-fit) sin que la lista de
   secciones se quede ridícula al lado. Los topes del clamp mantienen legibles los
   nombres largos abajo y evitan una columna desproporcionada arriba. */
.cfg-layout {
  display: grid;
  grid-template-columns: clamp(230px, 15vw, 320px) minmax(0, 1fr);
  gap: clamp(20px, 1.6vw, 36px);
  align-items: start;
}
/* minmax(0,1fr) arriba + min-width:0 aquí: sin esto una tarjeta ancha (la rejilla
   de logs, el editor de embeds) estira la columna y desborda la rejilla. */
.cfg-main { min-width: 0; }
@media (min-width: 981px) {
  /* El formulario ocupa todo el alto y se desplaza por dentro. El hueco de
     abajo es para la barra flotante de guardado, que si no tapa el último
     ajuste de la sección. */
  .cfg-main { align-self: stretch; min-height: 0; overflow-y: auto; padding-bottom: 96px;
              overscroll-behavior: contain; }
}
/* Apilado simple para secciones con varias tarjetas (p.ej. General). */
.cfg-stack { display: flex; flex-direction: column; gap: 24px; }
/* Las pestañas Configuración/Métricas necesitan aire antes del panel. */
.page-tabs-cfg { margin-bottom: 32px; }

/* Fija en su sitio: las secciones largas (logs, tickets) medían varias
   pantallas y obligaban a subir del todo para cambiar de plugin. La caja no
   se mueve; si la lista no cabe, se desplaza por DENTRO (ver el app shell
   de main.wide, más arriba). */
.cfg-nav {
  display: flex; flex-direction: column; gap: 4px;
  padding: 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  /* 100% = el alto de la fila de la rejilla, que con el app shell es justo
     el hueco libre de la ventana. Sin él, una lista larga desbordaría. */
  max-height: 100%;
  overflow-y: auto;
  /* Fuera de la vista táctil: que la rueda dentro de la lista no arrastre
     también al panel de al lado al llegar a los topes. */
  overscroll-behavior: contain;
}
.cfg-nav-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 10px 12px;
  border: 1px solid transparent; border-radius: var(--radius-btn);
  background: transparent; color: var(--text-muted);
  font-family: monospace; font-size: 0.78rem; font-weight: 600;
  text-transform: uppercase; letter-spacing: 0.06em;
  text-align: left; cursor: pointer;
  transition: color var(--transition-smooth), background var(--transition-smooth), border-color var(--transition-smooth);
}
.cfg-nav-item:hover { color: var(--text); background: var(--bg); border-color: var(--border); }
.cfg-nav-item.active { color: var(--text); background: var(--primary-bg); border-color: var(--border-hover); }
.cfg-nav-label { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ============================================================
   NAVEGACIÓN: GRUPOS
   13 secciones sueltas no dicen a qué familia pertenece cada una,
   así que se reparten en grupos con su encabezado.
   ============================================================ */
.cfg-nav-list { display: flex; flex-direction: column; gap: 4px; }
.cfg-group { display: flex; flex-direction: column; gap: 4px; margin-top: 10px; }
.cfg-group-title {
  margin: 0; padding: 0 12px 2px;
  font-family: monospace; font-size: 0.62rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.14em; color: var(--border-hover);
}


/* Punto de estado: de un vistazo se ve qué plugins están encendidos sin tener
   que entrar plugin por plugin. La sección General no lleva (no se apaga). */
.cfg-dot { flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--border-hover);
  transition: background var(--transition-smooth), box-shadow var(--transition-smooth); }
.cfg-dot.on { background: var(--accent); box-shadow: 0 0 6px var(--accent); }

/* Cabecera de la sección visible: su nombre + «valores por defecto». El botón
   vive aquí, y no en una barra global, porque restaura SOLO esta sección. */
.cfg-section-head { display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 20px; padding-bottom: 16px; border-bottom: 1px solid var(--border); }
/* Sin el subrayado del <h2> genérico: al estar dentro de un flex, ese
   border-bottom se encogía al ancho del texto y quedaba una rayita suelta
   debajo del nombre de la sección. */
.cfg-section-title { font-size: 1.15rem; margin: 0; border-bottom: none; padding-bottom: 0; }
.cfg-reset { height: 38px; padding: 0 14px; font-size: 0.72rem; }

/* Barra de guardado: pegada abajo mientras haya cambios sin guardar. Antes la
   acción principal de la página era un icono de 48px en la barra superior,
   pegado al botón rojo de restaurar. */
.cfg-savebar {
  position: sticky; bottom: 16px; z-index: 40;
  display: none; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap;
  margin-top: 28px; padding: 14px 20px;
  background: var(--surface-solid);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  border: 1px solid var(--border-hover); border-radius: var(--radius);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.45);
}
.cfg-savebar.show { display: flex; animation: save-pop 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); }
.cfg-savebar-text { font-size: 0.85rem; font-family: monospace; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--text); }
.cfg-savebar-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.cfg-savebar-actions .btn { height: 42px; }
/* Hueco del icono del botón (disquete -> spinner -> tick al guardar). */
.cfg-btn-ic { display: inline-flex; align-items: center; }
.cfg-btn-ic svg { width: 18px; height: 18px; }

/* Diálogo de confirmación (restaurar valores por defecto) */
.modal-back {
  position: fixed; inset: 0; z-index: 2000;
  display: flex; align-items: center; justify-content: center; padding: 24px;
  background: rgba(0, 0, 0, 0.6); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
  animation: modal-fade 0.15s ease-out;
}
.modal-card {
  width: 100%; max-width: 460px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  padding: 24px; box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5);
  animation: save-pop 0.25s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.modal-title { margin: 0 0 10px; font-size: 1.05rem; color: var(--text); }
.modal-text { margin: 0 0 20px; font-size: 0.9rem; line-height: 1.5; }
.modal-actions { display: flex; justify-content: flex-end; gap: 10px; flex-wrap: wrap; }
.modal-actions .btn { height: 38px; padding: 0 16px; font-size: 0.85rem; }
@keyframes modal-fade { from { opacity: 0; } to { opacity: 1; } }

/* Aviso de borrador sin guardar */
.draft-banner { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 24px; padding: 14px 20px; background: var(--primary-bg); border: 1px solid var(--primary); border-radius: var(--radius); }
.draft-text { font-size: 0.9rem; color: var(--text); }
.draft-actions { display: flex; gap: 10px; }
.draft-actions .btn { height: 38px; padding: 0 16px; font-size: 0.85rem; }

/* Idioma del bot (selector segmentado ES/EN) */
.lang-seg { display: inline-flex; border: 1px solid var(--border); border-radius: var(--radius-btn); overflow: hidden; background: var(--bg); }
.lang-opt { padding: 0 18px; height: 40px; border: none; background: transparent; color: var(--text-muted); font-family: monospace; font-size: 0.85rem; cursor: pointer; transition: background .15s, color .15s; }
.lang-opt + .lang-opt { border-left: 1px solid var(--border); }
.lang-opt:hover { color: var(--text); }
.lang-opt.active { background: var(--primary); color: var(--on-primary); }

/* Editor de tipos de ticket */
.tt-help { font-size: 0.8rem; margin: -4px 0 12px; }
/* Selector de canal + botón «Publicar panel» (pestaña Tickets). */
.panel-pub { display: flex; gap: 10px; align-items: center; }
.panel-pub select { flex: 1; }
.panel-pub .panel-pub-btn { flex: none; white-space: nowrap; height: 48px; }
.panel-pub + .tt-help { margin: 8px 0 0; }
.tt-rows { display: flex; flex-direction: column; gap: 10px; margin-bottom: 12px; }
.tt-head, .tt-row { display: grid; grid-template-columns: 70px 1fr 1.2fr 1.2fr 40px; gap: 10px; align-items: center; }
.tt-head { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted); font-family: monospace; padding: 0 12px; }
.tt-row input, .tt-row select { width: 100%; height: 44px; padding: 0 12px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-btn); color: var(--text); font-family: monospace; font-size: 0.9rem; outline: none; appearance: none; }
.tt-row select { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='24' width='24' fill='%23a1a1aa'%3E%3Cpath d='M7 10l5 5 5-5z'/%3E%3C/svg%3E"); background-repeat: no-repeat; background-position: right 10px center; padding-right: 34px; }
.tt-row input:focus, .tt-row select:focus { border-color: var(--text); background: var(--surface-solid); }
.tt-emoji { text-align: center; }
.tt-del { height: 44px; border: 1px solid var(--border); background: var(--bg); color: var(--text-muted); border-radius: var(--radius-btn); cursor: pointer; font-size: 0.9rem; transition: color .15s, border-color .15s; }
.tt-del:hover { color: #ef4444; border-color: #ef4444; }
/* Editor de auto-roles: mismas cajas que los tipos de ticket, pero con sus
   cuatro columnas propias (emoji, rol, texto del botón y descripción). */
.sr-head, .sr-row { grid-template-columns: 70px 1.2fr 1fr 1.4fr 40px; }
.tt-empty { font-size: 0.85rem; padding: 8px 0; }
.tt-add { height: 40px; padding: 0 16px; font-size: 0.85rem; }

/* Campos de texto libre personalizables (mensajes/embeds de tickets). */
.cfg-input, .cfg-textarea {
  width: 100%; padding: 12px 16px;
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-btn);
  color: var(--text); font-family: monospace; font-size: 0.9rem; outline: none;
  transition: background var(--transition-smooth), border-color var(--transition-smooth);
}
.cfg-input { height: 48px; }
.cfg-textarea { resize: vertical; min-height: 64px; line-height: 1.5; }
.cfg-input:focus, .cfg-textarea:focus { border-color: var(--text); background: var(--surface-solid); }

/* Cada tipo de ticket es una tarjeta: la fila de campos + sus textos opcionales. */
.tt-item { border: 1px solid var(--border); border-radius: var(--radius-btn); padding: 12px; background: var(--surface); }
.tt-extra { display: flex; flex-direction: column; gap: 6px; margin-top: 10px; }
.tt-sub { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted); font-family: monospace; }
.tt-text { width: 100%; padding: 8px 12px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-btn); color: var(--text); font-family: monospace; font-size: 0.85rem; outline: none; resize: vertical; line-height: 1.5; }
.tt-text:focus { border-color: var(--text); background: var(--surface-solid); }

/* ====== Preview de embeds (pestaña Embeds), imitando el render de Discord ====== */
.demb-list { display: flex; flex-direction: column; gap: 20px; margin-top: 12px; }
.demb-item { display: flex; flex-direction: column; gap: 6px; }
.demb-name { font-family: monospace; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted); }
.demb {
  position: relative; max-width: 520px;
  background: #2b2d31; border-radius: 4px; border-left: 4px solid #4f545c;
  padding: 12px 16px; color: #dbdee1; font-size: 0.875rem; line-height: 1.4;
}
.demb-author { display: flex; align-items: center; gap: 8px; font-weight: 600; font-size: 0.82rem; color: #f2f3f5; margin-bottom: 8px; }
.demb-author-icon { width: 24px; height: 24px; border-radius: 50%; }
.demb-title { font-weight: 700; color: #f2f3f5; margin-bottom: 8px; }
.demb-desc { white-space: pre-wrap; word-wrap: break-word; margin-bottom: 8px; }
.demb-fields { display: grid; grid-template-columns: 1fr; gap: 8px; margin-bottom: 8px; }
.demb-field-name { font-weight: 700; color: #f2f3f5; font-size: 0.82rem; margin-bottom: 2px; }
.demb-field-val { white-space: pre-wrap; word-wrap: break-word; }
/* Si hay campos inline, la rejilla pasa a 2 columnas; los no-inline ocupan toda la fila. */
.demb-fields:has(.inline) { grid-template-columns: repeat(2, 1fr); }
.demb-fields:has(.inline) .demb-field:not(.inline) { grid-column: 1 / -1; }
.demb-thumb { float: right; max-width: 80px; max-height: 80px; border-radius: 4px; margin: 0 0 8px 16px; }
.demb-image { display: block; max-width: 100%; border-radius: 4px; margin-top: 8px; }
.demb-footer { display: flex; align-items: center; gap: 8px; font-size: 0.75rem; color: #b5bac1; margin-top: 8px; clear: both; }
.demb-footer-icon { width: 20px; height: 20px; border-radius: 50%; }

/* ---- Markdown del preview (lo genera web/static/markdown.js) ----
   Colores y tamaños calcados de Discord, para que el preview no prometa algo
   distinto de lo que se verá en el servidor. Solo aplica dentro de la
   descripción y del valor de los campos, que es donde Discord lo renderiza. */
.demb-desc > :first-child, .demb-field-val > :first-child { margin-top: 0; }
.demb-desc > :last-child, .demb-field-val > :last-child { margin-bottom: 0; }
.md-p { white-space: pre-wrap; word-wrap: break-word; }
/* Estos son h1/h2/h3 de verdad, así que hay que desactivar el estilo de
   encabezado del PANEL (mayúsculas, raya inferior…): aquí mandan los de
   Discord, no los del panel. */
.md-h1, .md-h2, .md-h3 { color: #f2f3f5; font-weight: 700; line-height: 1.25; margin: 12px 0 6px;
  border: none; padding: 0; text-transform: none; letter-spacing: normal; }
.md-h1 { font-size: 1.5em; }
.md-h2 { font-size: 1.25em; }
.md-h3 { font-size: 1.1em; }
.md-subtext { font-size: 0.8em; color: #949ba4; margin: 2px 0; }
.md-b { font-weight: 700; }
.md-i { font-style: italic; }
.md-u { text-decoration: underline; }
.md-s { text-decoration: line-through; }
.md-code { background: #1e1f22; border-radius: 3px; padding: 1px 4px; font-family: monospace; font-size: 0.86em; }
.md-pre { background: #1e1f22; border: 1px solid #1e1f22; border-radius: 4px; padding: 8px 10px;
  margin: 6px 0; font-family: monospace; font-size: 0.86em; white-space: pre-wrap; word-wrap: break-word; }
.md-quote { border-left: 4px solid #4e5058; border-radius: 2px; padding-left: 12px; margin: 4px 0; white-space: pre-wrap; }
.md-list { padding-left: 22px; margin: 4px 0; }
.md-list li { margin: 2px 0; }
.md-link { color: #00a8fc; text-decoration: none; }
.md-link:hover { text-decoration: underline; }
.md-mention { color: #c9cdfb; background: rgba(88, 101, 242, 0.18); border-radius: 3px; padding: 0 2px; font-weight: 500; }
.md-time { background: rgba(255, 255, 255, 0.06); border-radius: 3px; padding: 0 2px; }
.md-emoji { width: 1.375em; height: 1.375em; vertical-align: -0.3em; object-fit: contain; }
/* Spoiler: tapado hasta que se pulsa (igual que en Discord). */
.md-spoiler { background: #17181a; color: transparent; border-radius: 3px; cursor: pointer; }
.md-spoiler * { visibility: hidden; }
.md-spoiler.revealed { background: rgba(255, 255, 255, 0.06); color: inherit; cursor: auto; }
.md-spoiler.revealed * { visibility: visible; }

/* ====== Autocompletado de menciones (@ y #) en los campos de texto ======
   El desplegable cuelga de <body> con posición absoluta: así no lo recorta el
   overflow de la tarjeta del plugin. Lo coloca web/static/mentions.js. */
.mention-box {
  position: absolute; z-index: 60; max-height: 264px; overflow-y: auto;
  background: var(--surface-solid); border: 1px solid var(--border);
  border-radius: var(--radius-btn); box-shadow: 0 12px 32px rgba(0, 0, 0, 0.38);
}
.mention-item { display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 12px; cursor: pointer; }
.mention-item.sel, .mention-item:hover { background: var(--surface); }
.mention-name { font-family: monospace; font-size: 0.85rem; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mention-kind { flex-shrink: 0; font-size: 0.66rem; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--text-muted); }

/* ====== Pestaña Embeds: lista + editor ====== */
.emb-bar { display: flex; gap: 10px; align-items: center; margin: 12px 0 20px; }
.emb-empty { padding: 24px 0; font-size: 0.95rem; }

/* Lista: una tarjeta por embed (nombre + preview), clicable para editar. */
.emb-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 16px; }
.emb-card { display: flex; flex-direction: column; gap: 8px; align-items: stretch; text-align: left;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-btn);
  padding: 14px; cursor: pointer; transition: border-color var(--transition-smooth), transform var(--transition-smooth); }
.emb-card:hover { border-color: var(--primary); transform: translateY(-2px); }
.emb-card-name { font-family: monospace; font-weight: 700; font-size: 0.9rem; color: var(--text); }
.emb-card .demb { max-width: none; pointer-events: none; }
.emb-card-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }

/* Ámbito de un embed: global del servidor o personal. En la lista es solo el
   icono; en el editor, la etiqueta entera (de ahí que el padding se ajuste). */
.emb-scope {
  flex: none; font-size: 0.72rem; font-family: monospace; letter-spacing: 0.06em;
  padding: 4px 8px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--bg); color: var(--text-muted);
}
.emb-scope-global { color: var(--accent); border-color: var(--accent); }
/* Bloques de la lista (globales / míos). */
.emb-group + .emb-group { margin-top: 32px; }
.emb-group-title { margin-bottom: 4px; }
.emb-group .tt-help { margin-bottom: 14px; }
.emb-new-scope { width: auto; min-width: 210px; height: 44px; }

/* Editor: formulario | preview, y acciones abajo. */
.emb-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; align-items: start; }
.emb-form { display: flex; flex-direction: column; }
.emb-form .field { margin-bottom: 16px; }
.emb-side { position: sticky; top: 16px; display: flex; flex-direction: column; gap: 16px; }
.emb-preview { min-height: 60px; }
.emb-actions { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; margin-top: 24px; padding-top: 20px; border-top: 1px solid var(--border); }
.emb-send { display: flex; gap: 10px; align-items: center; margin-left: auto; }
.emb-send select { min-width: 160px; }
.emb-color { display: flex; gap: 12px; align-items: center; }
.emb-color-picker { flex: none; width: 52px; height: 40px; padding: 2px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-btn); cursor: pointer; }
.emb-hex { flex: none; width: 130px; height: 40px; text-transform: uppercase; }
.emb-color-clear { flex: none; width: 32px; height: 32px; border: 1px solid var(--border); background: var(--bg); color: var(--text-muted); border-radius: var(--radius-btn); cursor: pointer; transition: color .15s, border-color .15s; }
.emb-color-clear:hover { color: #ef4444; border-color: #ef4444; }
/* Importar un embed ya guardado: desplegable + botón, arriba del formulario. */
.emb-import { display: flex; gap: 10px; align-items: center; margin-bottom: 18px;
  padding-bottom: 16px; border-bottom: 1px dashed var(--border); }
.emb-import-sel { flex: 1; min-width: 0; height: 40px; }
.emb-import-btn { flex: none; }
/* El editor incrustado como ajuste de un plugin (embed del panel de auto-roles):
   ocupa la fila entera de .plugin-body, como el resto de editores grandes. */
.emb-field .emb-cols { margin-top: 4px; }
.emb-frows { display: flex; flex-direction: column; gap: 10px; margin-bottom: 12px; }
.emb-frow { display: grid; grid-template-columns: 1fr 1.4fr auto 40px; gap: 10px; align-items: start; }
.emb-inline { display: flex; align-items: center; gap: 8px; font-size: 0.78rem; color: var(--text-muted); padding-top: 12px; cursor: pointer; }

@media (max-width: 860px) {
  .emb-cols { grid-template-columns: 1fr; }
  .emb-side { position: static; }
  .emb-frow { grid-template-columns: 1fr 40px; }
  .emb-send { margin-left: 0; width: 100%; }
}

/* Toggle Switch (Industrial Style) */
.switch-row { display: flex; align-items: center; gap: 16px; padding: 10px 0; cursor: pointer; }
.switch-row span { font-size: 0.85rem; font-family: monospace; text-transform: uppercase; letter-spacing: 0.05em; }

/* Settings Menu */
.settings-menu {
  position: absolute;
  top: 100%; right: 0; margin-top: 16px;
  background: var(--surface-solid);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid var(--border);
  border-radius: var(--radius-btn);
  padding: 8px;
  display: flex; flex-direction: column; gap: 4px;
  min-width: 200px;
  box-shadow: 0 4px 16px rgba(0,0,0,0.5);
  z-index: 2000;
}
.settings-menu.hidden { display: none; }
.settings-menu .menu-item {
  padding: 10px 16px;
  text-decoration: none;
  color: var(--text);
  font-size: 0.85rem;
  border-radius: 8px;
  cursor: pointer;
  transition: background 0.2s;
  display: flex; align-items: center; gap: 8px;
  white-space: nowrap;
}
.settings-menu .menu-item:hover { background: var(--surface); }
.settings-menu .menu-item.text-err { color: #ef4444; }
.settings-menu .menu-item.text-err:hover { background: rgba(239, 68, 68, 0.1); }

.switch { display: inline-flex; }
input.toggle {
  appearance: none; -webkit-appearance: none;
  width: 48px; height: 24px;
  background: var(--bg); border: 1px solid var(--border); position: relative; cursor: pointer;
  flex-shrink: 0; outline: none; border-radius: 12px;
}
input.toggle::after {
  content: ""; position: absolute; top: 3px; left: 3px;
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--text-muted);
}
input.toggle:checked { background: var(--bg); border-color: var(--accent); }
input.toggle:checked::after { transform: translateX(24px); background: var(--accent); box-shadow: 0 0 8px var(--accent); }

/* Logs Category */
.subcard { background: var(--bg); border: 1px solid var(--border); padding: 24px; margin-bottom: 16px; border-radius: calc(var(--radius) - 4px); }
.subcard h4 { margin: 0 0 16px; font-size: 0.9rem; display: flex; align-items: center; gap: 8px; text-transform: uppercase; font-family: monospace; }

/* Animations */
@keyframes spin { 100% { transform: rotate(360deg); } }
.icon-spin { animation: spin 0.8s linear infinite; transform-origin: center; }

/* Toast */
#toast {
  position: fixed; bottom: 32px; right: 32px; left: auto;
  background: var(--text); color: var(--bg);
  border: 1px solid var(--text);
  border-radius: var(--radius-btn);
  padding: 16px 24px;
  font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.1em; font-family: monospace;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4);
  z-index: 1000;
  
  /* Animated Entry/Exit */
  visibility: hidden;
  transform: translateY(40px) scale(0.95);
  opacity: 0;
  transition: visibility 0.4s, opacity 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275), transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
#toast.show { 
  visibility: visible;
  transform: translateY(0) scale(1);
  opacity: 1;
}
#toast.err { background: #ef4444; color: #fff; border-color: #dc2626; }

.loading { text-align: center; color: var(--text-muted); padding: 80px; font-size: 0.85rem; text-transform: uppercase; letter-spacing: 0.2em; font-family: monospace; opacity: 0; animation: delayed-show 0.2s 0.15s forwards; }
.loading::after { content: '...'; }
@keyframes delayed-show { to { opacity: 1; } }

.err { background: var(--bg); color: #ef4444; padding: 16px; margin-bottom: 24px; border: 1px solid #ef4444; border-radius: var(--radius-btn); font-size: 0.85rem; font-family: monospace; text-transform: uppercase; }
.ok { background: var(--bg); color: var(--text); padding: 16px; margin-bottom: 24px; border: 1px solid var(--text); border-radius: var(--radius-btn); font-size: 0.85rem; font-family: monospace; text-transform: uppercase; }
.empty { text-align: center; padding: 80px 20px; border: 1px dashed var(--border); border-radius: var(--radius); color: var(--text-muted); font-family: monospace; text-transform: uppercase; font-size: 0.85rem; letter-spacing: 0.1em; }

/* ============================================================
   Dashboard de métricas (sección «📊 Métricas» del panel)
   ============================================================ */
.metrics-bar { display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 32px; }
.page-tabs { display: flex; gap: 8px; }
.page-tabs .tab {
  padding: 8px 16px; text-decoration: none; color: var(--text-muted);
  font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.1em;
  border: 1px solid var(--border); border-radius: var(--radius-btn); font-family: monospace;
}
.page-tabs .tab:hover { color: var(--text); border-color: var(--border-hover); }
.page-tabs .tab.active { color: var(--bg); background: var(--text); border-color: var(--text); }

.range-sel { display: flex; gap: 4px; flex-wrap: wrap; align-items: center; }
.range-btn {
  padding: 8px 14px; text-decoration: none; color: var(--text-muted);
  font-size: 0.7rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.1em;
  border: 1px solid var(--border); border-radius: var(--radius-btn); font-family: monospace; background: transparent; cursor: pointer;
}
.range-btn:hover { color: var(--text); border-color: var(--border-hover); }
.range-btn.active { color: var(--accent); border-color: var(--accent); background: rgba(81, 140, 255, 0.1); }
/* Campo de días personalizados (máx = retención del servidor). Separado de los
   presets con un margen + línea divisoria para que se lea como control aparte. */
.range-custom-wrap {
  display: flex; gap: 4px; align-items: center;
  margin-left: 16px; padding-left: 16px; border-left: 1px solid var(--border);
}
.range-custom {
  width: 68px; padding: 8px 10px; background: var(--bg); border: 1px solid var(--border);
  border-radius: var(--radius-btn);
  color: var(--text); font-family: monospace; font-size: 0.72rem; outline: none;
}
.range-custom:focus { border-color: var(--accent); }
/* El botón «Ir» del rango personalizado destaca en color de acento. */
.range-btn.range-go { color: var(--accent); border-color: var(--accent); }
.range-btn.range-go:hover { background: rgba(81, 140, 255, 0.1); }

/* KPIs */
.kpis { display: grid; grid-template-columns: repeat(auto-fill, minmax(180px, 1fr)); gap: 16px; margin-bottom: 24px; }
.kpi { background: var(--surface); border: 1px solid var(--border); padding: 20px; border-radius: var(--radius); transition: transform var(--transition-smooth), border-color var(--transition-smooth), box-shadow var(--transition-smooth); }
.kpi:hover { border-color: var(--border-hover); transform: translateY(-4px); box-shadow: 0 8px 24px rgba(0,0,0,0.2); }
.kpi-val { font-size: 2rem; font-weight: 700; letter-spacing: -0.03em; color: var(--text); line-height: 1.1; }
.kpi-lbl { margin-top: 8px; font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.1em; color: var(--text-muted); font-family: monospace; }
.kpi-sub { margin-top: 4px; font-size: 0.7rem; color: var(--text-muted); font-family: monospace; }

/* Tarjetas de gráfica. En rejilla de dos columnas: en una sola había que bajar
   media pantalla por gráfica para ver la siguiente. */
.metric-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; }
.metric-card { padding: 24px; min-width: 0; }
.metric-card .section { margin-bottom: 16px; }
@media (max-width: 1100px) { .metric-grid { grid-template-columns: 1fr; } }
/* ============================================================
   Constructor de formularios y sus respuestas
   ============================================================ */
.ff-form { border-left: 3px solid var(--accent); }
.ff-head { display: flex; gap: 10px; align-items: center; margin-bottom: 10px; }
.ff-head .tt-text { flex: 1; min-width: 0; }
.ff-head .tt-emoji { flex: none; width: 60px; text-align: center; }
.ff-fields-title { margin: 16px 0 8px; font-size: 0.72rem; text-transform: uppercase;
  letter-spacing: 0.1em; color: var(--text-muted); font-family: monospace; }
.ff-fields { display: flex; flex-direction: column; gap: 10px; margin-bottom: 12px; }
.ff-item { background: var(--bg); }
.tt-sub-box { margin-top: 10px; }
.tt-range { display: flex; gap: 10px; }
.tt-range .num { width: 100px; }

/* ============================================================
   Constructor de comandos personalizados
   ============================================================ */
.cc-item { border-left: 3px solid var(--accent); }
/* La barra del comando, pegada al nombre: se lee '/reglas' de un vistazo, que
   es como se va a escribir en Discord. */
.cc-slash { font-family: monospace; font-size: 1rem; color: var(--text-muted); }
.cc-item .ff-head .cc-name { flex: 1; font-family: monospace; }
.cc-item .emb-cols, .cc-item .perm-control { margin-top: 8px; }

/* Respuestas recibidas */
/* ---- Sorteos (sección «🎉 Sorteos»): el formulario de uno nuevo y la lista
   de los que hay. Cada sorteo es una tarjeta con sus datos en una línea y sus
   acciones debajo; los ya terminados se apagan para distinguirlos de un vistazo. */
.gw-new { padding: 16px; margin-top: 8px; }
.gw-new > h3.section { margin-top: 0; }
.gw-form { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 14px 28px; align-items: start; }
.gw-form .cfg-input, .gw-form select, .gw-form .num { width: 100%; }
.gw-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 12px; }
.gw-list { display: flex; flex-direction: column; gap: 12px; margin-top: 8px; }
.gw-card { border: 1px solid var(--border); border-radius: var(--radius); padding: 14px; }
.gw-card.off { opacity: 0.72; }
.gw-head { display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap;
  padding-bottom: 8px; border-bottom: 1px solid var(--border); }
.gw-prize { font-weight: 700; }
.gw-link { margin-left: auto; font-size: 0.78rem; color: var(--accent); }
.gw-meta { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 10px;
  font-size: 0.8rem; color: var(--text-muted); }
.gw-winners { margin-top: 8px; font-size: 0.82rem; }
.gw-card .gw-actions { margin-top: 12px; }

.fr-list { display: flex; flex-direction: column; gap: 12px; margin-top: 8px; }
.fr-card { border: 1px solid var(--border); border-radius: var(--radius); padding: 14px; }
.fr-head { display: flex; gap: 12px; align-items: baseline; flex-wrap: wrap;
  margin-bottom: 10px; padding-bottom: 8px; border-bottom: 1px solid var(--border); }
.fr-form { font-weight: 700; }
.fr-user { color: var(--text-muted); font-size: 0.8rem; }
/* Respuesta rectificada por su autor (una sola corrección por respuesta). */
.fr-edited { margin-left: auto; font-family: monospace; font-size: 0.68rem;
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--accent);
  border: 1px solid var(--accent); border-radius: 999px; padding: 2px 8px; }
.fr-answers { display: flex; flex-direction: column; gap: 8px; }
.fr-a { display: grid; grid-template-columns: minmax(120px, 30%) 1fr; gap: 12px;
  font-size: 0.82rem; }
.fr-q { color: var(--text-muted); font-family: monospace; font-size: 0.72rem;
  text-transform: uppercase; letter-spacing: 0.06em; }
.fr-v { white-space: pre-wrap; word-break: break-word; }
@media (max-width: 700px) { .fr-a { grid-template-columns: 1fr; gap: 2px; } }

/* ============================================================
   Histórico de tickets (sección «🎫 Tickets» del panel)
   ============================================================ */
.tk-dash { margin-top: 8px; }
.tk-bar { display: flex; align-items: center; justify-content: space-between;
  gap: 16px; flex-wrap: wrap; margin-bottom: 16px; }

/* Fila de controles de la tarjeta «Copiar configuración». Se envuelve en móvil
   en vez de desbordar. */
.io-row { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.io-row + .io-row, .sec-pick + .io-row { margin-top: 12px; }

/* ============================================================
   COPIAR CONFIGURACIÓN (pestaña General)
   Dos bloques: traer de otro servidor mío y las copias guardadas.
   ============================================================ */
.copy-block + .copy-block { margin-top: 32px; }
.copy-src { width: auto; min-width: 240px; max-width: 100%; height: 40px; }
.preset-input {
  height: 40px; padding: 0 14px; min-width: 240px; flex: 1 1 240px;
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-btn);
  color: var(--text); font-family: monospace; font-size: 0.9rem; outline: none;
}
.preset-input:focus { border-color: var(--text); background: var(--surface-solid); }

/* Selector de secciones. En rejilla y no en lista: son trece, y en una columna
   había que bajar media pantalla para llegar al botón de confirmar. */
.sec-pick { margin: 12px 0; }
.sec-bar { display: flex; gap: 8px; align-items: center; margin-bottom: 10px; }
.sec-bar .muted { font-family: monospace; font-size: 0.7rem;
  text-transform: uppercase; letter-spacing: 0.1em; }
.sec-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 6px 16px; }
.sec-item { display: flex; align-items: center; gap: 8px; font-size: 0.85rem;
  cursor: pointer; padding: 4px 0; }
.sec-item input { accent-color: var(--accent); width: 16px; height: 16px; cursor: pointer; }

/* Copias guardadas: una fila por copia, con su detalle desplegable debajo
   (mismo patrón que la conversación de un ticket). */
.preset-list { display: flex; flex-direction: column;
  border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden;
  margin-bottom: 16px; }
.preset-entry + .preset-entry .preset-row { border-top: 1px solid var(--border); }
.preset-row { display: flex; align-items: center; gap: 12px; padding: 10px 14px;
  flex-wrap: wrap; }
.preset-row:hover { background: var(--surface); }
.preset-name { font-weight: 600; font-size: 0.9rem; }
.preset-meta { font-family: monospace; font-size: 0.72rem; flex: 1 1 auto; }
.preset-row .btn { height: 36px; padding: 0 16px; font-size: 11px; }
.preset-panel { padding: 4px 14px 16px; }

/* ============================================================
   ACCESO DE EQUIPO (ver src/core/superuser.py)
   Todo lo que sea de otra gente va marcado en ámbar. No es
   decoración: es la diferencia entre tocar lo tuyo y tocar lo de
   otro, y tiene que verse sin leer nada.
   ============================================================ */
.team-banner {
  display: flex; gap: 12px; align-items: flex-start; flex-wrap: wrap;
  border: 1px solid #f59e0b; border-left-width: 3px;
  background: rgba(245, 158, 11, 0.08);
  border-radius: var(--radius); padding: 12px 16px; margin-bottom: 24px;
}
.team-banner p { margin: 0; font-size: 0.8rem; line-height: 1.5; }
.team-tag {
  font-family: monospace; font-size: 0.62rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.12em; color: #f59e0b;
  border: 1px solid #f59e0b; border-radius: var(--radius-btn);
  padding: 3px 8px; white-space: nowrap;
}
.team-sub { color: #f59e0b; border-bottom-color: rgba(245, 158, 11, 0.4); margin-top: 28px; }
.team-ack { color: #f59e0b; margin: 4px 0 12px; }
.preset-entry.foreign .preset-row { border-left: 3px solid #f59e0b; }
/* Las descargas de métricas van con el aspecto de los botones de rango, que es
   con quien comparten barra; como son <a>, necesitan alinearse como caja. */
.range-btn.dl-btn { display: inline-flex; align-items: center; }
.tk-table { display: flex; flex-direction: column;
  border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
/* Una rejilla, no una <table>: así las filas se pueden estrechar en móvil sin
   scroll horizontal y cada columna manda en su ancho. */
.tk-row { display: grid; grid-template-columns: 64px minmax(0, 1.4fr) minmax(0, 1.4fr) 170px 170px 80px 90px;
  gap: 12px; align-items: center; padding: 10px 14px; font-size: 0.8rem;
  border-top: 1px solid var(--border); }
.tk-entry:first-child .tk-row { border-top: none; }
.tk-row:first-child { border-top: none; }
.tk-row:hover:not(.tk-head) { background: var(--surface); }
.tk-head { background: var(--surface); font-family: monospace; font-size: 0.68rem;
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted); }
.tk-id { font-family: monospace; color: var(--text-muted); }
.tk-user, .tk-claim { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tk-claim { color: var(--text-muted); }
/* La fecha no se parte: en una columna estrecha salía en tres líneas y la fila
   crecía al triple de alto. */
.tk-date { font-family: monospace; font-size: 0.72rem; color: var(--text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tk-dur { font-family: monospace; text-align: right; }
.tk-open-btn { justify-self: end; padding: 4px 10px; font-size: 0.66rem; }
/* Un ticket todavía abierto se marca con una barra al principio de la fila. */
.tk-row.open { box-shadow: inset 3px 0 0 var(--accent); }
/* Conversación desplegada bajo su fila. */
.tk-convo { padding: 16px 18px; background: var(--bg); border-top: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 14px; max-height: 560px; overflow-y: auto; }
.tkm { display: flex; flex-direction: column; gap: 4px; }
.tkm-head { display: flex; gap: 10px; align-items: baseline; }
.tkm-author { font-weight: 700; font-size: 0.8rem; }
.tkm-body { font-size: 0.85rem; line-height: 1.5; word-break: break-word;
  display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
/* Imágenes y vídeos se ven, pero acotados: una captura de 4000px no puede
   reventar la tabla ni obligar a bajar media pantalla por mensaje. */
.tkm-media { max-width: min(420px, 100%); max-height: 320px; border-radius: var(--radius);
  border: 1px solid var(--border); object-fit: contain; background: #000; }
/* El audio (mensajes de voz de Discord incluidos) no lleva marco ni fondo negro:
   son los controles nativos del navegador, y 'color-scheme: dark' es lo que hace
   que los pinte oscuros en vez de en su gris claro de siempre, que en este panel
   canta muchísimo. */
.tkm-audio { width: min(340px, 100%); height: 40px; color-scheme: dark; }
.tkm-file { font-family: monospace; font-size: 0.72rem; color: var(--text-muted);
  border: 1px solid var(--border); border-radius: var(--radius-btn); padding: 3px 8px; }

.tk-pager { display: flex; gap: 12px; align-items: center; justify-content: center;
  margin-top: 16px; }
.tk-pager .range-btn:disabled { opacity: 0.35; cursor: default; }
@media (max-width: 980px) {
  .tk-row { grid-template-columns: 48px 1fr 1fr 64px 80px; }
  /* En pantalla estrecha sobran las dos fechas: queda quién, quién, cuánto y ver. */
  .tk-row > .tk-date { display: none; }
  .tk-head > span:nth-child(4), .tk-head > span:nth-child(5) { display: none; }
}

/* Dashboard incrustado en la sección «📊 Métricas» del panel. */
.metrics-dash { margin-top: 8px; }
.metrics-dash .metrics-bar { margin-bottom: 20px; }
.metrics-since { font-family: monospace; font-size: 0.7rem; }
.chart { width: 100%; height: 240px; display: block; }
.legend { display: flex; gap: 16px; flex-wrap: wrap; margin-bottom: 8px; }
.legend .lg { display: flex; align-items: center; gap: 6px; font-size: 0.7rem; font-family: monospace; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); }
.legend .lg i { width: 12px; height: 12px; border-radius: 3px; display: inline-block; }

/* Desgloses (barras horizontales) */
.bd-list { display: flex; flex-direction: column; gap: 12px; }
.bd-row { display: flex; align-items: center; gap: 12px; }
.bd-name { flex: 0 0 130px; font-size: 0.8rem; font-family: monospace; color: var(--text); text-transform: uppercase; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bd-bar-wrap { flex: 1; height: 10px; background: var(--bg); border: 1px solid var(--border); border-radius: 6px; overflow: hidden; }
.bd-bar { height: 100%; background: var(--accent); }
.bd-val { flex: 0 0 auto; font-size: 0.8rem; font-family: monospace; color: var(--text-muted); min-width: 32px; text-align: right; }

/* En pantallas medianas la columna lateral se queda sin sitio: pasa a ser una
   tira horizontal de UNA sola fila con scroll (nunca envuelve, que es justo lo
   que hacía insufrible la fila de 13 pestañas de antes). */
@media (max-width: 980px) {
  .cfg-layout { grid-template-columns: 1fr; gap: 20px; }
  /* Todas las secciones se aplanan en una única tira horizontal:
     'display: contents' disuelve las cajas de grupo, así sus botones pasan a
     ser hijos directos de la tira en vez de formar una fila con scroll cada
     uno. Los títulos de grupo se ocultan porque partirían la fila. */
  .cfg-nav { position: static; max-height: none; }
  .cfg-nav-list { flex-direction: row; gap: 8px; overflow-x: auto; overflow-y: hidden; }
  .cfg-group { display: contents; }
  .cfg-group-title { display: none; }
  .cfg-nav-item { width: auto; flex: none; white-space: nowrap; }
  .cfg-nav-label { overflow: visible; }
}

@media (max-width: 768px) {
  /* La barra fija se pega arriba sin márgenes y adelgaza: el hueco que reserva
     <body> y el 'top' de la navegación sticky se recalculan solos con esto. */
  :root { --rail-h: 64px; --rail-gap: 0px; }
  .kpis { grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); }
  .metrics-bar { flex-direction: column; align-items: stretch; }
  
  /* Topbar stays at the top but gets slimmer */
  .rail {
    left: 0; top: 0; right: 0; border-radius: 0; box-shadow: none; height: 64px; padding: 0 16px;
    flex-direction: row; border: none; border-bottom: 1px solid var(--border); z-index: 1000;
  }
  .rail-logo { display: flex; flex-shrink: 0; }
  .rail-logo-img { width: 28px; height: 28px; }
  .rail-sep { width: 1px; height: 24px; margin: 0 12px; display: block; }
  .rail-tip { display: none; }
  .rail-list { flex-direction: row; justify-content: flex-start; gap: 12px; width: auto; height: 100%; }
  .rail-item { width: 40px; height: 40px; flex-shrink: 0; }
  .rail-icon { width: 40px; height: 40px; border: 1px solid transparent; }
  .rail-icon.fallback { font-size: 14px; }
  
  /* Main wrapper */
  main { width: auto; padding: 20px 16px; margin: 12px; }
  
  /* Header stacking */
  header { flex-direction: column; align-items: flex-start; gap: 16px; margin-bottom: 24px; padding-bottom: 16px; }
  header .logout { margin-left: 0; width: 100%; text-align: center; }
  
  /* Grid & Cards fix for tiny screens */
  .features, .grid { grid-template-columns: 1fr; gap: 16px; }
  .guild-card { flex-direction: column; text-align: center; }
  .guild-card .gicon { margin: 0 auto; }
  
  /* Config forms */
  .cfg-section-head { gap: 12px; }
  .cfg-savebar { flex-direction: column; align-items: stretch; bottom: 8px; }
  .cfg-savebar-actions { width: 100%; }
  .cfg-savebar-actions .btn { flex: 1; }
  .plugin-head { flex-direction: column; align-items: flex-start; gap: 12px; }
  input.num { width: 100%; }
  .tt-head { display: none; }
  .tt-row { grid-template-columns: 60px 1fr 40px; grid-auto-rows: auto; }
  .tt-cat, .tt-role { grid-column: 1 / -1; }
  /* En móvil: emoji + rol + ✕ en la primera fila, y los textos debajo a lo ancho
     (colocados a mano: por orden de aparición el ✕ caería suelto al final). */
  .sr-row { grid-template-columns: 60px 1fr 40px; }
  .sr-row .tt-emoji { grid-column: 1; grid-row: 1; }
  .sr-row .sr-role  { grid-column: 2; grid-row: 1; }
  .sr-row .tt-del   { grid-column: 3; grid-row: 1; }
  .sr-row .sr-label { grid-column: 1 / -1; grid-row: 2; }
  .sr-row .sr-desc  { grid-column: 1 / -1; grid-row: 3; }
  .switch-row { align-items: flex-start; justify-content: space-between; gap: 16px; }
  .switch-row span { flex: 1; }
  
  /* Hero section */
  .hero { padding: 32px 16px; align-items: center; text-align: center; }
  .hero-header { flex-direction: row; gap: 12px; margin-bottom: 16px; justify-content: center; }
  .hero-logo-img { width: 40px; height: 40px; }
  .hero-sep { font-size: 2.25rem; margin-top: -4px; }
  .hero-title { font-size: 2.25rem; text-align: center; }
  .hero-actions { flex-direction: column; width: 100%; gap: 12px; }
  .hero-actions .btn { width: 100%; }
}

/* Multiselect Component */
.multiselect-container {
  display: flex;
  flex-direction: column;
  max-height: 180px;
  overflow-y: auto;
  border: 1px solid var(--border);
  background: var(--bg);
  border-radius: var(--radius-btn);
  padding: 10px;
  gap: 8px;
}
.multiselect-item {
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  padding: 6px 8px;
  border-radius: 6px;
  font-size: 14px;
  transition: background var(--transition-smooth);
}
.multiselect-item:hover {
  background: rgba(255, 255, 255, 0.05);
}
.multiselect-item input[type="checkbox"] {
  width: auto;
  margin: 0;
  cursor: pointer;
}


/* ============================================================
   PESTAÑA «PERMISOS»
   Una fila por acción del bot, a ancho completo (la rejilla de dos
   columnas de .plugin-body partiría la lista de roles justo por la
   mitad). Cada fila: qué es la acción arriba y quién puede usarla
   debajo, en fichas.
   ============================================================ */
.plugin-body.perm-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.perm-node {
  padding: 14px 0;
  border-bottom: 1px solid var(--border);
}
.perm-node:last-child { border-bottom: none; padding-bottom: 0; }
.perm-node-head { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.perm-node-label { font-weight: 600; font-size: 0.95rem; }
.perm-control {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 10px;
}
.perm-chips { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* Sin roles: en vez de un hueco vacío, se dice qué pasa entonces. */
.perm-empty { font-size: 0.8rem; font-style: italic; }
.perm-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 8px 5px 10px;
  font-size: 0.8rem;
  background: var(--primary-bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-btn);
}
.perm-chip-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--border-hover);
  flex: none;
}
.perm-chip-del {
  background: none;
  border: none;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0 2px;
  font-size: 0.85rem;
  line-height: 1;
  transition: color var(--transition-smooth);
}
.perm-chip-del:hover { color: #ef4444; }
/* El select del panel es width:100% por defecto (ocupa su campo); aquí convive
   con las fichas en la misma fila, así que se queda a su ancho. */
.perm-add { width: auto; min-width: 190px; max-width: 100%; height: 40px; }
.perm-add:disabled { opacity: 0.5; cursor: not-allowed; }


/* ============================================================
   PÁGINAS DE ESTADO (web/error.html)
   Un error no es una pantalla de ajustes: no necesita el panel de
   1600px ni la cabecera con su raya de lado a lado. Es una tarjeta
   corta, centrada en el hueco que deja la barra superior, con el
   mismo vocabulario que el resto (superficie translúcida, borde,
   monoespaciada para los metadatos y los botones del panel).
   ============================================================ */
main.state {
  max-width: 560px;
  /* 'auto' en los cuatro lados: <body> es un flex en columna con alto mínimo
     de pantalla, así que la tarjeta queda centrada también en vertical, dentro
     del hueco que ya reserva el padding para la barra fija. */
  margin: auto;
  padding: 32px;
  background: var(--surface);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
}

.state-head { display: flex; align-items: center; gap: 14px; margin-bottom: 24px; }
.state-ic {
  flex: none; width: 44px; height: 44px;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius-btn);
  color: var(--text-muted);
}
.state-ic svg { width: 22px; height: 22px; }
/* «Error 4xx»: el dato técnico, en el mismo tono que las etiquetas del panel. */
.state-code {
  margin: 0; font-family: monospace; font-size: 0.72rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.14em; color: var(--text-muted);
}
/* El <h1> genérico son 3rem: dentro de una tarjeta de 560px se come dos líneas. */
.state-title { font-size: 1.6rem; margin-bottom: 10px; }
.state-msg { margin-bottom: 28px; font-size: 0.95rem; }
.state-actions { display: flex; gap: 12px; flex-wrap: wrap; }
.state-actions .btn { height: 44px; }

/* Volver a iniciar sesión solo ayuda si el problema ES la sesión o el permiso;
   en un 502/503 el botón mandaría al usuario a repetir un login que va a fallar
   igual, así que ahí no aparece. */
.state-login { display: none; }
main.state[data-status="400"] .state-login,
main.state[data-status="401"] .state-login,
main.state[data-status="403"] .state-login { display: inline-flex; }

/* 5xx: el fallo es del lado del bot, no de quien mira la página. */
main.state[data-status^="5"] .state-ic { color: #ef4444; border-color: #ef4444; }

/* ============================================================
   MOVIMIENTO REDUCIDO. Todo el panel entra con rebotes
   (--transition-bounce, slide-up-fade, save-pop) y eso marea a
   quien tiene activado "reducir movimiento" en su sistema. Se
   neutraliza sin quitar los cambios de color del hover.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  /* El spinner de guardar es el único movimiento que informa de algo (que la
     petición sigue en curso), así que se conserva, más lento. */
  .icon-spin { animation: spin 1.6s linear infinite !important; }
}

/* ============================================================
   GROSOR DEL BORDE DE LAS SUPERFICIES
   Un trazo de 1px sobre una esquina redondeada nunca llega a
   cubrir un píxel entero: el rasterizador lo reparte entre varios
   con cobertura parcial, así que la curva se dibuja más apagada
   que los tramos rectos (que sí caen justo sobre la rejilla de
   píxeles) y se lee como un cambio de color en las esquinas. Con
   2px el centro de la curva ya cubre un píxel completo y el color
   coincide con el de las rectas.
   Los controles pequeños (inputs, selects, botones, interruptores)
   se quedan en 1px a propósito: su radio es corto, el efecto
   apenas se nota y 2px los dejaría demasiado pesados.
   ============================================================ */
.rail, main, .hero, .feature, .guild-card, .card, .cfg-nav, .cfg-savebar,
.kpi, .modal-card, .draft-banner, .subcard, .emb-card, .tt-item,
.settings-menu, .mention-box {
  border-width: var(--border-w);
}
