/* ============================================================
   Inter font (Google Fonts CDN)
   ============================================================ */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');

/* ============================================================
   Variables globales — paleta Venezuela
   ============================================================ */
:root {
  /* Controles nativos (date picker, flecha de select, scrollbars, botón clear del
     search) siguen este esquema → adaptan a oscuro sin CSS extra. Se invierte en
     html.light-mode. */
  color-scheme: dark;
  /* ── Fondos / superficies (OSCURO = base) ── */
  --bg:                #0d1117;
  --bg-2:              #0f172a;
  --surface:           rgba(255,255,255,0.04);
  --surface-2:         rgba(255,255,255,0.06);
  --surface-3:         #0f172a;
  --panel:             rgba(255,255,255,0.05);
  --panel-2:           #1e293b;
  /* Superficie de overlays flotantes (modales / drawer): casi opaca para que el
     contenido detrás no se transparente y el panel sea legible. NO usar --surface
     (tinte translúcido pensado para cards en flujo). */
  --surface-overlay:   rgba(26,34,52,0.97);
  --control-bg:        rgba(255,255,255,0.06);
  --control-bg-hover:  rgba(255,255,255,0.10);
  --control-border:    rgba(255,255,255,0.12);
  --scrim:             rgba(15,23,42,0.65);
  /* ── Texto ── */
  --text:              #e2e8f0;
  --text-strong:       #f1f5f9;
  --muted:             #94a3b8;
  --muted-2:           #64748b;
  /* ── Bordes ── */
  --border:            rgba(255,255,255,0.08);
  --border-soft:       rgba(255,255,255,0.05);
  /* ── Marca / acento (vivos, iguales en ambos temas salvo los soft) ── */
  --brand:             #3b82f6;
  --brand-dark:        #2563eb;
  --brand-soft-bg:     rgba(59,130,246,0.18);
  --brand-soft-fg:     #93c5fd;
  /* Tripletes RGB de marca (para rgba(var(--brand*-rgb), a)) + variante mas oscura que
     usan los hovers de los CTA. Iguales en ambos temas (marca no se redefine en claro). */
  --brand-rgb:         59,130,246;
  --brand-dark-rgb:    37,99,235;
  --brand-darker:      #1d4ed8;
  --brand-darker-rgb:  29,78,216;
  --accent:            #111827;
  --danger:            #ef4444;
  --success:           #10b981;
  /* ── Barra superior y sidebar (OSCURO) ──
     Se DERIVAN de --brand-dark con color-mix, nunca con un hex fijo: así, al
     activar un tema desde Identidad Visual (que solo redefine --brand*), la barra
     superior y la lateral cambian solas. Un hex fijo aquí es justo el bug que
     tenía el panel original: eran azules hardcodeados y se quedaban azules con
     cualquier tema. Cada token se declara DOS veces — el hex plano es el fallback
     para navegadores sin color-mix, que descartan la 2ª declaración.

     Los PORCENTAJES están calibrados para que, con la marca de fábrica
     (--brand-dark #2563eb sobre --bg #0d1117), el resultado reproduzca la paleta
     histórica del panel — pizarra casi neutra, NO azul saturado:

       --nav-bg    11% → rgb(16,26,46)  vs #131a2a rgb(19,26,42)  → Δ -3, 0,+4
       --nav-bg-2   7% → rgb(15,23,38)  vs #111827 rgb(17,24,39)  → Δ -2,-1,-1

     Subirlos vuelve a teñir la barra de azul (28%/16% daban rgb(20,40,82)). No
     los toques sin recalcular contra esos hex de referencia. */
  --nav-bg:            #131a2a;
  --nav-bg:            color-mix(in srgb, var(--brand-dark) 11%, var(--bg));
  --nav-bg-2:          #111827;
  --nav-bg-2:          color-mix(in srgb, var(--brand-dark) 7%, var(--bg));
  --nav-border:        rgba(226,232,240,0.09);
  /* Velo que separa la subsidebar de la sidebar. Va como token y no como un
     segundo color de fondo para que siga al tema de Identidad Visual: el color
     base es el MISMO (--nav-bg-2) y solo cambia la profundidad. */
  --nav-shade:         rgba(0,0,0,0.30);
  /* ── Tooltip ── */
  --tooltip-bg:        #1e293b;
  --tooltip-fg:        #f1f5f9;
  /* ── Tags / badges (bg + fg) ── */
  --badge-success-bg:  rgba(16,185,129,0.15);  --badge-success-fg: #34d399;
  --badge-warn-bg:     rgba(245,158,11,0.16);  --badge-warn-fg:    #fbbf24;
  --badge-danger-bg:   rgba(239,68,68,0.15);   --badge-danger-fg:  #f87171;
  --badge-info-bg:     rgba(59,130,246,0.16);  --badge-info-fg:    #60a5fa;
  --badge-neutral-bg:  rgba(148,163,184,0.18); --badge-neutral-fg: #cbd5e1;
  --badge-purple-bg:   rgba(139,92,246,0.16);  --badge-purple-fg:  #a78bfa;
  /* ── Sombras (oscuro: más marcadas para que se vean) ── */
  --shadow-sm:  0 1px 2px rgba(0,0,0,0.30);
  --shadow-md:  0 4px 6px rgba(0,0,0,0.35), 0 2px 4px rgba(0,0,0,0.30);
  --shadow-lg:  0 12px 28px rgba(0,0,0,0.50), 0 4px 8px rgba(0,0,0,0.40);
}

/* ============================================================
   Reset / base
   ============================================================ */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

/* --font-scale: escala global de tipografía, la fija la Identidad Visual (base del
   panel) y la puede pisar cada usuario desde Perfil → Apariencia. Lo inyecta
   src/theme.rs como `:root{--font-scale:…}` / `html:root{…}`, y el script
   pre-paint de index.html lo aplica desde el cache antes del primer render.
   Todo lo dimensionado en rem reescala con esto; los px literales NO. */
html { font-size: calc(16px * var(--font-scale, 1)); }

body {
  /* --font-family: lo fija el fontpack activo (si lo hay); fallback = Inter. */
  font-family: var(--font-family, 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
  background: var(--bg);
  min-height: 100vh;
  color: var(--text);
  -webkit-font-smoothing: antialiased;
}

.active {
  background: var(--brand-dark) !important;
  color: #fff !important;
}

/* ============================================================
   Splash / carga inicial
   ============================================================ */
.splash {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, #0f172a 0%, #1e293b 50%, #0f172a 100%);
  color: var(--muted);
  font-size: 0.875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* ============================================================
   LOGIN PAGE
   ============================================================ */
.login-container {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: linear-gradient(135deg, #0f172a 0%, #1e3a5f 40%, #0f172a 100%);
  position: relative;
  overflow: hidden;
}

/* capa de estrellas animadas */
.login-container::before {
  content: '';
  position: fixed;
  inset: 0;
  background-image:
    radial-gradient(circle, rgba(255,255,255,0.75) 1px, transparent 1px),
    radial-gradient(circle, rgba(147,197,253,0.60) 1px, transparent 1px),
    radial-gradient(circle, rgba(255,255,255,0.45) 1px, transparent 1px),
    radial-gradient(circle, rgba(96,165,250,0.40) 1px, transparent 1px),
    radial-gradient(circle, rgba(255,255,255,0.30) 1px, transparent 1px);
  background-size: 280px 280px, 190px 190px, 130px 130px, 90px 90px, 60px 60px;
  background-position: 15px 25px, 55px 70px, 90px 15px, 130px 110px, 40px 80px;
  animation: starDrift 50s linear infinite;
  pointer-events: none;
  z-index: 0;
}

/* orbs de brillo pulsantes */
.login-container::after {
  content: '';
  position: fixed;
  inset: 0;
  background:
    radial-gradient(ellipse 650px 650px at 78% 8%,  rgba(59,130,246,0.14) 0%, transparent 65%),
    radial-gradient(ellipse 450px 450px at 22% 92%, rgba(37,99,235,0.09)  0%, transparent 65%),
    radial-gradient(ellipse 300px 300px at 55% 50%, rgba(99,102,241,0.06) 0%, transparent 60%);
  pointer-events: none;
  z-index: 0;
  animation: orbPulse 9s ease-in-out infinite alternate;
}

@keyframes starDrift {
  from { background-position: 15px 25px, 55px 70px, 90px 15px, 130px 110px, 40px 80px; }
  to   { background-position: 295px 305px, 245px 260px, 220px 145px, 220px 200px, 100px 140px; }
}

@keyframes orbPulse {
  from { opacity: 0.6; }
  to   { opacity: 1.0; }
}

/* tarjeta */
.login-card {
  width: 100%;
  max-width: 420px;
  padding: 40px;
  border-radius: 24px;
  background: linear-gradient(145deg, rgba(255,255,255,0.98) 0%, rgba(241,245,249,0.95) 100%);
  border: 1px solid rgba(226,232,240,0.8);
  box-shadow:
    0 25px 60px rgba(0,0,0,0.3),
    0 0 0 1px rgba(255,255,255,0.08),
    inset 0 1px 0 rgba(255,255,255,0.9);
  backdrop-filter: blur(20px);
  animation: fadeInUp 0.45s cubic-bezier(0.4, 0, 0.2, 1);
  position: relative;
  z-index: 1;
  /* GPU: compositor handles transform+opacity animation without layout recalc */
  will-change: transform, opacity;
  contain: layout style paint;
}

@keyframes fadeInUp {
  from { opacity: 0; transform: translateY(28px) scale(0.98); }
  to   { opacity: 1; transform: translateY(0)   scale(1);    }
}

/* header */
.login-header {
  text-align: center;
  margin-bottom: 36px;
}

.login-logo {
  width: 52px;
  height: 52px;
  margin: 0 auto 18px;
  background: linear-gradient(135deg, #1d4ed8 0%, #3b82f6 100%);
  border-radius: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 8px 20px rgba(37,99,235,0.4), 0 2px 6px rgba(37,99,235,0.2);
}

.login-logo svg {
  color: #ffffff;
}

.login-header h1 {
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  background: linear-gradient(135deg, var(--brand-dark) 0%, var(--accent) 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  margin-bottom: 6px;
}

.login-subtitle {
  color: var(--muted);
  font-size: 0.875rem;
  font-weight: 500;
}

.login-weather-chip {
  margin-top: 16px;
  padding: 12px 14px;
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.62);
  border: 1px solid rgba(148, 163, 184, 0.22);
  backdrop-filter: blur(12px);
  display: grid;
  gap: 4px;
}

.login-weather-chip__location {
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--text-strong);
}

.login-weather-chip__country {
  font-size: 0.77rem;
  font-weight: 600;
  color: var(--text-strong);
}

.login-weather-chip__status {
  font-size: 0.76rem;
  color: var(--muted);
  font-weight: 500;
}

.login-container--dynamic {
  background: linear-gradient(135deg, #0f172a 0%, #1e3a5f 40%, #0f172a 100%);
  transition: background 1.2s ease;
}

/* ── Paleta de cielo por franja horaria (ortogonal al clima) ─────
   El tema (clima) define las partículas; la fase define el cielo.
   Los climas que ocurren a cualquier hora (nublado/lluvia/nieve)
   construyen su fondo sobre estas variables. ─────────────────── */
.login-container--dynamic.phase-dawn  { --sky-a: #f7b27a; --sky-b: #c98a9b; --sky-c: #5b6aa8; }
.login-container--dynamic.phase-day   { --sky-a: #6fa8dc; --sky-b: #9cc3e6; --sky-c: #3d6aa3; }
.login-container--dynamic.phase-dusk  { --sky-a: #e8915b; --sky-b: #9b5e8e; --sky-c: #2e2f5b; }
.login-container--dynamic.phase-night { --sky-a: #050816; --sky-b: #102347; --sky-c: #040a17; }
/* Fallback si por algún motivo no hay clase de fase. */
.login-container--dynamic { --sky-a: #4b5f79; --sky-b: #6f86a3; --sky-c: #2e3d53; }

.login-container--dynamic.theme-default::before {
  background-image:
    radial-gradient(circle, rgba(255,255,255,0.75) 1px, transparent 1px),
    radial-gradient(circle, rgba(147,197,253,0.60) 1px, transparent 1px),
    radial-gradient(circle, rgba(255,255,255,0.45) 1px, transparent 1px),
    radial-gradient(circle, rgba(96,165,250,0.40) 1px, transparent 1px),
    radial-gradient(circle, rgba(255,255,255,0.30) 1px, transparent 1px);
}

.login-container--dynamic.theme-default::after {
  background:
    radial-gradient(ellipse 650px 650px at 78% 8%,  rgba(59,130,246,0.14) 0%, transparent 65%),
    radial-gradient(ellipse 450px 450px at 22% 92%, rgba(37,99,235,0.09)  0%, transparent 65%),
    radial-gradient(ellipse 300px 300px at 55% 50%, rgba(99,102,241,0.06) 0%, transparent 60%);
}

/* El cielo soleado sigue la hora (amanecer/día/atardecer); el sol cambia de
   posición y color por fase vía variables (usadas en `.theme-sunny .wbg-1`). */
.login-container--dynamic.theme-sunny {
  --sun-x: 83%; --sun-y: 16%;
  --sun-core: rgba(255,255,220,1);
  --sun-glow: rgba(255,228,60,0.38);
  background: linear-gradient(160deg, #8ec5ef 0%, #bfe0f5 45%, #ffe9a8 100%);
}
.login-container--dynamic.theme-sunny.phase-day {
  --sun-x: 83%; --sun-y: 16%;
  --sun-core: rgba(255,255,225,1);
  --sun-glow: rgba(255,228,60,0.38);
  background: linear-gradient(160deg, #8ec5ef 0%, #bfe0f5 45%, #ffe9a8 100%);
}
.login-container--dynamic.theme-sunny.phase-dawn {
  --sun-x: 80%; --sun-y: 62%;
  --sun-core: rgba(255,238,205,1);
  --sun-glow: rgba(255,182,120,0.42);
  background: linear-gradient(160deg, #fde7c7 0%, #f7b98a 46%, #e98a86 100%);
}
.login-container--dynamic.theme-sunny.phase-dusk {
  --sun-x: 22%; --sun-y: 64%;
  --sun-core: rgba(255,226,184,1);
  --sun-glow: rgba(255,140,90,0.44);
  background: linear-gradient(160deg, #ffd29b 0%, #ff9e7a 46%, #b5638f 100%);
}

.login-container--dynamic.theme-sunny::before {
  background:
    radial-gradient(circle at 82% 18%, rgba(255, 252, 227, 0.92) 0 10%, rgba(255, 252, 227, 0.25) 18%, transparent 38%),
    radial-gradient(circle at 12% 22%, rgba(255,255,255,0.24) 0 8%, transparent 24%),
    radial-gradient(circle at 22% 30%, rgba(255,255,255,0.16) 0 7%, transparent 22%);
  animation: orbPulse 8s ease-in-out infinite alternate;
}

.login-container--dynamic.theme-sunny::after {
  background:
    linear-gradient(115deg, rgba(255,255,255,0) 20%, rgba(255,255,255,0.18) 44%, rgba(255,255,255,0) 62%),
    radial-gradient(ellipse 560px 220px at 20% 100%, rgba(116, 185, 129, 0.22) 0%, transparent 62%);
  animation: sunnyGlow 9s ease-in-out infinite alternate;
}

.login-container--dynamic.theme-cloudy {
  /* Velo gris translúcido sobre el cielo de la fase → nublado de día u
     oscuro de noche según las variables --sky-*. */
  background:
    linear-gradient(180deg, rgba(120,134,158,0.42) 0%, rgba(70,84,108,0.34) 100%),
    linear-gradient(135deg, var(--sky-a) 0%, var(--sky-b) 45%, var(--sky-c) 100%);
}

.login-container--dynamic.theme-cloudy::before {
  background:
    radial-gradient(ellipse 360px 135px at 18% 22%, rgba(255,255,255,0.22) 0%, transparent 70%),
    radial-gradient(ellipse 460px 155px at 76% 20%, rgba(255,255,255,0.18) 0%, transparent 72%),
    radial-gradient(ellipse 400px 145px at 48% 74%, rgba(255,255,255,0.10) 0%, transparent 70%);
  filter: blur(6px);
  animation: cloudDrift 24s ease-in-out infinite alternate;
}

.login-container--dynamic.theme-cloudy::after {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.06) 0%, rgba(255,255,255,0) 55%),
    radial-gradient(ellipse 580px 360px at 50% 10%, rgba(255,255,255,0.08) 0%, transparent 70%);
}

.login-container--dynamic.theme-rainy {
  /* Cielo de la fase (azul de día … negro de noche) + velo de tormenta
     cuya opacidad sube con la intensidad (clases .intensity-*). */
  --storm: rgba(8,12,24,0.34);
  background:
    linear-gradient(180deg, var(--storm) 0%, var(--storm) 100%),
    linear-gradient(135deg, var(--sky-a) 0%, var(--sky-b) 46%, var(--sky-c) 100%);
}
.login-container--dynamic.theme-rainy.intensity-1 { --storm: rgba(20,28,44,0.20); }
.login-container--dynamic.theme-rainy.intensity-2 { --storm: rgba(12,18,32,0.36); }
.login-container--dynamic.theme-rainy.intensity-3 { --storm: rgba(4,8,18,0.55); }

.login-container--dynamic.theme-rainy::before {
  background-image:
    repeating-linear-gradient(110deg,
      transparent                    0px    7px,
      rgba(174,214,241, 0.44)        7px    8.5px,
      transparent                    8.5px  24px,
      rgba(174,214,241, 0.26)        24px   25.5px,
      transparent                    25.5px 42px);
  background-size: 42px 88px;
  animation: rainFall 0.48s linear infinite;
  opacity: 1;
}

.login-container--dynamic.theme-rainy::after {
  background:
    radial-gradient(ellipse 620px 280px at 50% 100%, rgba(56, 189, 248, 0.16) 0%, transparent 68%),
    radial-gradient(ellipse 260px 260px at 85% 18%, rgba(14, 165, 233, 0.14) 0%, transparent 70%);
}

.login-container--dynamic.theme-snowy {
  /* Aclarado suave sobre el cielo de la fase: nieve luminosa de día,
     más sobria de noche (las variables --sky-* ya oscurecen). */
  background:
    linear-gradient(180deg, rgba(225,236,246,0.34) 0%, rgba(183,202,223,0.20) 100%),
    linear-gradient(135deg, var(--sky-a) 0%, var(--sky-b) 45%, var(--sky-c) 100%);
}

.login-container--dynamic.theme-snowy::before {
  background-image:
    radial-gradient(circle, rgba(255,255,255,0.92) 1.5px, transparent 1.5px),
    radial-gradient(circle, rgba(255,255,255,0.72) 1px, transparent 1px),
    radial-gradient(circle, rgba(255,255,255,0.54) 1.2px, transparent 1.2px);
  background-size: 180px 180px, 120px 120px, 90px 90px;
  background-position: 10px 10px, 70px 40px, 30px 80px;
  animation: snowFall 12s linear infinite;
}

.login-container--dynamic.theme-snowy::after {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.20) 0%, rgba(255,255,255,0.00) 52%),
    radial-gradient(ellipse 440px 200px at 50% 100%, rgba(255,255,255,0.18) 0%, transparent 70%);
}

.login-container--dynamic.theme-night {
  background: linear-gradient(135deg, #050816 0%, #102347 45%, #040a17 100%);
}

.login-container--dynamic.theme-night::before {
  background-image:
    radial-gradient(circle, rgba(255,255,255,0.86) 1px, transparent 1px),
    radial-gradient(circle, rgba(96,165,250,0.58) 1px, transparent 1px),
    radial-gradient(circle, rgba(255,255,255,0.38) 1px, transparent 1px);
  background-size: 220px 220px, 130px 130px, 80px 80px;
  background-position: 15px 25px, 55px 70px, 90px 15px;
  animation: starDrift 40s linear infinite;
}

.login-container--dynamic.theme-night::after {
  /* Sin disco brillante aquí: la luna (con su fase real) la dibuja el canvas.
     Solo queda el ambiente azulado del cielo nocturno. */
  background:
    radial-gradient(ellipse 460px 460px at 78% 10%, rgba(59,130,246,0.16) 0%, transparent 68%),
    radial-gradient(ellipse 350px 160px at 50% 100%, rgba(37,99,235,0.10) 0%, transparent 72%);
}

.login-container--dynamic.theme-christmas {
  background: linear-gradient(135deg, #0f2e24 0%, #7f1d1d 52%, #1f2937 100%);
}

.login-container--dynamic.theme-christmas::before {
  background-image:
    radial-gradient(circle, rgba(248, 250, 252, 0.92) 2px, transparent 2px),
    radial-gradient(circle, rgba(248, 113, 113, 0.72) 2.5px, transparent 2.5px),
    radial-gradient(circle, rgba(74, 222, 128, 0.72) 2.5px, transparent 2.5px),
    radial-gradient(circle, rgba(250, 204, 21, 0.76) 2px, transparent 2px);
  background-size: 170px 170px, 210px 210px, 240px 240px, 130px 130px;
  background-position: 18px 40px, 42px 82px, 110px 22px, 84px 124px;
  animation: festiveBokeh 14s ease-in-out infinite alternate;
}

.login-container--dynamic.theme-christmas::after {
  background:
    radial-gradient(ellipse 540px 220px at 50% 100%, rgba(250, 204, 21, 0.14) 0%, transparent 68%),
    linear-gradient(180deg, rgba(255,255,255,0.10) 0%, rgba(255,255,255,0.00) 48%);
}

@keyframes rainFall {
  from { background-position: 0 0; }
  to   { background-position: -42px 88px; }
}

@keyframes snowFall {
  /* background-position animation: each layer moves exactly one tile height = seamless loop */
  from { background-position: 10px  10px, 70px 40px,  30px 80px; }
  to   { background-position: -10px 190px, 55px 160px, 10px 170px; }
}

@keyframes cloudDrift {
  from { transform: translateX(-14px); opacity: 0.8; }
  to { transform: translateX(16px); opacity: 1; }
}

@keyframes sunnyGlow {
  from { opacity: 0.7; transform: translateX(-12px); }
  to { opacity: 1; transform: translateX(12px); }
}

@keyframes festiveBokeh {
  from { opacity: 0.78; transform: scale(1); }
  to { opacity: 1; transform: scale(1.04); }
}

/* ═══════════════════════════════════════════════════════════════
   Weather background animation layers (.wbg)
   3 fixed divs injected by login.rs, z-index: 0, pointer-events: none
   Each theme drives its own wbg-1/2/3 rules.
   ═══════════════════════════════════════════════════════════════ */

.wbg {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
}

/* ── Selector de fondos (solo modo test) ──────────────────────── */
.bgsel {
  position: fixed;
  top: 14px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 5;
  pointer-events: auto;
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-width: min(92vw, 720px);
  padding: 10px 14px;
  border-radius: 14px;
  background: rgba(15, 23, 42, 0.72);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(148, 163, 184, 0.28);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
  color: #e2e8f0;
  font-size: 0.78rem;
}
.bgsel__title {
  font-weight: 700;
  font-size: 0.74rem;
  letter-spacing: 0.02em;
  opacity: 0.85;
  margin-bottom: 2px;
}
.bgsel__row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.bgsel__lbl {
  flex: 0 0 70px;
  font-weight: 600;
  opacity: 0.7;
  font-size: 0.72rem;
}
.bgsel__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
}
.bgsel__chip {
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid rgba(148, 163, 184, 0.32);
  background: rgba(255, 255, 255, 0.06);
  color: #e2e8f0;
  font-size: 0.72rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.bgsel__chip:hover {
  background: rgba(255, 255, 255, 0.14);
  border-color: rgba(148, 163, 184, 0.55);
}
.bgsel__chip.is-active {
  background: #3b82f6;
  border-color: #60a5fa;
  color: #fff;
}
@media (max-width: 560px) {
  .bgsel__lbl { flex-basis: 100%; }
  .bgsel__row { flex-wrap: wrap; }
}

/* Canvas cloud — sits above .wbg layers; blur matches HTML example */
canvas.login-cloud-canvas {
  position: fixed;
  inset: 0;
  display: block;
  pointer-events: none;
  z-index: 0;
  filter: blur(3px);
}

/* Canvas rain — sits above .wbg layers, below .login-card (z-index:1) */
canvas.login-rain-canvas {
  position: fixed;
  inset: 0;
  display: block;
  pointer-events: none;
  z-index: 0;
}

/* Canvas moon — luna con fase real (tema noche); sobre las estrellas .wbg */
canvas.login-moon-canvas {
  position: fixed;
  inset: 0;
  display: block;
  pointer-events: none;
  z-index: 0;
}

/* ── CLOUDY: puffy cloud formations scrolling across sky ─────── */
/* wbg-1/2 hidden — canvas handles foreground clouds */
.theme-cloudy .wbg-1,
.theme-cloudy .wbg-2 { display: none; }

.theme-cloudy .wbg-1-UNUSED {
  /* Tile 680×210px: two distinct cloud formations built from
     overlapping circles — fewer blur pixels = crisper puffs. */
  background-image:
    /* Cloud A — left formation */
    radial-gradient(circle 78px  at 17% 72%, rgba(228,240,254,0.96) 0%, transparent 80%),
    radial-gradient(circle 62px  at 23% 56%, rgba(228,240,254,0.94) 0%, transparent 78%),
    radial-gradient(circle 70px  at 32% 58%, rgba(228,240,254,0.96) 0%, transparent 78%),
    radial-gradient(circle 56px  at 40% 67%, rgba(220,234,252,0.90) 0%, transparent 78%),
    radial-gradient(circle 48px  at  8% 76%, rgba(210,228,250,0.82) 0%, transparent 78%),
    /* Cloud B — right formation */
    radial-gradient(circle 62px  at 71% 68%, rgba(220,234,252,0.90) 0%, transparent 78%),
    radial-gradient(circle 50px  at 77% 56%, rgba(220,234,252,0.88) 0%, transparent 76%),
    radial-gradient(circle 56px  at 85% 62%, rgba(220,234,252,0.90) 0%, transparent 76%),
    radial-gradient(circle 42px  at 64% 73%, rgba(210,226,248,0.80) 0%, transparent 78%),
    radial-gradient(circle 36px  at 93% 70%, rgba(210,226,248,0.76) 0%, transparent 76%);
  background-size: 680px 210px;
  background-repeat: repeat-x;
  filter: blur(2.5px);
  opacity: 0.94;
  animation: cloudRoll1 32s linear infinite;
}

.theme-cloudy .wbg-2 {
  /* Larger background clouds, slower + softer */
  background-image:
    radial-gradient(circle 115px at 17% 62%, rgba(195,218,240,0.80) 0%, transparent 78%),
    radial-gradient(circle  98px at 26% 50%, rgba(195,218,240,0.76) 0%, transparent 76%),
    radial-gradient(circle 108px at 36% 55%, rgba(195,218,240,0.78) 0%, transparent 76%),
    radial-gradient(circle  88px at 46% 63%, rgba(185,210,236,0.72) 0%, transparent 76%),
    radial-gradient(circle  92px at 70% 60%, rgba(190,212,238,0.74) 0%, transparent 74%),
    radial-gradient(circle  80px at 79% 50%, rgba(190,212,238,0.70) 0%, transparent 74%),
    radial-gradient(circle  88px at 88% 58%, rgba(190,212,238,0.72) 0%, transparent 74%),
    radial-gradient(circle  72px at 60% 66%, rgba(182,206,234,0.68) 0%, transparent 74%);
  background-size: 900px 280px;
  background-repeat: repeat-x;
  filter: blur(10px);
  opacity: 0.72;
  animation: cloudRoll2 56s linear infinite;
}

.theme-cloudy .wbg-3 {
  background:
    linear-gradient(180deg, rgba(52,72,98,0.62) 0%, rgba(52,72,98,0.18) 26%, transparent 50%),
    linear-gradient(  0deg, rgba(40,58,82,0.32) 0%, transparent 16%);
}

@keyframes cloudRoll1 {
  from { background-position:    0px   70px; }
  to   { background-position:  680px   70px; }
}
@keyframes cloudRoll2 {
  from { background-position: -200px 230px; }
  to   { background-position:  700px 230px; }
}

/* ── RAINY: drizzle + storm clouds + lightning flash ─────────── */

.theme-rainy .wbg-1 {
  /* Very faint background rain — Canvas handles the foreground drops */
  background-image:
    repeating-linear-gradient(107deg,
      transparent            0px   13px,
      rgba(174,214,241,0.09) 13px  14px,
      transparent            14px  42px);
  background-size: 42px 125px;
  animation: rainWbgB 0.72s linear infinite;
  opacity: 0.7;
}

/* Relámpago: solo en lluvia fuerte/tormenta (intensity-3). */
.theme-rainy .wbg-2 { display: none; }
.theme-rainy.intensity-3 .wbg-2 {
  display: block;
  /* Lightning flash: long silence then rapid double-strike (18s cycle). */
  background: linear-gradient(155deg,
    rgba(205,232,255,0.94) 0%,
    rgba(225,244,255,0.65) 40%,
    transparent 78%);
  opacity: 0;
  animation: lightningFlash 18s ease-in 0s infinite;
}

.theme-rainy .wbg-3 {
  /* Oscurecimiento superior que sigue la intensidad (--storm). Las nubes
     volumétricas las dibuja el canvas según la fase (claras de día,
     oscuras de noche), por eso aquí solo damos profundidad al cielo. */
  background:
    linear-gradient(180deg, var(--storm) 0%, transparent 46%);
  opacity: 0.9;
  animation: stormDrift 50s ease-in-out infinite alternate;
}

@keyframes lightningFlash {
  /* Double-strike at 70% of 18s = 12.6s. Total duration ≈ 324ms. */
  0%,   70%,   70.8%, 71%,   71.8%, 100% { opacity: 0; }
  70.3%                                   { opacity: 0.90; }
  70.5%                                   { opacity: 0.28; }
  71.3%                                   { opacity: 0.74; }
  71.6%                                   { opacity: 0.10; }
}

@keyframes rainWbgB {
  from { background-position: 0 0; }
  to   { background-position: -42px 125px; }
}

@keyframes stormDrift {
  from { transform: translateX(-18px); }
  to   { transform: translateX( 18px); }
}

/* ── SUNNY: sun disc + ray corona + wispy clouds ─────────────── */

.theme-sunny .wbg-1 {
  /* Sun disc + inner corona + outer halo + conic ray spikes.
     Posición (--sun-x/--sun-y) y color (--sun-core/--sun-glow) varían por fase. */
  background:
    radial-gradient(circle 52px  at var(--sun-x) var(--sun-y), var(--sun-core) 0%, rgba(255,248,140,0.90) 35%, transparent 58%),
    radial-gradient(circle 118px at var(--sun-x) var(--sun-y), var(--sun-glow)  0%, transparent 62%),
    radial-gradient(circle 245px at var(--sun-x) var(--sun-y), rgba(255,210,20,0.14)  0%, transparent 78%),
    repeating-conic-gradient(from 0deg at var(--sun-x) var(--sun-y),
      rgba(255,240,80,0.28) 0deg 4deg,
      transparent 4deg 22deg);
  animation: sunBeat 5.5s ease-in-out infinite alternate;
}

.theme-sunny .wbg-2 {
  /* Wispy cloud tile 920×130px drifting left to right */
  background-image:
    radial-gradient(ellipse 190px 58px at 22% 66%, rgba(255,255,255,0.64) 0%, transparent 72%),
    radial-gradient(ellipse 148px 44px at 36% 58%, rgba(255,255,255,0.52) 0%, transparent 70%),
    radial-gradient(ellipse 168px 52px at 57% 62%, rgba(255,255,255,0.58) 0%, transparent 70%),
    radial-gradient(ellipse 132px 40px at 72% 58%, rgba(255,255,255,0.50) 0%, transparent 68%),
    radial-gradient(ellipse 155px 48px at 90% 65%, rgba(255,255,255,0.56) 0%, transparent 70%);
  background-size: 920px 130px;
  background-repeat: repeat-x;
  filter: blur(3px);
  opacity: 0.82;
  animation: cloudRollSun 70s linear infinite;
}

.theme-sunny .wbg-3 {
  background:
    linear-gradient(0deg, rgba(255,175,55,0.14) 0%, transparent 32%),
    radial-gradient(ellipse 340px 240px at 92% 12%, rgba(255,255,220,0.20) 0%, transparent 70%);
  animation: sunHaze 9s ease-in-out infinite alternate;
}

@keyframes cloudRollSun {
  from { background-position:    0px 160px; }
  to   { background-position:  920px 160px; }
}
@keyframes sunBeat {
  from { opacity: 0.80; transform: scale(0.97); }
  to   { opacity: 1.00; transform: scale(1.03); }
}
@keyframes sunHaze {
  from { opacity: 0.68; }
  to   { opacity: 1.00; }
}

/* ── SNOWY: layered snowflakes + cloud ceiling ───────────────── */

.theme-snowy .wbg-1 {
  background-image:
    radial-gradient(circle 3.8px at 20% 50%, rgba(255,255,255,0.92) 0%, transparent 100%),
    radial-gradient(circle 2.6px at 68% 50%, rgba(255,255,255,0.82) 0%, transparent 100%);
  background-size: 210px 210px, 140px 140px;
  animation: snowWbgA 18s linear infinite;
}

.theme-snowy .wbg-2 {
  background-image:
    radial-gradient(circle 2.0px at 42% 50%, rgba(255,255,255,0.78) 0%, transparent 100%),
    radial-gradient(circle 1.6px at 74% 50%, rgba(255,255,255,0.66) 0%, transparent 100%);
  background-size: 115px 115px, 78px 78px;
  animation: snowWbgB 10s linear infinite;
  opacity: 0.85;
}

.theme-snowy .wbg-3 {
  /* Soft cloud ceiling at top + ground glow at bottom */
  background:
    radial-gradient(ellipse 460px 130px at 28% 8%,  rgba(222,236,252,0.48) 0%, transparent 72%),
    radial-gradient(ellipse 380px 110px at 74% 5%,  rgba(222,236,252,0.42) 0%, transparent 70%),
    linear-gradient(  0deg, rgba(215,232,250,0.40) 0%, transparent 24%),
    linear-gradient(180deg, rgba(200,222,244,0.22) 0%, transparent 14%);
}

@keyframes snowWbgA {
  from { background-position:  35px   0px,  85px  60px; }
  to   { background-position: -10px 210px,  60px 200px; }
}
@keyframes snowWbgB {
  from { background-position:  58px  22px,  22px  42px; }
  to   { background-position:  20px 137px,  -2px 120px; }
}

/* ── NIGHT: dense starfield + nebula + moon disc ─────────────── */

.theme-night .wbg-1 {
  background-image:
    radial-gradient(circle 1.5px at 50% 50%, rgba(255,255,255,0.90) 0%, transparent 100%),
    radial-gradient(circle 1.0px at 50% 50%, rgba(200,220,255,0.78) 0%, transparent 100%),
    radial-gradient(circle 1.2px at 50% 50%, rgba(255,255,255,0.62) 0%, transparent 100%);
  background-size: 225px 225px, 145px 145px, 88px 88px;
  background-position: 18px 28px, 58px 72px, 40px 14px;
  animation: starTwinkleWbg 5s ease-in-out infinite alternate;
}

.theme-night .wbg-2 {
  background:
    radial-gradient(ellipse 720px 420px at 62% 32%, rgba(22,46,110,0.24) 0%, transparent 74%),
    radial-gradient(ellipse 380px 260px at 16% 74%, rgba(10,22,90,0.15)  0%, transparent 66%);
  animation: nebulaPulse 15s ease-in-out infinite alternate;
}

.theme-night .wbg-3 {
  /* Solo el resplandor azulado de fondo; el disco lunar lo dibuja el canvas
     (login-moon-canvas) con la fase real y su propio halo. */
  background:
    radial-gradient(ellipse 620px 480px at 50% 0%, rgba(59,130,246,0.12) 0%, transparent 72%);
}

@keyframes starTwinkleWbg {
  from { opacity: 0.60; }
  to   { opacity: 1.00; }
}
@keyframes nebulaPulse {
  from { opacity: 0.48; transform: scale(1.00); }
  to   { opacity: 1.00; transform: scale(1.06); }
}

/* ── CHRISTMAS: snowfall + bokeh + festive corner glow ──────── */

.theme-christmas .wbg-1 {
  background-image:
    radial-gradient(circle 2.8px at 20% 50%, rgba(255,255,255,0.90) 0%, transparent 100%),
    radial-gradient(circle 1.8px at 66% 50%, rgba(255,255,255,0.76) 0%, transparent 100%);
  background-size: 160px 160px, 102px 102px;
  animation: snowWbgA 14s linear infinite;
  opacity: 0.90;
}

.theme-christmas .wbg-2 {
  background-image:
    radial-gradient(circle 16px at 50% 50%, rgba(248,113,113,0.74) 0%, transparent 100%),
    radial-gradient(circle 12px at 50% 50%, rgba(74,222,128,0.70)  0%, transparent 100%),
    radial-gradient(circle 18px at 50% 50%, rgba(250,204,21,0.76)  0%, transparent 100%),
    radial-gradient(circle 11px at 50% 50%, rgba(248,250,252,0.84) 0%, transparent 100%);
  background-size: 225px 225px, 182px 182px, 265px 265px, 138px 138px;
  background-position: 44px 84px, 112px 24px, 86px 126px, 20px 42px;
  filter: blur(2px);
  animation: festiveBokeh 14s ease-in-out infinite alternate;
  opacity: 0.82;
}

.theme-christmas .wbg-3 {
  background:
    radial-gradient(ellipse 620px 295px at 16% 90%, rgba(12,68,34,0.28)  0%, transparent 72%),
    radial-gradient(ellipse 520px 260px at 84% 94%, rgba(110,12,12,0.23) 0%, transparent 68%),
    linear-gradient(180deg, rgba(255,255,255,0.08) 0%, transparent 16%);
}

/* ── DEFAULT: subtle orb depth ──────────────────────────────── */
.theme-default .wbg-2 {
  background:
    radial-gradient(ellipse 500px 350px at 72% 28%, rgba(37,99,235,0.08)  0%, transparent 68%),
    radial-gradient(ellipse 380px 280px at 28% 80%, rgba(29,78,216,0.06) 0%, transparent 65%);
  animation: nebulaPulse 18s ease-in-out infinite alternate;
}

/* campos */
.form-field {
  margin-bottom: 20px;
}

.form-field label {
  display: block;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 8px;
}

/* La tarjeta de login es SIEMPRE clara (independiente del tema), así que sus
   labels deben ser oscuros en ambos temas para no quedar blancos sobre blanco. */
.login-card .form-field label { color: var(--text-strong); }

/* Selects en tema OSCURO (base): sin `color` explícito el texto del <select> y
   su popup nativo de <option> caen al negro por defecto del navegador → invisibles
   sobre superficie oscura. Damos color legible y un popup casi opaco. En claro,
   los overrides con !important de `html.light-mode select` ganan a esta base. */
select { color: var(--text); }
select option {
  background: var(--surface-overlay);
  color: var(--text);
}

.input-wrapper {
  position: relative;
  display: flex;
  align-items: center;
}

.input-wrapper input {
  width: 100%;
  padding: 14px 46px 14px 14px;
  border-radius: 12px;
  border: 2px solid var(--border);
  background: var(--surface-2);
  color: var(--text);
  font-size: 0.9375rem;
  font-family: inherit;
  font-weight: 400;
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: var(--shadow-sm);
}

.input-wrapper input::placeholder {
  color: var(--muted-2);
  font-weight: 400;
}

.input-wrapper input:focus {
  outline: none;
  border-color: var(--brand-dark);
  box-shadow: 0 0 0 3px rgba(37,99,235,0.1), var(--shadow-sm);
  transform: translateY(-1px);
  background: var(--surface);
}

.input-icon {
  position: absolute;
  right: 14px;
  color: var(--muted-2);
  pointer-events: none;
  transition: color 0.2s ease;
  display: flex;
  align-items: center;
}

.input-wrapper:focus-within .input-icon {
  color: var(--brand);
}

.otp-input-group {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 44px));
  gap: 10px;
  justify-content: start;
}

.pin-box {
  width: 44px;
  height: 52px;
  padding: 0;
  text-align: center;
  border-radius: 12px;
  border: 2px solid var(--border);
  background: var(--surface-2);
  color: var(--text-strong);
  font-size: 1.2rem;
  font-weight: 700;
  font-family: inherit;
  box-shadow: var(--shadow-sm);
  transition:
    transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1),
    border-color 0.2s ease,
    box-shadow 0.2s ease,
    background 0.2s ease;
}

.pin-box::placeholder {
  color: var(--muted-2);
  opacity: 0.7;
}

.pin-box.filled {
  border-color: var(--amber, #d97706);
  background: color-mix(in srgb, var(--surface) 86%, #f59e0b 14%);
}

.pin-box.pop {
  transform: scale(1.14);
}

.pin-box:focus {
  border-color: var(--amber, #d97706);
  outline: none;
  box-shadow: 0 0 0 3px rgba(217, 119, 6, 0.16), var(--shadow-sm);
  background: var(--surface);
}

.password-toggle {
  position: absolute;
  right: 10px;
  background: none;
  border: none;
  color: var(--muted-2);
  cursor: pointer;
  padding: 6px;
  border-radius: 8px;
  transition: all 0.2s ease;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2;
}

.password-toggle:hover {
  color: var(--text);
  background: rgba(37,99,235,0.08);
}

/* botón submit */
.btn-login {
  width: 100%;
  padding: 15px 24px;
  border-radius: 12px;
  font-size: 0.9375rem;
  font-weight: 600;
  font-family: inherit;
  letter-spacing: 0.015em;
  background: linear-gradient(135deg, var(--brand-darker) 0%, var(--brand) 100%);
  color: white;
  border: none;
  cursor: pointer;
  box-shadow: 0 4px 16px rgba(var(--brand-dark-rgb),0.45), 0 1px 3px rgba(var(--brand-dark-rgb),0.3);
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
  margin-top: 12px;
}

/* Recarga de SOLO la tabla (filtros, paginación, cards): la bandeja se atenúa y
   deja de aceptar clics, pero nada se desmonta — el resto del módulo sigue ahí. */
.tk-reloading { opacity: 0.55; pointer-events: none; transition: opacity 0.12s ease; }

/* ── Ticket module layout ───────────────────────────────── */

/* Márgenes del módulo: el contenido no debe pegarse a los bordes de la pantalla
   (sidebar, cabecera y pie). Sin esto la bandeja chocaba con las tres. */
.tickets-content { padding: 24px 32px; }

.ticket-summary-grid,
.ticket-grid {
  display: grid;
  gap: 14px;
}

.ticket-summary-grid {
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  margin-bottom: 20px;
}

.ticket-grid {
  grid-template-columns: minmax(0, 2fr) minmax(280px, 1fr);
  align-items: start;
}

.ticket-grid-single {
  grid-template-columns: minmax(0, 1fr);
}

/* ── Ticket tabs — pill-group ───────────────────────────── */

.ticket-tabs {
  display: flex;
  gap: 3px;
  margin-bottom: 20px;
  background: var(--surface-2);
  border-radius: 999px;
  padding: 5px;
  width: fit-content;
  max-width: 100%;
  overflow-x: auto;
}

.ticket-tabs button {
  appearance: none;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font-size: 0.8125rem;
  font-weight: 600;
  font-family: inherit;
  padding: 8px 18px;
  white-space: nowrap;
  transition: all 0.15s;
}

.ticket-tabs button:not(.active):hover {
  background: var(--control-bg-hover);
  color: var(--text);
}

.ticket-tabs button.active {
  background: var(--brand-dark) !important;
  color: #fff !important;
  box-shadow: 0 1px 4px rgba(0,0,0,0.12);
}

/* ── Toolbar ────────────────────────────────────────────── */

.ticket-toolbar {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 180px));
  gap: 10px;
  align-items: center;
  margin-bottom: 16px;
}

/* Toolbar de la bandeja: nº variable de selects (el de "cerrado" y los desenlaces
   solo existen para supervisor/owner) → flex con wrap, no grid de columnas fijas.
   Los botones van pegados a la derecha; si no caben, envuelven a otra fila. */
.ticket-toolbar-wide {
  display: flex;
  flex-wrap: wrap;
}

.ticket-toolbar-wide select {
  width: auto;
  min-width: 150px;
  flex: 0 1 190px;
}

.ticket-toolbar-wide .ticket-toolbar-actions {
  margin-left: auto;
  flex: 0 0 auto;
}

/* Cada filtro con su título arriba, para que se entienda qué hace. */
.ticket-filter-field {
  display: flex;
  flex-direction: column;
  gap: 3px;
  flex: 0 1 190px;
}
.ticket-filter-field > select {
  width: 100%;
  min-width: 0;
  flex: none;
}
.ticket-filter-label {
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--muted);
  letter-spacing: 0.02em;
}

/* Segunda fila de filtros de la bandeja: búsqueda por texto + rango de fechas. */
.ticket-subfilters {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin: -4px 0 16px;
}
.ticket-search {
  flex: 1 1 240px;
  min-width: 200px;
  min-height: 38px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: inherit;
  font-size: 0.9rem;
  color: var(--text);
  background: var(--control-bg);
}
.ticket-search:focus { outline: none; border-color: var(--brand); }
.ticket-daterange {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--muted);
  font-size: 0.85rem;
}
.ticket-daterange input[type="date"] {
  min-height: 38px;
  padding: 7px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: inherit;
  font-size: 0.85rem;
  color: var(--text);
  background: var(--control-bg);
}
.ticket-daterange input[type="date"]:focus { outline: none; border-color: var(--brand); }
.ticket-clear-dates {
  border: 1px solid var(--control-border);
  background: var(--control-bg);
  color: var(--muted);
  border-radius: 6px;
  width: 26px;
  height: 26px;
  cursor: pointer;
  line-height: 1;
}
.ticket-clear-dates:hover { background: var(--control-bg-hover); color: var(--text); }
.ticket-created { color: var(--muted); font-size: 0.82rem; white-space: nowrap; }

/* Bandeja: layout fijo para respetar el colgroup y que nada se desborde. */
.tickets-table { table-layout: fixed; width: 100%; }
.tickets-table th,
.tickets-table td {
  padding: 11px 10px;
  vertical-align: middle;
  white-space: normal;
  word-break: normal;
  overflow-wrap: break-word;   /* parte solo si no hay espacio/guion; sin cortes a media palabra */
  overflow: hidden;
  text-overflow: ellipsis;
}
.tickets-table td > .ticket-cell-text,
.tickets-table td > .ticket-cell-clamp {
  display: block;
  max-width: 100%;
  overflow: hidden;
}
.tickets-table td > .ticket-cell-text {
  white-space: nowrap;
  text-overflow: ellipsis;
}
/* REF: código monoespaciado; quiebra limpio en el guion si no cabe */
.tickets-table td.tk-ref {
  font-family: ui-monospace, "Cascadia Code", Menlo, Consolas, monospace;
  font-size: 0.75rem;
  letter-spacing: -0.02em;
  color: var(--muted-2);
}
/* ASUNTO: máximo 2 líneas con elipsis sin romper el layout tabular */
.tickets-table td > .ticket-cell-clamp {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  white-space: normal;
}
/* CREADO: fecha+hora en una sola línea */
.tickets-table td.ticket-created { white-space: nowrap; font-size: 0.8rem; color: var(--muted-2); }
/* La columna de acciones debe poder desbordar para el menú flotante */
.tickets-table .table-actions { overflow: visible; }
.tickets-table .table-actions button { padding: 4px 8px; font-size: 0.73rem; }

/* Paginación de la bandeja */
.ticket-pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}
.ticket-pagination-info { color: var(--muted); font-size: 0.83rem; }
.ticket-pagination-controls { display: flex; align-items: center; gap: 10px; }
.ticket-pagination-page { color: var(--text); font-size: 0.85rem; font-weight: 600; }
.ticket-pagination-controls button[disabled] { opacity: 0.5; cursor: not-allowed; }

/* ── Cabeceras ordenables del monitor interno ─────────────────────────────────
   La flecha está SIEMPRE presente (tenue si la columna no es la activa) para que
   se vea de un vistazo qué se puede ordenar; si solo apareciera al pasar el ratón,
   la mitad de las columnas parecerían fijas. Se usan tokens semánticos, no colores
   literales, para que funcione igual en tema claro y oscuro. */
th.th-sortable {
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}
th.th-sortable:hover { background: var(--control-bg-hover); }
th.th-sortable .th-sort-arrow {
  margin-left: 5px;
  font-size: 0.72em;
  color: var(--muted-2);
  opacity: 0.55;
}
th.th-sortable.th-sorted { color: var(--text-strong); }
th.th-sortable.th-sorted .th-sort-arrow { color: var(--brand); opacity: 1; }

.ticket-toolbar-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

.ticket-toolbar select {
  width: 100%;
  padding: 9px 12px;
  border: 1.5px solid var(--border);
  border-radius: 9px;
  font: inherit;
  font-size: 0.85rem;
  background: var(--control-bg);
  color: var(--text);
  cursor: pointer;
  transition: border-color 0.15s;
}

.ticket-toolbar select:focus {
  outline: none;
  border-color: var(--brand-dark);
}

/* Toolbar de filtros de las pestañas Tipos/Planes: layout flex (no el grid de la
   bandeja), para que la búsqueda se estire y los selects/botón queden alineados. */
.ticket-toolbar--filters {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}
.ticket-toolbar--filters > select {
  width: auto;
  min-width: 150px;
  flex: 0 1 190px;
}
.ticket-toolbar--filters > input[type="text"] {
  flex: 1 1 200px;
  min-width: 160px;
  min-height: 38px;
  padding: 9px 12px;
  border: 1.5px solid var(--border);
  border-radius: 9px;
  font: inherit;
  font-size: 0.85rem;
  background: var(--control-bg);
  color: var(--text);
}
.ticket-toolbar--filters > input[type="text"]:focus { outline: none; border-color: var(--brand-dark); }
.ticket-toolbar--filters > button { flex: 0 0 auto; }

/* Reasignar departamento (reclasificar) en el detalle del ticket */
.ticket-reassign-hint { color: var(--muted); font-size: 0.84rem; margin-bottom: 8px; }
/* Título + ℹ en la misma línea. El margen inferior es lo que impide que el
   desplegable de abajo se pegue al aviso (el choque que había antes). */
.ticket-reassign-head { display: flex; align-items: center; gap: 6px; margin-bottom: 12px; }
.ticket-reassign-head .ticket-detail-section-title { margin-bottom: 0; }
/* En columna: el botón va DEBAJO del desplegable, no a su lado — en media
   columna del detalle no caben los dos en línea sin estrangular el select. */
.ticket-reassign-row { display: flex; flex-direction: column; gap: 10px; align-items: stretch; }
.ticket-reassign-select {
  /* Ancho, no flex: en un contenedor en columna `flex-basis` sería la ALTURA. */
  width: 100%;
  min-width: 180px;
  min-height: 38px;
  padding: 9px 12px;
  border: 1.5px solid var(--border);
  border-radius: 9px;
  font: inherit;
  font-size: 0.88rem;
  background: var(--control-bg);
  color: var(--text);
  cursor: pointer;
}
.ticket-reassign-select:focus { outline: none; border-color: var(--brand-dark); }
.ticket-reassign-btn { align-self: flex-start; }

/* Cambio sin guardar: desplegable y botón en ámbar. Mientras no lo haya el botón
   va bloqueado y en gris, con cursor de "no permitido" al apuntarlo. */
.ticket-reassign-select.is-dirty {
  border-color: var(--badge-warn-fg);
  background: var(--badge-warn-bg);
  color: var(--badge-warn-fg);
}
.ticket-reassign-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.ticket-reassign-error { color: var(--badge-danger-fg); font-size: 0.82rem; margin-top: 8px; }

.ticket-toolbar button,
.ticket-toolbar-actions button {
  padding: 9px 16px;
  border: 1.5px solid var(--border);
  border-radius: 9px;
  background: var(--control-bg);
  color: var(--text);
  font: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.15s;
}

.ticket-toolbar button:hover,
.ticket-toolbar-actions button:hover {
  border-color: var(--brand);
  color: var(--brand-dark);
}

.ticket-toolbar-actions .btn-create {
  background: var(--brand-dark);
  color: #fff;
  border-color: var(--brand-dark);
}

.ticket-toolbar-actions .btn-create:hover {
  background: var(--brand-darker);
  border-color: var(--brand-darker);
  color: #fff;
}

.ticket-toolbar-actions .btn-export {
  border-color: rgba(14,116,144,0.22);
  background: linear-gradient(135deg, #ecfeff 0%, #f0fdfa 100%);
  color: #0f766e;
  box-shadow: 0 1px 3px rgba(15,118,110,0.10);
}

.ticket-toolbar-actions .btn-export:hover {
  border-color: #0f766e;
  color: #115e59;
  transform: translateY(-1px);
}

.ticket-toolbar-actions .btn-export--excel {
  border-color: rgba(22,163,74,0.24);
  background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%);
  color: #15803d;
}

.ticket-toolbar-actions .btn-export--excel:hover {
  border-color: #16a34a;
  color: #166534;
}

.ticket-toolbar-actions .btn-export:disabled,
.ticket-toolbar-actions .btn-export--excel:disabled {
  opacity: 0.58;
  cursor: not-allowed;
  transform: none;
}

/* ── Generic export buttons (CSV / Excel) ───────────────── */

.btn-export {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px;
  font-size: 12px;
  font-weight: 600;
  border-radius: 6px;
  border: 1px solid rgba(14,116,144,0.22);
  background: linear-gradient(135deg, #ecfeff 0%, #f0fdfa 100%);
  color: #0f766e;
  cursor: pointer;
  transition: border-color 0.15s, transform 0.1s;
  box-shadow: 0 1px 3px rgba(15,118,110,0.10);
  white-space: nowrap;
}

.btn-export:hover {
  border-color: #0f766e;
  color: #115e59;
  transform: translateY(-1px);
}

.btn-export--excel {
  border-color: rgba(22,163,74,0.24);
  background: linear-gradient(135deg, #f0fdf4 0%, #dcfce7 100%);
  color: #15803d;
}

.btn-export--excel:hover {
  border-color: #16a34a;
  color: #166534;
}

.btn-export:disabled,
.btn-export--excel:disabled {
  opacity: 0.58;
  cursor: not-allowed;
  transform: none;
}

/* ── Summary cards ──────────────────────────────────────── */

.ticket-summary-card {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 0;
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.ticket-summary-card h3 {
  background: linear-gradient(135deg, #1e293b 0%, #334155 100%);
  color: #f1f5f9;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  padding: 10px 16px;
  margin: 0;
}

.ticket-summary-card p {
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--text);
  padding: 12px 16px 4px;
  margin: 0;
}

.ticket-summary-card small {
  font-size: 0.74rem;
  color: var(--muted);
  padding: 0 16px 14px;
  line-height: 1.5;
}

/* Segunda línea de la tarjeta: desglose del desenlace de los tickets cerrados */
.ticket-summary-card small.ticket-summary-resolutions {
  margin-top: -8px;
  font-size: 0.7rem;
  color: var(--muted-2);
}

/* Cards de resumen clickeables (interruptor de filtro por dominio): elevación
   leve al apuntar, anillo de marca cuando el filtro está activo. */
.ticket-summary-card--clickable {
  cursor: pointer;
  transition: transform 0.15s, box-shadow 0.15s;
}
.ticket-summary-card--clickable:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
.ticket-summary-card--clickable:focus-visible {
  outline: none;
  transform: translateY(-2px);
  box-shadow: 0 0 0 2px var(--brand), var(--shadow-md);
}
.ticket-summary-card--clickable.is-active { box-shadow: 0 0 0 2px var(--brand); }

/* ── Ticket panels ──────────────────────────────────────── */

.ticket-panel {
  background: rgba(255,255,255,0.04);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 20px 20px 16px;
  box-shadow: var(--shadow-sm);
}

.ticket-panel h3 {
  font-size: 0.9rem;
  font-weight: 700;
  color: #f1f5f9;
  margin: 0 0 14px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.ticket-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 14px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
}

.ticket-panel-header h3 {
  margin: 0;
  padding-bottom: 0;
  border-bottom: none;
}
/* Botones de acción del header (p. ej. "Órdenes SAE" + "+ Nuevo tipo"). */
.ticket-header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}
/* Modal ancho para tablas (catálogo de órdenes SAE, 9 columnas con selects +
   inputs + toggles). Más ancho para que la data respire; en pantallas chicas usa
   casi todo el viewport y la tabla igual hace scroll-x en .ticket-table-wrap. */
.modal-card--wide {
  max-width: min(1280px, 96vw);
  width: 96%;
}

/* Contenedor de scroll para tablas anchas dentro de modales/paneles (p. ej. el
   catálogo de órdenes SAE: 9 columnas). Sin esto la tabla desborda la modal y,
   como .modal-card tiene overflow-x:hidden, las últimas columnas (los toggles de
   acción: "Sube a SAE", "Requiere equipo Fibex", "Activo") quedaban recortadas e
   inaccesibles. Aquí la tabla hace scroll horizontal propio en vez de recortarse. */
.ticket-table-wrap {
  width: 100%;
  max-width: 100%;
  overflow-x: auto;
  overflow-y: hidden;
  -webkit-overflow-scrolling: touch;
}
.ticket-table-wrap > table { min-width: max-content; }

/* ── Ticket form ────────────────────────────────────────── */

.ticket-form {
  display: grid;
  gap: 10px;
}

.ticket-form input,
.ticket-form select,
.ticket-form textarea {
  width: 100%;
  padding: 9px 12px;
  border: 1.5px solid var(--border);
  border-radius: 9px;
  font: inherit;
  font-size: 0.87rem;
  background: var(--surface-2);
  color: var(--text);
  transition: border-color 0.15s;
}

.ticket-form input:focus,
.ticket-form select:focus,
.ticket-form textarea:focus {
  outline: none;
  border-color: var(--brand-dark);
  background: var(--surface);
}

.ticket-form textarea {
  min-height: 80px;
  resize: vertical;
}

.ticket-form button[type="submit"] {
  padding: 10px 18px;
  background: var(--brand-dark);
  color: #fff;
  border: 0;
  border-radius: 9px;
  font: inherit;
  font-size: 0.87rem;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s;
}

.ticket-form button[type="submit"]:hover {
  background: #1d4ed8;
}

.type-form-actions {
  display: flex;
  gap: 8px;
}

.type-form-actions .btn-cancel {
  padding: 10px 14px;
  background: var(--surface-2);
  color: var(--muted);
  border: 1.5px solid var(--border);
  border-radius: 9px;
  font: inherit;
  font-size: 0.87rem;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.15s;
}

.type-form-actions .btn-cancel:hover {
  background: var(--control-bg-hover);
}

/* ── Table action buttons ───────────────────────────────── */

.table-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}

.table-actions button {
  padding: 5px 10px;
  font-size: 0.77rem;
  font-weight: 600;
  font-family: inherit;
  border: 1.5px solid var(--border);
  border-radius: 7px;
  background: var(--surface);
  color: var(--muted);
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.15s;
}

.table-actions button:hover:not(:disabled) {
  border-color: var(--brand);
  color: var(--brand-dark);
}

.table-actions button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* ── Manage modal tabs ──────────────────────────────────── */

.ticket-manage-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  padding: 0 24px 16px;
}

/* Sub-tags del monitor Interno: cambian entre tablas (cada una carga su sección) */
.ticket-monitor-subtabs {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--border);
}
.ticket-monitor-subtabs button {
  padding: 8px 14px;
  border: none;
  background: transparent;
  color: var(--muted);
  font-size: 0.86rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  border-radius: 8px 8px 0 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.ticket-monitor-subtabs button:hover { color: var(--text); background: var(--control-bg-hover); }
.ticket-monitor-subtabs button.active { color: var(--brand); border-bottom-color: var(--brand); }

.ticket-manage-tabs button {
  appearance: none;
  border: 0;
  border-radius: 8px;
  background: var(--surface-2);
  color: var(--muted);
  cursor: pointer;
  font-size: 0.82rem;
  font-weight: 600;
  font-family: inherit;
  padding: 7px 16px;
  white-space: nowrap;
  transition: all 0.15s;
}

.ticket-manage-tabs button.active {
  background: var(--brand-dark) !important;
  color: #fff !important;
  box-shadow: 0 1px 4px rgba(0,0,0,0.12);
}

.ticket-manage-tabs button:not(.active):hover {
  background: var(--control-bg-hover);
  color: var(--text);
}

.ticket-manage-form {
  padding-bottom: 0;
}

/* Row highlight when editing */
tr.row-editing {
  background: rgba(59,130,246,0.04);
  outline: 2px solid rgba(59,130,246,0.25);
  outline-offset: -2px;
}

/* ── SLA badges ─────────────────────────────────────────── */

.sla-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 88px;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 0.77rem;
  font-weight: 600;
  white-space: nowrap;
  border: 1px solid transparent;
}

.sla-green  { background: var(--badge-success-bg); color: var(--badge-success-fg); border-color: var(--badge-success-bg); }
.sla-yellow { background: var(--badge-warn-bg);  color: var(--badge-warn-fg); border-color: var(--badge-warn-bg); }
.sla-red    { background: var(--badge-danger-bg);   color: var(--badge-danger-fg); border-color: var(--badge-danger-bg); }

/* ── Badges de Estado y Prioridad (bandeja de tickets) ── */
.ticket-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 58px;
  max-width: 100%;
  padding: 3px 9px;
  border-radius: 999px;
  font-size: 0.74rem;
  font-weight: 600;
  white-space: nowrap;
  border: 1px solid transparent;
}
.tk-status-abierto    { background: var(--badge-info-bg);  color: var(--badge-info-fg); border-color: var(--badge-info-bg); }
.tk-status-tomado     { background: var(--badge-purple-bg); color: var(--badge-purple-fg); border-color: var(--badge-purple-bg); }
.tk-status-en_proceso { background: var(--badge-warn-bg);  color: var(--badge-warn-fg); border-color: var(--badge-warn-bg); }
.tk-status-escalado   { background: var(--badge-danger-bg);   color: var(--badge-danger-fg); border-color: var(--badge-danger-bg); }
.tk-status-resuelto   { background: var(--badge-success-bg);  color: var(--badge-success-fg); border-color: var(--badge-success-bg); }
.tk-status-cerrado    { background: var(--badge-neutral-bg); color: var(--badge-neutral-fg); border-color: var(--badge-neutral-bg); }

.tk-prio-baja    { background: var(--badge-success-bg);  color: var(--badge-success-fg); border-color: var(--badge-success-bg); }
.tk-prio-media   { background: var(--badge-info-bg);  color: var(--badge-info-fg); border-color: var(--badge-info-bg); }
.tk-prio-alta    { background: var(--badge-warn-bg);  color: var(--badge-warn-fg); border-color: var(--badge-warn-bg); }
.tk-prio-critica { background: var(--badge-danger-bg);   color: var(--badge-danger-fg); border-color: var(--badge-danger-bg); }

/* ── Menú desplegable de acciones (bandeja de tickets) ── */
/* ── Resolution status badges ───────────────────────────── */

.res-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 600;
  white-space: nowrap;
  border: 1px solid transparent;
}
.res-resuelto    { background: var(--badge-success-bg);  color: var(--badge-success-fg); border-color: var(--badge-success-bg); }
.res-no_resuelto { background: var(--badge-danger-bg);   color: var(--badge-danger-fg); border-color: var(--badge-danger-bg); }
.res-cancelado   { background: var(--badge-neutral-bg); color: var(--badge-neutral-fg); border-color: var(--badge-neutral-bg); }
.res-pausado     { background: var(--badge-warn-bg);  color: var(--badge-warn-fg); border-color: var(--badge-warn-bg); }
.res-sin_estado  { background: var(--badge-neutral-bg);  color: var(--badge-neutral-fg); border-color: var(--badge-neutral-bg); }

/* Tinted header cells for resolution outcome columns */
.res-col-resuelto    { color: var(--badge-success-fg); }
.res-col-no_resuelto { color: var(--badge-danger-fg); }
.res-col-cancelado   { color: var(--badge-neutral-fg); }
.res-col-pausado     { color: var(--badge-warn-fg); }

/* Truncated notes cell in trazabilidad */
.res-notes-cell {
  max-width: 220px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 0.8rem;
  color: var(--muted);
}

/* ── Monitor tab layout ─────────────────────────────────── */

.ticket-monitor-layout {
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* Allow dense tables (planes, trazabilidad) to scroll horizontally
   instead of squashing columns below readable width              */
.ticket-panel-scroll {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

.ticket-panel-scroll .contacts-table {
  min-width: 900px;
}

/* ── Responsive ─────────────────────────────────────────── */

@media (max-width: 1024px) {
  .ticket-grid,
  .ticket-toolbar {
    grid-template-columns: 1fr;
  }

  .ticket-tabs {
    flex-wrap: wrap;
  }
}

.btn-login:not(:disabled):hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 24px rgba(var(--brand-dark-rgb),0.55), 0 2px 6px rgba(var(--brand-dark-rgb),0.3);
}

.btn-login:not(:disabled):active {
  transform: translateY(0);
  box-shadow: 0 2px 8px rgba(var(--brand-dark-rgb),0.4);
}

.btn-login:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

/* enlaces debajo del botón */
.login-footer-links {
  text-align: center;
  margin-top: 16px;
}

.link-forgot {
  color: var(--muted);
  font-size: 0.8125rem;
  font-weight: 500;
  text-decoration: none;
  transition: color 0.2s ease;
}

.link-forgot:hover {
  color: var(--brand-dark);
  text-decoration: underline;
}

/* banner de éxito */
.success-banner {
  background: linear-gradient(135deg, rgba(16,185,129,0.08) 0%, rgba(5,150,105,0.05) 100%);
  border: 1px solid rgba(16,185,129,0.25);
  color: #059669;
  padding: 14px 16px;
  border-radius: 12px;
  font-size: 0.875rem;
  font-weight: 500;
  margin-bottom: 20px;
  display: flex;
  align-items: center;
  gap: 10px;
  animation: fadeInUp 0.25s ease;
}

/* banner de error */
.error-banner {
  background: linear-gradient(135deg, rgba(239,68,68,0.08) 0%, rgba(220,38,38,0.05) 100%);
  border: 1px solid rgba(239,68,68,0.25);
  color: #dc2626;
  padding: 14px 16px;
  border-radius: 12px;
  font-size: 0.875rem;
  font-weight: 500;
  margin-bottom: 20px;
  display: flex;
  align-items: center;
  gap: 10px;
  animation: fadeInUp 0.25s ease;
}

/* ============================================================
   HOME PAGE
   ============================================================ */
.home-container {
  min-height: 100vh;
  background: var(--bg);
  display: flex;
  flex-direction: column;
}

/* ---- Header ---- */

/* Subtle gradient accent line at bottom */


.app-logo-badge {
  width: 30px;
  height: 30px;
  border-radius: 8px;
  background: linear-gradient(135deg, #3b82f6 0%, #6366f1 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #ffffff;
  flex-shrink: 0;
  box-shadow: 0 2px 10px rgba(99, 102, 241, 0.45);
}

.app-title {
  font-size: 0.9375rem;
  font-weight: 700;
  color: #f1f5f9;
  letter-spacing: -0.02em;
}

.header-right {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* ---- Body layout (sidebar + main) ---- */
.home-layout {
  display: flex;
  flex: 1;
  min-height: 0;
}

/* ---- Sidebar ---- */
.home-sidebar {
  width: 232px;
  flex-shrink: 0;
  background: #0f172a;
  border-right: 1px solid rgba(255, 255, 255, 0.06);
  padding: 20px 12px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  overflow-y: auto;
  position: sticky;
  top: 64px;
  height: calc(100vh - 64px);
}

.home-sidebar-user {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px;
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.04);
  margin-bottom: 2px;
}

.home-sidebar-avatar {
  width: 36px;
  height: 36px;
  border-radius: 9px;
  background: linear-gradient(135deg, #3b82f6 0%, #6366f1 100%);
  color: #fff;
  font-size: 0.875rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  letter-spacing: 0;
}

.home-sidebar-user-info {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.home-sidebar-name {
  font-size: 0.8125rem;
  font-weight: 600;
  color: #e2e8f0;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.home-sidebar-role {
  font-size: 0.6875rem;
  color: var(--muted-2);
  font-weight: 500;
  white-space: nowrap;
}

.home-sidebar-sep {
  height: 1px;
  background: rgba(255, 255, 255, 0.06);
  margin: 10px 4px;
}

.home-sidebar-label {
  font-size: 0.6875rem;
  font-weight: 700;
  color: var(--muted-2);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  padding: 0 10px;
  margin-bottom: 4px;
}

.home-sidebar-nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.home-sidebar-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 9px;
  border: none;
  background: transparent;
  color: var(--muted-2);
  font-size: 0.8375rem;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
  text-align: left;
  width: 100%;
}

.home-sidebar-item:hover:not(.home-sidebar-item--maint) {
  background: rgba(255, 255, 255, 0.06);
  color: #93c5fd;
}

.home-sidebar-item--maint {
  opacity: 0.45;
  cursor: not-allowed;
}

.home-sidebar-item-icon {
  font-size: 1rem;
  flex-shrink: 0;
  line-height: 1;
  width: 20px;
  text-align: center;
}

.home-sidebar-item-name {
  flex: 1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.home-sidebar-item-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: #f59e0b;
  flex-shrink: 0;
}

.home-sidebar-empty {
  font-size: 0.8rem;
  color: var(--muted-2);
  padding: 8px 10px;
}

/* ---- Main ---- */
.app-main {
  flex: 1;
  padding: 36px 40px;
  min-width: 0;
  overflow-y: auto;
}

.module-main {
  --module-main-max-width: 1440px;
  --module-main-pad-x: clamp(20px, 2.2vw, 36px);
  --module-main-pad-y: clamp(24px, 2vw, 32px);
  width: min(100%, var(--module-main-max-width));
  margin: 0 auto;
  padding: var(--module-main-pad-y) var(--module-main-pad-x) !important;
}

.module-main > * {
  min-width: 0;
}

.module-main--compact {
  --module-main-max-width: 1280px;
}

.module-main--wide {
  --module-main-max-width: 1680px;
}

.module-main--xl {
  --module-main-max-width: 1920px;
}

/* El chat del asistente ya no reserva hueco al lado: desde que es una ventana centrada
   (`.asst-split`), el estado del objeto se ve en SU panel lateral, dentro del chat. Aquí
   vivían `--asst-ancho` y `.module-main--con-asistente`, que empujaban el contenido. */

@media (max-width: 860px) {
  .module-main {
    --module-main-pad-x: 16px;
    --module-main-pad-y: 20px;
  }
}

/* ---- Greeting inline (no box) ---- */
.home-welcome {
  margin-bottom: 32px;
  padding-top: 4px;
}

.home-welcome-title {
  font-size: 1.875rem;
  font-weight: 800;
  color: #f1f5f9;
  letter-spacing: -0.04em;
  margin-bottom: 6px;
  line-height: 1.15;
}

.home-welcome-sub {
  font-size: 0.875rem;
  color: var(--muted);
  font-weight: 400;
}

/* ---- Modules grid ---- */
.modules-heading {
  font-size: 0.6875rem;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin-bottom: 18px;
}

.empty-state {
  color: var(--muted);
  font-size: 0.9375rem;
  padding: 40px;
  text-align: center;
  background: var(--surface);
  border-radius: 16px;
  border: 2px dashed var(--border);
}

/* ---- Banner de la portada (imagen de fondo) ----
   Se enciende al poner una imagen en Identidad Visual; sin imagen no existe y la
   portada queda como antes. */
.home-banner {
  position: relative;
  overflow: hidden;
  /* Contexto de apilamiento propio: el velo y el degradado se quedan dentro y no
     compiten con nada de la página. */
  isolation: isolate;
  margin-bottom: 24px;
  height: var(--hb-h);
  border-radius: 18px;
  background-color: var(--surface-2);
  border: 1px solid var(--border-soft);
}

/* La altura va por variable y no con `height` directo porque el modo con el
   saludo dentro necesita el mismo valor como MÍNIMO: si el saludo y el buscador
   no cupieran, el banner crece en vez de recortarlos. */
.hb--h-s  { --hb-h: clamp(72px,  8vw,  104px); }
.hb--h-m  { --hb-h: clamp(104px, 12vw, 156px); }
.hb--h-l  { --hb-h: clamp(140px, 16vw, 210px); }
.hb--h-xl { --hb-h: clamp(180px, 21vw, 280px); }

.hb-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* `cover` + punto focal: la franja es ancha y baja, así que la foto SIEMPRE se
     recorta. Lo que se elige en Identidad Visual es qué parte sobrevive. */
  object-fit: cover;
  display: block;
  user-select: none;
}

/* El velo va en su propio elemento, no como opacidad de la imagen: así se puede
   oscurecer el fondo sin desvanecer la foto contra el color del panel. */
.hb-veil {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, var(--hb-dim, 0.4));
  pointer-events: none;
}

/* ---- Saludo dentro del banner ---- */
/* No cambia la altura: el contenido se coloca encima en posición absoluta. Con
   flujo normal, el saludo sumaría su alto y el banner crecería solo. */
.home-banner--overlay { height: var(--hb-h); }

/* Degradado de apoyo, aparte del velo. Sobre una foto clara el texto blanco
   desaparece, y no se puede depender del velo: es una decisión estética distinta
   y puede estar en 0. */
.home-banner--overlay::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 25%, rgba(0, 0, 0, 0.55));
  pointer-events: none;
}

.hb-slot {
  position: absolute;
  inset: clamp(14px, 2vw, 22px) clamp(16px, 2.4vw, 26px);
  z-index: 1;
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
}

/* Sobre la imagen el texto es blanco fijo en los DOS temas: lo que hay detrás es
   una foto, no una superficie del panel, así que `--text` no aplica. */
.home-banner--overlay .home-welcome { margin-bottom: 0; }

.home-banner--overlay .home-welcome-title {
  color: #fff;
  font-size: clamp(1.25rem, 2.4vw, 1.875rem);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
}

.home-banner--overlay .home-welcome-sub {
  color: rgba(255, 255, 255, 0.88);
  font-size: 0.8125rem;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
}

/* En el banner bajo no cabe la segunda línea sin apretar el saludo contra el
   borde. */
.hb--h-s.home-banner--overlay .home-welcome-sub { display: none; }

/* El buscador sobre la foto: translúcido con desenfoque, para que se lea encima
   de cualquier imagen sin tapar el fondo con una caja opaca. */
.home-banner--overlay .home-search-ico { color: rgba(255, 255, 255, 0.85); }

.home-banner--overlay .home-search-input {
  background: rgba(255, 255, 255, 0.16);
  border-color: rgba(255, 255, 255, 0.35);
  color: #fff;
  backdrop-filter: blur(8px);
}

.home-banner--overlay .home-search-input::placeholder { color: rgba(255, 255, 255, 0.75); }

.home-banner--overlay .home-search-input:focus {
  background: rgba(255, 255, 255, 0.26);
  border-color: rgba(255, 255, 255, 0.7);
  box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.18);
}

.home-banner--overlay .home-search-clear { color: rgba(255, 255, 255, 0.85); }
.home-banner--overlay .home-search-clear:hover {
  background: rgba(255, 255, 255, 0.2);
  color: #fff;
}

/* Saludo a la izquierda, buscador a la derecha. */
.home-topline {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 32px;
}

/* El margen inferior lo pone la fila; si lo dejara además el saludo, el buscador
   quedaría descolgado respecto al título. */
.home-topline .home-welcome { margin-bottom: 0; }

/* Misma píldora y misma lupa a la derecha que el buscador de los listados. */
.home-search {
  position: relative;
  display: flex;
  align-items: center;
  flex: 0 1 380px;
  min-width: 260px;
}

.home-search-ico {
  position: absolute;
  right: 14px;
  z-index: 1;
  display: flex;
  color: var(--muted-2);
  pointer-events: none;
}

.home-search-ico svg { width: 16px; height: 16px; display: block; }

/* Con texto escrito la lupa cede el sitio a la ×: comparten esquina. */
.home-search.is-filled .home-search-ico { display: none; }

.home-search-input {
  width: 100%;
  padding: 10px 40px 10px 18px;
  border-radius: 999px;
  border: 1px solid var(--control-border);
  background: var(--control-bg);
  color: var(--text);
  font-family: inherit;
  font-size: 0.875rem;
  outline: none;
  transition: background 0.15s, border-color 0.15s, box-shadow 0.15s;
}

.home-search-input::placeholder { color: var(--muted-2); }

.home-search-input:focus {
  background-color: var(--control-bg-hover);
  border-color: var(--brand);
  box-shadow: 0 0 0 3px rgba(var(--brand-rgb), 0.12);
}

.home-search-clear {
  position: absolute;
  right: 10px;
  z-index: 1;
  border: 0;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font-size: 1.05rem;
  line-height: 1;
  padding: 2px 6px;
  border-radius: 6px;
}

.home-search-clear:hover {
  background: var(--control-bg-hover);
  color: var(--text-strong);
}

/* Cabecera de la rejilla: título + controles de orden y vista. */
.modules-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 18px;
}

.modules-bar .modules-heading { margin-bottom: 0; }

.modules-tools {
  display: flex;
  align-items: center;
  gap: 10px;
}

/* Estos dos botones viven pegados al borde DERECHO del contenido, así que su
   menú se ancla por la derecha: con el anclaje por defecto (pensado para
   toolbars que empiezan a la izquierda) se salía de la pantalla. */
.modules-tools .ui-menu-pop { left: auto; right: 0; }

.modules-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 14px;
}

/* ---- Vistas de la rejilla (calcadas del explorador de archivos) ----
   Un solo marcado de tarjeta para las ocho: lo que cambia es la disposición. Así
   una tarjeta nueva no hay que escribirla ocho veces, y ninguna vista se queda
   sin un dato que las demás sí enseñan. */
.mg--xl { grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); }
.mg--m  { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }

.mg--xl .mod-icon { width: 84px; height: 84px; border-radius: 21px; font-size: 2.8rem; }
.mg--xl .mod-icon svg { width: 48px; height: 48px; }
.mg--xl .mod-name { font-size: 0.95rem; }

.mg--m .mod-card { padding: 20px 14px 16px; }
.mg--m .mod-icon { width: 46px; height: 46px; border-radius: 12px; font-size: 1.5rem; }
.mg--m .mod-icon svg { width: 26px; height: 26px; }
.mg--m .mod-name { font-size: 0.78rem; }
/* Medianos: la tarjeta es baja y estrecha, así que el panel de descripción se
   aprieta para que la mayoría de textos entren enteros. */
.mg--m .mod-desc { padding: 10px 12px 12px; font-size: 0.72rem; line-height: 1.38; }

/* Las cinco vistas en fila comparten esqueleto: icono a la izquierda, texto a la
   derecha, y sin el salto al pasar por encima (en una lista, un elemento que se
   levanta desalinea la fila entera). */
.mg--s .mod-card,
.mg--lista .mod-card,
.mg--detalles .mod-card,
.mg--mosaicos .mod-card,
.mg--contenido .mod-card {
  flex-direction: row;
  align-items: center;
  text-align: left;
  gap: 12px;
  border-radius: 12px;
  padding: 10px 14px;
}

.mg--s .mod-card--link:hover,
.mg--lista .mod-card--link:hover,
.mg--detalles .mod-card--link:hover,
.mg--mosaicos .mod-card--link:hover,
.mg--contenido .mod-card--link:hover { transform: none; }

.mg--s .mod-name,
.mg--lista .mod-name,
.mg--detalles .mod-name,
.mg--mosaicos .mod-name,
.mg--contenido .mod-name { text-align: left; }

.mg--s { grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: 8px; }
.mg--s .mod-icon { width: 28px; height: 28px; border-radius: 8px; font-size: 0.95rem; }
.mg--s .mod-icon svg { width: 17px; height: 17px; }

.mg--lista { grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); gap: 6px; }
.mg--lista .mod-card { padding: 7px 12px; }
.mg--lista .mod-icon { width: 22px; height: 22px; border-radius: 6px; font-size: 0.8rem; }
.mg--lista .mod-icon svg { width: 14px; height: 14px; }

/* Iconos pequeños y Lista solo enseñan el nombre: es justo el punto de esas dos
   vistas, ver muchos módulos de un vistazo. */
.mg--s .mod-desc,
.mg--lista .mod-desc { display: none; }

/* Detalles, Mosaicos y Contenido sacan la descripción del panel deslizante y la
   ponen en línea: si hay que pasar el ratón para leerla, no es un detalle. */
.mg--detalles .mod-desc,
.mg--mosaicos .mod-desc,
.mg--contenido .mod-desc {
  position: static;
  transform: none;
  background: none;
  border-radius: 0;
  padding: 0;
  max-height: none;
  overflow: visible;
  text-align: left;
  color: var(--muted);
  font-size: 0.75rem;
  line-height: 1.45;
}

.mg--detalles { grid-template-columns: 1fr; gap: 4px; }
.mg--detalles .mod-card { padding: 8px 14px; }
.mg--detalles .mod-icon { width: 26px; height: 26px; border-radius: 7px; font-size: 0.9rem; }
.mg--detalles .mod-icon svg { width: 16px; height: 16px; }
/* Nombre en columna fija: las descripciones arrancan alineadas, que es lo que
   hace legible una vista de detalles. */
.mg--detalles .mod-name { flex: 0 0 clamp(140px, 18vw, 230px); }
.mg--detalles .mod-desc { flex: 1 1 auto; }

.mg--mosaicos { grid-template-columns: repeat(auto-fill, minmax(310px, 1fr)); }
.mg--mosaicos .mod-card { padding: 12px 14px; align-items: flex-start; }
.mg--mosaicos .mod-icon { width: 44px; height: 44px; border-radius: 12px; font-size: 1.4rem; }
.mg--mosaicos .mod-icon svg { width: 25px; height: 25px; }

.mg--contenido { grid-template-columns: 1fr; gap: 8px; }
.mg--contenido .mod-card { padding: 14px 16px; align-items: flex-start; }
.mg--contenido .mod-icon { width: 52px; height: 52px; border-radius: 14px; font-size: 1.7rem; }
.mg--contenido .mod-icon svg { width: 30px; height: 30px; }
.mg--contenido .mod-name { font-size: 0.95rem; }

/* En Mosaicos y Contenido el nombre y la descripción se apilan a la derecha del
   icono. Se apoya en el orden del marcado (icono · nombre · chapa · descripción)
   colocando el texto con grid, en vez de envolverlo en otro div —que obligaría a
   un marcado distinto por vista. */
.mg--mosaicos .mod-card,
.mg--contenido .mod-card {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  column-gap: 14px;
  row-gap: 2px;
}

.mg--mosaicos .mod-icon,
.mg--contenido .mod-icon { grid-row: 1 / span 2; }

.mg--mosaicos .maint-badge,
.mg--contenido .maint-badge { grid-column: 2; justify-self: start; }

/* ---- Module card ---- */
.mod-card {
  position: relative;
  /* Tokens, NO rgba(255,255,255,·): sobre el fondo claro ese velo blanco dejaba la
     tarjeta prácticamente sin fondo, y obligaba a parchear `html.light-mode
     .mod-card` aparte (justo el patrón que prohíbe CLAUDE.md). */
  background: var(--surface);
  border-radius: 20px;
  border: 1px solid var(--border);
  padding: 28px 20px 22px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  overflow: hidden;
  transition: transform 0.22s cubic-bezier(0.4, 0, 0.2, 1),
              box-shadow 0.22s cubic-bezier(0.4, 0, 0.2, 1),
              border-color 0.22s ease;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.04), 0 4px 16px rgba(0, 0, 0, 0.04);
}

.mod-card--link {
  cursor: pointer;
}

.mod-card--link:hover {
  transform: translateY(-4px);
  box-shadow:
    0 2px 4px rgba(0, 0, 0, 0.04),
    0 12px 32px rgba(var(--brand-rgb), 0.12),
    0 4px 12px rgba(0, 0, 0, 0.06);
  border-color: rgba(var(--brand-rgb), 0.3);
}

.mod-card--maint {
  opacity: 0.55;
  cursor: default;
}

.mod-icon {
  font-size: 2rem;
  line-height: 1;
  width: 60px;
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(145deg, var(--brand) 0%, var(--brand-dark) 100%);
  border-radius: 15px;
  border: 1px solid rgba(var(--brand-rgb), 0.35);
  flex-shrink: 0;
  transition: transform 0.22s cubic-bezier(0.4, 0, 0.2, 1);
  /* Insignia SÓLIDA de marca (sigue al tema en claro y oscuro): un icono de
     iconset —monocromo, currentColor— sale blanco y legible encima; los emoji
     multicolor del fallback ignoran el color, que es lo que se quiere. */
  color: #fff;
}

/* Si un iconset aporta un SVG monocromo, se dimensiona acorde a la insignia
   (el emoji del fallback lo hace por `font-size`). */
.mod-icon svg {
  width: 34px;
  height: 34px;
  display: block;
}

.mod-card--link:hover .mod-icon {
  transform: scale(1.06);
}

.mod-name {
  font-size: 0.84rem;
  font-weight: 600;
  color: var(--text-strong);
  text-align: center;
  line-height: 1.35;
}

.maint-badge {
  font-size: 0.6875rem;
  font-weight: 600;
  color: var(--badge-warn-fg);
  background: var(--badge-warn-bg);
  border: 1px solid color-mix(in srgb, var(--badge-warn-fg) 30%, transparent);
  border-radius: 6px;
  padding: 2px 8px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* Description slides up from bottom on hover */
.mod-desc {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 16px 18px 18px;
  background: linear-gradient(160deg, var(--brand-dark) 0%, var(--brand) 100%);
  color: rgba(255, 255, 255, 0.92);
  font-size: 0.775rem;
  font-weight: 400;
  line-height: 1.55;
  text-align: center;
  /* +2px: sin ellos el borde superior del panel oculto asoma como una línea de
     marca en la base de la tarjeta (redondeo a subpíxel). */
  transform: translateY(calc(100% + 2px));
  transition: transform 0.26s cubic-bezier(0.4, 0, 0.2, 1);
  border-radius: 0 0 20px 20px;
}

.mod-card--link:hover .mod-desc {
  transform: translateY(0);
}

/* ============================================================
   CONTACTS PAGE (shared page shell)
   ============================================================ */
.page-container {
  min-height: 100vh;
  background: var(--bg);
  display: flex;
  flex-direction: column;
}

.page-header {
  background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
  padding: 0 32px;
  height: 64px;
  display: flex;
  align-items: center;
  gap: 20px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.2);
  position: sticky;
  top: 0;
  z-index: 100;
}

.btn-back {
  padding: 7px 14px;
  border-radius: 8px;
  font-size: 0.8125rem;
  font-weight: 600;
  font-family: inherit;
  background: rgba(255,255,255,0.08);
  color: #cbd5e1;
  border: 1px solid rgba(255,255,255,0.12);
  cursor: pointer;
  transition: all 0.2s ease;
}

.btn-back:hover {
  background: rgba(255,255,255,0.15);
  color: #f8fafc;
}

.page-header h1 {
  font-size: 1rem;
  font-weight: 700;
  color: #f8fafc;
}

.page-content {
  flex: 1;
  padding: 28px 32px;
  max-width: 1200px;
  width: 100%;
  margin: 0 auto;
}

/* ---- Search bar ---- */
.search-form {
  display: flex;
  gap: 10px;
  margin-bottom: 20px;
}

.search-input {
  flex: 1;
  padding: 11px 16px;
  border-radius: 10px;
  border: 1.5px solid var(--border);
  background: rgba(255, 255, 255, 0.06);
  font-size: 0.9375rem;
  font-family: inherit;
  color: var(--text);
  transition: border-color 0.2s, box-shadow 0.2s;
  box-shadow: var(--shadow-sm);
}

.search-input:focus {
  outline: none;
  border-color: var(--brand);
  box-shadow: 0 0 0 3px rgba(59,130,246,0.12);
}

.btn-search {
  padding: 11px 22px;
  border-radius: 10px;
  font-size: 0.875rem;
  font-weight: 600;
  font-family: inherit;
  background: var(--brand-dark);
  color: white;
  border: none;
  cursor: pointer;
  transition: background 0.2s;
}

.btn-search:hover:not(:disabled) { background: var(--brand-darker); }
.btn-search:disabled { opacity: 0.5; cursor: not-allowed; }

.btn-clear {
  padding: 11px 16px;
  border-radius: 10px;
  font-size: 0.8125rem;
  font-weight: 600;
  font-family: inherit;
  background: var(--surface);
  color: var(--muted);
  border: 1.5px solid var(--border);
  cursor: pointer;
  transition: all 0.2s;
}

.btn-clear:hover { background: var(--surface-2); color: var(--danger); border-color: var(--danger); }

/* ---- Result count ---- */
.result-count {
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--muted);
  margin-bottom: 12px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

/* ---- Table wrapper ---- */
.table-wrapper {
  background: #161b22;
  border-radius: 16px;
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}

.contacts-table {
  width: 100%;
  border-collapse: collapse;
}

.contacts-table th {
  background: rgba(255,255,255,0.04);
  padding: 12px 18px;
  text-align: left;
  font-size: 0.6875rem;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.contacts-table td {
  padding: 14px 18px;
  font-size: 0.875rem;
  color: var(--text);
  border-bottom: 1px solid rgba(255,255,255,0.06);
}

.contacts-table tbody tr:last-child td { border-bottom: none; }

.contact-row {
  cursor: pointer;
  transition: background 0.15s;
}

.contact-row:hover td { background: rgba(255,255,255,0.04); }

.row-blocked td { color: var(--muted); }
.row-blocked:hover td { background: var(--badge-danger-bg); }

.td-name {
  font-weight: 600;
  color: var(--text);
}

.td-center { text-align: center; }
.td-muted { color: var(--muted); font-size: 0.84rem; }

/* ---- Badges ---- */
.channel-badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 600;
  background: rgba(59,130,246,0.1);
  color: var(--brand-dark);
}

.status-badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 600;
}

.status-active {
  background: rgba(16,185,129,0.1);
  color: #059669;
}

.status-blocked {
  background: rgba(239,68,68,0.1);
  color: var(--danger);
}

/* ---- States ---- */
.loading-state {
  text-align: center;
  padding: 48px;
  color: var(--muted);
  font-size: 0.9375rem;
  background: var(--surface);
  border-radius: 16px;
  border: 1px solid var(--border);
}

.error-msg {
  color: var(--danger);
  font-size: 0.875rem;
  background: rgba(239,68,68,0.06);
  border: 1px solid rgba(239,68,68,0.2);
  border-radius: 10px;
  padding: 12px 16px;
  margin-bottom: 16px;
}

/* ---- Pagination ---- */
.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 20px;
}

.btn-page {
  padding: 8px 16px;
  border-radius: 8px;
  font-size: 0.8125rem;
  font-weight: 600;
  font-family: inherit;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  cursor: pointer;
  transition: all 0.2s ease;
}

.btn-page:hover:not(:disabled) {
  background: var(--brand-dark);
  color: white;
  border-color: var(--brand-dark);
}

.btn-page:disabled { opacity: 0.4; cursor: not-allowed; }

.page-info {
  font-size: 0.875rem;
  color: var(--muted);
  padding: 0 8px;
}

/* ---- Contact detail drawer ---- */
.drawer-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(15,23,42,0.45);
  z-index: 199;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.28s ease;
}

.drawer-backdrop.open {
  opacity: 1;
  pointer-events: all;
}

.contact-drawer {
  position: fixed;
  top: 0;
  right: 0;
  height: 100vh;
  width: 380px;
  background: var(--surface-overlay);
  box-shadow: -8px 0 40px rgba(0,0,0,0.14);
  z-index: 200;
  transform: translateX(100%);
  transition: transform 0.3s cubic-bezier(0.4,0,0.2,1);
  overflow-y: auto;
}

.contact-drawer.open { transform: translateX(0); }

.drawer-inner {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.drawer-top {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 28px 24px 24px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
}

.drawer-avatar {
  width: 56px;
  height: 56px;
  border-radius: 16px;
  background: linear-gradient(135deg, #1d4ed8 0%, #3b82f6 100%);
  color: white;
  font-size: 1.25rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  letter-spacing: 0.02em;
}

.drawer-avatar-pic {
  width: 56px;
  height: 56px;
  border-radius: 16px;
  object-fit: cover;
  flex-shrink: 0;
}

.drawer-identity {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.drawer-name {
  font-size: 1rem;
  font-weight: 700;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.drawer-close {
  padding: 6px 10px;
  border-radius: 8px;
  font-size: 0.9375rem;
  background: rgba(15,23,42,0.06);
  color: var(--muted);
  border: none;
  cursor: pointer;
  transition: all 0.15s;
  flex-shrink: 0;
  align-self: flex-start;
}

.drawer-close:hover { background: rgba(239,68,68,0.1); color: var(--danger); }

.drawer-body {
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 0;
}

.drawer-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 16px 0;
  border-bottom: 1px solid var(--border-soft);
}

.drawer-field:last-child { border-bottom: none; }

.field-label {
  font-size: 0.6875rem;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.07em;
}

.field-value {
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--text);
}

.field-id {
  font-family: 'Courier New', monospace;
  font-size: 0.75rem;
  color: var(--muted);
  word-break: break-all;
}

/* ============================================================
   USERS PAGE
   ============================================================ */

.users-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
}

.users-filterbar {
  align-items: end;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow-sm);
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 16px;
  padding: 14px;
}

.users-filter {
  display: flex;
  flex: 1 1 180px;
  flex-direction: column;
  gap: 5px;
  min-width: 160px;
}

.users-filter--text {
  flex-basis: 220px;
}

.users-filter label {
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.users-filter input,
.users-filter select {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-family: inherit;
  font-size: 0.84rem;
  min-height: 36px;
  padding: 8px 10px;
}

.users-filter input:focus,
.users-filter select:focus {
  background: var(--surface);
  border-color: var(--brand-dark);
  box-shadow: 0 0 0 3px rgba(59,130,246,0.12);
  outline: none;
}

.users-filter-reset {
  min-height: 36px;
}

.users-table-wrap {
  background: var(--surface);
  border-radius: 14px;
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  overflow-x: auto;
}

.users-table {
  width: 100%;
  border-collapse: collapse;
}

.users-table th {
  background: rgba(255,255,255,0.04);
  padding: 11px 14px;
  text-align: left;
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}

.users-table td {
  padding: 12px 14px;
  font-size: 0.875rem;
  color: var(--text);
  border-bottom: 1px solid rgba(255,255,255,0.06);
  vertical-align: middle;
}

.users-table tr:last-child td { border-bottom: none; }
.users-table tr:hover td { background: rgba(255,255,255,0.04); }
.users-table tr.row-blocked td { opacity: 0.6; }

.col-email { color: var(--muted); font-size: 0.8125rem; }
.col-date  { color: var(--muted); font-size: 0.8125rem; white-space: nowrap; }
.col-actions { white-space: nowrap; display: flex; gap: 5px; align-items: center; }

/* Badges — definición retirada. Era una de DOS declaraciones de `.badge` en este
   archivo (la otra estaba ~3400 líneas más abajo, con otra geometría). Esta
   escribía los colores en tonos de tema CLARO (#059669, #dc2626, #b45309) y la
   otra en tonos de OSCURO: cada módulo eligió un tema y el otro quedaba mal.
   Ahora todo sale de `--badge-*` → ver "BADGES / TAGS DE ESTADO" al final. */

/* Action buttons */
.btn-action {
  padding: 8px 16px;
  border-radius: 9px;
  font-size: 0.8125rem;
  font-weight: 600;
  font-family: inherit;
  border: none;
  cursor: pointer;
  transition: all 0.2s ease;
}

.btn-create  { background: var(--brand-dark); color: white; }
.btn-create:hover { background: var(--brand-darker); }

.btn-invite  { background: rgba(139,92,246,0.12); color: #7c3aed; border: 1px solid rgba(139,92,246,0.25); }
.btn-invite:hover { background: rgba(139,92,246,0.2); }

.btn-delete-confirm { background: var(--danger); color: white; }
.btn-delete-confirm:hover { background: #dc2626; }

/* Small action buttons in table rows */
.btn-sm {
  padding: 4px 10px;
  border-radius: 7px;
  font-size: 0.75rem;
  font-weight: 600;
  font-family: inherit;
  border: 1px solid transparent;
  cursor: pointer;
  transition: all 0.15s ease;
}

.btn-edit    { background: var(--control-bg); color: var(--text); border-color: var(--control-border); }
.btn-edit:hover { background: var(--control-bg-hover); }

/* .btn-block: color retirado (lo fija "BOTONES", variante peligro). */
.btn-block:hover { background: rgba(239,68,68,0.15); }

.btn-unblock { background: rgba(16,185,129,0.08); color: #059669; border-color: rgba(16,185,129,0.2); }
.btn-unblock:hover { background: rgba(16,185,129,0.15); }

.btn-perms   { background: rgba(var(--brand-rgb),0.08); color: var(--brand-darker); border-color: rgba(var(--brand-rgb),0.2); }
.btn-perms:hover { background: rgba(var(--brand-rgb),0.15); }

/* Color en "BOTONES" (variante peligro); aquí solo queda su tamaño propio. */
.btn-delete  { font-size: 0.85rem; padding: 4px 8px; }
.btn-delete:hover { background: rgba(239,68,68,0.18); }

.btn-cancel  { background: var(--control-bg); color: var(--muted); border-color: var(--control-border); }
.btn-cancel:hover { background: var(--control-bg-hover); color: var(--text); }

.btn-view    { background: rgba(99,102,241,0.08); color: #4f46e5; border-color: rgba(99,102,241,0.2); }
.btn-view:hover { background: rgba(99,102,241,0.16); }

/* ── Resultados de encuesta (drill-down canal → contacto → respuestas) ───────── */
/* max-height + overflow:hidden → el scroll vive SOLO en .survey-res-channels,
   no en toda la tarjeta (así el header y el resumen quedan fijos).
   Selector .modal-card.survey-res: gana en especificidad al overflow-y:auto de .modal-card. */
.modal-card.survey-res { max-height: 88vh; display: flex; flex-direction: column; overflow: hidden; padding: 18px 0 6px; }
.survey-res .kn-wizard-head { flex-wrap: wrap; gap: 8px; }

.survey-res-summary {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin: 4px 0 18px;
}
.survey-res-kpi {
  flex: 1 1 120px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 12px 10px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 12px;
}
.survey-res-kpi__n { font-size: 1.5rem; font-weight: 800; color: var(--brand); line-height: 1; }
.survey-res-kpi__l { font-size: 0.72rem; color: var(--muted); font-weight: 600; text-transform: uppercase; letter-spacing: .03em; }

/* El scroll vive en .survey-res-body (hijo directo estático de la tarjeta, flex item
   fiable). channels solo apila; así el header queda fijo y el cuerpo se desplaza. */
.survey-res-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.survey-res-channels { display: flex; flex-direction: column; gap: 10px; }

.survey-res-channel { border: 1px solid var(--border); border-radius: 12px; overflow: hidden; background: var(--surface); }
.survey-res-channel__head {
  width: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 13px 16px;
  background: var(--brand-soft-bg);
  border: none;
  cursor: pointer;
  font-family: inherit;
  text-align: left;
}
.survey-res-channel__head:hover { background: var(--brand-soft-bg); }
.survey-res-channel__name { font-weight: 700; color: var(--text-strong); font-size: 0.95rem; }
.survey-res-channel__meta { font-size: 0.78rem; color: var(--muted); white-space: nowrap; }

.survey-res-contacts { padding: 6px 10px 10px; display: flex; flex-direction: column; gap: 6px; }

.survey-res-contact { border: 1px solid var(--border); border-radius: 10px; overflow: hidden; }
.survey-res-contact__head {
  width: 100%;
  display: grid;
  grid-template-columns: 1fr auto auto auto;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  background: var(--surface);
  border: none;
  cursor: pointer;
  font-family: inherit;
  text-align: left;
}
.survey-res-contact__head:hover { background: var(--surface-2); }
.survey-res-contact__name { font-weight: 600; color: var(--text-strong); font-size: 0.88rem; }
.survey-res-contact__pct  { font-size: 0.78rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.survey-res-contact__date { font-size: 0.74rem; color: var(--muted-2); white-space: nowrap; }
.survey-res-contact__sub  { font-size: 0.78rem; color: var(--muted); margin: 0 0 8px; }

.survey-res-pill {
  font-size: 0.7rem;
  font-weight: 700;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--muted);
  white-space: nowrap;
}

.survey-res-answers { padding: 4px 14px 14px; background: var(--surface-2); border-top: 1px dashed var(--border); }
.survey-res-answer {
  display: grid;
  grid-template-columns: minmax(140px, 40%) 1fr;
  gap: 12px;
  padding: 7px 0;
  border-bottom: 1px solid var(--border-soft);
}
.survey-res-answer:last-child { border-bottom: none; }
.survey-res-answer__q { font-size: 0.82rem; color: var(--muted); font-weight: 600; }
.survey-res-answer__a { font-size: 0.86rem; color: var(--text-strong); font-weight: 600; word-break: break-word; }
.survey-res-empty { font-size: 0.82rem; color: var(--muted); margin: 4px 0; font-style: italic; }

/* Responsive: en móvil el modal ocupa casi toda la pantalla y los grids apilan */
@media (max-width: 640px) {
  .modal-card.modal-xl { max-width: 100%; }
  .modal-card.survey-res { max-height: 92vh; padding: 14px 0 6px; }
  .modal-card.survey-res > div:not(.modal-header):not(.modal-footer) { padding: 0 14px; }
  .survey-res-summary { gap: 8px; margin: 4px 0 12px; }
  .survey-res-kpi { flex: 1 1 calc(50% - 8px); padding: 10px 8px; }
  .survey-res-kpi__n { font-size: 1.25rem; }
  /* fila de contacto: nombre|pill arriba, %|fecha en la 2da línea */
  .survey-res-contact__head {
    grid-template-columns: 1fr auto;
    row-gap: 4px;
  }
  .survey-res-answer { grid-template-columns: 1fr; gap: 2px; }
}

/* Header nav */
.header-left { display: flex; align-items: center; gap: 16px; }


.header-back {
  color: var(--muted-2);
  font-size: 0.8125rem;
  font-weight: 500;
  text-decoration: none;
  transition: color 0.2s;
  padding: 6px 12px;
  border-radius: 8px;
  background: rgba(255,255,255,0.07);
  border: 1px solid rgba(255,255,255,0.1);
}
.header-back:hover { color: #f8fafc; background: rgba(255,255,255,0.13); }

/* Modals */
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(15,23,42,0.55);
  backdrop-filter: blur(4px);
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
}

.modal-card {
  background: var(--surface-overlay);
  border-radius: 20px;
  box-shadow: 0 25px 60px rgba(0,0,0,0.25);
  width: 100%;
  max-width: 480px;
  max-height: 90vh;
  overflow-y: auto;
  overflow-x: hidden;   /* nunca scroll horizontal: el contenido se ajusta en Y */
  animation: modalSlideIn 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes modalSlideIn {
  from { opacity: 0; transform: translateY(18px) scale(0.96); }
  to   { opacity: 1; transform: translateY(0)    scale(1);    }
}

/* ── Modal de error crítico (sesión expirada, fallo al iniciar, etc.) ── */
.crit-overlay {
  position: fixed;
  inset: 0;
  z-index: 3000;                 /* por encima de cualquier modal/drawer */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  background: var(--scrim);
  backdrop-filter: blur(4px);
}
.crit-modal {
  width: min(420px, 94vw);
  background: var(--surface-overlay);
  border: 1px solid var(--border);
  border-radius: 18px;
  box-shadow: var(--shadow-lg);
  padding: 28px 26px 24px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  animation: modalSlideIn 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.crit-img { width: 160px; max-width: 60%; height: auto; margin-bottom: 4px; }
.crit-title { font-size: 1.25rem; font-weight: 700; color: var(--text-strong); margin: 0; }
.crit-msg { font-size: 0.92rem; color: var(--muted); margin: 0; line-height: 1.5; white-space: pre-line; }
.crit-btn {
  margin-top: 8px;
  padding: 11px 22px;
  border: none;
  border-radius: 10px;
  background: var(--brand);
  color: #fff;
  font-size: 0.92rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: background 0.15s;
}
.crit-btn:hover { background: var(--brand-dark); }

/* ── Ruta inexistente (fallback del router: /docs y cualquier URL desconocida) ── */
.route-notfound {
  min-height: 70vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 12px;
  padding: 32px 20px;
}
.route-notfound-img { width: 160px; max-width: 55%; height: auto; margin-bottom: 4px; }
.route-notfound-title { font-size: 1.4rem; font-weight: 700; color: var(--text-strong); margin: 0; }
.route-notfound-msg { font-size: 0.95rem; color: var(--muted); margin: 0; max-width: 460px; line-height: 1.5; }
.route-notfound-btn {
  margin-top: 8px;
  padding: 11px 22px;
  border-radius: 10px;
  background: var(--brand);
  color: #fff;
  font-size: 0.92rem;
  font-weight: 600;
  text-decoration: none;
  transition: background 0.15s;
}
.route-notfound-btn:hover { background: var(--brand-dark); }

.modal-card.modal-wide { max-width: 640px; }
.modal-card.permissions-modal { max-width: min(1080px, 95vw); }
.modal-card.modal-sm   { max-width: 380px; padding: 28px; }

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px 24px 0;
  margin-bottom: 20px;
}

.modal-header h3 {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text);
}

.modal-close {
  background: none;
  border: none;
  font-size: 1.1rem;
  color: var(--muted);
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 6px;
  transition: all 0.15s;
}
.modal-close:hover { background: var(--control-bg-hover); color: var(--text); }

.modal-card form,
.modal-card > div:not(.modal-header):not(.modal-footer) {
  padding: 0 24px;
}

.modal-card .form-field { margin-bottom: 16px; }

.modal-card .form-field input:not([type="checkbox"]):not([type="radio"]),
.modal-card .form-field textarea,
.modal-card .form-field select {
  width: 100%;
  max-width: 100%;
  padding: 10px 14px;
  border-radius: 10px;
  border: 2px solid var(--border);
  font-size: 0.9rem;
  font-family: inherit;
  background: var(--surface-2);
  color: var(--text);
  transition: border-color 0.2s;
}
.modal-card .form-field input:not([type="checkbox"]):not([type="radio"]):focus,
.modal-card .form-field select:focus {
  outline: none;
  border-color: var(--brand-dark);
  background: var(--surface);
}

.modal-card .form-field label {
  display: block;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 6px;
}

.form-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; }

.form-check { margin: 4px 0 8px; }
.check-label {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  font-size: 0.82rem;
  color: var(--text);
  cursor: pointer;
  line-height: 1.4;
}
.check-label input[type="checkbox"] { margin-top: 2px; flex-shrink: 0; }

.modal-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  padding: 20px 24px;
  border-top: 1px solid var(--border);
  margin-top: 20px;
}

/* Permissions panel */
.perms-filterbar {
  display: flex;
  align-items: end;
  gap: 10px;
  flex-wrap: wrap;
  padding: 0 24px 14px;
}

.perms-filterbar--roles {
  padding: 0 0 14px;
}

.perms-filter {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 190px;
}

.perms-filter label {
  color: var(--muted);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.perms-filter select {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  font-family: inherit;
  font-size: 0.82rem;
  min-height: 34px;
  padding: 7px 34px 7px 10px;
}

.perms-filter select:focus {
  background: var(--surface);
  border-color: var(--brand-dark);
  box-shadow: 0 0 0 3px rgba(59,130,246,0.12);
  outline: none;
}

.perms-filter-reset {
  min-height: 34px;
}

.perms-scroll {
  max-height: 52vh;
  overflow-x: auto;
  overflow-y: auto;
  padding: 0 24px;
}

.perms-table {
  width: 100%;
  min-width: 920px;
  border-collapse: collapse;
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}

.perms-table th {
  background: rgba(255,255,255,0.04);
  border-bottom: 1px solid var(--border);
  color: var(--muted);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  padding: 9px 10px;
  text-align: left;
  text-transform: uppercase;
  white-space: nowrap;
}

.perms-table td {
  border-bottom: 1px solid rgba(255,255,255,0.06);
  color: var(--text);
  font-size: 0.78rem;
  padding: 9px 10px;
  vertical-align: middle;
}

.perms-table tr:last-child td { border-bottom: none; }
.perms-table tr:hover td { background: rgba(255,255,255,0.04); }
.perms-table tr.perm-granted td { background: rgba(16,185,129,0.035); }
/* Permiso restringido por whitelist de departamento y el depto seleccionado NO está */
.perms-table tr.perm-dept-filtered td { background: rgba(239,68,68,0.05); }
.perm-dept-lock { color: #b45309; font-size: 0.72rem; font-weight: 600; white-space: nowrap; }

.perm-module-cell {
  color: var(--muted);
  font-weight: 700;
  min-width: 180px;
}

.perm-module-chip {
  border-radius: 999px;
  display: inline-flex;
  font-size: 0.72rem;
  font-weight: 800;
  line-height: 1;
  padding: 6px 9px;
  white-space: nowrap;
}

.module-contacts { background: rgba(20,184,166,0.14); color: #0f766e; }
.module-users { background: rgba(99,102,241,0.14); color: #4338ca; }
.module-campaigns { background: rgba(245,158,11,0.16); color: #b45309; }
.module-support { background: rgba(14,165,233,0.14); color: #0369a1; }
.module-control { background: rgba(139,92,246,0.14); color: #6d28d9; }
.module-analytics { background: rgba(16,185,129,0.14); color: #047857; }
.module-security { background: rgba(239,68,68,0.13); color: #b91c1c; }
.module-billing { background: rgba(217,119,6,0.14); color: #92400e; }
.module-other { background: var(--bg); color: var(--muted); }

.perm-action-badge.action-view { background: rgba(59,130,246,0.12); color: #1d4ed8; }
.perm-action-badge.action-create { background: rgba(16,185,129,0.14); color: #047857; }
.perm-action-badge.action-edit { background: rgba(245,158,11,0.15); color: #b45309; }
.perm-action-badge.action-delete { background: rgba(239,68,68,0.12); color: #dc2626; }
.perm-action-badge.action-export { background: rgba(14,165,233,0.14); color: #0369a1; }
.perm-action-badge.action-manage { background: rgba(139,92,246,0.14); color: #6d28d9; }
.perm-action-badge.action-other { background: var(--surface-2); color: var(--text); }

.perm-action-badge {
  background: var(--surface-2);
  border-radius: 999px;
  color: var(--text);
  display: inline-flex;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1;
  padding: 6px 9px;
  white-space: nowrap;
}

.perm-id-cell {
  color: var(--text-strong);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.74rem !important;
  min-width: 230px;
  word-break: break-word;
}

.perm-description-cell {
  color: var(--muted) !important;
  max-width: 280px;
  min-width: 220px;
}

.perm-status {
  display: inline-flex;
  font-size: 0.75rem;
  font-weight: 700;
  white-space: nowrap;
}
.status-granted { color: #059669; }
.status-denied  { color: #cbd5e1; }

.perm-override-badge {
  display: inline-flex;
  font-size: 0.72rem;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: 999px;
  white-space: nowrap;
}

.override-yes {
  background: rgba(245,158,11,0.12);
  color: #b45309;
}

.override-no {
  background: rgba(239,68,68,0.10);
  color: #dc2626;
}

.perm-override-empty {
  color: var(--muted-2);
  font-size: 0.74rem;
  font-weight: 600;
}

.perm-action-cell { white-space: nowrap; }

/* ============================================================
   CONTROL CENTER
   ============================================================ */

.control-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  margin-bottom: 28px;
  overflow: visible;
  background: var(--surface-2);
  border-radius: 999px;
  padding: 5px;
  width: 100%;
  max-width: 100%;
}

.control-tab {
  appearance: none;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font-size: 0.8125rem;
  font-weight: 600;
  font-family: inherit;
  padding: 8px 18px;
  white-space: nowrap;
  transition: all 0.15s;
}

.control-tab:not(.active):hover {
  background: var(--control-bg-hover);
  color: var(--text);
}

/* global .active rule provides background+color — just ensure proper shape */
.control-tab.active {
  box-shadow: 0 1px 4px rgba(0,0,0,0.12) !important;
}

.control-tab:disabled {
  cursor: not-allowed;
  opacity: 0.4;
}

/* Centro de Control / Perfil — navegación de 2 niveles.
   N1 = grupos: .control-tabs (pill segmentado, look por defecto).
   N2 = subtabs: .cc-subtabs, aspecto ligero (texto + subrayado) para distinguirlo
   del grupo. Clases NUEVAS y aditivas: solo aplican donde se ponen; no tocan el
   .control-tabs que usan los pickers de modelo ni otras vistas. */
.cc-group-tabs { margin-bottom: 8px; }
.cc-subtabs { margin-bottom: 24px; }
/* El aspecto de `.cc-subtabs` (nivel 2) ya no se define aquí. Era el único nivel 2
   con look de subrayado: Perfil resolvía su nivel 2 con pastillas y Métricas con
   otra variante, así que dos módulos con la misma jerarquía se veían distintos.
   Ahora los dos niveles son pastilla y se distinguen por tamaño — ver el bloque
   "PESTAÑAS DE MÓDULO" al final del archivo. Lo que había aquí llevaba
   `background: none !important` en el estado activo y habría ganado a la regla
   unificada. */

.control-table .col-code {
  color: var(--muted);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.78rem;
}

.control-table .col-outputs {
  color: var(--muted);
  max-width: 320px;
}

.control-table .col-token {
  min-width: 160px;
  vertical-align: top;
}
.control-table .col-token .key-status-info {
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
  margin-bottom: 6px;
}

.badge-status {
  border-radius: 999px;
}

.badge-status-live {
  background: rgba(16,185,129,0.12);
  color: #059669;
}

.badge-status-test {
  background: rgba(245,158,11,0.14);
  color: #b45309;
}

.badge-status-off {
  background: rgba(148,163,184,0.18);
  color: var(--muted);
}

.output-section {
  margin-bottom: 4px;
}

.form-section-label {
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  margin: 0 0 8px;
  text-transform: uppercase;
}

.output-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(126px, 1fr));
  gap: 8px;
  margin: 0 0 20px;
}

.output-toggle {
  align-items: center;
  background: var(--surface-2);
  border: 1.5px solid var(--border);
  border-radius: 10px;
  color: var(--text);
  cursor: pointer;
  display: flex;
  font-size: 0.84rem;
  font-weight: 500;
  gap: 8px;
  min-height: 44px;
  padding: 8px 12px;
  transition: border-color 0.15s, background 0.15s, box-shadow 0.15s, color 0.15s;
  user-select: none;
}

.output-toggle:hover {
  background: var(--surface-2);
  border-color: var(--muted-2);
}

.output-toggle:has(input:checked) {
  background: var(--brand-soft-bg);
  border-color: #3b82f6;
  color: #1d4ed8;
  box-shadow: 0 0 0 3px rgba(59,130,246,0.1);
}

.output-toggle input[type="checkbox"] {
  accent-color: #3b82f6;
  cursor: pointer;
  flex-shrink: 0;
  height: 15px;
  width: 15px !important;
}

.output-toggle-icon {
  font-size: 1rem;
  line-height: 1;
  flex-shrink: 0;
}

.output-toggle-label {
  flex: 1;
}

.readonly-line {
  align-items: center;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  display: flex;
  gap: 12px;
  margin-bottom: 16px;
  padding: 10px 14px;
}

.readonly-info-pair {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.readonly-label {
  color: var(--muted);
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.readonly-line strong {
  color: var(--text);
  font-size: 0.84rem;
  font-weight: 600;
}

.control-form-panel {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow-sm);
  padding: 20px 24px 0;
}

.form-section {
  margin-bottom: 24px;
}

.form-section-title {
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text);
  margin: 0 0 16px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
}

/* Checkbox con etiqueta dentro de .form-field: `.form-field label` (block)
   pisa a `.check-label` (flex) por especificidad y el checkbox quedaba
   flotando en su propia línea. Restaurar el layout en línea. */
.form-field label.check-label {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
  font-weight: 600;
}

/* Límites → Bloqueo de loop concurrente: lista de estado por canal */
.ll-channel-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-width: 620px;
  margin-top: 8px;
}
.ll-channel-row {
  display: grid;
  grid-template-columns: minmax(180px, 1fr) 170px auto;
  gap: 12px;
  align-items: center;
  padding: 8px 14px;
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  border-radius: 10px;
}
.ll-channel-name {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.ll-channel-name > span:first-child {
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ll-channel-id {
  font-size: 0.72rem;
  color: var(--muted);
}
.control-form-panel .form-field select.ll-channel-select {
  width: 170px;
  padding: 7px 10px;
}
.ll-override-tag {
  font-size: 0.7rem;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--badge-info-bg);
  color: var(--badge-info-fg);
  white-space: nowrap;
}
@media (max-width: 560px) {
  .ll-channel-row { grid-template-columns: 1fr; gap: 6px; }
  .control-form-panel .form-field select.ll-channel-select { width: 100%; }
}

.control-form-panel .form-field input:not([type="checkbox"]):not([type="radio"]),
.control-form-panel .form-field textarea,
.control-form-panel .form-field select {
  width: 100%;
  padding: 10px 14px;
  border-radius: 10px;
  border: 2px solid var(--border);
  font-size: 0.9rem;
  font-family: inherit;
  background: var(--surface-2);
  color: var(--text);
  transition: border-color 0.2s;
}

.control-form-panel .form-field select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 16px;
  padding-right: 36px;
  cursor: pointer;
}

.control-form-panel .form-field input:not([type="checkbox"]):not([type="radio"]):focus,
.control-form-panel .form-field textarea:focus,
.control-form-panel .form-field select:focus {
  outline: none;
  border-color: var(--brand-dark);
  background: var(--surface);
}

.control-form-panel .form-field input:not([type="checkbox"]):not([type="radio"]):disabled,
.control-form-panel .form-field textarea:disabled,
.control-form-panel .form-field select:disabled {
  color: var(--muted);
  cursor: not-allowed;
}

.control-textarea {
  min-height: 150px;
  resize: vertical;
}

.control-textarea-tall {
  min-height: 220px;
}

.control-form-footer {
  margin-left: -24px;
  margin-right: -24px;
}

.control-save-state {
  color: #059669;
  font-size: 0.8rem;
  font-weight: 700;
}

/* ============================================================
   LLM panel
   ============================================================ */

.llm-key-field {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 16px;
}

.key-input-row {
  display: flex;
  gap: 8px;
  align-items: center;
}

.key-input-row input {
  flex: 1;
}

.key-set-badge {
  color: #059669;
  font-weight: 600;
  font-size: 0.85rem;
}

.key-unset-badge {
  color: var(--muted-2);
  font-weight: 500;
  font-size: 0.85rem;
}

.form-hint {
  display: block;
  margin-top: 4px;
  font-size: 0.75rem;
  color: var(--muted-2);
  line-height: 1.4;
}

.evidencia-tipos {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 8px;
  background: #1e293b;
  border-radius: 6px;
  flex-wrap: wrap;
}
.evidencia-label {
  font-size: 0.75rem;
  color: var(--muted-2);
  white-space: nowrap;
}

input[type="range"] {
  width: 100%;
  accent-color: var(--brand);
  cursor: pointer;
}

input[type="range"]:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.range-labels {
  display: flex;
  justify-content: space-between;
  font-size: 0.72rem;
  color: var(--muted-2);
  margin-top: 2px;
}

.range-val {
  font-weight: 700;
  color: var(--brand);
  font-variant-numeric: tabular-nums;
}

/* ── LLM panel extras ───────────────────────────────────── */

.fallback-checks {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 6px;
}

/* Fallback chips — hide native checkbox, use pill style */
.fallback-checks .check-label {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 5px 13px;
  border-radius: 20px;
  border: 1.5px solid var(--border);
  background: var(--surface-2);
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--muted);
  cursor: pointer;
  user-select: none;
  transition: all 0.15s;
  line-height: 1;
}

.fallback-checks .check-label input[type="checkbox"] {
  display: none;
}

.fallback-checks .check-label::before {
  content: '○';
  font-size: 0.75rem;
  opacity: 0.5;
  transition: all 0.15s;
}

.fallback-checks .check-label:has(input:checked) {
  background: rgba(59,130,246,0.08);
  border-color: var(--brand);
  color: var(--brand-dark);
  font-weight: 600;
}

.fallback-checks .check-label:has(input:checked)::before {
  content: '✓';
  opacity: 1;
}

.fallback-checks .check-label:hover:not(:has(input:disabled)) {
  border-color: var(--muted-2);
  color: var(--text);
}

.timeout-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  margin-top: 6px;
}

.timeout-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.timeout-label {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--muted);
}

.provider-model-tabs {
  display: flex;
  gap: 3px;
  margin-bottom: 14px;
  background: var(--surface-2);
  border-radius: 999px;
  padding: 4px;
  width: fit-content;
  flex-wrap: wrap;
}

.model-fields-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 16px;
}

.llm-keys-section {
  margin-top: 24px;
  padding: 16px 24px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
}

.llm-keys-title {
  margin: 0 0 4px;
  font-size: 0.9rem;
  font-weight: 700;
  color: var(--text-strong);
}

.llm-keys-grid {
  display: flex;
  flex-direction: column;
}

.llm-key-row .timeout-label {
  min-width: 148px;
  flex-shrink: 0;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text-strong);
}

/* ============================================================
   LLM Key Status badges
   ============================================================ */
.key-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 10px;
  border-radius: 12px;
  font-size: 0.72rem;
  font-weight: 600;
  white-space: nowrap;
}
.key-badge.valid       { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.key-badge.low-credits { background: var(--badge-warn-bg); color: var(--badge-warn-fg); }
.key-badge.invalid     { background: var(--badge-danger-bg); color: var(--badge-danger-fg); }
.key-badge.no-key      { background: var(--surface-2); color: var(--muted); }
.key-badge.error       { background: var(--badge-danger-bg); color: var(--badge-danger-fg); }
.key-badge.unknown     { background: var(--surface-2); color: var(--muted-2); }

.key-credits-info {
  font-size: 0.7rem;
  color: var(--muted);
  margin-left: 2px;
}
.key-error-hint {
  font-size: 0.68rem;
  color: #991b1b;
}
.key-checked-at {
  font-size: 0.65rem;
  color: var(--muted);
}

.btn-verify {
  padding: 5px 12px;
  font-size: 0.75rem;
  font-weight: 600;
  font-family: inherit;
  border-radius: 7px;
  border: 1.5px solid var(--border);
  background: var(--surface);
  color: var(--muted);
  cursor: pointer;
  transition: all 0.15s;
  white-space: nowrap;
}
.btn-verify:hover:not(:disabled) {
  border-color: var(--brand);
  color: var(--brand);
  background: rgba(59,130,246,0.05);
}
.btn-verify:disabled { opacity: 0.45; cursor: not-allowed; }

/* Un <a> con pinta de botón es inline: sin esto el relleno vertical no cuenta y
   queda descuadrado junto a un <button> hermano. Aplica a los enlaces-botón que
   navegan fuera del panel («Abrir chat», «Descargar QR»), que tienen que ser <a>
   para conservar clic central, «copiar enlace» y target=_blank. */
a.btn-verify,
a.btn-sm,
a.btn-action {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
}

/* ── Compartir un canal: enlace de chat + QR (Centro de Control → Canales) ── */
.cc-share-card { max-width: 420px; }

.cc-share-qr {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 200px;
  margin: 14px 0 4px;
  padding: 16px;
  /* EXCEPCIÓN intencional, igual que .totp-qr-container: fondo BLANCO fijo en
     ambos temas. Un QR se lee por contraste; sobre la superficie oscura del panel
     el lector falla. */
  background: #fff;
  border: 1.5px solid var(--border);
  border-radius: 14px;
}

.cc-share-qr-img { width: 174px; height: 174px; display: block; }

/* El mensaje de carga/error vive DENTRO de la caja blanca: color fijo oscuro,
   porque var(--text) sería casi invisible ahí en tema claro. */
.cc-share-qr-msg { margin: 0; font-size: 0.82rem; color: #475569; text-align: center; }

.cc-share-footer { flex-wrap: wrap; gap: 8px; }
.cc-share-open { margin-left: auto; }

/* Notification tabs (Plantillas | Historial) */
.notif-tab-nav {
  display: flex;
  gap: 4px;
  margin-bottom: 20px;
  border-bottom: 2px solid var(--border);
  padding-bottom: 0;
}
.notif-tab {
  padding: 8px 18px;
  font-size: 0.8125rem;
  font-weight: 600;
  font-family: inherit;
  border: none;
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  transition: color 0.15s, border-color 0.15s;
  border-radius: 6px 6px 0 0;
}
.notif-tab:hover { color: var(--brand); background: var(--brand-soft-bg); }
.notif-tab--active {
  color: var(--brand);
  border-bottom-color: var(--brand);
  background: rgba(59,130,246,0.07);
}

/* Notification log — filter bar */
.notif-log-filters {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 16px;
  padding: 14px 16px;
  background: var(--panel-1);
  border: 1px solid var(--border);
  border-radius: 10px;
}

/* Notification log — pagination */
.notif-log-pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 0 4px;
}

/* Variable chips — email template editor */
.var-chips-container {
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  margin-bottom: 14px;
}
.var-chips-label {
  display: block;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 8px;
}
.var-chips-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.var-chip {
  display: inline-flex;
  align-items: center;
  padding: 3px 9px;
  border-radius: 20px;
  font-size: 0.72rem;
  font-family: 'JetBrains Mono', Consolas, monospace;
  font-weight: 600;
  background: rgba(99,102,241,0.08);
  color: #4f46e5;
  border: 1.5px solid rgba(99,102,241,0.25);
  cursor: pointer;
  transition: all 0.12s;
  white-space: nowrap;
  line-height: 1;
}
.var-chip:hover {
  background: rgba(99,102,241,0.18);
  border-color: #4f46e5;
  transform: translateY(-1px);
}
/* form-label utility used in tpl create form */
.form-label {
  display: block;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--text-1);
  margin-bottom: 6px;
}

/* Input base GLOBAL — con tokens (tema claro/oscuro). Antes solo existía
   `.kn-wizard .form-input`, así que cualquier `.form-input` fuera del wizard
   (p. ej. los modales de edición dedicados) quedaba sin estilo → se veía roto /
   sin tema oscuro. `.kn-wizard .form-input` (más específico) sigue ganando donde
   aplica, así que no hay regresión en los wizards. */
.form-input {
  display: block;
  width: 100%;
  max-width: 100%;
  box-sizing: border-box;
  padding: 10px 14px;
  border-radius: 10px;
  border: 2px solid var(--border);
  background: var(--surface-2);
  color: var(--text);
  font-size: 0.9rem;
  font-family: inherit;
  outline: none;
  transition: border-color 0.18s, box-shadow 0.18s, background 0.18s;
}
.form-input:focus {
  border-color: var(--brand-dark);
  background: var(--surface);
  box-shadow: 0 0 0 3px rgba(99, 102, 241, .12);
}
.form-input::placeholder { color: var(--muted-2); }

.key-status-row {
  display: flex;
  align-items: center;
  gap: 16px;
  flex: 1;
  min-width: 0;
  padding: 11px 0;
  border-bottom: 1px solid var(--border-soft);
}

.key-status-info {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 10px;
  flex: 1;
  min-width: 0;
  flex-wrap: wrap;
}

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

.llm-key-row {
  display: flex;
  align-items: center;
  gap: 0;
}

.llm-key-row:last-child .key-status-row { border-bottom: none; }

/* ============================================================
   Auditoría
   ============================================================ */
.audit-filters {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px 20px;
  margin-bottom: 18px;
  box-shadow: var(--shadow-sm);
}
.audit-filter-row {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  align-items: flex-end;
}
.audit-filter-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 130px;
}
.audit-filter-field--wide  { min-width: 200px; flex: 1; }
.audit-filter-field--action { min-width: 100px; }
.audit-filter-field label {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.audit-filter-field input,
.audit-filter-field select {
  padding: 7px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 0.85rem;
  background: var(--panel);
  color: var(--text);
  outline: none;
}
.audit-filter-field input:focus,
.audit-filter-field select:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 2px rgba(59,130,246,0.15);
}

.audit-table-wrap {
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: auto;
  box-shadow: var(--shadow-sm);
  margin-bottom: 18px;
}
.audit-loading {
  padding: 40px;
  text-align: center;
  color: var(--muted);
  font-size: 0.9rem;
}
.audit-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.83rem;
}
.audit-table thead tr {
  background: var(--panel-2);
  border-bottom: 1px solid var(--border);
}
.audit-table th {
  padding: 10px 14px;
  font-weight: 600;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  text-align: left;
  white-space: nowrap;
}
.audit-table td { padding: 9px 14px; border-bottom: 1px solid var(--border); vertical-align: top; }
.audit-table tbody tr:last-child td { border-bottom: none; }
.audit-table tbody tr:hover td { background: rgba(59,130,246,0.03); }

.audit-cell--dt   { white-space: nowrap; color: var(--muted); font-size: 0.8rem; }
.audit-cell--user { min-width: 160px; }
.audit-cell--action { max-width: 380px; font-size: 0.84rem; }
.audit-cell--resource { color: var(--muted); font-size: 0.8rem; white-space: nowrap; }
.audit-cell--ip   { color: var(--muted); font-size: 0.78rem; white-space: nowrap; }
.audit-cell--result { white-space: nowrap; }
.audit-cell--toggle { white-space: nowrap; }

.audit-user-name  { display: block; font-weight: 500; }
.audit-user-email { display: block; font-size: 0.76rem; color: var(--muted); }

/* Celda de acción en tres líneas: qué se hizo · sobre qué objeto · qué cambió.
   El objetivo y el resumen son el snapshot legible que graba core/audit_diff.py;
   las filas anteriores a esa función simplemente no los pintan. */
.audit-action-name    { display: block; font-weight: 500; }
.audit-action-target  { display: block; font-size: 0.78rem; color: var(--text); }
.audit-change-summary {
  display: block;
  font-size: 0.76rem;
  color: var(--muted);
  line-height: 1.35;
  margin-top: 2px;
}

.audit-action {
  font-family: 'Fira Code', 'Cascadia Code', monospace;
  font-size: 0.78rem;
  background: var(--panel-2);
  border-radius: 4px;
  padding: 1px 6px;
  color: #1e40af;
  word-break: break-all;
}

.audit-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px 10px;
  border-radius: 12px;
  font-size: 0.72rem;
  font-weight: 600;
}
.audit-badge--ok     { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.audit-badge--denied { background: var(--badge-warn-bg); color: var(--badge-warn-fg); }
.audit-badge--error  { background: var(--badge-danger-bg); color: var(--badge-danger-fg); }

.audit-error-detail {
  display: block;
  font-size: 0.72rem;
  color: var(--danger);
  margin-top: 2px;
  cursor: help;
}

.audit-toggle-btn {
  background: none;
  border: 1px solid var(--border);
  border-radius: 5px;
  padding: 3px 8px;
  font-size: 0.75rem;
  color: var(--muted);
  cursor: pointer;
  white-space: nowrap;
}
.audit-toggle-btn:hover { background: var(--panel-2); color: var(--text); }

.audit-row--expanded > td { background: rgba(59,130,246,0.04); }
.audit-row-detail > td {
  background: var(--panel-2);
  padding: 0 14px 12px;
  border-bottom: 1px solid var(--border);
}
.audit-cell--module { white-space: nowrap; }

.audit-module-tag {
  display: inline-block;
  font-family: 'Fira Code', 'Cascadia Code', monospace;
  font-size: 0.72rem;
  background: #ede9fe;
  color: #5b21b6;
  border: 1px solid #c4b5fd;
  border-radius: 4px;
  padding: 2px 7px;
  white-space: nowrap;
}

.audit-detail-content {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 10px 0 4px;
}

.audit-detail-section {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.audit-detail-label {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}

.audit-detail-label--error { color: #991b1b; }

.audit-changes-pre {
  font-size: 0.78rem;
  font-family: 'Fira Code', 'Cascadia Code', monospace;
  white-space: pre-wrap;
  word-break: break-all;
  color: var(--text);
  margin: 0;
  padding: 10px 12px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  max-height: 300px;
  overflow-y: auto;
}

.audit-error-pre {
  background: var(--surface)5f5;
  border-color: #fecaca;
  color: #7f1d1d;
}

.audit-pagination {
  display: flex;
  align-items: center;
  gap: 14px;
  justify-content: center;
  padding: 12px 0 4px;
}
.audit-page-info {
  font-size: 0.84rem;
  color: var(--muted);
}

/* ============================================================
   Metrics module
   ============================================================ */

.metrics-toolbar {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  flex-wrap: wrap;
  padding: 16px 40px 0;
}

.metrics-header-controls {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.metrics-period-select {
  appearance: none;
  -webkit-appearance: none;
  background: rgba(255,255,255,0.1);
  color: #f1f5f9;
  border: 1px solid rgba(255,255,255,0.2);
  border-radius: 8px;
  padding: 7px 30px 7px 12px;
  font-size: 0.85rem;
  font-family: inherit;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23f1f5f9' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 12px;
  transition: border-color 0.2s;
}
.metrics-period-select:focus { outline: none; border-color: rgba(255,255,255,0.5); }
.metrics-period-select option { background: #1e293b; color: #f1f5f9; }

.metrics-refresh-btn {
  padding: 7px 12px;
  font-size: 1rem;
  min-width: 36px;
  background: rgba(255,255,255,0.1);
  border: 1px solid rgba(255,255,255,0.2);
  color: #f1f5f9;
  border-radius: 8px;
  cursor: pointer;
  font-family: inherit;
  transition: background 0.15s;
}
.metrics-refresh-btn:hover { background: rgba(255,255,255,0.18); }

/* ── Main tab nav (pill-group) ── */
.metrics-tabs {
  display: flex;
  gap: 3px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 5px;
  width: fit-content;
  margin: 8px 40px 0;
}

.metrics-tab {
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--muted-2);
  padding: 8px 20px;
  font-size: 0.85rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.metrics-tab:hover { color: var(--text-strong); }
.metrics-tab.active {
  background: var(--brand-dark) !important;
  color: #fff !important;
  box-shadow: 0 1px 4px rgba(0,0,0,0.14);
}

/* align app-main below the pill tab row */
.metrics-tabs ~ .app-main { padding-top: 20px; }

/* ── KPI grid ── */
.metrics-kpi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
  gap: 12px;
  margin-bottom: 24px;
}

.metrics-kpi-card {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--border);
  border-left: 3px solid var(--kpi-accent, var(--brand));
  border-radius: 10px;
  padding: 18px 16px;
  box-shadow: var(--shadow-sm);
}

.metrics-kpi-value {
  font-size: 1.7rem;
  font-weight: 700;
  color: #e2e8f0;
  line-height: 1;
  margin-bottom: 6px;
}

.metrics-kpi-label {
  font-size: 0.75rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-weight: 600;
}

/* ── Charts grid ── */
.metrics-charts-grid {
  display: grid;
  /* auto-fit (no auto-fill): colapsa las columnas vacías y estira los gráficos
     presentes para llenar todo el ancho, proporcional a la tabla de abajo. */
  grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
  gap: 16px;
  margin-bottom: 24px;
}

.metrics-charts-grid--2col {
  grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
}

.metrics-chart-card {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 18px 16px;
  box-shadow: var(--shadow-sm);
}

.metrics-chart-card--full { grid-column: 1 / -1; }
.metrics-chart-card--sm   { min-width: 200px; }

.metrics-chart-title {
  font-size: 0.8rem;
  font-weight: 700;
  color: #e2e8f0;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 14px;
}

.metrics-chart-container { min-height: 200px; }

.metrics-section-title {
  font-size: 0.8rem;
  font-weight: 700;
  color: var(--text-strong);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin: 16px 0 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border-soft);
}

.metrics-loading {
  text-align: center;
  padding: 48px 24px;
  color: var(--muted);
  font-size: 0.95rem;
}

.metrics-empty {
  color: var(--muted);
  font-size: 0.88rem;
  padding: 32px 16px;
  text-align: center;
}

/* ── Barras de cobertura de guías (Uso del Panel › Guías) ── */
.metrics-cov-list { display: flex; flex-direction: column; gap: 14px; padding: 6px 2px; }
.metrics-cov-row { display: flex; flex-direction: column; gap: 6px; }
.metrics-cov-head { display: flex; justify-content: space-between; align-items: baseline; font-size: 13px; }
.metrics-cov-label { font-weight: 600; color: var(--text-strong); }
.metrics-cov-val { font-variant-numeric: tabular-nums; color: var(--muted); font-weight: 600; }
.metrics-cov-track { height: 12px; background: var(--surface-2); border-radius: 999px; overflow: hidden; }
.metrics-cov-fill {
  height: 100%;
  background: linear-gradient(90deg, #7c6af7, #60a5fa);
  border-radius: 999px;
  transition: width 0.4s ease;
  min-width: 2px;
}

/* ── Agent sub-tabs (pill-group) ── */
.metrics-agent-tabs {
  display: flex;
  gap: 3px;
  background: var(--surface-2);
  border-radius: 999px;
  padding: 5px;
  width: fit-content;
  margin-bottom: 20px;
  border-bottom: none;
}

.metrics-subtab {
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--muted);
  padding: 7px 16px;
  font-size: 0.8125rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.metrics-subtab:hover { color: var(--text-strong); }
.metrics-subtab.active {
  background: var(--brand-dark) !important;
  color: #fff !important;
  box-shadow: 0 1px 4px rgba(0,0,0,0.14);
}

/* ── Light controls for Investment Tab ── */
.metrics-select-light {
  appearance: none;
  -webkit-appearance: none;
  background-color: var(--control-bg);
  color: var(--text);
  border: 1px solid var(--control-border);
  border-radius: 8px;
  padding: 7px 32px 7px 12px;
  font-size: 0.85rem;
  font-family: inherit;
  font-weight: 500;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  background-size: 12px;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
  box-shadow: var(--shadow-sm);
}
.metrics-select-light:focus {
  outline: none;
  border-color: #3b82f6;
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
}
.metrics-select-light option {
  background: var(--surface);
  color: var(--text);
}

.metrics-input-light {
  background: var(--control-bg);
  color: var(--text);
  border: 1px solid var(--control-border);
  border-radius: 8px;
  padding: 6px 12px;
  font-size: 0.85rem;
  font-family: inherit;
  font-weight: 500;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
.metrics-input-light:focus {
  outline: none;
  border-color: #3b82f6;
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15);
}


/* ============================================================
   LIVECHAT MODULE
   ============================================================ */

/* Badge variants (--modifier on base .badge) */

/* Page header meta (conversation count) */
.page-header-meta {
  font-size: 0.8125rem;
  color: var(--muted);
  font-weight: 500;
  margin-left: auto;
}

/* ── 3-column layout ─────────────────────────────────────── */
.livechat-page {
  height: 100vh;
  overflow: hidden;
}

.livechat-page .page-header {
  flex-shrink: 0;
}

.livechat-layout {
  display: grid;
  grid-template-columns: 320px 1fr 300px;
  height: calc(100vh - 60px);
  overflow: hidden;
  background: var(--bg);
}

/* ── Bandeja (izquierda) ─────────────────────────────────── */
.livechat-sidebar {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border-right: 1px solid var(--border-soft);
  overflow: hidden;
}

.livechat-filters {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px 16px;
  border-bottom: 1px solid rgba(255,255,255,0.08);
  flex-shrink: 0;
}

.filter-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

/* Búsqueda de conversaciones (nombre / user_id) */
.lc-search {
  position: relative;
  display: flex;
  align-items: center;
}
.lc-search-icon {
  position: absolute;
  left: 10px;
  font-size: 0.8rem;
  opacity: 0.7;
  pointer-events: none;
}
.lc-search-input {
  width: 100%;
  padding: 8px 30px 8px 30px;
  border: 1px solid var(--control-border);
  border-radius: 8px;
  background: var(--control-bg);
  color: var(--text);
  font-size: 0.85rem;
  outline: none;
}
.lc-search-input::placeholder { color: var(--muted-2); }
.lc-search-input:focus {
  border-color: var(--brand);
  background: var(--control-bg-hover);
}
.lc-search-clear {
  position: absolute;
  right: 8px;
  border: none;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font-size: 0.8rem;
  line-height: 1;
  padding: 4px;
  border-radius: 6px;
}
.lc-search-clear:hover { color: var(--text); background: var(--control-bg-hover); }

.livechat-filters select {
  width: 100%;
  padding: 9px 30px 9px 12px;
  border-radius: 8px;
  border: 1px solid rgba(255,255,255,0.12);
  background: rgba(255,255,255,0.07);
  color: #cbd5e1;
  font-size: 0.78rem;
  font-family: inherit;
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  outline: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 10px center;
  background-size: 10px;
}

.livechat-filters select:focus {
  border-color: rgba(99,179,237,0.5);
  background-color: rgba(255,255,255,0.1);
}

.livechat-filters select option { background: #1e293b; }

.filter-channel-select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E") !important;
}

.filter-pills {
  display: flex;
  gap: 6px;
}

.filter-pill {
  flex: 1;
  padding: 8px 10px;
  border-radius: 20px;
  border: 1px solid rgba(255,255,255,0.12);
  background: rgba(255,255,255,0.05);
  color: var(--muted-2);
  font-size: 0.75rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: all 0.15s;
  text-align: center;
}

.filter-pill:hover {
  background: rgba(255,255,255,0.1);
  color: #e2e8f0;
}

/* Color en el bloque "CHIPS INTERACTIVOS" del final. Los tres !important que había
   aquí no competían con nada: la clase es `filter-pill--active`, no `.active`, así
   que no la alcanzaba la regla global. Solo servían para impedir que el canónico
   la gobernara. */

.conversation-list {
  list-style: none;
  overflow-y: auto;
  flex: 1;
  padding: 8px;
}

.conversation-list::-webkit-scrollbar { width: 4px; }
.conversation-list::-webkit-scrollbar-track { background: transparent; }
.conversation-list::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.12); border-radius: 2px; }

.conv-item {
  padding: 12px 14px;
  border-radius: 10px;
  cursor: pointer;
  transition: background 0.15s ease;
  margin-bottom: 4px;
}

.conv-item:hover {
  background: rgba(255,255,255,0.06);
}

.conv-item--selected {
  background: rgba(59,130,246,0.18) !important;
  border: 1px solid rgba(59,130,246,0.3);
}

.conv-item-header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
}

.conv-channel-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  border-radius: 8px;
  background: #475569;
  flex-shrink: 0;
  overflow: hidden;
}

.conv-channel-icon {
  width: 30px;
  height: 30px;
  display: block;
  object-fit: cover;
}

.conv-contact-pic {
  width: 30px;
  height: 30px;
  display: block;
  object-fit: cover;
  border-radius: 50%;
}

/* Per-channel brand colors (fallback when img fails) */
.conv-channel-badge--wa   { background: #25D366; }
.conv-channel-badge--wapi { background: #1DAA61; }
.conv-channel-badge--ig   { background: linear-gradient(135deg, #833AB4, #E1306C, #F77737); }
.conv-channel-badge--tg   { background: #229ED9; }
.conv-channel-badge--fb   { background: #0084FF; }
.conv-channel-badge--tt   { background: #111; }
.conv-channel-badge--web  { background: #3b5bdb; }
.conv-channel-badge--other { background: #475569; }

/* Channel type cell in config table */
.ch-type-cell {
  align-items: center;
  display: flex;
  gap: 8px;
}

.ch-type-label {
  color: var(--text);
  font-size: 0.78rem;
  font-weight: 500;
  white-space: nowrap;
}

.conv-title {
  flex: 1;
  font-size: 0.8125rem;
  font-weight: 600;
  color: #e2e8f0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.conv-item-meta {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 6px;
}

.conv-last-msg {
  font-size: 0.75rem;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
  max-width: 180px;
}

.conv-time {
  font-size: 0.7rem;
  color: var(--muted);
  white-space: nowrap;
  flex-shrink: 0;
}

.conv-assigned {
  font-size: 0.7rem;
  color: #22c55e;
  margin-top: 2px;
  font-weight: 500;
}

/* Sidebar pagination */
.livechat-sidebar .pagination {
  padding: 8px 12px;
  border-top: 1px solid rgba(255,255,255,0.06);
  flex-shrink: 0;
  justify-content: space-between;
}

.livechat-sidebar .pagination button {
  padding: 5px 10px;
  border-radius: 7px;
  font-size: 0.75rem;
  font-weight: 600;
  font-family: inherit;
  background: rgba(255,255,255,0.07);
  color: var(--muted-2);
  border: 1px solid rgba(255,255,255,0.1);
  cursor: pointer;
  transition: all 0.15s;
}

.livechat-sidebar .pagination button:hover:not(:disabled) {
  background: rgba(255,255,255,0.13);
  color: #e2e8f0;
}

.livechat-sidebar .pagination button:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

.livechat-sidebar .pagination span {
  font-size: 0.75rem;
  color: var(--muted);
}

.livechat-sidebar .loading-row,
.livechat-sidebar .error-banner {
  margin: 6px;
  padding: 8px 12px;
  font-size: 0.8rem;
  border-radius: 8px;
}

.livechat-sidebar .loading-row {
  color: var(--muted);
  text-align: center;
  padding: 20px;
}

/* ── Historial de mensajes (centro) ──────────────────────── */
.livechat-messages {
  display: flex;
  flex-direction: column;
  background: #0f172a;
  border-right: 1px solid var(--border);
  overflow: hidden;
}

.livechat-empty {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-size: 0.9375rem;
  font-weight: 500;
  background: var(--bg);
}

.messages-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 24px;
  border-bottom: 1px solid var(--border);
  background: #0f172a;
  flex-shrink: 0;
  gap: 12px;
  flex-wrap: wrap;
}

.messages-header-id {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

.messages-header-id strong {
  font-size: 0.8125rem;
  font-weight: 700;
  color: var(--text);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.action-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.action-error {
  font-size: 0.78rem;
  color: var(--danger);
  font-weight: 500;
  max-width: 200px;
}

/* Livechat action buttons */
.btn-action--pause {
  padding: 6px 14px;
  border-radius: 8px;
  font-size: 0.8125rem;
  font-weight: 600;
  font-family: inherit;
  border: none;
  cursor: pointer;
  transition: all 0.15s ease;
  background: rgba(245,158,11,0.12);
  color: #b45309;
  border: 1px solid rgba(245,158,11,0.3);
}
.btn-action--pause:hover:not(:disabled) { background: rgba(245,158,11,0.2); }

.btn-action--resume {
  padding: 6px 14px;
  border-radius: 8px;
  font-size: 0.8125rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: all 0.15s ease;
  background: rgba(16,185,129,0.12);
  color: #059669;
  border: 1px solid rgba(16,185,129,0.3);
}
.btn-action--resume:hover:not(:disabled) { background: rgba(16,185,129,0.2); }

.btn-action--assign {
  padding: 6px 14px;
  border-radius: 8px;
  font-size: 0.8125rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: all 0.15s ease;
  background: rgba(59,130,246,0.1);
  color: #1d4ed8;
  border: 1px solid rgba(59,130,246,0.25);
}
.btn-action--assign:hover:not(:disabled) { background: rgba(59,130,246,0.18); }

.btn-action--unassign {
  padding: 6px 14px;
  border-radius: 8px;
  font-size: 0.8125rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: all 0.15s ease;
  background: var(--surface-2);
  color: var(--muted);
  border: 1px solid var(--border);
}
.btn-action--unassign:hover:not(:disabled) { background: var(--control-bg-hover); color: var(--text); }

.btn-action--resolve {
  padding: 6px 14px;
  border-radius: 8px;
  font-size: 0.8125rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: all 0.15s ease;
  background: rgba(139,92,246,0.1);
  color: #7c3aed;
  border: 1px solid rgba(139,92,246,0.25);
}
.btn-action--resolve:hover:not(:disabled) { background: rgba(139,92,246,0.18); }

.btn-action--send {
  padding: 6px 18px;
  border-radius: 8px;
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.15s ease;
  background: var(--brand-dark);
  color: #fff;
  border: none;
  white-space: nowrap;
  align-self: flex-end;
}
.btn-action--send:hover:not(:disabled) { background: var(--brand-darker); }

.btn-action--pause:disabled,
.btn-action--resume:disabled,
.btn-action--assign:disabled,
.btn-action--unassign:disabled,
.btn-action--resolve:disabled,
.btn-action--send:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Reply box */
.reply-box {
  flex-shrink: 0;
  border-top: 1px solid var(--border);
  background: #0f172a;
  padding: 16px 20px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.reply-input-row {
  display: flex;
  gap: 10px;
  align-items: flex-end;
}

.reply-textarea {
  flex: 1;
  min-height: 72px;
  max-height: 160px;
  resize: vertical;
  border: 1px solid rgba(255,255,255,0.15);
  border-radius: 10px;
  padding: 10px 14px;
  font-size: 0.85rem;
  font-family: inherit;
  line-height: 1.5;
  color: #e2e8f0;
  background: rgba(255,255,255,0.07);
  outline: none;
  transition: border-color 0.15s, background 0.15s;
}
.reply-textarea:focus { border-color: rgba(99,179,237,0.5); background: rgba(255,255,255,0.1); }
.reply-textarea::placeholder { color: var(--muted); }

.reply-error {
  margin: 0;
  font-size: 0.8rem;
}

.reply-ia-notice {
  flex-shrink: 0;
  border-top: 1px solid var(--border);
  background: var(--surface)beb;
  color: #92400e;
  font-size: 0.85rem;
  font-weight: 500;
  padding: 12px 16px;
  text-align: center;
}
.reply-ia-notice--warn {
  background: var(--badge-danger-bg);
  color: #991b1b;
  border-top-color: #fecaca;
}

/* Messages list */
.messages-list {
  flex: 1;
  overflow-y: auto;
  padding: 20px 28px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  background: var(--surface-2);
}

.messages-list::-webkit-scrollbar { width: 5px; }
.messages-list::-webkit-scrollbar-track { background: transparent; }
.messages-list::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 3px; }

/* Bubbles */
.msg-bubble {
  max-width: 72%;
  padding: 12px 16px;
  border-radius: 16px;
  word-break: break-word;
}

.msg-bubble--user {
  align-self: flex-end;
  background: var(--badge-info-bg);
  border: 1px solid rgba(59,130,246,0.25);
  border-bottom-right-radius: 4px;
}

.msg-bubble--agent {
  align-self: flex-start;
  background: var(--surface);
  border: 1px solid var(--border);
  border-bottom-left-radius: 4px;
  box-shadow: var(--shadow-sm);
}

.msg-bubble--operator {
  align-self: flex-start;
  background: var(--badge-success-bg);
  border: 1px solid rgba(34,197,94,0.25);
  border-bottom-left-radius: 4px;
}

.msg-bubble--system {
  align-self: center;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 5px 14px;
  max-width: 90%;
}

.msg-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}

.msg-sender {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--muted);
}

.msg-bubble--user .msg-sender { color: var(--badge-info-fg); }
.msg-bubble--operator .msg-sender { color: var(--badge-success-fg); }
.msg-bubble--system .msg-sender { display: none; }

.msg-time {
  font-size: 0.68rem;
  color: var(--muted-2);
  margin-left: auto;
}

.msg-text {
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--text);
  white-space: pre-wrap;
}

.msg-bubble--system .msg-text {
  font-size: 0.78rem;
  color: var(--muted);
  text-align: center;
}

.msg-empty {
  color: var(--muted-2) !important;
  font-style: italic;
}

.msg-media-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--brand-dark);
  text-decoration: none;
  font-size: 0.875rem;
  font-weight: 500;
}
.msg-media-link:hover { text-decoration: underline; }

/* ── Rich media bubbles ─────────────────────────────────────── */
.msg-media-block {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.msg-media-img {
  max-width: 280px;
  max-height: 280px;
  border-radius: 10px;
  object-fit: cover;
  display: block;
  cursor: pointer;
  transition: opacity 0.15s;
}
.msg-media-img:hover { opacity: 0.88; }

.msg-media-sticker {
  max-width: 140px;
  max-height: 140px;
  object-fit: contain;
  display: block;
}

.msg-media-video {
  max-width: 300px;
  border-radius: 10px;
  display: block;
  background: #000;
}

.msg-media-audio {
  width: 260px;
  max-width: 100%;
  height: 36px;
  accent-color: var(--brand);
}

.msg-media-doc {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  border-radius: 8px;
  background: rgba(0,0,0,0.05);
  color: var(--brand-dark);
  text-decoration: none;
  font-size: 0.875rem;
  font-weight: 500;
  max-width: 260px;
}
.msg-media-doc:hover { background: rgba(0,0,0,0.1); }
.msg-media-doc-icon { font-size: 1.2rem; flex-shrink: 0; }
.msg-media-doc-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.msg-media-caption {
  margin-top: 2px;
  font-size: 0.825rem;
  color: var(--text);
}

.msg-location {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.msg-location-link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--brand-dark);
  font-size: 0.875rem;
  font-weight: 600;
  text-decoration: none;
  background: rgba(59,130,246,0.1);
  padding: 5px 10px;
  border-radius: 6px;
}
.msg-location-link:hover { background: rgba(59,130,246,0.18); }
.msg-location-addr {
  font-size: 0.78rem;
  color: var(--muted);
}

/* ── Ficha del contacto (derecha) ───────────────────────── */
.livechat-contact-panel {
  display: flex;
  flex-direction: column;
  background: #0f172a;
  overflow-y: auto;
  padding: 20px;
}

.livechat-contact-panel::-webkit-scrollbar { width: 4px; }
.livechat-contact-panel::-webkit-scrollbar-track { background: transparent; }
.livechat-contact-panel::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 2px; }

.contact-empty {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-size: 0.875rem;
  font-weight: 500;
  text-align: center;
  padding: 24px;
}

.contact-card {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 20px;
  box-shadow: var(--shadow-sm);
  display: flex;
  flex-direction: column;
  gap: 14px;
}

.contact-name {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text);
  margin-bottom: 4px;
}

.contact-field {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.contact-label {
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--muted-2);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.contact-value {
  font-size: 0.8375rem;
  color: var(--text);
  font-weight: 500;
  word-break: break-all;
}

.contact-card .badge {
  align-self: flex-start;
}

.contact-profile-pic {
  width: 76px;
  height: 76px;
  border-radius: 50%;
  object-fit: cover;
  align-self: center;
  border: 2px solid var(--border);
}

.contact-card-header {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 6px;
}

.contact-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.contact-section-title {
  font-size: 0.65rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  padding: 10px 0 4px;
  border-bottom: 1px solid var(--border);
  margin-top: 6px;
}

.contact-empty { color: var(--text-muted, #9ca3af); font-style: italic; font-size: 0.8rem; }
.contact-yes   { color: #16a34a; font-weight: 600; }
.contact-no    { color: var(--text); }

/* ── Drawer full-detail extra classes ───────────────────────── */

.drawer-section-title {
  font-size: 0.6rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--accent);
  padding: 10px 0 2px;
  border-bottom: 1px solid var(--border);
  margin-top: 4px;
}

.field-empty { color: var(--text-muted, #9ca3af); font-style: italic; }
.field-yes   { color: #16a34a; font-weight: 600; }
.field-no    { color: var(--text); }

.drawer-loading {
  padding: 12px 0;
  color: var(--text-muted, #9ca3af);
  font-size: 0.875rem;
}

.drawer-error {
  padding: 8px;
  color: #dc2626;
  background: var(--badge-danger-bg);
  border-radius: 6px;
  font-size: 0.8rem;
  margin: 8px 0;
}

/* ── Agent JSON response rendering ──────────────────────────── */
.agent-response {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.agent-thought {
  background: rgba(0,0,0,0.04);
  border: 1px solid rgba(0,0,0,0.08);
  border-radius: 8px;
  padding: 6px 10px;
  font-size: 0.82rem;
  color: var(--muted);
}

.agent-thought summary.agent-thought-label {
  cursor: pointer;
  font-weight: 600;
  font-size: 0.78rem;
  color: var(--muted-2);
  user-select: none;
  list-style: none;
  padding: 2px 0;
}

.agent-thought summary.agent-thought-label::-webkit-details-marker {
  display: none;
}

.agent-thought[open] summary.agent-thought-label {
  margin-bottom: 6px;
  color: var(--muted);
}

.agent-thought .msg-text {
  font-size: 0.8rem;
  color: var(--muted);
  font-style: italic;
  margin: 2px 0;
}

.agent-user-parts {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.agent-user-parts .msg-text {
  margin: 0;
}

/* Metadatos del agente por mensaje: tarea + etapa embudo */
.msg-agent-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-top: 2px;
}

.msg-flag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 0.72rem;
  font-weight: 600;
  padding: 2px 8px;
  border-radius: 10px;
  white-space: nowrap;
}

.msg-flag--task {
  background: rgba(245, 158, 11, 0.12);
  color: #b45309;
  border: 1px solid rgba(245, 158, 11, 0.3);
}

.msg-flag--done {
  background: rgba(34, 197, 94, 0.12);
  color: #15803d;
  border: 1px solid rgba(34, 197, 94, 0.3);
}

.msg-flag--embudo {
  background: rgba(99, 102, 241, 0.10);
  color: #4f46e5;
  border: 1px solid rgba(99, 102, 241, 0.25);
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: default;
}

/* ============================================================
   Base de Conocimiento (Centro de Control)
   ============================================================ */

.kn-toolbar { flex-wrap: wrap; gap: 10px; }
.kn-filters { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.kn-search {
  padding: 7px 10px; border: 1px solid var(--control-border); border-radius: 8px;
  font-size: 0.85rem; min-width: 180px;
}
.kn-select {
  padding: 7px 10px; border: 1px solid var(--control-border); border-radius: 8px;
  font-size: 0.85rem; background: var(--surface); color: var(--text);
}

/* Badges de tipo */
.kn-tipo-badge {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 0.74rem; font-weight: 600; padding: 3px 9px;
  border-radius: 10px; white-space: nowrap;
}
.kn-tipo-informacion_basica      { background: rgba(59,130,246,.12); color:#1d4ed8; border:1px solid rgba(59,130,246,.3); }
.kn-tipo-instrucciones           { background: rgba(14,165,233,.12); color:#0369a1; border:1px solid rgba(14,165,233,.3); }
.kn-tipo-promociones             { background: rgba(236,72,153,.12); color:#be185d; border:1px solid rgba(236,72,153,.3); }
.kn-tipo-informacion_corporativa { background: rgba(100,116,139,.12); color: var(--text-strong); border:1px solid rgba(100,116,139,.3); }
.kn-tipo-reglas                  { background: rgba(34,197,94,.12); color:#15803d; border:1px solid rgba(34,197,94,.3); }
.kn-tipo-restricciones           { background: rgba(239,68,68,.12); color:#b91c1c; border:1px solid rgba(239,68,68,.3); }

/* Chips de canal */
.kn-chip {
  display: inline-block; font-size: 0.72rem; padding: 2px 8px; margin: 1px 2px;
  border-radius: 10px; background: rgba(99,102,241,.1); color:#4f46e5;
  border: 1px solid rgba(99,102,241,.25);
}
.kn-chip-all { background: rgba(34,197,94,.1); color:#15803d; border-color: rgba(34,197,94,.25); }
.kn-td-chips { max-width: 200px; }
.kn-td-tema { font-weight: 600; max-width: 260px; }
.kn-td-updated { font-size: 0.78rem; color: var(--muted); }

.kn-row-expired td { opacity: 0.75; }
.kn-badge-expired {
  display:inline-block; margin-left:5px; font-size:0.7rem; font-weight:700;
  padding:2px 7px; border-radius:8px; background:rgba(239,68,68,.12);
  color:#b91c1c; border:1px solid rgba(239,68,68,.3);
}
.kn-badge-hidden {
  display:inline-block; margin-left:5px; font-size:0.7rem; font-weight:600;
  padding:2px 7px; border-radius:8px; background:rgba(245,158,11,.12);
  color:#b45309; border:1px solid rgba(245,158,11,.3);
}
/* .btn-danger: regla retirada. Era una TERCERA declaración de la misma clase (hay
   otra con la geometría más abajo) y clavaba #b91c1c, un rojo de tema claro. El
   color lo fija ahora el bloque "BOTONES" del final. */

/* ── Wizard ── */
.kn-wizard {
  max-width: 720px; width: 95%; max-height: 92vh;
  overflow-y: auto; padding: 24px 28px;
}
.kn-wizard-head { display:flex; justify-content:space-between; align-items:center; margin-bottom:14px; }
.kn-wizard-body { min-height: 280px; }

/* Campos del wizard */
.kn-form-step { display:flex; flex-direction:column; gap:0; width:100%; }
.kn-form-group { display:flex; flex-direction:column; gap:6px; margin-bottom:20px; }
.kn-form-group:last-child { margin-bottom:4px; }

/* Campo multimedia: lista de archivos (varios) + subir/añadir */
.kn-media { display:flex; flex-direction:column; gap:10px; }
.kn-media-row { display:flex; gap:8px; flex-wrap:wrap; align-items:center; }
.kn-media-list { display:flex; flex-direction:column; gap:10px; }
.kn-media-item {
  display:flex; flex-direction:column; gap:6px;
  padding:10px; border:1px solid var(--border-soft); border-radius:8px;
  background:var(--surface-2);
}
.kn-media-item-row { display:flex; gap:6px; align-items:center; }
.kn-media-item-row .form-input { flex:1; }
.kn-media-del { color:var(--badge-danger-fg, #ef4444); }
.kn-media-newurl { flex:1; min-width:160px; }
.kn-media-upload { cursor:pointer; display:inline-flex; align-items:center; }
.kn-media-upload.is-busy { opacity:0.6; pointer-events:none; }
.kn-media-required {
  display:flex; align-items:center; gap:6px;
  font-size:0.8rem; color:var(--muted); cursor:pointer; user-select:none;
}
.kn-media-required input { width:15px; height:15px; cursor:pointer; }
.kn-media-msg { font-size:0.8rem; color:var(--muted); }
.kn-media-ok  { font-size:0.82rem; color:var(--badge-success-fg, #22c55e); font-weight:600; }
.kn-media-err { font-size:0.82rem; color:var(--badge-danger-fg, #ef4444); font-weight:600; }

/* ── Multimedia del agente (Personalidad → stickers / galería) ── */
.pm-media-panel { margin-top:24px; padding-top:20px; border-top:1px solid var(--border); }
.pm-media-panel-head {
  display:flex; align-items:flex-start; justify-content:space-between; gap:12px; margin-bottom:16px;
}
.pm-media-panel-sub { display:block; margin-top:2px; font-size:0.8rem; color:var(--muted); }
.pm-media-section {
  padding:14px 18px; margin-bottom:18px; border-radius:0 8px 8px 0;
  background:var(--surface-2);
}
.pm-media-head { display:flex; align-items:center; justify-content:space-between; margin-bottom:4px; }
.pm-media-title { font-size:11px; font-weight:700; letter-spacing:0.1em; text-transform:uppercase; }
.pm-media-count { font-size:12px; color:var(--muted); font-variant-numeric:tabular-nums; }
.pm-media-sub { margin:0 0 12px; font-size:12px; color:var(--muted); }
.pm-media-grid {
  display:grid; grid-template-columns:repeat(auto-fill, minmax(320px, 1fr)); gap:12px;
}
.pm-media-item {
  display:flex; gap:10px; padding:10px; border-radius:8px;
  background:var(--surface); border:1px solid var(--border);
}
.pm-media-preview {
  flex:0 0 64px; width:64px; height:64px; border-radius:6px; overflow:hidden;
  display:flex; align-items:center; justify-content:center;
  background:var(--control-bg); border:1px solid var(--border);
}
.pm-media-img { width:100%; height:100%; object-fit:cover; }
.pm-media-ph { font-size:22px; color:var(--muted); }
.pm-media-fields { flex:1; display:flex; flex-direction:column; gap:6px; min-width:0; }
.pm-media-row1 { display:flex; gap:6px; align-items:center; }
.pm-media-row1 .form-input { flex:1; min-width:0; }
.pm-media-url { font-family:monospace; font-size:12px; }
.pm-media-del { color:var(--badge-danger-fg, #ef4444); flex:0 0 auto; }
.pm-media-add { display:flex; gap:8px; flex-wrap:wrap; align-items:center; margin-top:12px; }
.pm-media-upload { cursor:pointer; display:inline-flex; align-items:center; }
.pm-media-upload.is-busy { opacity:0.6; pointer-events:none; }
.pm-media-newurl { flex:1; min-width:180px; }
.pm-media-msg { margin-top:8px; font-size:0.8rem; color:var(--muted); }
.pm-media-savebar { display:flex; justify-content:flex-end; margin-top:8px; }

/* ── Whitelist de modo test (Canales) ── */
.tw-section {
  margin-top:16px; padding:14px 16px; border-radius:8px;
  background:var(--surface-2); border-left:3px solid var(--brand);
}
.tw-head { display:flex; align-items:center; justify-content:space-between; margin-bottom:4px; }
.tw-title { font-size:11px; font-weight:700; letter-spacing:0.1em; text-transform:uppercase; color:var(--brand); }
.tw-sub { margin:0 0 12px; font-size:12px; color:var(--muted); line-height:1.5; }
.tw-chips { display:flex; flex-wrap:wrap; gap:6px; margin-bottom:12px; min-height:26px; }
.tw-empty { font-size:12px; color:var(--muted); }
.tw-chip {
  display:inline-flex; align-items:center; gap:6px; padding:4px 8px;
  border-radius:14px; font-size:12px; font-family:monospace;
  background:var(--badge-info-bg); color:var(--badge-info-fg);
}
.tw-chip-x { border:0; background:transparent; color:inherit; cursor:pointer; font-size:12px; line-height:1; padding:0; }
.tw-add { display:flex; gap:8px; align-items:center; margin-bottom:10px; }
.tw-add .form-input { flex:1; min-width:0; }
.tw-picker { display:flex; flex-direction:column; gap:6px; }
.tw-picker-list {
  display:flex; flex-wrap:wrap; gap:6px; max-height:140px; overflow-y:auto;
  padding:2px;
}
.tw-picker-item {
  border:1px solid var(--border); background:var(--control-bg); color:var(--text);
  border-radius:14px; padding:4px 10px; font-size:12px; cursor:pointer;
}
.tw-picker-item:hover { background:var(--control-bg-hover); }
.tw-savebar { display:flex; justify-content:flex-end; align-items:center; gap:10px; margin-top:12px; }
/* Aviso de whitelist editada y no guardada: su guardado es independiente del form
   del canal, así que sin este recordatorio se pierde al cerrar el modal. */
.tw-dirty { font-size:12px; color:var(--badge-warn-fg); }

.kn-wizard .form-label {
  display:flex; align-items:center; gap:4px;
  font-size:0.83rem; font-weight:600; color: var(--text-strong);
}
.kn-wizard .form-input {
  display:block; width:100%; padding:10px 14px;
  border-radius:10px; border:2px solid var(--border);
  background: var(--surface-2); font-size:0.9rem; font-family:inherit;
  color: var(--text-strong); transition: border-color 0.18s, box-shadow 0.18s, background 0.18s;
  box-sizing:border-box; outline:none;
}
.kn-wizard .form-input:focus {
  border-color:#4f46e5; background: var(--surface);
  box-shadow: 0 0 0 3px rgba(99,102,241,.12);
}
.kn-wizard .form-input::placeholder { color: var(--muted-2); font-size:0.86rem; }

.kn-textarea-sm { min-height: 90px; resize: vertical; line-height:1.55; }
.kn-textarea-md { min-height: 120px; resize: vertical; line-height:1.55; }
.kn-textarea-lg { min-height: 260px; resize: vertical; font-family:inherit; line-height:1.6; }

.kn-stepper {
  display:flex; gap: 4px; margin-bottom: 20px; flex-wrap: wrap;
}
.kn-step {
  display:flex; align-items:center; gap:6px; padding:5px 10px;
  border-radius: 14px; font-size: 0.76rem; color: var(--muted-2);
}
.kn-step-dot {
  display:inline-flex; align-items:center; justify-content:center;
  width: 20px; height: 20px; border-radius:50%;
  background: var(--control-bg-hover); color: var(--muted); font-size:0.72rem; font-weight:700;
  flex-shrink:0;
}
.kn-step.active { color:#4f46e5; font-weight:600; background: rgba(99,102,241,.08); }
.kn-step.active .kn-step-dot { background:#4f46e5; color:#fff; }
.kn-step.done .kn-step-dot { background:#22c55e; color:#fff; }
.kn-step.done { color:#15803d; }

.kn-step-question { font-weight:600; color: var(--text); margin: 4px 0 14px; }

/* Cards de tipo (paso 1) */
.kn-tipo-cards {
  display:grid; grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 10px;
}
.kn-tipo-card {
  display:flex; flex-direction:column; align-items:flex-start; gap:4px;
  padding: 13px 14px; border: 2px solid var(--border); border-radius: 12px;
  background: rgba(255,255,255,0.04); cursor:pointer; text-align:left; transition: border-color .15s, box-shadow .15s;
  width:100%; box-sizing:border-box;
}
.kn-tipo-card:hover { border-color:#818cf8; background: rgba(255,255,255,0.08); }
/* Fondo y borde en el bloque TARJETAS (variante seleccionada). Aquí queda el halo,
   derivado de la marca en vez del índigo fijo que llevaba. */
.kn-tipo-card.selected { box-shadow: 0 0 0 3px rgba(var(--brand-rgb), 0.15); }
.kn-tipo-card-icon { font-size: 1.5rem; }

/* Canal chips — selector de canales en wizard de tareas */
.kn-channel-chips { display:flex; flex-wrap:wrap; gap:8px; margin-top:6px; }
.kn-channel-chip {
  padding: 5px 14px; border-radius: 20px;
  border: 1.5px solid var(--border); cursor: pointer;
  font-size: 0.82rem; color: var(--muted); background: var(--surface-2);
  font-weight: 500; transition: border-color 0.15s, background 0.15s, color 0.15s;
}
.kn-channel-chip:hover { border-color: #a5b4fc; background: var(--surface-2); color: #4f46e5; }
.kn-channel-chip.active {
  border-color: #4f46e5; background: rgba(99,102,241,.08);
  color: #4f46e5; font-weight: 700;
  box-shadow: 0 0 0 2px rgba(99,102,241,.15);
}
.kn-tipo-card-label { font-weight:700; color: var(--text-strong); font-size:0.88rem; }
.kn-tipo-card-desc { font-size:0.74rem; color: var(--muted); line-height:1.35; }

/* Tooltips de ayuda */
/* `.kn-help` retirado: era un TERCER mecanismo de tooltip —un icono "?" con
   `title` nativo— que duplicaba `InfoTooltip` con peor aspecto (burbuja del
   sistema operativo, con retardo, sin tokens). Sus 7 usos se migraron a
   <InfoTooltip/>. No confundir con `.kn-help-text`, que son párrafos de ayuda
   VISIBLE y siguen en uso. */
.kn-hint-warn { margin-top:10px; padding:8px 12px; border-radius:8px; font-size:0.8rem; color:#92400e; background:rgba(245,158,11,.08); border:1px solid rgba(245,158,11,.25); }

/* ── Asistente de canal Telegram ─────────────────────────────────────────── */
.tg-help { display:block; margin-top:6px; font-size:0.78rem; color: var(--muted); line-height:1.4; }
.kn-warn { margin-top:10px; padding:8px 12px; border-radius:8px; font-size:0.8rem; color:#92400e; background:rgba(245,158,11,.10); border:1px solid rgba(245,158,11,.30); }
.kn-ok { margin-top:10px; padding:8px 12px; border-radius:8px; font-size:0.8rem; color:#065f46; background:rgba(16,185,129,.10); border:1px solid rgba(16,185,129,.30); }

/* Reemplazo de credenciales (solo owner) en el modal de edición de canal */
.cc-creds {
  margin-top: 18px;
  padding: 16px;
  border: 1px solid rgba(239, 68, 68, 0.25);
  border-radius: 12px;
  background: rgba(239, 68, 68, 0.04);
}
.cc-creds-head { display: flex; flex-direction: column; gap: 4px; margin-bottom: 12px; }
.cc-creds-title { font-weight: 700; color: var(--text); font-size: 0.92rem; }
.cc-creds-sub { color: var(--muted); font-size: 0.8rem; line-height: 1.4; }
.cc-masked { color: var(--muted); letter-spacing: 1px; }
.cc-creds-msg {
  margin-top: 10px;
  padding: 8px 12px;
  border-radius: 8px;
  font-size: 0.82rem;
  color: var(--brand-dark);
  background: rgba(59, 130, 246, 0.08);
  border: 1px solid rgba(59, 130, 246, 0.25);
}
.cc-creds-actions { margin-top: 12px; display: flex; justify-content: flex-end; }
.tg-cta { padding:18px; border:1px dashed #38bdf8; border-radius:12px; background:rgba(56,189,248,.06); text-align:center; }
.tg-cta-title { margin:0 0 6px; font-weight:700; color:#0369a1; }
.tg-cta-text { margin:0 0 14px; font-size:0.85rem; color: var(--muted); line-height:1.5; }
.tg-url { display:block; margin-top:6px; padding:8px 10px; border-radius:8px; background:#0f172a; color:#7dd3fc; font-family:ui-monospace,SFMono-Regular,Menlo,monospace; font-size:0.78rem; word-break:break-all; }
.tg-secret-row { display:flex; gap:8px; align-items:center; }
.tg-secret-row input { flex:1; }
.tg-review { list-style:none; margin:8px 0; padding:0; }
.tg-review li { padding:6px 0; border-bottom:1px solid var(--border); font-size:0.85rem; color: var(--text-strong); }
.tg-review li:last-child { border-bottom:none; }
.tg-result .tg-review li { border-bottom:1px solid var(--border); }
.kn-required { color:#b91c1c; font-size:0.76rem; font-weight:600; }
.kn-optional { color: var(--muted-2); font-size:0.76rem; }

/* Duplicados */
.kn-dup-error { margin-top:6px; font-size:0.8rem; color:#b91c1c; font-weight:600; }
.kn-dup-warn {
  margin-top:8px; padding:8px 12px; border-radius:8px; font-size:0.8rem;
  background: rgba(245,158,11,.08); border:1px solid rgba(245,158,11,.3); color:#92400e;
}
.kn-dup-warn ul { margin: 4px 0 0 18px; }

/* Canales (paso 4) */
.kn-check { display:flex; align-items:center; gap:6px; padding:5px 0; font-size:0.85rem; color: var(--text-strong); cursor:pointer; }
.kn-channel-list { margin-left: 18px; border-left: 2px solid var(--border); padding-left: 12px; }
.kn-channel-type { font-size:0.7rem; color: var(--muted-2); margin-left:6px; }
.kn-fecha-row { display:flex; gap:10px; align-items:center; flex-wrap:wrap; }
.kn-date { max-width: 170px; }
.kn-fecha-chips { display:flex; gap:6px; flex-wrap:wrap; }
.kn-chip-btn {
  padding: 4px 10px; font-size:0.76rem; border-radius: 12px;
  border:1px solid var(--control-border); background: var(--surface-2); color: var(--text-strong); cursor:pointer;
}
.kn-chip-btn:hover { background: var(--brand-soft-bg); border-color:#a5b4fc; }

/* Revisión (paso 5) */
.kn-preview-index {
  padding: 12px 14px; border:1px solid var(--border); border-radius:10px;
  background: var(--surface-2); margin-bottom:10px;
}
.kn-preview-index strong { display:block; margin-top:6px; color: var(--text-strong); }
.kn-preview-desc { margin:4px 0 0; font-size:0.82rem; color: var(--muted); }
.kn-preview-detail { margin: 8px 0; font-size: 0.82rem; }
.kn-preview-detail summary { cursor:pointer; color:#4f46e5; font-weight:600; padding:4px 0; }
.kn-preview-content {
  white-space: pre-wrap; background: var(--surface-2); padding:10px 12px;
  border-radius:8px; font-size:0.78rem; max-height: 220px; overflow-y:auto;
}
.kn-human-summary {
  margin-top:10px; padding:10px 14px; border-radius:10px; font-size:0.85rem;
  background: rgba(34,197,94,.07); border:1px solid rgba(34,197,94,.25); color:#14532d;
}
.kn-edit-toggles { margin-top:12px; display:flex; gap:18px; }

/* Conflictos */
.kn-conflict {
  padding: 14px 16px; border-radius:10px; margin-bottom: 10px;
  background: rgba(245,158,11,.07); border:1px solid rgba(245,158,11,.35);
}
.kn-conflict-title { margin: 0 0 8px; color:#92400e; }
.kn-conflict-list { margin: 6px 0 10px 16px; font-size:0.84rem; }
.kn-similarity { color: var(--muted-2); font-size:0.76rem; }
.kn-llm-explain {
  padding:8px 12px; background: var(--surface); border-radius:8px;
  border:1px solid rgba(245,158,11,.3); font-size:0.84rem; color: var(--text-strong);
}

/* Historial */
.kn-history { max-width: 640px; width: 95%; max-height: 85vh; overflow-y:auto; padding: 22px 26px; }
.kn-hist-list { display:flex; flex-direction:column; gap:6px; }
.kn-hist-item {
  border:1px solid var(--border); border-radius:10px; padding:8px 12px; font-size:0.84rem;
}
.kn-hist-item summary { cursor:pointer; }
.kn-hist-action { font-weight:700; color:#4f46e5; }
.kn-hist-date { float:right; color: var(--muted-2); font-size:0.76rem; }
.kn-hist-field { margin: 8px 0 0 8px; }
.kn-hist-fieldname { font-weight:600; font-size:0.78rem; color: var(--text-strong); }
.kn-hist-diff { display:flex; gap:8px; align-items:flex-start; margin-top:2px; flex-wrap:wrap; }
.kn-hist-old {
  background: rgba(239,68,68,.08); color:#991b1b; padding:2px 8px;
  border-radius:6px; font-size:0.76rem; max-width:45%; overflow-wrap:anywhere;
}
.kn-hist-new {
  background: rgba(34,197,94,.08); color:#166534; padding:2px 8px;
  border-radius:6px; font-size:0.76rem; max-width:45%; overflow-wrap:anywhere;
}
.kn-hist-arrow { color: var(--muted-2); }
.kn-hist-note { font-size:0.8rem; color: var(--muted); margin:6px 0 0; }

/* ============================================================
   Responsive
   ============================================================ */
@media (max-width: 480px) {
  .login-card {
    padding: 28px 24px;
  }

  /* La cabecera es ahora la barra global `.ph` (components/global_header.rs). */
  .ph, .page-header {
    padding: 0 16px;
  }

  .app-main, .page-content {
    padding: 20px 16px;
  }

  .modules-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .greeting-title {
    font-size: 1.5rem;
  }

  .home-greeting {
    padding: 28px 24px;
  }
}

/* ============================================================
   CAMPAÑAS MASIVAS
   ============================================================ */

.campaigns-page {
  padding: 28px 32px;
}

.campaigns-header {
  margin-bottom: 20px;
}

.campaigns-title {
  font-size: 1.5rem;
  font-weight: 700;
  color: var(--text);
  margin: 0 0 4px;
}

.campaigns-subtitle {
  color: var(--muted);
  font-size: 0.88rem;
  margin: 0;
}

/* ── Banners ── */
.camp-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 16px;
  border-radius: 8px;
  font-size: 0.88rem;
  margin-bottom: 16px;
  gap: 12px;
}

.camp-banner--error   { background: var(--badge-danger-bg); color: var(--badge-danger-fg); border: 1px solid rgba(239,68,68,0.4); }
.camp-banner--success { background: var(--badge-success-bg); color: var(--badge-success-fg); border: 1px solid rgba(16,185,129,0.4); }

.camp-banner-close {
  background: none;
  border: none;
  cursor: pointer;
  color: inherit;
  font-size: 1rem;
  padding: 0 4px;
  opacity: 0.7;
}

.camp-banner-close:hover { opacity: 1; }

/* ── Tabs ── */
.camp-tabs {
  display: flex;
  gap: 4px;
  background: var(--surface-2);
  border-radius: 999px;
  padding: 5px;
  width: fit-content;
  margin-bottom: 24px;
}

.camp-tab {
  padding: 7px 18px;
  border: none;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-size: 0.88rem;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.15s;
  white-space: nowrap;
}

.camp-tab:hover      { background: var(--control-bg-hover); color: var(--text); }
.camp-tab--active    { background: var(--surface); color: var(--text); font-weight: 600;
                       box-shadow: 0 1px 4px rgba(0,0,0,0.08); }

/* ── Content ── */
.camp-content {
  background: var(--surface);
  border-radius: 12px;
  border: 1px solid var(--border);
  padding: 24px;
  box-shadow: 0 1px 4px rgba(0,0,0,0.04);
}

.camp-empty {
  text-align: center;
  color: var(--muted);
  font-size: 0.9rem;
  padding: 40px 0;
}

/* ── Detalle de campaña: rejilla de metadatos ── */
.camp-detail-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 10px 16px;
  margin-bottom: 1rem;
}
.camp-detail-toolbar {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 10px;
}
.camp-detail-counts { display: flex; gap: 6px; flex-wrap: wrap; }
.camp-detail-export { margin-left: auto; display: flex; gap: 6px; }

/* ── Modal de detalle de campaña ────────────────────────────────────────────
   `.modal-card` NO trae padding propio: lo reparten `.modal-header` y la regla
   genérica `.modal-card > div:not(.modal-header):not(.modal-footer)`, que solo
   pone padding HORIZONTAL (`0 24px`). Un modal con cabecera propia, pestañas y
   tabla paginada se quedaba sin aire arriba ni abajo: el título pegado al borde
   superior y el paginador al inferior.

   Y esa misma regla genérica gana en especificidad a `.camp-tabs` (0,3,1 frente
   a 0,1,0), así que la pastilla de pestañas perdía su `padding: 5px` y las
   pestañas quedaban a ras de su propio borde. Por eso el reset excluye
   `.camp-tabs`: la pastilla conserva el suyo y del resto se encarga el
   contenedor.

   Este bloque va DESPUÉS de la regla genérica a propósito — misma especificidad,
   gana por orden de aparición y no hace falta `!important`.                    */
.modal-card.camp-detail-modal { padding: 22px 24px 24px; }
.modal-card.camp-detail-modal > div:not(.camp-tabs) { padding: 0; }

.camp-detail-modal-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}
.camp-detail-modal-head h4 { margin: 0; font-size: 0.95rem; color: var(--text-strong); }
.camp-detail-modal .camp-tabs { margin-bottom: 16px; }

/* El scroll horizontal de la tabla vive AQUÍ, nunca en el modal: `.modal-card`
   es `overflow-x: hidden` y sin este contenedor la tabla ancha se recortaría. */
.camp-detail-modal-scroll { overflow-x: auto; }

.camp-detail-pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-top: 14px;
}
.camp-detail-pager span { font-size: 0.8rem; color: var(--muted); }

.camp-detail-leads-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.camp-detail-leads-head p { margin: 0; font-size: 0.8rem; color: var(--muted); }
.camp-detail-leads-head div { display: flex; gap: 6px; }

/* ── Reporte de embudo de una campaña automática ────────────────────────────
   `auto-fit` y no `auto-fill`: con siete cifras las tarjetas se estiran para
   llenar la fila y quedan simétricas con la tabla de abajo, en vez de dejar
   columnas fantasma a la derecha (la misma regla que el módulo Métricas).     */
.camp-report-kpis {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 8px;
  margin-bottom: 14px;
}
.camp-report-kpi {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 10px 12px;
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  border-radius: 10px;
}
.camp-report-kpi-n { font-size: 1.15rem; font-weight: 700; color: var(--text-strong); }
.camp-report-kpi-k { font-size: 0.72rem; color: var(--muted); line-height: 1.25; }

/* Aviso de lo que este reporte NO puede saber (sin encuesta vinculada, sin tipo de
   pool). Se dice en pantalla: una columna muda se lee como un fallo. */
.camp-report-nota {
  margin: 0 0 10px;
  padding: 8px 12px;
  font-size: 0.78rem;
  color: var(--muted);
  background: var(--surface-2);
  border-left: 3px solid var(--border);
  border-radius: 6px;
}

/* Segunda línea de la celda de contacto (el nombre bajo el teléfono). */
.camp-report-sub { font-size: 0.75rem; color: var(--muted); margin-top: 2px; }
.camp-cell-err {
  max-width: 240px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  color: var(--muted); font-size: 0.8rem;
}
.camp-detail-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 12px;
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
}
.camp-detail-k {
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--muted);
}
.camp-detail-v {
  font-size: 0.9rem;
  color: var(--text-strong);
  font-weight: 600;
  word-break: break-word;
}

/* ── Badges ── definición retirada: era la SEGUNDA declaración de `.badge` del
   archivo, con geometría distinta a la primera (inline-block 20px frente a
   inline-flex 999px) y colores en tonos de tema OSCURO. Ver el bloque
   "BADGES / TAGS DE ESTADO" al final. */

/* ── Table ── */
.camp-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.875rem;
}

.camp-table th {
  text-align: left;
  padding: 10px 12px;
  font-weight: 600;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  border-bottom: 1px solid var(--border);
}

.camp-table td {
  padding: 12px 12px;
  border-bottom: 1px solid rgba(255,255,255,0.06);
  vertical-align: middle;
}

.camp-table tr:last-child td { border-bottom: none; }
.camp-table tr:hover td      { background: rgba(255,255,255,0.04); }

.camp-cell-title { font-weight: 600; color: var(--text); margin-bottom: 2px; }
.camp-cell-sub   { font-size: 0.78rem; color: var(--muted); }

.camp-date { font-size: 0.8rem; color: var(--muted); white-space: nowrap; }

/* ── Progress bar ── */
.camp-progress {
  height: 6px;
  background: var(--control-bg-hover);
  border-radius: 3px;
  overflow: hidden;
  margin-bottom: 4px;
  min-width: 80px;
}

.camp-progress-bar {
  height: 100%;
  background: linear-gradient(90deg, #3b82f6, #1d4ed8);
  border-radius: 3px;
  transition: width 0.4s ease;
  min-width: 2px;
}

.camp-progress-label {
  font-size: 0.78rem;
  color: var(--muted);
  white-space: nowrap;
}

.camp-failed-count { color: #dc2626; }

.camp-spinner {
  display: inline-block;
  animation: campPulse 1s ease-in-out infinite;
  color: #3b82f6;
}

@keyframes campPulse {
  0%, 100% { opacity: 1; }
  50%       { opacity: 0.3; }
}

/* ── Action buttons ── */
.camp-actions { white-space: nowrap; }

.camp-btn {
  padding: 5px 12px;
  border-radius: 6px;
  border: 1px solid transparent;
  font-size: 0.82rem;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.15s;
  margin-right: 4px;
}

.camp-btn:disabled { opacity: 0.5; cursor: not-allowed; }

.camp-btn--primary { background: var(--brand-dark); color: #fff; border-color: var(--brand-dark); }
.camp-btn--primary:hover:not(:disabled) { background: var(--brand-darker); }

.camp-btn--warn    { background: #f59e0b; color: #fff; border-color: #f59e0b; }
.camp-btn--warn:hover:not(:disabled)    { background: #d97706; }

.camp-btn--danger  { background: var(--control-bg); color: var(--badge-danger-fg); border-color: rgba(239,68,68,0.45); }
.camp-btn--danger:hover:not(:disabled)  { background: var(--badge-danger-bg); }

.camp-btn--secondary { background: var(--control-bg); color: var(--text); border-color: var(--control-border); }
.camp-btn--secondary:hover:not(:disabled) { background: var(--control-bg-hover); border-color: var(--muted); color: var(--text-strong); }

.camp-btn--sm      { padding: 4px 10px; font-size: 0.78rem; }

.camp-btn--lg      { padding: 10px 24px; font-size: 0.95rem; }

/* ── Form ── */
.camp-form {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.camp-form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  margin-bottom: 20px;
}

.camp-field        { display: flex; flex-direction: column; gap: 6px; }
.camp-field--full  { grid-column: 1 / -1; }

.camp-label {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text);
}

.camp-hint-inline {
  font-weight: 400;
  color: var(--muted);
  font-size: 0.78rem;
  margin-left: 6px;
}

.camp-hint {
  font-size: 0.78rem;
  color: var(--muted);
  margin: 2px 0 0;
}

.camp-input,
.camp-select,
.camp-textarea {
  padding: 9px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 0.88rem;
  color: var(--text);
  background: var(--surface);
  transition: border-color 0.15s;
  font-family: inherit;
  width: 100%;
  box-sizing: border-box;
}

.camp-input:focus,
.camp-select:focus,
.camp-textarea:focus {
  outline: none;
  border-color: #3b82f6;
  box-shadow: 0 0 0 3px rgba(59,130,246,0.15);
}

.camp-input:disabled,
.camp-select:disabled,
.camp-textarea:disabled { background: var(--surface-2); color: var(--muted); }

.camp-textarea     { resize: vertical; min-height: 80px; }
.camp-textarea--csv { font-family: 'Courier New', monospace; font-size: 0.8rem; }

.camp-csv-count {
  font-size: 0.82rem;
  font-weight: 600;
  color: #3b82f6;
  margin-top: 4px;
}

.camp-form-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: 16px;
  border-top: 1px solid var(--border);
}

.camp-checkbox-label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.88rem;
  color: var(--text);
  cursor: pointer;
  user-select: none;
}

/* ── Templates tab ── */
.camp-templates { }

.camp-templates-toolbar {
  display: flex;
  gap: 12px;
  align-items: center;
  margin-bottom: 20px;
}

.camp-templates-toolbar .camp-select { max-width: 280px; }

.camp-template-name { font-weight: 500; font-family: monospace; font-size: 0.85rem; }
.camp-vars-count    { text-align: center; font-weight: 600; color: #7c3aed; }
.camp-sync-time     { font-size: 0.78rem; color: var(--muted); white-space: nowrap; }

/* ── Config tab ── */
.camp-config { }

.camp-section-title {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text);
  margin: 0 0 12px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
}

.camp-channels-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 28px;
}

.camp-channel-card {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 16px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface-2);
}

.camp-channel-info {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  flex: 1;
}

.camp-channel-name   { font-weight: 700; color: var(--text); }
.camp-channel-nameid { font-family: monospace; font-size: 0.8rem; color: var(--muted); }
.camp-channel-checked { font-size: 0.78rem; color: var(--muted); width: 100%; }
.camp-channel-err    { color: #dc2626; }

.camp-channel-creds {
  display: flex;
  gap: 12px;
  align-items: center;
  flex-shrink: 0;
}

.camp-creds-masked {
  font-size: 0.78rem;
  color: var(--muted);
  font-family: monospace;
}

.camp-channel-actions { flex-shrink: 0; }

.camp-channel-form { margin-top: 8px; }


.camp-edit-form {
  flex-basis: 100%;
  width: 100%;
  margin-top: 12px;
  padding: 14px;
  background: var(--surface);
  border: 1px dashed var(--primary);
  border-radius: 8px;
}

.camp-edit-title {
  font-size: 0.82rem;
  color: var(--muted);
  margin: 0 0 10px;
}

.camp-edit-actions {
  display: flex;
  gap: 8px;
  margin-top: 12px;
}

/* ── Utility: toggle switch ── */
.switch-field {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  max-width: 100%;
  cursor: pointer;
  color: var(--text);
  font-size: 0.92rem;
  font-weight: 600;
  line-height: 1.35;
}

.form-field label.switch-field {
  display: inline-flex;
  margin-bottom: 6px;
}

.switch-field__text {
  display: inline-block;
}

/* Variante compacta: filas de toggles pequeños (multimedia, obligatorio en
   gestión de tickets). Menos peso/tamaño para que no dominen el modal. */
.switch-field--sm {
  gap: 8px;
  font-size: 0.82rem;
  font-weight: 500;
}

.toggle-switch {
  --switch-width: 46px;
  --switch-height: 24px;
  --switch-knob-size: 18px;
  --switch-knob-offset: 3px;
  position: relative;
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
  width: var(--switch-width);
  height: var(--switch-height);
  cursor: pointer;
}
.toggle-switch input { opacity: 0; width: 0; height: 0; }
.toggle-slider {
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--muted-2) 40%, transparent);
  border: 1px solid color-mix(in srgb, var(--border) 82%, transparent);
  border-radius: 999px;
  transition: background 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;
}
.toggle-slider::before {
  content: "";
  position: absolute;
  width: var(--switch-knob-size);
  height: var(--switch-knob-size);
  border-radius: 50%;
  background: #fff;
  top: var(--switch-knob-offset);
  left: var(--switch-knob-offset);
  box-shadow: 0 2px 6px rgba(15, 23, 42, 0.22);
  transition:
    transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1),
    background 0.3s ease;
}
.toggle-switch input:focus-visible + .toggle-slider {
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.18);
}
.toggle-switch input:checked + .toggle-slider {
  background: color-mix(in srgb, var(--brand) 72%, #ffffff 8%);
  border-color: color-mix(in srgb, var(--brand) 82%, #ffffff 6%);
}
.toggle-switch input:checked + .toggle-slider::before {
  transform: translateX(22px);
}
.toggle-switch input:disabled + .toggle-slider {
  opacity: 0.62;
  cursor: not-allowed;
}
.toggle-switch--sm {
  --switch-width: 32px;
  --switch-height: 18px;
  --switch-knob-size: 12px;
  --switch-knob-offset: 3px;
}
.toggle-switch--sm input:checked + .toggle-slider::before { transform: translateX(14px); }

/* ── Utility: small buttons ── */
.btn-xs {
  font-size: 0.75rem; padding: 3px 10px; border-radius: 6px;
  border: 1px solid var(--border); background: var(--panel-2);
  color: var(--text); cursor: pointer; white-space: nowrap;
}
.btn-xs:hover { background: var(--border); }
.btn-link-xs {
  font-size: 0.75rem; padding: 0 4px; border: none; background: none;
  color: var(--brand); cursor: pointer; text-decoration: underline;
}
.btn-link-xs:hover { color: var(--brand-dark); }

/* ── Utility: status chips ── */
.status-chip {
  font-size: 0.7rem; padding: 2px 8px; border-radius: 999px;
  font-weight: 600; white-space: nowrap;
}
.chip-active { background: rgba(16,185,129,0.15); color: #34d399; }
.chip-off    { background: rgba(239,68,68,0.15);  color: #f87171; }

/* ── Herramientas panel ── */
.tools-panel { padding: 24px; display: flex; flex-direction: column; gap: 12px; }

/* Header con botón agregar */
.tools-list-header { display: flex; justify-content: flex-end; padding-bottom: 4px; }

/* Botón peligro pequeño en tarjeta */
.btn-danger-xs {
  padding: 3px 10px; font-size: 0.75rem; border-radius: 6px; border: none; cursor: pointer;
  background: var(--badge-danger-bg); color: var(--badge-danger-fg); font-weight: 600; transition: background 0.15s;
}
.btn-danger-xs:hover { background: rgba(239,68,68,0.3); }

/* Formulario crear MCP */
.tools-create-form { display: flex; flex-direction: column; gap: 14px; padding: 8px 0; }
.tools-create-field { display: flex; flex-direction: column; gap: 4px; }
.tools-create-field label { font-size: 0.78rem; font-weight: 600; color: var(--muted); }
.tools-create-field .form-hint { font-size: 0.72rem; color: var(--muted-2); }
.tools-create-row { display: flex; gap: 16px; }
.tools-create-row .tools-create-field { flex: 1; }

.tools-feedback {
  padding: 8px 14px; background: var(--badge-success-bg); color: var(--badge-success-fg);
  border-radius: 8px; font-size: 0.85rem; font-weight: 500;
}

.tools-list { display: flex; flex-direction: column; gap: 12px; }

.tools-card {
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 12px; overflow: hidden;
  transition: opacity 0.2s;
}
.tools-card--off { opacity: 0.6; }

.tools-card-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 18px; gap: 12px; flex-wrap: wrap;
}
.tools-card-title { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.tools-mcp-id    { font-weight: 700; font-size: 0.95rem; }
.tools-mcp-type  { font-size: 0.78rem; color: var(--muted); }

.health-badge {
  font-size: 0.7rem; font-weight: 600; padding: 2px 10px;
  border-radius: 999px; white-space: nowrap;
}
.health-badge--ok       { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.health-badge--error    { background: var(--badge-danger-bg); color: var(--badge-danger-fg); }
.health-badge--timeout  { background: var(--badge-warn-bg); color: var(--badge-warn-fg); }
.health-badge--internal { background: var(--badge-purple-bg); color: var(--badge-purple-fg); }
.health-badge--unknown  { background: var(--panel-2); color: var(--muted); }
.health-ms { font-weight: 400; font-size: 0.68rem; }

.tools-card-btns { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

.tools-card-meta {
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  padding: 8px 18px 14px; border-top: 1px solid var(--border);
  font-size: 0.82rem; color: var(--muted);
}
.tools-meta-ch    { display: flex; align-items: center; gap: 4px; }
.tools-meta-check { font-size: 0.78rem; }

.tools-tools-grid {
  display: flex; flex-direction: column; gap: 0;
  border-top: 1px solid var(--border);
}
.tools-tool-row {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 18px; border-bottom: 1px solid var(--border);
  font-size: 0.85rem; flex-wrap: wrap;
}
.tools-tool-row:last-child { border-bottom: none; }
.tools-tool-row--off { opacity: 0.55; }
.tools-tool-name { font-weight: 600; min-width: 140px; }
.tools-tool-ch   { color: var(--muted); flex: 1; font-size: 0.78rem; }
.tools-tool-acts { display: flex; align-items: center; gap: 8px; margin-left: auto; }

.tools-key-note {
  margin: 12px 0 8px; font-size: 0.82rem; color: var(--muted);
}

.tools-channels-body { padding: 12px 0; display: flex; flex-direction: column; gap: 8px; }
.tools-channels-opts { display: flex; flex-direction: column; gap: 6px; padding-left: 8px; }
.tools-channel-opt {
  display: flex; align-items: center; gap: 8px;
  font-size: 0.85rem; cursor: pointer;
}
.tools-channel-opt input { cursor: pointer; }

/* ── Responsive ── */
@media (max-width: 768px) {
  .campaigns-page { padding: 20px 16px; }
  .camp-form-grid { grid-template-columns: 1fr; }
  .camp-field--full { grid-column: 1; }
  .camp-table th, .camp-table td { padding: 8px 8px; }
  .camp-channel-card { flex-direction: column; }
  .camp-channel-creds { flex-wrap: wrap; }
  .camp-tabs { flex-wrap: wrap; width: 100%; }
  .camp-template-actions .camp-btn { flex: 1 1 180px; }
}

/* ═══════════════════════════════════════════════════════════════
   Contacts Page — redesign
   ═══════════════════════════════════════════════════════════════ */

.contacts-page {
  display: flex;
  flex-direction: column;
  min-height: 100%;
  background: var(--bg);
}

/* ── Header card ── */
.contacts-hdr {
  background: linear-gradient(135deg, #1e3a8a 0%, #1d4ed8 65%, #2563eb 100%);
  padding: 24px 32px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.contacts-hdr-left {
  display: flex;
  align-items: center;
  gap: 16px;
}

.contacts-hdr-icon {
  width: 48px;
  height: 48px;
  background: rgba(255,255,255,0.15);
  border-radius: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  flex-shrink: 0;
}

.contacts-hdr-title {
  color: white;
  font-size: 1.25rem;
  font-weight: 700;
  margin: 0;
  line-height: 1.3;
}

.contacts-hdr-sub {
  color: rgba(255,255,255,0.65);
  font-size: 0.78rem;
  margin: 3px 0 0;
}

.btn-back-contacts {
  background: rgba(255,255,255,0.12);
  border: 1px solid rgba(255,255,255,0.22);
  border-radius: 8px;
  color: white;
  cursor: pointer;
  font-family: inherit;
  font-size: 0.8125rem;
  font-weight: 600;
  padding: 7px 14px;
  transition: background 0.15s;
  white-space: nowrap;
  flex-shrink: 0;
}
.btn-back-contacts:hover { background: rgba(255,255,255,0.22); }

.contacts-toolbar {
  display: flex;
  align-items: center;
  padding: 16px 24px;
}

.contacts-search-form {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  max-width: 480px;
}

.contacts-search-input {
  background: rgba(255,255,255,0.15);
  border: 1px solid rgba(255,255,255,0.25);
  border-radius: 10px;
  color: white;
  font-family: inherit;
  font-size: 0.875rem;
  outline: none;
  flex: 1;
  padding: 10px 18px;
  width: 280px;
  transition: background 0.15s, border-color 0.15s;
}
.contacts-search-input::placeholder { color: rgba(255,255,255,0.5); }
.contacts-search-input:focus {
  background: rgba(255,255,255,0.22);
  border-color: rgba(255,255,255,0.5);
}

.contacts-refresh-btn {
  align-items: center;
  background: rgba(255,255,255,0.15);
  border: 1px solid rgba(255,255,255,0.25);
  border-radius: 10px;
  color: white;
  cursor: pointer;
  display: flex;
  height: 42px;
  justify-content: center;
  transition: background 0.15s;
  width: 42px;
  flex-shrink: 0;
}
.contacts-refresh-btn:hover { background: rgba(255,255,255,0.28); }
.contacts-refresh-btn:disabled { opacity: 0.5; cursor: not-allowed; }

/* ============================================================
   TOOLBAR CANÓNICO (port sestia) — buscador + embudo + acciones
   ------------------------------------------------------------
   Clases NUEVAS, aditivas. Las variantes de buscador/embudo van
   SCOPEADAS a .tickets-toolbar para NO tocar el buscador global de
   sofia (que va en blanco sobre header de color). Solo los módulos
   migrados a .tickets-toolbar adoptan el look theme-aware de sestia.
   Usa el componente compartido components/toolbar.rs::list_toolbar.
   ============================================================ */
.tickets-toolbar {
  position: relative;                 /* ancla del popover de filtros */
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}
.tickets-toolbar-right {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* Popover: se renderiza siempre; se muestra/oculta por CSS. `absolute` lo saca
   del flujo → abrirlo NO mueve los botones de acción. */
.tickets-filters-wrap { display: none; position: absolute; top: 0; left: 0; }
.tickets-filters-wrap.is-open { display: block; }
.tickets-toolbar .tickets-filters-popover {
  top: 52px; left: 0;
  width: min(420px, calc(100vw - 48px));
}
.filters-backdrop { position: fixed; inset: 0; z-index: 40; }

/* Buscador dentro del toolbar: pastilla theme-aware (override scopeado del
   buscador global de sofia, que es blanco sobre header).
   `.flx-topbar` (lista de Flujos) entra aquí porque es el MISMO buscador metido
   en otra caja. Sin este scope se quedaba con el estilo base —pensado para la
   barra oscura de Contactos: fondo blanco translúcido, texto blanco y
   `width: 280px`—, que dentro de una columna de 300px desbordaba. */
.tickets-toolbar .contacts-search-form { max-width: 520px; gap: 2px; }
.tickets-toolbar .contacts-search-input,
.flx-topbar .contacts-search-input {
  background: var(--control-bg);
  border: 1px solid var(--control-border);
  border-radius: 999px;
  color: var(--text);
  width: auto;
  padding: 10px 40px 10px 18px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2394a3b8' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M20 20l-3.5-3.5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
}
.tickets-toolbar .contacts-search-input::placeholder,
.flx-topbar .contacts-search-input::placeholder { color: var(--muted-2); }
.tickets-toolbar .contacts-search-input:focus,
.flx-topbar .contacts-search-input:focus {
  background-color: var(--control-bg-hover);
  border-color: var(--brand);
  box-shadow: 0 0 0 3px rgba(var(--brand-rgb), 0.12);
}

/* Iconos de acción dentro del toolbar: sin caja; el hover los levanta y tiñe. */
.tickets-toolbar .contacts-refresh-btn,
.flx-topbar .contacts-refresh-btn {
  width: 34px; height: 34px;
  background: none;
  border: none;
  color: var(--muted);
  border-radius: 8px;
}
.tickets-toolbar .contacts-refresh-btn svg,
.flx-topbar .contacts-refresh-btn svg { transition: transform 0.15s ease, color 0.15s ease; }
.tickets-toolbar .contacts-refresh-btn:hover:not(:disabled),
.flx-topbar .contacts-refresh-btn:hover:not(:disabled) { background: none; color: var(--brand); }
.tickets-toolbar .contacts-refresh-btn:hover:not(:disabled) svg,
.flx-topbar .contacts-refresh-btn:hover:not(:disabled) svg { transform: translateY(-2px); }
.tickets-toolbar .contacts-refresh-btn:disabled,
.flx-topbar .contacts-refresh-btn:disabled { opacity: 0.35; cursor: not-allowed; pointer-events: none; }

/* Embudo + contador de filtros activos */
.contacts-filter-btn { position: relative; }
.contacts-filter-btn.is-active { color: var(--brand); }
.contacts-filter-btn.is-active svg { transform: translateY(-2px); }
.contacts-filter-count {
  position: absolute; top: 0; right: 0;
  min-width: 15px; height: 15px; padding: 0 3px;
  background: var(--brand); color: #fff;
  border-radius: 8px; font-size: 0.6rem; font-weight: 700;
  display: flex; align-items: center; justify-content: center; line-height: 1;
}

/* Envoltorio del botón deshabilitado: recibe hover, cursor y tooltip. */
.tb-icon-wrap { display: inline-flex; }
.tb-icon-wrap.is-disabled { cursor: not-allowed; }

/* Popover de filtros avanzados.
   `.flx-filters-popover` (Flujos) se suma aquí en vez de definir su propia caja:
   es el MISMO widget. Cada consumidor solo pone su anclaje (top/left/right). */
.contacts-filters-popover,
.flx-filters-popover {
  position: absolute; z-index: 41;
  display: flex; flex-direction: column; gap: 14px;
  padding: 14px;
  background: var(--surface-overlay);   /* NUNCA --surface: sería translúcido en oscuro */
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow-md);
}
.contacts-fpop-section { display: flex; flex-direction: column; gap: 8px; }
.contacts-fpop-title {
  font-size: 0.68rem; font-weight: 800; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted-2);
}
.contacts-filters-popover select,
.contacts-filters-popover input[type="text"],
.contacts-filters-popover input[type="date"],
.flx-filters-popover select {
  width: 100%;
  padding: 9px 12px;
  border: 1px solid var(--control-border);
  border-radius: 9px;
  font: inherit;
  font-size: 0.85rem;
  background: var(--control-bg);
  color: var(--text);
}
.contacts-filters-popover select,
.flx-filters-popover select { cursor: pointer; }
.contacts-filters-popover select:focus,
.contacts-filters-popover input:focus,
.flx-filters-popover select:focus { outline: none; border-color: var(--brand); }

/* ── Channel chips bar ── */
.contacts-channel-bar {
  background: #0f172a;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: 8px;
  overflow-x: auto;
  padding: 12px 24px;
  scrollbar-width: none;
}
.contacts-channel-bar::-webkit-scrollbar { display: none; }

.ch-chip {
  align-items: center;
  background: rgba(255, 255, 255, 0.06);
  border: 1.5px solid var(--border);
  border-radius: 999px;
  color: var(--text);
  cursor: pointer;
  display: inline-flex;
  flex-shrink: 0;
  font-family: inherit;
  font-size: 0.8125rem;
  font-weight: 500;
  gap: 6px;
  padding: 6px 14px;
  transition: border-color 0.15s, background 0.15s, color 0.15s;
  white-space: nowrap;
}
.ch-chip:hover { background: rgba(255, 255, 255, 0.1); border-color: var(--muted); }
.ch-chip--on {
  background: var(--brand-soft-bg);
  border-color: #3b82f6;
  color: #1d4ed8;
  font-weight: 600;
}
.ch-chip-icon {
  flex-shrink: 0;
  height: 16px;
  object-fit: contain;
  width: 16px;
}
.ch-chip-count {
  background: rgba(0,0,0,0.07);
  border-radius: 999px;
  color: inherit;
  font-size: 0.72rem;
  font-weight: 700;
  padding: 1px 7px;
}
.ch-chip--on .ch-chip-count { background: rgba(59,130,246,0.15); }

/* ── Status sub-bar ── */
.contacts-subbar {
  background: #0f172a;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 24px;
}

.contacts-sc-wrap {
  display: flex;
  gap: 6px;
}

.sc-chip {
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--muted);
  cursor: pointer;
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 500;
  padding: 5px 14px;
  transition: all 0.15s;
}
.sc-chip:hover { border-color: var(--muted-2); color: var(--text); }
.sc-chip--on {
  background: #1d4ed8;
  border-color: #1d4ed8;
  color: white;
  font-weight: 600;
}

.contacts-count-label {
  color: var(--muted);
  font-size: 0.8125rem;
  font-weight: 500;
}

/* ── Content wrapper ── */
.contacts-content {
  padding: 24px 32px;
  flex: 1;
}

/* ── Table — contact cell ── */
.contact-cell {
  align-items: center;
  display: flex;
  gap: 12px;
}

.contact-avatar {
  align-items: center;
  border-radius: 50%;
  color: white;
  display: flex;
  flex-shrink: 0;
  font-size: 0.875rem;
  font-weight: 700;
  height: 38px;
  justify-content: center;
  letter-spacing: 0.02em;
  width: 38px;
}

.contact-avatar-pic {
  width: 38px;
  height: 38px;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
}

/* Avatar color variants */
.av-indigo  { background: #4f46e5; }
.av-emerald { background: #059669; }
.av-violet  { background: #7c3aed; }
.av-amber   { background: #d97706; }
.av-rose    { background: #e11d48; }
.av-sky     { background: #0284c7; }

.contact-cell-info {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.contact-cell-name {
  color: var(--text);
  font-size: 0.875rem;
  font-weight: 600;
}

.contact-cell-phone {
  color: var(--muted);
  font-size: 0.75rem;
}

/* ── Status badges (contacts) ── */
.contact-sbadge {
  border-radius: 999px;
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 600;
  padding: 3px 10px;
  white-space: nowrap;
}
.contact-sbadge--pending  { background: var(--surface-2); color: var(--muted); }

.contact-estado-cell { display: flex; flex-direction: column; gap: 3px; }

/* ── Contracts / friendship / actions ── */
.contracts-count {
  color: var(--text);
  font-size: 0.84rem;
  font-weight: 500;
}

.friendship-val {
  align-items: center;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: var(--text);
  display: inline-flex;
  font-size: 0.84rem;
  font-weight: 600;
  justify-content: center;
  min-width: 32px;
  padding: 3px 8px;
}

.contact-actions-cell {
  display: flex;
  align-items: center;
  gap: 6px;
}

.btn-ver-contact {
  background: var(--brand-soft-bg);
  border: 1px solid #bfdbfe;
  border-radius: 7px;
  color: #1d4ed8;
  cursor: pointer;
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  padding: 5px 14px;
  transition: background 0.15s, border-color 0.15s;
  white-space: nowrap;
}
.btn-ver-contact:hover { background: #dbeafe; border-color: #93c5fd; }

.btn-chat-contact {
  background: var(--badge-success-bg);
  border: 1px solid #bbf7d0;
  border-radius: 7px;
  color: #16a34a;
  cursor: pointer;
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  padding: 5px 14px;
  transition: background 0.15s, border-color 0.15s;
  white-space: nowrap;
}

/* ── Campañas: plantilla row + vista previa ────────────────────────────────── */

.camp-template-row {
  display: flex;
  gap: 8px;
  align-items: stretch;
}
.camp-template-row .camp-select { flex: 1; }

.camp-btn--outline {
  background: transparent;
  border: 1.5px solid var(--brand);
  color: var(--brand);
  border-radius: 7px;
  cursor: pointer;
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  padding: 0 14px;
  white-space: nowrap;
  transition: background 0.15s, color 0.15s;
}
.camp-btn--outline:hover:not(:disabled) {
  background: var(--brand);
  color: #fff;
}
.camp-btn--outline:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.camp-preview-label {
  font-size: 0.8rem;
  color: var(--muted);
  margin-bottom: 10px;
}
.camp-preview-label code {
  background: var(--surface-2);
  border-radius: 4px;
  padding: 1px 5px;
  font-size: 0.78rem;
  color: #7c3aed;
}

.camp-preview-phone {
  display: inline-flex;
  flex-direction: column;
  gap: 0;
  max-width: 380px;
}

.camp-preview-bubble {
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--border);
  border-radius: 12px 12px 12px 2px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.2);
  overflow: hidden;
  font-size: 0.88rem;
  color: var(--text);
}

.camp-preview-media {
  background: #d1fae5;
  color: #065f46;
  font-size: 0.8rem;
  font-weight: 600;
  padding: 10px 14px;
  border-bottom: 1px solid #a7f3d0;
}

.camp-preview-header {
  background: var(--badge-success-bg);
  color: #14532d;
  font-weight: 700;
  font-size: 0.92rem;
  padding: 10px 14px;
  border-bottom: 1px solid #bbf7d0;
}

.camp-preview-body {
  padding: 12px 14px;
  white-space: pre-wrap;
  line-height: 1.55;
  color: var(--text-strong);
}

.camp-preview-footer {
  padding: 6px 14px 10px;
  font-size: 0.77rem;
  color: var(--muted-2);
  border-top: 1px solid var(--border-soft);
}

.camp-preview-btns {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin-top: 2px;
}

/* ── Header multimedia: estado + subida ── */
.camp-hdr-media {
  margin-top: 14px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface-2);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.camp-hdr-media-head { font-size: 0.85rem; color: var(--text); }
.camp-hdr-media-ok   { font-size: 0.82rem; color: var(--badge-success-fg); font-weight: 600; }
.camp-hdr-media-warn { font-size: 0.82rem; color: var(--badge-warn-fg); font-weight: 600; }
.camp-hdr-media-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.camp-hdr-media-msg  { font-size: 0.82rem; color: var(--muted); }

/* Mapeo de variables de plantilla → campo del CSV */
.camp-varmap { border: 1px solid var(--border); border-radius: 10px; padding: 12px 14px; background: var(--surface-2); }
.camp-varmap-row { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; flex-wrap: wrap; }
.camp-varmap-token {
  font-family: monospace; font-size: 0.82rem; font-weight: 700;
  color: var(--brand); background: var(--brand-soft-bg);
  padding: 3px 8px; border-radius: 6px; min-width: 72px; text-align: center;
}
.camp-varmap-arrow { color: var(--muted); }
.camp-varmap-select {
  flex: 1 1 220px; min-width: 180px; min-height: 36px;
  padding: 8px 10px; border: 1px solid var(--control-border); border-radius: 8px;
  background: var(--control-bg); color: var(--text); font-size: 0.86rem; font-family: inherit;
}
.camp-varmap-select:focus { outline: none; border-color: var(--brand-dark); }

/* Picker de archivo del storage para el header media de la campaña */
.camp-hdr-storage { margin-top: 10px; border-top: 1px dashed var(--border); padding-top: 8px; }
.camp-hdr-storage-title { font-size: 0.8rem; color: var(--muted); margin-bottom: 6px; text-align: center; }
.camp-hdr-storage-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.camp-hdr-storage-input {
  flex: 1 1 140px; min-width: 120px; min-height: 34px; padding: 7px 10px;
  border: 1px solid var(--control-border); border-radius: 8px;
  background: var(--control-bg); color: var(--text); font-size: 0.84rem; font-family: inherit;
}
.camp-hdr-storage-list { margin-top: 8px; display: flex; flex-direction: column; gap: 4px; max-height: 180px; overflow-y: auto; }
.camp-hdr-storage-item {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  font-size: 0.84rem; padding: 4px 8px; border: 1px solid var(--border); border-radius: 6px;
}
.camp-hdr-storage-item--off { opacity: 0.55; }
.camp-hdr-storage-use { padding: 2px 10px; }
.camp-hdr-storage-crumbs { display: flex; flex-wrap: wrap; align-items: center; gap: 4px; margin: 6px 0; font-size: 0.82rem; }
.camp-crumb { background: none; border: none; color: var(--brand); cursor: pointer; padding: 0 2px; font: inherit; }
.camp-crumb:hover { text-decoration: underline; }
.camp-crumb-sep { color: var(--muted); }
.camp-hdr-storage-folder { cursor: pointer; }
.camp-hdr-storage-folder:hover { background: var(--control-bg-hover); }

.camp-preview-btn {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  color: #2563eb;
  cursor: default;
  font-size: 0.82rem;
  font-weight: 600;
  padding: 9px 14px;
  text-align: center;
}

.camp-preview-empty {
  color: var(--muted);
  font-size: 0.82rem;
  padding: 8px 0;
}

/* ── Campañas: carga de archivo CSV / Excel ────────────────────────────────── */

.camp-file-zone {
  display: flex;
  align-items: center;
  gap: 8px;
  border: 2px dashed #cbd5e1;
  border-radius: 8px;
  padding: 14px 18px;
  cursor: pointer;
  font-size: 0.85rem;
  color: var(--muted);
  transition: border-color 0.2s, background 0.2s;
  background: var(--surface-2);
  user-select: none;
}
.camp-file-zone:hover {
  border-color: var(--brand);
  background: var(--brand-soft-bg);
  color: var(--brand);
}
.camp-file-zone--has-file {
  border-color: #10b981;
  background: var(--badge-success-bg);
  color: #065f46;
  font-weight: 600;
}
.camp-file-icon {
  font-size: 1.1rem;
}

.camp-template-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 8px;
}

.camp-divider {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 10px 0;
  color: var(--muted-2);
  font-size: 0.75rem;
}
.camp-divider::before,
.camp-divider::after {
  content: "";
  flex: 1;
  border-top: 1px solid var(--border);
}
.btn-chat-contact:hover { background: #dcfce7; border-color: #86efac; }

.btn-pausar-ia {
  background: rgba(245,158,11,0.1);
  border: 1px solid rgba(245,158,11,0.4);
  border-radius: 7px;
  color: #b45309;
  cursor: pointer;
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  padding: 5px 10px;
  transition: background 0.15s;
  white-space: nowrap;
}
.btn-pausar-ia:hover { background: rgba(245,158,11,0.2); }

.btn-reanudar-ia {
  background: rgba(16,185,129,0.1);
  border: 1px solid rgba(16,185,129,0.4);
  border-radius: 7px;
  color: #059669;
  cursor: pointer;
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  padding: 5px 10px;
  transition: background 0.15s;
  white-space: nowrap;
}
.btn-reanudar-ia:hover { background: rgba(16,185,129,0.2); }

/* ── Contact edit button (livechat panel) ── */
.btn-edit-contact {
  background: var(--surface-2);
  border: 1px solid var(--control-border);
  border-radius: 7px;
  color: var(--muted);
  cursor: pointer;
  font-family: inherit;
  font-size: 0.78rem;
  font-weight: 600;
  margin-top: 6px;
  padding: 4px 12px;
  transition: background 0.15s;
}
.btn-edit-contact:hover { background: var(--control-bg-hover); }

/* ── Contact edit form (livechat panel) ── */
.contact-edit-form {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 10px 0;
  padding: 14px;
}
.edit-field-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.edit-field-row label {
  color: var(--muted);
  font-size: 0.75rem;
  font-weight: 600;
}
.edit-field-row input[type="text"],
.edit-field-row input[type="email"] {
  background: var(--surface);
  border: 1px solid var(--control-border);
  border-radius: 6px;
  color: var(--text);
  font-family: inherit;
  font-size: 0.84rem;
  outline: none;
  padding: 6px 10px;
  transition: border-color 0.15s;
}
.edit-field-row input[type="text"]:focus,
.edit-field-row input[type="email"]:focus { border-color: #6366f1; }

.edit-field-row--check label {
  align-items: center;
  color: var(--text);
  display: flex;
  font-size: 0.84rem;
  font-weight: 500;
  gap: 6px;
}
.edit-actions {
  display: flex;
  gap: 8px;
  margin-top: 4px;
}
.btn-save-contact {
  background: #4f46e5;
  border: none;
  border-radius: 7px;
  color: #fff;
  cursor: pointer;
  font-family: inherit;
  font-size: 0.84rem;
  font-weight: 600;
  padding: 6px 18px;
  transition: background 0.15s;
}
.btn-save-contact:hover:not(:disabled) { background: #4338ca; }
.btn-save-contact:disabled { opacity: 0.6; cursor: not-allowed; }

.btn-cancel-edit {
  background: var(--surface-2);
  border: 1px solid var(--control-border);
  border-radius: 7px;
  color: var(--muted);
  cursor: pointer;
  font-family: inherit;
  font-size: 0.84rem;
  font-weight: 600;
  padding: 6px 14px;
  transition: background 0.15s;
}
.btn-cancel-edit:hover { background: var(--control-bg-hover); }

/* ── Badge paused in livechat contact panel ── */

/* ============================================================
   Ticket picker modal (livechat — Asignarme)
   ============================================================ */
.ticket-picker-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0,0,0,0.5);
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
}

.ticket-picker-modal {
  background: var(--surface-overlay);
  border-radius: 12px;
  box-shadow: var(--shadow-lg);
  width: 480px;
  max-width: 95vw;
  max-height: 80vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.ticket-picker-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
}
.ticket-picker-header h3 {
  font-size: 1rem;
  font-weight: 600;
  color: var(--text-strong);
  margin: 0;
}

.btn-close-picker {
  background: none;
  border: none;
  font-size: 1.4rem;
  color: var(--muted-2);
  cursor: pointer;
  line-height: 1;
  padding: 0 4px;
  transition: color 0.15s;
}
.btn-close-picker:hover { color: var(--text-strong); }

.ticket-picker-list {
  overflow-y: auto;
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.ticket-picker-item {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.ticket-picker-item:hover {
  background: var(--brand-soft-bg);
  border-color: #3b82f6;
}

.ticket-picker-top {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}

.ticket-picker-ref {
  font-size: 0.72rem;
  font-weight: 700;
  color: #6366f1;
  background: rgba(99,102,241,0.08);
  padding: 2px 6px;
  border-radius: 4px;
  font-family: monospace;
}

.ticket-picker-type {
  font-size: 0.72rem;
  color: var(--muted);
  background: var(--surface-2);
  padding: 2px 6px;
  border-radius: 4px;
}

.ticket-picker-title {
  font-size: 0.88rem;
  font-weight: 500;
  color: var(--text-strong);
  margin-bottom: 6px;
  line-height: 1.3;
}

.ticket-picker-meta {
  display: flex;
  align-items: center;
  gap: 8px;
}

.ticket-picker-status {
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  padding: 2px 7px;
  border-radius: 10px;
  background: var(--surface-2);
  color: var(--muted);
}
.tps--abierto  { background: rgba(59,130,246,0.1);  color: #2563eb; }
.tps--tomado   { background: rgba(245,158,11,0.1);  color: #d97706; }
.tps--en_proceso { background: rgba(139,92,246,0.1); color: #7c3aed; }

.ticket-picker-taken {
  font-size: 0.75rem;
  color: var(--muted);
}

.ticket-picker-empty {
  padding: 24px;
  text-align: center;
  color: var(--muted-2);
  font-size: 0.875rem;
}

/* ============================================================
   Ticket detail inline panel (livechat — badge click)
   ============================================================ */
.badge--ticket-active {
  cursor: pointer;
  border: none;
  font-size: inherit;
  padding: 3px 10px;
  border-radius: 9999px;
  transition: background 0.15s;
}
.badge--ticket-active:hover { background: rgba(99,102,241,0.20); }
.badge--ticket-open { background: rgba(99,102,241,0.22); outline: 2px solid rgba(99,102,241,0.35); }

/* ── Modal cierre de ticket (livechat) ───────────────────────────────── */
.lc-close-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  backdrop-filter: blur(3px);
  z-index: 800;
}
.lc-close-modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: min(460px, 94vw);
  background: var(--surface-overlay);
  border-radius: 14px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.08);
  z-index: 801;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  animation: lcModalIn 0.18s cubic-bezier(0.4, 0, 0.2, 1);
}
@keyframes lcModalIn {
  from { opacity: 0; transform: translate(-50%, -52%) scale(0.97); }
  to   { opacity: 1; transform: translate(-50%, -50%) scale(1); }
}
.lc-close-modal-header {
  padding: 18px 46px 14px 20px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
  position: relative;
}
.lc-close-modal-ticket-meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 10px;
  margin-bottom: 6px;
}
.lc-close-modal-ticket-ref {
  font-family: 'SFMono-Regular', Consolas, monospace;
  font-size: 0.82rem;
  font-weight: 700;
  color: #4f46e5;
}
.lc-close-modal-ticket-domain {
  font-size: 0.71rem;
  color: var(--muted);
  background: var(--control-bg-hover);
  padding: 2px 7px;
  border-radius: 4px;
  text-transform: uppercase;
  letter-spacing: .04em;
}
.lc-close-modal-ticket-title {
  font-size: 0.94rem;
  font-weight: 600;
  color: var(--text-strong);
  line-height: 1.35;
}
.lc-close-modal-x {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 30px;
  height: 30px;
  border: none;
  background: var(--control-bg-hover);
  border-radius: 6px;
  cursor: pointer;
  font-size: 0.9rem;
  color: var(--muted);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.12s, color 0.12s;
  line-height: 1;
}
/* Fix bug tema oscuro: hover con #cbd5e1 (gris claro) + var(--text-strong) (claro
   en oscuro) hacía la X invisible. Overlay translúcido, legible en ambos temas. */
.lc-close-modal-x:hover { background: rgba(255, 255, 255, 0.14); color: var(--text-strong); }

.lc-close-modal-body {
  padding: 18px 20px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.lc-close-field {
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.lc-close-label {
  font-size: 0.71rem;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: .05em;
}
.lc-close-select {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--control-border);
  border-radius: 7px;
  font-family: inherit;
  font-size: 0.88rem;
  color: var(--text, #0f172a);
  background: var(--surface);
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
  cursor: pointer;
}
.lc-close-select:focus {
  border-color: #6366f1;
  box-shadow: 0 0 0 3px rgba(99,102,241,0.12);
}
.lc-close-textarea {
  width: 100%;
  min-height: 82px;
  padding: 9px 10px;
  border: 1px solid var(--control-border);
  border-radius: 7px;
  font-family: inherit;
  font-size: 0.88rem;
  resize: vertical;
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
  box-sizing: border-box;
  color: var(--text, #0f172a);
}
.lc-close-textarea:focus {
  border-color: #6366f1;
  box-shadow: 0 0 0 3px rgba(99,102,241,0.12);
}
.lc-close-modal-footer {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  padding: 14px 20px;
  border-top: 1px solid var(--border);
  background: var(--surface-2);
}

.btn-action--close-ticket {
  background: #dc2626;
  color: #fff;
  border: none;
  border-radius: 7px;
  padding: 8px 18px;
  font-size: 0.84rem;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  transition: background 0.15s;
}
.btn-action--close-ticket:hover:not(:disabled) { background: #b91c1c; }
.btn-action--close-ticket:disabled { opacity: 0.55; cursor: not-allowed; }

/* ============================================================
   Ticket detail modal
   ============================================================ */
.modal-card.modal-xl { max-width: 860px; }

.ticket-detail-modal .modal-header { align-items: flex-start; gap: 12px; }

.ticket-detail-title-block { flex: 1; min-width: 0; }

.ticket-detail-badges {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
  flex-wrap: wrap;
}

.ticket-ref-badge {
  font-family: 'Roboto Mono', ui-monospace, monospace;
  font-size: 0.78rem;
  font-weight: 600;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--muted);
  padding: 2px 8px;
  border-radius: 6px;
  letter-spacing: 0.04em;
}

.ticket-detail-title {
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--text);
  margin: 0;
  word-break: break-word;
}

/* La barra de scroll no se ve en reposo: aparece al pasar el puntero por el
   cuerpo del detalle. Lo que NO cambia nunca es su ancho — solo el color del
   pulgar. Hacerla crecer de 0 a 8 px al apuntar encogía la caja de contenido y
   empujaba todo a la izquierda; con el ancho fijo la geometría no se mueve.
   Los 8 px que ocupa salen del padding derecho (16 + 8 = los 24 de la izquierda),
   así que no añade hueco visible. */
.ticket-detail-body {
  padding: 0 16px 0 24px;
  overflow-y: auto;
  max-height: 62vh;
  display: flex;
  flex-direction: column;
  scrollbar-width: thin;
  scrollbar-color: transparent transparent;
}
.ticket-detail-body:hover { scrollbar-color: var(--control-border) transparent; }
.ticket-detail-body::-webkit-scrollbar { width: 8px; }
.ticket-detail-body::-webkit-scrollbar-thumb {
  background: transparent;
  border-radius: 8px;
  transition: background-color 0.2s ease;
}
.ticket-detail-body:hover::-webkit-scrollbar-thumb { background: var(--control-border); }

.ticket-detail-section {
  padding: 14px 0;
  border-bottom: 1px solid var(--border);
}

.ticket-detail-section:last-child { border-bottom: none; }

.ticket-detail-section-title {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--muted);
  margin-bottom: 10px;
}

.ticket-detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 10px 16px;
}

.ticket-detail-field { display: flex; flex-direction: column; gap: 3px; }

/* Información general del detalle: una tarjeta por BLOQUE de campos afines
   (clasificación, contacto, trazabilidad, asignación), no una por campo. En
   varias columnas para que quepa de un vistazo al abrir el modal, sin scroll.
   `auto-fit` (no `auto-fill`): las tarjetas presentes se estiran a llenar la
   fila en vez de dejar columnas fantasma. */
.ticket-detail-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 12px;
  align-items: start;
}

.ticket-detail-card {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 14px 14px;
}

.ticket-detail-card-title {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--muted-2);
  margin-bottom: 4px;
}

/* Dentro de la tarjeta: lista clave-valor a UNA columna, en formato tabla sin
   bordes — etiqueta de ancho fijo a la izquierda, valor pegado a su derecha y
   alineado a la izquierda. Los hijos son los <span> alternos (.tdl/.tdv), sin
   envoltorio por fila.

   Las filas se separan con una regla horizontal CONTINUA: por eso el hueco entre
   columnas es `padding-right` de la etiqueta y no `column-gap` — con gap la línea
   se partiría en dos trozos y aparecería una separación vertical falsa. */
.ticket-detail-list {
  display: grid;
  grid-template-columns: 116px minmax(0, 1fr);
  gap: 0;
  /* `stretch` (no `baseline`): con baseline cada celda se ajustaba a SU texto y,
     como la etiqueta y el valor tienen tamaños distintos, la línea de cada
     columna caía a distinta altura y se veía partida. Estirando, las dos celdas
     de una fila miden lo mismo y el borde inferior es uno solo continuo. */
  align-items: stretch;
}
.ticket-detail-list > * {
  padding: 8px 0;
  /* Alto de línea en px, igual para etiqueta y valor: iguala también la posición
     vertical del texto pese a la diferencia de `font-size`. */
  line-height: 20px;
  border-bottom: 1px solid var(--border-soft);
}
.ticket-detail-list > .tdl { padding-right: 12px; }
/* Solo ENTRE filas: la última no lleva línea, el borde de la tarjeta ya cierra. */
.ticket-detail-list > :nth-last-child(1),
.ticket-detail-list > :nth-last-child(2) { border-bottom: none; padding-bottom: 0; }
.ticket-detail-list .tdv {
  font-size: 0.875rem;
  color: var(--text);
  overflow-wrap: anywhere;
}

/* Fila compartida del detalle: reasignación (izquierda) + evidencias (derecha).
   `is-single` = el ticket no trae evidencias → la reasignación toma todo el ancho. */
.ticket-detail-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 8px 24px;
  align-items: start;
  padding: 14px 0;
  border-bottom: 1px solid var(--border);
}
.ticket-detail-split.is-single { grid-template-columns: minmax(0, 1fr); }
.ticket-detail-split:last-child { border-bottom: none; }
.ticket-detail-split > .ticket-detail-section { padding: 0; border-bottom: none; }
/* Separador vertical entre reasignación (izq.) y evidencias (der.). */
.ticket-detail-split > .ticket-detail-section + .ticket-detail-section {
  border-left: 1px solid var(--border-soft);
  padding-left: 24px;
}

@media (max-width: 860px) {
  .ticket-detail-split { grid-template-columns: minmax(0, 1fr); }
  .ticket-detail-list { grid-template-columns: 120px minmax(0, 1fr); }
  /* A una columna el separador pasa a horizontal: en vertical no separaría nada. */
  .ticket-detail-split > .ticket-detail-section + .ticket-detail-section {
    border-left: none;
    padding-left: 0;
    border-top: 1px solid var(--border-soft);
    padding-top: 14px;
  }
}

.tdl {
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--muted-2);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.ticket-detail-text {
  font-size: 0.875rem;
  color: var(--text);
  line-height: 1.65;
  white-space: pre-wrap;
  background: var(--panel-2);
  border-radius: 8px;
  padding: 10px 14px;
  border: 1px solid var(--border);
  margin: 0;
}

/* Evidence */
.ticket-evidence-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 12px;
}

.evidence-item {
  border-radius: 10px;
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--panel-2);
  display: block;
  text-decoration: none;
  transition: box-shadow 0.15s;
}

.evidence-item:hover { box-shadow: var(--shadow-md); }

.evidence-img {
  width: 100%;
  height: 150px;
  object-fit: cover;
  display: block;
  transition: opacity 0.15s;
}

.evidence-img:hover { opacity: 0.88; }

.evidence-video {
  width: 100%;
  height: 150px;
  display: block;
  background: #000;
}

.evidence-item--audio {
  grid-column: 1 / -1;
  padding: 12px;
}

.evidence-item--audio audio { width: 100%; }

.evidence-item--file {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 80px;
  color: var(--brand);
  font-size: 0.85rem;
  font-weight: 600;
}

.evidence-item--file:hover { background: var(--brand-soft-bg); }

.evidence-item--invalid {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 80px;
  padding: 10px 12px;
  border: 1px dashed #fca5a5;
  background: var(--badge-danger-bg);
  color: #b91c1c;
  font-size: 0.8rem;
  font-weight: 600;
  text-align: center;
}
.evidence-invalid-icon { font-size: 1rem; line-height: 1; }

/* Ticket status badges (bandeja + detail) */
.status-abierto    { background: rgba(59,130,246,0.1);  color: #2563eb; }
.status-tomado     { background: rgba(139,92,246,0.1);  color: #7c3aed; }
.status-en_proceso { background: rgba(245,158,11,0.1);  color: #d97706; }
.status-escalado   { background: rgba(239,68,68,0.1);   color: #dc2626; }
.status-resuelto   { background: rgba(16,185,129,0.1);  color: #059669; }
.status-cerrado    { background: rgba(100,116,139,0.1); color: var(--muted); }

/* Priority badge */
.priority-badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 999px;
  font-size: 0.75rem;
  font-weight: 600;
}

.priority-baja    { background: rgba(100,116,139,0.1); color: var(--muted); }
.priority-media   { background: rgba(59,130,246,0.1);  color: #2563eb; }
.priority-alta    { background: rgba(245,158,11,0.1);  color: #d97706; }
.priority-critica { background: rgba(239,68,68,0.1);   color: #dc2626; }

/* Ver button in ticket row */
.btn-detail { background: var(--brand-soft-bg); color: var(--brand-dark); border-color: #bfdbfe; }
.btn-detail:hover { background: #dbeafe; }

/* ============================================================
   Tutorial overlay
   ============================================================ */

/* Full-screen dark backdrop — blocks all pointer events on the page */
.tut-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.68);
  z-index: 2000;
  pointer-events: all;
}

/* Highlighted element lifts above the backdrop */
.tut-focused {
  position: relative !important;
  z-index: 2001 !important;
  pointer-events: none !important;   /* no interaction during tutorial */
  outline: 3px solid #3b82f6 !important;
  outline-offset: 6px !important;
  border-radius: 10px;
  animation: tut-pulse 1.8s ease-in-out infinite;
}

/* Keep sticky positioning for the header */
#tut-header.tut-focused {
  position: sticky !important;
}

@keyframes tut-pulse {
  0%, 100% { outline-color: #3b82f6; }
  50%       { outline-color: rgba(59, 130, 246, 0.35); }
}

/* Tooltip card — sits above highlighted element */
.tut-card {
  position: fixed;
  bottom: 40px;
  left: 50%;
  transform: translateX(-50%);
  width: min(480px, calc(100vw - 32px));
  background: var(--surface);
  border-radius: 20px;
  padding: 28px 28px 24px;
  box-shadow:
    0 24px 64px rgba(0, 0, 0, 0.28),
    0 0 0 1px rgba(0, 0, 0, 0.06);
  z-index: 2002;
  animation: tut-slide-in 0.25s ease;
}

@keyframes tut-slide-in {
  from { opacity: 0; transform: translateX(-50%) translateY(16px); }
  to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}

/* Header row: dots + counter */
.tut-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 20px;
}

.tut-dots {
  display: flex;
  gap: 6px;
}

.tut-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--control-bg-hover);
  transition: background 0.2s, transform 0.2s;
}

.tut-dot--on {
  background: #3b82f6;
  transform: scale(1.25);
}

.tut-counter {
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--muted-2);
  letter-spacing: 0.04em;
}

/* Icon */
.tut-icon {
  font-size: 2.25rem;
  margin-bottom: 12px;
  line-height: 1;
}

/* Title */
.tut-title {
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--text-strong);
  margin-bottom: 10px;
  letter-spacing: -0.02em;
}

/* Body text */
.tut-body {
  font-size: 0.9375rem;
  color: var(--muted);
  line-height: 1.6;
  margin-bottom: 24px;
}

/* Actions row */
.tut-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.tut-btn-group {
  display: flex;
  gap: 8px;
}

.tut-btn-skip {
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--muted-2);
  background: none;
  border: none;
  cursor: pointer;
  padding: 6px 4px;
  font-family: inherit;
  transition: color 0.15s;
}
.tut-btn-skip:hover { color: var(--muted); }

.tut-btn-prev,
.tut-btn-next {
  padding: 9px 18px;
  border-radius: 10px;
  font-size: 0.875rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: all 0.15s;
  border: none;
}

.tut-btn-prev {
  background: var(--surface-2);
  color: var(--muted);
}
.tut-btn-prev:hover { background: var(--control-bg-hover); }

.tut-btn-next {
  background: var(--brand-dark);
  color: #fff;
}
.tut-btn-next:hover { background: var(--brand-darker); }

/* Modules wrapper (tutorial target) */
#tut-modules {
  /* No visual impact — only provides the highlight target id */
}

/* ============================================================
   BOTONES GLOBALES (btn-primary / btn-secondary / btn-danger)
   ============================================================ */
.btn-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px 20px;
  border-radius: 10px;
  font-size: 0.875rem;
  font-weight: 600;
  font-family: inherit;
  border: none;
  cursor: pointer;
  transition: all 0.2s ease;
  background: var(--brand-dark);
  color: #fff;
}
.btn-primary:hover:not(:disabled) { background: var(--brand-darker); transform: translateY(-1px); box-shadow: 0 4px 12px rgba(var(--brand-dark-rgb),0.35); }
.btn-primary:active:not(:disabled) { transform: translateY(0); }
.btn-primary:disabled { opacity: 0.55; cursor: not-allowed; }

.btn-secondary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px 20px;
  border-radius: 10px;
  font-size: 0.875rem;
  font-weight: 600;
  font-family: inherit;
  border: 1px solid var(--border);
  cursor: pointer;
  transition: all 0.2s ease;
  background: var(--control-bg-hover);
  color: var(--text-strong);
}
/* Fix bug tema oscuro: el hover ponia un gris claro (#cbd5e1) con el texto claro
   heredado -> texto invisible. Overlay translucido + color de texto fijo, legible
   en ambos temas (light-mode conserva su override con --surface-2, abajo). */
.btn-secondary:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.14);
  border-color: rgba(255, 255, 255, 0.2);
  color: var(--text-strong);
}
.btn-secondary:disabled { opacity: 0.55; cursor: not-allowed; }

.btn-danger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 10px 20px;
  border-radius: 10px;
  font-size: 0.875rem;
  font-weight: 600;
  font-family: inherit;
  border: none;
  cursor: pointer;
  transition: all 0.2s ease;
  background: rgba(239,68,68,0.1);
  color: #dc2626;
  border: 1px solid rgba(239,68,68,0.25);
}
.btn-danger:hover:not(:disabled) { background: #ef4444; color: #fff; }
.btn-danger:disabled { opacity: 0.55; cursor: not-allowed; }

/* ============================================================
   PROFILE PAGE
   ============================================================ */

/* ── Layout ── */
.profile-page {
  min-height: 100vh;
  background: var(--bg);
  display: flex;
  flex-direction: column;
}

.profile-main {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 28px 32px;
  max-width: 860px;
  width: 100%;
  margin: 0 auto;
  box-sizing: border-box;
}

/* ── Tab nav ── */
.profile-tabs {
  display: flex;
  gap: 3px;
  margin-bottom: 24px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 4px;
  width: fit-content;
  max-width: 100%;
  overflow-x: auto;
}

.profile-tab {
  appearance: none;
  border: none;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font-size: 0.8125rem;
  font-weight: 600;
  font-family: inherit;
  padding: 8px 16px;
  white-space: nowrap;
  transition: all 0.15s ease;
}
.profile-tab:hover { color: var(--text); background: var(--control-bg-hover); }
.profile-tab--active {
  background: var(--brand-dark) !important;
  color: #fff !important;
  box-shadow: 0 1px 4px rgba(0,0,0,0.15);
}

/* ── Content area ── */
.profile-content {
  animation: fadeInUp 0.2s ease;
}

/* ── Card / form ── */
.profile-form {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 24px 28px 28px;
  box-shadow: var(--shadow-md);
}

.profile-section-title {
  font-size: 1rem;
  font-weight: 700;
  color: var(--text);
  margin: 0 0 20px;
  padding-bottom: 12px;
  border-bottom: 2px solid var(--border);
}

/* ── Inputs scoped to profile ── */
.profile-form .form-field input,
.profile-form .form-field select,
.profile-form .form-field textarea {
  width: 100%;
  box-sizing: border-box;
  padding: 10px 14px;
  border-radius: 9px;
  border: 1.5px solid var(--border);
  background: var(--surface-2);
  color: var(--text);
  font-size: 0.9rem;
  font-family: inherit;
  transition: border-color 0.2s, box-shadow 0.2s;
}
.profile-form .form-field input:focus,
.profile-form .form-field select:focus,
.profile-form .form-field textarea:focus {
  outline: none;
  border-color: var(--brand-dark);
  box-shadow: 0 0 0 3px rgba(37,99,235,0.1);
  background: var(--surface);
}
.profile-form .form-field input:disabled,
.profile-form .form-field select:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  background: var(--surface-2);
}

/* ── Helpers ── */
.profile-hint {
  font-size: 0.875rem;
  color: var(--muted);
  margin: 0 0 18px;
  line-height: 1.5;
}
.profile-hint strong { color: var(--text); }

.profile-row {
  display: flex;
  gap: 10px;
  align-items: center;
  margin-top: 20px;
  flex-wrap: wrap;
}

/* ── Info banner ── */
.info-banner {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 16px;
  border-radius: 10px;
  font-size: 0.875rem;
  font-weight: 500;
  border: 1px solid rgba(59,130,246,0.3);
  background: rgba(59,130,246,0.07);
  color: #1d4ed8;
  margin-bottom: 18px;
}

/* ── MFA ── */
.mfa-status {
  font-size: 0.9rem;
  color: var(--muted);
  margin-bottom: 20px;
}
.mfa-status strong { color: var(--text); }

.mfa-options {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.mfa-buttons {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}

/* ── TOTP ── */
.totp-qr-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  margin: 16px 0;
  padding: 20px;
  background: #fff; /* EXCEPCIÓN intencional: el QR necesita fondo claro para escanearse en ambos temas */
  border: 1.5px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow-md);
}

.totp-qr-img {
  width: 200px;
  height: 200px;
  border-radius: 8px;
  display: block;
}

.totp-secret {
  display: block;
  font-family: 'Courier New', Courier, monospace;
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 14px;
  word-break: break-all;
  color: var(--text);
  user-select: all;
}

/* ── Security questions ── */
.security-question-block {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px 18px;
  margin-bottom: 14px;
}

/* ── Responsive ── */
@media (max-width: 640px) {
  .profile-main { padding: 16px; }
  .profile-tabs { width: 100%; overflow-x: auto; }
  .profile-form { padding: 18px 16px 22px; }
  .mfa-buttons { flex-direction: column; }
  .profile-row { flex-direction: column; align-items: stretch; }
  .profile-row .btn-primary,
  .profile-row .btn-secondary { width: 100%; justify-content: center; }
}

/* ── Monitor health cards ── */
.monitor-health-grid {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 18px;
}

.monitor-health-card {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 10px 16px;
  min-width: 110px;
  display: flex;
  flex-direction: column;
  gap: 3px;
  box-shadow: 0 1px 3px rgba(0,0,0,.05);
  transition: box-shadow .15s;
}

.monitor-health-card:hover {
  box-shadow: 0 3px 8px rgba(0,0,0,.08);
}

.monitor-health-card-top {
  display: flex;
  align-items: center;
  gap: 7px;
}

.monitor-health-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}

.monitor-health-dot--ok   { background: #22c55e; }
.monitor-health-dot--warn { background: #f59e0b; animation: campPulse 1.5s infinite; }
.monitor-health-dot--err  { background: #ef4444; }
.monitor-health-dot--conn { background: #94a3b8; animation: campPulse 1s infinite; }

.monitor-health-name {
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text-strong);
}

.monitor-health-status {
  font-size: 0.68rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--muted);
}

.monitor-health-latency {
  font-size: 0.68rem;
  color: var(--muted-2);
  font-family: 'JetBrains Mono', monospace;
}

/* ── Monitor interno (tab "Interno" ticket management) ── */
.monitor-filters {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
  margin: 14px 0 16px;
  padding: 14px 16px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 12px;
}

.monitor-filters > select,
.monitor-filters > input[type="date"],
.monitor-filters > input[type="text"] {
  padding: 8px 12px;
  border: 1.5px solid var(--border);
  border-radius: 9px;
  background: var(--surface);
  color: var(--text);
  font-size: 0.88rem;
  min-width: 150px;
  height: 38px;
  transition: border-color 0.15s;
}

.monitor-filters > select:focus,
.monitor-filters > input:focus {
  outline: none;
  border-color: var(--brand-dark);
}

.monitor-filters > .btn-primary,
.monitor-filters > .btn-secondary {
  height: 38px;
  padding: 0 18px;
  flex-shrink: 0;
}

.monitor-filter-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.monitor-filter-field label {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--muted);
}

.monitor-filter-field input,
.monitor-filter-field select {
  min-width: 140px;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--surface);
  color: var(--text);
}

.monitor-filter-check {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 38px;
  padding: 0 12px;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: var(--surface);
  color: var(--text);
  font-size: 0.84rem;
  font-weight: 500;
  cursor: pointer;
}

.monitor-filter-check input {
  margin: 0;
  width: 16px;
  height: 16px;
  accent-color: var(--brand-dark);
  cursor: pointer;
}

.monitor-filter-check span {
  line-height: 1;
  white-space: nowrap;
}

.monitor-click-row {
  cursor: pointer;
}

.monitor-detail-row td {
  background: var(--surface-2);
}

.monitor-detail-panel {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px 18px;
  margin: 6px 0;
}

.monitor-detail-section {
  margin-bottom: 12px;
}

.monitor-detail-label {
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 5px;
}

.monitor-detail-text {
  display: block;
  margin: 0;
  white-space: pre-wrap;
  word-break: break-word;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  color: var(--text-strong);
  font-size: 0.84rem;
}

.monitor-terminal {
  background: #0f172a;
  color: #e2e8f0;
  border: 1px solid #1e293b;
  border-radius: 12px;
  padding: 14px 16px;
  min-height: 320px;
  max-height: 560px;
  overflow: auto;
}

.monitor-log-pre {
  margin: 0 0 10px;
  padding-bottom: 10px;
  border-bottom: 1px solid rgba(148, 163, 184, 0.18);
  font-size: 0.78rem;
  white-space: pre-wrap;
  word-break: break-word;
}

/* Log entry lines — colored by level */
.monitor-log-entry {
  padding: 2px 0;
  font-family: 'JetBrains Mono', 'Fira Code', 'Courier New', monospace;
  font-size: 0.78rem;
  white-space: pre-wrap;
  word-break: break-all;
  line-height: 1.55;
  border-bottom: 1px solid rgba(148, 163, 184, 0.06);
}
.monitor-log-entry--debug   { color: var(--muted); }
.monitor-log-entry--info    { color: var(--muted-2); }
.monitor-log-entry--warning { color: #fbbf24; }
.monitor-log-entry--error   { color: #f87171; }
.monitor-log-entry--critical { color: #f43f5e; font-weight: 700; }

/* Conversaciones — chat bubbles */
.monitor-context-list {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 8px 0;
  max-height: 620px;
  overflow-y: auto;
}

.monitor-msg {
  display: flex;
  flex-direction: column;
  max-width: 78%;
}
.monitor-msg--user  { align-self: flex-end;  align-items: flex-end; }
.monitor-msg--agent { align-self: flex-start; align-items: flex-start; }
.monitor-msg-role {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--muted);
  margin-bottom: 4px;
  text-transform: capitalize;
}
.monitor-msg-content {
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: 12px;
  font-size: 0.85rem;
  white-space: pre-wrap;
  word-break: break-word;
  line-height: 1.55;
  color: var(--text-strong);
  background: var(--surface);
}
.monitor-msg--user  .monitor-msg-content {
  background: var(--brand-soft-bg);
  border-color: #bfdbfe;
  color: #1e3a5f;
  border-radius: 12px 12px 4px 12px;
}
.monitor-msg--agent .monitor-msg-content {
  border-radius: 12px 12px 12px 4px;
}

.monitor-context-item {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px 14px;
}

.monitor-context-item pre {
  margin: 0;
  white-space: pre-wrap;
  word-break: break-word;
}

.monitor-pagination {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  margin-top: 14px;
}

.monitor-page-info {
  color: var(--muted);
  font-size: 0.82rem;
}

.monitor-breadcrumb {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}

.monitor-cards-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 14px;
}

.monitor-channel-card {
  text-align: left;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 16px;
  cursor: pointer;
  box-shadow: 0 10px 30px rgba(0,0,0,0.12);
  transition: transform .15s ease, border-color .15s ease, box-shadow .15s ease, background .15s ease;
}

.monitor-channel-card:hover {
  transform: translateY(-2px);
  border-color: #3b82f6;
  box-shadow: 0 14px 34px rgba(37,99,235,0.18);
}

.monitor-channel-title {
  font-size: 1rem;
  font-weight: 700;
  margin-bottom: 12px;
}

.monitor-channel-stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}

.monitor-channel-stats div {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 10px;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.monitor-channel-stats span {
  font-size: 0.7rem;
  color: var(--muted-2);
  text-transform: uppercase;
}

.monitor-channel-stats strong {
  font-size: 0.95rem;
  color: var(--text-strong);
}

.monitor-channel-footer {
  margin-top: 12px;
  font-size: 0.76rem;
  color: var(--muted-2);
}

.monitor-users-actions {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 12px;
}

.monitor-exec-table td,
.monitor-exec-table th {
  white-space: nowrap;
}

.monitor-provider-badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 700;
}

.monitor-provider-openrouter { background: var(--badge-info-bg); color: var(--badge-info-fg); }
.monitor-provider-gemini { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.monitor-provider-kimi { background: var(--badge-warn-bg); color: var(--badge-warn-fg); }
.monitor-provider-deepseek { background: var(--badge-purple-bg); color: var(--badge-purple-fg); }
.monitor-provider-other { background: var(--badge-neutral-bg); color: var(--badge-neutral-fg); }

.monitor-inline-flag {
  margin-left: 6px;
}

.monitor-row-error td { background: var(--badge-danger-bg); }
.monitor-row-timeout td { background: var(--surface)7ed; }
.monitor-row-running td { background: var(--brand-soft-bg); }
.monitor-row-tool-warn td { background: var(--surface)beb; }

/* ── Monitor detail v2: header bar ────────────────────────────────── */
.monitor-detail-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 18px;
  padding: 10px 14px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 9px;
  margin-bottom: 12px;
}
.monitor-detail-meta-item {
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.monitor-detail-meta-key {
  font-size: 0.65rem;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--muted-2);
  letter-spacing: .04em;
}
.monitor-detail-meta-val {
  font-size: 0.82rem;
  color: var(--text-strong);
}
.monitor-detail-meta-val--bold { font-weight: 700; }

/* ── Token grid ────────────────────────────────────────────────────── */
.monitor-token-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(90px, 1fr));
  gap: 8px;
  margin-top: 6px;
}
.monitor-token-grid--sm {
  grid-template-columns: repeat(auto-fill, minmax(90px, 1fr));
}
.monitor-token-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 10px 8px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  text-align: center;
  gap: 4px;
  min-width: 0;
}
.monitor-token-cell--total {
  border-color: var(--brand);
  background: var(--brand-soft-bg);
}
.monitor-token-cell--prompt { border-color: #93c5fd; background: var(--brand-soft-bg); }
.monitor-token-cell--compl  { border-color: #86efac; background: var(--badge-success-bg); }
.monitor-token-cell--think  { border-color: #d8b4fe; background: var(--badge-purple-bg); }
.monitor-token-cell-label {
  font-size: 0.64rem;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--muted);
  letter-spacing: .04em;
}
.monitor-token-cell-val {
  font-size: 1.1rem;
  font-weight: 800;
  color: var(--text-strong);
}
.monitor-token-cell--total  .monitor-token-cell-val { color: var(--brand-dark); }
.monitor-token-cell--prompt .monitor-token-cell-val { color: #1d4ed8; }
.monitor-token-cell--compl  .monitor-token-cell-val { color: #15803d; }
.monitor-token-cell--think  .monitor-token-cell-val { color: #7c3aed; }

/* ── Media analysis input block ───────────────────────────────────── */
.monitor-media-block {
  margin-top: 10px;
  padding: 12px 14px;
  background: var(--badge-warn-bg);
  border: 1px solid #fde68a;
  border-radius: 8px;
}
.monitor-media-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
  font-size: 0.83rem;
  color: #78350f;
  margin: 8px 0 0;
}
.monitor-media-meta span {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px;
  background: rgba(253,230,138,0.5);
  border-radius: 5px;
}

/* ── Round accordion ──────────────────────────────────────────────── */
.monitor-round-accordion {
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
  background: var(--surface);
}
.monitor-round-accordion-header {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  cursor: pointer;
  user-select: none;
  background: var(--surface-2);
  transition: background 0.12s;
}
.monitor-round-accordion-header:hover { background: var(--surface-2); }
.monitor-round-toggle {
  font-size: 0.82rem;
  color: var(--muted);
  width: 14px;
  flex-shrink: 0;
}
.monitor-round-accordion-title {
  font-weight: 700;
  font-size: 0.88rem;
  color: var(--text-strong);
}
.monitor-round-accordion-meta {
  font-size: 0.78rem;
  color: var(--muted);
  margin-left: auto;
}
.monitor-round-accordion-body {
  padding: 12px 14px;
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* ── Thinking block ───────────────────────────────────────────────── */
.monitor-thinking-block {
  background: var(--badge-purple-bg);
  border: 1px solid #e9d5ff;
  border-radius: 8px;
  padding: 10px 12px;
}

/* ── Detail panel: prevent horizontal overflow inside scrollable table ── */
.monitor-detail-panel {
  min-width: 0;
  overflow-x: hidden;
}
pre.monitor-detail-text {
  overflow-x: auto;
  max-height: 260px;
}

/* ── Tool card header + I/O two-column ───────────────────────────── */
.monitor-tool-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 5px 10px;
  margin-bottom: 10px;
}
.monitor-tool-name {
  font-weight: 700;
  font-size: 0.88rem;
  color: var(--text-strong);
}
.monitor-tool-mcp {
  font-size: 0.76rem;
  color: #6366f1;
  background: var(--brand-soft-bg);
  padding: 2px 7px;
  border-radius: 5px;
  font-weight: 600;
}
.monitor-tool-ronda,
.monitor-tool-dur {
  font-size: 0.76rem;
  color: var(--muted);
}
.monitor-tool-io {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
}

/* ── Agent output error state ────────────────────────────────────── */
.monitor-output-error {
  background: var(--badge-danger-bg);
  border: 1px solid #fecaca;
  border-radius: 8px;
  padding: 12px 14px;
  color: #991b1b;
  font-size: 0.88rem;
  white-space: pre-wrap;
  word-break: break-word;
}

/* ── Media output blocks ─────────────────────────────────────────── */
.monitor-media-out-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 10px;
}
.monitor-media-out-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 0.84rem;
}
.monitor-media-out-type {
  font-weight: 700;
  font-size: 0.68rem;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--control-bg-hover);
  padding: 2px 6px;
  border-radius: 4px;
}

/* ── Input preview in executions table ───────────────────────────── */
.monitor-exec-input-preview {
  color: var(--muted);
  font-size: 0.79rem;
  font-style: italic;
  max-width: 220px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  display: block;
}

@media (max-width: 900px) {
  .monitor-token-grid        { grid-template-columns: repeat(2, 1fr); }
  .monitor-token-grid--sm    { grid-template-columns: 1fr; }
  .monitor-tool-io           { grid-template-columns: 1fr; }
  .monitor-drawer            { width: 100vw; }
}

/* ── Drawer de detalle de ejecución ─────────────────────────────────── */
.monitor-drawer-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.38);
  backdrop-filter: blur(2px);
  z-index: 900;
}
.monitor-drawer {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(700px, 92vw);
  background: var(--surface-overlay);
  z-index: 901;
  display: flex;
  flex-direction: column;
  box-shadow: -6px 0 32px rgba(0, 0, 0, 0.14);
  animation: drawerSlideIn 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
@keyframes drawerSlideIn {
  from { transform: translateX(100%); }
  to   { transform: translateX(0); }
}
.monitor-drawer-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
  flex-shrink: 0;
  gap: 12px;
}
.monitor-drawer-title {
  font-size: 0.97rem;
  font-weight: 700;
  color: var(--text-strong);
}
.monitor-drawer-subtitle {
  font-size: 0.76rem;
  color: var(--muted);
  margin-top: 2px;
  font-family: 'SFMono-Regular', Consolas, monospace;
  letter-spacing: .03em;
}
.monitor-drawer-close {
  width: 34px;
  height: 34px;
  border: none;
  background: var(--control-bg-hover);
  border-radius: 7px;
  cursor: pointer;
  font-size: 1rem;
  color: var(--muted);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  transition: background 0.12s, color 0.12s;
  line-height: 1;
}
.monitor-drawer-close:hover {
  background: #cbd5e1;
  color: var(--text-strong);
}
.monitor-drawer-body {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
}

.monitor-detail-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

.monitor-detail-section--full {
  grid-column: 1 / -1;
}

.monitor-rounds-list,
.monitor-tools-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.monitor-round-card,
.monitor-tool-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 12px;
}

.monitor-round-title,
.monitor-tool-title {
  font-weight: 700;
  color: var(--text-strong);
  margin-bottom: 8px;
}

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

  .monitor-detail-section--full {
    grid-column: auto;
  }
}

/* ============================================================
   Workflow Visualizer (logs en vivo — vista workflow)
   ============================================================ */

.wf-view-toggle {
  display: flex;
  gap: 6px;
  margin-bottom: 12px;
}

.wf-toggle-btn {
  padding: 5px 14px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--muted);
  font-size: 0.8rem;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.15s;
}

/* El !important está para ganarle a la regla global `.active` de la cabecera de
   este archivo, que impone --brand-dark a cualquier `.active`. Aquí el toggle
   marca "vista seleccionada", no una acción de marca, así que usa la superficie
   invertida. Antes iban dos hexes fijos (#1e293b/#e2e8f0) que en tema claro daban
   un botón oscuro; ahora sale de tokens y conmuta. */
.wf-toggle-btn.active {
  background: var(--panel-2) !important;
  color: var(--text-strong) !important;
  border-color: var(--border);
}

/* Container */
.wf-container {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-height: 72vh;
  overflow-y: auto;
  padding-right: 4px;
}

.wf-container::-webkit-scrollbar { width: 4px; }
.wf-container::-webkit-scrollbar-thumb { background: #334155; border-radius: 2px; }

/* Empty state */
.wf-empty-state {
  text-align: center;
  padding: 48px 20px;
  color: var(--muted);
  /* Tokenizado: era #0f172a fijo, un rectángulo oscuro en pleno tema claro. */
  background: var(--surface-2);
  border-radius: 10px;
}

.wf-empty-icon { font-size: 36px; margin-bottom: 10px; }
.wf-empty-state p { font-size: 0.85rem; }

/* Execution card */
.wf-card {
  background: #1a1d27;
  border: 1px solid #2e3348;
  border-radius: 10px;
  overflow: hidden;
  transition: border-color 0.2s;
  flex-shrink: 0;
}

.wf-card--running { border-color: #4f6ef7; box-shadow: 0 0 0 1px rgba(79,110,247,0.15); }
.wf-card--done    { border-color: #22c55e; }
.wf-card--error   { border-color: #ef4444; }

/* Card header */
.wf-card-header {
  padding: 9px 14px;
  display: flex;
  align-items: center;
  gap: 10px;
  background: #22263a;
  border-bottom: 1px solid #2e3348;
  flex-wrap: wrap;
}

.wf-req    { font-family: monospace; font-size: 10px; color: var(--muted); flex-shrink: 0; }
.wf-user   { font-size: 11px; color: #06b6d4; }
.wf-canal  { font-size: 11px; color: #a855f7; }
.wf-time   { font-size: 11px; color: var(--muted); margin-left: auto; }

.wf-badge  { padding: 2px 7px; border-radius: 4px; font-size: 10px; font-weight: 700; flex-shrink: 0; }

/* Pipeline flow */
.wf-pipeline-flow {
  padding: 16px 14px 12px;
  display: flex;
  align-items: center;
  overflow-x: auto;
}

.wf-pipeline-flow::-webkit-scrollbar { height: 3px; }
.wf-pipeline-flow::-webkit-scrollbar-thumb { background: #2e3348; border-radius: 2px; }

/* Node */
.wf-node { flex-shrink: 0; }

.wf-node-box {
  width: 100px;
  background: #0f1117;
  border: 1.5px solid #2e3348;
  border-radius: 10px;
  padding: 9px 6px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  transition: all 0.25s;
  position: relative;
}

.wf-node-box.pending { opacity: 0.32; }

.wf-node-box.active {
  border-color: #4f6ef7;
  box-shadow: 0 0 0 3px rgba(79,110,247,0.25);
  background: rgba(79,110,247,0.04);
}

.wf-node-box.active::after {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: 10px;
  border: 1.5px solid #4f6ef7;
  animation: wf-pulse-border 1.5s ease-out infinite;
  pointer-events: none;
}

@keyframes wf-pulse-border {
  0%   { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.07); }
}

.wf-node-box.done {
  border-color: #22c55e;
  box-shadow: 0 0 10px rgba(34,197,94,0.3);
  background: rgba(34,197,94,0.04);
}

.wf-node-box.error {
  border-color: #ef4444;
  background: rgba(239,68,68,0.05);
}

.wf-node-box.active .wf-node-label { color: #6c8af7; }
.wf-node-box.done   .wf-node-label { color: #22c55e; }
.wf-node-box.error  .wf-node-label { color: #ef4444; }

.wf-node-icon   { font-size: 18px; line-height: 1; }
.wf-node-label  { font-size: 10px; font-weight: 600; color: var(--muted-2); text-align: center; }
.wf-node-detail { font-size: 8px; color: var(--muted); text-align: center; max-width: 90px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Round dots inside agent node */
.wf-rounds-row { display: flex; gap: 3px; flex-wrap: wrap; justify-content: center; margin-top: 3px; }
.wf-round-dot  { width: 6px; height: 6px; border-radius: 50%; background: #2e3348; }
.wf-round-dot.tool  { background: #f97316; box-shadow: 0 0 4px rgba(249,115,22,0.5); }
.wf-round-dot.final { background: #22c55e; }

/* Edge connector */
.wf-edge { flex-shrink: 0; display: flex; align-items: center; width: 28px; }

.wf-edge-line {
  height: 2px;
  width: 100%;
  background: #2e3348;
  border-radius: 1px;
  transition: background 0.3s;
}

.wf-edge-line.lit {
  background: #22c55e;
  box-shadow: 0 0 6px rgba(34,197,94,0.4);
}

/* Tool cluster */
.wf-tool-cluster {
  padding: 8px 14px 4px;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  border-top: 1px solid #2e3348;
}

.wf-mcp-bubble {
  background: #0f1117;
  border: 1px solid #2e3348;
  border-radius: 8px;
  padding: 6px 8px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  min-width: 70px;
}

.wf-mcp-label   { font-size: 8px; color: var(--muted); font-weight: 700; text-transform: uppercase; letter-spacing: 0.5px; }
.wf-tool-pills  { display: flex; flex-wrap: wrap; gap: 3px; justify-content: center; }

.wf-tool-pill {
  border-radius: 20px;
  padding: 2px 6px;
  font-size: 9px;
  border: 1px solid #2e3348;
  color: var(--muted-2);
  background: #22263a;
}

.wf-tool-pill.ok   { border-color: rgba(34,197,94,0.4);  color: #22c55e; }
.wf-tool-pill.fail { border-color: rgba(239,68,68,0.4);  color: #ef4444; }

/* Metrics bar */
.wf-metrics-bar {
  padding: 7px 14px 10px;
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  border-top: 1px solid #2e3348;
}

.wf-metric       { display: flex; flex-direction: column; gap: 2px; }
.wf-metric-key   { font-size: 8px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.5px; }
.wf-metric-val   { font-size: 11px; font-weight: 600; color: #e2e8f0; font-family: monospace; }
.wf-metric-val.blue   { color: #06b6d4; }
.wf-metric-val.purple { color: #a855f7; }
.wf-metric-val.green  { color: #22c55e; }
.wf-metric-val.orange { color: #f97316; }

/* Log trail */
.wf-log-trail { padding: 0 14px 10px; border-top: 1px solid #2e3348; }

.wf-log-trail-toggle {
  font-size: 10px;
  color: var(--muted);
  cursor: pointer;
  padding: 6px 0 2px;
  user-select: none;
  transition: color 0.15s;
}

.wf-log-trail-toggle:hover { color: var(--muted-2); }

.wf-log-list {
  margin-top: 4px;
  display: flex;
  flex-direction: column;
  gap: 1px;
  max-height: 140px;
  overflow-y: auto;
}

.wf-log-list::-webkit-scrollbar { width: 3px; }
.wf-log-list::-webkit-scrollbar-thumb { background: #2e3348; }

.wf-log-entry {
  font-family: monospace;
  font-size: 9px;
  color: var(--muted);
  padding: 2px 4px;
  border-radius: 3px;
  line-height: 1.5;
}

.wf-log-entry:hover    { background: #22263a; color: var(--muted-2); }
.wf-log-entry.level-warn  { color: #eab308; }
.wf-log-entry.level-error { color: #ef4444; }

@media (max-width: 900px) {
  .wf-pipeline-flow { gap: 0; }
  .wf-node-box { width: 80px; }
  .wf-node-label { font-size: 9px; }
  .wf-edge { width: 18px; }
}

/* ============================================================
   Módulo Multimedia
   ============================================================ */
.mm-page { padding: 28px 32px; }
.mm-header { margin-bottom: 20px; }
.mm-title { font-size: 1.5rem; font-weight: 700; color: var(--text); margin: 10px 0 4px; }
.mm-subtitle { color: var(--muted); font-size: 0.88rem; margin: 0; }
.mm-banner {
  margin-bottom: 16px;
  padding: 11px 14px;
  border-radius: 10px;
  border: 1px solid rgba(59, 130, 246, 0.30);
  background: rgba(59, 130, 246, 0.08);
  color: var(--brand-dark);
  font-size: 0.86rem;
}
.mm-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 20px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.04);
  margin-bottom: 16px;
}
.mm-row,
.mm-toolbar {
  display: flex;
  gap: 12px;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
}
.mm-toolbar { margin-top: 14px; }
.mm-section-title { font-size: 1rem; font-weight: 700; color: var(--text); margin-bottom: 4px; }
.mm-helper { color: var(--muted); font-size: 0.82rem; }
.mm-error { color: var(--badge-danger-fg); font-size: 0.82rem; margin-top: 6px; }
.mm-buckets {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 12px;
  margin-top: 16px;
}
.mm-bucket {
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface);
  padding: 14px;
  text-align: left;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
  display: grid;
  gap: 6px;
}
.mm-bucket:hover {
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
  border-color: var(--brand);
}
.mm-bucket--active {
  border-color: var(--brand);
  background: rgba(59, 130, 246, 0.06);
  box-shadow: 0 0 0 1px var(--brand) inset;
}
.mm-bucket span { color: var(--text); }
.mm-bucket small { color: var(--muted); font-size: 0.75rem; }
.mm-input,
.mm-select,
.mm-file {
  min-height: 40px;
  border: 1px solid var(--control-border);
  border-radius: 8px;
  padding: 9px 12px;
  background: var(--control-bg);
  color: var(--text);
  font-size: 0.88rem;
  font-family: inherit;
}
.mm-input:focus,
.mm-select:focus,
.mm-file:focus { outline: none; border-color: var(--brand); }
.mm-input { min-width: 240px; flex: 1 1 240px; }
.mm-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 38px;
  padding: 0 14px;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text);
  font-size: 0.85rem;
  font-weight: 600;
  font-family: inherit;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.mm-btn:hover { background: var(--panel-2); }
.mm-btn--sm { min-height: 32px; padding: 0 10px; font-size: 0.78rem; font-weight: 500; }
.mm-btn--ghost { background: transparent; border-color: transparent; color: var(--muted); }
.mm-btn--ghost:hover { background: var(--panel-2); color: var(--text); }
.mm-btn--primary {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
}
.mm-btn--primary:hover { background: var(--brand-dark); border-color: var(--brand-dark); }
.mm-btn--danger {
  color: var(--danger);
  border-color: rgba(239, 68, 68, 0.35);
  background: var(--surface);
}
.mm-btn--danger:hover { background: rgba(239, 68, 68, 0.08); border-color: var(--danger); }
.mm-objects {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 14px;
  margin-top: 16px;
}
.mm-object {
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  background: var(--surface);
  display: flex;
  flex-direction: column;
  transition: box-shadow 0.15s ease, border-color 0.15s ease;
}
.mm-object:hover { box-shadow: var(--shadow-md); }
.mm-thumb {
  display: block;
  width: 100%;
  height: 170px;
  object-fit: cover;
  background: var(--panel-2);
}
.mm-fileicon {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 170px;
  background: linear-gradient(135deg, var(--panel-2) 0%, #e2e8f0 100%);
  color: var(--muted);
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.mm-object-info { padding: 14px; display: grid; gap: 8px; }
.mm-object-key {
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.mm-item-desc { color: var(--muted); font-size: 0.8rem; }
.mm-object-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.mm-empty {
  margin-top: 14px;
  padding: 20px;
  border: 1px dashed var(--border);
  border-radius: 10px;
  color: var(--muted);
  background: var(--panel-2);
  font-size: 0.86rem;
  text-align: center;
}

/* ── Discos: cabecera de fila con acciones ──────────────────── */
.mm-row-actions { display: flex; gap: 8px; align-items: center; }

/* ── Tarjeta de disco: nombre, barra de uso y etiquetas ─────── */
.mm-bucket-name { font-weight: 700; color: var(--text); }
.mm-usage { margin-top: 8px; display: flex; flex-direction: column; gap: 4px; }
.mm-usage-track {
  width: 100%;
  height: 6px;
  border-radius: 999px;
  background: var(--border);
  overflow: hidden;
}
.mm-usage-bar {
  height: 100%;
  border-radius: 999px;
  background: var(--brand);
  transition: width 0.3s ease;
}
.mm-usage-bar.full { background: var(--danger); }
.mm-usage-text { color: var(--muted); font-size: 0.78rem; }
.mm-bucket-tags { display: flex; gap: 6px; margin-top: 8px; flex-wrap: wrap; }
.mm-tag {
  font-size: 0.72rem;
  font-weight: 600;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--panel-2);
  color: var(--muted);
  border: 1px solid var(--border);
}

/* ── Breadcrumbs del explorador ─────────────────────────────── */
.mm-crumbs {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 2px;
  margin: 12px 0;
  padding: 8px 12px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.mm-crumb-item { display: inline-flex; align-items: center; gap: 2px; }
.mm-crumb {
  background: none;
  border: none;
  color: var(--brand-dark);
  cursor: pointer;
  font-size: 0.85rem;
  font-weight: 500;
  font-family: inherit;
  padding: 2px 6px;
  border-radius: 6px;
}
.mm-crumb:hover { background: rgba(59, 130, 246, 0.10); }
.mm-crumb-sep { color: var(--muted); padding: 0 1px; }

/* ── Barra de subida en el directorio actual ────────────────── */
.mm-uploadbar {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
  flex-wrap: wrap;
}

/* ── Barra de búsqueda y filtros del explorador ─────────────── */
.mm-filters {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 14px;
  padding: 10px 12px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 12px;
}
.mm-filter-search {
  flex: 1 1 220px;
  min-width: 180px;
}
/* Los selects del explorador necesitan más ancho que los del modal "Crear disco". */
.mm-filters .mm-select {
  max-width: none;
  flex: 0 0 auto;
  min-width: 140px;
}
.mm-filter-date {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.82rem;
  color: var(--muted);
  white-space: nowrap;
}
.mm-filters .mm-input--narrow {
  flex: 0 0 auto;
  width: auto;
  min-width: 130px;
  max-width: 150px;
}
.mm-filter-count {
  margin-left: auto;
  font-size: 0.82rem;
  color: var(--muted);
  white-space: nowrap;
}
@media (max-width: 720px) {
  .mm-filter-count { margin-left: 0; }
  .mm-filters .mm-select,
  .mm-filter-search { flex: 1 1 100%; }
}

/* ── Carpeta (tarjeta clicable) ─────────────────────────────── */
.mm-folder { cursor: pointer; }
.mm-folder:hover { border-color: var(--brand); }
.mm-foldericon {
  background: linear-gradient(135deg, rgba(59, 130, 246, 0.14), rgba(59, 130, 246, 0.05));
  color: var(--brand-dark);
  font-size: 2.4rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ── Modal "Crear disco" ────────────────────────────────────── */
.mm-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: 16px;
}
.mm-modal {
  background: var(--surface-overlay);
  border: 1px solid var(--border);
  border-radius: 14px;
  padding: 24px;
  width: 100%;
  max-width: 460px;
  max-height: 90vh;
  overflow-y: auto;
  box-shadow: var(--shadow-lg);
}
.mm-modal .mm-section-title { margin-bottom: 2px; }
.mm-field-label {
  display: block;
  margin: 14px 0 6px;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text);
}
.mm-field-row { display: flex; gap: 8px; align-items: center; }
.mm-field-inline { display: flex; gap: 6px; align-items: center; color: var(--text); font-size: 0.88rem; }
.mm-select { max-width: 90px; cursor: pointer; }
/* Selector a ancho completo (p.ej. la duración del enlace): anula el cap de 90px que
   sirve al selector de unidad MB/GB inline, manteniendo el resto del estilo de mm-select. */
.mm-select--wide { max-width: 100%; }
.mm-input--narrow { max-width: 80px; min-width: 0; flex: 0 0 80px; }
.mm-check {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
  font-size: 0.88rem;
  color: var(--text);
  cursor: pointer;
}
.mm-modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 22px;
}

@media (max-width: 900px) {
  .mm-page { padding: 22px 16px; }
  .mm-objects,
  .mm-buckets { grid-template-columns: 1fr; }
}

/* ============================================================
   Módulo QA — homogéneo con el resto del panel (mismos tokens)
   ============================================================ */
.qa-page { padding: 28px 32px; }
/* El PageHeader rompe el padding del root para quedar a ancho completo (igual
   que en .page-container), no constreñido por el contenido del módulo. */
.qa-page > .ph,
.mm-page > .ph,
.campaigns-page > .ph {
  margin: -28px -32px 18px;
}
.qa-header { margin-bottom: 20px; }
.qa-header-row { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; margin-top: 10px; }
.qa-title { font-size: 1.5rem; font-weight: 700; color: var(--text); margin: 0 0 4px; }
.qa-subtitle { color: var(--muted); font-size: 0.88rem; margin: 0; }
.qa-actions { display: flex; gap: 8px; flex-shrink: 0; }

.qa-card { background: rgba(255,255,255,0.05); border: 1px solid var(--border); border-radius: 12px; padding: 20px; box-shadow: 0 1px 4px rgba(0,0,0,0.1); margin-bottom: 16px; }
.qa-section-title { font-size: 1rem; font-weight: 700; color: var(--text); margin: 0 0 12px; }

.qa-btn { padding: 7px 14px; border-radius: 8px; border: 1px solid var(--border); background: rgba(255,255,255,0.06); color: var(--text); font-size: 0.85rem; font-weight: 600; font-family: inherit; cursor: pointer; transition: all 0.15s; }
.qa-btn:hover:not(:disabled) { background: rgba(255,255,255,0.1); }
.qa-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.qa-btn--primary { background: var(--brand-dark); color: #fff; border-color: var(--brand-dark); }
.qa-btn--primary:hover:not(:disabled) { background: var(--brand-darker); }
.qa-btn--danger { color: #dc2626; border-color: #fca5a5; }
.qa-btn--danger:hover:not(:disabled) { background: var(--badge-danger-bg); }
.qa-btn--sm { padding: 4px 10px; font-size: 0.78rem; font-weight: 500; }

.qa-label { display: block; font-size: 0.8rem; font-weight: 600; color: var(--muted); margin: 10px 0 4px; }
.qa-input, .qa-textarea { width: 100%; padding: 9px 12px; border: 1px solid var(--border); border-radius: 8px; font-size: 0.88rem; font-family: inherit; box-sizing: border-box; color: var(--text); }
.qa-input:focus, .qa-textarea:focus { outline: none; border-color: #3b82f6; }
.qa-textarea { resize: vertical; min-height: 90px; }
.qa-form-actions { display: flex; gap: 8px; margin-top: 14px; }

.qa-item { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 12px 14px; border: 1px solid var(--border); border-radius: 10px; margin-bottom: 8px; }
.qa-item-name { font-weight: 600; color: var(--text); }
.qa-item-id { color: var(--muted); font-size: 0.82rem; }
.qa-item-desc { color: var(--muted); font-size: 0.82rem; margin-top: 2px; }
.qa-item-actions { display: flex; gap: 6px; flex-shrink: 0; }

.qa-run { display: flex; justify-content: space-between; align-items: center; padding: 10px 14px; border: 1px solid var(--border); border-radius: 8px; margin-bottom: 6px; cursor: pointer; transition: background 0.15s; }
.qa-run:hover { background: var(--surface-2); }

.qa-banner { padding: 10px 16px; border-radius: 8px; font-size: 0.88rem; margin-bottom: 16px; background: var(--brand-soft-bg); color: #1d4ed8; border: 1px solid #bfdbfe; }
.qa-empty { color: var(--muted); font-size: 0.88rem; padding: 8px 0; }

.qa-result { padding: 8px 0; border-bottom: 1px solid var(--border); }
.qa-tag { font-weight: 700; }
.qa-tag--pass { color: #16a34a; }
.qa-tag--fail { color: #dc2626; }

.qa-help { background: var(--surface-2); border: 1px solid var(--border); border-radius: 8px; padding: 10px 14px; color: var(--muted); font-size: 0.82rem; margin-bottom: 16px; line-height: 1.5; }
.qa-assert { font-size: 0.82rem; margin: 3px 0; color: var(--text); }
.qa-assert-ev { color: var(--muted); }
.qa-transcript { margin-top: 8px; }
.qa-transcript summary { cursor: pointer; color: var(--muted); font-size: 0.8rem; }
.qa-msg { font-size: 0.82rem; padding: 4px 0; border-bottom: 1px solid var(--border); }
.qa-msg-role { font-weight: 600; color: var(--muted); margin-right: 6px; }

/* Impresión / PDF: aísla el detalle de la corrida */
@media print {
  body * { visibility: hidden; }
  .qa-print-area, .qa-print-area * { visibility: visible; }
  .qa-print-area { position: absolute; left: 0; top: 0; width: 100%; box-shadow: none !important; border: none !important; }
  .qa-noprint { display: none !important; }
  .qa-transcript[open] summary { display: none; }
}

/* ── Colored action pill buttons (dark theme) ──────────────────────── */
.btn-detail  { background: rgba(37,99,235,0.12);  color: #60a5fa;  border-color: rgba(59,130,246,0.28); }
.btn-detail:hover:not(:disabled)  { background: rgba(37,99,235,0.22);  border-color: rgba(59,130,246,0.45); }

.btn-tomar   { background: rgba(16,185,129,0.1);  color: #34d399;  border-color: rgba(16,185,129,0.28); }
.btn-tomar:hover:not(:disabled)   { background: rgba(16,185,129,0.2);  border-color: rgba(16,185,129,0.45); }

/* .btn-cerrar: color retirado (lo fija "BOTONES", variante peligro). */
.btn-cerrar:hover:not(:disabled)  { background: rgba(239,68,68,0.2);   border-color: rgba(239,68,68,0.45); }

.btn-asignar { background: rgba(139,92,246,0.1);  color: #a78bfa;  border-color: rgba(139,92,246,0.28); }
.btn-asignar:hover:not(:disabled) { background: rgba(139,92,246,0.2);  border-color: rgba(139,92,246,0.45); }

/* Ticket missing utilities */

.btn-action--danger {
  background: rgba(239,68,68,0.12);
  color: #f87171;
  border: 1px solid rgba(239,68,68,0.25);
}
.btn-action--danger:hover:not(:disabled) {
  background: rgba(239,68,68,0.22);
  border-color: rgba(239,68,68,0.4);
}
.btn-action--danger:disabled { opacity: 0.45; cursor: not-allowed; }

.ticket-detail-field span:last-child {
  font-size: 0.875rem;
  color: #cbd5e1;
}

.form-field-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 8px;
}

.input-req-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 4px;
}

.input-req-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.input-req-row select,
.input-req-row input[type="text"] {
  flex: 1;
  min-width: 100px;
  padding: 7px 10px;
  border: 1px solid rgba(255,255,255,0.09);
  border-radius: 8px;
  background: rgba(255,255,255,0.05);
  color: #e2e8f0;
  font: inherit;
  font-size: 0.82rem;
}

.input-req-row select option { background: #1e293b; color: #e2e8f0; }

.input-req-row select:focus,
.input-req-row input[type="text"]:focus {
  outline: none;
  border-color: rgba(99,102,241,0.5);
  background: rgba(255,255,255,0.08);
}

.input-req-row .btn-danger {
  background: rgba(239,68,68,0.12);
  color: #f87171;
  border-color: rgba(239,68,68,0.25);
}
.input-req-row .btn-danger:hover { background: rgba(239,68,68,0.2); }

/* ============================================================
   PAGE HEADER COMPONENT (.ph) — dark theme base styles
   ============================================================ */

/* Barra superior GLOBAL: se monta una sola vez en el shell (components/global_header.rs),
   no una por página. Tokenizada para que siga al tema activo. */
.ph {
  background: var(--nav-bg);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border-bottom: 1px solid var(--nav-border);
  /* padding-left alineado con la columna de iconos de la sidebar
     (sidebar 10px + item 12px = 22px al borde del icono). */
  padding: 0 24px 0 22px;
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  position: sticky;
  top: 0;
  z-index: 100;
}

/* ── Left side ── */
.ph-left {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
  flex: 1;
}

.ph-back {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(255, 255, 255, 0.04);
  color: rgba(148, 163, 184, 0.85);
  cursor: pointer;
  transition: background 0.18s, border-color 0.18s, color 0.18s;
  flex-shrink: 0;
}

.ph-back:hover {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.15);
  color: #f8fafc;
}

.ph-divider {
  width: 1px;
  height: 18px;
  background: rgba(255, 255, 255, 0.1);
  flex-shrink: 0;
}

.ph-icon {
  font-size: 1.1875rem;
  flex-shrink: 0;
  line-height: 1;
}

.ph-title-wrap {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.ph-title {
  font-size: 0.9375rem;
  font-weight: 700;
  color: #f1f5f9;
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ph-meta {
  font-size: 0.725rem;
  color: rgba(148, 163, 184, 0.65);
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ── Right side ── */
.ph-right {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}

/* Module switcher */
.ph-switcher {
  position: relative;
}

.ph-switcher-btn {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: 8px;
  border: 1px solid rgba(255, 255, 255, 0.09);
  background: rgba(255, 255, 255, 0.05);
  color: rgba(203, 213, 225, 0.9);
  font-size: 0.8rem;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  transition: background 0.18s, border-color 0.18s, color 0.18s;
  white-space: nowrap;
}

.ph-switcher-btn:hover {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.16);
  color: #f8fafc;
}

.ph-chevron {
  transition: transform 0.2s ease;
  flex-shrink: 0;
}

.ph-chevron--open {
  transform: rotate(180deg);
}

.ph-backdrop {
  position: fixed;
  inset: 0;
  z-index: 50;
}

.ph-dropdown {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 210px;
  background: #1a2234;
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 14px;
  padding: 8px;
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.25);
  z-index: 60;
  animation: phDropIn 0.18s cubic-bezier(0.4, 0, 0.2, 1);
}

@keyframes phDropIn {
  from { opacity: 0; transform: translateY(-6px) scale(0.97); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}

.ph-dropdown-label {
  font-size: 0.6875rem;
  font-weight: 700;
  color: rgba(100, 116, 139, 0.75);
  text-transform: uppercase;
  letter-spacing: 0.07em;
  padding: 4px 8px 8px;
  display: block;
}

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

.ph-mod-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  border-radius: 9px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--muted-2);
  font-size: 0.8125rem;
  font-weight: 500;
  font-family: inherit;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
  text-align: left;
  width: 100%;
}

.ph-mod-item:hover:not(.ph-mod-item--maint) {
  background: rgba(59, 130, 246, 0.1);
  border-color: rgba(59, 130, 246, 0.18);
  color: #93c5fd;
}

.ph-mod-item--maint {
  opacity: 0.4;
  cursor: not-allowed;
}

.ph-mod-icon {
  font-size: 0.9375rem;
  flex-shrink: 0;
  line-height: 1;
}

.ph-mod-name {
  flex: 1;
}

.ph-mod-maint-dot {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: #f59e0b;
  flex-shrink: 0;
}

/* User chip */
.ph-user-chip {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 10px 4px 4px;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.07);
  background: rgba(255, 255, 255, 0.04);
}

.ph-user-avatar {
  width: 28px;
  height: 28px;
  border-radius: 7px;
  background: linear-gradient(135deg, #3b82f6 0%, #6366f1 100%);
  color: #fff;
  font-size: 0.75rem;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  letter-spacing: 0;
}

.ph-user-info {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.ph-user-name {
  font-size: 0.8125rem;
  font-weight: 600;
  color: #f1f5f9;
  white-space: nowrap;
}

.ph-user-role {
  font-size: 0.6875rem;
  color: rgba(148, 163, 184, 0.65);
  font-weight: 500;
  white-space: nowrap;
}

/* Logout button */
.ph-logout {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 8px;
  border: 1px solid rgba(239, 68, 68, 0.2);
  background: rgba(239, 68, 68, 0.06);
  color: rgba(252, 165, 165, 0.65);
  cursor: pointer;
  transition: background 0.18s, border-color 0.18s, color 0.18s;
  flex-shrink: 0;
}

.ph-logout:hover {
  background: rgba(239, 68, 68, 0.16);
  border-color: rgba(239, 68, 68, 0.32);
  color: #f87171;
}

/* THEME TOGGLE BUTTON */

.ph-theme-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.12);
  background: rgba(255,255,255,0.06);
  color: rgba(224,231,255,0.85);
  font-size: 1rem;
  cursor: pointer;
  transition: background 0.18s, border-color 0.18s, transform 0.15s;
  flex-shrink: 0;
}
.ph-theme-btn:hover {
  background: rgba(255,255,255,0.12);
  border-color: rgba(255,255,255,0.22);
  transform: scale(1.08);
}

/* LIGHT MODE OVERRIDES  (html.light-mode) */

/* ── Swap GLOBAL de tokens (CLARO). Global, NO scoped a .page-container, para
   que el login y CUALQUIER raíz adapten. Único lugar de la verdad del tema:
   migrar colores hardcodeados a estos tokens (ver tabla en el plan). ── */
html.light-mode {
  color-scheme: light;
  --bg:                #eef2f9;
  --bg-2:              #f1f5f9;
  --surface:           #ffffff;
  --surface-2:         #f8fafc;
  --surface-3:         #f1f5f9;
  --surface-overlay:   rgba(255,255,255,0.98);
  --panel:             rgba(255,255,255,0.96);
  --panel-2:           rgba(248,250,252,0.9);
  --control-bg:        #ffffff;
  --control-bg-hover:  #f1f5f9;
  --control-border:    rgba(0,0,0,0.12);
  --scrim:             rgba(15,23,42,0.45);
  --text:              #1e293b;
  --text-strong:       #0f172a;
  --muted:             rgba(71,85,105,0.9);
  --muted-2:           rgba(71,85,105,0.6);
  --border:            rgba(0,0,0,0.09);
  --border-soft:       rgba(0,0,0,0.05);
  --brand-soft-bg:     rgba(59,130,246,0.10);
  --brand-soft-fg:     #1d4ed8;
  /* Barra y sidebar en CLARO: la marca va sobre la superficie clara y en dosis
     mínima — la barra debe leerse como blanca "de la marca", no como una banda
     de color. Mismo mecanismo derivado que en oscuro. */
     Calibrado igual que en oscuro contra la paleta histórica (--surface #ffffff,
     --brand #3b82f6): 5% → rgb(245,249,255) vs #f5f7fb, y 9% → rgb(237,244,254)
     vs #eef2f9. El canal azul queda ~4 por encima y es imperceptible sobre blanco;
     bajarlo más apagaría el tinte de marca por completo. */
  --nav-bg:            #f5f7fb;
  --nav-bg:            color-mix(in srgb, var(--brand) 5%, var(--surface));
  --nav-bg-2:          #eef2f9;
  --nav-bg-2:          color-mix(in srgb, var(--brand) 9%, var(--surface));
  --nav-border:        rgba(37,99,235,0.12);
  /* En claro el velo es mucho más suave: sobre una superficie clara un 30 %
     ennegrece de verdad en vez de dar profundidad. */
  --nav-shade:         rgba(0,0,0,0.055);
  --tooltip-bg:        #1e293b;
  --tooltip-fg:        #f1f5f9;
  --badge-success-bg:  #dcfce7; --badge-success-fg: #15803d;
  --badge-warn-bg:     #fef9c3; --badge-warn-fg:    #a16207;
  --badge-danger-bg:   #fef2f2; --badge-danger-fg:  #b91c1c;
  --badge-info-bg:     #dbeafe; --badge-info-fg:    #1d4ed8;
  --badge-neutral-bg:  #f1f5f9; --badge-neutral-fg: #475569;
  --badge-purple-bg:   #ede9fe; --badge-purple-fg:  #7c3aed;
  --shadow-sm:  0 1px 2px rgba(0,0,0,0.05);
  --shadow-md:  0 4px 6px rgba(0,0,0,0.07), 0 2px 4px rgba(0,0,0,0.06);
  --shadow-lg:  0 10px 25px rgba(0,0,0,0.12), 0 4px 8px rgba(0,0,0,0.06);
}

html.light-mode body { background: var(--bg); }

/* La tarjeta de login es SIEMPRE clara (independiente del tema): fija un
   contexto de tokens claro para que su contenido sea legible en ambos temas. */
.login-card {
  /* La tarjeta es clara aun en tema oscuro → sus controles nativos (autofill,
     date/time, flecha de select) también deben renderizar en claro. */
  color-scheme: light;
  --text:           #1e293b;
  --text-strong:    #0f172a;
  --muted:          #475569;
  --muted-2:        #64748b;
  --border:         rgba(0,0,0,0.10);
  --border-soft:    rgba(0,0,0,0.06);
  --surface:        #ffffff;
  --surface-2:      #f8fafc;
  --control-bg:     #ffffff;
  --control-bg-hover: #f1f5f9;
  --control-border: rgba(0,0,0,0.12);
}

html.light-mode .page-container { background: var(--bg); }



html.light-mode .app-title {
  color: var(--text-strong);
}

html.light-mode .home-container {
  background: #eef2f9;
}

html.light-mode .home-sidebar {
  background: rgba(255, 255, 255, 0.95);
  border-right-color: rgba(0, 0, 0, 0.07);
}

html.light-mode .home-sidebar-user {
  background: rgba(0, 0, 0, 0.03);
}

html.light-mode .home-sidebar-name {
  color: var(--text-strong);
}

html.light-mode .home-sidebar-role {
  color: var(--muted-2);
}

html.light-mode .home-sidebar-sep {
  background: rgba(0, 0, 0, 0.07);
}

html.light-mode .home-sidebar-item {
  color: var(--muted);
}

html.light-mode .home-sidebar-item:hover:not(.home-sidebar-item--maint) {
  background: rgba(59, 130, 246, 0.07);
  color: #2563eb;
}

html.light-mode .home-welcome-title {
  color: var(--text-strong);
}

html.light-mode .home-welcome-sub {
  color: var(--muted);
}

/* El fondo, el borde y el color de `.mod-card`/`.mod-name` los fija la propia
   regla base en tokens: ya siguen al tema sin parche por elemento. */

html.light-mode .ph {
  background: rgba(255,255,255,0.92);
  border-bottom: 1px solid rgba(0,0,0,0.08);
  backdrop-filter: blur(16px);
}
html.light-mode .ph-title  { color: var(--text-strong); }
html.light-mode .ph-meta   { color: var(--muted); }
html.light-mode .ph-icon   { color: #4f46e5; }
html.light-mode .ph-divider { background: rgba(0,0,0,0.1); }

html.light-mode .ph-back,
html.light-mode .ph-logout {
  color: var(--muted);
  border-color: rgba(0,0,0,0.08);
  background: rgba(0,0,0,0.03);
}
html.light-mode .ph-back:hover,
html.light-mode .ph-logout:hover {
  color: var(--text-strong);
  background: rgba(0,0,0,0.07);
}

html.light-mode .ph-theme-btn {
  background: rgba(0,0,0,0.04);
  border-color: rgba(0,0,0,0.1);
  color: var(--muted);
}
html.light-mode .ph-theme-btn:hover {
  background: rgba(0,0,0,0.08);
}

html.light-mode .ph-switcher-btn {
  background: rgba(0,0,0,0.04);
  color: var(--text-strong);
  border-color: rgba(0,0,0,0.1);
}
html.light-mode .ph-switcher-btn:hover {
  background: rgba(0,0,0,0.07);
}
html.light-mode .ph-dropdown {
  background: var(--surface);
  border: 1px solid rgba(0,0,0,0.1);
  box-shadow: 0 8px 32px rgba(0,0,0,0.12);
}
html.light-mode .ph-dropdown-label { color: var(--muted); }
html.light-mode .ph-mod-item {
  background: rgba(0,0,0,0.02);
  color: var(--text-strong);
  border-color: rgba(0,0,0,0.06);
}
html.light-mode .ph-mod-item:hover:not(.ph-mod-item--maint) {
  background: rgba(99,102,241,0.08);
  color: #4f46e5;
}

html.light-mode .ph-user-chip {
  background: rgba(0,0,0,0.04);
  border-color: rgba(0,0,0,0.08);
}
html.light-mode .ph-user-name  { color: var(--text-strong); }
html.light-mode .ph-user-role  { color: var(--muted); }
html.light-mode .ph-user-avatar {
  background: rgba(99,102,241,0.15);
  color: #4f46e5;
}

/* De esta lista salieron `.tools-card`, `.users-table-wrap`, `.perms-table` y
   `.table-wrapper`: su superficie la fijan ahora los bloques TARJETAS y TABLAS del
   final, en tokens. Aquí se les imponía rgba(255,255,255,0.96) con !important, que
   habría ganado al canónico y los habría dejado descolgados del resto. Quedan solo
   los paneles que aún no tienen canónico propio. */
html.light-mode .ticket-panel,
html.light-mode .camp-content,
html.light-mode .control-form-panel,
html.light-mode .contact-detail-panel {
  background: rgba(255,255,255,0.96) !important;
  border-color: rgba(0,0,0,0.08) !important;
  box-shadow: 0 2px 16px rgba(0,0,0,0.06);
}

/* Las pestañas de módulo YA NO se re-pintan aquí. El color de los 12 grupos de
   navegación interna vive en un único bloque tokenizado al final del archivo
   ("PESTAÑAS DE MÓDULO — capa de color única"). Lo que había aquí clavaba el
   activo a hexes de fábrica (#4f46e5 / #2563eb) con !important, así que en tema
   claro Centro de Control, Tickets y Campañas se quedaban azules por mucho que
   el usuario activara otro tema — en oscuro sí cambiaban, porque ahí caían en la
   regla global `.active`. Ese era el bug. */

html.light-mode .contact-row:hover td {
  background: var(--brand-soft-bg);
}


/* Separadores y hover de `.camp-table` y `.perms-table`: los fija el bloque TABLAS
   del final. Aquí iban rgba(0,0,0,0.05) y un hover en rgba(99,102,241,0.04) —
   índigo fijo que no seguía al tema activo. */

html.light-mode input[type="text"],
html.light-mode input[type="email"],
html.light-mode input[type="password"],
html.light-mode input[type="number"],
html.light-mode input[type="search"],
html.light-mode input[type="tel"],
html.light-mode input[type="url"],
html.light-mode select,
html.light-mode textarea {
  background: rgba(255,255,255,0.9) !important;
  border-color: rgba(0,0,0,0.12) !important;
  color: var(--text-strong) !important;
}
html.light-mode select option {
  background: var(--surface);
  color: var(--text-strong);
}
html.light-mode input:focus,
html.light-mode select:focus,
html.light-mode textarea:focus {
  border-color: rgba(99,102,241,0.5) !important;
  background: var(--surface) !important;
}
html.light-mode input::placeholder,
html.light-mode textarea::placeholder {
  color: rgba(71,85,105,0.5) !important;
}

html.light-mode .filter-bar,
html.light-mode .contacts-filter-bar {
  background: rgba(255,255,255,0.9);
  border-color: rgba(0,0,0,0.08);
}

html.light-mode .section-title,
html.light-mode .contacts-title,
html.light-mode .users-title,
html.light-mode .control-title,
html.light-mode .panel-title,
html.light-mode .ticket-section-title { color: var(--text-strong); }

html.light-mode label               { color: var(--muted) !important; }
html.light-mode .form-section-title { color: var(--text-strong) !important; }

/* El fondo y el borde de .home-card/.mod-card los fija ahora el bloque TARJETAS
   del final, en tokens. Aquí iban rgba(255,255,255,0.92) y rgba(0,0,0,0.08)
   escritos a mano, que no seguían al tema activo. Se conserva solo la sombra del
   hover, que sí es propia de estas tarjetas (son enlaces a módulos). */
html.light-mode .home-card:hover,
html.light-mode .mod-card:hover {
  box-shadow: 0 4px 20px rgba(0,0,0,0.1);
}
/* Se han quitado los parches de .mod-card-title/.mod-card-desc/.home-card-title/
   .home-card-desc: ninguna de esas cuatro clases existe ya en el markup. */

html.light-mode ::-webkit-scrollbar-track { background: rgba(0,0,0,0.04); }
html.light-mode ::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.15); }
html.light-mode ::-webkit-scrollbar-thumb:hover { background: rgba(0,0,0,0.25); }

/* ── Light-mode overrides for newly darkened module elements ── */
html.light-mode .page-container         { background: var(--surface-2); }
html.light-mode .livechat-layout        { background: var(--surface-2); }
html.light-mode .livechat-messages      { background: var(--surface); }
html.light-mode .livechat-empty         { background: var(--surface-2); }
html.light-mode .messages-header        { background: var(--surface); }
html.light-mode .livechat-contact-panel { background: var(--surface-2); }
html.light-mode .reply-box              { background: var(--surface); border-top-color: #e2e8f0; }
html.light-mode .reply-textarea         { background: var(--surface-2); border-color: var(--control-border); color: var(--text-strong); }
html.light-mode .reply-textarea::placeholder { color: var(--muted-2); }
html.light-mode .reply-textarea:focus   { background: var(--surface); border-color: #2563eb; }
html.light-mode .messages-list          { background: var(--surface-2); }
html.light-mode .livechat-sidebar       { background: var(--surface); border-right-color: #e2e8f0; }
html.light-mode .livechat-filters       { border-bottom-color: #e2e8f0; }
html.light-mode .livechat-filters select { background: var(--surface); border-color: var(--border); color: #374151; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E"); }
html.light-mode .livechat-filters select option { background: var(--surface); }
html.light-mode .livechat-filters select:focus  { border-color: #3b82f6; background-color: var(--surface); }
/* .filter-pill: retirado. Es un chip interactivo y su color lo fija ahora el
   bloque "CHIPS INTERACTIVOS" del final, en tokens. Aquí había tres hexes a mano
   (#6b7280, #374151, #1d4ed8) que no seguían al tema activo. */
html.light-mode .conv-item:hover        { background: var(--surface-2); }
html.light-mode .conv-item--selected    { background: rgba(59,130,246,0.08) !important; border-color: rgba(59,130,246,0.25); }
html.light-mode .conv-title             { color: var(--text-strong); }
html.light-mode .conv-last-msg          { color: var(--muted); }
html.light-mode .conv-time              { color: var(--muted-2); }
html.light-mode .contacts-channel-bar   { background: var(--surface); }
html.light-mode .contacts-subbar        { background: var(--surface); }
html.light-mode .ch-chip                { background: var(--surface-2); }
html.light-mode .ch-chip:hover          { background: var(--surface-2); border-color: var(--muted-2); }
html.light-mode .users-filterbar        { background: var(--surface); }
html.light-mode .metrics-kpi-value      { color: var(--text-strong); }
html.light-mode .metrics-chart-title    { color: var(--text-strong); }
html.light-mode .qa-card                { background: var(--surface); box-shadow: 0 1px 4px rgba(0,0,0,0.04); }
/* .qa-btn: retirado. Es un botón secundario y su color lo fija ahora el bloque
   "BOTONES" del final; mantener este override lo dejaba en --surface solo en tema
   claro, distinto del resto de secundarios. */
html.light-mode .profile-page           { background: var(--surface-2); }
html.light-mode .search-input           { background: var(--surface); }

/* ── Phase-2: theme-adaptive overrides (tabs, ticket panel, pastel tags) ── */
/* .metrics-tabs / .metrics-tab: ver el bloque canónico de pestañas al final del
   archivo. Estas tres reglas ya usaban tokens (por eso Métricas era el único
   módulo que se veía bien en claro) y ahora son redundantes. */

html.light-mode .ticket-panel h3        { color: var(--text-strong); border-bottom-color: rgba(0,0,0,0.07); }
html.light-mode .ticket-panel-header    { border-bottom-color: rgba(0,0,0,0.07); }
html.light-mode .tickets-table td.tk-ref      { color: var(--muted); }
html.light-mode .tickets-table td.ticket-created { color: var(--muted); }
html.light-mode .ticket-toolbar button,
html.light-mode .ticket-toolbar-actions button { background: var(--surface); color: var(--text-strong); }

/* Los badges ya no se re-pintan aquí. Estas ocho reglas existían porque las bases
   clavaban colores de tema oscuro y en claro había que repararlas una a una —dos
   de ellas con hexes propios (#fef9c3/#a16207, #ede9fe/#7c3aed) que no seguían a
   ningún tema. Ahora el color sale de los tokens `--badge-*-bg/-fg`, que ya
   conmutan solos. Ver "BADGES / TAGS DE ESTADO" al final del archivo. */

/* Controles translúcidos (diseñados sobre oscuro) que se camuflan en claro.
   `.btn-secondary` salió de aquí: su color lo fija el bloque "BOTONES" del final
   con `--control-bg`/`--control-border`, que ya conmutan solos. Este override
   —con un `rgba(0,0,0,0.12)` a mano— le daba en claro un borde y un fondo
   distintos a los del resto de botones secundarios. */
html.light-mode .metrics-refresh-btn,
html.light-mode .contacts-refresh-btn {
  background: var(--surface);
  border-color: rgba(0,0,0,0.12);
  color: var(--text-strong);
}
html.light-mode .metrics-refresh-btn:hover,
html.light-mode .contacts-refresh-btn:hover { background: var(--surface-2); }
html.light-mode .metrics-period-select {
  background-color: var(--surface);
  border-color: rgba(0,0,0,0.12);
  color: var(--text-strong);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%231e293b' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
}
html.light-mode .contacts-search-input {
  background: var(--surface);
  border-color: rgba(0,0,0,0.12);
  color: var(--text-strong);
}
html.light-mode .contacts-search-input::placeholder { color: rgba(71,85,105,0.55); }
html.light-mode .kn-tipo-card:hover     { background: var(--surface-2); border-color: var(--brand); }
/* .kn-tipo-card.selected: color en el bloque TARJETAS (variante seleccionada). */
html.light-mode .camp-preview-bubble    { background: var(--surface); color: #111827; border-color: var(--border); }

/* ── InfoTooltip component ───────────────────────────────────────────────── */
.info-tooltip-wrapper {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-left: 4px;
  vertical-align: middle;
  overflow: visible;
  outline: none;
}

.info-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  /* Tokenizado: era rgba(99,102,241,0.15) — índigo fijo que no seguía al tema. */
  background: var(--brand-soft-bg);
  color: var(--brand);
  font-size: 10px;
  font-style: normal;
  cursor: default;
  user-select: none;
  line-height: 1;
}

.info-tooltip-text {
  visibility: hidden;
  opacity: 0;
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  background: var(--tooltip-bg);
  color: var(--tooltip-fg);
  font-size: 12px;
  font-weight: 400;
  line-height: 1.45;
  padding: 9px 11px;
  border-radius: 8px;
  width: max-content;
  max-width: min(280px, calc(100vw - 32px));
  white-space: normal;
  z-index: 1200;
  pointer-events: none;
  transition: opacity 0.15s ease;
  box-shadow: var(--shadow-md);
}

.info-tooltip-text::before {
  content: "";
  position: absolute;
  left: 50%;
  bottom: 100%;
  transform: translateX(-50%);
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-bottom: 6px solid var(--tooltip-bg);
}

.info-tooltip-wrapper:hover .info-tooltip-text,
.info-tooltip-wrapper:focus .info-tooltip-text,
.info-tooltip-wrapper:focus-within .info-tooltip-text {
  visibility: visible;
  opacity: 1;
}

/* ── Módulo Gestión de Pagos ───────────────────────────────────────────────── */
.pagos-page .page-content { background: var(--bg); max-width: 1440px; }
.pg-header { margin-bottom: 18px; }
.pg-title { font-size: 1.4rem; font-weight: 700; color: var(--text); margin: 10px 0 2px; }
.pg-subtitle { color: var(--muted); font-size: 0.9rem; margin: 0; }
.pg-banner { background: var(--badge-info-bg); border: 1px solid var(--badge-info-fg); color: var(--badge-info-fg); padding: 10px 14px; border-radius: 8px; margin-bottom: 14px; font-size: 0.88rem; }

.ui-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 12px; margin-bottom: 18px; }
.ui-card { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 14px 18px; box-shadow: var(--shadow-sm); }
.ui-card-n { font-size: 1.6rem; font-weight: 700; color: var(--text); line-height: 1.1; }
.ui-card-l { font-size: 0.78rem; color: var(--muted); margin-top: 4px; }
.ui-card--warn { border-color: rgba(245,158,11,0.45); background: var(--badge-warn-bg); }
.ui-card--ok { border-color: rgba(16,185,129,0.45); background: var(--badge-success-bg); }

.pg-filters { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-bottom: 14px; }
.ui-input { padding: 8px 10px; border: 1px solid var(--control-border); border-radius: 8px; font-family: inherit; font-size: 0.85rem; background: var(--control-bg); color: var(--text); min-width: 140px; flex: 1 1 auto; }
.ui-input:focus { outline: 2px solid var(--brand-soft-fg); outline-offset: -1px; }

.ui-btn { padding: 7px 13px; border-radius: 8px; border: 1px solid var(--control-border); background: var(--control-bg); color: var(--text); font-size: 0.83rem; font-weight: 600; font-family: inherit; cursor: pointer; transition: all 0.15s; }
.ui-btn:hover:not(:disabled) { background: var(--control-bg-hover); }
/* Unificada con .btn-primary: base --brand-dark, hover --brand-darker (misma primaria en
   contexto denso y en contexto normal; antes .ui-btn--primary arrancaba un tono mas claro). */
.ui-btn--primary { background: var(--brand-dark); color: #fff; border-color: var(--brand-dark); }
.ui-btn--primary:hover:not(:disabled) { background: var(--brand-darker); }
.ui-btn--danger { color: var(--badge-danger-fg); border-color: rgba(239,68,68,0.45); }
.ui-btn--danger:hover:not(:disabled) { background: var(--badge-danger-bg); }
.ui-btn--sm { padding: 4px 9px; font-size: 0.76rem; }

/* overflow-x:auto → en pantallas angostas la tabla (grid de ancho fijo) hace scroll
   horizontal DENTRO de su tarjeta en vez de recortar la columna de acciones. */
.ui-table { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; overflow-x: auto; overflow-y: hidden; box-shadow: var(--shadow-sm); }
.pg-row { display: grid; grid-template-columns: 92px 1.2fr 110px 1.4fr 95px 1fr 110px 56px 272px; gap: 8px; padding: 10px 14px; border-bottom: 1px solid var(--border); font-size: 0.82rem; color: var(--text); align-items: center; min-width: 900px; }
.pg-row:last-child { border-bottom: none; }
.pg-row > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pg-row--head { font-weight: 700; background: var(--surface-2); color: var(--muted); text-transform: uppercase; font-size: 0.68rem; letter-spacing: 0.03em; }
.ui-empty { padding: 26px; text-align: center; color: var(--muted); }
.pg-actions { display: flex; gap: 4px; white-space: nowrap; }

/* Estilos de celda cuando .ui-table se usa sobre un <table> REAL (catálogo de
   órdenes SAE). Las demás .ui-table son grids de divs (.pg-row) → estas reglas,
   al apuntar a thead/th/td, NO las afectan. Sin esto la tabla SAE salía sin
   formato (HTML plano, celdas apretadas). */
/* width:auto + min-width:100% → la tabla llena el modal como mínimo pero CRECE con
   su contenido (celdas nowrap) en vez de comprimir 9 columnas en el ancho del modal.
   overflow:visible anula el overflow-x del .ui-table base: el scroll horizontal lo
   maneja SOLO .ticket-table-wrap (evita doble scroll y el apretado). */
table.ui-table { border-collapse: separate; border-spacing: 0; width: auto; min-width: 100%; overflow: visible; }
.ui-table thead th {
  text-align: left; padding: 11px 12px; white-space: nowrap;
  font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--muted); background: var(--surface-2);
  border-bottom: 1px solid var(--border); position: sticky; top: 0; z-index: 1;
}
.ui-table tbody td {
  padding: 9px 12px; font-size: 0.84rem; color: var(--text);
  border-bottom: 1px solid var(--border-soft); vertical-align: middle; white-space: nowrap;
}
.ui-table tbody tr:last-child td { border-bottom: none; }
.ui-table tbody tr:hover td { background: var(--surface-2); }
.ui-table th.ui-cell--center, .ui-table td.ui-cell--center { text-align: center; }
/* Anchos mínimos por columna para que la data no quede apretada (celdas nowrap ya
   evitan el corte; esto asegura columnas legibles y toggles con aire). */
.ui-table thead th, .ui-table tbody td { min-width: 5.5rem; }
.ui-table thead th:first-child, .ui-table tbody td:first-child { min-width: 12rem; }   /* Detalle */
.ui-table thead th:nth-child(2),  .ui-table tbody td:nth-child(2)  { min-width: 10rem; }   /* Tipo / grupo */
.ui-table th.ui-cell--center, .ui-table td.ui-cell--center { min-width: 6.5rem; }          /* toggles con aire */
/* Los controles de fila (select/input) heredan el ancho justo, no todo el td. */
.ui-table tbody td .ui-input { min-width: 8rem; }

.pg-tag { display: inline-block; padding: 2px 9px; border-radius: 999px; font-size: 0.72rem; font-weight: 600; }
.pg-tag--registrado { background: var(--badge-neutral-bg); color: var(--badge-neutral-fg); }
.pg-tag--en_revision { background: var(--badge-warn-bg); color: var(--badge-warn-fg); }
.pg-tag--validado { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.pg-tag--rechazado { background: var(--badge-danger-bg); color: var(--badge-danger-fg); }
.pg-tag--cerrado { background: var(--badge-purple-bg); color: var(--badge-purple-fg); }

.ui-pager { display: flex; gap: 16px; align-items: center; justify-content: center; margin-top: 16px; color: var(--text); font-size: 0.85rem; }

/* En móvil, los filtros de estos módulos ocupan el ancho completo (una columna)
   en vez de quedar apretados o desbordar. Las tablas anchas siguen con scroll-x
   dentro de su contenedor. */
@media (max-width: 640px) {
  .users-filter,
  .users-filter--text,
  .perms-filter { flex: 1 1 100%; min-width: 0; }
  .ui-input { flex: 1 1 100%; }
  .monitor-filters > select,
  .monitor-filters > input[type="date"],
  .monitor-filters > input[type="text"] { flex: 1 1 100%; min-width: 0; }
}

/* ── Modal de detalle del pago ─────────────────────────────────────────────── */
.ui-btn--ghost { background: transparent; }
.ui-modal-overlay {
  position: fixed; inset: 0; z-index: 1000;
  background: var(--scrim);
  backdrop-filter: blur(2px);
  display: flex; align-items: center; justify-content: center;
  padding: clamp(12px, 4vw, 24px);
}
.ui-modal {
  background: var(--surface-overlay);
  border-radius: 14px;
  width: min(680px, 100%);
  max-height: 88vh;
  overflow: hidden;
  display: flex; flex-direction: column;
  box-shadow: var(--shadow-lg);
}
.ui-modal-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
}
.ui-modal-head h3 { margin: 0; font-size: 1.05rem; color: var(--text); }
.ui-modal-close {
  border: none; background: transparent; cursor: pointer;
  font-size: 1.1rem; color: var(--muted); line-height: 1; padding: 4px 8px; border-radius: 8px;
}
.ui-modal-close:hover { background: var(--control-bg-hover); color: var(--text); }
.ui-modal-body { padding: 18px 20px; overflow-y: auto; }
.pg-detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 10px 18px;
}
.pg-detail-item { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.pg-detail-k { font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--muted); font-weight: 600; }
.pg-detail-item > span:last-child { font-size: 0.9rem; color: var(--text); word-break: break-word; }
.pg-detail-section { margin-top: 16px; }
.pg-detail-notes {
  margin-top: 6px; padding: 10px 12px; background: var(--surface-2);
  border: 1px solid var(--border); border-radius: 8px;
  font-size: 0.85rem; color: var(--text); white-space: pre-wrap; word-break: break-word;
}
.pg-proof { margin-top: 8px; display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }
.pg-proof-img {
  max-width: 100%; max-height: 360px; border-radius: 10px;
  border: 1px solid var(--border); object-fit: contain; background: var(--surface-2);
}
.pg-proof-link { font-size: 0.82rem; color: var(--brand); text-decoration: none; }
.pg-proof-link:hover { text-decoration: underline; }

/* ═══════════════════════════════════════════════════════════════
   App shell + sidebar global de módulos (navegación unificada)
   Reemplaza el sidebar duplicado de home y el dropdown "Módulos".
   ═══════════════════════════════════════════════════════════════ */
/* El shell pasa a COLUMNA: la barra superior es global y va a todo lo ancho, por
   encima de la fila [sidebar | contenido]. Antes cada página pintaba su propia
   cabecera dentro del contenido, así que la barra empezaba después de la sidebar. */
.app-shell { display: flex; flex-direction: column; min-height: 100vh; }
.app-body { display: flex; align-items: stretch; flex: 1 1 auto; min-height: 0; }
.app-content { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; }

.module-sidebar {
  flex: 0 0 auto;
  width: 224px;
  /* Tokenizado: con un hex fijo la sidebar se quedaba azul con cualquier tema. */
  background: var(--nav-bg-2);
  border-right: 1px solid var(--nav-border);
  padding: 14px 10px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  position: sticky;
  /* Vive BAJO la barra global (60px): pega justo debajo y no la tapa. */
  top: 60px;
  align-self: flex-start;
  height: calc(100vh - 60px);
  overflow-y: auto;
  transition: width 0.18s ease;
  z-index: 30;
}
.module-sidebar--collapsed { width: 64px; }

.module-sidebar-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 9px 12px;
  margin-bottom: 8px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 10px;
  background: transparent;
  color: #e2e8f0;
  font-family: inherit;
  font-weight: 700;
  font-size: 0.8rem;
  cursor: pointer;
}
.module-sidebar-toggle:hover { background: rgba(255, 255, 255, 0.06); }
.module-sidebar-toggle-icon { font-size: 1rem; line-height: 1; width: 18px; text-align: center; }
.module-sidebar--collapsed .module-sidebar-toggle { justify-content: center; }
.module-sidebar--collapsed .module-sidebar-toggle-label { display: none; }

.module-sidebar-nav { display: flex; flex-direction: column; gap: 2px; }

.module-sidebar-item {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  padding: 10px 12px;
  border: none;
  border-radius: 10px;
  background: transparent;
  color: #cbd5e1;
  font-family: inherit;
  font-size: 0.86rem;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.12s ease, color 0.12s ease;
}
.module-sidebar-item:hover { background: rgba(255, 255, 255, 0.07); color: #fff; }
.module-sidebar-item.is-active { background: var(--brand-dark); color: #fff; }
.module-sidebar-item.is-maint { opacity: 0.45; cursor: not-allowed; }
.module-sidebar-icon { font-size: 1.1rem; width: 22px; text-align: center; flex-shrink: 0; }
/* Obligatorio: un iconset del Marketplace puede traer un SVG SIN medidas, y un
   SVG sin tamaño cae al 300x150 por defecto del navegador — reventaría la barra.
   El emoji del respaldo se dimensiona por `font-size` y no pasa por aquí. */
.module-sidebar-icon svg { width: 18px; height: 18px; display: inline-block; }
.module-sidebar-label { overflow: hidden; text-overflow: ellipsis; }

/* Mismo motivo para los iconos de acción de fila (`components/act_icons.rs`):
   el SVG de respaldo va sin medidas para que el iconset pueda sustituirlo, así
   que el tamaño lo pone esta clase. */
.icon-ic { width: 15px; height: 15px; }
.module-sidebar-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--badge-warn-fg); margin-left: auto; flex-shrink: 0;
}
.module-sidebar--collapsed .module-sidebar-item { justify-content: center; padding: 10px 0; }
.module-sidebar--collapsed .module-sidebar-label,
.module-sidebar--collapsed .module-sidebar-dot { display: none; }

/* ═══════════════════════════════════════════════════════════════
   SUBSIDEBAR DE PESTAÑAS (hover sobre una fila de la sidebar)
   ───────────────────────────────────────────────────────────────
   Es una extensión de la misma superficie de navegación, no una tarjeta en
   flujo: mismo color base (`--nav-bg-2`) con el velo `--nav-shade` encima para
   la profundidad. Todo por tokens, así que no necesita parche de tema claro.
   ═══════════════════════════════════════════════════════════════ */
.module-subsidebar {
  position: fixed;
  left: 224px;                     /* = ancho de .module-sidebar */
  top: 60px;                       /* bajo la barra global */
  bottom: 0;
  width: 226px;
  background-color: var(--nav-bg-2);
  background-image: linear-gradient(var(--nav-shade), var(--nav-shade));
  border-right: 1px solid var(--nav-border);
  padding: 14px 10px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  overflow-y: auto;
  z-index: 31;                     /* sobre el contenido, bajo la barra global */
  scrollbar-width: thin;
  /* El panel NO se desmonta al cerrarse: si se desmontara no habría salida que
     animar. `visibility` se retrasa hasta el final del fundido por eso mismo. */
  opacity: 0;
  visibility: hidden;
  transform: translateX(-8px);
  pointer-events: none;
  transition: opacity 0.14s ease, transform 0.14s ease, visibility 0s linear 0.14s;
}
.module-subsidebar.is-open {
  opacity: 1;
  visibility: visible;
  transform: none;
  pointer-events: auto;
  transition: opacity 0.14s ease, transform 0.14s ease, visibility 0s;
}
.module-subsidebar--rail { left: 64px; }   /* sidebar en riel */

/* Flecha "hay más": SIEMPRE visible en las filas con pestañas — es lo que
   anuncia que ese módulo despliega panel. El hover solo la refuerza. */
.module-sidebar-caret {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  color: currentColor;
  opacity: 0.45;
  transition: opacity 0.12s ease, transform 0.12s ease;
}
.module-sidebar-item:hover .module-sidebar-caret { opacity: 0.9; transform: translateX(2px); }
.module-sidebar-item.is-active .module-sidebar-caret { opacity: 0.9; }
.module-sidebar-dot + .module-sidebar-caret { margin-left: 6px; }
.module-sidebar--collapsed .module-sidebar-caret { display: none; }

.module-subsidebar-title {
  padding: 4px 12px 8px;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.module-subsidebar-nav { display: flex; flex-direction: column; gap: 2px; }

.module-subsidebar-item {
  display: flex;
  align-items: center;
  width: 100%;
  padding: 9px 12px;
  border: none;
  border-radius: 10px;
  background: transparent;
  color: var(--muted);
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  transition: background 0.12s ease, color 0.12s ease;
}
.module-subsidebar-item:hover { background: var(--control-bg-hover); color: var(--text-strong); }
.module-subsidebar-item.is-active { background: var(--brand-dark); color: #fff; }

/* Botón ☰ del header (toggle de la sidebar) */
.ph-menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px; height: 34px;
  border: 1px solid var(--border);
  border-radius: 9px;
  background: transparent;
  color: var(--text);
  cursor: pointer;
  flex-shrink: 0;
}
.ph-menu-toggle:hover { background: rgba(255, 255, 255, 0.06); }

/* Móvil: sidebar como overlay; colapsada = oculta */
@media (max-width: 860px) {
  .module-sidebar {
    position: fixed; left: 0; top: 0; bottom: 0; height: 100vh;
    box-shadow: 6px 0 24px rgba(0, 0, 0, 0.4);
  }
  .module-sidebar--collapsed {
    width: 0; padding: 0; overflow: hidden; border: none; box-shadow: none;
  }
  /* La sidebar sube a top:0 al volverse overlay; el panel la acompaña. */
  .module-subsidebar { top: 0; }
  /* Con la sidebar en riel aquí NO hay riel: está oculta (width:0). Un panel
     flotando pegado al borde izquierdo, sin nada de lo que colgar, se leería
     como un menú suelto. */
  .module-subsidebar--rail { display: none; }
}

/* ── Light mode: sidebar global ── */
/* El panel de pestañas es la MISMA superficie de navegación, así que entra en
   este override en vez de traer uno propio: si no, en claro la sidebar sería
   blanca y el panel pegado a ella azulado. */
html.light-mode .module-sidebar,
html.light-mode .module-subsidebar { background-color: var(--surface); border-right-color: #e6ebf2; }
html.light-mode .module-sidebar-toggle { color: var(--text-strong); border-color: var(--border); }
html.light-mode .module-sidebar-toggle:hover { background: var(--surface-2); }
html.light-mode .module-sidebar-item { color: var(--muted); }
html.light-mode .module-sidebar-item:hover { background: var(--surface-2); color: var(--text-strong); }
html.light-mode .module-sidebar-item.is-active { background: var(--brand-dark); color: #fff; }
html.light-mode .ph-menu-toggle { color: var(--text-strong); border-color: var(--border); }
html.light-mode .ph-menu-toggle:hover { background: var(--surface-2); }

/* ── Pill deslizante en barras de tabs (segmented controls) ──────────────────
   El resaltado del tab activo (fondo brand-dark) se DESLIZA entre pestañas en vez
   de saltar. Es 100% global: un listener en index.html marca cada contenedor de
   tabs con `.slide-tabs` y escribe las variables `--pill-*` a partir del botón
   activo (detectado por su clase: .active / .is-active / *--active). No hay que
   tocar la lógica de cada tab. Los tabs de SUBRAYADO (ticket-monitor-subtabs,
   notif) NO se incluyen (usan border-bottom, no un fondo). La lista de
   contenedores vive en el JS de index.html. Ver docs/frontend/tabs_pill_deslizante.md */
.slide-tabs { position: relative; }
.slide-tabs > button { position: relative; z-index: 1; }
.slide-tabs::after {
  content: "";
  position: absolute;
  left: 0; top: 0;
  width: var(--pill-w, 0);
  height: var(--pill-h, 0);
  transform: translate(var(--pill-x, 0), var(--pill-y, 0));
  background: var(--brand-dark);
  border-radius: 999px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.14);
  opacity: var(--pill-o, 0);
  z-index: 0;
  pointer-events: none;
  transition: transform 0.4s cubic-bezier(0.65, 0, 0.35, 1),
              width     0.4s cubic-bezier(0.65, 0, 0.35, 1),
              height    0.4s cubic-bezier(0.65, 0, 0.35, 1);
}
/* Primer posicionamiento sin animación (evita que el pill "crezca" desde 0,0). */
.slide-tabs.slide-tabs--no-anim::after { transition: none; }

/* El botón activo deja de pintar su propio fondo: el pill es el único resaltado.
   (Gana en especificidad al `.active { background: !important }` global y a los
   `*--active` de cada módulo.) El color del texto lo mantiene cada módulo. */
.slide-tabs > .active,
.slide-tabs > .is-active,
.slide-tabs > [class*="--active"] {
  background: transparent !important;
  box-shadow: none !important;
}

/* camp-tabs usa un pill claro (var(--surface)) en vez de brand-dark. */
.slide-tabs.camp-tabs::after {
  background: var(--surface);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.08);
}

@media (prefers-reduced-motion: reduce) {
  .slide-tabs::after { transition: none; }
}

/* ── Medidor de fortaleza de contraseña ──────────────────────────────────────
   Segmentos que se llenan según el score 0..4 (util::password::password_score),
   alineado con la política de contraseñas del backend. Colores por tokens. */
.pw-meter { margin-top: 8px; display: flex; flex-direction: column; gap: 5px; }
.pw-meter--hidden { display: none; }

.meter { display: flex; gap: 5px; }
.meter span {
  flex: 1; height: 5px; border-radius: 3px;
  background: var(--control-bg);
  transform: scaleX(0); transform-origin: left;
  transition: transform 0.35s cubic-bezier(0.34, 1.56, 0.64, 1), background 0.2s ease;
}
.meter[data-score="1"] span:nth-child(-n+1),
.meter[data-score="2"] span:nth-child(-n+2),
.meter[data-score="3"] span:nth-child(-n+3),
.meter[data-score="4"] span { transform: scaleX(1); }

.meter[data-score="1"] span { background: var(--badge-danger-fg); }
.meter[data-score="2"] span { background: var(--badge-warn-fg); }
.meter[data-score="3"] span,
.meter[data-score="4"] span { background: var(--badge-success-fg); }

.pw-meter__row { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.pw-meter__label { font-size: 12px; font-weight: 600; white-space: nowrap; }
.pw-meter__label[data-score="1"] { color: var(--badge-danger-fg); }
.pw-meter__label[data-score="2"] { color: var(--badge-warn-fg); }
.pw-meter__label[data-score="3"],
.pw-meter__label[data-score="4"] { color: var(--badge-success-fg); }
.pw-meter__hint { font-size: 11.5px; color: var(--muted); text-align: right; }

/* ── Feedback al presionar un botón ──────────────────────────────────────────
   Indica visualmente que el click se registró. Aplica a TODOS los botones (micro
   escala al presionar); el ripple va en los botones de acción principales.
   `:disabled` no reacciona (los botones en curso ya se bloquean — anti doble envío). */
button { transition: transform 0.16s cubic-bezier(0.34, 1.56, 0.64, 1); }
button:active:not(:disabled) {
  transform: scale(0.96);
  transition: transform 0.07s ease-out;
}

/* Ripple: onda desde el punto de click en los CTA principales. El <span.ripple> lo
   inyecta un listener delegado en index.html. Requiere overflow:hidden en el host. */
.btn-primary, .btn-login, .btn-danger, .btn-create, .camp-btn {
  position: relative;
  overflow: hidden;
}
.ripple {
  position: absolute;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.4);
  transform: scale(0);
  animation: ripple-out 0.6s ease-out;
  pointer-events: none;
}
@keyframes ripple-out {
  to { transform: scale(3); opacity: 0; }
}

/* ══════════════════════════════════════════════════════════════════════════
   Notificaciones internas — campana del header + página + preferencias
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Campana en el header ── */
.ph-notif { position: relative; display: flex; align-items: center; }
.ph-notif-btn {
  position: relative;
  background: var(--control-bg);
  border: 1px solid var(--control-border);
  border-radius: 10px;
  width: 38px; height: 38px;
  font-size: 1.05rem;
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  color: var(--text);
  transition: background .15s;
}
.ph-notif-btn:hover { background: var(--control-bg-hover); }
.ph-notif-badge {
  position: absolute; top: -4px; right: -4px;
  min-width: 17px; height: 17px; padding: 0 4px;
  background: #ff8a00; color: #fff;
  border-radius: 9px; font-size: 0.66rem; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  line-height: 1;
  z-index: 1;
}
/* Halo pulsante detrás del badge mientras haya no-leídas (solo se renderiza el
   badge cuando unread > 0, así que la animación solo corre cuando corresponde). */
.ph-notif-badge::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: 50%;
  background: #ff8a00;
  z-index: -1;
  animation: notif-pulse 1.8s ease-out infinite;
}
@keyframes notif-pulse {
  0%        { transform: scale(1);   opacity: 0.7; }
  70%, 100% { transform: scale(2.6); opacity: 0; }
}
.ph-notif-backdrop {
  position: fixed; inset: 0; z-index: 40;
}
/* Menú de la campana. `components/notification_bell.rs` NO lo desmonta: siempre
   está en el DOM y solo alterna la clase `is-open`, así que el estado CERRADO
   tiene que definirse aquí. Sin estas dos reglas el panel se queda desplegado
   de forma permanente — que es exactamente lo que pasaba.

   Se oculta con visibility+opacity, no con `display:none`, porque `display` no
   es animable y el componente espera una transición. `visibility: hidden` lo
   saca del árbol de accesibilidad y `pointer-events: none` evita que capture
   clics sobre lo que hay debajo mientras está invisible; la transición de
   `visibility` va retrasada al final para que el fundido de salida se vea. */
.ph-notif-menu {
  position: absolute; top: 46px; right: 0; z-index: 41;
  width: 340px; max-width: 90vw;
  background: var(--surface-overlay);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow-lg);
  overflow: hidden;

  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateY(-6px) scale(0.98);
  transform-origin: top right;
  transition: opacity 0.16s ease, transform 0.16s ease, visibility 0s linear 0.16s;
}
.ph-notif-menu.is-open {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: none;
  transition: opacity 0.16s ease, transform 0.16s ease, visibility 0s;
}
.ph-notif-menu-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border-soft);
  font-weight: 600; color: var(--text-strong);
  font-size: 0.9rem;
}
.ph-notif-all {
  background: none; border: none; cursor: pointer;
  color: var(--brand); font-size: 0.8rem; font-weight: 600;
}
.ph-notif-menu-list { max-height: 380px; overflow-y: auto; }
.ph-notif-empty { padding: 24px; text-align: center; color: var(--muted); font-size: 0.85rem; }
.ph-notif-row {
  padding: 10px 14px; border-bottom: 1px solid var(--border-soft);
}
.ph-notif-row:last-child { border-bottom: none; }
.ph-notif-row--unread { background: var(--brand-soft-bg); }
.ph-notif-row-title { font-size: 0.85rem; font-weight: 600; color: var(--text-strong); }
.ph-notif-row-body {
  font-size: 0.78rem; color: var(--muted); margin-top: 2px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ══════════════════════════════════════════════════════════════════════════
   Esqueletos de carga (shimmer) — LiveChat: lista, chat y ficha de contacto
   ══════════════════════════════════════════════════════════════════════════ */
/* Tokens: :root = tema oscuro (base); html.light-mode = claro. */
:root { --skel-base: #232326; --skel-hi: #34343a; }
html.light-mode { --skel-base: #e5e8ee; --skel-hi: #f3f5f9; }

.skel {
  background: linear-gradient(90deg, var(--skel-base) 25%, var(--skel-hi) 50%, var(--skel-base) 75%);
  background-size: 200% 100%;
  animation: shimmer-sweep 1.4s ease-in-out infinite;
  border-radius: 6px;
}
@keyframes shimmer-sweep {
  0%   { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) { .skel { animation: none; } }

/* formas base */
.skel-avatar    { width: 40px; height: 40px; border-radius: 50%; flex-shrink: 0; }
.skel-avatar-lg { width: 60px; height: 60px; border-radius: 50%; margin: 0 auto 6px; }
.skel-bar       { height: 11px; }
.skel-line      { height: 12px; }
.skel-bubble    { height: 34px; border-radius: 14px; }

/* lista de conversaciones */
.conv-skel-list { list-style: none; margin: 0; padding: 0; }
.conv-skel {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 14px; border-bottom: 1px solid var(--border-soft);
}
.conv-skel-lines { flex: 1; display: flex; flex-direction: column; gap: 8px; }

/* chat */
.chat-skel { display: flex; flex-direction: column; gap: 12px; padding: 18px 16px; }
.msg-skel { display: flex; }
.msg-skel--in  { justify-content: flex-start; }
.msg-skel--out { justify-content: flex-end; }
.msg-skel .skel-bubble { min-width: 120px; }

/* ficha de contacto */
.contact-skel { display: flex; flex-direction: column; gap: 12px; padding: 16px; }
.contact-skel-field { display: flex; flex-direction: column; gap: 6px; }

/* ── Toasts (notificaciones emergentes) ── */
.toast-host {
  position: fixed; top: 18px; left: 50%; transform: translateX(-50%);
  z-index: 9999; display: flex; flex-direction: column; gap: 10px;
  align-items: center; pointer-events: none;
}
.toast {
  pointer-events: auto;
  display: flex; align-items: center; gap: 11px;
  min-width: 280px; max-width: 92vw;
  padding: 12px 18px;
  background: var(--surface-overlay);
  border: 1px solid var(--border);
  border-left: 4px solid var(--brand);
  border-radius: 12px;
  box-shadow: var(--shadow-lg);
  color: var(--text-strong); font-size: 0.9rem; font-weight: 600;
  animation: toast-in 0.55s cubic-bezier(0.18, 1.25, 0.4, 1) both;
}
.toast--info    { border-left-color: var(--badge-info-fg, #3b82f6); }
.toast--ok      { border-left-color: var(--badge-success-fg, #22c55e); }
.toast--warn    { border-left-color: #ff8a00; }
.toast--danger  { border-left-color: var(--badge-danger-fg, #ef4444); }
.toast-dot {
  width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0;
  background: currentColor;
}
.toast--info   .toast-dot { color: var(--badge-info-fg, #3b82f6); }
.toast--ok     .toast-dot { color: var(--badge-success-fg, #22c55e); }
.toast--warn   .toast-dot { color: #ff8a00; }
.toast--danger .toast-dot { color: var(--badge-danger-fg, #ef4444); }
.toast-title { line-height: 1.3; }
@keyframes toast-in {
  from { transform: translateY(-160%); opacity: 0; }
  to   { transform: translateY(0);     opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .toast { animation: none; }
}

/* ── Página de notificaciones ── */
.notif-tabs { display: flex; gap: 6px; margin: 0 0 16px; flex-wrap: wrap; }
.notif-tabs button {
  padding: 8px 16px; border-radius: 8px;
  background: var(--control-bg); border: 1px solid var(--control-border);
  color: var(--text); cursor: pointer; font-size: 0.88rem; font-weight: 500;
}
.notif-tabs button:hover { background: var(--control-bg-hover); }
.notif-tabs button.active { background: var(--brand); border-color: var(--brand); color: #fff; }

.notif-empty { text-align: center; color: var(--muted); padding: 36px 0; font-size: 0.9rem; }

.notif-inbox-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 12px;
}
.notif-check { font-size: 0.85rem; color: var(--muted); display: flex; align-items: center; gap: 6px; }

.notif-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
.notif-item {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
  padding: 12px 14px;
  background: var(--surface); border: 1px solid var(--border-soft);
  border-radius: 10px;
}
.notif-item--unread { border-left: 3px solid var(--brand); background: var(--surface-2); }
.notif-item-main { min-width: 0; flex: 1; }
.notif-item-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.notif-item-title { font-weight: 600; color: var(--text-strong); font-size: 0.9rem; }
.notif-item-body {
  font-size: 0.83rem; color: var(--muted); margin-top: 4px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.notif-item-meta { font-size: 0.74rem; color: var(--muted-2); margin-top: 6px; }
.notif-item-actions { display: flex; gap: 6px; flex-shrink: 0; align-items: center; }

/* fila completa clicable (abre el detalle) */
.notif-item-btn {
  flex: 1; min-width: 0; width: 100%;
  background: none; border: none; margin: 0; padding: 0;
  text-align: left; cursor: pointer; color: inherit; font: inherit;
  display: flex; flex-direction: column; gap: 4px;
}
.notif-item-btn:hover .notif-item-title { color: var(--brand); }
.notif-dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--brand); flex-shrink: 0;
}

/* modal de detalle */
.notif-detail-backdrop {
  position: fixed; inset: 0; z-index: 60; background: var(--scrim, rgba(0,0,0,0.5));
}
.notif-detail {
  position: fixed; z-index: 61; top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 780px; max-width: 94vw; max-height: 88vh; overflow-y: auto;
  background: var(--surface-overlay); border: 1px solid var(--border);
  border-radius: 14px; box-shadow: var(--shadow-lg); padding: 24px 28px;
}
.notif-detail-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.notif-detail-close {
  background: none; border: none; cursor: pointer; font-size: 1.05rem;
  color: var(--muted); line-height: 1; padding: 4px;
}
.notif-detail-title { margin: 0 0 10px; font-size: 1.1rem; color: var(--text-strong); text-wrap: balance; }
.notif-detail-body { margin: 0 0 16px; font-size: 0.92rem; color: var(--text); line-height: 1.6; white-space: pre-wrap; }
.notif-detail-meta { display: flex; flex-direction: column; gap: 6px; margin-bottom: 16px; }
.notif-detail-meta > div { display: flex; gap: 10px; font-size: 0.85rem; color: var(--text); }
.notif-detail-k {
  min-width: 52px; color: var(--muted); text-transform: uppercase;
  letter-spacing: 0.03em; font-size: 0.72rem; padding-top: 2px;
}
.notif-detail-go { display: inline-block; text-decoration: none; }
.notif-detail-foot { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-top: 4px; }
.notif-detail-foot .camp-btn { text-decoration: none; }
.notif-detail-hist {
  background: none; border: none; cursor: pointer; padding: 0;
  color: var(--brand); font: inherit; font-size: 0.85rem; font-weight: 600;
}

/* enlace con subrayado animado (hover) */
.underline-link {
  position: relative;
  text-decoration: none;
}
.underline-link::after {
  content: '';
  position: absolute;
  left: 0; bottom: -4px;
  width: 100%; height: 2px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.4s cubic-bezier(0.65, 0, 0.35, 1);
}
.underline-link:hover::after { transform: scaleX(1); }
@media (prefers-reduced-motion: reduce) {
  .underline-link::after { transition: none; }
}

/* cuerpo markdown en el detalle */
.notif-md { line-height: 1.6; }
.notif-md > *:first-child { margin-top: 0; }
.notif-md > *:last-child { margin-bottom: 0; }
.notif-md p { margin: 0 0 10px; }
.notif-md h1, .notif-md h2, .notif-md h3, .notif-md h4 {
  margin: 14px 0 8px; color: var(--text-strong); line-height: 1.3;
}
.notif-md h1 { font-size: 1.15rem; }
.notif-md h2 { font-size: 1.05rem; }
.notif-md h3 { font-size: 0.98rem; }
.notif-md ul, .notif-md ol { margin: 0 0 10px; padding-left: 22px; }
.notif-md li { margin: 3px 0; }
.notif-md a { color: var(--brand); text-decoration: underline; }
.notif-md code {
  background: var(--surface-2); border: 1px solid var(--border-soft);
  border-radius: 5px; padding: 1px 5px; font-size: 0.86em;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.notif-md pre {
  background: var(--surface-2); border: 1px solid var(--border-soft);
  border-radius: 8px; padding: 12px 14px; overflow-x: auto; margin: 0 0 10px;
}
.notif-md pre code { background: none; border: none; padding: 0; }
.notif-md blockquote {
  margin: 0 0 10px; padding: 4px 14px; border-left: 3px solid var(--border);
  color: var(--muted);
}
.notif-md table { border-collapse: collapse; width: 100%; margin: 0 0 10px; font-size: 0.86rem; }
.notif-md th, .notif-md td { border: 1px solid var(--border-soft); padding: 6px 9px; text-align: left; }
.notif-md hr { border: none; border-top: 1px solid var(--border-soft); margin: 12px 0; }

/* ── Historial de enviados: filtros + paginación ── */
.notif-sent-filters {
  display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-bottom: 14px;
}
.notif-sent-filters select,
.notif-sent-filters input {
  background: var(--control-bg); border: 1px solid var(--control-border);
  border-radius: 8px; padding: 8px 10px; color: var(--text); font-size: 0.85rem;
}
.notif-sent-filters .notif-search { min-width: 200px; flex: 1; }
.notif-pager {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-top: 12px;
}
.notif-pager-info { font-size: 0.82rem; color: var(--muted); }
.notif-table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.notif-table-scroll .camp-table { min-width: 520px; }

/* ── Responsive: pantallas pequeñas ── */
@media (max-width: 640px) {
  .notif-page { padding-left: 12px; padding-right: 12px; }
  .notif-tabs { overflow-x: auto; flex-wrap: nowrap; }
  .notif-tabs button { white-space: nowrap; }
  .notif-sent-filters { flex-direction: column; align-items: stretch; }
  .notif-sent-filters select,
  .notif-sent-filters input,
  .notif-sent-filters .notif-search { width: 100%; min-width: 0; }
  .notif-pager { flex-wrap: wrap; gap: 8px; }
  .notif-item { flex-direction: column; align-items: stretch; }
  .notif-detail { width: 96vw; max-height: 90vh; padding: 16px 16px; }
  .notif-detail-foot { flex-direction: column; align-items: stretch; }
  .notif-inbox-toolbar { flex-direction: column; align-items: stretch; gap: 8px; }
  .ph-notif-menu { width: 94vw; right: -6px; }
}

/* ── Compositor ── */
.notif-compose, .notif-inbox { max-width: 720px; }
.notif-sent { max-width: 960px; }
.notif-field { margin-bottom: 14px; display: flex; flex-direction: column; gap: 6px; }
.notif-field > label { font-size: 0.8rem; font-weight: 600; color: var(--text-strong); }
.notif-field input[type=text], .notif-field textarea, .notif-field select {
  background: var(--control-bg); border: 1px solid var(--control-border);
  border-radius: 8px; padding: 9px 11px; color: var(--text); font-size: 0.88rem;
  width: 100%;
}
.notif-chips { display: flex; flex-wrap: wrap; gap: 8px; margin: -6px 0 14px; }
.notif-chip {
  display: flex; align-items: center; gap: 6px;
  padding: 6px 12px; border-radius: 20px;
  background: var(--control-bg); border: 1px solid var(--control-border);
  font-size: 0.83rem; color: var(--text); cursor: pointer;
}
.notif-banner { padding: 10px 14px; border-radius: 8px; margin-bottom: 14px; font-size: 0.86rem; }
.notif-banner--ok  { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.notif-banner--err { background: var(--badge-danger-bg);  color: var(--badge-danger-fg); }

/* ── Preferencias / ajustes (tablas de checkboxes) ── */
.notif-master { display: flex; align-items: center; gap: 8px; font-size: 0.9rem; color: var(--text-strong); font-weight: 600; margin-bottom: 8px; }
.notif-prefs-hint { font-size: 0.8rem; color: var(--muted); margin: 0 0 14px; }
.notif-prefs-table th:not(:first-child), .cc-notif-settings .camp-table th:not(:first-child) { width: 90px; text-align: center; }
.notif-prefs-table td:not(:first-child), .cc-notif-settings .camp-table td:not(:first-child) { text-align: center; }
.notif-lock { font-size: 0.75rem; }
.notif-recipients { margin-top: 18px; border-top: 1px solid var(--border-soft); padding-top: 14px; }
.notif-recipients-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.notif-recipients-head h4 { margin: 0; font-size: 0.9rem; color: var(--text-strong); }

/* ── Módulo Mapa Interactivo (owner-only) ─────────────────────────────────── */
.mapa-page { display: flex; flex-direction: column; gap: 14px; padding: 18px; height: 100%; box-sizing: border-box; }
/* El PageHeader rompe el padding del root para quedar a ancho completo (igual que
   en los demás módulos). Sin esto la barra superior queda embutida y se ve mal. */
.mapa-page > .ph { margin: -18px -18px 0; }
.mapa-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.mapa-title { margin: 0; font-size: 1.4rem; color: var(--text-strong); }
.mapa-subtitle { margin: 2px 0 0; color: var(--muted); font-size: 0.9rem; }
.mapa-mode-tabs { display: flex; gap: 8px; }
.mapa-tab { padding: 8px 14px; border-radius: 10px; border: 1px solid var(--control-border);
    background: var(--control-bg); color: var(--text); cursor: pointer; font-weight: 600; font-size: 0.9rem; }
.mapa-tab:hover { background: var(--control-bg-hover); }
.mapa-tab.is-active { background: var(--brand); border-color: var(--brand); color: #fff; }

.mapa-alert { padding: 10px 14px; border-radius: 10px; font-size: 0.88rem; }
.mapa-alert--err { background: var(--badge-danger-bg); color: var(--badge-danger-fg); }
.mapa-alert--ok { background: var(--badge-success-bg); color: var(--badge-success-fg); }

/* Altura FIJA basada en viewport → el mapa no crece con la lista; ambas columnas
   tienen scroll interno propio. */
.mapa-body { display: flex; gap: 14px; height: calc(100dvh - 210px); min-height: 460px; }
.mapa-controls { width: 330px; flex-shrink: 0; height: 100%; overflow-y: auto; display: flex; flex-direction: column; gap: 14px;
    background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 14px; }
.mapa-control-block { display: flex; flex-direction: column; }
.mapa-label { font-size: 0.78rem; color: var(--muted); margin-bottom: 4px; font-weight: 600; }
.mapa-select, .mapa-input { width: 100%; box-sizing: border-box; padding: 8px 10px; border-radius: 8px;
    border: 1px solid var(--control-border); background: var(--control-bg); color: var(--text); font-size: 0.88rem; }
.mapa-input { margin-bottom: 8px; }

.mapa-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 14px; }
.mapa-stat { background: var(--surface-2); border-radius: 8px; padding: 8px 10px; display: flex; flex-direction: column; }
.mapa-stat span { font-size: 0.72rem; color: var(--muted); }
.mapa-stat b { font-size: 1.15rem; color: var(--text-strong); }

.mapa-offices-actions { display: flex; gap: 8px; margin-bottom: 12px; flex-wrap: wrap; }
.mapa-btn { padding: 8px 12px; border-radius: 8px; border: 1px solid var(--control-border);
    background: var(--control-bg); color: var(--text); cursor: pointer; font-size: 0.85rem; font-weight: 600; }
.mapa-btn:hover { background: var(--control-bg-hover); }
.mapa-btn--primary { background: var(--brand); border-color: var(--brand); color: #fff; }
.mapa-btn--danger { background: var(--badge-danger-bg); color: var(--badge-danger-fg); border-color: transparent; }
.mapa-btn:disabled { opacity: 0.55; cursor: not-allowed; }

.mapa-editor { background: var(--surface-2); border-radius: 10px; padding: 12px; margin-bottom: 12px; }
.mapa-editor-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: -2px 0 10px; padding-bottom: 8px; border-bottom: 1px solid var(--border-soft); }
.mapa-editor-title { font-weight: 600; color: var(--text-strong); font-size: 0.95rem; }
.mapa-editor-close { background: var(--control-bg); border: 1px solid var(--control-border); color: var(--muted); border-radius: 8px; width: 28px; height: 28px; line-height: 1; cursor: pointer; font-size: 0.9rem; display: flex; align-items: center; justify-content: center; }
.mapa-editor-close:hover { background: var(--control-bg-hover); color: var(--text-strong); }
.mapa-editor-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 6px; }
.mapa-coord-row { display: flex; gap: 8px; }
.mapa-coord-row .mapa-input { flex: 1; min-width: 0; }

.mapa-office-list { display: flex; flex-direction: column; gap: 12px; }
.mapa-office-group { display: flex; flex-direction: column; }
.mapa-office-estado { font-size: 0.8rem; font-weight: 700; color: var(--text-strong); text-transform: uppercase;
    letter-spacing: 0.4px; margin-bottom: 4px; display: flex; align-items: center; gap: 6px; width: 100%;
    background: var(--surface-2); border: 1px solid var(--border-soft); border-radius: 8px; padding: 7px 10px;
    cursor: pointer; text-align: left; }
.mapa-office-estado:hover { background: var(--control-bg-hover); }
.mapa-acc-chevron { display: inline-block; transition: transform 0.15s; color: var(--muted); font-size: 0.75rem; }
.mapa-acc-chevron.is-open { transform: rotate(90deg); }
.mapa-office-estado .mapa-office-count { margin-left: auto; }
.mapa-office-group-body { display: flex; flex-direction: column; padding: 4px 0 2px; }
.mapa-office-count { background: var(--badge-neutral-bg); color: var(--badge-neutral-fg); border-radius: 999px;
    padding: 0 7px; font-size: 0.7rem; font-weight: 700; }
.mapa-office-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; width: 100%;
    padding: 7px 10px; border-radius: 8px; border: 1px solid transparent; background: transparent; color: var(--text);
    cursor: pointer; text-align: left; font-size: 0.86rem; }
.mapa-office-row:hover { background: var(--control-bg-hover); border-color: var(--border-soft); }
.mapa-office-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mapa-office-flags { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.mapa-badge { border-radius: 999px; padding: 1px 8px; font-size: 0.68rem; font-weight: 700; }
.mapa-badge--warn { background: var(--badge-warn-bg); color: var(--badge-warn-fg); }
.mapa-pin--miss { color: var(--badge-warn-fg); }

/* z-index:0 aísla el stacking context de Leaflet (sus panes/controles usan
   z-index hasta ~1000). Sin esto el mapa se pinta sobre overlays de la barra
   superior (p. ej. el desplegable de notificaciones, z-index 41). */
.mapa-canvas-wrap { flex: 1; position: relative; z-index: 0; min-width: 0; height: 100%; border-radius: 12px; overflow: hidden;
    border: 1px solid var(--border); }
.mapa-canvas { width: 100%; height: 100%; }
/* Toggle de vista de cobertura (calor / puntos / zonas) */
.mapa-view-toggle { display: flex; gap: 4px; }
.mapa-view-btn { flex: 1; padding: 6px 4px; font-size: 0.75rem; border: 1px solid var(--control-border);
    background: var(--control-bg); color: var(--muted); border-radius: 8px; cursor: pointer; white-space: nowrap; }
.mapa-view-btn:hover { background: var(--control-bg-hover); }
.mapa-view-btn.is-active { background: var(--brand-soft-bg); color: var(--brand-soft-fg); border-color: var(--brand); font-weight: 600; }
/* divIcons de cobertura (Leaflet inyecta estos className) */
.mapa-pin-ico { background: none; border: none; font-size: 20px; line-height: 1; text-align: center;
    filter: drop-shadow(0 1px 2px rgba(0,0,0,0.4)); }
.mapa-cluster-label { background: none; border: none; display: flex; align-items: center; justify-content: center;
    font-weight: 700; color: #fff; font-size: 0.82rem; text-shadow: 0 1px 3px rgba(0,0,0,0.7); pointer-events: none; }
.mapa-place-hint { position: absolute; top: 12px; left: 50%; transform: translateX(-50%); z-index: 500;
    background: var(--brand); color: #fff; padding: 8px 16px; border-radius: 999px; font-size: 0.85rem;
    font-weight: 600; box-shadow: var(--shadow-md); }

/* Estilo "midnight": tiñe de azul los tiles oscuros (CARTO dark_all no es azul
   nativo; sin API key no hay raster midnight, así que se logra por filtro CSS
   solo sobre el pane de tiles → no afecta marcadores/heatmap ni popups). */
.mapa-midnight .leaflet-tile-pane {
    filter: sepia(0.7) hue-rotate(178deg) saturate(2.2) brightness(0.78) contrast(1.05);
}

/* Leaflet popups en tema oscuro/claro */
.leaflet-popup-content-wrapper, .leaflet-popup-tip { background: var(--surface-overlay); color: var(--text); }
.leaflet-popup-content { font-size: 0.85rem; }
.leaflet-container { background: var(--surface-2); font: inherit; }

@media (max-width: 860px) {
    .mapa-body { flex-direction: column; }
    .mapa-controls { width: 100%; max-height: 340px; }
    .mapa-canvas-wrap { min-height: 420px; }
}

/* ── Buscador de modelos OpenRouter (modal LLM/Multimedia) ─────────────────── */
.model-picker-modal {
  max-width: min(1180px, 96vw);
  width: 96%;
  display: flex;
  flex-direction: column;
  max-height: 90vh;
  overflow: hidden; /* solo el área de scroll interna scrollea (no doble scroll) */
}
.model-picker-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
  margin-bottom: 12px;
}
.model-picker-filters select,
.model-picker-filters input {
  padding: 9px 12px;
  border-radius: 8px;
  border: 1px solid var(--control-border);
  background: var(--control-bg);
  color: var(--text);
  font-size: 0.9rem;
}
.model-picker-filters .model-picker-search { flex: 1 1 240px; min-width: 200px; }
.model-picker-filters input[type="number"] { width: 200px; }
.model-picker-scroll {
  overflow: auto;
  flex: 1 1 auto;
  min-height: 0; /* imprescindible para que un hijo flex pueda scrollear */
  border: 1px solid var(--border);
  border-radius: 12px;
}
.model-picker-table {
  width: 100%;
  min-width: 760px;
  border-collapse: collapse;
  font-size: 0.9rem;
}
.model-picker-table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--surface-2);
  color: var(--text-strong);
  font-weight: 600;
  text-align: left;
  padding: 10px 14px;
  white-space: nowrap;
  border-bottom: 1px solid var(--border);
}
.model-picker-table td {
  padding: 10px 14px;
  border-bottom: 1px solid var(--border-soft);
  vertical-align: top;
  white-space: nowrap;
}
.model-picker-table tbody tr:hover { background: var(--surface-2); }
.model-picker-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.model-picker-name { white-space: normal; min-width: 240px; max-width: 380px; }
.model-picker-name-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.model-picker-model { font-weight: 600; color: var(--text-strong); }
.model-picker-name code { font-size: 0.72rem; color: var(--muted); word-break: break-all; }
.model-picker-caps { font-size: 0.78rem; color: var(--muted); white-space: normal; max-width: 170px; }
.model-picker-free {
  font-size: 0.68rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.02em;
  padding: 1px 7px; border-radius: 999px;
  background: var(--badge-success-bg); color: var(--badge-success-fg);
}
.model-picker-warn {
  display: flex; gap: 12px; align-items: center; justify-content: space-between;
  background: var(--badge-warn-bg); color: var(--badge-warn-fg);
  border: 1px solid var(--border); border-radius: 10px;
  padding: 10px 14px; margin-bottom: 12px; font-size: 0.85rem; line-height: 1.4;
}
.model-picker-warn button { flex: 0 0 auto; }
@media (max-width: 640px) {
  .model-picker-filters .model-picker-search,
  .model-picker-filters input[type="number"] { flex: 1 1 100%; width: 100%; }
}

/* ── Step-up de desactivar 2FA: tabs contraseña / código ────────────────────── */
.mfa-stepup { margin-top: 4px; }
.mfa-tabs { display: flex; gap: 8px; margin-bottom: 12px; }
.mfa-tab {
  flex: 1;
  padding: 9px 12px;
  border-radius: 8px;
  cursor: pointer;
  border: 1px solid var(--control-border);
  background: var(--control-bg);
  color: var(--muted);
  font-size: 0.85rem;
  font-weight: 600;
  font-family: inherit;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.mfa-tab:hover { background: var(--control-bg-hover); }
.mfa-tab.active {
  background: var(--brand-soft-bg);
  color: var(--brand-soft-fg);
  border-color: var(--brand);
}

/* Auditor del system prompt (Personalidad > Auditar) */
.prompt-audit-legend { display:flex; flex-wrap:wrap; gap:8px 14px; align-items:center; padding:10px 12px; margin-bottom:12px; background:var(--surface-2); border:1px solid var(--border); border-radius:10px; }
.prompt-audit-total { display:flex; flex-direction:column; margin-right:6px; padding-right:14px; border-right:1px solid var(--border); }
.prompt-audit-total-num { font-size:1.25rem; font-weight:700; color:var(--text-strong); font-variant-numeric:tabular-nums; line-height:1.1; }
.prompt-audit-total-lbl { font-size:0.72rem; color:var(--muted); }
.prompt-audit-chip { display:flex; align-items:center; gap:6px; font-size:0.78rem; }
.prompt-audit-dot { width:10px; height:10px; border-radius:3px; flex:0 0 auto; }
.prompt-audit-chip-lbl { color:var(--muted); }
.prompt-audit-chip-tok { color:var(--text-strong); font-variant-numeric:tabular-nums; font-weight:600; }
.prompt-audit-scroll { overflow:auto; flex:1 1 auto; min-height:0; display:flex; flex-direction:column; gap:10px; padding-right:4px; }
.prompt-audit-seg { border-left:4px solid #94a3b8; background:var(--surface-2); border-radius:0 8px 8px 0; padding:10px 14px; }
.prompt-audit-seg-head { display:flex; align-items:center; gap:10px; margin-bottom:6px; flex-wrap:wrap; }
.prompt-audit-seg-title { font-weight:700; color:var(--text-strong); font-size:0.9rem; }
.prompt-audit-seg-src { font-size:0.72rem; font-weight:600; text-transform:uppercase; letter-spacing:0.02em; }
.prompt-audit-seg-tok { margin-left:auto; font-size:0.75rem; color:var(--muted); font-variant-numeric:tabular-nums; }
.prompt-audit-seg-text { margin:0; white-space:pre-wrap; word-break:break-word; font-family:ui-monospace,Menlo,Consolas,monospace; font-size:0.8rem; line-height:1.5; color:var(--text); background:var(--bg); border:1px solid var(--border-soft); border-radius:6px; padding:8px 10px; max-height:300px; overflow:auto; }
.prompt-audit-tools-head { display:flex; align-items:center; gap:10px; margin:16px 0 2px; padding-top:12px; border-top:1px solid var(--border); }
.prompt-audit-tools-head .prompt-audit-seg-tok { margin-left:auto; }
.prompt-audit-tool { padding:6px 0; border-top:1px solid var(--border-soft); }
.prompt-audit-tool:first-child { border-top:none; }
.prompt-audit-tool-head { display:flex; align-items:center; gap:8px; }
.prompt-audit-tool-head .prompt-audit-seg-tok { margin-left:auto; }
.prompt-audit-tool-name { font-weight:600; color:var(--text-strong); font-size:0.82rem; }
.prompt-audit-tool-desc { font-size:0.78rem; color:var(--muted); white-space:pre-wrap; margin-top:2px; line-height:1.45; }

/* ============================================================================
   crm.css — Estilos del módulo CRM (Kanban de embudos + constructor + modales)

   Extraído de frontend/style.css del panel original. Al portar:
   · Opción A: pega este bloque al final de tu style.css.
   · Opción B: si tu bundler soporta @import, déjalo como archivo aparte.

   DEPENDE de los tokens semánticos de tema del panel (var(--brand), var(--surface),
   var(--text), var(--border), var(--badge-*), etc.). Si el proyecto destino NO tiene
   esos tokens, define equivalentes en :root o reemplaza los var(--token) por colores
   fijos. Ver la sección "Theming (tokens)" del CLAUDE.md del panel original.
   ============================================================================ */

/* ── CRM · Kanban de embudos ─────────────────────────────────────────────── */
.crm-wrap { padding: 16px 24px 32px; display: flex; flex-direction: column; gap: 16px; }
.crm-toolbar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.crm-embudo-select {
  background: var(--control-bg); color: var(--text);
  border: 1px solid var(--control-border); border-radius: 10px;
  padding: 8px 12px; font-size: 14px; min-width: 220px;
}
.crm-embudo-select:hover { background: var(--control-bg-hover); }
.crm-run-btn {
  background: var(--brand); color: #fff; border: none; border-radius: 10px;
  padding: 8px 16px; font-size: 14px; font-weight: 600; cursor: pointer;
  box-shadow: var(--shadow-sm); transition: background .15s ease;
}
.crm-run-btn:hover { background: var(--brand-dark); }
.crm-loading-chip {
  font-size: 12px; color: var(--muted);
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 999px; padding: 4px 10px;
}

.crm-board {
  display: flex; gap: 16px; align-items: flex-start;
  overflow-x: auto; padding-bottom: 12px;
}
.crm-col {
  flex: 0 0 288px; min-width: 288px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 14px; padding: 12px; box-shadow: var(--shadow-sm);
  display: flex; flex-direction: column; gap: 8px;
}
.crm-col-head { display: flex; align-items: center; justify-content: space-between; }
.crm-col-title { display: flex; align-items: center; gap: 8px; }
.crm-col-name { font-weight: 700; color: var(--text-strong); font-size: 15px; }
.crm-col-flag {
  font-size: 11px; font-weight: 600; padding: 2px 8px; border-radius: 999px;
  background: var(--badge-success-bg); color: var(--badge-success-fg);
}
.crm-col-count {
  font-size: 12px; font-weight: 600; color: var(--muted);
  background: var(--surface-2); border-radius: 999px; padding: 2px 9px; min-width: 24px; text-align: center;
}
.crm-col-obj { font-size: 12px; color: var(--muted); line-height: 1.35; min-height: 16px; }
.crm-col-body { display: flex; flex-direction: column; gap: 8px; }

.crm-card {
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 10px; padding: 10px; display: flex; flex-direction: column; gap: 6px;
}
.crm-card-top { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
.crm-card-name { font-weight: 600; color: var(--text); font-size: 14px; }
.crm-card-lock { font-size: 12px; }
.crm-card-sub { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--muted); flex-wrap: wrap; }
.crm-card-chan {
  font-size: 11px; padding: 1px 7px; border-radius: 999px;
  background: var(--badge-info-bg); color: var(--badge-info-fg);
}
.crm-move-select {
  margin-top: 2px; width: 100%; font-size: 12px;
  background: var(--control-bg); color: var(--text);
  border: 1px solid var(--control-border); border-radius: 8px; padding: 5px 8px;
}
.crm-move-select:hover { background: var(--control-bg-hover); }
.crm-col-empty { font-size: 12px; color: var(--muted-2); text-align: center; padding: 10px 0; font-style: italic; }

/* ── CRM · Constructor + tabs + modales ──────────────────────────────────── */
.crm-viewtabs { display: inline-flex; background: var(--surface-2); border: 1px solid var(--border); border-radius: 10px; padding: 3px; gap: 2px; }
.crm-tab { background: transparent; color: var(--muted); border: none; border-radius: 8px; padding: 6px 14px; font-size: 13px; font-weight: 600; cursor: pointer; }
.crm-tab.active { background: var(--brand); color: #fff; }
.crm-cons-actions { display: inline-flex; gap: 8px; }
.crm-btn-sec { background: var(--control-bg); color: var(--text); border: 1px solid var(--control-border); border-radius: 9px; padding: 7px 12px; font-size: 13px; cursor: pointer; }
.crm-btn-sec:hover { background: var(--control-bg-hover); }
.crm-btn-danger { color: var(--danger, #ef4444); }

.crm-constructor { display: flex; flex-direction: column; gap: 12px; max-width: 860px; }

/* Canvas / flujo horizontal del constructor */
.crm-canvas-viewport {
  position: relative; overflow: auto; border: 1px solid var(--border); border-radius: 16px;
  background:
    linear-gradient(90deg, var(--surface-2) 1px, transparent 1px) 0 0 / 28px 28px,
    linear-gradient(var(--surface-2) 1px, transparent 1px) 0 0 / 28px 28px,
    var(--bg-2, var(--bg));
  padding: 28px; min-height: 340px;
}
.crm-canvas-zoom {
  position: sticky; top: 10px; left: 10px; z-index: 5; display: inline-flex; align-items: center; gap: 4px;
  background: var(--surface-overlay, var(--panel-2)); border: 1px solid var(--border); border-radius: 10px;
  padding: 4px 6px; box-shadow: var(--shadow-sm); width: fit-content;
}
.crm-canvas-zoom-label { font-size: 12px; color: var(--muted); min-width: 38px; text-align: center; }
.crm-flow {
  display: flex; align-items: flex-start; gap: 0; width: max-content; margin-top: 10px;
  transition: transform .12s ease;
}
.crm-flow-item { display: flex; align-items: flex-start; flex: 0 0 auto; }
.crm-flow-node { flex: 0 0 auto; width: 268px; }
.crm-flow-arrow {
  flex: 0 0 auto; align-self: center; color: var(--muted-2); font-size: 20px; padding: 0 6px;
  transform: translateY(-2px);
}
.crm-flow-entry {
  display: flex; align-items: center; gap: 10px; background: var(--brand-soft-bg, var(--surface-2));
  border: 1px solid var(--border); border-radius: 14px; padding: 14px 16px; box-shadow: var(--shadow-sm);
}
.crm-flow-entry-ico { font-size: 18px; color: var(--brand); }
.crm-flow-entry strong { display: block; color: var(--text-strong); font-size: 14px; }
.crm-flow-entry span { display: block; color: var(--muted); font-size: 12px; }

.crm-fase-card { background: var(--surface); border: 1px solid var(--border); border-radius: 14px; padding: 14px 16px; box-shadow: var(--shadow-sm); }
.crm-fase-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.crm-fase-title { display: flex; align-items: center; gap: 9px; color: var(--text-strong); font-size: 15px; }
.crm-fase-orden { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 7px; background: var(--brand-soft-bg, var(--surface-2)); color: var(--brand-soft-fg, var(--brand)); font-size: 12px; font-weight: 700; }
.crm-fase-tools { display: inline-flex; gap: 4px; }
.crm-icon-btn { background: var(--control-bg); border: 1px solid var(--control-border); border-radius: 7px; width: 28px; height: 28px; color: var(--text); cursor: pointer; font-size: 13px; line-height: 1; }
.crm-icon-btn:hover:not(:disabled) { background: var(--control-bg-hover); }
.crm-icon-btn:disabled { opacity: .4; cursor: not-allowed; }
.crm-fase-obj { color: var(--muted); font-size: 12.5px; margin: 6px 0 10px; }
.crm-fase-sec { display: flex; align-items: center; justify-content: space-between; margin-top: 10px; }
.crm-fase-sec-title { font-size: 12px; font-weight: 600; color: var(--muted-2); text-transform: uppercase; letter-spacing: .03em; }
.crm-mini-btn { background: transparent; border: 1px dashed var(--border); border-radius: 8px; color: var(--brand); font-size: 12px; padding: 3px 10px; cursor: pointer; }
.crm-mini-btn:hover { background: var(--surface-2); }
.crm-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }
.crm-chip { display: inline-flex; align-items: center; gap: 6px; background: var(--badge-info-bg); color: var(--badge-info-fg); border-radius: 999px; padding: 3px 10px; font-size: 12px; }
.crm-chip-action { background: var(--badge-purple-bg); color: var(--badge-purple-fg); }
.crm-chip-x { background: transparent; border: none; color: inherit; cursor: pointer; font-size: 14px; line-height: 1; opacity: .7; padding: 0; }
.crm-chip-x:hover { opacity: 1; }
.crm-soft-empty { font-size: 12px; color: var(--muted-2); font-style: italic; }
.crm-entry-mode { font-size: 12.5px; font-weight: 600; color: var(--brand); background: var(--brand-soft-bg, var(--surface-2)); border: 1px solid var(--border-soft); border-radius: 8px; padding: 5px 10px; margin-top: 4px; }
.crm-add-fase {
  align-self: center; background: transparent; border: 1.5px dashed var(--brand); color: var(--brand);
  border-radius: 14px; padding: 18px 14px; font-size: 13px; font-weight: 600; cursor: pointer;
  min-height: 64px;
}
.crm-add-fase:hover { background: var(--brand-soft-bg, var(--surface-2)); }

.crm-modal-backdrop { position: fixed; inset: 0; background: var(--scrim, rgba(0,0,0,.5)); display: flex; align-items: center; justify-content: center; z-index: 1000; padding: 20px; }
.crm-modal { background: var(--surface-overlay, var(--panel-2)); border: 1px solid var(--border); border-radius: 16px; box-shadow: var(--shadow-lg); width: 100%; max-width: 460px; max-height: 90vh; overflow-y: auto; }
.crm-modal-head { display: flex; align-items: center; justify-content: space-between; padding: 16px 18px; border-bottom: 1px solid var(--border); color: var(--text-strong); font-size: 16px; }
.crm-modal-foot { display: flex; justify-content: flex-end; gap: 8px; padding: 14px 18px; border-top: 1px solid var(--border); }
.crm-form { display: flex; flex-direction: column; gap: 6px; padding: 16px 18px; }
.crm-form label { font-size: 12.5px; font-weight: 600; color: var(--muted); margin-top: 6px; }
.crm-input { background: var(--control-bg); color: var(--text); border: 1px solid var(--control-border); border-radius: 9px; padding: 8px 11px; font-size: 14px; width: 100%; box-sizing: border-box; }
.crm-textarea { min-height: 70px; resize: vertical; font-family: inherit; }
.crm-hint { font-size: 11.5px; color: var(--muted-2); margin-top: 4px; }

/* ── CRM · Detalle del lead (notas + historial) ──────────────────────────── */
.crm-card-name-link { cursor: pointer; text-decoration: underline; text-decoration-color: transparent; transition: text-decoration-color .12s ease; }
.crm-card-name-link:hover { text-decoration-color: var(--brand); color: var(--brand); }

.crm-modal-lead { max-width: 520px; }
.crm-lead-toolbar { display: flex; align-items: center; justify-content: space-between; padding: 12px 18px 0; gap: 10px; }
.crm-lead-body { padding: 14px 18px 18px; }
.crm-lead-notas { display: flex; flex-direction: column; gap: 12px; }
.crm-note-form { display: flex; flex-direction: column; gap: 8px; background: var(--surface-2); border: 1px solid var(--border); border-radius: 12px; padding: 12px; }
.crm-note-tipo { width: auto; align-self: flex-start; }
.crm-lead-list { display: flex; flex-direction: column; gap: 8px; max-height: 320px; overflow-y: auto; }
.crm-note-item { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 9px 12px; }
.crm-note-item-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 4px; }
.crm-note-tag { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--brand); }
.crm-note-date { font-size: 11px; color: var(--muted-2); }
.crm-note-text { font-size: 13.5px; color: var(--text); line-height: 1.4; }
.crm-hist-item { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px 12px; background: var(--surface); border: 1px solid var(--border); border-radius: 10px; }
.crm-hist-evento { font-size: 13px; color: var(--text); font-weight: 600; }

/* ── CRM · Ficha del cliente (contacto + actividades + cronología) ────────── */
.crm-lead-contact { display: flex; flex-wrap: wrap; gap: 8px; padding: 12px 18px 0; }
.crm-contact-chip {
  display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px;
  background: var(--surface-2); color: var(--text); border: 1px solid var(--border);
  border-radius: 999px; padding: 4px 12px; text-decoration: none;
}
.crm-contact-chip:hover { border-color: var(--brand); color: var(--brand); }
.crm-note-form-row { display: flex; gap: 8px; align-items: center; }
.crm-note-due { width: auto; flex: 0 0 auto; }
.crm-lead-section-title { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); margin-top: 2px; }

/* Actividad pendiente (nota con vencimiento) */
.crm-activity-item {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 10px;
  background: var(--surface); border: 1px solid var(--border); border-left-width: 3px;
  border-radius: 10px; padding: 9px 12px;
}
.crm-activity-item.crm-due-overdue { border-left-color: var(--badge-danger-fg); }
.crm-activity-item.crm-due-today   { border-left-color: var(--badge-warn-fg); }
.crm-activity-item.crm-due-soon    { border-left-color: var(--badge-success-fg); }
.crm-activity-main { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.crm-activity-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.crm-activity-actions { display: flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.crm-due-badge { font-size: 11px; font-weight: 700; border-radius: 999px; padding: 2px 9px; white-space: nowrap; }
.crm-due-badge.crm-due-overdue { background: var(--badge-danger-bg); color: var(--badge-danger-fg); }
.crm-due-badge.crm-due-today   { background: var(--badge-warn-bg); color: var(--badge-warn-fg); }
.crm-due-badge.crm-due-soon    { background: var(--badge-success-bg); color: var(--badge-success-fg); }

/* Cronología unificada */
.crm-timeline { position: relative; }
.crm-timeline-item { display: flex; gap: 10px; padding: 8px 12px; background: var(--surface); border: 1px solid var(--border); border-radius: 10px; }
.crm-timeline-icon { font-size: 15px; flex: 0 0 auto; line-height: 1.5; }
.crm-timeline-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1 1 auto; }
.crm-timeline-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }

/* ════════════════════════════════════════════════════════════════════════════
   CRM · Rediseño estilo Odoo (panel de control + vistas + tarjetas grandes)
   Estas reglas van DESPUÉS de las base → ganan por cascada (mismo specificity).
   ════════════════════════════════════════════════════════════════════════════ */

/* Más aire general */
.crm-wrap { padding: 0 0 32px; gap: 0; }

/* ── Panel de control (barra superior tipo Odoo) ─────────────────────────── */
.crm-cpanel {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  flex-wrap: wrap; padding: 12px 24px; margin-bottom: 18px;
  background: var(--surface); border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 20;
}
.crm-cpanel-left { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.crm-cpanel-right { display: flex; align-items: center; gap: 10px; }
.crm-embudo-select { min-width: 200px; }

/* Conmutador de vistas (iconos, derecha) */
.crm-viewswitch { display: inline-flex; background: var(--surface-2); border: 1px solid var(--border); border-radius: 10px; padding: 3px; gap: 2px; }
.crm-viewbtn {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 34px; height: 30px; padding: 0 8px; font-size: 15px; line-height: 1;
  background: transparent; color: var(--muted); border: none; border-radius: 8px; cursor: pointer;
  transition: background .12s ease, color .12s ease;
}
.crm-viewbtn:hover { background: var(--control-bg-hover); color: var(--text); }
.crm-viewbtn.active { background: var(--brand); color: #fff; box-shadow: var(--shadow-sm); }
/* El botón Constructor (⚙) va suelto a la derecha del grupo */
.crm-cpanel-right > .crm-viewbtn { border: 1px solid var(--border); background: var(--surface-2); }
.crm-cpanel-right > .crm-viewbtn.active { border-color: var(--brand); background: var(--brand); }

/* Buscador (centro del panel) */
.crm-cpanel-search { flex: 1 1 240px; max-width: 480px; position: relative; display: flex; align-items: center; }
.crm-search-ico { position: absolute; left: 13px; font-size: 13px; opacity: .55; pointer-events: none; }
.crm-search-input {
  width: 100%; background: var(--control-bg); color: var(--text);
  border: 1px solid var(--control-border); border-radius: 999px;
  padding: 9px 34px 9px 36px; font-size: 13.5px; box-sizing: border-box;
}
.crm-search-input:focus { border-color: var(--brand); outline: none; box-shadow: 0 0 0 3px var(--brand-soft-bg, transparent); }
.crm-search-clear {
  position: absolute; right: 8px; width: 22px; height: 22px; border: none; background: transparent;
  color: var(--muted); cursor: pointer; font-size: 17px; line-height: 1; border-radius: 50%;
}
.crm-search-clear:hover { background: var(--surface-2); color: var(--text); }

/* Botón "+" de alta manual por fase */
.crm-col-head-actions { display: flex; align-items: center; gap: 6px; }
.crm-col-add {
  width: 24px; height: 24px; border-radius: 7px; border: 1px solid var(--border);
  background: var(--surface); color: var(--brand); font-size: 17px; line-height: 1;
  cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
  transition: background .12s ease, color .12s ease, border-color .12s ease;
}
.crm-col-add:hover { background: var(--brand); color: #fff; border-color: var(--brand); }

/* Board sin scrollbars internos por columna: la página entera scrollea */
.crm-col { max-height: none; }
.crm-col-body { overflow-y: visible; }
.crm-board { padding-bottom: 24px; }

/* ── Ficha completa del lead (/crm/lead/:embudo/:user) ───────────────────── */
.crm-lead-page { padding: 18px 24px 48px; display: flex; flex-direction: column; gap: 18px; max-width: 1100px; margin: 0 auto; }
.crm-lp-top { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.crm-lp-title { display: flex; flex-direction: column; gap: 2px; }
.crm-lp-title h2 { margin: 0; font-size: 22px; font-weight: 800; color: var(--text-strong); }
.crm-lp-id { font-size: 11.5px; color: var(--muted-2); font-family: ui-monospace, monospace; }
.crm-lp-stepper { display: flex; flex-wrap: wrap; border: 1px solid var(--border); border-radius: 10px; overflow: hidden; background: var(--surface-2); }
.crm-lp-step { flex: 1 1 auto; min-width: 96px; padding: 11px 14px; border: none; border-right: 1px solid var(--border); background: transparent; color: var(--muted); font-size: 13.5px; font-weight: 700; cursor: pointer; transition: background .12s ease, color .12s ease; }
.crm-lp-step:last-child { border-right: none; }
.crm-lp-step:hover:not(:disabled) { background: var(--surface-3, var(--surface)); color: var(--text); }
.crm-lp-step.active { background: var(--brand); color: #fff; }
.crm-lp-step:disabled { cursor: default; opacity: .9; }
.crm-lp-body { display: grid; grid-template-columns: minmax(0, 340px) minmax(0, 1fr); gap: 18px; align-items: start; }
.crm-lp-main { display: flex; flex-direction: column; gap: 14px; }
.crm-lp-card { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 16px; box-shadow: var(--shadow-sm); }
.crm-lp-card-title { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--muted); margin-bottom: 10px; }
.crm-lp-card-title--sep { margin-top: 14px; }
.crm-lp-field { display: flex; align-items: center; gap: 8px; font-size: 14px; color: var(--text); padding: 5px 0; }
.crm-lp-field > span:first-child { width: 18px; text-align: center; flex: 0 0 auto; }
.crm-lp-field a { color: var(--brand); text-decoration: none; }
.crm-lp-field a:hover { text-decoration: underline; }
.crm-lp-chatter { display: flex; flex-direction: column; gap: 12px; background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 16px; box-shadow: var(--shadow-sm); }
@media (max-width: 860px) { .crm-lp-body { grid-template-columns: 1fr; } }

/* ── Ficha del lead v2 — split-screen alta densidad (estilo Odoo clásico) ─── */
.crm-lp2-toolbar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 8px 20px; background: var(--surface-2); border-bottom: 1px solid var(--border); }
.crm-lp2-btn { padding: 7px 14px; font-size: 13px; font-weight: 600; border: 1px solid var(--border); background: var(--surface); color: var(--text); border-radius: 4px; cursor: pointer; transition: background .12s ease, border-color .12s ease; }
.crm-lp2-btn:hover:not(:disabled) { background: var(--surface-3, var(--surface-2)); border-color: var(--brand); }
.crm-lp2-btn--won { background: var(--brand); color: #fff; border-color: var(--brand); }
.crm-lp2-btn--won:hover:not(:disabled) { background: var(--brand-dark, var(--brand)); }
.crm-lp2-btn:disabled { opacity: .5; cursor: default; }

.crm-lp2 { display: flex; align-items: stretch; }
.crm-lp2-left { flex: 1 1 60%; min-width: 0; padding: 20px 26px; border-right: 1px solid var(--border); }
.crm-lp2-right { flex: 1 1 40%; min-width: 0; padding: 16px 20px; background: var(--bg-2, var(--surface-2)); }

.crm-lp2-headrow { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-bottom: 18px; }
.crm-lp2-titlewrap { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.crm-lp2-title { margin: 0; font-size: 26px; font-weight: 800; color: var(--text-strong); line-height: 1.1; }

/* Breadcrumb con chevrons (arriba-derecha) */
.crm-lp2-breadcrumb { display: inline-flex; }
.crm-lp2-step {
  border: none; background: var(--surface-2); color: var(--muted); font-size: 12px; font-weight: 700;
  padding: 8px 14px 8px 22px; cursor: pointer; white-space: nowrap;
  clip-path: polygon(0 0, calc(100% - 11px) 0, 100% 50%, calc(100% - 11px) 100%, 0 100%, 11px 50%);
  margin-left: -10px;
}
.crm-lp2-step:first-child { margin-left: 0; padding-left: 14px; clip-path: polygon(0 0, calc(100% - 11px) 0, 100% 50%, calc(100% - 11px) 100%, 0 100%); }
.crm-lp2-step:hover:not(:disabled):not(.active) { background: var(--surface-3, var(--surface)); color: var(--text); }
.crm-lp2-step.active { background: var(--brand); color: #fff; }
.crm-lp2-step:disabled { cursor: default; }

/* Grid etiqueta-valor en DOS columnas de pares (aprovecha el ancho, con aire) */
.crm-lp2-grid { display: grid; grid-template-columns: 118px minmax(0, 1fr) 118px minmax(0, 1fr); gap: 14px 24px; align-items: baseline; font-size: 13.5px; }
.crm-lp2-lbl { color: var(--muted); font-weight: 600; padding: 1px 0; }
.crm-lp2-val { color: var(--text); padding: 1px 0; min-width: 0; word-break: break-word; }
.crm-lp2-val a { color: var(--brand); text-decoration: none; }
.crm-lp2-val a:hover { text-decoration: underline; }
.crm-lp2-money { font-size: 20px; font-weight: 800; color: var(--text-strong); }
.crm-lp2-empty { color: var(--muted-2); }
.crm-lp2-grid--info { margin-top: 2px; grid-template-columns: 118px minmax(0, 1fr); gap: 12px 20px; }
@media (max-width: 620px) { .crm-lp2-grid { grid-template-columns: 110px minmax(0, 1fr); } }

/* Tabs inferiores izquierda */
.crm-lp2-subtabs { display: flex; border-bottom: 1px solid var(--border); margin-top: 22px; }
.crm-lp2-subtab { padding: 9px 16px; border: none; background: transparent; color: var(--muted); font-size: 13.5px; font-weight: 600; cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px; }
.crm-lp2-subtab:hover { color: var(--text); }
.crm-lp2-subtab.active { color: var(--brand); border-bottom-color: var(--brand); }
.crm-lp2-subtabbody { padding: 14px 0; }
.crm-lp2-notelist { display: flex; flex-direction: column; gap: 10px; }
.crm-lp2-noteitem { border-bottom: 1px solid var(--border-soft, var(--border)); padding-bottom: 8px; }
.crm-lp2-noteitem:last-child { border-bottom: none; }
.crm-lp2-noteitem-head { display: flex; justify-content: space-between; gap: 8px; margin-bottom: 3px; }

/* Chatter derecha */
.crm-lp2-chattertabs { display: flex; gap: 6px; border-bottom: 1px solid var(--border); margin-bottom: 14px; }
.crm-lp2-ctab { padding: 8px 14px; border: none; background: transparent; color: var(--muted); font-size: 13.5px; font-weight: 700; cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px; }
.crm-lp2-ctab:hover { color: var(--text); }
.crm-lp2-ctab.active { color: var(--brand); border-bottom-color: var(--brand); }
.crm-lp2-chatterform { display: flex; flex-direction: column; gap: 8px; margin-bottom: 8px; }
.crm-lp2-tl-title { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); margin: 16px 0 8px; }
.crm-lp2-act { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; padding: 8px 0 8px 10px; border-left: 3px solid var(--border); margin-bottom: 4px; }
.crm-lp2-act.crm-due-overdue { border-left-color: var(--badge-danger-fg); }
.crm-lp2-act.crm-due-today { border-left-color: var(--badge-warn-fg); }
.crm-lp2-act.crm-due-soon { border-left-color: var(--badge-success-fg); }
.crm-lp2-act-main { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1 1 auto; }
.crm-lp2-timeline { display: flex; flex-direction: column; }
.crm-lp2-tl-item { display: flex; gap: 12px; padding: 11px 0; border-bottom: 1px solid var(--border-soft, var(--border)); }
.crm-lp2-tl-item:last-child { border-bottom: none; }
.crm-lp2-tl-dot { width: 9px; height: 9px; border-radius: 50%; flex: 0 0 auto; margin-top: 6px; background: var(--muted-2); }
.crm-tl-move { background: var(--brand); }
.crm-tl-note { background: var(--badge-success-fg); }
.crm-tl-system { background: var(--muted-2); }
.crm-lp2-tl-body { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.crm-lp2-tl-line1 { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.crm-lp2-tl-who { font-weight: 700; color: var(--text-strong); font-size: 13px; }
.crm-lp2-tl-what { font-size: 12.5px; color: var(--muted); }
.crm-lp2-tl-detail { font-size: 13px; color: var(--text); margin-top: 3px; line-height: 1.4; }

@media (max-width: 900px) {
  .crm-lp2 { flex-direction: column; }
  .crm-lp2-left { border-right: none; border-bottom: 1px solid var(--border); flex-basis: auto; }
  .crm-lp2-headrow { flex-direction: column; }
}

/* ── Ficha del lead v2 — fuentes más grandes + modales (etiquetas / actividad) ─ */
.crm-lp2-title { font-size: 28px; }
.crm-lp2-grid { font-size: 15px; }
.crm-lp2-lbl { font-size: 13.5px; }
.crm-lp2-val { font-size: 15px; }
.crm-lp2-money { font-size: 22px; }
.crm-lp2-left .crm-note-text, .crm-lp2-right .crm-note-text { font-size: 14px; }
.crm-lp2-tl-who { font-size: 14.5px; }
.crm-lp2-tl-what { font-size: 13.5px; }
.crm-lp2-tl-detail { font-size: 14px; }
.crm-lp2-tl-title { font-size: 12px; }
.crm-lp2-noteitem-head .crm-note-tag, .crm-lp2-act .crm-note-tag { font-size: 12.5px; }

/* Modal actividad — selector de tipo */
.crm-actmodal-types { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 4px; }
.crm-actmodal-type { padding: 8px 13px; border: 1px solid var(--border); background: var(--surface-2); color: var(--text); border-radius: 6px; font-size: 13px; font-weight: 600; cursor: pointer; }
.crm-actmodal-type:hover { border-color: var(--brand); }
.crm-actmodal-type.active { background: var(--brand); color: #fff; border-color: var(--brand); }

/* Modal etiquetas — catálogo con color */
.crm-tagmodal-list { display: flex; flex-wrap: wrap; gap: 8px; min-height: 20px; }
.crm-tagchip { display: inline-flex; align-items: center; gap: 2px; border: 1.5px solid; border-radius: 999px; padding: 3px 4px 3px 11px; font-size: 13px; font-weight: 600; background: transparent; }
.crm-tagchip.on { box-shadow: 0 0 0 2px rgba(0,0,0,.06) inset; }
.crm-tagchip-lbl { cursor: pointer; }
.crm-tagchip-del { border: none; background: transparent; color: inherit; cursor: pointer; font-size: 15px; line-height: 1; opacity: .55; padding: 0 3px; }
.crm-tagchip-del:hover { opacity: 1; }
.crm-tagmodal-create { display: flex; gap: 8px; align-items: center; }
.crm-tagmodal-create .crm-input { flex: 1 1 auto; }
.crm-tagmodal-color { width: 44px; height: 38px; padding: 2px; border: 1px solid var(--control-border); border-radius: 8px; background: var(--control-bg); cursor: pointer; flex: 0 0 auto; }

/* Vista Actividades — barra de filtros + estado hecho + quién */
.crm-acts-bar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
.crm-act-who { font-size: 12px; color: var(--muted-2); margin-top: 3px; }
.crm-act-done { opacity: .72; }
.crm-act-done.crm-act-item { border-left-color: var(--muted-2); }
.crm-act-done .crm-note-text { text-decoration: line-through; }
.crm-act-group-title:not(.crm-due-overdue):not(.crm-due-today):not(.crm-due-soon) { color: var(--muted); }

/* Constructor — form amigable de condición/regla + drag de fases */
.crm-cond-fields { display: flex; flex-wrap: wrap; gap: 8px 16px; padding: 4px 0 2px; }
.crm-check { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; color: var(--text); cursor: pointer; }
.crm-check input[type="checkbox"] { width: 16px; height: 16px; cursor: pointer; accent-color: var(--brand); }
.crm-fase-card[draggable="true"] { cursor: grab; }
.crm-fase-card[draggable="true"]:active { cursor: grabbing; }

/* ── Kanban más grande, vibrante y aireado (estilo Odoo, colores de marca) ── */
.crm-board { gap: 16px; padding: 0 24px 18px; }
.crm-col {
  flex: 0 0 340px; min-width: 340px;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 14px; padding: 0; box-shadow: none; gap: 0;
  max-height: calc(100vh - 180px);
  transition: box-shadow .12s ease, border-color .12s ease, background .12s ease;
}
.crm-col-head {
  padding: 14px 16px 10px; border-top: 4px solid var(--brand); border-radius: 14px 14px 0 0;
  align-items: flex-start;
  background: linear-gradient(var(--brand-soft-bg, transparent), transparent);
}
.crm-col-name { font-size: 15px; font-weight: 800; letter-spacing: -.01em; }
.crm-col-count { font-size: 12.5px; }
.crm-col-obj { padding: 0 16px; }
.crm-col-body { padding: 12px 14px 16px; gap: 12px; overflow-y: auto; min-height: 60px; }
/* Resaltado al arrastrar sobre la columna */
.crm-col-drop { border-color: var(--brand); box-shadow: 0 0 0 2px var(--brand) inset; background: var(--brand-soft-bg, var(--surface-3)); }
.crm-col-drophint { border: 1.5px dashed var(--border); border-radius: 10px; }

.crm-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 12px; padding: 14px 15px; gap: 10px; box-shadow: var(--shadow-sm);
  cursor: grab; transition: box-shadow .12s ease, transform .12s ease, border-color .12s ease;
}
.crm-card:hover { box-shadow: var(--shadow-md); transform: translateY(-2px); border-color: var(--brand); }
.crm-card:active { cursor: grabbing; }
.crm-card-name { font-size: 15.5px; font-weight: 700; color: var(--text-strong); }
.crm-card-sub { font-size: 12.5px; }

/* Etiquetas (tags) */
.crm-card-tags { display: flex; flex-wrap: wrap; gap: 6px; }
.crm-tag {
  display: inline-flex; align-items: center; font-size: 11px; font-weight: 600;
  background: var(--badge-info-bg); color: var(--badge-info-fg);
  border-radius: 6px; padding: 2px 8px;
}
.crm-tag-add { background: transparent; color: var(--muted); border: 1px dashed var(--border); cursor: pointer; }
.crm-tag-add:hover { color: var(--brand); border-color: var(--brand); }

.crm-card-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-top: 2px; }
/* Estrellas de prioridad (0-3) */
.crm-card-stars { display: inline-flex; gap: 1px; }
.crm-star { font-size: 16px; line-height: 1; color: var(--border); cursor: pointer; transition: color .1s ease, transform .1s ease; }
.crm-star:hover { transform: scale(1.2); }
.crm-star.on { color: #f5b301; }
.crm-card-activity {
  display: inline-flex; align-items: center; gap: 4px; font-size: 11px; font-weight: 700;
  border-radius: 999px; padding: 3px 10px; white-space: nowrap;
}
.crm-card-activity.crm-due-overdue { background: var(--badge-danger-bg); color: var(--badge-danger-fg); }
.crm-card-activity.crm-due-today   { background: var(--badge-warn-bg); color: var(--badge-warn-fg); }
.crm-card-activity.crm-due-soon    { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.crm-card-avatar {
  margin-left: auto; flex: 0 0 auto; width: 28px; height: 28px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center; font-size: 13px; font-weight: 800;
  background: var(--brand); color: #fff;
}

/* ── Vista Lista ─────────────────────────────────────────────────────────── */
.crm-list-wrap { margin: 0 24px; border: 1px solid var(--border); border-radius: 12px; overflow: hidden; background: var(--surface); }
.crm-list-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.crm-list-table thead th {
  text-align: left; padding: 11px 14px; font-size: 12px; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: .03em; background: var(--surface-2); border-bottom: 1px solid var(--border);
}
.crm-list-table td { padding: 11px 14px; border-bottom: 1px solid var(--border-soft, var(--border)); color: var(--text); }
.crm-list-row { cursor: pointer; transition: background .1s ease; }
.crm-list-row:hover { background: var(--surface-2); }
.crm-list-row:last-child td { border-bottom: none; }
.crm-list-name { font-weight: 600; color: var(--text-strong); }
.crm-pill {
  display: inline-flex; align-items: center; font-size: 12px; font-weight: 600;
  background: var(--surface-2); color: var(--text); border: 1px solid var(--border);
  border-radius: 999px; padding: 2px 10px;
}
.crm-estado-activo { background: var(--badge-success-bg); color: var(--badge-success-fg); border-color: transparent; }
.crm-estado-pausado { background: var(--badge-warn-bg); color: var(--badge-warn-fg); border-color: transparent; }
.crm-estado-completado { background: var(--badge-info-bg); color: var(--badge-info-fg); border-color: transparent; }

/* ── Vista Actividades ───────────────────────────────────────────────────── */
.crm-acts { display: flex; flex-direction: column; gap: 18px; padding: 0 24px; max-width: 900px; }
.crm-act-group { display: flex; flex-direction: column; gap: 8px; }
.crm-act-group-title { font-size: 13px; font-weight: 700; padding: 4px 2px; }
.crm-act-group-title.crm-due-overdue { color: var(--badge-danger-fg); }
.crm-act-group-title.crm-due-today   { color: var(--badge-warn-fg); }
.crm-act-group-title.crm-due-soon    { color: var(--badge-success-fg); }
.crm-act-item {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
  background: var(--surface); border: 1px solid var(--border); border-left-width: 3px;
  border-radius: 10px; padding: 11px 14px;
}
.crm-act-item.crm-due-overdue { border-left-color: var(--badge-danger-fg); }
.crm-act-item.crm-due-today   { border-left-color: var(--badge-warn-fg); }
.crm-act-item.crm-due-soon    { border-left-color: var(--badge-success-fg); }
.crm-act-main { display: flex; flex-direction: column; gap: 5px; cursor: pointer; min-width: 0; flex: 1 1 auto; }
.crm-act-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* ── Vista Calendario ────────────────────────────────────────────────────── */
.crm-cal { padding: 0 24px; }
.crm-cal-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }
.crm-cal-title { font-size: 17px; font-weight: 700; color: var(--text-strong); min-width: 160px; }
.crm-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.crm-cal-dow { text-align: center; font-size: 11px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; padding: 4px 0; }
.crm-cal-cell {
  min-height: 108px; background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  padding: 6px; display: flex; flex-direction: column; gap: 4px;
}
.crm-cal-empty { background: transparent; border-color: transparent; }
.crm-cal-today { border-color: var(--brand); box-shadow: inset 0 0 0 1px var(--brand); }
.crm-cal-daynum { font-size: 12px; font-weight: 700; color: var(--muted); align-self: flex-end; }
.crm-cal-today .crm-cal-daynum { color: var(--brand); }
.crm-cal-events { display: flex; flex-direction: column; gap: 3px; overflow: hidden; }
.crm-cal-ev {
  font-size: 11px; font-weight: 600; border-radius: 6px; padding: 2px 6px; cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.crm-cal-ev.crm-due-overdue { background: var(--badge-danger-bg); color: var(--badge-danger-fg); }
.crm-cal-ev.crm-due-today   { background: var(--badge-warn-bg); color: var(--badge-warn-fg); }
.crm-cal-ev.crm-due-soon    { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.crm-cal-ev.crm-cal-done    { background: var(--surface-2); color: var(--muted-2); text-decoration: line-through; }

@media (max-width: 720px) {
  .crm-cal-cell { min-height: 74px; }
  .crm-cpanel { padding: 10px 14px; }
  .crm-board, .crm-acts, .crm-cal, .crm-list-wrap { padding-left: 14px; padding-right: 14px; }
  .crm-list-wrap { margin: 0 14px; }
}

/* ── CRM · Entrada del flujo (con reglas de inscripción) ─────────────────── */
.crm-flow-entry-card { background: var(--brand-soft-bg, var(--surface-2)); border: 1px solid var(--border); border-radius: 14px; padding: 14px 16px; box-shadow: var(--shadow-sm); }
.crm-flow-entry-ico { font-size: 16px; color: var(--brand); }

/* ── CRM · Plantillas / Import / Export ──────────────────────────────────── */
.crm-modal-wide { max-width: 640px; }
.crm-template-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 10px; padding: 16px 18px; }
.crm-template-card {
  display: flex; flex-direction: column; gap: 6px; background: var(--surface-2);
  border: 1px solid var(--border); border-radius: 12px; padding: 14px; cursor: pointer;
  transition: border-color .15s ease, background .15s ease;
}
.crm-template-card:hover { border-color: var(--brand); background: var(--brand-soft-bg, var(--surface)); }
.crm-template-icon { font-size: 22px; }
.crm-template-card strong { color: var(--text-strong); font-size: 14px; }
.crm-template-resumen { color: var(--muted); font-size: 12px; line-height: 1.4; }
.crm-textarea-lg { min-height: 220px; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px; }

/* ═══════════════════════════════════════════════════════════════════════════
   Demos multiagente — panel visual (Centro de Control → Demos)
   ═══════════════════════════════════════════════════════════════════════════ */

/* Hero: Smartacus como agente orquestador */
.demos-hero {
  display: flex; gap: 18px; align-items: flex-start;
  padding: 22px 24px; margin-bottom: 22px; border-radius: 18px;
  background:
    radial-gradient(1200px 200px at 0% 0%, var(--brand-soft-bg), transparent 60%),
    linear-gradient(135deg, var(--surface-2), var(--surface));
  border: 1px solid var(--border-soft);
  position: relative; overflow: hidden;
}
.demos-hero::after {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 5px;
  background: linear-gradient(180deg, var(--brand), #8b5cf6 45%, #ec4899);
}
.demos-hero__badge {
  flex: 0 0 66px; width: 66px; height: 66px; border-radius: 18px;
  display: grid; place-items: center; font-size: 36px; line-height: 1;
  background: var(--surface); box-shadow: var(--shadow-sm);
  border: 1px solid var(--border-soft);
}
.demos-hero__title { margin: 0; font-size: 20px; font-weight: 750; color: var(--text-strong); letter-spacing: -.01em; }
.demos-hero__sub { margin: 6px 0 0; font-size: 13px; line-height: 1.55; color: var(--muted); max-width: 68ch; }
.demos-hero__tags { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 12px; }
.demos-hero__tag {
  font-size: 11.5px; font-weight: 600; padding: 5px 11px; border-radius: 999px;
  background: var(--surface); border: 1px solid var(--border-soft); color: var(--text);
}

/* Encabezado de la lista */
.demos-section-label {
  display: flex; align-items: center; gap: 10px; margin: 4px 0 14px;
  font-size: 13px; font-weight: 700; color: var(--text-strong); text-transform: uppercase; letter-spacing: .04em;
}
.demos-count {
  font-size: 12px; font-weight: 700; color: var(--brand);
  background: var(--brand-soft-bg); border-radius: 999px; padding: 2px 10px; letter-spacing: 0;
}

/* Grid de tarjetas */
.demos-grid {
  display: grid; gap: 16px;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}

/* Tarjeta de demo */
.demo-card {
  --demo-accent: var(--brand);
  --demo-accent-soft: var(--brand-soft-bg);
  position: relative; display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 16px; overflow: hidden;
  transition: transform .16s ease, box-shadow .16s ease, border-color .16s ease;
}
.demo-card::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 4px;
  background: var(--demo-accent);
}
.demo-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lg);
  border-color: var(--demo-accent);
}
.demo-card--concesionarios { --demo-accent: #3b82f6; --demo-accent-soft: rgba(59,130,246,.13); }
.demo-card--ventas         { --demo-accent: #8b5cf6; --demo-accent-soft: rgba(139,92,246,.13); }
.demo-card--eventos        { --demo-accent: #ec4899; --demo-accent-soft: rgba(236,72,153,.13); }
.demo-card--inactive { opacity: .6; filter: saturate(.6); }

.demo-card__head { display: flex; align-items: flex-start; justify-content: space-between; padding: 16px 16px 0; }
.demo-card__icon {
  width: 54px; height: 54px; border-radius: 14px; font-size: 28px;
  display: grid; place-items: center; background: var(--demo-accent-soft);
}
.demo-card__reorder { display: flex; flex-direction: column; gap: 3px; }
.demo-reorder-btn {
  width: 26px; height: 20px; border-radius: 6px; cursor: pointer; font-size: 11px; line-height: 1;
  display: grid; place-items: center;
  border: 1px solid var(--control-border); background: var(--control-bg); color: var(--muted);
  transition: background .12s, color .12s;
}
.demo-reorder-btn:hover { background: var(--control-bg-hover); color: var(--text); }

.demo-card__body { padding: 12px 16px 0; flex: 1 1 auto; }
.demo-card__title { margin: 0; font-size: 16px; font-weight: 700; color: var(--text-strong); }
.demo-card__agent { margin-top: 3px; font-size: 12px; color: var(--muted); }
.demo-card__meta { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 13px; }
.demo-chip {
  display: inline-flex; align-items: center; gap: 4px; max-width: 100%;
  font-size: 11px; font-weight: 600; padding: 3px 9px; border-radius: 999px;
  border: 1px solid var(--border-soft); background: var(--surface-2); color: var(--text);
}
.demo-chip--model {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.demo-card__footer {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 13px 16px; margin-top: 14px; border-top: 1px solid var(--border-soft);
}
.demo-status { display: inline-flex; align-items: center; gap: 7px; font-size: 12px; font-weight: 600; }
.demo-status::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%; background: currentColor;
  box-shadow: 0 0 0 3px var(--demo-accent-soft);
}
.demo-status--on { color: var(--badge-success-fg); }
.demo-status--off { color: var(--muted); }
.demo-status--off::before { box-shadow: none; }

.demo-card__actions { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.demo-act {
  font-size: 12px; font-weight: 600; padding: 5px 10px; border-radius: 8px; cursor: pointer;
  border: 1px solid var(--control-border); background: var(--control-bg); color: var(--text);
  transition: background .12s, border-color .12s, color .12s;
}
.demo-act:hover { background: var(--control-bg-hover); }
.demo-act--danger:hover { border-color: var(--badge-danger-fg); color: var(--badge-danger-fg); background: var(--badge-danger-bg); }

/* ==========================================================================
   ACCESIBILIDAD — safety net global de movimiento reducido
   Respeta prefers-reduced-motion:reduce para TODA animacion/transicion del panel
   (fondos de clima, modales, drawers, pulsos, ripple, shimmer, toasts…), presentes
   y futuras — no hace falta un bloque por animacion. Se usa 0.01ms (NO 0 / NO
   animation:none) a proposito: la animacion aun "corre" y dispara animationend/
   transitionend, asi el JS que depende de esos eventos (autocierre de toasts, fin de
   modal) no se cuelga; ademas evita que un fill:both quede congelado en su estado
   inicial (p.ej. toast-in arranca invisible). iteration-count:1 corta los loops
   infinitos. Excepcion futura: una animacion que SI comunique estado se reactiva con
   una regla mas especifica dentro de otra query reduced-motion.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }
}

/* ============================================================
   IDENTIDAD VISUAL — Centro de Control y Perfil → Apariencia
   ------------------------------------------------------------
   Todo por tokens: estas reglas tienen que seguir siendo legibles con CUALQUIER
   tema activo, incluido el que el usuario acabe de elegir en esta misma pantalla.
   ============================================================ */
.idv-saved {
  margin-bottom: 12px;
  padding: 9px 14px;
  border-radius: 10px;
  background: var(--badge-success-bg);
  color: var(--badge-success-fg);
  font-size: 0.85rem;
  font-weight: 600;
}

/* auto-fit (no auto-fill): las tarjetas presentes se estiran para llenar la fila.
   Con auto-fill quedarían columnas fantasma y la rejilla se vería descolgada. */
.idv-theme-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
  margin-top: 12px;
}

.idv-theme {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border: 1px solid var(--control-border);
  border-radius: 12px;
  background: var(--control-bg);
  color: var(--text);
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  text-align: left;
  transition: background 0.15s, border-color 0.15s;
}
.idv-theme:hover:not(:disabled) { background: var(--control-bg-hover); }
.idv-theme:disabled { opacity: 0.5; cursor: not-allowed; }
/* El seleccionado se marca con borde + halo de marca, no solo con color de fondo:
   con el tema Grafito (monocromo) un fondo tintado no se distinguiría. */
.idv-theme.is-active {
  border-color: var(--brand);
  box-shadow: 0 0 0 2px rgba(var(--brand-rgb), 0.25);
}

.idv-swatch {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  flex-shrink: 0;
  border: 1px solid rgba(255, 255, 255, 0.18);
}
/* Los colores de las muestras son literales a propósito: representan el acento
   de CADA preset, así que no pueden salir de var(--brand) — sería el color activo
   repetido seis veces. Deben seguir a backend/sql/138_temas_base.sql. */
.idv-swatch--factory        { background: linear-gradient(135deg, #3b82f6, #2563eb); }
.idv-swatch--theme-indigo   { background: linear-gradient(135deg, #9095f0, #4338ca); }
.idv-swatch--theme-esmeralda{ background: linear-gradient(135deg, #43c99a, #047857); }
.idv-swatch--theme-ambar    { background: linear-gradient(135deg, #f0b45f, #b45309); }
.idv-swatch--theme-oceano   { background: linear-gradient(135deg, #58b6d4, #0e7490); }
.idv-swatch--theme-grafito  { background: linear-gradient(135deg, #a1a1aa, #3f3f46); }

.idv-theme-name { line-height: 1.2; }

.idv-scale-row {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: 10px;
}

/* Vista previa del banner de inicio: reusa .home-welcome-title/-sub para que lo
   que se ve aqui sea literalmente lo que se vera en la portada. Encuadrada para
   que nadie la confunda con el propio saludo del panel. */
/* Vista previa de la imagen del banner. Reutiliza `.home-banner` tal cual —mismo
   recorte, mismo velo, mismo alto— para que lo que se ve aquí sea exactamente lo
   que quedará publicado; una maqueta aparte se desincroniza en cuanto cambie el
   banner de verdad. Solo se le pone margen. */
.idv-banner-live { margin-top: 14px; }

.idv-banner-preview {
  position: relative;
  margin-top: 14px;
  padding: 18px 18px 14px;
  border: 1px dashed var(--control-border);
  border-radius: 12px;
  background: var(--surface-2);
}
.idv-banner-preview-tag {
  position: absolute;
  top: -9px;
  left: 14px;
  padding: 1px 8px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--muted-2);
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.idv-banner-preview .home-welcome-title { margin: 0; }
.idv-banner-preview .home-welcome-sub { margin: 4px 0 0; }

.idv-name-row {
  display: flex;
  gap: 8px;
  align-items: center;
  max-width: 460px;
}

/* ============================================================
   BARRA GLOBAL — marca y variante tematizada
   ------------------------------------------------------------
   `.ph-brand` es el bloque izquierdo cuando NO hay módulo activo (inicio): cohete
   + nombre del panel. `.ph--themed` lo aplica `components/global_header.rs` cuando
   el owner activa «Cabecera con el color de marca» en Identidad Visual.

   Va al FINAL del archivo a propósito: estas reglas y las del bloque de tema claro
   tienen la MISMA especificidad, así que quien gana es el último declarado. Si
   suben por encima, el switch deja de verse en claro y el fallo parece intermitente.

   El color sale de --brand-dark, que por convención del sistema de tokens es
   SIEMPRE la variante sobre la que se apoya texto blanco — por eso todo lo de
   dentro pasa a #fff sin comprobar el tema.
   ============================================================ */
.ph-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.ph--themed {
  background: var(--brand-dark);
  border-bottom-color: color-mix(in srgb, var(--brand-dark) 70%, black 20%);
}
.ph--themed .ph-title,
.ph--themed .ph-user-name,
.ph--themed .app-title,
.ph--themed .ph-icon { color: #fff; }
.ph--themed .ph-meta,
.ph--themed .ph-user-role { color: rgba(255, 255, 255, 0.75); }
.ph--themed .ph-back,
.ph--themed .ph-menu-toggle,
.ph--themed .ph-theme-btn,
.ph--themed .ph-logout,
.ph--themed .ph-user-chip {
  background: rgba(255, 255, 255, 0.14);
  border-color: rgba(255, 255, 255, 0.22);
  color: #fff;
}
.ph--themed .ph-divider { background: rgba(255, 255, 255, 0.28); }
.ph--themed .ph-back:hover,
.ph--themed .ph-menu-toggle:hover,
.ph--themed .ph-theme-btn:hover,
.ph--themed .ph-logout:hover,
.ph--themed .ph-user-chip:hover { background: rgba(255, 255, 255, 0.22); }


/* ============================================================
   NOTIFICACIONES — historico, filtros y modal de envio
   ------------------------------------------------------------
   Portado de sestia junto con pages/notifications.rs. Reusa la toolbar
   canonica (.tickets-toolbar + .contacts-search-form) que este panel ya
   tenia, asi que aqui solo van las piezas propias del modulo.
   ============================================================ */
/* Fila clickeable → abre el detalle (se elimino la accion "Ver"). */
.tk-row-click { cursor: pointer; }

.tk-row-click:hover > td { background: rgba(255, 255, 255, 0.03); }

/* El backdrop es hijo de la card (que es clicable): no debe heredar el cursor pointer
   ni pintarlo por toda la pantalla mientras el dropdown está abierto. */
.interno-card .lc-filters-backdrop { cursor: default; }

/* Popover de filtros (empaquetados tras el embudo) */
.lc-filters-backdrop {
  position: fixed; inset: 0; z-index: 40;
  background: transparent;
}

/* "Ver más (+N)": carga la siguiente tanda sin salir del dropdown. */
.ph-notif-more {
  display: block;
  width: 100%;
  appearance: none;
  border: none;
  border-top: 1px solid var(--border-soft);
  background: transparent;
  color: var(--brand);
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  padding: 10px 14px;
  transition: background 0.12s ease;
}

.ph-notif-more:hover { background: var(--control-bg-hover); }

.ph-notif-more:disabled { color: var(--muted); cursor: default; }

/* ── Página de notificaciones ── */
/* .notif-tabs / .notif-tab: SEGMENTED estándar, estilo en el bloque canónico
   (buscar "SEGMENTED CONTROL ESTÁNDAR"). Aquí solo el contenido del módulo. */

/* El módulo respira: mismo ancho de columna en las 3 pestañas y separado de los
   bordes de la pantalla (antes las filas quedaban pegadas a la izquierda). */
.notif-main {
  width: 100%;
  max-width: 1100px;
  margin: 0 auto;
  padding: 20px 24px 32px;
}

.notif-main .notif-tabs { margin: 0 0 18px; }

/* ── Historial de enviados ──
   Filtros y paginación usan los bloques canónicos: TOOLBAR ESTÁNDAR
   (.tickets-toolbar + .contacts-search-form + embudo) y PAGINACIÓN ESTÁNDAR
   (.ui-pager). Aquí solo queda el scroll de la tabla. */
.notif-table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* Móvil. Estas dos reglas habían perdido su `@media`: solo sobrevivía la llave de
   cierre, suelta al final del bloque. Un `}` de más lo ignora el parser, así que
   no rompía la hoja — pero dejaba el padding de móvil aplicándose TAMBIÉN en
   escritorio, pisando el `.notif-main` de arriba (20px 24px 32px). Por eso el
   módulo de notificaciones se veía más apretado que el resto. */
@media (max-width: 640px) {
  .notif-table-scroll .notif-table { min-width: 520px; }
  .notif-main { padding: 14px 12px 24px; }
}

/* ── Compositor (modal) ── */
/* El ancho lo pone .notif-main; las pestañas ya no fijan el suyo (antes la lista
   quedaba anclada a la izquierda con 720px sueltos). */
.notif-compose-card { width: min(640px, 94vw); }

/* Detalle de una enviada: modal de solo lectura con sus destinatarios. */
.notif-detail-card { width: min(820px, 94vw); }

.notif-detail-card .notif-table-scroll { max-height: 60vh; overflow-y: auto; padding: 0 18px; }

.notif-compose-card .notif-compose { padding: 4px 18px 0; max-height: 66vh; overflow-y: auto; }

/* ============================================================
   MODULO FLUJOS DE TRABAJO (.flx-*)
   ------------------------------------------------------------
   Portado del repo sestia junto con pages/flujos.rs. Todo el color va por
   tokens, asi que sigue al tema activo sin tocar una regla.
   ============================================================ */
/* ═══════════════════════════════════════════════════════════════════════════
   FLUJOS DE TRABAJO — sistema propio `flx-*` (tokens, claro + oscuro).
   Flujo de trabajo del constructor: (izq) lista de flujos configurados →
   (der) ① disparadores → ② embudo de fases (drag & drop) → ③ revisión.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Layout de 2 columnas: sidebar de flujos + canvas del flujo seleccionado. */
.flx-layout {
  display: grid;
  grid-template-columns: 300px minmax(0, 1fr);
  gap: 18px;
  align-items: start;
}

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

/* ── Sidebar: lista de flujos configurados ─────────────────────────────────── */
/* El relleno VERTICAL es el mismo que el de las tarjetas de la derecha
   (`.flx-flow-header` / `.flx-section`, 16px): las dos columnas empiezan a la
   misma altura. Con 14px el título de la izquierda salía 2px más arriba que el
   de la derecha y las dos columnas se leían descuadradas.
   El horizontal sí es menor: la columna mide 300px y 18px por lado le comen
   demasiado ancho a los nombres de flujo. */
.flx-sidebar {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 16px 14px;
  position: sticky;
  top: 14px;
  box-shadow: var(--shadow-sm);
}

.flx-sidebar-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 12px;
}

.flx-sidebar-title {
  font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted-2);
}

.flx-flow-list { display: flex; flex-direction: column; gap: 8px; }

.flx-flow-card {
  display: flex; flex-direction: column; gap: 6px;
  width: 100%; text-align: left; cursor: pointer;
  background: var(--surface-2); border: 1px solid var(--border);
  border-left: 3px solid transparent;
  border-radius: 12px; padding: 11px 13px;
  transition: border-color .15s ease, background .15s ease, transform .05s ease;
}

.flx-flow-card:hover { background: var(--control-bg-hover); border-color: var(--border-soft); }

.flx-flow-card:active { transform: translateY(1px); }

.flx-flow-card.active {
  border-color: var(--brand); border-left-color: var(--brand);
  background: var(--brand-soft-bg, var(--surface-2));
}

.flx-flow-card-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; }

.flx-flow-card-name { font-size: 14px; font-weight: 600; color: var(--text-strong); line-height: 1.25; }

.flx-flow-card-meta { font-size: 11.5px; color: var(--muted); }

.flx-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; background: var(--muted-2); }

.flx-dot.on { background: var(--badge-success-fg, #10b981); box-shadow: 0 0 0 3px var(--badge-success-bg); }

/* ── Canvas del flujo ──────────────────────────────────────────────────────── */
.flx-canvas { display: flex; flex-direction: column; gap: 16px; min-width: 0; }

.flx-flow-header {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 14px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 16px; padding: 16px 18px; box-shadow: var(--shadow-sm);
}

.flx-flow-title-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

.flx-flow-title { font-size: 18px; font-weight: 700; color: var(--text-strong); margin: 0; }

.flx-flow-obj { font-size: 13px; color: var(--muted); margin: 6px 0 0; line-height: 1.45; max-width: 60ch; }

.flx-flow-header-actions { display: inline-flex; gap: 6px; flex: 0 0 auto; }

.flx-status-badge {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em;
  padding: 3px 9px; border-radius: 999px;
}

.flx-status-badge.on { background: var(--badge-success-bg); color: var(--badge-success-fg); }

.flx-status-badge.off { background: var(--badge-neutral-bg); color: var(--badge-neutral-fg); }

/* Botones del canvas */
.flx-btn {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--control-bg); color: var(--text);
  border: 1px solid var(--control-border); border-radius: 9px;
  padding: 7px 12px; font-size: 13px; cursor: pointer;
  transition: background .12s ease, border-color .12s ease;
}

.flx-btn:hover { background: var(--control-bg-hover); }

.flx-btn-primary { background: var(--brand); border-color: var(--brand); color: #fff; }

.flx-btn-primary:hover { background: var(--brand-dark, var(--brand)); }

.flx-btn-danger { color: var(--danger, #ef4444); border-color: var(--control-border); }

.flx-btn-danger:hover { background: var(--badge-danger-bg); border-color: var(--badge-danger-fg); }

.flx-btn-add {
  background: transparent; border: 1px dashed var(--brand); color: var(--brand);
  border-radius: 9px; padding: 6px 12px; font-size: 12.5px; font-weight: 600; cursor: pointer;
}

.flx-btn-add:hover { background: var(--brand-soft-bg, var(--surface-2)); }

.flx-icon-btn {
  background: var(--control-bg); border: 1px solid var(--control-border); border-radius: 8px;
  width: 30px; height: 30px; color: var(--text); cursor: pointer; font-size: 14px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center;
}

.flx-icon-btn:hover:not(:disabled) { background: var(--control-bg-hover); }

.flx-icon-btn:disabled { opacity: .35; cursor: not-allowed; }

/* ── Barra de etapas (①→②→③) ──────────────────────────────────────────────── */
.flx-stagebar { display: flex; align-items: center; gap: 6px; padding: 2px 2px 0; flex-wrap: wrap; }

.flx-stagebar-item {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 12.5px; color: var(--muted); font-weight: 600;
  padding: 5px 12px; border-radius: 999px; background: var(--surface-2);
  border: 1px solid var(--border);
}

.flx-stagebar-item .flx-stage-badge {
  width: 20px; height: 20px; border-radius: 50%; display: inline-flex;
  align-items: center; justify-content: center; font-size: 11px; font-weight: 700;
  background: var(--control-bg); color: var(--muted-2);
}

.flx-stagebar-item.done { color: var(--brand); border-color: var(--brand); }

.flx-stagebar-item.done .flx-stage-badge { background: var(--brand); color: #fff; }

.flx-stagebar-arrow { color: var(--muted-2); font-size: 14px; }

/* ── Secciones del canvas ──────────────────────────────────────────────────── */
.flx-section {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 16px; padding: 16px 18px; box-shadow: var(--shadow-sm);
}

.flx-section-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-bottom: 12px;
}

.flx-section-title {
  display: flex; align-items: center; gap: 9px;
  font-size: 14px; font-weight: 700; color: var(--text-strong);
}

.flx-section-title .flx-num {
  width: 22px; height: 22px; border-radius: 7px; display: inline-flex;
  align-items: center; justify-content: center; font-size: 12px; font-weight: 700;
  background: var(--brand-soft-bg, var(--surface-2)); color: var(--brand-soft-fg, var(--brand));
}

.flx-section-hint { font-size: 12px; color: var(--muted-2); margin: -6px 0 12px; }

/* ── Chips (disparadores / condiciones) ────────────────────────────────────── */
.flx-chips { display: flex; flex-wrap: wrap; gap: 7px; }

.flx-chip {
  display: inline-flex; align-items: center; gap: 7px;
  background: var(--badge-info-bg); color: var(--badge-info-fg);
  border-radius: 999px; padding: 4px 11px; font-size: 12.5px; font-weight: 500;
}

.flx-chip.purple { background: var(--badge-purple-bg); color: var(--badge-purple-fg); }

.flx-chip-x {
  background: transparent; border: none; color: inherit; cursor: pointer;
  font-size: 15px; line-height: 1; opacity: .6; padding: 0;
}

.flx-chip-x:hover { opacity: 1; }

.flx-empty { font-size: 12.5px; color: var(--muted-2); font-style: italic; }

/* ── Embudo de fases (drag & drop) ─────────────────────────────────────────── */
.flx-funnel { display: flex; flex-direction: column; align-items: center; gap: 0; }

.flx-stage {
  width: 100%;
  display: flex; align-items: stretch; gap: 0;
  transition: transform .08s ease, opacity .12s ease;
}

.flx-stage.dragging { opacity: .45; }

.flx-stage.over .flx-stage-body { border-color: var(--brand); box-shadow: 0 0 0 2px var(--brand-soft-bg, var(--surface-2)) inset; }

/* Riel numerado + conector vertical (metáfora de embudo). */
.flx-stage-rail { display: flex; flex-direction: column; align-items: center; flex: 0 0 44px; }

.flx-stage-num {
  width: 30px; height: 30px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 13px; font-weight: 700; flex: 0 0 auto;
  background: var(--brand); color: #fff; box-shadow: 0 0 0 4px var(--brand-soft-bg, var(--surface-2));
}

.flx-stage-line { width: 2px; flex: 1 1 auto; min-height: 18px; background: var(--border); margin: 4px 0; }

.flx-stage.terminal .flx-stage-num { background: var(--muted-2); }

.flx-stage-body {
  flex: 1 1 auto; min-width: 0;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 14px; padding: 13px 15px; margin-bottom: 14px;
  transition: border-color .12s ease, box-shadow .12s ease;
}

.flx-stage-head { display: flex; align-items: center; gap: 9px; }

.flx-drag-handle {
  cursor: grab; color: var(--muted-2); font-size: 15px; user-select: none;
  padding: 2px 4px; border-radius: 6px; flex: 0 0 auto;
}

.flx-drag-handle:hover { color: var(--text); background: var(--control-bg); }

.flx-drag-handle:active { cursor: grabbing; }

.flx-stage-name { font-size: 14.5px; font-weight: 600; color: var(--text-strong); flex: 1 1 auto; min-width: 0; }

.flx-stage-tags { display: inline-flex; gap: 5px; flex-wrap: wrap; }

.flx-tag {
  font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .02em;
  padding: 2px 7px; border-radius: 6px; background: var(--badge-neutral-bg); color: var(--badge-neutral-fg);
}

.flx-tag.mode { background: var(--badge-info-bg); color: var(--badge-info-fg); }

.flx-tag.warn { background: var(--badge-warn-bg); color: var(--badge-warn-fg); }

/* Fase que pertenece a una RAMA: sin esta etiqueta, en la lista no hay forma de saber que
   esa fase solo la recorre parte de los contactos. */
.flx-tag.rama { background: var(--badge-purple-bg); color: var(--badge-purple-fg); }

.flx-stage-actions { display: inline-flex; gap: 4px; flex: 0 0 auto; }

/* ── Bifurcación: ramas del flujo ──
   Va sobre la lista de fases porque decide QUÉ fases recorre cada contacto. */
/* Rejilla de canales del flujo (paso «Activación» del wizard). Es de ESTE módulo: la
   casilla en sí es la canónica `.kn-check`; esto solo la coloca en columnas para que 8
   canales no salgan en una lista de 8 líneas. */
.flx-canales-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 4px 12px;
}

.flx-ramas {
  margin: 0 0 14px;
  padding: 12px;
  border: 1px dashed var(--border);
  border-radius: 12px;
  background: var(--surface-2);
}

.flx-ramas-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 8px; }

.flx-ramas-title { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 700; color: var(--text-strong); }

.flx-rama-list { display: flex; flex-direction: column; gap: 8px; }

.flx-rama-card {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 4px 10px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
}

/* Rama desactivada: el agente no puede elegirla. Se atenúa en vez de ocultarse — sigue
   siendo configuración vigente y sus fases siguen ahí. */
.flx-rama-card.is-off { opacity: .6; border-style: dashed; }

.flx-rama-main { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; min-width: 0; }

.flx-rama-name { font-size: 13.5px; font-weight: 600; color: var(--text-strong); }

.flx-rama-key {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px; color: var(--muted);
  background: var(--control-bg); border-radius: 6px; padding: 1px 6px;
}

/* El criterio es lo único que lee el agente para elegir: se muestra completo, no truncado. */
.flx-rama-crit { grid-column: 1 / -1; margin: 0; font-size: 12.5px; color: var(--muted); line-height: 1.45; }

/* Herramientas de la fase (paso «Herramientas» del asistente). Sugeridas = chips
   simples; bloqueadas = chip + motivo editable, que es documentación para el equipo
   y nunca viaja al prompt del agente. */
.flx-tool-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }

.flx-tool-chip {
  display: inline-flex; align-items: center; gap: 6px; padding: 4px 8px;
  border-radius: 14px; font-size: 12px; font-family: monospace;
  background: var(--badge-info-bg); color: var(--badge-info-fg);
}

.flx-tool-chip-x {
  border: 0; background: transparent; color: inherit; cursor: pointer;
  font-size: 12px; line-height: 1; padding: 0;
}

.flx-tool-blk-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 8px; }

.flx-tool-blk-row { display: flex; align-items: center; gap: 8px; }

.flx-tool-blk-row .flx-tool-chip { background: var(--badge-danger-bg); color: var(--badge-danger-fg); }

.flx-tool-blk-row .form-input { flex: 1; min-width: 0; font-size: 12px; }

/* Tool configurada en la fase que ya no está activa en Centro de Control: el motor la
   ignora, así que se marca apagada en vez de fingir que sigue en juego. */
.flx-tool-chip.is-off {
  background: var(--badge-neutral-bg); color: var(--muted-2);
  text-decoration: line-through; opacity: .85;
}

.flx-tool-error { font-size: 12px; color: var(--badge-danger-fg); }

.flx-stage-obj { font-size: 12.5px; color: var(--muted); margin: 8px 0 0; line-height: 1.4; }

.flx-stage-rules {
  font-size: 12px; color: var(--muted-2); margin: 8px 0 0; padding-left: 14px;
  display: flex; flex-direction: column; gap: 3px;
}

.flx-stage-rules li { list-style: disc; }

.flx-stage-cond { margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--border); }

.flx-stage-cond-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .03em; color: var(--muted-2); margin-bottom: 6px; }

.flx-add-stage {
  width: 100%; background: transparent; border: 1.5px dashed var(--brand); color: var(--brand);
  border-radius: 14px; padding: 14px; font-size: 13px; font-weight: 600; cursor: pointer;
  transition: background .12s ease;
}

.flx-add-stage:hover { background: var(--brand-soft-bg, var(--surface-2)); }

/* ── Revisión de cambios ───────────────────────────────────────────────────── */
.flx-review-grid { display: flex; flex-direction: column; gap: 9px; }

.flx-check {
  display: flex; align-items: center; gap: 10px;
  font-size: 13px; color: var(--text); padding: 9px 12px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 10px;
}

.flx-check-ico { width: 20px; height: 20px; flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; font-size: 13px; border-radius: 50%; }

.flx-check.ok .flx-check-ico { background: var(--badge-success-bg); color: var(--badge-success-fg); }

.flx-check.no .flx-check-ico { background: var(--badge-danger-bg); color: var(--badge-danger-fg); }

.flx-check.warn .flx-check-ico { background: var(--badge-warn-bg); color: var(--badge-warn-fg); }

.flx-review-actions { display: flex; align-items: center; gap: 10px; margin-top: 14px; flex-wrap: wrap; }

.flx-review-note { font-size: 12px; color: var(--muted-2); }

/* ── Estimador de tokens de contexto (revisión del constructor) ────────────── */
.flx-token-card {
  margin-top: 14px; padding: 14px 16px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 12px;
}

.flx-token-head { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600;
  color: var(--text-strong); margin-bottom: 12px; }

.flx-token-ico { font-size: 15px; }

.flx-token-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }

.flx-token-item { text-align: center; padding: 10px 6px; border-radius: 10px;
  background: var(--surface); border: 1px solid var(--border-soft); }

.flx-token-item--total { background: var(--brand-soft-bg); border-color: var(--brand); }

.flx-token-val { font-size: 20px; font-weight: 700; color: var(--text-strong); line-height: 1.1; }

.flx-token-item--total .flx-token-val { color: var(--brand-soft-fg); }

.flx-token-lbl { font-size: 11px; color: var(--muted); margin-top: 4px; }

.flx-token-note { font-size: 11.5px; color: var(--muted-2); line-height: 1.45; margin: 10px 0 0; }

/* ── Toolbar de export de reportes (auditoría) ─────────────────────────────── */
/* La fila del selector de flujo, el rango de fechas y los dos botones de export.
   Envuelve en pantallas estrechas en vez de desbordar; el separador y la flecha
   marcan los tres grupos. */
.flx-rep-toolbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 4px;
}
/* Dentro de la toolbar los controles no deben estirarse: `ui-input` trae
   `flex: 1 1 auto` para vivir en un formulario, y aquí eso los descuadraba. */
.flx-rep-toolbar .ui-input { flex: 0 0 auto; min-width: 0; }

.flx-rep-sep { display: inline-block; width: 1px; height: 22px; background: var(--border); margin: 0 4px; }

.flx-rep-dash { color: var(--muted-2); font-size: 13px; }

.flx-rep-note { font-size: 12px; color: var(--muted-2); line-height: 1.45; margin: 8px 0 0; }

/* ── Objetivos: editor (wizard) + display (tarjeta de fase) ────────────────── */
.flx-wizard-hint { font-size: 12px; color: var(--muted); line-height: 1.45; margin: 0 0 12px; }

.flx-obj-editor { display: flex; flex-direction: column; gap: 10px; margin-bottom: 10px; }

.flx-obj-row { display: flex; align-items: flex-start; gap: 8px; }

.flx-obj-fields { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 6px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 12px; padding: 10px; }

.flx-obj-desc-input { min-height: 54px; resize: vertical; font-family: inherit; }

/* Fila de recurso: nombre + tipo en la misma línea (el <select> no necesita el ancho
   completo y así la fila no crece a cuatro campos apilados). */
.flx-rec-grid { display: grid; grid-template-columns: 1fr 140px; gap: 6px; }

/* Paso de seguimiento: minutos estrecho + su equivalencia en horas/días al lado. */
.flx-paso-grid { display: grid; grid-template-columns: 120px 1fr; gap: 8px; align-items: center; }

.flx-paso-eq { font-size: 12px; color: var(--muted); }

/* Umbral por encima del tope de la ventana de 24 h: se marca mientras se escribe, no solo
   al guardar — el tope no es una manía del formulario, es que fuera de la ventana Meta no
   entrega el mensaje. */
.flx-paso-eq.is-bad { color: var(--badge-danger-fg); font-weight: 600; }

/* Aviso de regla dura dentro de un paso del asistente (no es una sugerencia). */
.flx-wizard-hint.flx-rule {
  border-left: 3px solid var(--badge-warn-fg);
  background: var(--badge-warn-bg);
  color: var(--badge-warn-fg);
  border-radius: 0 8px 8px 0;
  padding: 8px 10px;
}

@media (max-width: 560px) {
  .flx-rec-grid { grid-template-columns: 1fr; }
}

.flx-stage-objectives { margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--border); }

.flx-obj-list { list-style: none; margin: 6px 0 0; padding: 0; display: flex; flex-direction: column; gap: 5px; }

.flx-obj-item { display: flex; align-items: baseline; gap: 7px; font-size: 12.5px; flex-wrap: wrap; }

.flx-obj-check { color: var(--brand); font-size: 11px; flex: 0 0 auto; }

.flx-obj-name { font-weight: 600; color: var(--text-strong); }

.flx-obj-desc { color: var(--muted); }

.flx-obj-desc::before { content: "— "; color: var(--muted-2); }

/* ── Documento JSON de fases ──────────────────────────────────────────────────
   Modal a dos columnas: el documento a la izquierda, el PLAN a la derecha. Van juntos
   a propósito — se edita mirando lo que va a pasar, no en pantallas distintas. Debajo
   de 900px se apilan (el textarea primero). */
.flx-doc-modal { max-width: 1100px; width: 92vw; }
.flx-doc-body {
  display: grid; grid-template-columns: minmax(320px, 1fr) minmax(320px, 1fr);
  gap: 16px; align-items: stretch;
}
.flx-doc-textarea {
  min-height: 52vh; resize: vertical;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px; line-height: 1.5; white-space: pre; overflow-wrap: normal;
  overflow-x: auto; tab-size: 2;
}
.flx-doc-side {
  display: flex; flex-direction: column; gap: 10px;
  max-height: 52vh; overflow-y: auto;
}
.flx-doc-side-title {
  font-size: 12px; font-weight: 700; color: var(--text-strong);
  text-transform: uppercase; letter-spacing: .04em;
}
.flx-doc-errores {
  background: var(--badge-danger-bg); color: var(--badge-danger-fg);
  border: 1px solid var(--border); border-radius: 10px; padding: 10px 12px;
}
.flx-doc-errores ul { margin: 6px 0 0; padding-left: 18px; }
.flx-doc-errores li { font-size: 12.5px; margin-bottom: 4px; }
.flx-doc-errores code, .flx-doc-side code {
  font-size: 11.5px; background: var(--surface-2); color: var(--text);
  padding: 1px 5px; border-radius: 5px;
}
.flx-doc-avisos { margin: 0; padding-left: 18px; color: var(--muted); font-size: 12.5px; }
.flx-doc-avisos li { margin-bottom: 4px; }

@media (max-width: 900px) {
  .flx-doc-body { grid-template-columns: 1fr; }
  .flx-doc-textarea { min-height: 32vh; }
  .flx-doc-side { max-height: none; }
}

/* Empty state grande cuando no hay flujo seleccionado */
.flx-blank {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; text-align: center; padding: 60px 24px;
  background: var(--surface); border: 1px dashed var(--border); border-radius: 16px;
  color: var(--muted);
}

.flx-blank-ico { font-size: 40px; opacity: .5; }

/* ============================================================
   FLUJOS — rediseño del Constructor (portado de sestia)
   ------------------------------------------------------------
   Riel colapsable, etapas como tarjetas navegables, lienzo libre
   estilo n8n con arrastre, y palabras clave como badges.

   Dos renombrados respecto al origen, a propósito:
   · `.lc-topbar` / `.lc-filters-popover` → `.flx-topbar` /
     `.flx-filters-popover`. Allí venían de la bandeja de Livechat;
     aquí Livechat no las define, así que la clase es de este módulo.
     La CAJA del popover no se redefine: se suma al grupo canónico
     de `.contacts-filters-popover`, que es el mismo widget.
   · `.mm-menu*` → `.ui-menu*` (bloque canónico del final).
   ============================================================ */

/* Barra superior de la lista: búsqueda + embudo + colapsar. Va DEBAJO del
   título y el botón "Nuevo", así que la separación la da el margen. */
.flx-topbar {
  display: flex;
  align-items: center;
  gap: 2px;
  flex-shrink: 0;
}
.flx-topbar .contacts-search-input { flex: 1 1 auto; min-width: 0; }
.flx-topbar--collapsed { justify-content: center; padding: 12px 4px; }

/* Botón "Nuevo": relleno sólido de marca (antes era punteado/fantasma). El
   hover sube levemente y refuerza la sombra para que se sienta presionable. */
.flx-btn-new {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 13px;
  border: 1px solid var(--brand-dark);
  border-radius: 9px;
  background: var(--brand-dark);
  color: #fff;
  font-size: 12.5px; font-weight: 600; font-family: inherit;
  cursor: pointer; white-space: nowrap;
  box-shadow: var(--shadow-sm);
  transition: transform .12s ease, box-shadow .12s ease, filter .12s ease;
}
.flx-btn-new:hover { filter: brightness(1.1); transform: translateY(-1px); box-shadow: var(--shadow-md); }
.flx-btn-new:active { transform: translateY(0); box-shadow: var(--shadow-sm); filter: brightness(0.96); }
.flx-btn-new:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

.flx-sidebar .flx-topbar { margin: 0 0 10px; padding: 0; }
.flx-sidebar .flx-filters-popover { top: 92px; left: 8px; right: 8px; }

/* Colapso: la rejilla pasa a un riel angosto. La transición es del ancho de la
   columna, así que va en el grid, no en el aside. */
.flx-layout { transition: grid-template-columns .18s ease; }
.flx-layout--collapsed { grid-template-columns: 62px minmax(0, 1fr); }
.flx-sidebar--collapsed { padding: 10px 8px; align-items: center; }
.flx-sidebar--collapsed .flx-topbar--collapsed { justify-content: center; margin-bottom: 8px; }
.flx-rail-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; align-items: center; }
.flx-rail-item {
  position: relative;
  width: 38px; height: 38px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--control-border);
  border-radius: 10px;
  background: var(--control-bg);
  color: var(--text);
  font-family: inherit;
  cursor: pointer;
  transition: background .12s, border-color .12s;
}
.flx-rail-item:hover { background: var(--control-bg-hover); }
.flx-rail-item.is-selected { border-color: var(--brand); background: var(--brand-soft-bg); color: var(--brand-soft-fg); }
.flx-rail-ini { font-size: 13px; font-weight: 700; }
.flx-rail-item .flx-dot { position: absolute; top: 4px; right: 4px; width: 6px; height: 6px; box-shadow: none; }

/* "Ver más": tanda siguiente de la lista. */
.flx-more-btn {
  margin-top: 4px;
  padding: 8px;
  border: 1px dashed var(--control-border);
  border-radius: 10px;
  background: transparent;
  color: var(--muted);
  font-size: 12px; font-family: inherit;
  cursor: pointer;
  transition: background .12s, color .12s, border-color .12s;
}
.flx-more-btn:hover { background: var(--control-bg); color: var(--text); border-color: var(--border-soft); }

/* ── Panel derecho: estado vacío ──────────────────────────────────────────── */
/* Sin flujo elegido la columna derecha es solo este bloque. El canónico
   `ui-empty` no trae superficie —está pensado para vivir DENTRO de una tarjeta—,
   así que aquí, que es el contenido entero de la columna, se le pone la misma
   que a `.flx-section`. Sin ella la izquierda era un panel y la derecha texto
   suelto flotando: las dos columnas no se leían como pareja. */
.flx-canvas > .flx-blank {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  box-shadow: var(--shadow-sm);
  min-height: 260px;
}

.flx-blank-title { font-size: 15px; font-weight: 600; color: var(--text-strong); }
.flx-blank-sub { font-size: 13px; color: var(--muted); max-width: 46ch; line-height: 1.5; text-align: center; }
.flx-flow-header-actions.ui-menu { position: relative; }

/* ── Etapas como tarjetas navegables ──────────────────────────────────────── */
/* `stretch` y no el `center` de la regla base: las tres tarjetas llevan un meta
   de largo distinto ("2 fase(s)" vs "Solo por el agente"), así que centradas
   quedaban a tres alturas y con los bordes superiores descuadrados. Estirando,
   la fila mide lo que la más alta y las tres empiezan y acaban igual. La flecha
   sí se centra a mano: estirada quedaría pegada arriba. */
.flx-stagebar { gap: 10px; align-items: stretch; }
.flx-stagebar-arrow { align-self: center; }
.flx-stagecard {
  flex: 1 1 0;
  min-width: 150px;
  display: flex; flex-direction: column; align-items: flex-start; gap: 3px;
  padding: 11px 14px;
  border: 1px solid var(--border);
  border-radius: 13px;
  background: var(--surface);
  color: var(--text);
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  transition: transform .12s ease, border-color .12s, box-shadow .12s, background .12s;
}
.flx-stagecard:hover { transform: translateY(-1px); border-color: var(--border-soft); box-shadow: var(--shadow-sm); }
.flx-stagecard.done { border-color: var(--brand); }
.flx-stagecard.done .flx-stage-badge { background: var(--brand-dark); color: #fff; }
.flx-stagecard.is-open {
  background: var(--brand-soft-bg);
  border-color: var(--brand);
  box-shadow: 0 0 0 1px var(--brand) inset;
}
.flx-stagecard .flx-stage-badge {
  width: 20px; height: 20px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--muted);
  font-size: 11px; font-weight: 700;
}
.flx-stagecard-label { font-size: 13.5px; font-weight: 600; color: var(--text-strong); }
.flx-stagecard-meta { font-size: 11.5px; color: var(--muted); }
.flx-stage-hint { font-size: 12.5px; color: var(--muted-2); font-style: italic; margin: 2px 0 0; }

/* Drill de etapa: entra desde la derecha y sale por donde vino. */
.flx-drill { animation: flx-drill-in .22s cubic-bezier(0.2, 0.7, 0.2, 1); }
.flx-drill.is-closing { animation: flx-drill-out .2s cubic-bezier(0.4, 0, 1, 1) forwards; }
@keyframes flx-drill-in {
  from { opacity: 0; transform: scale(0.96) translateX(14px); }
  to   { opacity: 1; transform: none; }
}
@keyframes flx-drill-out {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: scale(0.96) translateX(14px); }
}

/* El botón de añadir vive en la esquina superior derecha de la etapa. */
.flx-section-actions { display: inline-flex; align-items: center; gap: 8px; flex: 0 0 auto; }

/* Conmutador de vista de las fases (Detalle | Flujo). */
.flx-viewswitch {
  display: inline-flex;
  padding: 3px;
  gap: 2px;
  border-radius: 999px;
  background: var(--surface-2);
}
.flx-viewswitch-btn {
  padding: 5px 11px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-size: 11.5px; font-weight: 600; font-family: inherit;
  cursor: pointer;
  transition: background .12s, color .12s;
}
.flx-viewswitch-btn:hover { color: var(--text); }
.flx-viewswitch-btn.is-on { background: var(--surface); color: var(--text-strong); box-shadow: var(--shadow-sm); }

/* ── (1) Disparadores: una tarjeta por grupo, un badge por palabra ────────── */
.flx-disp-list { display: flex; flex-direction: column; gap: 10px; }
.flx-disp-card {
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface-2);
  padding: 11px 13px;
}
.flx-disp-head { display: flex; align-items: center; gap: 9px; margin-bottom: 9px; }
.flx-disp-label { font-size: 12.5px; font-weight: 600; color: var(--text-strong); }
.flx-disp-mode {
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--badge-neutral-bg);
  color: var(--badge-neutral-fg);
  font-size: 10.5px; font-weight: 600;
}
.flx-disp-head .flx-icon-btn { margin-left: auto; }
.flx-disp-actions { display: inline-flex; gap: 4px; margin-left: auto; }
.flx-disp-card.is-off { opacity: .6; border-style: dashed; }
.flx-disp-mode.is-off { background: var(--badge-warn-bg); color: var(--badge-warn-fg); }
.flx-kw-list { display: flex; flex-wrap: wrap; gap: 6px; }
.flx-kw {
  padding: 4px 10px;
  border: 1px solid var(--brand);
  border-radius: 999px;
  background: var(--brand-soft-bg);
  color: var(--brand-soft-fg);
  font-size: 11.5px; font-weight: 600;
}

/* Caja de etiquetas del formulario: las palabras ya encerradas y, detrás de
   ellas, el input donde se escribe la siguiente. Parece un solo campo. */
.flx-kwbox {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  padding: 8px 10px;
  border: 1px solid var(--control-border);
  border-radius: 10px;
  background: var(--control-bg);
  cursor: text;
  transition: border-color .12s, box-shadow .12s;
}
.flx-kwbox:focus-within {
  border-color: var(--brand);
  box-shadow: 0 0 0 2px var(--brand-soft-bg);
}
/* El input no lleva caja propia: la caja es `.flx-kwbox`. */
.flx-kw-input {
  flex: 1 1 90px;
  min-width: 90px;
  border: 0;
  outline: none;
  background: transparent;
  color: var(--text);
  font-size: 12.5px;
  font-family: inherit;
  padding: 3px 2px;
}
.flx-kw-input::placeholder { color: var(--muted-2); }
/* × de cada badge dentro del formulario. */
.flx-kw-x {
  margin-left: 6px;
  border: 0;
  background: transparent;
  color: inherit;
  font-size: 13px;
  line-height: 1;
  cursor: pointer;
  opacity: .6;
  padding: 0;
  font-family: inherit;
}
.flx-kw-x:hover { opacity: 1; }

/* Botón secundario: crear un grupo extra es la excepción, no la acción
   principal, así que va en fantasma y no compite con "+ Palabra clave". */
.flx-btn-ghost {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px;
  border: 1px solid var(--control-border);
  border-radius: 9px;
  background: transparent;
  color: var(--muted);
  font-size: 12px; font-weight: 600; font-family: inherit;
  cursor: pointer; white-space: nowrap;
  transition: background .12s, color .12s, border-color .12s;
}
.flx-btn-ghost:hover { background: var(--control-bg); color: var(--text); border-color: var(--border-soft); }

/* ── (2) Vista "Flujo" apilada: cajas resumidas + conectores ──────────────── */
.flx-canvasflow { display: flex; flex-direction: column; align-items: center; gap: 0; padding: 4px 0; }
.flx-node-wrap { display: flex; flex-direction: column; align-items: center; width: 100%; max-width: 460px; }
.flx-node {
  width: 100%;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--surface);
  padding: 11px 14px;
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: transform .12s ease, border-color .12s, box-shadow .12s;
}
.flx-node:hover { transform: translateY(-1px); border-color: var(--border-soft); box-shadow: var(--shadow-md); }
.flx-node.is-open { border-color: var(--brand); }
.flx-node.dragging { opacity: .45; }
.flx-node.over { border-color: var(--brand); box-shadow: 0 0 0 2px var(--brand-soft-bg) inset; }
.flx-node.terminal { border-style: dashed; }
.flx-node-head { display: flex; align-items: center; gap: 9px; }
.flx-node-num {
  width: 22px; height: 22px; flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: var(--brand-dark);
  color: #fff;
  font-size: 11px; font-weight: 700;
}
.flx-node-name { font-size: 13.5px; font-weight: 600; color: var(--text-strong); }
.flx-node-tags { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 7px; }
.flx-node-tags:empty { margin-top: 0; }
.flx-node-detail { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border); }
.flx-node-facts { display: flex; flex-wrap: wrap; gap: 5px; margin-bottom: 8px; }
.flx-connector { color: var(--muted-2); font-size: 17px; line-height: 1; padding: 5px 0; }

@media (max-width: 900px) {
  .flx-layout--collapsed { grid-template-columns: 1fr; }
  .flx-stagecard { min-width: 0; }
}

/* Las dos columnas miden lo mismo: el grid estira la izquierda hasta el alto
   del canvas de la derecha y la lista scrollea por dentro. Por eso el sidebar
   deja de ser `sticky` — con altura completa no tiene nada que seguir. */
.flx-layout { align-items: stretch; }
.flx-sidebar {
  /* `relative` y no `static` (que es lo que trae el origen): hay que quitarle el
     `sticky` de arriba, pero el popover de filtros es `absolute` y necesita este
     elemento como referencia; con `static` se anclaría al contenedor de página.
     `top: auto` es OBLIGATORIO: el `top: 14px` que traía el `sticky` sigue
     aplicando y en `relative` desplaza la columna 14px hacia abajo, con lo que
     la izquierda quedaba descolgada respecto a la derecha. */
  position: relative;
  top: auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.flx-sidebar .flx-flow-list {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: transparent transparent;
}
.flx-sidebar .flx-flow-list:hover { scrollbar-color: var(--control-border) transparent; }
.flx-sidebar .flx-flow-list::-webkit-scrollbar { width: 6px; }
.flx-sidebar .flx-flow-list::-webkit-scrollbar-thumb { background: transparent; border-radius: 6px; }
.flx-sidebar .flx-flow-list:hover::-webkit-scrollbar-thumb { background: var(--control-border); }
.flx-sidebar--collapsed .flx-rail-list { flex: 1 1 auto; min-height: 0; overflow-y: auto; }

/* ── (3) Vista "Flujo" libre: lienzo estilo n8n ───────────────────────────── */
.flx-flow-help {
  font-size: 12px; color: var(--muted-2); font-style: italic;
  margin: 0 0 10px; line-height: 1.5;
}
.flx-flowcanvas {
  position: relative;
  width: 100%;
  overflow: auto;
  border: 1px dashed var(--border);
  border-radius: 14px;
  background:
    radial-gradient(circle, var(--border) 1px, transparent 1px) 0 0 / 24px 24px;
  /* `touch-action: none` es lo que permite arrastrar con el dedo sin que el
     navegador se quede el gesto para hacer scroll. */
  touch-action: none;
  /* El alto lo fija el componente (crece con las cajas y con la que esté
     desplegada); aquí solo el suelo, para que nunca se sienta una tira. */
  min-height: 560px;
  resize: vertical;             /* el usuario puede darse más alto si quiere */
  /* Barras de scroll discretas: el lienzo se desplaza cuando se arrastra una
     caja fuera de la vista, no como forma normal de navegarlo. */
  scrollbar-width: thin;
  scrollbar-color: transparent transparent;
}
.flx-flowcanvas:hover { scrollbar-color: var(--control-border) transparent; }
.flx-flowcanvas::-webkit-scrollbar { width: 8px; height: 8px; }
.flx-flowcanvas::-webkit-scrollbar-thumb { background: transparent; border-radius: 8px; }
.flx-flowcanvas:hover::-webkit-scrollbar-thumb { background: var(--control-border); }
/* Las líneas van DEBAJO de las cajas y no interceptan el puntero. */
.flx-flowlinks {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 0;
}
.flx-flowlinks line {
  stroke: var(--brand);
  stroke-width: 2;
  stroke-linecap: round;
  opacity: 0.55;
}
/* Punta de flecha del conector: mismo color que la línea, sin borde. */
.flx-flowarrow { fill: var(--brand); opacity: 0.55; }
.flx-node--free {
  position: absolute;
  z-index: 1;
  cursor: grab;
  user-select: none;
  transform: none;              /* el hover no debe desplazar una caja posicionada */
}
.flx-node--free:hover { transform: none; }
.flx-node--free.dragging {
  cursor: grabbing;
  opacity: 1;
  z-index: 3;
  border-color: var(--brand);
  box-shadow: var(--shadow-lg);
}
.flx-node--free.is-open { z-index: 2; }
/* El detalle desplegado no puede crecer sin fin: pasado un límite scrollea
   dentro de la caja en vez de empujar el lienzo entero. */
.flx-node--free .flx-node-detail {
  max-height: 220px;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--control-border) transparent;
}
/* Caja de destino: anillo de marca + fondo teñido + un salto de escala. */
.flx-node--free.drop-target {
  border-color: var(--brand);
  background: var(--brand-soft-bg);
  box-shadow: 0 0 0 3px var(--brand-soft-bg), var(--shadow-md);
  transform: scale(1.03);
  transition: transform .12s ease, box-shadow .12s ease, background .12s ease;
}
/* La que se arrastra, cuando hay destino bajo el puntero: se inclina un poco
   para que se lea que las dos están emparejadas. */
.flx-node--free.will-swap {
  border-color: var(--brand);
  transform: rotate(-1.5deg);
}
/* Etiqueta flotante sobre la caja de destino. */
.flx-swap-hint {
  position: absolute;
  top: -11px;
  left: 50%;
  transform: translateX(-50%);
  white-space: nowrap;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--brand-dark);
  color: #fff;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .02em;
  box-shadow: var(--shadow-sm);
  pointer-events: none;
  z-index: 4;
}
/* Mientras se arrastra, el cursor de agarre manda en todo el lienzo: si solo
   estuviera en la caja, al adelantarse el puntero volvía a la flecha. */
.flx-flowcanvas:has(.flx-node--free.dragging) { cursor: grabbing; }
.flx-flowcanvas:has(.flx-node--free.dragging) .flx-node--free { cursor: grabbing; }

/* ── Centro de Control · canales eliminados ──────────────────────────────────
   Bloque separado y atenuado: son registros históricos, no algo con lo que se
   pueda operar. Se apagan con opacidad en vez de con un color de alerta porque
   no hay ningún problema que resolver: el canal se quitó a propósito. */
.cc-deleted-block {
  margin-top: 28px;
  padding-top: 18px;
  border-top: 1px solid var(--border);
}
.cc-deleted-title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 4px;
  font-size: 0.95rem;
  color: var(--muted);
}
.cc-deleted-row { opacity: 0.65; }
.cc-deleted-row code { color: var(--muted); }

/* ── Multimedia · selección múltiple ─────────────────────────────────────────
   La casilla se ancla a la esquina de la tarjeta y se sale del flujo para no
   descuadrar la miniatura. z-index porque la imagen la taparía. */
.mm-object { position: relative; }
.mm-select {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 2;
  display: flex;
  padding: 3px;
  border-radius: 6px;
  background: var(--surface-overlay);
  border: 1px solid var(--border);
  cursor: pointer;
}
.mm-object.is-selected {
  border-color: var(--brand);
  box-shadow: 0 0 0 2px rgba(var(--brand-rgb), 0.25);
}

.mm-selbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 10px;
  padding: 8px 12px;
  border: 1px solid var(--brand);
  border-radius: 10px;
  background: var(--brand-soft-bg);
}
.mm-selbar-count { font-size: 0.85rem; font-weight: 600; color: var(--brand-soft-fg); }
.mm-selbar-actions { display: flex; gap: 6px; flex-wrap: wrap; }

.mm-selectall-row {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}
.mm-selectall {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.8rem;
  color: var(--muted);
  cursor: pointer;
}
/* Aclaración de que las carpetas quedan fuera. Va en tono secundario: informa,
   no alarma — no ha ocurrido nada malo. */
.mm-selectall-note {
  font-size: 0.75rem;
  color: var(--muted-2);
  font-style: italic;
}

/* ── Multimedia · subida con arrastre y progreso ─────────────────────────────
   El borde discontinuo es la convención de "suelta aquí"; `is-over` lo tiñe con
   la marca mientras el archivo sobrevuela, para que se vea que el destino acepta
   el soltar. */
.mm-dropzone {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 18px;
  border: 2px dashed var(--border);
  border-radius: 12px;
  background: var(--surface-2);
  text-align: center;
  transition: background 0.15s, border-color 0.15s;
}
.mm-dropzone.is-over {
  border-color: var(--brand);
  background: var(--brand-soft-bg);
}
.mm-dropzone-text { font-size: 0.86rem; color: var(--text); }
.mm-dropzone-link {
  color: var(--brand);
  font-weight: 600;
  cursor: pointer;
  text-decoration: underline;
}

.mm-uploads {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-top: 12px;
}
.mm-upload-row {
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface);
}
.mm-upload-head {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  font-size: 0.8rem;
}
.mm-upload-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
}
.mm-upload-size { color: var(--muted); flex-shrink: 0; }

/* Carril de progreso. La barra se pinta SIEMPRE al 100% en los estados finales:
   en "Listo" para cerrar el gesto, y en error para que la fila roja se lea de un
   vistazo sin tener que interpretar una barra a medias. */
.mm-upload-track {
  height: 6px;
  margin: 6px 0 4px;
  border-radius: 999px;
  background: var(--surface-2);
  overflow: hidden;
}
.mm-upload-fill {
  height: 100%;
  background: var(--brand);
  transition: width 0.2s ease;
}
.mm-upload-row.is-done   .mm-upload-fill { background: var(--badge-success-fg); }
.mm-upload-row.is-failed .mm-upload-fill { background: var(--badge-danger-fg); }
.mm-upload-state { font-size: 0.74rem; color: var(--muted); }
.mm-upload-row.is-done   .mm-upload-state { color: var(--badge-success-fg); }
.mm-upload-row.is-failed .mm-upload-state { color: var(--badge-danger-fg); }

/* Fila del enlace generado en Multimedia: el campo crece y el botón Copiar se
   queda pegado a su derecha, sin encogerse cuando la URL firmada es larga. */
.mm-link-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.mm-link-row .mm-input {
  flex: 1;
  min-width: 0;
}
.mm-link-row .mm-btn {
  flex-shrink: 0;
}

/* ── Imagen promocional de campaña ───────────────────────────────────────────
   El botón de adjuntar reutiliza `ui-btn`; aquí solo la vista previa y el bloque
   de configuración, que son específicos del formulario de campañas. */
.camp-promo-preview {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface-2);
  max-width: 100%;
}
.camp-promo-thumb {
  width: 56px;
  height: 56px;
  object-fit: cover;
  border-radius: 8px;
  border: 1px solid var(--border-soft);
  flex-shrink: 0;
}
.camp-promo-name {
  flex: 1;
  min-width: 0;
  font-size: 0.82rem;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.camp-promo-cfg {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border-soft);
}

/* ══════════════════════════════════════════════════════════════════════════════
   PESTAÑAS DE MÓDULO — capa de color única
   ──────────────────────────────────────────────────────────────────────────────
   Cada módulo trae su PROPIA clase de pestañas por razones históricas: .control-tab,
   .metrics-tab, .metrics-subtab, .camp-tab, .profile-tab, .notif-tab, .mapa-tab,
   .mfa-tab, y tres grupos de tickets que usan `button` directo. Doce implementaciones
   del mismo widget: tocar una NO arreglaba las otras once.

   Ese reparto era el bug del tema claro. Cada grupo tenía su propio override
   `html.light-mode .x` escrito a mano, y varios clavaban el estado activo a un hex
   de fábrica con !important (#2563eb en Centro de Control, #4f46e5 en Tickets y
   Campañas). Resultado: en OSCURO el activo caía en la regla global `.active`
   —tokenizada— y seguía al tema; en CLARO lo pisaba el hex y se quedaba azul con
   cualquier tema activo. Métricas se veía bien solo porque su override usaba tokens.

   Aquí se define el COLOR una vez, en tokens, para los doce. La GEOMETRÍA (forma,
   padding, radio) sigue siendo de cada módulo: esto no reubica ni redimensiona nada.

   Va al FINAL del archivo a propósito: misma especificidad que las reglas de cada
   módulo, así que gana por orden de aparición y no necesita !important.

   REGLAS:
     · NO añadir `html.light-mode` para pestañas. Los tokens ya hacen el swap; un
       override por elemento es justo lo que se acaba de quitar.
     · Grupo nuevo → añadir su selector a estas cuatro listas, no crear un bloque
       propio.
   ══════════════════════════════════════════════════════════════════════════════ */

/* 1 · Contenedor del grupo — GEOMETRÍA + color.
   Antes cada grupo traía la suya: radios de 999px, 8px, 10px y 6px 6px 0 0;
   paddings de 4px, 5px, 0 24px 16px y ninguno; gaps de 3, 4, 6 y 8px; y cuatro
   grupos sin contenedor visible. De ahí que Métricas, Usuarios, Perfil y Centro
   de Control se vieran distintos entre sí. Aquí se fija UNA pastilla para todos.

   `width: fit-content` — la pastilla mide lo que miden sus pestañas. Tres grupos
   pedían `width: 100%` y quedaban como una barra estirada con las pestañas
   apelotonadas a la izquierda y un vacío a la derecha. */
.ticket-tabs,
.control-tabs,
.metrics-tabs,
.camp-tabs,
.profile-tabs,
.notif-tabs,
.mapa-mode-tabs,
.mfa-tabs,
.ticket-manage-tabs,
.ticket-monitor-subtabs,
.metrics-agent-tabs,
.notif-tab-nav,
.provider-model-tabs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 3px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 5px;
  width: fit-content;
  max-width: 100%;
}

/* Nivel 2 — misma pastilla, un punto más pequeña y sobre una superficie más
   tenue. La jerarquía se lee por tamaño, no por una forma distinta. */
.cc-subtabs,
.ticket-monitor-subtabs,
.metrics-agent-tabs,
.notif-tab-nav,
.provider-model-tabs,
.mfa-tabs,
.ticket-manage-tabs {
  gap: 2px;
  padding: 4px;
  background: var(--surface);
}

/* `.ticket-manage-tabs` vive dentro de un modal y su separación exterior la daba
   un `padding: 0 24px 16px` que ahora ocupa la pastilla. Se repone como margen. */
.ticket-manage-tabs { margin: 0 24px 16px; }
.ticket-monitor-subtabs { margin-bottom: 14px; }

/* Pastilla DENTRO del contenedor de módulo: sin margen lateral.
   `.metrics-tabs` nació fuera del `<main>` (Métricas la pinta como hermana), así
   que lleva `margin: 8px 40px 0` para alinearse a mano con el `padding: 40px` de
   `.app-main`. Metida dentro de `.module-main` ese margen SE SUMA al padding del
   contenedor y la pastilla queda ~40px más adentro que el contenido de abajo —
   que es como se veía el módulo Flujos. El margen vertical también se normaliza,
   y el de debajo es lo que más se
   nota: fuera del `<main>` la separación la daba la regla hermana
   `.metrics-tabs ~ .app-main { padding-top: 20px }`, que dentro no aplica, así
   que la pastilla quedaba pegada al primer panel.

   28px es la separación que ya usa `.control-tabs` en Centro de Control, que es
   el caso equivalente: pastilla de módulo dentro de `.module-main` y tarjetas
   debajo. Arriba va a 0 para que la pastilla arranque en el padding del
   contenedor, como allí, y no 8px más abajo. */
.module-main > .ticket-tabs,
.module-main > .control-tabs,
.module-main > .metrics-tabs,
.module-main > .camp-tabs,
.module-main > .profile-tabs,
.module-main > .notif-tabs {
  margin: 0 0 28px;
}

/* 2 · Pestaña en reposo — GEOMETRÍA + color.
   El radio es lo que más se notaba: varias pestañas eran rectángulos de 8px
   DENTRO de un contenedor de 999px, así que la pastilla no encajaba con su
   relleno. Aquí todas son 999px, como el contenedor. */
.ticket-tabs > button,
.ticket-manage-tabs > button,
.ticket-monitor-subtabs > button,
.notif-tabs > button,
.control-tab,
.metrics-tab,
.metrics-subtab,
.camp-tab,
.profile-tab,
.notif-tab,
.mapa-tab,
.mfa-tab {
  appearance: none;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font-family: inherit;
  font-size: 0.8125rem;
  font-weight: 600;
  padding: 8px 18px;
  margin: 0;
  white-space: nowrap;
  transition: background 0.15s, color 0.15s;
}

/* Pestaña de nivel 2 — un punto menor, a juego con su contenedor. */
.cc-subtabs > .control-tab,
.ticket-monitor-subtabs > button,
.ticket-manage-tabs > button,
.metrics-subtab,
.notif-tab,
.mfa-tab {
  padding: 6px 14px;
  font-size: 0.78rem;
  border-bottom: 0;
}

/* 3 · Hover — nunca sobre la activa: taparía el color de marca */
.ticket-tabs > button:not(.active):hover,
.ticket-manage-tabs > button:not(.active):hover,
.control-tab:not(.active):hover,
.metrics-tab:not(.active):hover,
.metrics-subtab:not(.active):hover,
.camp-tab:not(.camp-tab--active):hover,
.profile-tab:not(.profile-tab--active):hover,
.notif-tab:not(.notif-tab--active):hover,
.notif-tabs > button:not(.active):hover,
.mapa-tab:not(.is-active):hover,
.mfa-tab:not(.active):hover {
  background: var(--control-bg-hover);
  color: var(--text-strong);
}

/* 4 · Pestaña activa — el ÚNICO sitio donde se decide el color del activo.
   --brand-dark es el tono sobre el que se apoya texto blanco en ambos temas, y lo
   redefine cada tema de Identidad Visual (junto a su gemelo --light-brand-dark),
   así que esto sigue al tema sin una línea extra. */
.ticket-tabs > button.active,
.ticket-manage-tabs > button.active,
.control-tab.active,
.metrics-tab.active,
.metrics-subtab.active,
.camp-tab--active,
.profile-tab--active,
.notif-tab--active,
.notif-tabs > button.active,
.mapa-tab.is-active,
.mfa-tab.active {
  background: var(--brand-dark);
  border-color: var(--brand-dark);
  color: #fff;
}

/* .ticket-monitor-subtabs (Interno) queda fuera de las listas de arriba a
   propósito, pero NO porque conserve su look de subrayado: no lo conserva. Sus
   botones llevan `class:active`, así que les entra la regla global `.active` de
   la cabecera de este archivo, que impone `background: var(--brand-dark)` y
   `color: #fff` con !important y gana a la regla local. De su estilo de subrayado
   solo sobrevive `border-bottom-color`, que el global no toca.

   Se deja como está porque el resultado YA es tokenizado y sigue al tema en ambos
   modos — que es lo que había que arreglar. Unificar su forma con el resto es un
   cambio de diseño aparte.

   Ese `.active` global con !important es también la razón de que varios activos
   se vieran correctos en oscuro: los pintaba él, no la regla del módulo. En claro
   lo pisaban los overrides con hex fijo que se acaban de retirar. */


/* ══════════════════════════════════════════════════════════════════════════════
   ESTADO VACÍO — componente único `ui-empty`
   ──────────────────────────────────────────────────────────────────────────────
   Segundo widget del sistema `ui-*` (el primero fueron las pestañas). Había 19
   familias distintas para "aquí no hay nada": .empty-state, .metrics-empty,
   .camp-empty, .notif-empty, .mm-empty, .qa-empty, .tw-empty, .flx-blank,
   .wf-empty-state… cada una con su padding, su tamaño y su color.

   Dos variantes, porque de verdad son dos cosas distintas:
     · `ui-empty`      BLOQUE — ocupa el hueco de una tabla o panel sin datos.
     · `ui-empty-note` NOTA   — línea suelta en cursiva dentro de un formulario o
                                una ficha; no centra ni reserva espacio.
     · `ui-empty-ico`  icono opcional del bloque.

   Las clases antiguas se listan aquí como ALIAS: el markup existente sigue
   funcionando sin tocar 19 ficheros, y la migración a `ui-empty` puede ir módulo
   a módulo. Al migrar un módulo, quitar su clase vieja de estas listas.

   Va al FINAL: misma especificidad que las reglas de cada módulo, gana por orden
   y no necesita !important.

   NO están livechat (`.livechat-empty`, `.msg-empty`) ni contactos
   (`.contact-empty`, `.field-empty`): livechat está excluido por acuerdo y
   `.contact-empty` tiene hoy DOS definiciones contradictorias (bloque e inline)
   que hay que resolver antes de unificarla.
   ══════════════════════════════════════════════════════════════════════════════ */

.ui-empty,
.empty-state,
.metrics-empty,
.camp-empty,
.ticket-picker-empty,
.wf-empty-state,
.mm-empty,
.ph-notif-empty,
.notif-empty,
.flx-blank {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 36px 20px;
  text-align: center;
  color: var(--muted);
  font-size: 0.9rem;
  line-height: 1.5;
}

.ui-empty-ico,
.wf-empty-icon,
.flx-blank-ico {
  font-size: 36px;
  line-height: 1;
  opacity: 0.5;
}

.ui-empty-note,
.survey-res-empty,
.perm-override-empty,
.camp-preview-empty,
.qa-empty,
.tw-empty,
.flx-empty,
.home-sidebar-empty {
  display: block;
  padding: 6px 0;
  color: var(--muted-2);
  font-size: 0.82rem;
  font-style: italic;
}


/* ══════════════════════════════════════════════════════════════════════════════
   BADGES / TAGS DE ESTADO — componente único `ui-badge`
   ──────────────────────────────────────────────────────────────────────────────
   Tercer widget del sistema `ui-*`. Era el más disperso: 36 familias y 155 clases
   para "una pastilla de color que dice un estado".

   El problema NO era solo el nombre. Los colores estaban escritos a mano y cada
   módulo eligió el tono de UN tema: conviven `#059669` (verde oscuro, pensado
   para fondo claro) y `#34d399` (verde claro, para fondo oscuro) como "éxito".
   Según qué badge mirases, se veía bien en claro o en oscuro, nunca en ambos. Los
   parches `html.light-mode .badge-*` que había justo por eso ya se retiraron.

   Aquí el color sale SIEMPRE de los pares `--badge-{success,warn,danger,info,
   neutral,purple}-{bg,fg}`, que ya conmutan con el tema y los redefine cada tema
   de Identidad Visual.

   Las clases viejas quedan como ALIAS agrupadas por SIGNIFICADO, no por módulo:
   `.badge-active`, `.chip-active`, `.wf-badge--done` y `.pg-tag--validado` decían
   todas "esto va bien" y ahora comparten definición. Al migrar el markup de un
   módulo a `ui-badge ui-badge--success`, quitar su clase vieja de estas listas.

   FUERA de este bloque, a propósito:
     · Chips INTERACTIVOS (`.filter-pill`, `.ch-chip`, `.sc-chip`, `.kn-channel-chip`,
       `.var-chip`, `.flx-chip`): son controles seleccionables, no indicadores.
       Widget distinto, canónico aparte.
     · `.conv-channel-badge--*`: llevan el color de marca de cada plataforma
       (WhatsApp #25D366, Telegram #229ED9…). Fijos por definición.
   ══════════════════════════════════════════════════════════════════════════════ */

/* Base — geometría común */
.ui-badge,
.badge,
.audit-badge,
.health-badge,
.channel-badge,
.contact-sbadge,
.wf-badge,
.pg-tag,
.survey-res-pill,
.badge-status,
.badge-role {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 10px;
  border-radius: 999px;
  border: 0;
  font-size: 0.72rem;
  font-weight: 600;
  line-height: 1.45;
  white-space: nowrap;
  background: var(--badge-neutral-bg);
  color: var(--badge-neutral-fg);
}

/* Éxito / activo / validado */
.ui-badge--success,
.badge--success,
.badge-active,
.badge-green,
.badge-operator,
.badge-status-live,
.chip-active,
.contact-sbadge--verified,
.survey-res-pill--ok,
.wf-badge--done,
.audit-badge--ok,
.health-badge--ok,
.pg-tag--validado {
  background: var(--badge-success-bg);
  color: var(--badge-success-fg);
}

/* Error / bloqueado / rechazado */
.ui-badge--danger,
.badge--danger,
.badge--locked,
.badge-blocked,
.badge-red,
.chip-off,
.contact-sbadge--blocked,
.wf-badge--error,
.audit-badge--error,
.health-badge--error,
.pg-tag--rechazado,
.qa-tag--fail {
  background: var(--badge-danger-bg);
  color: var(--badge-danger-fg);
}

/* Aviso / pausado / pendiente de acción */
.ui-badge--warn,
.badge--warn,
.badge--paused,
.badge-warn,
.badge-yellow,
.badge-marketing,
.badge-status-test,
.contact-sbadge--paused,
.survey-res-pill--warn,
.health-badge--timeout,
.mapa-badge--warn,
.audit-badge--denied,
.pg-tag--en {
  background: var(--badge-warn-bg);
  color: var(--badge-warn-fg);
}

/* Informativo / en curso */
.ui-badge--info,
.badge--info,
.badge-blue,
.badge-supervisor,
.badge--ticket-active,
.badge--ticket-open,
.wf-badge--running {
  background: var(--badge-info-bg);
  color: var(--badge-info-fg);
}

/* Neutro / inactivo / sin dato */
.ui-badge--neutral,
.badge-gray,
.badge-guest,
.badge-status-off,
.contact-sbadge--pending {
  background: var(--badge-neutral-bg);
  color: var(--badge-neutral-fg);
}

/* Rol elevado / categoría */
.ui-badge--purple,
.badge-owner,
.badge-type,
.audit-module-tag {
  background: var(--badge-purple-bg);
  color: var(--badge-purple-fg);
}


/* ══════════════════════════════════════════════════════════════════════════════
   BOTONES — capa de INTENCIÓN única
   ──────────────────────────────────────────────────────────────────────────────
   Cuarto widget del sistema `ui-*`. 20 familias y 99 clases.

   Aquí se unifica la INTENCIÓN (primaria / secundaria / peligro / fantasma), NO
   la geometría. A diferencia de las pestañas, en botones el tamaño sí varía por
   motivos legítimos y el repo ya tiene dos escalas sanas:
     · normal — `.btn-primary` y compañía: padding 10px 20px, radio 10px.
     · densa  — `.ui-btn`: padding 7px 13px, radio 8px. Para toolbars y filas.
   Forzar una sola habría reventado toolbars y celdas de tabla.

   Lo que sí estaba roto era el color:

   1. La PRIMARIA estaba partida en dos. `.btn-primary`, `.btn-create`,
      `.camp-btn--primary`, `.qa-btn--primary` usaban `--brand-dark`; pero
      `.flx-btn-primary`, `.mapa-btn--primary` y `.mm-btn--primary` usaban
      `--brand`, un tono más claro. Dos primarias distintas en el mismo panel.
      Y `.btn-save-contact` clavaba `#4f46e5`, que no seguía a ningún tema.
      Estándar: `--brand-dark`, hover `--brand-darker` (lo que ya documentaba
      `.ui-btn--primary`).

   2. El PELIGRO mezclaba tres estilos —relleno sólido, relleno suave y solo
      color— y clavaba rojos de tema CLARO (`#dc2626`, `#b91c1c`, `#f87171`),
      que en tema oscuro quedaban con poco contraste. Ahora sale de
      `--badge-danger-*`, igual que los badges. El relleno sólido se reserva
      para confirmar algo destructivo: `ui-btn--danger-solid`.

   Al migrar el markup de un módulo a `ui-btn ui-btn--primary`, quitar su clase
   vieja de estas listas.

   FUERA a propósito: `.btn-login` (degradado propio de la pantalla de acceso,
   excepción ya documentada), `.camp-btn--outline` (botón contorneado de marca,
   que no es lo mismo que fantasma) y los botones-icono sin relleno
   (`.contacts-refresh-btn`, `.ph-*-btn`), que son otro widget.
   ══════════════════════════════════════════════════════════════════════════════ */

/* Primaria — la acción principal de la vista. Una sola por pantalla. */
.ui-btn--primary,
.btn-primary,
.btn-create,
.btn-search,
.btn-action--send,
.camp-btn--primary,
.qa-btn--primary,
.flx-btn-primary,
.mapa-btn--primary,
.mm-btn--primary,
.btn-save-contact,
.crit-btn,
.route-notfound-btn,
.tut-btn-next {
  background: var(--brand-dark);
  border: 1px solid var(--brand-dark);
  color: #fff;
}
.ui-btn--primary:hover:not(:disabled),
.btn-primary:hover:not(:disabled),
.btn-create:hover:not(:disabled),
.btn-search:hover:not(:disabled),
.btn-action--send:hover:not(:disabled),
.camp-btn--primary:hover:not(:disabled),
.qa-btn--primary:hover:not(:disabled),
.flx-btn-primary:hover:not(:disabled),
.mapa-btn--primary:hover:not(:disabled),
.mm-btn--primary:hover:not(:disabled),
.btn-save-contact:hover:not(:disabled),
.crit-btn:hover:not(:disabled),
.route-notfound-btn:hover:not(:disabled),
.tut-btn-next:hover:not(:disabled) {
  background: var(--brand-darker);
  border-color: var(--brand-darker);
}

/* Secundaria — acción de apoyo. Es el estado por defecto de las bases de módulo. */
.ui-btn,
.btn-secondary,
.btn-cancel,
.btn-page,
.btn-clear,
.camp-btn,
.camp-btn--secondary,
.mm-btn,
.qa-btn,
.mapa-btn,
.flx-btn,
.tut-btn-prev {
  background: var(--control-bg);
  border: 1px solid var(--control-border);
  color: var(--text);
}
.ui-btn:hover:not(:disabled),
.btn-secondary:hover:not(:disabled),
.btn-cancel:hover:not(:disabled),
.btn-page:hover:not(:disabled),
.btn-clear:hover:not(:disabled),
.camp-btn:hover:not(:disabled),
.camp-btn--secondary:hover:not(:disabled),
.mm-btn:hover:not(:disabled),
.qa-btn:hover:not(:disabled),
.mapa-btn:hover:not(:disabled),
.flx-btn:hover:not(:disabled),
.tut-btn-prev:hover:not(:disabled) {
  background: var(--control-bg-hover);
}

/* Peligro (suave) — acciones destructivas en línea, dentro de filas y toolbars.
   El borde se deriva del propio color de peligro con color-mix, para no volver a
   escribir un rgba() de rojo a mano. */
.ui-btn--danger,
.btn-danger,
.btn-danger-xs,
.btn-delete,
.btn-block,
.btn-cerrar,
.btn-action--danger,
.camp-btn--danger,
.flx-btn-danger,
.mapa-btn--danger,
.mm-btn--danger,
.qa-btn--danger {
  background: var(--badge-danger-bg);
  border: 1px solid color-mix(in srgb, var(--badge-danger-fg) 35%, transparent);
  color: var(--badge-danger-fg);
}
.ui-btn--danger:hover:not(:disabled),
.btn-danger:hover:not(:disabled),
.btn-danger-xs:hover:not(:disabled),
.btn-delete:hover:not(:disabled),
.btn-block:hover:not(:disabled),
.btn-cerrar:hover:not(:disabled),
.btn-action--danger:hover:not(:disabled),
.camp-btn--danger:hover:not(:disabled),
.flx-btn-danger:hover:not(:disabled),
.mapa-btn--danger:hover:not(:disabled),
.mm-btn--danger:hover:not(:disabled),
.qa-btn--danger:hover:not(:disabled) {
  border-color: color-mix(in srgb, var(--badge-danger-fg) 60%, transparent);
}

/* Peligro (sólido) — SOLO para confirmar algo irreversible. Que el botón que
   borra de verdad no se parezca al que abre el diálogo es deliberado. */
.ui-btn--danger-solid,
.btn-delete-confirm {
  background: var(--danger);
  border: 1px solid var(--danger);
  color: #fff;
}

/* Fantasma — acción terciaria: sin caja hasta el hover. */
.ui-btn--ghost,
.btn-link-xs,
.mm-btn--ghost,
.tut-btn-skip {
  background: transparent;
  border-color: transparent;
  color: var(--muted);
}
.ui-btn--ghost:hover:not(:disabled),
.btn-link-xs:hover:not(:disabled),
.mm-btn--ghost:hover:not(:disabled),
.tut-btn-skip:hover:not(:disabled) {
  background: var(--control-bg-hover);
  color: var(--text);
}


/* ══════════════════════════════════════════════════════════════════════════════
   MODALES Y DRAWERS — velo y superficie únicos
   ──────────────────────────────────────────────────────────────────────────────
   Quinto widget del sistema `ui-*`. 10 familias.

   Aquí se unifican solo DOS cosas, y a propósito:

   1. EL VELO. Había seis oscurecimientos distintos escritos a mano —
      rgba(15,23,42,0.45), rgba(15,23,42,0.55), rgba(0,0,0,0.38), (0,0,0,0.45),
      (0,0,0,0.5), (0,0,0,0.68)— mientras el token `--scrim` ya existía y solo lo
      usaban tres reglas. Abrir dos modales del panel oscurecía el fondo con
      intensidades distintas.

   2. LA SUPERFICIE. Casi todas ya usaban `--surface-overlay` (bien: es la regla
      del theming para paneles flotantes), pero con radios de 20px, 14px y 12px.

   NO se toca el `z-index`. Los valores actuales (40, 50, 60, 100, 199, 800, 900,
   1000, 2000, 3000) parecen caos, pero codifican APILAMIENTO REAL: un selector
   se abre sobre un modal, y el tutorial sobre todo. Unificarlos rompería ese
   orden sin ganar nada visual.

   Tampoco se tocan paddings ni anchos: cada modal tiene su contenido.

   FUERA: livechat (`.lc-*`) por acuerdo, y `.tut-overlay`, cuyo velo es más
   opaco a propósito para aislar el paso del tutorial.
   ══════════════════════════════════════════════════════════════════════════════ */

/* Velo */
.ui-modal-overlay,
.modal-backdrop,
.mm-modal-overlay,
.ticket-picker-overlay,
.crit-overlay,
.drawer-backdrop,
.monitor-drawer-overlay,
.notif-detail-backdrop {
  background: var(--scrim);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

/* Superficie flotante */
.ui-modal,
.modal-card,
.mm-modal,
.crit-modal,
.ticket-picker-modal,
.model-picker-modal,
.contact-drawer,
.monitor-drawer {
  background: var(--surface-overlay);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow-lg);
}

/* Los drawers se anclan a un borde: el radio completo los despegaría de él. */
.contact-drawer,
.monitor-drawer {
  border-radius: 0;
}


/* ══════════════════════════════════════════════════════════════════════════════
   CHIPS INTERACTIVOS — `ui-chip`
   ──────────────────────────────────────────────────────────────────────────────
   Sexto widget. Es el que salió de la revisión de badges: un chip que se PULSA
   (filtrar, seleccionar un canal, alternar) no es lo mismo que un badge, que solo
   informa. Se separaron por eso.

   Había seis radios (999px, 20px, 14px, 12px, 10px, 8px), fondos que iban de
   `rgba(255,255,255,0.06)` a `transparent`, y estados activos en `#1d4ed8`,
   `#93c5fd` y `#4f46e5` — cada módulo eligió un tema, igual que en los badges.

   FUERA: `.login-weather-chip` (pantalla de acceso, excepción documentada),
   `.ph-user-chip` (pieza de la barra global) y los chips que en realidad son
   indicadores de estado (`.chip-active`, `.chip-off`, `.flx-chip`, `.tw-chip`,
   `.status-chip`, `.survey-res-pill`, `.wf-tool-pill`) — esos van al bloque de
   BADGES.
   ══════════════════════════════════════════════════════════════════════════════ */

.ui-chip,
.ch-chip,
.filter-pill,
.kn-channel-chip,
.kn-chip-btn,
.sc-chip,
.var-chip,
.notif-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid var(--control-border);
  background: var(--control-bg);
  color: var(--muted);
  font-size: 0.78rem;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.ui-chip:hover,
.ch-chip:hover,
.filter-pill:hover,
.kn-channel-chip:hover,
.kn-chip-btn:hover,
.sc-chip:hover,
.var-chip:hover,
.notif-chip:hover {
  background: var(--control-bg-hover);
  color: var(--text);
}

/* Seleccionado. Tinte de marca en vez de relleno sólido: un chip activo convive
   con sus hermanos apagados y el relleno lo haría gritar como un botón primario. */
.ui-chip--on,
.ui-chip.is-active,
.ch-chip--on,
.filter-pill--active,
.kn-channel-chip.active,
.sc-chip--on {
  background: var(--brand-soft-bg);
  border-color: var(--brand);
  color: var(--brand-soft-fg);
}


/* ══════════════════════════════════════════════════════════════════════════════
   TARJETAS — superficie única `ui-card`
   ──────────────────────────────────────────────────────────────────────────────
   Séptimo widget. 18 familias.

   Se unifica SOLO la superficie: fondo, borde y radio. **No se toca el padding**,
   y es deliberado: `.tools-card` lleva `overflow:hidden` con su propia cabecera
   paginada, `.ticket-summary-card` usa `padding: 0` a propósito y las tarjetas de
   gráficas de Métricas tienen su propio reglamento en CLAUDE.md. Un padding
   común habría descuadrado las tres.

   Lo que estaba roto era el fondo. Convivían cuatro formas de decir "superficie
   de tarjeta":
       var(--surface)   var(--surface-2)   var(--panel)
       rgba(255,255,255,0.04) / 0.05   ← velo blanco: solo funciona sobre oscuro
       #1a1d27 / #2e3348 (wf-card)     ← directamente un color fijo oscuro
   Los velos y los hexes obligaban a un parche `html.light-mode .x` por tarjeta
   para que no desaparecieran en claro; esos parches ya se retiran.

   Radios: había 10, 12, 16, 20 y 24px. Queda 12px.

   FUERA a propósito: `.login-card` (excepción documentada en CLAUDE.md, tiene su
   propio contexto de tokens), y `.modal-card`/`.notif-compose-card`/
   `.notif-detail-card`/`.tut-card`, que son superficies FLOTANTES y las gobierna
   el bloque de MODALES con `--surface-overlay`.
   ══════════════════════════════════════════════════════════════════════════════ */

.ui-card,
.mm-card,
.qa-card,
.tools-card,
.mod-card,
.home-card,
.contact-card,
.camp-channel-card,
.monitor-channel-card,
.monitor-health-card,
.monitor-round-card,
.monitor-tool-card,
.kn-tipo-card,
.flx-flow-card,
.flx-token-card,
.wf-card,
.ticket-summary-card,
.metrics-kpi-card,
.metrics-chart-card,
.interno-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
}

/* Tarjeta seleccionable (elegir un tipo, un canal…). Mismo tinte de marca que el
   chip activo, para que "seleccionado" se lea igual en todo el panel. */
.ui-card--selected,
.kn-tipo-card.selected,
.flx-flow-card.active {
  background: var(--brand-soft-bg);
  border-color: var(--brand);
}


/* ══════════════════════════════════════════════════════════════════════════════
   TABLAS Y PAGINACIÓN — `ui-table` / `ui-pager`
   ──────────────────────────────────────────────────────────────────────────────
   Octavo widget. 19 familias entre ambas.

   Igual que en tarjetas: se unifica el COLOR (superficie, cabecera, separadores,
   hover de fila) y NO el padding de las celdas. Cada tabla tiene su densidad —
   la bandeja de tickets aprieta más que la de usuarios — y forzarla habría
   descuadrado anchos de columna calculados a mano.

   Qué estaba roto:
     · Envoltorios con `#161b22` fijo (`.table-wrapper`), `--panel`, `--surface`,
       y radios de 10, 12, 14 y 16px.
     · Los `th`/`td` se pintaban con velos blancos sobre oscuro, así que cada
       tabla necesitaba su parche `html.light-mode` para no desaparecer en claro.
     · El hover de fila iba a `rgba(99,102,241,0.04)` — índigo fijo — en cuatro
       tablas distintas. Con un tema activo seguía siendo índigo.

   La cabecera usa `--surface-2` (un escalón sobre la superficie) y el hover de
   fila también: es el mismo gesto de "esta franja está resaltada".
   ══════════════════════════════════════════════════════════════════════════════ */

/* Envoltorio con superficie propia */
.ui-table,
.ui-table-wrap,
.audit-table-wrap,
.users-table-wrap,
.table-wrapper,
.perms-table {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
}

/* Cabecera */
.ui-table th,
.contacts-table th,
.users-table th,
.audit-table th,
.camp-table th,
.perms-table th,
.tickets-table th,
.model-picker-table th,
.monitor-exec-table th,
.notif-prefs-table th {
  background: var(--surface-2);
  color: var(--muted);
  border-bottom: 1px solid var(--border);
  font-weight: 600;
}

/* Celdas */
.ui-table td,
.contacts-table td,
.users-table td,
.audit-table td,
.camp-table td,
.perms-table td,
.tickets-table td,
.model-picker-table td,
.monitor-exec-table td,
.notif-prefs-table td {
  color: var(--text);
  border-bottom: 1px solid var(--border-soft);
}

/* Fila resaltada */
.ui-table tbody tr:hover td,
.contacts-table tbody tr:hover td,
.users-table tbody tr:hover td,
.audit-table tbody tr:hover td,
.camp-table tbody tr:hover td,
.perms-table tbody tr:hover td,
.tickets-table tbody tr:hover td,
.monitor-exec-table tbody tr:hover td {
  background: var(--surface-2);
}

/* Paginación. Un solo pie para todas: había seis (.ticket-pagination,
   .notif-pager, .audit-pagination, .monitor-pagination, .pagination, .ui-pager)
   con separaciones y tamaños distintos bajo tablas que ya son iguales. */
.ui-pager,
.pagination,
.ticket-pagination,
.audit-pagination,
.monitor-pagination,
.notif-pager,
.notif-log-pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  flex-wrap: wrap;
  padding: 12px 2px 4px;
  font-size: 0.83rem;
  color: var(--muted);
}

.ui-pager-info,
.ticket-pagination-info,
.notif-pager-info {
  color: var(--muted);
  font-size: 0.83rem;
}

/* ============================================================
   MENÚ DESPLEGABLE — botón-icono + lista de opciones
   ------------------------------------------------------------
   Widget canónico: un botón que abre una lista corta de opciones
   excluyentes (ordenar por…, ver como…). NO es el popover de
   filtros (`.contacts-filters-popover`), que lleva formulario y
   varios controles a la vez.

   Va al final del archivo a propósito: misma especificidad que
   las reglas de cada módulo, así que gana por orden de aparición
   y no necesita `!important`.

   Uso:
     <span class="ui-menu">
       <button class="contacts-refresh-btn">…</button>
       <div class="ui-menu-backdrop"></div>
       <div class="ui-menu-pop">
         <button class="ui-menu-item is-active">…</button>
       </div>
     </span>
   ============================================================ */

.ui-menu { position: relative; display: inline-flex; }

/* Cierra al pulsar fuera. Va DEBAJO del panel y por encima del resto. */
.ui-menu-backdrop {
  position: fixed;
  inset: 0;
  z-index: 59;
}

.ui-menu-pop {
  position: absolute;
  top: 38px;
  left: 0;
  z-index: 60;
  min-width: 210px;
  padding: 5px;
  border: 1px solid var(--border);
  border-radius: 10px;
  /* Flota sobre el contenido → superficie casi opaca, no `--surface`. */
  background: var(--surface-overlay);
  box-shadow: var(--shadow-lg);
}

/* Con glifo + etiqueta hace falta más ancho que con solo texto. */
.ui-menu-pop--wide { min-width: 232px; }

/* Anclado a la derecha. Necesario cuando el disparador vive en el borde derecho
   de su contenedor (cabecera de un flujo): con `left: 0` el panel se saldría. */
.ui-menu-pop--right { left: auto; right: 0; top: 30px; min-width: 168px; }

.ui-menu-item {
  display: block;
  width: 100%;
  text-align: left;
  padding: 8px 10px;
  border: 0;
  border-radius: 7px;
  background: transparent;
  color: var(--text);
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  cursor: pointer;
}

.ui-menu-item:hover { background: var(--control-bg-hover); }
.ui-menu-item.is-active { color: var(--brand); }

/* Fila destructiva (borrar). Va por el par de tokens de peligro, no por un hex:
   así el rojo lo decide el tema, igual que en los badges. */
.ui-menu-item.is-danger { color: var(--badge-danger-fg); }
.ui-menu-item.is-danger:hover { background: var(--badge-danger-bg); }

/* Disparador "⋯" del menú. Sin caja hasta que se apunta, para no competir con
   los botones reales de la cabecera donde vive. */
.ui-menu-dots {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  color: var(--muted);
  font-family: inherit;
  cursor: pointer;
}
.ui-menu-dots:hover { background: var(--control-bg-hover); color: var(--text); border-color: var(--control-border); }

/* Las filas con glifo delante dejan de ser `display:block` para poder alinearlo
   con la etiqueta. */
.ui-menu-pop--wide .ui-menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
}

.ui-menu-ico {
  display: inline-flex;
  align-items: center;
  color: var(--muted);
  flex: none;
}

/* En la fila activa el glifo toma el color de marca de la fila, no el apagado. */
.ui-menu-item.is-active .ui-menu-ico { color: inherit; }

/* ── BARRA DE PROGRESO (canónico ui-*) ──────────────────────────────────────────
   Widget reutilizable para esperas. `--indeterminate` es para procesos sin
   porcentaje conocido (p. ej. generación de reportes por IA): un bloque desliza en
   bucle para indicar "trabajando". En tokens, sin hex de marca, para respetar el
   tema claro/oscuro. Si algún día hace falta la variante determinada (con width),
   se añade aquí, no en una clase por módulo. */
.ui-progress {
  height: 6px;
  background: var(--control-bg-hover);
  border-radius: 3px;
  overflow: hidden;
}

.ui-progress--indeterminate::after {
  content: "";
  display: block;
  height: 100%;
  width: 40%;
  border-radius: 3px;
  background: var(--brand);
  animation: uiProgressSlide 1.1s ease-in-out infinite;
}

@keyframes uiProgressSlide {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(300%); }
}

/* ═══════════════════════════════════════════════════════════════════════════
   DOCUMENTO JSON DE FASES · ASISTENTE DE IA DEL PANEL
   ---------------------------------------------------------------------------
   Dos superficies nuevas del módulo Flujos. Todo en tokens: ni un hex de marca
   ni un parche `html.light-mode` por elemento (el swap de tema ya lo hacen los
   tokens; ese patrón fue justo lo que rompió el tema claro en las pestañas).

   `.flx-doc-*` es del modal de import/export — específico de un módulo, así que
   lleva su prefijo. `.asst-*` es del drawer de chat, que es GENÉRICO: el mismo
   componente lo usará el asistente de Guías, y por eso no lleva prefijo `flx-`.
   ═══════════════════════════════════════════════════════════════════════════ */

.flx-doc-modal {
  max-width: 1100px;
  width: 94vw;
}

/* El JSON y el plan, lado a lado: editar a ciegas y luego bajar a leer el
   resultado es lo que hace que nadie revise el plan. */
.flx-doc-body {
  display: grid;
  grid-template-columns: minmax(320px, 1fr) minmax(320px, 1fr);
  gap: 16px;
  align-items: start;
}

@media (max-width: 900px) {
  .flx-doc-body { grid-template-columns: 1fr; }
}

.flx-doc-textarea {
  min-height: 52vh;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px;
  line-height: 1.5;
  white-space: pre;
  overflow: auto;
  resize: vertical;
}

.flx-doc-side {
  max-height: 52vh;
  overflow: auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.flx-doc-side-title {
  font-weight: 600;
  color: var(--text-strong);
  font-size: 13px;
}

.flx-doc-errores {
  border: 1px solid var(--badge-danger-bg);
  background: var(--badge-danger-bg);
  color: var(--badge-danger-fg);
  border-radius: 8px;
  padding: 10px 12px;
}

.flx-doc-errores ul,
.flx-doc-avisos { margin: 8px 0 0; padding-left: 18px; }

.flx-doc-errores li,
.flx-doc-avisos li { margin-bottom: 6px; font-size: 12px; line-height: 1.45; }

.flx-doc-errores code {
  background: var(--surface-2);
  color: var(--text-strong);
  padding: 1px 5px;
  border-radius: 4px;
}

.flx-doc-avisos {
  color: var(--muted);
  font-size: 12px;
}

/* ── Ventana del asistente ── */
/* Dejó de ser un cajón pegado al borde: mientras está abierto, el chat ES la pantalla.
   El estado del objeto entra por el panel de la derecha, que se pide (cerrado por
   defecto) en vez de robarle la mitad al chat.
   Flota sobre el contenido → `--surface-overlay`, no `--surface`: el tinte translúcido
   de las cards en flujo se ve casi invisible sobre un backdrop. */
.asst-backdrop { position: fixed; inset: 0; background: var(--scrim); z-index: 1199; }
.asst-split {
  position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 1200;
  width: min(1180px, 96vw); height: min(88vh, 900px);
  display: flex; overflow: hidden;
  background: var(--surface-overlay); border: 1px solid var(--border);
  border-radius: 16px; box-shadow: var(--shadow-lg);
}
.asst-drawer {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: var(--surface-overlay);
}

/* Panel lateral del objeto. Colapsa animando `flex-basis`: va siempre montado y solo
   cambia de ancho, así hay algo que animar (montarlo/desmontarlo no se puede
   transicionar). `visibility` corta el foco y el lector de pantalla cuando está cerrado. */
.asst-side {
  flex: 0 0 0; width: 0; min-width: 0; overflow: hidden; visibility: hidden; opacity: 0;
  display: flex; flex-direction: column;
  background: var(--surface-2); border-left: 1px solid transparent;
  transition: flex-basis 0.24s cubic-bezier(0.4, 0, 0.2, 1),
              opacity 0.18s ease, visibility 0s linear 0.24s, border-left-color 0.24s ease;
}
.asst-side.is-open {
  flex-basis: 360px; visibility: visible; opacity: 1;
  border-left-color: var(--border);
  transition: flex-basis 0.24s cubic-bezier(0.4, 0, 0.2, 1),
              opacity 0.18s ease 0.06s, visibility 0s, border-left-color 0.24s ease;
}
/* El contenido no se comprime mientras el panel se abre: se mantiene a su ancho final y
   el recorte del panel lo va revelando. */
.asst-side > * { flex: 0 0 auto; width: 360px; }
.asst-side-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 14px 16px; border-bottom: 1px solid var(--border);
}
.asst-side-body { flex: 1 1 auto; overflow-y: auto; padding: 14px 16px; }
.asst-panel-toggle.is-active { background: var(--brand-soft-bg); color: var(--brand-soft-fg); border-color: transparent; }

@media (max-width: 860px) {
  .asst-split { flex-direction: column; width: 96vw; height: 92vh; }
  /* En vertical el panel va DEBAJO del chat: colapsa en alto, no en ancho. */
  .asst-side { width: auto; border-left: none; border-top: 1px solid transparent; }
  .asst-side > * { width: auto; }
  .asst-side.is-open { flex-basis: 45%; border-left-color: transparent; border-top-color: var(--border); }
}

/* ── Panel de fases del chat (lo aporta Flujos) ── */
.flx-live-flow { display: flex; flex-direction: column; align-items: stretch; }
.flx-live-node {
  background: var(--surface); border: 1px solid var(--brand); border-radius: 10px;
  padding: 10px 12px; box-shadow: var(--shadow-sm); cursor: pointer;
  transition: border-color 0.16s ease, box-shadow 0.16s ease;
}
.flx-live-node:hover { border-color: var(--brand); box-shadow: var(--shadow-md); }
.flx-live-node-head { display: flex; align-items: center; gap: 8px; width: 100%; }
.flx-live-node-num {
  width: 22px; height: 22px; border-radius: 6px; flex: 0 0 auto;
  background: var(--brand-soft-bg); color: var(--brand-soft-fg); font-weight: 700; font-size: 12px;
  display: inline-flex; align-items: center; justify-content: center;
}
.flx-live-node-name { font-weight: 600; color: var(--text-strong); font-size: 13px; }
.flx-live-node-chevron { margin-left: auto; color: var(--muted); font-size: 11px; transition: transform 0.15s ease; }
.flx-live-node-chevron.is-open { transform: rotate(90deg); }
.flx-live-node-tags { margin-top: 6px; display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.flx-live-node-modo { font-size: 10.5px; padding: 1px 7px; border-radius: 999px; background: var(--surface-2); color: var(--muted); }
.flx-live-tag { font-size: 10.5px; padding: 1px 7px; border-radius: 999px; background: var(--badge-neutral-bg); color: var(--badge-neutral-fg); }
.flx-live-tag.is-term { background: var(--badge-warn-bg); color: var(--badge-warn-fg); }
.flx-live-node-obj { font-size: 10.5px; color: var(--muted); }
.flx-live-node-detail { display: none; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border-soft); }
.flx-live-node.is-open > .flx-live-node-detail { display: block; }
.flx-live-arrow { text-align: center; color: var(--brand); font-size: 16px; line-height: 1.2; margin: 3px 0; }
.flx-live-fase-obj { margin-top: 2px; font-size: 12.5px; color: var(--text); line-height: 1.45; }
.flx-live-sub { margin-top: 8px; font-weight: 700; color: var(--text-strong); font-size: 12.5px; }
.flx-live-list { margin: 4px 0 0; padding-left: 18px; display: flex; flex-direction: column; gap: 3px; }
.flx-live-list li { font-size: 12.5px; color: var(--text); }
.flx-live-muted { color: var(--muted); font-size: 12.5px; }

.asst-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border-soft);
}

.asst-title { font-weight: 600; color: var(--text-strong); }
.asst-sub   { font-size: 12px; color: var(--muted); margin-top: 2px; }
.asst-head-btns { display: flex; align-items: center; gap: 6px; }

.asst-aviso {
  margin: 12px 16px 0;
  padding: 10px 12px;
  border-radius: 8px;
  background: var(--badge-warn-bg);
  color: var(--badge-warn-fg);
  font-size: 12px;
  line-height: 1.45;
}

.asst-body {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.asst-intro { color: var(--muted); font-size: 13px; line-height: 1.5; }
.asst-intro ul { margin: 8px 0 0; padding-left: 18px; }

.asst-msg {
  max-width: 88%;
  padding: 9px 12px;
  border-radius: 12px;
  font-size: 13px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
}

.asst-msg--user {
  align-self: flex-end;
  background: var(--brand-soft-bg);
  color: var(--brand-soft-fg);
  border-bottom-right-radius: 4px;
}

.asst-msg--bot {
  align-self: flex-start;
  background: var(--surface-2);
  color: var(--text);
  border-bottom-left-radius: 4px;
}

/* Los turnos de tool se pliegan a una línea: interesa QUE se consultó algo, no
   el volcado JSON, que además llenaría el hilo. */
.asst-tool {
  align-self: flex-start;
  font-size: 11px;
  color: var(--muted-2);
  font-style: italic;
  padding-left: 4px;
}

.asst-propuesta {
  border-top: 1px solid var(--border-soft);
  padding: 12px 16px;
  background: var(--surface-2);
  max-height: 40vh;
  overflow: auto;
}

.asst-propuesta-head {
  font-size: 12px;
  font-weight: 600;
  color: var(--text-strong);
  margin-bottom: 8px;
}

.asst-propuesta-btns {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  flex-wrap: wrap;
}

.asst-input {
  display: flex;
  gap: 8px;
  align-items: flex-end;
  padding: 12px 16px;
  border-top: 1px solid var(--border-soft);
}

.asst-input textarea { flex: 1; resize: none; }

/* ── Pestaña Centro de Control → Panel → Asistente ── */
.asst-card {
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 16px;
  background: var(--surface);
  margin-bottom: 16px;
}

.asst-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.asst-caps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 16px;
  margin: 14px 0;
}

.asst-caps ul { margin: 6px 0 0; padding-left: 18px; }
.asst-caps li { font-size: 12px; line-height: 1.5; color: var(--text); margin-bottom: 4px; }

.asst-prompt {
  background: var(--surface-2);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  padding: 12px;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11px;
  line-height: 1.55;
  white-space: pre-wrap;
  max-height: 340px;
  overflow: auto;
  color: var(--text);
}


/* ──────────────────────────────────────────────────────────────────────────────
   EVENTOS SAE (pestaña de Gestión de Tickets) — Fase 1: observación
   ──────────────────────────────────────────────────────────────────────────────
   Clases con prefijo de módulo a propósito: son de esta pantalla y de ninguna
   otra. Los widgets reutilizables que usa (tabla, botones, badges, estado vacío)
   ya son canónicos `ui-*` y no se redefinen aquí.
   Todo en tokens: ni un hex, ni un parche `html.light-mode` por elemento.
   ────────────────────────────────────────────────────────────────────────────── */

.tk-sae-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 10px;
}

/* Las muestras son texto que escribió SAE: puede venir largo y sin espacios, así
   que se corta en lugar de estirar la tabla a lo ancho. */
.tk-sae-muestras {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11px;
  color: var(--muted);
  max-width: 380px;
  overflow-wrap: anywhere;
}

.tk-sae-muestra {
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  padding: 8px 10px;
  margin-bottom: 8px;
  background: var(--surface-2);
}

.tk-sae-muestra > summary {
  cursor: pointer;
  color: var(--muted);
  font-size: 12px;
}

/* El cuerpo se pinta como TEXTO dentro de un <pre>. Nunca por inner_html: lo
   escribió un tercero. */
.tk-sae-json {
  margin: 8px 0 0;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11px;
  line-height: 1.55;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  max-height: 320px;
  overflow: auto;
  color: var(--text);
}

.tk-sae-acciones {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: 10px;
}

/* ── BOTÓN-ICONO DE FILA (canónico ui-*) ────────────────────────────────────────
   Acciones inline de las tablas: un icono por acción, cuadrado, sin texto. Se
   combina con `.ui-btn` (fondo, borde y estados salen de ahí) y con `.pg-actions`
   como contenedor de la celda. El nombre de la acción va SIEMPRE en `title=`,
   que es además su nombre accesible.
   Unifica: `.flx-icon-btn` (Flujos), que queda como alias hasta migrar su markup. */
.ui-icon-btn,
.flx-icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  padding: 0;
}

/* Variante destructiva: tiñe el icono en rojo, hover incluido. */
.ui-icon-btn--danger { color: var(--badge-danger-fg); }
.ui-icon-btn--danger:hover:not(:disabled) { color: var(--badge-danger-fg); border-color: var(--badge-danger-fg); }

/* Aviso — hay un cambio hecho y SIN guardar. Es una variante del botón canónico,
   no una clase por módulo: cualquier formulario en línea (reasignar departamento
   del ticket, y lo que venga) marca así su acción pendiente. */
.ui-btn--warn:not(:disabled) {
  background: var(--badge-warn-bg);
  border-color: var(--badge-warn-fg);
  color: var(--badge-warn-fg);
}


/* Condiciones de uso del asistente. Se despliegan con el chat, no viven en la
   documentación: hay que leerlas ANTES de escribir, sobre todo la de privacidad. */
/* Condiciones de uso: ventana flotante CENTRADA sobre el chat, no una franja dentro
   del hilo. El `box-shadow` gigante hace de velo — `.asst-split` tiene
   `overflow:hidden`, así que se recorta a la caja del chat. */
.asst-legal {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 3;
  width: min(460px, calc(100% - 48px)); max-height: calc(100% - 48px); overflow-y: auto;
  border: 1px solid var(--border);
  background: var(--surface-overlay);
  border-radius: 14px;
  padding: 18px 20px;
  font-size: 12px;
  color: var(--muted);
  box-shadow: var(--shadow-lg), 0 0 0 9999px var(--scrim);
}

.asst-legal-title {
  color: var(--text-strong);
  font-weight: 700;
  font-size: 13px;
  margin-bottom: 6px;
}
.asst-legal-ok { width: 100%; margin-top: 14px; }

.asst-legal ol { margin: 8px 0 0; padding-left: 18px; }
.asst-legal li { margin-bottom: 6px; line-height: 1.5; }
.asst-legal b { color: var(--text); }

/* ── Aviso de cuenta de arranque única ────────────────────────────────────────
   Barra permanente bajo la cabecera global mientras el sistema dependa de la
   cuenta temporal creada al arrancar. No se puede cerrar a propósito: cuando esa
   cuenta caduque queda congelada y nadie —ni un owner— puede reactivarla, así que
   el aviso debe seguir ahí hasta que exista una cuenta real.
   Todo en tokens: se ve igual de bien en tema claro y oscuro.                  */
.bootstrap-banner {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 18px;
  background: var(--badge-warn-bg);
  color: var(--text);
  border-bottom: 1px solid var(--badge-warn-fg);
  font-size: 13.5px;
  line-height: 1.5;
}

.bootstrap-banner-icon {
  flex: 0 0 auto;
  color: var(--badge-warn-fg);
  font-size: 16px;
  line-height: 1.35;
}

.bootstrap-banner-texto { flex: 1 1 auto; }
.bootstrap-banner-texto strong { color: var(--text-strong); }

.bootstrap-banner-enlace {
  color: var(--brand);
  font-weight: 600;
  text-decoration: underline;
}
.bootstrap-banner-enlace:hover { color: var(--brand-dark); }

/* ── Canal que aceptaría webhooks sin firmar ──────────────────────────────────
   Se resalta la fila SOLO cuando la configuración del canal permite saltarse la
   verificación de firma (`webhook_secret_required=false`, o modo test sin secreto).
   Un canal que exige firma no muestra nada: el aviso tiene que significar algo, y
   marcar todas las filas sería lo mismo que no marcar ninguna.                  */
.cc-row-sin-firma > td {
  background: var(--badge-danger-bg);
}

.cc-row-sin-firma:hover > td {
  background: var(--badge-danger-bg);
}

.cc-sin-firma-marca {
  display: inline-block;
  margin-left: 8px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--badge-danger-bg);
  color: var(--badge-danger-fg);
  border: 1px solid var(--badge-danger-fg);
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
  cursor: help;
}

/* ══════════════════════════════════════════════════════════════════════════
   MODAL DE DEPARTAMENTOS (Usuarios › 🗂 Departamentos)

   Va al FINAL a propósito, igual que los demás bloques canónicos: la regla
   genérica `.modal-card > div:not(.modal-header):not(.modal-footer)` tiene
   especificidad (0,3,1) —tres clases MÁS el tipo `div`— y gana por orden a
   cualquier cosa anterior. El selector de aquí lleva `div` a propósito
   (`.modal-card.users-dept-modal > div.users-dept-body`) para empatar en
   (0,3,1) y ganar por orden de aparición. Sin ese `div` serían (0,3,0) y
   PERDERÍA: el bloque parecería aplicado y no lo estaría. Sin un solo
   `!important`.

   Qué arreglaba esto. La modal tenía dos problemas y los dos venían de la
   misma regla:

     · `.users-filterbar` (padding 14px) y `.users-table-wrap` eran hijas
       DIRECTAS de la tarjeta, así que la genérica les imponía `padding: 0 24px`
       — 0 arriba y abajo. Los campos quedaban pegados al borde de su propio
       recuadro y la tabla, con 24px metidos DENTRO de su borde, desbordaba por
       la derecha y recortaba la columna de acciones.
     · A la vez, el contenido no tenía aire propio: todo el espaciado eran
       `style="margin-bottom:12px"` sueltos en el markup.

   Con el envoltorio `users-dept-body` esas cajas dejan de ser hijas directas,
   conservan su padding, y el espaciado vertical lo pone un `gap` en un sitio.
   ═══════════════════════════════════════════════════════════════════════ */

/* Cinco columnas (nombre, código, domain, estado, acciones) no caben en los
   640 px de `modal-wide`: los nombres largos partían en dos líneas y la fila de
   creación tiraba el botón «+ Crear» a un segundo renglón. */
.modal-card.users-dept-modal { max-width: min(1000px, 94vw); }

.modal-card.users-dept-modal > div.users-dept-body {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 18px 24px 4px;
}

/* El espaciado lo pone el `gap` del contenedor: los márgenes propios de estas
   piezas se sumarían al hueco y descuadrarían el ritmo. */
.users-dept-body > .users-filterbar { margin-bottom: 0; }
.users-dept-body > .users-dept-help { margin: 0; }

/* La tarjeta es `overflow-x: hidden`: si la tabla no cabe, el scroll tiene que
   ser SUYO o las columnas de la derecha se recortan y quedan inalcanzables.
   `.users-table-wrap` ya trae `overflow-x: auto`; el `min-width` de la tabla es
   lo que lo activa en vez de dejar que las cinco columnas se aplasten. */
.users-dept-body > .users-table-wrap { max-width: 100%; }
.users-dept-body .users-table { min-width: 620px; }

/* Que no se lleve el ancho de un campo de texto ni se caiga de renglón. */
.users-dept-crear { flex: 0 0 auto; min-height: 36px; }

@media (max-width: 700px) {
  .modal-card.users-dept-modal > div.users-dept-body { padding: 14px 16px 4px; gap: 12px; }
  .users-dept-crear { flex: 1 1 100%; }
}

/* ── Invitaciones pendientes (módulo Usuarios) ───────────────────────────────
   Bloque propio del módulo: sólo existe en Gestión de Usuarios. La tabla y los
   botones son los canónicos (`ui-table`, `ui-btn`), aquí sólo va la cabecera de
   la sección. Todo en tokens — nada de hexes ni parches html.light-mode. */
.users-invites-section { margin-top: 22px; }
.users-invites-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; margin-bottom: 10px; flex-wrap: wrap;
}
.users-invites-title {
  margin: 0; font-size: 0.95rem; font-weight: 700; color: var(--text-strong);
  display: flex; align-items: center; gap: 8px;
}
.users-invites-count {
  background: var(--badge-info-bg); color: var(--badge-info-fg);
  border-radius: 999px; padding: 1px 8px; font-size: 0.75rem; font-weight: 700;
}

/* ══════════════════════════════════════════════════════════════════════════
   INDICADOR DE CARGA — `ui-loading` / `ui-progress`

   Canónico: se define UNA vez y lo consume cualquier módulo (componente en
   `components/loading.rs`). No crear `.camp-loading`, `.metrics-loading` ni
   familia por módulo.

   El `<progress>` sin `value` sale INDETERMINADO y lo anima el navegador; con
   `value` y `max` es una barra normal. Los dos casos se estilan aquí, incluida
   la animación del indeterminado, porque el aspecto nativo cambia entre
   navegadores y en tema oscuro llega a no verse.
   ═══════════════════════════════════════════════════════════════════════ */

.ui-loading {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 22px 18px;
  width: 100%;
}

.ui-loading-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}

.ui-loading-txt  { color: var(--text); font-size: 0.9rem; }
.ui-loading-pct  { color: var(--muted); font-size: 0.8rem; font-variant-numeric: tabular-nums; }
.ui-loading-nota { color: var(--muted-2); font-size: 0.78rem; line-height: 1.45; }

/* Reset del aspecto nativo: sin esto cada navegador pinta el suyo y ninguno
   respeta los tokens del tema. */
.ui-progress {
  -webkit-appearance: none;
  appearance: none;
  border: none;
  width: 100%;
  height: 6px;
  border-radius: 999px;
  overflow: hidden;
  background: var(--surface-2);
  color: var(--brand);            /* Firefox usa `color` para la parte llena */
}

.ui-progress::-webkit-progress-bar   { background: var(--surface-2); border-radius: 999px; }
.ui-progress::-webkit-progress-value { background: var(--brand); border-radius: 999px; transition: width 0.25s ease; }
.ui-progress::-moz-progress-bar      { background: var(--brand); border-radius: 999px; }

/* Indeterminado: `<progress>` SIN atributo `value`. `:indeterminate` es el
   selector estándar para esa forma. Se pinta una banda que recorre la barra,
   porque el indeterminado nativo de WebKit desaparece con el reset de arriba. */
.ui-progress:indeterminate {
  background: linear-gradient(90deg,
      var(--surface-2) 0%, var(--surface-2) 35%,
      var(--brand)     50%,
      var(--surface-2) 65%, var(--surface-2) 100%);
  background-size: 250% 100%;
  animation: uiProgressSlide 1.15s linear infinite;
}
.ui-progress:indeterminate::-webkit-progress-bar   { background: transparent; }
.ui-progress:indeterminate::-webkit-progress-value { background: transparent; }
.ui-progress:indeterminate::-moz-progress-bar      { background: transparent; }

@keyframes uiProgressSlide {
  from { background-position: 150% 0; }
  to   { background-position: -50% 0; }
}

/* Respeta a quien pidió menos movimiento: la barra se queda quieta y sigue
   comunicando «esto está en marcha» por el texto de al lado. */
@media (prefers-reduced-motion: reduce) {
  .ui-progress:indeterminate { animation: none; background-position: 50% 0; }
}

/* Enrutamiento por respuesta de herramienta (constructor de flujos).
   Una fila por regla: campo → operador → valor → rama. Envuelve en pantallas
   estrechas en vez de recortar: una regla a medias no se puede revisar. */
.flx-ruta-row,
.flx-ruta-regla {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
}
.flx-ruta-regla { padding-left: 4px; }
.flx-ruta-regla .form-input { flex: 1 1 130px; min-width: 110px; }
.flx-ruta-row .form-input   { flex: 0 1 220px; }

.flx-ruta-lbl {
  color: var(--muted);
  font-size: 0.8rem;
  white-space: nowrap;
}
.flx-ruta-ok    { color: var(--badge-success-fg); font-size: 0.8rem; }
.flx-ruta-aviso { color: var(--badge-warn-fg);    font-size: 0.8rem; }

/* ──────────────────────────────────────────────────────────────────────────────
   ASISTENTES DEL PANEL — listado en tarjetas + detalle en acordeón
   ------------------------------------------------------------------------------
   Amplía la familia `.asst-*`, que ya era del asistente y es genérica. Dos vistas:
   el LISTADO, para elegir, y el DETALLE, en el que se entra viendo qué secciones
   hay en vez de todo el contenido de golpe.
   ────────────────────────────────────────────────────────────────────────────── */

/* ── Listado ───────────────────────────────────────────────────────────────── */
.asst-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 290px));
  gap: 14px; margin-top: 16px;
}
/* Nombre arriba, módulo y estado abajo. Nada más: para elegir un asistente no hace
   falta su descripción, que vive en su detalle. */
.asst-mini {
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  padding: 14px; cursor: pointer;
  display: flex; flex-direction: column; gap: 12px;
  transition: transform 0.16s ease, box-shadow 0.16s ease, border-color 0.16s ease;
}
.asst-mini:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: var(--brand); }
.asst-mini-title {
  margin: 0; font-size: 0.92rem; color: var(--text-strong); font-weight: 650; line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
/* Las dos etiquetas en UNA fila: si el módulo es largo se recorta el chip, nunca se
   parte la fila. */
.asst-mini-foot { display: flex; align-items: center; gap: 6px; flex-wrap: nowrap; min-width: 0; }
.asst-mini-foot .asst-chip { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.asst-mini-foot .ui-badge { flex: 0 0 auto; }
.asst-chip {
  font-size: 0.72rem; padding: 3px 9px; border-radius: 999px;
  background: var(--surface-2); color: var(--muted); border: 1px solid var(--border-soft);
  white-space: nowrap;
}
/* Acción bloqueada: el `title` y el cursor viven en el envoltorio porque un
   <button disabled> no dispara ninguno de los dos. */
.asst-locked-wrap { display: inline-flex; cursor: not-allowed; }
.asst-btn-locked { pointer-events: none; opacity: 0.45; filter: grayscale(1); }

/* ── Detalle ───────────────────────────────────────────────────────────────── */
.asst-back { margin-bottom: 18px; }
.asst-id { padding-bottom: 18px; border-bottom: 1px solid var(--border); margin-bottom: 22px; }
.asst-id-name {
  margin: 0 0 10px; font-size: 1.45rem; line-height: 1.25; font-weight: 700;
  color: var(--text-strong); letter-spacing: -0.01em;
}
.asst-id-meta { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* Cada sección es una caja propia con aire alrededor, no un bloque apilado contra
   una línea. Arrancan cerradas. */
.asst-acc {
  background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  margin-bottom: 12px; overflow: hidden;
}
.asst-acc-head {
  width: 100%; display: flex; align-items: center; gap: 10px;
  background: none; border: 0; padding: 16px 20px; cursor: pointer; text-align: left;
  color: var(--text-strong); font: inherit; transition: background-color 0.14s ease;
}
.asst-acc-head:hover { background: var(--surface-2); }
.asst-acc.is-open > .asst-acc-head { border-bottom: 1px solid var(--border-soft); }
.asst-acc-title { font-size: 1rem; font-weight: 650; flex: 0 0 auto; }
.asst-acc-chevron { color: var(--muted); font-size: 0.8rem; transition: transform 0.15s ease; }
.asst-acc-chevron.is-open { transform: rotate(90deg); }
/* Resumen: un dato corto, nunca un texto que haya que recortar. */
.asst-acc-sum {
  margin-left: auto; min-width: 0; font-size: 0.82rem; color: var(--muted);
  font-weight: 400; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.asst-acc-body { display: none; padding: 20px; }
.asst-acc.is-open > .asst-acc-body { display: block; }

/* Etiqueta pequeña sobre el valor. Dos columnas como máximo: el ancho de la
   pantalla no es el ancho de lectura. */
.asst-fields { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 20px 28px; }
.asst-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.asst-field--wide { grid-column: 1 / -1; }
.asst-field-label {
  font-size: 0.72rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--muted-2);
}
.asst-field-val { font-size: 0.92rem; color: var(--text); }
.asst-prose { max-width: 78ch; line-height: 1.6; color: var(--muted); }

/* ── System prompt: archivo / vista previa ─────────────────────────────────── */
.asst-prompt-block { margin-top: 26px; padding-top: 20px; border-top: 1px solid var(--border-soft); }
.asst-prompt-head { display: flex; align-items: center; gap: 10px; }
.asst-prompt-meta { font-size: 0.78rem; color: var(--muted); }
.asst-prompt-block .asst-prompt { margin-top: 12px; max-height: 260px; }
.asst-prompt-expand {
  margin-left: auto; background: var(--control-bg); border: 1px solid var(--control-border);
  color: var(--text); border-radius: 8px; width: 28px; height: 28px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; font-size: 0.9rem;
}
.asst-prompt-expand:hover { background: var(--control-bg-hover); color: var(--brand); }
.asst-prompt-modal { display: flex; flex-direction: column; width: min(980px, 96vw); }
.asst-prompt-full { max-height: 72vh; margin: 0 22px 20px; }

/* Segmented archivo/vista previa. */
.asst-seg {
  display: inline-flex; gap: 2px; padding: 2px; border-radius: 999px;
  background: var(--control-bg); border: 1px solid var(--control-border);
}
.asst-seg-btn {
  width: 26px; height: 26px; border: 0; border-radius: 999px; cursor: pointer;
  background: none; color: var(--muted);
  display: inline-flex; align-items: center; justify-content: center;
}
.asst-seg-btn:hover { color: var(--text); }
.asst-seg-btn.is-active { background: var(--brand-soft-bg); color: var(--brand-soft-fg); }

/* Vista previa del prompt: el Markdown aplicado en la MISMA caja que el archivo,
   así alternar no mueve nada de sitio. */
.asst-md { white-space: normal; font-family: inherit; font-size: 0.88rem; line-height: 1.6; }
.asst-md > :first-child { margin-top: 0; }
.asst-md > :last-child { margin-bottom: 0; }
.asst-md h1, .asst-md h2, .asst-md h3, .asst-md h4 {
  color: var(--text-strong); line-height: 1.3; margin: 18px 0 8px; font-weight: 650;
}
.asst-md h1 { font-size: 1.15rem; }
.asst-md h2 { font-size: 1.05rem; }
.asst-md h3 { font-size: 0.96rem; }
.asst-md h4 { font-size: 0.9rem; color: var(--text); }
.asst-md p { margin: 0 0 10px; }
.asst-md ul, .asst-md ol { margin: 0 0 10px; padding-left: 22px; }
.asst-md li { margin-bottom: 4px; }
.asst-md code {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.82em;
  background: var(--control-bg); padding: 1px 5px; border-radius: 5px;
}
.asst-md pre {
  background: var(--control-bg); border: 1px solid var(--border-soft); border-radius: 8px;
  padding: 10px 12px; overflow-x: auto; margin: 0 0 12px;
}
.asst-md pre code { background: none; padding: 0; }
.asst-md blockquote {
  margin: 0 0 12px; padding: 2px 0 2px 12px;
  border-left: 3px solid var(--border); color: var(--muted);
}
.asst-md a { color: var(--brand); }
.asst-md hr { border: 0; border-top: 1px solid var(--border-soft); margin: 16px 0; }
.asst-md table { border-collapse: collapse; margin: 0 0 12px; font-size: 0.85em; }
.asst-md th, .asst-md td { border: 1px solid var(--border-soft); padding: 5px 9px; text-align: left; }
.asst-md th { background: var(--surface-2); color: var(--text-strong); }

/* Barra de scroll estilo sidebar: fina, sin carril reservado (no empuja el
   contenido) y visible solo al pasar el puntero. */
.asst-scroll { scrollbar-width: thin; scrollbar-color: transparent transparent; }
.asst-scroll:hover { scrollbar-color: var(--control-border) transparent; }
.asst-scroll::-webkit-scrollbar { width: 8px; }
.asst-scroll::-webkit-scrollbar-track { background: transparent; }
.asst-scroll::-webkit-scrollbar-thumb {
  background: transparent; border: 2px solid transparent; background-clip: padding-box;
  border-radius: 8px; transition: background-color 0.2s ease;
}
.asst-scroll:hover::-webkit-scrollbar-thumb { background: var(--control-border); background-clip: padding-box; }
