/* ═══════════════════════════════════════════════════════════════════════════
   NOVA UI SYSTEM — sistema de diseño del panel de Hostbrid
   Aspecto CubePath: los tokens son los mismos de hostbrid.com
   (hostbrid-web/src/styles/global.css), copiados, no inventados.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ───────────────────────────────────────────────────────────────────────────
   1. TOKENS CUBEPATH — la única fuente de verdad del color
   ───────────────────────────────────────────────────────────────────────────
   Escala neutra (la de CubePath/shadcn) para no repetir grises a mano:
     950 #0a0a0a · 900 #171717 · 800 #262626 · 700 #404040 · 600 #525252
     500 #737373 · 400 #a1a1a1 · 300 #d4d4d4 · 200 #e5e5e5 · 100 #f5f5f5 · 50 #fafafa

   El panel arranca en OSCURO (base.html pone data-bs-theme="dark" y el script
   de <head> usa 'dark' por defecto), así que :root lleva los valores oscuros y
   [data-bs-theme="light"] los claros. Es como estaba montado el fichero: no lo
   cambio para no obligar a revisar 1.200 líneas de reglas heredadas.
   ─────────────────────────────────────────────────────────────────────────── */
:root {
  --radius: 0.625rem;

  /* Superficies y texto — OSCURO */
  --background: #0a0a0a;
  --foreground: #fafafa;
  --card: #171717;
  --card-foreground: #fafafa;
  --popover: #171717;
  --popover-foreground: #fafafa;
  --primary: #e5e5e5;            /* CubePath: "primary" es el neutro de máximo
                                    contraste, no la marca. La marca es --brand. */
  --primary-foreground: #171717;
  --secondary: #262626;
  --secondary-foreground: #fafafa;
  --muted: #262626;
  --muted-foreground: #a1a1a1;
  --accent: #262626;
  --accent-foreground: #fafafa;
  --destructive: #ff5a68;
  --border: #ffffff1a;
  --input: #ffffff26;
  --ring: #737373;

  /* Marca Hostbrid. --brand cuelga de --brand-500 a propósito: el whitelabel
     inyecta --brand-500 por tenant en base.html y así todo lo que use --brand
     (enlaces, foco, nav activo, acentos) se tiñe solo. */
  --brand-50: #eaf6ff;
  --brand-100: #cfeaff;
  --brand-200: #a5daff;
  --brand-300: #74c8ff;
  --brand-400: #4ebdff;
  --brand-500: #2cb2ff;
  --brand-600: #0d99e8;
  --brand-700: #0b7cbd;
  --brand-800: #0a6294;
  --brand-900: #0b4f76;
  --brand: var(--brand-500);
  --brand-light: #8ad7ff;
  --brand-dark: var(--brand-600);
  --brand-deep: #6fcbff;
  --brand-foreground: #04212f;
  --brand-subtle: #0d2634;
  /* El azul de marca sobre TEXTO no llega a contraste AA en fondo claro
     (#2cb2ff sobre blanco es 2,2:1; hace falta 4,5:1). Sobre fondo oscuro sí.
     --brand-text es el azul que se usa cuando el color va en la tipografía;
     --brand se reserva para rellenos, bordes y acentos. */
  --brand-text: var(--brand);

  /* Estados (los mismos que la página de estado de hostbrid.com) */
  --status-operational: #50c249;
  --status-operational-bg: #50c2491a;
  --status-degraded: #edb200;
  --status-degraded-bg: #edb2001a;
  --status-outage: #e40014;
  --status-outage-bg: #e400141a;
  --status-maintenance: #1578ef;
  --status-maintenance-bg: #1578ef1a;
  /* Mismo criterio que --brand-text: el color de relleno no sirve como color
     de texto. Estos son los tonos que llegan a 4,5:1 en cada tema. */
  --status-operational-text: var(--status-operational);
  --status-degraded-text: var(--status-degraded);
  --status-outage-text: var(--destructive);
  --status-maintenance-text: #4d94f5;   /* #1578ef sobre #0a0a0a se queda en 4,48 */

  /* ── Alias heredados: el panel entero ya consume estos nombres. Colgarlos de
     los tokens de arriba es lo que hace que 1.200 líneas cambien de aspecto sin
     tocarlas una a una. ── */
  --bg-primary: var(--background);
  --bg-secondary: var(--card);
  --bg-tertiary: var(--muted);
  --surface: var(--card);
  --surface-hover: var(--muted);
  --border-strong: var(--input);

  --text-primary: var(--foreground);
  --text-secondary: #d4d4d4;
  --text-muted: var(--muted-foreground);
  --text-disabled: #8f8f8f;   /* #737373 sobre la tarjeta oscura no llega a AA */

  --success: var(--status-operational);
  --warning: var(--status-degraded);
  --error: var(--destructive);
  --info: var(--brand);

  /* Sombras: CubePath es plano, así que en oscuro casi no se ven. */
  --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.30);
  --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.35);
  --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.40);
  --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.45);

  --space-xs: 0.25rem;
  --space-sm: 0.5rem;
  --space-md: 1rem;
  --space-lg: 1.5rem;
  --space-xl: 2rem;
  --space-2xl: 3rem;

  /* Radios derivados de --radius, igual que en CubePath */
  --radius-sm: calc(var(--radius) - 4px);   /* 6px  */
  --radius-md: calc(var(--radius) - 2px);   /* 8px  */
  --radius-lg: var(--radius);               /* 10px */
  --radius-xl: calc(var(--radius) + 4px);   /* 14px */
  --radius-2xl: calc(var(--radius) + 10px); /* 20px */

  /* Tipografía: CubePath usa Geist, pero aquí no hay CDN que valga (CSP) y no
     se van a empaquetar fuentes nuevas por un cambio de color. Se queda la que
     ya sirve el panel; la escala y los pesos sí son los de CubePath. */
  --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', sans-serif;
  --font-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, 'Fira Code', monospace;
}

/* ═══════════════════════════════════════════════════════════════════════════
   TEMA CLARO — sólo cambian los tokens; ninguna regla de componente se duplica
   ═══════════════════════════════════════════════════════════════════════════ */
[data-bs-theme="light"] {
  --background: #ffffff;
  --foreground: #0a0a0a;
  --card: #ffffff;
  --card-foreground: #0a0a0a;
  --popover: #ffffff;
  --popover-foreground: #0a0a0a;
  --primary: #171717;
  --primary-foreground: #fafafa;
  --secondary: #f5f5f5;
  --secondary-foreground: #171717;
  --muted: #f5f5f5;
  --muted-foreground: #737373;
  --accent: #f5f5f5;
  --accent-foreground: #171717;
  --destructive: #e40014;
  --border: #e5e5e5;
  --input: #e5e5e5;
  --ring: #a1a1a1;

  --brand-light: #6fcbff;
  --brand-deep: #0b6fa8;
  --brand-subtle: #eaf6ff;
  --brand-text: var(--brand-700);   /* #0b7cbd sobre blanco: 4,6:1 */

  --text-secondary: #404040;
  /* #a1a1a1 sobre blanco es 2,3:1. En fondo claro no cabe un gris terciario
     más claro que el apagado y que se siga leyendo: se igualan. */
  --text-disabled: var(--muted-foreground);
  --error: var(--status-outage);

  --status-operational-text: #3f7c39;
  --status-degraded-text: #8a6800;
  --status-outage-text: var(--status-outage);
  --status-maintenance-text: #0f66cf;

  --shadow-sm: 0 1px 2px 0 rgb(10 10 10 / 0.05);
  --shadow-md: 0 4px 6px -1px rgb(10 10 10 / 0.07);
  --shadow-lg: 0 10px 15px -3px rgb(10 10 10 / 0.08);
  --shadow-xl: 0 20px 25px -5px rgb(10 10 10 / 0.10);
}

/* ═══════════════════════════════════════════════════════════════════════════
   2. LA PALANCA: Bootstrap se pinta con --bs-*. Mapeándolas sobre los tokens,
   todos los componentes de Bootstrap (cards, tablas, modales, dropdowns,
   listas, formularios, offcanvas, paginación…) heredan el aspecto CubePath sin
   tocar una sola plantilla.

   Va en :root, no en [data-bs-theme], porque los valores son var() y se
   resuelven en el elemento que los usa: al cambiar de tema cambian los tokens
   y estas variables les siguen. Cero reglas duplicadas, cero !important.
   ═══════════════════════════════════════════════════════════════════════════ */
:root {
  /* Cuerpo */
  --bs-body-bg: var(--background);
  --bs-body-color: var(--foreground);
  --bs-emphasis-color: var(--foreground);
  --bs-heading-color: var(--foreground);
  --bs-secondary-bg: var(--muted);
  --bs-secondary-color: var(--muted-foreground);
  --bs-tertiary-bg: var(--muted);
  --bs-tertiary-color: var(--muted-foreground);

  /* Bordes y radios */
  --bs-border-color: var(--border);
  --bs-border-color-translucent: var(--border);
  --bs-border-radius: var(--radius);
  --bs-border-radius-sm: var(--radius-sm);
  --bs-border-radius-lg: var(--radius-lg);
  --bs-border-radius-xl: var(--radius-xl);
  --bs-border-radius-xxl: var(--radius-2xl);

  /* Tipografía */
  --bs-body-font-family: var(--font-sans);
  --bs-font-sans-serif: var(--font-sans);
  --bs-font-monospace: var(--font-mono);

  /* Enlaces y código: aquí sí manda la marca */
  --bs-link-color: var(--brand-text);
  --bs-link-hover-color: var(--brand-dark);
  --bs-link-color-rgb: 44, 178, 255;
  --bs-code-color: var(--brand-text);
  --bs-highlight-bg: var(--brand-subtle);

  /* Paleta semántica */
  --bs-primary: var(--brand);
  --bs-secondary: var(--muted-foreground);
  --bs-success: var(--status-operational);
  --bs-danger: var(--status-outage);
  --bs-warning: var(--status-degraded);
  --bs-info: var(--status-maintenance);
  --bs-light: var(--muted);
  --bs-dark: var(--foreground);
  --bs-primary-rgb: 44, 178, 255;
  --bs-success-rgb: 80, 194, 73;
  --bs-danger-rgb: 228, 0, 20;
  --bs-warning-rgb: 237, 178, 0;
  --bs-info-rgb: 21, 120, 239;

  /* Subtiles: Bootstrap los usa en alerts, badges y fondos suaves */
  --bs-primary-bg-subtle: var(--brand-subtle);
  --bs-success-bg-subtle: var(--status-operational-bg);
  --bs-danger-bg-subtle: var(--status-outage-bg);
  --bs-warning-bg-subtle: var(--status-degraded-bg);
  --bs-info-bg-subtle: var(--status-maintenance-bg);
  --bs-secondary-bg-subtle: var(--muted);
  --bs-light-bg-subtle: var(--muted);
  --bs-dark-bg-subtle: var(--muted);
  --bs-primary-border-subtle: color-mix(in srgb, var(--brand) 35%, transparent);
  --bs-success-border-subtle: color-mix(in srgb, var(--status-operational) 35%, transparent);
  --bs-danger-border-subtle: color-mix(in srgb, var(--status-outage) 35%, transparent);
  --bs-warning-border-subtle: color-mix(in srgb, var(--status-degraded) 35%, transparent);
  --bs-info-border-subtle: color-mix(in srgb, var(--status-maintenance) 35%, transparent);
  --bs-secondary-border-subtle: var(--border);
  --bs-primary-text-emphasis: var(--brand-text);
  --bs-success-text-emphasis: var(--status-operational-text);
  --bs-danger-text-emphasis: var(--status-outage-text);
  --bs-warning-text-emphasis: var(--status-degraded-text);
  --bs-info-text-emphasis: var(--status-maintenance-text);
  --bs-secondary-text-emphasis: var(--muted-foreground);

  /* Foco */
  --bs-focus-ring-color: color-mix(in srgb, var(--brand) 25%, transparent);
  --bs-focus-ring-width: 3px;
}

/* Los componentes de Bootstrap 5.3 llevan sus propias variables locales con
   valores compilados (un `.card` no lee --bs-body-bg, lee --bs-card-bg). Se
   redirigen aquí, una vez, en lugar de repetir reglas por tema. */
.card {
  --bs-card-bg: var(--card);
  --bs-card-color: var(--card-foreground);
  --bs-card-border-color: var(--border);
  --bs-card-border-radius: var(--radius-xl);
  --bs-card-inner-border-radius: var(--radius-lg);
  --bs-card-cap-bg: transparent;
  --bs-card-cap-color: var(--foreground);
}
.modal { --bs-modal-bg: var(--card); --bs-modal-color: var(--card-foreground);
         --bs-modal-border-color: var(--border); --bs-modal-border-radius: var(--radius-xl);
         --bs-modal-header-border-color: var(--border); --bs-modal-footer-border-color: var(--border); }
.dropdown-menu { --bs-dropdown-bg: var(--popover); --bs-dropdown-color: var(--popover-foreground);
         --bs-dropdown-border-color: var(--border); --bs-dropdown-border-radius: var(--radius-lg);
         --bs-dropdown-link-color: var(--popover-foreground);
         --bs-dropdown-link-hover-bg: var(--muted); --bs-dropdown-link-hover-color: var(--foreground);
         --bs-dropdown-link-active-bg: var(--muted); --bs-dropdown-link-active-color: var(--foreground);
         --bs-dropdown-divider-bg: var(--border); --bs-dropdown-header-color: var(--muted-foreground); }
.list-group { --bs-list-group-bg: transparent; --bs-list-group-color: var(--foreground);
         --bs-list-group-border-color: var(--border); --bs-list-group-border-radius: var(--radius-lg);
         --bs-list-group-action-hover-bg: var(--muted); --bs-list-group-action-hover-color: var(--foreground);
         --bs-list-group-active-bg: var(--muted); --bs-list-group-active-color: var(--foreground);
         --bs-list-group-active-border-color: var(--border); }
.table { --bs-table-bg: transparent; --bs-table-color: var(--foreground);
         --bs-table-border-color: var(--border);
         --bs-table-striped-bg: var(--muted); --bs-table-striped-color: var(--foreground);
         --bs-table-hover-bg: var(--muted); --bs-table-hover-color: var(--foreground); }
.offcanvas, .offcanvas-start, .offcanvas-end { --bs-offcanvas-bg: var(--card);
         --bs-offcanvas-color: var(--foreground); --bs-offcanvas-border-color: var(--border); }
.form-control, .form-select {
         --bs-body-bg: var(--background); --bs-border-color: var(--input); }
.nav-tabs { --bs-nav-tabs-border-color: var(--border);
         --bs-nav-tabs-link-active-bg: var(--card); --bs-nav-tabs-link-active-color: var(--foreground);
         --bs-nav-tabs-link-active-border-color: var(--border) var(--border) var(--card);
         --bs-nav-link-color: var(--muted-foreground); --bs-nav-link-hover-color: var(--foreground); }
.progress { --bs-progress-bg: var(--muted); --bs-progress-bar-bg: var(--brand);
         --bs-progress-border-radius: 999px; }
.accordion { --bs-accordion-bg: var(--card); --bs-accordion-color: var(--foreground);
         --bs-accordion-border-color: var(--border); --bs-accordion-btn-color: var(--foreground);
         --bs-accordion-active-bg: var(--muted); --bs-accordion-active-color: var(--foreground);
         --bs-accordion-border-radius: var(--radius-lg); }
.pagination { --bs-pagination-bg: transparent; --bs-pagination-color: var(--muted-foreground);
         --bs-pagination-border-color: var(--border); --bs-pagination-hover-bg: var(--muted);
         --bs-pagination-hover-color: var(--foreground); --bs-pagination-active-bg: var(--brand);
         --bs-pagination-active-border-color: var(--brand); --bs-pagination-active-color: var(--brand-foreground);
         --bs-pagination-border-radius: var(--radius-md); }
.alert { --bs-alert-border-radius: var(--radius-lg); }
.badge { --bs-badge-border-radius: 999px; }

/* Reset & Base */
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  font-family: var(--font-sans);
  background: var(--bg-primary);
  color: var(--text-primary);
  line-height: 1.6;
  overflow-x: hidden;
}

/* Topbar Navigation */
.nova-topbar {
  position: sticky;
  top: 0;
  z-index: 1000;
  background: var(--background);
  border-bottom: 1px solid var(--border);
  height: 64px;
}

.nova-topbar__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 100%;
  padding: 0 var(--space-lg);
  max-width: 1920px;
  margin: 0 auto;
}

.nova-topbar__left,
.nova-topbar__right {
  display: flex;
  align-items: center;
  gap: var(--space-md);
}

/* Brand Logo */
.nova-brand {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  font-weight: 700;
  font-size: 1.125rem;
  color: var(--text-primary);
  text-decoration: none;
  transition: transform 0.2s ease;
}

.nova-brand:hover {
  transform: scale(1.02);
  color: var(--text-primary);
}

.nova-brand__logo {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  background: var(--brand);
  border-radius: var(--radius-md);
}

.nova-brand__logo i {
  font-size: 1.25rem;
  color: white;
}

/* Custom logo image - no square box, full visual */
.nova-brand__img {
  object-fit: contain;
}
/* Theme-adaptive logo: show/hide based on data-bs-theme */
.nova-brand__img--light { display: none; }
[data-bs-theme="light"] .nova-brand__img--dark { display: none !important; }
[data-bs-theme="light"] .nova-brand__img--light { display: inline-block !important; }

/* Centered brand in topbar */
.nova-brand--center {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
}

/* Sidebar */
.nova-sidebar {
  width: 280px;
  min-width: 280px;
  background: var(--bg-secondary);
  border-right: 1px solid var(--border);
  overflow-y: auto;
  height: calc(100vh - 64px);
  position: sticky;
  top: 64px;
}

.nova-sidebar__section {
  padding: var(--space-lg) var(--space-md) var(--space-sm);
}

.nova-sidebar__title {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-muted);
  margin-bottom: var(--space-sm);
}

.nova-sidebar__nav {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.nova-nav-link {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-md);
  color: var(--text-secondary);
  font-size: 0.875rem;
  font-weight: 500;
  transition: all 0.2s ease;
  text-decoration: none;
}

.nova-nav-link:hover {
  background: var(--surface-hover);
  color: var(--text-primary);
}

.nova-nav-link.is-active {
  background: var(--muted);
  color: var(--foreground);
  font-weight: 600;
  border-left: 3px solid var(--brand);
  padding-left: calc(var(--space-md) - 3px);
}

.nova-nav-link__icon {
  font-size: 1.125rem;
  width: 20px;
  text-align: center;
}

/* Main Shell */
.nova-shell {
  display: flex;
  min-height: calc(100vh - 64px);
  background: var(--bg-primary);
}

.nova-main {
  flex: 1;
  padding: var(--space-lg);
  max-width: none;
  margin: 0;
  width: 100%;
}

/* Utilities para integración con Bootstrap */
.nova-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-sm) var(--space-md);
  border-radius: var(--radius-md);
  font-size: 0.875rem;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s ease;
  border: none;
  text-decoration: none;
}

.nova-btn--ghost {
  background: transparent;
  color: var(--text-secondary);
  border: 1px solid var(--border);
}

.nova-btn--ghost:hover {
  background: var(--surface-hover);
  color: var(--text-primary);
  border-color: var(--border-strong);
}

.nova-btn--primary {
  background: var(--primary);
  color: var(--primary-foreground);
  border: none;
}

.nova-btn--primary:hover {
  filter: brightness(0.92);
  color: var(--primary-foreground);
}

.nova-btn--icon {
  width: 40px;
  height: 40px;
  padding: 0;
  justify-content: center;
}

/* User Menu */
.nova-user {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-xs) var(--space-sm);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  cursor: pointer;
  transition: all 0.2s ease;
}

.nova-user:hover {
  background: var(--surface-hover);
  border-color: var(--border-strong);
}

.nova-user__avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--brand-500), var(--brand-700));
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 600;
  color: white;
  font-size: 0.875rem;
}

.nova-user__name {
  font-size: 0.875rem;
  color: var(--text-primary);
}

/* Responsive */
@media (max-width: 1024px) {
  .nova-sidebar:not(.nova-sidebar--mobile) {
    display: none;
  }

  .nova-main {
    padding: var(--space-lg);
  }
}

@media (max-width: 768px) {
  .nova-topbar__inner {
    padding: 0 var(--space-md);
  }

  .nova-main {
    padding: var(--space-md);
  }
}

/* Mobile Offcanvas Sidebar */
.nova-offcanvas {
  background: var(--bg-secondary) !important;
  border-right: 1px solid var(--border) !important;
  width: 280px !important;
}
.nova-offcanvas .offcanvas-header {
  background: var(--bg-secondary);
}
.nova-offcanvas .offcanvas-title {
  font-weight: 600;
}
.nova-offcanvas .nova-sidebar--mobile {
  display: block !important;
  position: static;
  width: 100%;
  height: auto;
  padding-top: var(--space-md);
  overflow-y: auto;
}
[data-bs-theme="light"] .nova-offcanvas {
  background: var(--bg-secondary) !important;
}
[data-bs-theme="light"] .nova-offcanvas .btn-close {
  filter: none;
}

/* ═══════════════════════════════════════════════════════════════════════════
   TEMA CLARO — componentes
   Este bloque tenía ~160 líneas de reglas [data-bs-theme="light"] con grises
   slate a fuego (#f1f5f9, #64748b, rgba(99,102,241,…)) que repetían en claro lo
   que ya decía la regla base en oscuro. Con --bs-* mapeadas sobre los tokens,
   todo eso lo resuelve el cambio de token. Sólo queda lo que Bootstrap no
   deriva de una variable.
   ═══════════════════════════════════════════════════════════════════════════ */

/* .card-header y .table-light no leen ninguna variable de tema en 5.3 */
.card-header {
  background-color: transparent;
  border-bottom-color: var(--border);
  color: var(--foreground);
}
.table-light th, .table-light td {
  background-color: var(--muted) !important;
  color: var(--foreground) !important;
  border-color: var(--border) !important;
}
.input-group-text {
  background-color: var(--muted);
  border-color: var(--input);
  color: var(--muted-foreground);
}
.toast {
  background-color: var(--popover);
  border-color: var(--border);
  color: var(--popover-foreground);
}
code {
  background-color: var(--muted);
  color: var(--brand-text);
  border-radius: var(--radius-sm);
  padding: 0.1em 0.35em;
}
pre {
  background-color: var(--muted);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}
pre code { background: transparent; padding: 0; }

/* Migas y avatar: acento de marca */
.breadcrumb-item a { color: var(--brand-text); text-decoration: none; }
.breadcrumb-item.active { color: var(--muted-foreground); }
.nova-user__avatar { background: var(--brand); color: var(--brand-foreground); }

/* ═══════════════════════════════════════════════════════════════════════════
   ADDITIONAL UTILITY CLASSES
   ═══════════════════════════════════════════════════════════════════════════ */

/* Stat cards - reutilizables en cualquier dashboard */
.nova-stat-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-lg);
  transition: box-shadow 0.2s ease, transform 0.2s ease;
}
.nova-stat-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}
.nova-stat-card__value {
  font-size: 1.75rem;
  font-weight: 700;
  color: var(--text-primary);
  line-height: 1;
}
.nova-stat-card__label {
  font-size: 0.75rem;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-top: var(--space-xs);
}
.nova-stat-card__icon {
  width: 48px;
  height: 48px;
  border-radius: var(--radius-lg);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.25rem;
}

/* KPI Card Component - replaces inline styles + onmouseover/onmouseout handlers */
.nova-kpi-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  transition: all 0.3s ease;
}
.nova-kpi-card--brand:hover { border-color: var(--brand-500); }
.nova-kpi-card--success:hover { border-color: var(--success); }
.nova-kpi-card--info:hover { border-color: var(--info); }
.nova-kpi-card--warning:hover { border-color: var(--warning); }
.nova-kpi-card--error:hover { border-color: var(--error); }
.nova-kpi-card__icon {
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-md);
}
.nova-kpi-card__icon--brand   { background: var(--brand);              color: var(--brand-foreground); }
.nova-kpi-card__icon--success { background: var(--status-operational); color: #04210a; }
.nova-kpi-card__icon--info    { background: var(--status-maintenance); color: #ffffff; }
.nova-kpi-card__icon--warning { background: var(--status-degraded);    color: #241a00; }
.nova-kpi-card__icon--error   { background: var(--status-outage);      color: #ffffff; }
.nova-kpi-card__label {
  font-size: 0.875rem;
  color: var(--text-muted);
  margin-bottom: 0.25rem;
}
.nova-kpi-card__value {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--text-primary);
}

/* Quick-access card hover - replaces onmouseover/onmouseout */
.nova-quick-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  overflow: hidden;
  transition: all 0.3s ease;
  height: 100%;
}
.nova-quick-card--brand:hover,
.nova-quick-card--info:hover,
.nova-quick-card--success:hover,
.nova-quick-card--warning:hover { border-color: var(--ring); box-shadow: var(--shadow-md); }

/* Botones. Bootstrap 5.3 compila los colores de cada variante en variables
   locales (--bs-btn-bg y compañía) que NO leen --bs-primary: hay que
   redirigirlas una a una o el botón sale azul Bootstrap.

   En CubePath el botón principal es el neutro de máximo contraste (negro en
   claro, blanco en oscuro), igual que el <Button variant="primary"> de
   hostbrid.com; el azul de marca queda para acentos. */
.btn {
  --bs-btn-border-radius: var(--radius-md);
  --bs-btn-font-weight: 500;
}
.btn-primary {
  --bs-btn-bg: var(--primary);            --bs-btn-color: var(--primary-foreground);
  --bs-btn-border-color: var(--primary);
  --bs-btn-hover-bg: var(--primary);      --bs-btn-hover-color: var(--primary-foreground);
  --bs-btn-hover-border-color: var(--primary);
  --bs-btn-active-bg: var(--primary);     --bs-btn-active-color: var(--primary-foreground);
  --bs-btn-active-border-color: var(--primary);
  --bs-btn-disabled-bg: var(--muted);     --bs-btn-disabled-color: var(--muted-foreground);
  --bs-btn-disabled-border-color: var(--border);
}
.btn-primary:hover, .btn-primary:focus-visible, .btn-primary:active { filter: brightness(0.9); }

/* Variante de marca, para cuando una plantilla quiera el azul de Hostbrid */
.btn-brand {
  --bs-btn-bg: var(--brand);              --bs-btn-color: var(--brand-foreground);
  --bs-btn-border-color: var(--brand);
  --bs-btn-hover-bg: var(--brand-dark);   --bs-btn-hover-color: #ffffff;
  --bs-btn-hover-border-color: var(--brand-dark);
  --bs-btn-active-bg: var(--brand-dark);  --bs-btn-active-color: #ffffff;
}

.btn-secondary, .btn-outline-secondary, .btn-light, .btn-dark {
  --bs-btn-bg: var(--muted);              --bs-btn-color: var(--foreground);
  --bs-btn-border-color: var(--border);
  --bs-btn-hover-bg: var(--secondary);    --bs-btn-hover-color: var(--foreground);
  --bs-btn-hover-border-color: var(--ring);
  --bs-btn-active-bg: var(--secondary);   --bs-btn-active-color: var(--foreground);
}
.btn-outline-primary {
  --bs-btn-color: var(--foreground);      --bs-btn-border-color: var(--border);
  --bs-btn-hover-bg: var(--muted);        --bs-btn-hover-color: var(--foreground);
  --bs-btn-hover-border-color: var(--ring);
  --bs-btn-active-bg: var(--muted);       --bs-btn-active-color: var(--foreground);
}
.btn-success { --bs-btn-bg: var(--status-operational); --bs-btn-border-color: var(--status-operational);
  --bs-btn-hover-bg: var(--status-operational); --bs-btn-hover-border-color: var(--status-operational);
  --bs-btn-active-bg: var(--status-operational); --bs-btn-color: #04210a; --bs-btn-hover-color: #04210a; }
.btn-danger  { --bs-btn-bg: var(--status-outage); --bs-btn-border-color: var(--status-outage);
  --bs-btn-hover-bg: var(--status-outage); --bs-btn-hover-border-color: var(--status-outage);
  --bs-btn-active-bg: var(--status-outage); --bs-btn-color: #ffffff; --bs-btn-hover-color: #ffffff; }
.btn-warning { --bs-btn-bg: var(--status-degraded); --bs-btn-border-color: var(--status-degraded);
  --bs-btn-hover-bg: var(--status-degraded); --bs-btn-hover-border-color: var(--status-degraded);
  --bs-btn-active-bg: var(--status-degraded); --bs-btn-color: #241a00; --bs-btn-hover-color: #241a00; }
.btn-info    { --bs-btn-bg: var(--status-maintenance); --bs-btn-border-color: var(--status-maintenance);
  --bs-btn-hover-bg: var(--status-maintenance); --bs-btn-hover-border-color: var(--status-maintenance);
  --bs-btn-active-bg: var(--status-maintenance); --bs-btn-color: #ffffff; --bs-btn-hover-color: #ffffff; }
.btn-success:hover, .btn-danger:hover, .btn-warning:hover, .btn-info:hover,
.btn-brand:hover { filter: brightness(0.92); }
body, .card, .modal-content, .nova-topbar, .nova-sidebar, .table,
.form-control, .form-select, .dropdown-menu, .list-group-item {
  transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

/* Theme-safe text helpers */
.nova-text-heading { color: var(--text-primary) !important; }
.nova-text-body    { color: var(--text-secondary) !important; }
.nova-text-muted   { color: var(--text-muted) !important; }

/* Theme-safe background helpers */
.nova-bg-primary   { background: var(--bg-primary) !important; }
.nova-bg-secondary { background: var(--bg-secondary) !important; }
.nova-bg-surface   { background: var(--surface) !important; }

/* Empty state component */
.nova-empty-state {
  text-align: center;
  padding: var(--space-2xl) var(--space-lg);
  color: var(--text-muted);
}
.nova-empty-state__icon {
  font-size: 3rem;
  margin-bottom: var(--space-md);
  opacity: 0.5;
}
.nova-empty-state__title {
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--text-secondary);
  margin-bottom: var(--space-sm);
}
.nova-empty-state__text {
  font-size: 0.875rem;
  color: var(--text-muted);
}

/* Badge variant for status */
.nova-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 8px;
  border-radius: var(--radius-sm);
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.5;
}
.nova-badge--success { background: var(--status-operational-bg); color: var(--status-operational-text); }
.nova-badge--warning { background: var(--status-degraded-bg);    color: var(--status-degraded-text); }
.nova-badge--error   { background: var(--status-outage-bg);      color: var(--status-outage-text); }
.nova-badge--info    { background: var(--status-maintenance-bg); color: var(--status-maintenance-text); }

/* Este bloque era la segunda tanda de overrides de tema claro (código, migas,
   avatar, card-header, input-group, acordeón, pestañas, paginación, toast) con
   los mismos grises a fuego. Todo eso está ahora resuelto por tokens, arriba. */

/* ═══════════════════════════════════════════════════════════════════════════
   MOBILE RESPONSIVE — Modal tables & forms
   ═══════════════════════════════════════════════════════════════════════════ */

@media (max-width: 767.98px) {
  /* Modal tables: smaller font, compact cells */
  .modal .table {
    font-size: 0.82rem;
  }
  .modal .table th,
  .modal .table td {
    padding: 0.4rem 0.35rem;
    white-space: nowrap;
  }
  /* Hide password + less-important columns on small screens */
  .modal .table .d-mobile-none {
    display: none !important;
  }
  /* Shrink input-groups (password fields) */
  .modal .input-group {
    max-width: 130px !important;
  }
  .modal .input-group .form-control-sm {
    font-size: 0.75rem;
  }
  /* Compact action buttons */
  .modal .btn-group-sm .btn {
    padding: 0.15rem 0.35rem;
    font-size: 0.78rem;
  }
  /* Stack header row in modals */
  .modal .d-flex.justify-content-between {
    flex-direction: column;
    gap: 0.5rem;
  }
  /* Forms: full-width on mobile */
  .modal .modal-body .form-control,
  .modal .modal-body .form-select {
    font-size: 0.9rem;
  }
  /* Dashboard stats cards: tighter spacing */
  .nova-main .row.g-3 > [class*="col-6"] .card-body {
    padding: 0.75rem;
  }
  .nova-main .row.g-3 > [class*="col-6"] .card-body h3 {
    font-size: 1.3rem;
  }
}

/* =========================================================================
   NEBULA — sistema visual del modulo de VMs (hermano del login audit365).
   Solo TOKENS namespaced --nx-*; los componentes viven en nebula.css y solo
   consumen estas variables -> el toggle de tema funciona sin reglas duplicadas.
   Anadido 2026-07 (rediseno gestion de VMs). No toca nada existente.
   ========================================================================= */
:root {
  /* Todo cuelga de los tokens CubePath de arriba: un solo sitio donde tocar.
     El degradado azul->violeta se va: CubePath es plano y el acento es la
     marca. Se deja --nx-grad como color liso para no romper quien lo use. */
  --nx-cyan: var(--brand);   --nx-cyan-bright: var(--brand-light);
  --nx-blue: var(--brand);   --nx-indigo: var(--brand-dark);   --nx-violet: var(--brand-deep);
  --nx-accent: var(--brand);
  --nx-grad: var(--brand);
  --nx-grad-hero: var(--brand);
  --nx-ok: var(--status-operational);  --nx-warn: var(--status-degraded);  --nx-danger: var(--destructive);
  --nx-app-bg: var(--background);
  --nx-card-bg: var(--card);
  --nx-card-border: var(--border);
  --nx-card-border-hover: color-mix(in srgb, var(--brand) 45%, transparent);
  --nx-surface-2: var(--muted);
  --nx-field-border: var(--input);
  --nx-text-1: var(--foreground); --nx-text-2: var(--muted-foreground); --nx-text-3: var(--text-disabled);
  --nx-grid-line: var(--border);
  --nx-shadow-card-hover: var(--shadow-md);
  --nx-shadow-btn: none;
  --nx-shadow-btn-hover: none;
  --nx-shadow-dropdown: var(--shadow-lg);
  --nx-focus-ring: 0 0 0 3px color-mix(in srgb, var(--brand) 25%, transparent);
  --nx-chart-cpu: #2cb2ff;  --nx-chart-ram: #50c249;
  --nx-chart-net-in: #6fcbff;  --nx-chart-net-out: #50c249;
  --nx-chart-disk-r: #2cb2ff;  --nx-chart-disk-w: #edb200;
  --nx-mono: var(--font-mono);
}

/* =========================================================================
   AUDIT365 LOOK — capa de componentes glass (acento cyan en DARK / indigo en LIGHT).
   Replica 1:1 del panel audit365 (m365-audit). CONVIVE con el whitelabel:
   sidebar/nav/logo siguen gobernados por {{ whitelabel.* }} inyectado en base.html
   (gana por !important y mayor especificidad). Fase 1: foundation + lista de VMs.
   Anadido 2026-07.
   ========================================================================= */
:root {
  --nx-panel-bg: var(--background);   /* topbar y sidebar: mismo fondo que la
                                         página, separados sólo por el borde.
                                         Es como está montada hostbrid.com. */
  --nx-hover-tint: var(--muted);
  --nx-thead-bg: transparent;
  --nx-thead-fg: var(--muted-foreground);
  --nx-badge-neutral: var(--muted-foreground);
  --nx-top-line: transparent; /* fuera la barra de degradado en las cards (tic de "IA") */
}

/* El shell debe dejar ver el canvas (fijo, detras). Body pinta el color base, que se
   propaga al canvas de la página y por tanto queda por debajo del starfield (z-index -1).
   OJO: el shell NO puede llevar z-index. Con position+z-index abre contexto de apilamiento
   y los modales declarados en {% block content %} quedan encerrados en él, por debajo del
   .modal-backdrop de Bootstrap (z-index 1050, que cuelga de <body>): se ven grises y no
   aceptan clics. Ver ModalStackingContextTest en vms/tests.py. */
body { background: var(--nx-app-bg); }
.nova-shell { background: transparent; position: relative; }
.nova-main { background: transparent; }

/* ---- Chrome glass (por defecto; el whitelabel del sidebar gana con !important) ---- */
.nova-topbar { background: var(--nx-panel-bg); border-bottom: 1px solid var(--border); }
.nova-sidebar { background: var(--nx-panel-bg); border-right: 1px solid var(--border); }

/* ---- Tarjetas glass: radius 14, linea-top gradiente animada, halo de acento ---- */
.card, .nova-kpi-card, .nova-stat-card, .nova-quick-card {
  position: relative;
  border-radius: var(--radius-xl);
  background: var(--card);
  border: 1px solid var(--border);
  overflow: hidden;
}
.card::before, .nova-kpi-card::before, .nova-stat-card::before, .nova-quick-card::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 1px;
  pointer-events: none; background: var(--nx-top-line);
  background-size: 200% 100%; animation: nxBorderFlow 6s linear infinite;
}
.card:hover, .nova-kpi-card:hover, .nova-stat-card:hover, .nova-quick-card:hover {
  border-color: var(--ring);
}
@keyframes nxBorderFlow { 0% { background-position: 0% 0; } 100% { background-position: 200% 0; } }

/* Modales tambien glass (sobre overlay) */
.modal-content {
  background-color: var(--card);
  border-color: var(--border);
  border-radius: var(--radius-xl);
}

/* ---- Tablas audit365 (SIN zebra: solo hover con tinte de acento) ---- */
.data-table {
  width: 100%; overflow-x: auto; border-radius: var(--radius-xl);
  border: 1px solid var(--border); background: var(--card);
}
.data-table table { width: 100%; border-collapse: collapse; }
.data-table thead th, .table thead th {
  background: var(--nx-thead-bg); color: var(--nx-thead-fg);
  text-transform: uppercase; font-size: .68rem; font-weight: 600; letter-spacing: .07em;
  padding: .4rem .8rem; text-align: left; border-bottom: 1px solid var(--nx-card-border);
}
.data-table tbody td {
  padding: .45rem .8rem; color: var(--nx-text-2); font-size: .82rem;
  border-bottom: 1px solid var(--nx-card-border);
}
.data-table tbody tr:last-child td { border-bottom: 0; }
.data-table tbody tr:hover { background: var(--nx-hover-tint); }
.table { --bs-table-hover-bg: var(--nx-hover-tint); --bs-table-hover-color: var(--nx-text-1); }

/* ---- Badges: texto solido + fondo 10% + ring inset 20% + glow 8%, rounded-full ---- */
.nx-badge {
  display: inline-flex; align-items: center; gap: .375rem;
  padding: .15rem .6rem; border-radius: 999px;
  font-size: .72rem; font-weight: 500; line-height: 1.5; white-space: nowrap;
}
.nx-badge i { font-size: .82em; }
/* Sin glow: CubePath no tiene halos. Color de estado + fondo al 10% + ring. */
.nx-badge--ok     { color: var(--status-operational-text); background: var(--status-operational-bg); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--status-operational) 25%, transparent); }
.nx-badge--warn   { color: var(--status-degraded-text);    background: var(--status-degraded-bg);    box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--status-degraded) 25%, transparent); }
.nx-badge--danger { color: var(--status-outage-text);      background: var(--status-outage-bg);      box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--status-outage) 25%, transparent); }
.nx-badge--info   { color: var(--status-maintenance-text); background: var(--status-maintenance-bg); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--status-maintenance) 25%, transparent); }
.nx-badge--neutral{ color: var(--nx-badge-neutral); background: var(--muted); box-shadow: inset 0 0 0 1px var(--border); }

/* ---- Botones: primario ya es gradiente+glow arriba; el resto en linea audit365 ---- */
/* Los degradados y los glow de los botones se fueron arriba, a las variables
   --bs-btn-* de cada variante. Aquí no queda nada que redefinir. */

/* ---- Inputs: focus ring de acento ---- */
.form-control, .form-select { border-radius: .6rem; }
.form-control:focus, .form-select:focus, .form-check-input:focus {
  border-color: var(--brand); box-shadow: var(--nx-focus-ring);
}
.form-check-input:checked { background-color: var(--brand); border-color: var(--brand); }

/* ---- Nav activo: barra vertical izq gradiente + punto "ping" ---- */
.nova-nav-link { position: relative; }
/* El nav activo ya lleva su barra de marca en la regla base. Fuera el
   degradado y fuera el punto que parpadeaba: CubePath no hace eso. */
.nova-nav-link.is-active { border-left: 3px solid var(--brand); }

/* ---- Dropdowns glass ---- */
.dropdown-menu {
  backdrop-filter: blur(20px) saturate(160%); -webkit-backdrop-filter: blur(20px) saturate(160%);
  border-radius: .75rem !important;
}

/* ---- Helpers tipograficos ---- */
.nx-mono { font-family: var(--nx-mono); }
/* Sin texto en degradado: en CubePath el titular es sólido y el acento se
   consigue con el color de marca, no con un arcoíris. */
.text-gradient, .nx-text-gradient { color: var(--brand-text); }
.nx-eyebrow {
  display: inline-block; font-family: var(--nx-mono);
  text-transform: uppercase; letter-spacing: .12em; font-size: .7rem; color: var(--brand-text);
}
.nx-page-title { font-size: 1.35rem; font-weight: 700; color: var(--nx-text-1); letter-spacing: -.01em; }
.nx-panel {
  position: relative; border-radius: 14px; padding: 1.15rem 1.25rem;
  background: var(--nx-card-bg); border: 1px solid var(--nx-card-border);
  backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); overflow: hidden;
}
.nx-panel::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 1px;
  background: var(--nx-top-line); background-size: 200% 100%;
  animation: nxBorderFlow 6s linear infinite; pointer-events: none;
}

/* ---- Fleet de VMs: rejilla de tarjetas glass ---- */
.nx-fleet { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 1rem; }
.nx-vm-card {
  position: relative; display: flex; flex-direction: column; gap: .85rem;
  padding: 1.15rem 1.25rem; border-radius: 14px; overflow: hidden;
  background: var(--nx-card-bg); border: 1px solid var(--nx-card-border);
  backdrop-filter: blur(16px) saturate(140%); -webkit-backdrop-filter: blur(16px) saturate(140%);
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.nx-vm-card::before {
  content: ""; position: absolute; top: 0; left: 0; right: 0; height: 1px; pointer-events: none;
  background: var(--nx-top-line); background-size: 200% 100%; animation: nxBorderFlow 6s linear infinite;
}
.nx-vm-card:hover { transform: translateY(-3px); box-shadow: var(--nx-shadow-card-hover); border-color: var(--nx-card-border-hover); }
.nx-vm-card__head { display: flex; align-items: flex-start; justify-content: space-between; gap: .75rem; }
.nx-vm-card__name { font-size: 1rem; font-weight: 600; color: var(--nx-text-1); line-height: 1.2; }
.nx-vm-card__meta { font-family: var(--nx-mono); font-size: .7rem; color: var(--nx-text-3); margin-top: .2rem; }
.nx-vm-card__specs { display: flex; flex-wrap: wrap; gap: .5rem .95rem; font-size: .8rem; color: var(--nx-text-2); }
.nx-spec { display: inline-flex; align-items: center; gap: .35rem; }
.nx-spec i { color: var(--nx-accent); font-size: .95em; }
.nx-vm-card__foot {
  display: flex; align-items: center; justify-content: space-between; gap: .5rem;
  margin-top: .1rem; padding-top: .8rem; border-top: 1px solid var(--nx-card-border);
}
.nx-vm-card__ip { font-family: var(--nx-mono); font-size: .78rem; color: var(--nx-text-2); }
.nx-vm-card__actions { display: inline-flex; gap: .3rem; }

/* ---- Respeto a prefers-reduced-motion ---- */
@media (prefers-reduced-motion: reduce) {
  .card::before, .nova-kpi-card::before, .nova-stat-card::before,
  .nova-quick-card::before, .nx-vm-card::before, .nx-panel::before { animation: none; }
  .nova-nav-link.is-active::after { animation: none; }
}

/* Marca Hostbrid: plano, sin glass translucido. */
.card, .nova-kpi-card, .nova-stat-card, .nova-quick-card, .data-table, .nx-panel, .nx-vm-card,
.modal-content, .dropdown-menu { backdrop-filter: none !important; -webkit-backdrop-filter: none !important; }

/* Tema CLARO: profundidad sutil (sin glass) para que no se vea plano/lavado */
/* CubePath separa las superficies con el borde, no con sombra. En claro se
   deja una sombra mínima para que la tarjeta no se funda con el fondo blanco. */
[data-bs-theme="light"] .card,
[data-bs-theme="light"] .vm-list,
[data-bs-theme="light"] .vm-tile,
[data-bs-theme="light"] .nx-panel,
[data-bs-theme="light"] .dstat,
[data-bs-theme="light"] .qcard { box-shadow: var(--shadow-sm); }
.vm-list .lrow:hover { background: var(--muted); }

/* ═══════════════════════════════════════════════════════════════════════════
   TAREAS Y NOTIFICACIONES (campanita, feed y modal de detalle)
   Venía incrustado en un <style id="nx-tasks-ui"> dentro de base.html. Ahí no
   se cachea, no se minifica y era el único sitio del panel con colores cyan a
   fuego después de repintar nova.css. Movido tal cual y pasado a tokens.
   El otro <style> de base.html (el del whitelabel) se queda: lo genera Django
   por tenant y tiene que seguir siendo dinámico.
   ═══════════════════════════════════════════════════════════════════════════ */
/* ---- Estado (píldoras) compartidas: feed + modal detalle ---- */
.nx-pill{display:inline-flex;align-items:center;gap:6px;padding:3px 10px;border-radius:999px;
  font-size:.7rem;font-weight:600;font-family:var(--nx-mono,ui-monospace,monospace);
  letter-spacing:.02em;line-height:1;border:1px solid transparent;white-space:nowrap}
.nx-pill i{font-size:.85em}
.nx-pill--running{color:var(--status-maintenance-text);background:var(--status-maintenance-bg);
  border-color:color-mix(in srgb,var(--status-maintenance) 28%,transparent)}
.nx-pill--success{color:var(--status-operational-text);background:var(--status-operational-bg);
  border-color:color-mix(in srgb,var(--status-operational) 28%,transparent)}
.nx-pill--error{color:var(--destructive);background:var(--status-outage-bg);
  border-color:color-mix(in srgb,var(--destructive) 28%,transparent)}
.nx-pill--pending{color:var(--muted-foreground);background:var(--muted);border-color:var(--border)}
.nx-pill__dot{width:7px;height:7px;border-radius:50%;background:currentColor}
.nx-pill--running .nx-pill__dot{animation:nxPulse 1.2s ease-in-out infinite}
@keyframes nxPulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.35;transform:scale(.7)}}
.nx-spin{display:inline-block;animation:nxSpin .8s linear infinite}
@keyframes nxSpin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){.nx-pill--running .nx-pill__dot,.nx-spin{animation:none}}

/* ---- Popup de notificaciones (campanita) ---- */
.nx-notif-pop{width:340px;max-width:92vw;padding:0;overflow:hidden;
  background:var(--popover);
  border:1px solid var(--border);border-radius:var(--radius-xl);box-shadow:var(--shadow-lg)}
.nx-notif-pop__head{display:flex;align-items:center;justify-content:space-between;
  padding:12px 14px;border-bottom:1px solid var(--nx-card-border)}
.nx-notif-pop__head h6{margin:0;font-size:.82rem;font-weight:700;color:var(--nx-text-1)}
.nx-notif-pop__head a{font-size:.72rem;font-weight:600;color:var(--brand-text);text-decoration:none}
.nx-notif-pop__head a:hover{text-decoration:underline}
.nx-notif-list{max-height:360px;overflow:auto;padding:4px}
.nx-notif-item{display:flex;gap:10px;padding:10px 11px;border-radius:10px;cursor:pointer;
  text-decoration:none;transition:background .15s;align-items:flex-start}
.nx-notif-item:hover{background:var(--muted)}
.nx-notif-item__dot{flex:0 0 auto;width:8px;height:8px;border-radius:50%;margin-top:6px;
  background:var(--brand)}
.nx-notif-item__dot.is-read{background:var(--nx-text-3);opacity:.35;box-shadow:none}
.nx-notif-item__body{min-width:0;flex:1;display:flex;flex-direction:column}
.nx-notif-item__title{font-size:.8rem;font-weight:600;color:var(--nx-text-1);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nx-notif-item__msg{font-size:.74rem;color:var(--nx-text-2);
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
.nx-notif-item__time{font-size:.68rem;color:var(--nx-text-3);margin-top:3px;
  font-family:var(--nx-mono,ui-monospace,monospace)}
.nx-notif-empty{padding:26px 14px;text-align:center;color:var(--nx-text-3);font-size:.8rem}

/* ---- Modal detalle de tarea ---- */
#taskDetailModal .modal-content{background:var(--card);
  border:1px solid var(--border);border-radius:var(--radius-2xl);box-shadow:var(--shadow-lg);color:var(--foreground)}
#taskDetailModal .modal-header,#taskDetailModal .modal-footer{border-color:var(--nx-card-border)}
.nx-task-modal__ico{flex:0 0 auto;width:38px;height:38px;border-radius:var(--radius-lg);display:grid;place-items:center;
  font-size:1.1rem;color:var(--brand);background:var(--muted);
  box-shadow:inset 0 0 0 1px var(--border)}
#taskDetailModal .modal-title{font-size:1rem;font-weight:700;color:var(--nx-text-1);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin:0}
.nx-task-modal__sub{font-size:.72rem;color:var(--nx-text-3);font-family:var(--nx-mono,ui-monospace,monospace);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nx-task-meta{display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;margin-bottom:14px}
.nx-task-meta__grid{display:flex;gap:18px;flex-wrap:wrap}
.nx-task-meta__grid b{display:block;font-size:.62rem;text-transform:uppercase;letter-spacing:.08em;
  color:var(--nx-text-3);font-weight:600;margin-bottom:2px}
.nx-task-meta__grid span{font-size:.78rem;font-family:var(--nx-mono,ui-monospace,monospace);color:var(--nx-text-1)}
.nx-task-progress{margin-bottom:14px}
.nx-task-progress__bar{height:6px;border-radius:999px;background:var(--muted);overflow:hidden}
.nx-task-progress__bar span{display:block;height:100%;border-radius:999px;width:0;
  background:var(--brand);transition:width .4s ease}
.nx-task-msg{font-size:.85rem;color:var(--nx-text-2);margin-bottom:14px}
.nx-task-msg:empty{display:none}
.nx-task-outlabel{font-size:.64rem;text-transform:uppercase;letter-spacing:.1em;color:var(--nx-text-3);
  font-weight:600;font-family:var(--nx-mono,ui-monospace,monospace);margin-bottom:7px}
/* La consola es una consola: negra en los dos temas, a propósito. */
.nx-console{font-family:var(--font-mono);font-size:.78rem;line-height:1.55;
  white-space:pre-wrap;word-break:break-word;color:#e5e5e5;background:#0a0a0a;
  border:1px solid var(--border);border-radius:var(--radius-lg);padding:14px 16px;max-height:340px;
  overflow:auto;margin:0}

/* ---- Banner de impersonación (estaba a fuego en base.html con #dc3545) ---- */
.nx-impersonate {
  position: fixed; top: 0; left: 0; right: 0; z-index: 10000;
  display: flex; align-items: center; justify-content: center; gap: 12px;
  padding: 8px 16px; text-align: center;
  font-size: .85rem; font-weight: 600;
  background: var(--status-outage); color: #ffffff;
}
.nx-impersonate__form { display: inline; margin: 0; }
.nx-impersonate__btn {
  padding: 4px 12px; font-size: .8rem; cursor: pointer;
  border-radius: var(--radius-sm);
  background: rgba(255,255,255,.18); color: #ffffff;
  border: 1px solid rgba(255,255,255,.35);
  transition: background .15s ease;
}
.nx-impersonate__btn:hover { background: rgba(255,255,255,.32); }
.nx-impersonate__spacer { height: 38px; }

/* ═══════════════════════════════════════════════════════════════════════════
   UTILIDADES .bg-* / .text-* : el color del texto que va ENCIMA
   ───────────────────────────────────────────────────────────────────────────
   En Bootstrap 5.3 `.bg-primary` y `.text-primary` salen de la MISMA variable
   (--bs-primary-rgb), pero no pueden ser el mismo azul: blanco sobre #2cb2ff da
   2,2:1 (hace falta 4,5:1) y el azul vivo como texto sobre blanco da lo mismo.
   Aquí se separan, y de paso se le pone a cada fondo de color un texto que se
   lea — las plantillas los pintan con `.text-white` a mano y en tres de los
   cinco colores de marca eso es ilegible.
   ═══════════════════════════════════════════════════════════════════════════ */
/* El FONDO no se toca: Bootstrap ya lo saca de --bs-*-rgb, que arriba apunta a
   los colores de marca, y así sigue respetando `.bg-opacity-10` — que es como
   están hechas media docena de pastillas de icono del panel. Sobreescribir el
   background con un color liso las convertía en manchas macizas con el icono
   invisible dentro.
   Lo que sí hace falta es el color del TEXTO cuando el fondo es opaco. */
.bg-primary:not([class*="bg-opacity"]),
.bg-primary:not([class*="bg-opacity"]) .text-white,
.badge.bg-primary { color: var(--brand-foreground) !important; }
.bg-success:not([class*="bg-opacity"]),
.bg-success:not([class*="bg-opacity"]) .text-white,
.badge.bg-success { color: #04210a !important; }
.bg-warning:not([class*="bg-opacity"]),
.bg-warning:not([class*="bg-opacity"]) .text-white,
.badge.bg-warning { color: #241a00 !important; }
.bg-danger:not([class*="bg-opacity"]), .badge.bg-danger { color: #ffffff !important; }
.bg-info:not([class*="bg-opacity"]),   .badge.bg-info   { color: #ffffff !important; }
.bg-secondary:not([class*="bg-opacity"]), .badge.bg-secondary {
  background-color: var(--muted) !important; color: var(--foreground) !important;
}
.bg-light:not([class*="bg-opacity"]) { background-color: var(--muted) !important; color: var(--foreground) !important; }
.bg-dark:not([class*="bg-opacity"])  { background-color: var(--foreground) !important; color: var(--background) !important; }
.bg-white { background-color: var(--card) !important; color: var(--card-foreground) !important; }

/* Texto de color: siempre la variante legible sobre el fondo del tema */
.text-primary { color: var(--brand-text) !important; }
.text-success { color: var(--status-operational-text) !important; }
.text-danger  { color: var(--status-outage-text) !important; }
.text-warning { color: var(--status-degraded-text) !important; }
.text-info    { color: var(--status-maintenance-text) !important; }
.text-muted, .text-secondary { color: var(--muted-foreground) !important; }
.text-body    { color: var(--foreground) !important; }

/* Bordes de color: el tono de relleno, que aquí sí vale */
.border-primary { border-color: var(--brand) !important; }
.border-success { border-color: var(--status-operational) !important; }
.border-danger  { border-color: var(--status-outage) !important; }
.border-warning { border-color: var(--status-degraded) !important; }
.border-info    { border-color: var(--status-maintenance) !important; }

/* Botones "outline": Bootstrap compila el color de cada variante en
   --bs-btn-color con su paleta (#ffc107, #198754…), que no lee --bs-warning ni
   --bs-success. Sin esto, un .btn-outline-warning se queda en 1,6:1 sobre
   blanco por muy bien mapeado que esté el resto. */
.btn-outline-success { --bs-btn-color: var(--status-operational-text); --bs-btn-border-color: var(--status-operational);
  --bs-btn-hover-bg: var(--status-operational); --bs-btn-hover-color: #04210a; --bs-btn-hover-border-color: var(--status-operational);
  --bs-btn-active-bg: var(--status-operational); --bs-btn-active-color: #04210a; }
.btn-outline-danger  { --bs-btn-color: var(--status-outage-text); --bs-btn-border-color: var(--status-outage);
  --bs-btn-hover-bg: var(--status-outage); --bs-btn-hover-color: #fff; --bs-btn-hover-border-color: var(--status-outage);
  --bs-btn-active-bg: var(--status-outage); --bs-btn-active-color: #fff; }
.btn-outline-warning { --bs-btn-color: var(--status-degraded-text); --bs-btn-border-color: var(--status-degraded);
  --bs-btn-hover-bg: var(--status-degraded); --bs-btn-hover-color: #241a00; --bs-btn-hover-border-color: var(--status-degraded);
  --bs-btn-active-bg: var(--status-degraded); --bs-btn-active-color: #241a00; }
.btn-outline-info    { --bs-btn-color: var(--status-maintenance-text); --bs-btn-border-color: var(--status-maintenance);
  --bs-btn-hover-bg: var(--status-maintenance); --bs-btn-hover-color: #fff; --bs-btn-hover-border-color: var(--status-maintenance);
  --bs-btn-active-bg: var(--status-maintenance); --bs-btn-active-color: #fff; }
.btn-outline-light, .btn-outline-dark { --bs-btn-color: var(--foreground); --bs-btn-border-color: var(--border);
  --bs-btn-hover-bg: var(--muted); --bs-btn-hover-color: var(--foreground); --bs-btn-hover-border-color: var(--ring);
  --bs-btn-active-bg: var(--muted); --bs-btn-active-color: var(--foreground); }

/* Cabeceras de tarjeta con fondo de color: las plantillas les ponen .text-white
   a los hijos, y blanco sobre el azul o el verde de marca no se lee (2,3:1).
   Se fuerza en todo el bloque, no sólo en el elemento con la clase. */
.card-header.bg-primary:not([class*="bg-opacity"]), .card-header.bg-primary:not([class*="bg-opacity"]) * { color: var(--brand-foreground) !important; }
.card-header.bg-success:not([class*="bg-opacity"]), .card-header.bg-success:not([class*="bg-opacity"]) * { color: #04210a !important; }
.card-header.bg-warning:not([class*="bg-opacity"]), .card-header.bg-warning:not([class*="bg-opacity"]) * { color: #241a00 !important; }
.card-header.bg-danger:not([class*="bg-opacity"]),  .card-header.bg-danger:not([class*="bg-opacity"])  * { color: #ffffff !important; }
.card-header.bg-info:not([class*="bg-opacity"]),    .card-header.bg-info:not([class*="bg-opacity"])    * { color: #ffffff !important; }
.card.bg-primary .card-title, .card.bg-primary .card-text { color: var(--brand-foreground) !important; }
.card.bg-success .card-title, .card.bg-success .card-text { color: #04210a !important; }
.card.bg-warning .card-title, .card.bg-warning .card-text { color: #241a00 !important; }
.card.bg-danger  .card-title, .card.bg-danger  .card-text { color: #ffffff !important; }
.card.bg-info    .card-title, .card.bg-info    .card-text { color: #ffffff !important; }

/* ═══════════════════════════════════════════════════════════════════════════
   PANTALLAS DE ENTRADA — .entrada
   (recuperar contraseña, segundo factor y el 403 de testigo CSRF caducado)
   ───────────────────────────────────────────────────────────────────────────
   Armazón de las siete pantallas que cuelgan de templates/entrada_base.html.
   No extienden base.html (a un anónimo le serviría la página vacía), pero sí
   cargan ESTE fichero, así que el color, la tipografía, los formularios y los
   botones les llegan por los mismos tokens que a las pantallas de dentro.

   Regla de este bloque: NI UN HEX A MANO. El azul sale de --brand, que
   entrada_base.html inyecta desde el WhiteLabelConfig del tenant igual que
   base.html; los estados salen de los tokens de estado. Por eso Hostbrid y
   everyWAN se pintan solos y no hay siete ficheros que tocar.

   Lo que NO hay aquí, a propósito: degradados, sombras de colores, fondos
   animados y cuadrículas. La tarjeta está callada mientras el proceso va
   bien; sólo cría un borde de color cuando el proceso TERMINA (verde si sale
   bien, rojo si el camino ya no lleva a ningún sitio). Ése es el único
   acento y además dice algo.
   ═══════════════════════════════════════════════════════════════════════════ */

body.entrada {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2.5rem 1rem;
  background: var(--background);
  color: var(--foreground);
}

.entrada__col { width: 100%; max-width: 30rem; }

/* ── Marca: lo único que identifica al cliente. Va en el color del texto, no
   en el de marca: un azul marino (#243C60, everyWAN) sobre el panel oscuro no
   se leería. El color de marca vive en enlaces, foco y acentos. ── */
.entrada__marca {
  display: flex; align-items: center; justify-content: center; gap: .625rem;
  margin-bottom: 1.5rem;
}
.entrada__logo { max-height: 2.25rem; max-width: 11rem; }
.entrada__logo--claro { display: none; }
[data-bs-theme="light"] .entrada__logo--oscuro { display: none; }
[data-bs-theme="light"] .entrada__logo--claro { display: inline-block; }
.entrada__marca-nombre {
  font-size: 1.0625rem; font-weight: 600; letter-spacing: -.01em;
  color: var(--foreground);
}

/* ── Tarjeta ── */
.entrada__tarjeta {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 1.75rem;
}
/* El raíl va con box-shadow interior, no con border-left: un borde de 3 px
   se sale de la esquina redondeada y encima ensancha la caja 2 px, así que
   las tarjetas con raíl y sin él no medirían lo mismo. */
.entrada__tarjeta--hecho { box-shadow: inset 3px 0 0 0 var(--status-operational); }
.entrada__tarjeta--roto  { box-shadow: inset 3px 0 0 0 var(--status-outage); }

.entrada__titular {
  font-size: 1.375rem; font-weight: 600; line-height: 1.25;
  letter-spacing: -.02em; color: var(--foreground);
  margin: 0 0 .625rem;
}
.entrada__entradilla {
  font-size: .9375rem; line-height: 1.6; color: var(--text-secondary);
  margin: 0 0 1.5rem;
}
.entrada__cuenta {
  font-family: var(--font-mono); font-size: .8125rem;
  color: var(--muted-foreground); word-break: break-all;
  margin: -.25rem 0 1.25rem;
}

/* ── Tira de pasos. Sólo la llevan las pantallas que SON una secuencia (pedir
   enlace → abrir correo → elegir contraseña, y el alta del segundo factor).
   Las columnas se reparten solas, así que sirve con dos o con tres. ── */
.entrada__pasos {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; gap: .5rem;
  list-style: none; margin: 0 0 1.5rem; padding: 0;
}
.entrada__pasos li {
  border-top: 2px solid var(--border);
  padding-top: .5rem;
  font-size: .6875rem; line-height: 1.35;
  color: var(--text-disabled);
}
.entrada__pasos .es-hecho { border-top-color: var(--muted-foreground); color: var(--muted-foreground); }
.entrada__pasos .es-ahora { border-top-color: var(--foreground); color: var(--foreground); font-weight: 600; }

/* ── Formulario ── */
.entrada__campo { margin-bottom: 1.125rem; }
/* .entrada__rotulo es para cuando el texto encabeza algo que NO es un campo
   (el QR). Un <label> sin control asociado es HTML inválido y el lector de
   pantalla lo anuncia como etiqueta de nada. */
.entrada__campo label,
.entrada__rotulo {
  display: block; font-size: .8125rem; font-weight: 500;
  color: var(--text-secondary); margin-bottom: .375rem;
}
.entrada__ayuda {
  font-size: .75rem; line-height: 1.5; color: var(--muted-foreground);
  margin-top: .375rem;
}
/* Códigos y claves: son cifras que se copian a mano, van en monoespaciada. */
.entrada__codigo {
  font-family: var(--font-mono); font-size: 1.5rem; font-weight: 600;
  text-align: center; letter-spacing: .35em; text-indent: .35em;
}
.entrada__clave {
  display: block; font-family: var(--font-mono); font-size: .8125rem;
  word-break: break-all; user-select: all;
  background: var(--muted); color: var(--foreground);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: .5rem .625rem;
}

/* Fuerza de la contraseña: 3 px y una palabra. Los colores son los de estado,
   que ya están comprobados a 4,5:1 en los dos temas. */
.entrada__fuerza { margin-top: .5rem; }
.entrada__fuerza-barra {
  height: 3px; border-radius: 999px; background: var(--muted); overflow: hidden;
}
.entrada__fuerza-barra span {
  display: block; height: 100%; width: 0; border-radius: 999px;
  background: var(--status-outage); transition: width .2s ease, background-color .2s ease;
}
.entrada__fuerza[data-nivel="media"] .entrada__fuerza-barra span { background: var(--status-degraded); }
.entrada__fuerza[data-nivel="buena"] .entrada__fuerza-barra span { background: var(--status-operational); }
.entrada__fuerza-texto { display: block; font-size: .75rem; color: var(--muted-foreground); margin-top: .375rem; }

/* ── Acciones ── */
.entrada__acciones { display: grid; gap: .625rem; margin-top: 1.5rem; }
.entrada__acciones .btn { width: 100%; padding: .625rem 1rem; font-size: .9375rem; }

.entrada__enlaces {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: .375rem 1.25rem; margin-top: 1.25rem;
  font-size: .875rem;
}

/* Cuadro del QR: fondo blanco fijo porque el código lo pinta un PNG negro
   sobre transparente y en tema oscuro no habría contraste que leer. */
.entrada__qr {
  display: block; width: fit-content; margin: 0 auto 1rem;
  background: #ffffff; border: 1px solid var(--border);
  border-radius: var(--radius-md); padding: .75rem; line-height: 0;
}

/* ── Pie: sólo el cambio de tema. No hay eslogan ni letra pequeña de adorno;
   lo que hay que contar ya está dicho arriba y repetirlo sólo hace ruido. ── */
.entrada__pie {
  display: flex; align-items: center; justify-content: flex-end;
  margin-top: 1.5rem;
}
.entrada__tema {
  flex-shrink: 0;
  width: 2rem; height: 2rem; display: flex; align-items: center; justify-content: center;
  background: transparent; color: var(--muted-foreground);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  cursor: pointer; transition: color .15s ease, border-color .15s ease;
}
.entrada__tema:hover { color: var(--foreground); border-color: var(--ring); }

@media (max-width: 30rem) {
  body.entrada { padding: 1.5rem 1rem; align-items: flex-start; }
  .entrada__tarjeta { padding: 1.25rem; }
  .entrada__titular { font-size: 1.25rem; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   PANTALLAS DE ENTRADA — .acceso
   ═══════════════════════════════════════════════════════════════════════════
   Login, alta de cuenta y las pantallas de allauth: todo lo que se ve SIN
   haber entrado. No cuelgan de base.html (base.html es el marco del panel ya
   autenticado y su bloque de contenido vive dentro de un `if
   user.is_authenticated`), así que hasta ahora cada plantilla llevaba su
   propio <style> con la paleta clavada a mano: cinco degradados y los colores
   por defecto de Tailwind (#06b6d4, #3b82f6, #8b5cf6). Aquí está una sola vez
   y sale de los tokens de arriba, así que el WhiteLabelConfig de cada tenant
   tiñe la entrada igual que tiñe las pantallas de dentro.

   TODO va bajo `.acceso` (una clase en el <body>) a propósito: estas
   plantillas heredan nombres genéricos —.btn, .panel, .field, .alert— que
   dentro del panel significan otra cosa. Sin el prefijo, retocar el login
   cambiaría los botones de todo el producto.

   El azul de marca NO se usa como color de texto. Son dos clientes: Hostbrid
   (#2CB2FF) y everyWAN (navy #243C60), y el navy sobre el fondo oscuro no
   llega ni a 2:1. Los enlaces van en --foreground subrayados y la marca se
   reserva para el foco y el icono de la tarjeta, a través de --acceso-marca,
   que es la marca mezclada con el color de texto hasta que se lee en los dos
   temas y con las dos marcas.

   El botón principal es NEUTRO (--primary: negro en claro, blanco en oscuro),
   como el <Button variant="primary"> de hostbrid.com y como el .btn-primary
   del panel. Nada de degradados.
   ═══════════════════════════════════════════════════════════════════════════ */
.acceso {
  /* La marca, empujada hacia el color de texto hasta que se ve con cualquier
     hue: sin esto el navy de everyWAN sobre el fondo oscuro es invisible y el
     foco deja de marcar dónde estás. La mezcla es más suave en claro (75 %)
     que en oscuro (70 %) porque en claro tira hacia el negro y con poco ya
     contrasta: pasarse le quita el color a la marca. */
  --acceso-marca: color-mix(in srgb, var(--brand) 70%, var(--foreground));
  --acceso-anillo: color-mix(in srgb, var(--acceso-marca) 30%, transparent);

  min-height: 100vh;
  background: var(--background);
  color: var(--foreground);
  font-family: var(--font-sans);
  line-height: 1.6;
  /* Lo que pinta el navegador y no nosotros: la casilla de condiciones, el
     amarillo del autocompletado y la barra de desplazamiento. Sin esto salen
     en claro sobre la tarjeta oscura. Va aquí y no en :root para no cambiar
     los controles del panel de dentro, que es otro lote. */
  color-scheme: dark;
}
[data-bs-theme="light"] .acceso {
  --acceso-marca: color-mix(in srgb, var(--brand) 75%, var(--foreground));
  color-scheme: light;
}

/* ---- Maquetación: dos platos, separados por una línea de un píxel ---- */
.acceso__marco { display: flex; min-height: 100vh; }
.acceso__marca {
  display: none;              /* sólo a partir de escritorio */
  width: 44%;
  flex-direction: column;
  justify-content: center;
  gap: 1.25rem;
  padding: 4rem;
  background: var(--muted);
  border-right: 1px solid var(--border);
}
@media (min-width: 1024px) { .acceso__marca { display: flex; } }
.acceso__panel {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2.5rem 1.25rem;
}
.acceso__caja { width: 100%; max-width: 26rem; }

/* Pantallas de una sola columna (allauth): la caja centrada y ya. */
.acceso--simple {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2.5rem 1.25rem;
}
.acceso__columna { width: 100%; max-width: 30rem; }
/* Firma de marca de las pantallas de una columna. No es adorno: ahí no hay
   plato de marca ni barra lateral, y el usuario llega desde Google. */
.acceso__firma { margin-bottom: 1.25rem; }
.acceso__firma img { display: block; height: 2rem; width: auto; }
.acceso__firma span { font-size: 1.15rem; font-weight: 600; letter-spacing: -0.02em; color: var(--foreground); }

/* ---- Plato de marca ---- */
.acceso .hero-logo { display: block; height: 2.75rem; width: auto; margin-bottom: 1.5rem; }
.acceso .hero-logo-text {
  font-size: 1.5rem; font-weight: 600; letter-spacing: -0.02em;
  color: var(--foreground); margin-bottom: 1.5rem;
}
.acceso .hero-title {
  font-size: clamp(1.9rem, 3.2vw, 2.4rem);
  font-weight: 600; line-height: 1.15; letter-spacing: -0.025em;
  color: var(--foreground); margin: 0;
}
.acceso .hero-subtitle {
  font-size: 1rem; line-height: 1.65; color: var(--text-secondary);
  max-width: 30rem; margin: 0;
}
/* Quedaba de cuando el nombre de marca y una palabra del titular iban con
   degradado de texto. La clase sigue en plantillas hijas; aquí lo único que
   hace es devolver el texto a su color. */
.acceso .grad-text {
  background: none;
  color: inherit;
  -webkit-text-fill-color: currentColor;
}

/* Tira de servicios: hoja de características, no bolitas de colores que
   parpadean. Va en la mono que ya usa el panel para lo técnico. */
.acceso__specs {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 0.4rem 0.9rem;
  list-style: none; margin: 0.5rem 0 0; padding: 0;
  font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: 0.01em;
  color: var(--muted-foreground);
}
.acceso__specs li { display: flex; align-items: center; }
.acceso__specs li + li::before {
  content: ""; width: 1px; height: 0.9em; margin-right: 0.9rem;
  background: currentColor; opacity: 0.35;
}

/* ---- Marca en móvil (el plato no cabe) ---- */
.acceso .mobile-logo { margin-bottom: 1.75rem; }
@media (min-width: 1024px) { .acceso .mobile-logo { display: none; } }
.acceso .mobile-logo-img { display: block; height: 2.25rem; width: auto; }
.acceso .mobile-logo-text { font-size: 1.25rem; font-weight: 600; letter-spacing: -0.02em; }

/* Cambio de logo por tema (los dos vienen del WhiteLabelConfig) */
.acceso .logo-light { display: none; }
[data-bs-theme="light"] .acceso .logo-dark { display: none; }
[data-bs-theme="light"] .acceso .logo-light { display: block; }

/* ---- Tarjeta ---- */
.acceso .card-inner,
.acceso .panel {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: 1.75rem;
}
.acceso .panel { width: 100%; max-width: 30rem; }
.acceso .card-header {
  display: flex; align-items: center; gap: 0.75rem;
  margin: 0 0 1.5rem; padding: 0;
  background: none; border: 0;
}
.acceso .header-icon-wrapper {
  width: 36px; height: 36px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--muted); border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.acceso .header-icon-wrapper i { font-size: 1.05rem; color: var(--acceso-marca); }
.acceso .card-title { font-size: 1.05rem; font-weight: 600; letter-spacing: -0.01em; margin: 0; }
.acceso .card-subtitle { font-size: 0.8125rem; color: var(--muted-foreground); margin: 0.1rem 0 0; }
.acceso .panel h1 { font-size: 1.15rem; font-weight: 600; letter-spacing: -0.01em; margin: 0 0 0.6rem; }
.acceso .panel p { font-size: 0.92rem; color: var(--text-secondary); margin: 0 0 0.5rem; }
.acceso .panel ul { font-size: 0.9rem; line-height: 1.7; color: var(--text-secondary); margin: 0.5rem 0; padding-left: 1.1rem; }

/* ---- Campos ---- */
.acceso .field { margin-bottom: 1rem; }
.acceso .field label {
  display: block; font-size: 0.8125rem; font-weight: 500;
  color: var(--text-secondary); margin-bottom: 0.375rem;
}
.acceso .input-wrap { position: relative; }
.acceso .input-wrap > i {
  position: absolute; left: 0.75rem; top: 50%; transform: translateY(-50%);
  font-size: 0.95rem; color: var(--muted-foreground); pointer-events: none;
}
.acceso .field input:not([type="checkbox"]) {
  width: 100%;
  padding: 0.625rem 0.75rem;
  background: var(--background); color: var(--foreground);
  border: 1px solid var(--input); border-radius: var(--radius-md);
  font-family: inherit; font-size: 0.9375rem; line-height: 1.5;
  outline: none;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.acceso .input-wrap input:not([type="checkbox"]) { padding-left: 2.25rem; }
.acceso .field input::placeholder { color: var(--muted-foreground); }
.acceso .field input:focus,
.acceso .field input:focus-visible {
  border-color: var(--acceso-marca);
  box-shadow: 0 0 0 3px var(--acceso-anillo);
}
.acceso .field input.error { border-color: var(--status-outage); }
.acceso .field-error,
.acceso .errors { font-size: 0.78rem; color: var(--status-outage-text); margin: 0.35rem 0 0; }
.acceso .field-hint { font-size: 0.75rem; color: var(--muted-foreground); margin-top: 0.35rem; }

/* Dos campos por fila cuando cabe */
.acceso .field-row { display: grid; grid-template-columns: 1fr; gap: 0 1rem; }
@media (min-width: 480px) { .acceso .field-row { grid-template-columns: 1fr 1fr; } }

/* Casilla de condiciones */
.acceso .check-field { display: flex; align-items: flex-start; gap: 0.6rem; margin: 1.1rem 0 1rem; }
.acceso .check-field input[type="checkbox"] {
  width: 1rem; height: 1rem; margin-top: 0.2rem; flex-shrink: 0;
  accent-color: var(--acceso-marca); cursor: pointer;
}
.acceso .check-field label {
  font-size: 0.82rem; line-height: 1.5; color: var(--text-secondary);
  margin: 0; cursor: pointer;
}

/* Campo trampa del alta: fuera de pantalla en vez de display:none, porque
   algunos bots saltan lo que está explícitamente oculto. */
.acceso .nx-trampa { position: absolute; left: -9999px; top: auto; width: 1px; height: 1px; overflow: hidden; }

/* ---- Botones ---- */
.acceso .btn-submit,
.acceso .btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
  width: 100%; padding: 0.65rem 1rem;
  background: var(--primary); color: var(--primary-foreground);
  border: 1px solid var(--primary); border-radius: var(--radius-md);
  font-family: inherit; font-size: 0.9375rem; font-weight: 500; line-height: 1.4;
  text-decoration: none; cursor: pointer;
  transition: opacity 0.15s ease;
}
.acceso .btn-submit:hover,
.acceso .btn:hover { opacity: 0.88; }
.acceso .btn-submit:focus-visible,
.acceso .btn:focus-visible,
.acceso .theme-toggle:focus-visible,
.acceso .btn-google:focus-visible,
.acceso a:focus-visible { outline: 2px solid var(--acceso-marca); outline-offset: 2px; }
.acceso .btn.secondary {
  background: transparent; color: var(--foreground); border-color: var(--border);
}
.acceso .btn.secondary:hover { background: var(--muted); opacity: 1; }
.acceso .panel .btn { margin-top: 1.25rem; }

/* ---- Avisos ---- */
.acceso .alert-box,
.acceso .alert {
  display: flex; align-items: flex-start; gap: 0.5rem;
  margin-bottom: 1rem; padding: 0.7rem 0.85rem;
  border-radius: var(--radius-md); font-size: 0.85rem;
  background: var(--status-outage-bg);
  border: 1px solid color-mix(in srgb, var(--status-outage) 30%, transparent);
  color: var(--status-outage-text);
}
.acceso .alert-box--ok {
  background: var(--status-operational-bg);
  border-color: color-mix(in srgb, var(--status-operational) 30%, transparent);
  color: var(--status-operational-text);
}
.acceso .alert-box ul { margin: 0; padding-left: 1rem; }

/* ---- Texto suelto ---- */
.acceso .info-text { font-size: 0.92rem; line-height: 1.65; color: var(--text-secondary); margin: 0; }
.acceso .info-text + .info-text { margin-top: 0.85rem; }
.acceso .info-mail,
.acceso .mail { font-weight: 600; color: var(--foreground); overflow-wrap: anywhere; }
.acceso .muted { font-size: 0.82rem; color: var(--muted-foreground); }
.acceso a {
  color: var(--foreground);
  text-decoration: underline;
  text-underline-offset: 0.18em;
  text-decoration-color: var(--input);
}
.acceso a:hover { text-decoration-color: currentColor; }
.acceso .form-foot { text-align: center; margin-top: 1rem; font-size: 0.85rem; }
/* Aquí no se carga el CSS de Bootstrap, sólo sus iconos: `me-1` no existe y el
   glifo quedaba pegado al texto. */
.acceso .form-foot i { margin-right: 0.35rem; }

/* ---- Pie de la caja: sello y cambio de tema ---- */
.acceso .footer-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; margin-top: 1.25rem;
}
.acceso .footer-text {
  margin: 0; font-family: var(--font-mono); font-size: 0.6875rem;
  letter-spacing: 0.03em; color: var(--muted-foreground);
}
.acceso .theme-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; flex-shrink: 0;
  background: transparent; border: 1px solid var(--border);
  border-radius: var(--radius-md); color: var(--muted-foreground); cursor: pointer;
  transition: color 0.15s ease, border-color 0.15s ease;
}
.acceso .theme-toggle:hover { color: var(--foreground); border-color: var(--ring); }

/* ---- Entrar con Google ----------------------------------------------------
   El logotipo de Google y su fondo blanco son requisito de marca de Google, no
   decoración nuestra: se quedan igual en los dos temas. Lo único que se toca
   es el borde y el hover, que iban en cian. */
.acceso .social-sep { display: flex; align-items: center; gap: 0.75rem; margin: 1.25rem 0 1rem; }
.acceso .social-sep::before,
.acceso .social-sep::after { content: ""; flex: 1; height: 1px; background: var(--border); }
/* Sin `text-transform: uppercase`: el separador es la palabra «o» y en
   versalita mono se lee como un cero. */
.acceso .social-sep span {
  font-family: var(--font-mono); font-size: 0.75rem; letter-spacing: 0.06em;
  color: var(--muted-foreground);
}
.acceso .btn-google {
  display: flex; align-items: center; justify-content: center; gap: 0.6rem;
  width: 100%; padding: 0.65rem 1rem;
  background: #ffffff; color: #1f1f1f; border: 1px solid #dadce0;
  border-radius: var(--radius-md);
  font-family: inherit; font-size: 0.9375rem; font-weight: 500; cursor: pointer;
  transition: background-color 0.15s ease;
}
.acceso .btn-google:hover { background: #f7f8f8; }
.acceso .btn-google svg { width: 18px; height: 18px; }

@media (prefers-reduced-motion: reduce) {
  .acceso *, .acceso *::before, .acceso *::after { transition: none !important; animation: none !important; }
}

/* ── Selector de idioma de la barra superior ──────────────────────────────
   Copia del de hostbrid.com (LangSwitcher.astro): botón fantasma con bandera,
   nombre del idioma y chevron; desplegable a la derecha con check en el activo.
   Allí las medidas vienen de utilidades de Tailwind (h-9, gap-1.5, w-44,
   rounded-xl); aquí van explícitas para que salga lo mismo. */
.nx-lang__trigger {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;          /* gap-1.5 */
  height: 2.25rem;        /* h-9 */
  padding: 0 0.625rem;    /* px-2.5 */
  border-radius: var(--radius-md, 0.5rem);
  font-size: 0.875rem;
}

.nx-lang__flag {
  width: 18px;
  height: 13px;
  border-radius: 2px;
  flex-shrink: 0;
  /* Las banderas son planas y algunas (Francia) tienen blanco pegado al borde:
     sin este filo se pierden sobre el fondo claro del tema light. */
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.12);
}

.nx-lang__caret { font-size: 0.75rem; color: var(--text-muted); }

.nx-lang__menu {
  min-width: 11rem;       /* w-44 */
  padding: 0.375rem;      /* p-1.5 */
  border-radius: var(--radius-lg, 0.75rem);
}

.nx-lang__item {
  display: flex;
  align-items: center;
  gap: 0.625rem;          /* gap-2.5 */
  width: 100%;
  padding: 0.5rem 0.625rem;
  border: 0;
  background: transparent;
  border-radius: var(--radius-md, 0.5rem);
  font-size: 0.875rem;
  color: var(--text-secondary);
  cursor: pointer;
  text-align: left;
}

.nx-lang__item:hover,
.nx-lang__item:focus-visible { background: var(--surface-hover); color: var(--text-primary); }

.nx-lang__item.is-active { color: var(--text-primary); font-weight: 500; }

/* El check va en color de marca, como en hostbrid.com (text-brand). */
.nx-lang__check { margin-left: auto; color: var(--brand); font-size: 0.875rem; }

/* ---- Selector de idioma de las pantallas de entrada -------------------- *
 * Cuatro banderas en fila, sin desplegable: esas pantallas no cargan el
 * JavaScript de Bootstrap. La activa se marca con opacidad llena y un filete
 * debajo; las demás quedan atenuadas y se encienden al pasar por encima.     */
.acceso__idiomas { display: flex; align-items: center; gap: .125rem; }
.acceso__idioma {
  display: inline-flex; align-items: center; justify-content: center;
  padding: .3rem .35rem; border: 0; background: none; cursor: pointer;
  border-bottom: 2px solid transparent; border-radius: .25rem;
  opacity: .45; transition: opacity .15s ease, border-color .15s ease;
}
.acceso__idioma:hover, .acceso__idioma:focus-visible { opacity: 1; }
.acceso__idioma.is-active { opacity: 1; border-bottom-color: var(--bs-primary, #2CB2FF); }
.acceso__idioma img { display: block; border-radius: 2px; }
