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

/* ============================================================
   Variables globales — identidad base Sestia (plantilla de marca)
   ------------------------------------------------------------
   Paleta de fábrica (5 colores, misma familia en ambos temas):
     #fbfcfd  casi blanco   → superficie de tarjetas (claro) / texto fuerte (oscuro)
     #eef1f7  gris frío     → lienzo del layout (claro) / texto base (oscuro)
     #e6ebf1  gris azulado  → superficies hundidas / tinte de las tarjetas oscuras
     #572d4b  ciruela       → ACENTO principal de marca
     #9c9ba9  gris medio    → texto secundario / jerarquía baja

   Todo color de la app sale de estos tokens. Un tema del Marketplace (o uno de
   los presets de fábrica, backend/sql/124_sestia_base_themes.sql) solo redefine
   tokens — nunca reglas. Ver docs/frontend/arquitectura/identidad_visual_sestia.md.
   ============================================================ */
: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) ──
     Lienzo = #eef1f7 llevado a carbón frío; las tarjetas son ese mismo gris
     azulado (#e6ebf1) en alfa baja → "flotan" sobre el lienzo sin bordes duros. */
  --bg:                #14161c;
  --bg-2:              #191c24;
  --surface:           rgba(230,235,241,0.05);
  --surface-2:         rgba(230,235,241,0.08);
  --surface-3:         #1b1f28;
  --panel:             rgba(230,235,241,0.06);
  --panel-2:           #232833;
  /* 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(28,32,41,0.97);
  --control-bg:        rgba(230,235,241,0.07);
  --control-bg-hover:  rgba(230,235,241,0.12);
  --control-border:    rgba(230,235,241,0.14);
  --scrim:             rgba(10,11,15,0.68);
  /* ── Texto ── */
  --text:              #eef1f7;
  --text-strong:       #fbfcfd;
  --muted:             #9c9ba9;
  --muted-2:           #74717f;
  /* ── Bordes ── */
  --border:            rgba(230,235,241,0.10);
  --border-soft:       rgba(230,235,241,0.06);
  /* ── Marca / acento — ciruela #572d4b ──
     En OSCURO la ciruela pura no llega a contraste de texto sobre carbón, así que
     --brand es la ciruela ACLARADA (bordes, iconos, texto de acento) y
     --brand-dark queda en la ciruela pura, que es donde se apoya texto blanco
     (#fff sobre #572d4b ≈ 9.7:1). En CLARO se invierte (ver html.light-mode). */
  --brand:             #a76b91;
  --brand-dark:        #572d4b;
  /* Componentes RGB de la marca — para tints con alfa: rgba(var(--brand-rgb),α).
     Un tema puede overridearlos igual que --brand y así controlar también los
     fondos/anillos translúcidos, no solo los colores sólidos. */
  --brand-rgb:         167, 107, 145;
  --brand-dark-rgb:    87, 45, 75;
  --brand-soft-bg:     rgba(167,107,145,0.18);
  --brand-soft-fg:     #d7abc4;
  --accent:            #14161c;
  --danger:            #ef4444;
  --success:           #10b981;
  /* ── Chrome de navegación (headerbar + sidebar de módulo) ──
     DERIVADOS de la marca a propósito: son `color-mix` sobre --brand-dark, así
     que al activar un preset (que solo redefine --brand*) la barra superior y la
     lateral cambian SOLAS. No pongas aquí un hex fijo — era justo el bug: 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 y se quedan con la 1ª). */
  --nav-bg:            #271c29;
  --nav-bg:            color-mix(in srgb, var(--brand-dark) 28%, var(--bg));
  --nav-bg-2:          #201a24;
  --nav-bg-2:          color-mix(in srgb, var(--brand-dark) 16%, var(--bg));
  --nav-border:        rgba(230,235,241,0.09);
  /* Velo que se superpone a --nav-bg-2 en la subsidebar: mismo color que la
     sidebar, un escalón más hundido (profundidad sin salirse de la identidad). */
  --nav-shade:         rgba(0,0,0,0.30);
  /* ── Tooltip ── */
  --tooltip-bg:        #262b36;
  --tooltip-fg:        #fbfcfd;
  /* ── Tags / badges (bg + fg) ──
     success/warn/danger/info son SEMÁNTICOS: no siguen la marca (un tema de marca
     roja no debe volver rojo el "todo ok"). El par purple sí sigue la marca. */
  --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(156,155,169,0.18); --badge-neutral-fg: #c9c7d2;
  --badge-purple-bg:   rgba(167,107,145,0.18); --badge-purple-fg:  #d7abc4;
  /* ── 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);
  /* ── Gráficas (ApexCharts) ──
     Los colores de serie NO pueden ser hexes literales en el .rs: ApexCharts
     recibe JSON, no CSS, así que no ve `var(--…)`. Los lee `charts.rs` con
     getComputedStyle y los pasa ya resueltos. Que estén aquí es lo que hace que
     las gráficas sigan al tema del usuario y —sobre todo— a las paletas de
     accesibilidad: antes iban en verde y ámbar fijos, que es justo el par que un
     deuteranope no separa, en el sitio donde más duele.

     `--chart-1..6` es la rampa CATEGÓRICA (series sin significado propio) y va
     ordenada por separabilidad: las dos primeras son las que más se usan y las
     que más lejos están entre sí en cada paleta. Los alias semánticos de abajo
     apuntan a la rampa, así que una paleta solo necesita redefinir los seis. */
  --chart-1:        #60a5fa;
  --chart-2:        #4caf88;
  --chart-3:        #f59e0b;
  --chart-4:        #7c6af7;
  --chart-5:        #ef4444;
  --chart-6:        #94a3b8;
  --chart-ok:       var(--chart-2);
  --chart-warn:     var(--chart-3);
  --chart-bad:      var(--chart-5);
  --chart-info:     var(--chart-1);
  --chart-accent:   var(--chart-4);
  --chart-neutral:  var(--chart-6);
  /* Cromo: rejilla, ejes, leyenda y el texto sobre las porciones del donut. */
  --chart-grid:      #2a2a3e;
  --chart-axis:      #a0a0b0;
  --chart-legend:    #c0c0d0;
  --chart-datalabel: #ffffff;
}

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

/* Transición suave claro⇄oscuro. Solo props de color; NO afecta la carga
   inicial (index.html fija la clase de tema en un script pre-paint, antes del
   primer render → la transición solo dispara en el toggle en runtime). Las
   reglas con transition propia (botones, hover, etc.) ganan por especificidad,
   así que las interacciones siguen igual de rápidas; aquí solo funden las
   superficies estáticas. box-shadow/transform se dejan a sus reglas de hover. */
*, *::before, *::after {
  transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease, fill 0.3s ease;
}

/* scrollbar-gutter: stable → reserva SIEMPRE el ancho de la barra de scroll del
   documento, aunque no haga falta. Evita que al pasar a una tab alta (Bloques)
   aparezca la barra, encoja el viewport y desplace el contenido centrado. */
/* --font-scale (F6.3): escala global de tipografía. Todo lo dimensionado en rem
   reescala con esto; los px literales NO (deuda conocida, riesgo 8 del plan). */
html { font-size: calc(16px * var(--font-scale, 1)); scrollbar-gutter: stable; }

body {
  /* --font-family (F6.5): lo fija el fontpack activo; fallback = Inter de fábrica. */
  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, #14161c 0%, #2b1f2b 50%, #14161c 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;
  /* Fondo estático del login (el dinámico por clima lo pisa .login-container--dynamic).
     Carbón frío → ciruela → carbón: la marca ya presente antes de entrar. */
  background: linear-gradient(135deg, #14161c 0%, #572d4b 45%, #14161c 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(var(--brand-rgb),0.14) 0%, transparent 65%),
    radial-gradient(ellipse 450px 450px at 22% 92%, rgba(var(--brand-dark-rgb),0.09)  0%, transparent 65%),
    radial-gradient(ellipse 300px 300px at 55% 50%, rgba(var(--brand-rgb),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, var(--brand-dark) 0%, var(--brand) 100%);
  border-radius: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 8px 20px rgba(var(--brand-dark-rgb),0.4), 0 2px 6px rgba(var(--brand-dark-rgb),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, #14161c 0%, #572d4b 45%, #14161c 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(var(--brand-rgb),0.14) 0%, transparent 65%),
    radial-gradient(ellipse 450px 450px at 22% 92%, rgba(var(--brand-dark-rgb),0.09)  0%, transparent 65%),
    radial-gradient(ellipse 300px 300px at 55% 50%, rgba(var(--brand-rgb),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(var(--brand-rgb),0.16) 0%, transparent 68%),
    radial-gradient(ellipse 350px 160px at 50% 100%, rgba(var(--brand-dark-rgb),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: var(--text);
  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: var(--text);
  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: var(--brand);
  border-color: var(--brand-soft-fg);
  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(var(--brand-rgb),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(var(--brand-dark-rgb),0.08)  0%, transparent 68%),
    radial-gradient(ellipse 380px 280px at 28% 80%, rgba(var(--brand-dark-rgb),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(var(--brand-dark-rgb),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(var(--brand-dark-rgb),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-dark) 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;
}

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

/* Márgenes del módulo: el contenido no debe pegarse a los bordes de la pantalla. */
.tickets-content { padding: 24px 32px; }

/* ── Toolbar reutilizable de tickets (bandeja + tipos) ─────────────────────── */
.tickets-toolbar {
  position: relative;               /* ancla del popover de filtros */
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 16px;
}
/* Botón de acción (crear/nuevo) DENTRO de la toolbar, pegado a la derecha y
   alineado verticalmente con la barra de búsqueda. margin-left:auto absorbe el
   espacio libre aunque el wrap del popover (invisible, 0px) quede en medio. */
.tickets-toolbar-action { margin-left: auto; flex-shrink: 0; }
.tickets-toolbar-right {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

/* ── TOOLBAR ESTÁNDAR (components/toolbar.rs) ─────────────────────────────────
   Controles compartidos por todos los módulos: segmented de vista, desplegable de
   orden y modo selección. El resto (pastilla de búsqueda, embudo, limpiar,
   refrescar) reutiliza las clases .contacts-* de este mismo bloque. */
.tb-actions { display: inline-flex; gap: 8px; align-items: center; }

.tb-viewseg {
  display: inline-flex; gap: 2px; padding: 3px; margin: 0 4px;
  border: 1px solid var(--control-border); border-radius: 999px;
  background: var(--surface-2);
}
.tb-viewseg-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 26px; padding: 0;
  border: 0; border-radius: 999px; background: transparent; color: var(--muted);
  cursor: pointer; transition: background 0.15s, color 0.15s;
}
.tb-viewseg-btn:hover:not(.is-active) { color: var(--text); }
.tb-viewseg-btn.is-active { background: var(--brand-dark); color: #fff; }

.tb-sort { position: relative; display: inline-flex; }
.tb-menu-pop {
  position: absolute; top: 38px; left: 0; z-index: 60;
  min-width: 210px; padding: 5px;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface-overlay); box-shadow: var(--shadow-lg);
}
.tb-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;
}
.tb-menu-item:hover { background: var(--control-bg-hover); }
.tb-menu-item.is-active { color: var(--brand); }

/* Toast de progreso de una acción masiva: barra + "hechos / total". Flota abajo a
   la derecha para no tapar la tabla sobre la que se está actuando. */
.tb-toast {
  position: fixed; right: 22px; bottom: 22px; z-index: 900;
  width: min(320px, calc(100vw - 44px));
  padding: 12px 14px;
  border: 1px solid var(--border); border-radius: 12px;
  background: var(--surface-overlay); box-shadow: var(--shadow-lg);
  animation: tb-toast-in 0.18s ease both;
}
@keyframes tb-toast-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}
.tb-toast-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.tb-toast-label { font-size: 0.84rem; font-weight: 700; color: var(--text-strong); }
.tb-toast-count { font-size: 0.8rem; font-weight: 700; color: var(--brand); font-variant-numeric: tabular-nums; }
.tb-toast-track {
  margin: 8px 0 6px; height: 6px; border-radius: 999px;
  background: var(--surface-2); overflow: hidden;
}
.tb-toast-fill {
  height: 100%; border-radius: 999px;
  background: var(--brand-dark);
  transition: width 0.2s ease;
}
.tb-toast.is-done .tb-toast-fill { background: var(--badge-success-fg); }
.tb-toast-foot { font-size: 0.76rem; color: var(--muted); }

/* Popover de filtros (se renderiza siempre, se muestra/oculta por CSS).
   position:absolute lo saca del flujo flex → abrir filtros NO mueve los botones. */
.tickets-filters-wrap { display: none; position: absolute; top: 0; left: 0; }
.tickets-filters-wrap.is-open { display: block; }
/* El wrap (absolute, sin ancho) hacía que el `calc(100% - 64px)` del popover
   colapsara → popover aplastado. Se fija el ancho por viewport, no por el wrap. */
.tickets-toolbar .tickets-filters-popover,
.monitor-toolbar .tickets-filters-popover { top: 52px; left: 0; width: min(420px, calc(100vw - 48px)); }
.monitor-toolbar .tickets-filters-popover { top: 44px; }

/* Botones de la toolbar de tickets al mismo tamaño que Añadir/Exportar (bandeja,
   tipos e interno): Limpiar (btn-sm) y Asignar (btn-secondary) quedaban dispares. */
.tickets-toolbar-right .btn-secondary,
.monitor-toolbar .btn-secondary {
  padding: 8px 16px;
  border-radius: 9px;
  font-size: 0.8125rem;
}

/* Recarga acotada a la tabla: se atenúa mientras llega la nueva página, sin
   desmontar toda la vista (tabs/toolbar quedan). */
.tk-reloading { opacity: 0.55; pointer-events: none; transition: opacity 0.12s ease; }

/* Recarga en curso a nivel de módulo. Se atenúan los HIJOS, no el contenedor:
   `opacity` en el padre tiñe todo el subárbol y ningún hijo puede recuperarse,
   así que la toolbar (`.tb`) y las tabs se apagarían con la tabla — y la toolbar
   es justo lo que tiene que seguir vivo, porque su icono girando es el aviso de
   que algo se está cargando. Con esto, al pulsar refrescar se ve recargarse lo
   que sea que muestre el módulo: tabla, tarjetas o gráficas. */
.is-reloading > *:not(.tb):not(nav):not(.error-banner) {
  opacity: 0.55;
  pointer-events: none;
  transition: opacity 0.12s ease;
}
/* Celdas centradas verticalmente: los badges (SLA/estado) hacían que el texto
   plano (Asunto/Cliente) se viera "subido". */
.tickets-table td { vertical-align: middle; }
/* 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); }

/* Scrollbar de los modales/forms: overlay auto-oculta, estilo sidebar (no una
   barra "metida" invasiva). Se revela solo al pasar el puntero por encima. */
.modal-card, .ticket-manage-form, .ticket-panel-scroll {
  scrollbar-width: thin;
  scrollbar-color: transparent transparent;
}
.modal-card:hover, .ticket-manage-form:hover, .ticket-panel-scroll:hover {
  scrollbar-color: var(--control-border) transparent;
}
.modal-card::-webkit-scrollbar,
.ticket-manage-form::-webkit-scrollbar,
.ticket-panel-scroll::-webkit-scrollbar { width: 10px; }
.modal-card::-webkit-scrollbar-thumb,
.ticket-manage-form::-webkit-scrollbar-thumb,
.ticket-panel-scroll::-webkit-scrollbar-thumb {
  background: transparent;
  border: 3px solid transparent;
  background-clip: padding-box;
  border-radius: 8px;
  transition: background-color 0.2s ease;
}
.modal-card:hover::-webkit-scrollbar-thumb,
.ticket-manage-form:hover::-webkit-scrollbar-thumb,
.ticket-panel-scroll:hover::-webkit-scrollbar-thumb {
  background: var(--control-border);
  background-clip: padding-box;
}
/* Selects dentro del popover de filtros (compartido contactos/tickets) */
.contacts-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);
  cursor: pointer;
}
.contacts-filters-popover select:focus { outline: none; border-color: var(--brand); }
.contacts-filters-popover .ticket-daterange { flex-wrap: wrap; }
/* Inputs de texto dentro del popover (Monitor filtra por User ID ahí). */
.contacts-filters-popover input[type="text"] {
  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 input[type="text"]:focus { outline: none; border-color: var(--brand); }

/* Dropdown Exportar (CSV / Excel) */
.tickets-export { position: relative; }
.btn-export-main {
  padding: 8px 14px;
  border: 1px solid var(--control-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: background 0.15s, border-color 0.15s;
}
.btn-export-main:hover:not(:disabled) { background: var(--control-bg-hover); border-color: var(--brand); }
.btn-export-main:disabled { opacity: 0.55; cursor: not-allowed; }
.tickets-export-menu {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 42;
  min-width: 140px;
  display: flex;
  flex-direction: column;
  padding: 5px;
  background: var(--surface-overlay);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--shadow-md);
}
.tickets-export-menu button {
  text-align: left;
  padding: 8px 12px;
  border: none;
  border-radius: 7px;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 0.85rem;
  cursor: pointer;
}
.tickets-export-menu button:hover { background: var(--control-bg-hover); }

/* Cards de resumen clickeables: elevación leve + cursor pointer */
.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.is-active { box-shadow: 0 0 0 2px var(--brand); }

/* Modal de confirmación de export */
.export-confirm-body { padding: 18px 20px; color: var(--text); font-size: 0.9rem; }

/* ── Form de nuevo ticket: canal Otro, picker de contacto, uploader ───────── */
.channel-other-input { margin-top: 8px; }

/* Picker de contacto (paginado + búsqueda) */
.ticket-contact-picker { position: relative; display: flex; gap: 8px; align-items: stretch; }
.ticket-contact-userid { flex: 1 1 auto; }
.ticket-contact-search-btn {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px;
  white-space: nowrap;
}
.ticket-picker-backdrop {
  position: fixed; inset: 0; z-index: 40; background: transparent;
}
.ticket-picker-pop {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 41;
  background: var(--surface-overlay); border: 1px solid var(--border);
  border-radius: 10px; box-shadow: var(--shadow-md);
  display: flex; flex-direction: column; overflow: hidden;
}
.ticket-picker-search {
  margin: 8px; width: calc(100% - 16px);
}
.ticket-picker-list {
  max-height: 240px; overflow-y: auto; display: flex; flex-direction: column;
  padding: 4px; gap: 2px;
  /* barra de scroll estilo sidebar (auto-oculta) */
  scrollbar-width: thin; scrollbar-color: transparent transparent;
}
.ticket-picker-list:hover { scrollbar-color: var(--control-border) transparent; }
.ticket-picker-list::-webkit-scrollbar { width: 8px; }
.ticket-picker-list::-webkit-scrollbar-thumb {
  background: transparent; border: 2px solid transparent; background-clip: padding-box;
  border-radius: 8px;
}
.ticket-picker-list:hover::-webkit-scrollbar-thumb { background: var(--control-border); background-clip: padding-box; }
.ticket-picker-item {
  display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
  padding: 8px 10px; border: none; border-radius: 7px; background: transparent;
  color: var(--text); text-align: left; cursor: pointer; width: 100%;
  transition: background 0.12s ease;
}
.ticket-picker-item:hover { background: var(--control-bg-hover); }
.ticket-picker-item-name { font-weight: 600; font-size: 0.88rem; }
.ticket-picker-item-sub { font-size: 0.76rem; color: var(--muted); }
.ticket-picker-empty, .ticket-picker-loading {
  padding: 14px; text-align: center; color: var(--muted); font-size: 0.82rem;
}

/* Uploader de evidencias + chips */
.evidence-uploader { display: flex; gap: 10px; align-items: stretch; flex-wrap: wrap; }
.evidence-upload-btn {
  display: inline-flex; align-items: center; gap: 6px; cursor: pointer;
  padding: 8px 14px; border-radius: 8px; border: 1px solid var(--control-border);
  background: var(--control-bg); color: var(--text); font-size: 0.85rem;
  white-space: nowrap; transition: background 0.12s ease;
}
.evidence-upload-btn:hover { background: var(--control-bg-hover); }
.evidence-upload-btn.is-busy { opacity: 0.6; pointer-events: none; }
.evidence-url-row { display: flex; gap: 8px; flex: 1 1 240px; }
.evidence-url-input { flex: 1 1 auto; }
.evidence-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.evidence-chip {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%;
  padding: 4px 6px 4px 10px; border-radius: 999px;
  background: var(--surface-2); border: 1px solid var(--border);
  font-size: 0.8rem; color: var(--text);
}
.evidence-chip-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.evidence-chip-x {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border: none; border-radius: 50%;
  background: transparent; color: var(--muted); cursor: pointer; font-size: 1rem;
  line-height: 1; transition: background 0.12s ease, color 0.12s ease;
}
.evidence-chip-x:hover { background: var(--badge-danger-bg); color: var(--badge-danger-fg); }

/* Limpiar filtros en la toolbar de contactos */
.contacts-toolbar-right { display: flex; align-items: center; gap: 10px; }

.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 ───────────────────────────── */

/* ── SEGMENTED CONTROL ESTÁNDAR ───────────────────────────────────────────────
   UN solo dialecto de barra de tabs para todo el panel. El de Tickets es el
   canónico; el resto de módulos se cuelga de estas mismas reglas en vez de
   inventar tamaños/colores propios.

   Para sumar una barra nueva: añade su clase de contenedor a las tres listas de
   abajo, a la lista `SEL` del script del pill en index.html, y a los grupos de
   `html.light-mode` (buscar "SEGMENTED"). No dupliques declaraciones.

   El resaltado del tab activo lo pinta el pill deslizante (.slide-tabs::after),
   que anula el `background` del botón activo — el `background` de aquí es solo
   el fallback de si el script no ha corrido todavía. */
.ticket-tabs,
.camp-tabs,
.metrics-tabs,
.metrics-agent-tabs,
.notif-tabs,
.mir-tabs {
  display: flex;
  gap: 3px;
  margin-bottom: 20px;
  background: var(--surface-2);
  border-radius: 999px;                        /* pill moderno (como el buscador) */
  padding: 5px;
  width: fit-content;
  max-width: 100%;
  overflow-x: auto;
}

.ticket-tabs button,
.camp-tab,
.metrics-tab,
.metrics-subtab,
.notif-tabs button,
.mir-tab {
  appearance: none;
  border: 0;
  border-radius: 999px;                        /* pill moderno */
  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,
.camp-tab:not(.camp-tab--active):hover,
.metrics-tab:not(.active):hover,
.metrics-subtab:not(.active):hover,
.notif-tabs button:not(.active):hover,
.mir-tab:not(.active):hover {
  background: var(--control-bg-hover);
  color: var(--text);
}

.ticket-tabs button.active,
.camp-tab--active,
.metrics-tab.active,
.metrics-subtab.active,
.notif-tabs button.active,
.mir-tab.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;
}
/* datetime-local además de date: Monitor filtra ejecuciones con hora. */
.ticket-daterange input[type="date"],
.ticket-daterange input[type="datetime-local"] {
  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);
  min-width: 0;
}
.ticket-daterange input[type="date"]:focus,
.ticket-daterange input[type="datetime-local"]: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. El clamp va en un SPAN interno para que el
   <td> siga siendo table-cell y `vertical-align: middle` centre el texto (con el
   clamp en el td, `display:-webkit-box` rompía el centrado → texto "levantado"). */
.tickets-table td.tk-subject { white-space: normal; }
.tickets-table td.tk-subject .tk-subject-txt {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* CREADO: fecha+hora en una sola línea */
.tickets-table td.ticket-created { white-space: nowrap; font-size: 0.8rem; color: var(--muted-2); }
/* Paginación de la bandeja: layout en el bloque canónico (buscar "PAGINACIÓN
   ESTÁNDAR"). Aquí solo la agrupación de los controles. */
.ticket-pagination-controls { display: flex; align-items: center; gap: 12px; }

.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; }
.ticket-reassign-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.ticket-reassign-select {
  flex: 1 1 220px;
  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 { flex: 0 0 auto; }
.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-dark);
  border-color: var(--brand-dark);
  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, var(--panel-2) 0%, var(--surface-3) 100%);
  color: var(--text-strong);
  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);
}

/* ── 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: var(--text-strong);
  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: var(--brand-dark);
}

.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);
}

/* Acciones de fila: ver .pg-actions / .pg-btn (patrón único del panel). */

/* ── 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) */
/* Las sub-tags del monitor interno usan el nivel 2 canónico (.cc-subtabs); el
   estilo propio que había aquí se eliminó. */

/* ── Monitor interno: la toolbar es la estándar (.tickets-toolbar); esta clase
   solo queda para ajustar la posición del popover de filtros. ── */
.monitor-toolbar { margin-bottom: 14px; }
.monitor-toolbar .tickets-filters-popover { top: 44px; left: 0; }

/* ── Monitor interno: grilla de cards con minitabla ── */
.interno-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 360px));
  justify-content: start;
  gap: 16px;
  align-items: start;
}
.interno-card {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 14px 16px 12px;
  cursor: pointer;
  transition: border-color 0.15s, box-shadow 0.15s;
}
/* OJO: NADA de `transform` en la card. Un transform crea containing block para los
   descendientes `position: fixed` → el backdrop del dropdown de Exportar (fixed, vive
   dentro de la card) dejaba de cubrir el viewport al hacer hover, el cursor salía de la
   card, se quitaba el hover, el backdrop volvía a cubrir todo… bucle infinito de cursor. */
.interno-card:hover {
  border-color: var(--brand);
  box-shadow: var(--shadow-md);
}
/* 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; }
.interno-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 10px;
}
.interno-card-head h3 { margin: 0; font-size: 0.92rem; color: var(--text-strong); }

/* Minitabla dentro de la card: compacta, sin scroll horizontal. */
.interno-mini { table-layout: fixed; width: 100%; font-size: 0.8rem; }
.interno-mini th {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--muted);
  padding: 4px 8px;
}
.interno-mini td {
  padding: 5px 8px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.interno-mini-empty { text-align: center; color: var(--muted); padding: 12px 8px; }
.interno-card-foot {
  margin-top: 10px;
  text-align: right;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--brand);
}

/* Cabecera de la tabla-detalle (al abrir una card): volver · título · Exportar. */
.interno-full-head {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 10px;
}
.interno-full-head h3 { margin: 0; font-size: 0.98rem; color: var(--text-strong); flex: 1; }
.interno-back {
  appearance: none;
  border: 1px solid var(--control-border);
  background: var(--control-bg);
  color: var(--text);
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  padding: 6px 12px;
  border-radius: 8px;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.15s, border-color 0.15s;
}
.interno-back:hover { background: var(--control-bg-hover); border-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: rgba(15,23,42,0.10);
  color: var(--text);
}

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

/* Row highlight when editing */
tr.row-editing {
  background: rgba(var(--brand-rgb),0.04);
  outline: 2px solid rgba(var(--brand-rgb),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); }

/* ── 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 ---- */
.app-header {
  background: var(--nav-bg);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
  border-bottom: 1px solid var(--nav-border);
  padding: 0 28px;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: sticky;
  top: 0;
  z-index: 100;
}

/* Subtle gradient accent line at bottom */
.app-header::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(var(--brand-rgb), 0.35) 25%,
    rgba(var(--brand-rgb), 0.5) 50%,
    rgba(var(--brand-rgb), 0.35) 75%,
    transparent 100%
  );
  pointer-events: none;
}

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

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

.app-title {
  font-size: 0.9375rem;
  font-weight: 700;
  color: var(--text-strong);
  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: var(--nav-bg-2);
  border-right: 1px solid var(--nav-border);
  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, var(--brand) 0%, var(--brand-dark) 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: var(--text);
  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: var(--brand-soft-fg);
}

.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;
}
/* Centro de Control: el main NO debe scrollear por dentro. Con .home-container
   (min-height:100vh) anidado en el shell (~100vh), el overflow-y:auto del main
   creaba un SEGUNDO scroll vertical junto al del body (doble barra que estorbaba
   al desplazarse). Dejamos que scrollee solo la página. */
.app-main.control-main { overflow: visible; }

.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;
}

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

/* ---- Banner de la portada ----
   Hermano del grid de módulos dentro de `.app-main`, así que ocupa el MISMO
   ancho sin márgenes negativos ni contenedor propio: si mañana cambia el
   padding del main, banner y módulos se mueven juntos.

   El arte de fábrica se dibuja con gradientes sobre los tokens de marca: pesa
   0 bytes, sigue al tema activo (y al modo claro/oscuro) y no obliga a tener
   dos imágenes. La imagen subida es la excepción, no la norma. */
.home-banner {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  margin-bottom: 24px;
  height: var(--hb-h);
  background-color: var(--surface-2);
  border: 1px solid var(--border-soft);
}

/* La altura va por variable, no por `height` directo, porque el modo con la
   cabecera dentro necesita el MISMO valor como mínimo y no como fijo: si el
   saludo y el buscador no caben, el banner crece en vez de recortarlos. */
.hb--h-compacto { --hb-h: clamp(64px, 7vw, 92px); }
.hb--h-normal   { --hb-h: clamp(84px, 9.5vw, 126px); }
.hb--h-alto     { --hb-h: clamp(104px, 12vw, 160px); }

/* ---- Cabecera dentro del banner ---- */
/* La cabecera dentro NO cambia la altura del banner: la altura sigue siendo la
   elegida y el contenido se coloca encima en posición absoluta. Con una rejilla
   de tres filas, las dos vacías sumaban su alto y el banner crecía solo. */
.home-banner--overlay { height: var(--hb-h); }

/* Degradado de apoyo: sobre una foto clara el texto blanco desaparece, y no se
   puede depender del oscurecimiento (es una decisión estética aparte, 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;
}

/* Las 9 celdas se resuelven con posición absoluta dentro del área útil del
   banner, no con una rejilla: una rejilla de tres filas reserva alto para las
   dos que están vacías y hacía crecer el banner por encima de la altura
   elegida. Aquí el contenido flota y la altura no se toca. */
.hb-content {
  position: absolute;
  inset: clamp(14px, 2vw, 22px) clamp(16px, 2.4vw, 26px);
  z-index: 1;
  pointer-events: none;
}

/* El contenedor deja pasar el ratón (es un marco vacío en su mayor parte); las
   piezas colocadas sí lo reciben, o el buscador no se podría ni pulsar. */
/* Cada pieza se queda dentro de SU tercio. La config ya obliga a que el saludo
   y el buscador estén en columnas distintas, y este tope es lo que convierte esa
   regla en geometría: sin él el saludo mide lo que mida su texto, cruza el
   centro y se come el buscador aunque estén en celdas diferentes. */
.hb-slot {
  position: absolute;
  max-width: calc(33.333% - 10px);
  pointer-events: auto;
}

.hb-slot .home-search { width: 100%; }

/* Dentro del banner el saludo baja de cuerpo: a 30 px no cabe en un tercio y
   saldría cortado siempre. Fuera del banner conserva su tamaño. */
.home-banner--overlay .home-welcome-title {
  font-size: clamp(1.05rem, 1.9vw, 1.45rem);
  margin-bottom: 2px;
}

.home-banner--overlay .home-welcome-sub { font-size: 0.8125rem; }

/* En compacto solo cabe una línea: el subtítulo se retira antes que desbordar. */
.hb--h-compacto.home-banner--overlay .home-welcome-sub { display: none; }

/* El texto que no cabe en su tercio se corta: el banner tiene una altura fija
   elegida por el usuario, así que envolver en dos líneas lo desbordaría. */
.home-banner--overlay .home-welcome-title,
.home-banner--overlay .home-welcome-sub {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.hb-at--arriba-izq     { top: 0; left: 0; }
.hb-at--arriba-centro  { top: 0; left: 50%; transform: translateX(-50%); }
.hb-at--arriba-der     { top: 0; right: 0; }
.hb-at--medio-izq      { top: 50%; left: 0; transform: translateY(-50%); }
.hb-at--medio-centro   { top: 50%; left: 50%; transform: translate(-50%, -50%); }
.hb-at--medio-der      { top: 50%; right: 0; transform: translateY(-50%); }
.hb-at--abajo-izq      { bottom: 0; left: 0; }
.hb-at--abajo-centro   { bottom: 0; left: 50%; transform: translateX(-50%); }
.hb-at--abajo-der      { bottom: 0; right: 0; }

/* El texto se alinea con su columna: un saludo a la derecha con el texto
   alineado a la izquierda se lee torcido. */
.hb-slot[class*="-centro"] { text-align: center; }
.hb-slot[class*="-der"]    { text-align: right; }

.home-banner--overlay .home-topline { margin-bottom: 0; }

.home-banner--overlay .home-welcome-title,
.home-banner--overlay .home-welcome-sub {
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}

.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(6px);
}

.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.24);
  border-color: #fff;
  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;
}

/* Formas. Arco y cinta son el MISMO radio elíptico invertido: curvan un borde
   largo sin recortar con máscara (una máscara obliga a un SVG externo y rompe
   el borde). */
.hb--recto       { border-radius: 0; }
.hb--redondeado  { border-radius: 20px; }
.hb--pastilla    { border-radius: 999px; }
.hb--arco        { border-radius: 20px 20px 46% 46% / 20px 20px 22% 22%; }
.hb--cinta       { border-radius: 46% 46% 20px 20px / 22% 22% 20px 20px; }

/* `pointer-events:none` + `user-drag:none`: sin esto el navegador arranca SU
   arrastre de imagen (el fantasma semitransparente) en cuanto se pulsa sobre la
   foto, se queda el gesto y el encuadre no se podía mover. La imagen es
   decorativa, así que no pierde nada al no recibir eventos. */
.hb-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
}

/* El velo es una capa aparte del fondo: así el mismo control de oscurecimiento
   sirve tanto a los dibujos como a la imagen subida. */
.hb-veil {
  position: absolute;
  inset: 0;
  background: #000;
  opacity: var(--hb-dim, 0);
  pointer-events: none;
}

.hb-art { background-color: var(--brand-dark); }

/* Nota de sintaxis (bug 2026-07-30): estos gradientes llevan SIEMPRE la palabra
   `ellipse`/`circle` delante del tamaño. La forma abreviada `radial-gradient(120%
   140% at …)` es válida en la especificación pero el pipeline de build la
   descarta, y descartar UNA capa invalida la declaración entera: los cuatro
   fondos que la usaban se veían como un plano de color, indistinguibles entre
   sí. `conic-gradient` corrió la misma suerte (no aparece en ningún otro sitio
   del archivo). El resto del CSS ya usaba la forma larga; aquí también. */
.hb-art--aurora {
  background-image:
    radial-gradient(ellipse 75% 130% at 8% -15%, rgba(255, 255, 255, 0.45) 0%, transparent 62%),
    radial-gradient(ellipse 85% 130% at 95% 115%, rgba(var(--brand-rgb), 0.95) 0%, transparent 64%),
    linear-gradient(115deg, var(--brand-dark) 0%, var(--brand) 100%);
}

/* Malla = rejilla romboidal: dos juegos de líneas finas cruzadas. Antes eran
   manchas difusas y no se distinguía de «aurora» — el nombre prometía una
   retícula y el dibujo no la tenía. */
/* Mismo motivo que en «rayos» para el `background-size`: las dos capas repetidas
   se acotan a un periodo. A 45° el paso de 16px se ve como 16·√2 = 22.63px tanto
   en horizontal como en vertical. */
.hb-art--malla {
  background-image:
    repeating-linear-gradient(45deg, rgba(255, 255, 255, 0.17) 0 1px, transparent 1px 16px),
    repeating-linear-gradient(-45deg, rgba(255, 255, 255, 0.17) 0 1px, transparent 1px 16px),
    radial-gradient(ellipse 90% 150% at 84% 6%, rgba(255, 255, 255, 0.3) 0%, transparent 62%),
    linear-gradient(100deg, var(--brand-dark), var(--brand));
  background-size: 22.63px 22.63px, 22.63px 22.63px, cover, cover;
}

/* Trama = semitono: dos rejillas de puntos de distinto calibre y paso, para que
   se lea como un degradado de grano y no como un patrón plano. */
.hb-art--trama {
  background-image:
    radial-gradient(circle, rgba(255, 255, 255, 0.34) 1.6px, transparent 1.8px),
    radial-gradient(circle, rgba(255, 255, 255, 0.13) 3px, transparent 3.2px),
    linear-gradient(120deg, var(--brand-dark), var(--brand));
  background-size: 14px 14px, 42px 42px, cover;
}

.hb-art--olas {
  background-image:
    radial-gradient(ellipse 140% 85% at 50% 168%, rgba(255, 255, 255, 0.34) 0 40%, transparent 41%),
    radial-gradient(ellipse 152% 92% at 50% 186%, rgba(255, 255, 255, 0.26) 0 40%, transparent 41%),
    radial-gradient(ellipse 168% 102% at 50% 206%, rgba(255, 255, 255, 0.18) 0 40%, transparent 41%),
    linear-gradient(160deg, var(--brand), var(--brand-dark));
}

/* Rayos con franjas repetidas en diagonal en vez de un `conic-gradient`: el
   abanico exacto no compensa depender de una función que el build tira. */
/* `background-size` OBLIGATORIO en las capas repetidas, y con estos números
   exactos (bug 2026-07-31: al animarlo salían franjas de anchos distintos y una
   cuña clara a un lado). Sin tamaño, la capa mide lo que mida el banner: al
   correr `background-position` el navegador repite ESE mosaico —del tamaño del
   elemento— y el patrón arranca de nuevo en un punto que no encaja con el
   anterior, así que la costura queda a la vista y además se desplaza.
   Con el mosaico acotado a UN periodo del patrón la repetición es exacta.
   Periodo del dibujo: 74px medidos perpendiculares a las franjas. A 72°,
   74/sin72 = 77.8px en horizontal y 74/cos72 = 239.5px en vertical. */
.hb-art--rayos {
  background-image:
    repeating-linear-gradient(72deg,
      rgba(255, 255, 255, 0.22) 0 9px, transparent 9px 30px,
      rgba(255, 255, 255, 0.12) 30px 37px, transparent 37px 74px),
    radial-gradient(ellipse 95% 150% at 6% 118%, rgba(255, 255, 255, 0.32) 0%, transparent 60%),
    linear-gradient(105deg, var(--brand-dark), var(--brand));
  background-size: 77.8px 239.5px, cover, cover;
}

.hb-art--circuito {
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.14) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.14) 1px, transparent 1px),
    radial-gradient(rgba(255, 255, 255, 0.5) 2px, transparent 2.2px),
    linear-gradient(135deg, var(--brand-dark), var(--brand));
  background-size: 26px 26px, 26px 26px, 78px 78px, cover;
}

/* Topografía = campo de puntos con relieve. Aquí solo va el COLOR; los puntos
   los dibuja un <canvas> (`components/dot_field.rs`), porque cada punto se
   desplaza por su cuenta y eso ningún degradado lo hace. El lienzo pinta en
   blanco con poca alfa, así que el tono sale de estos tokens y el fondo sigue
   al tema sin que el canvas sepa de colores. */
.hb-art--topografia {
  background-image:
    radial-gradient(ellipse 110% 150% at 50% -30%, rgba(255, 255, 255, 0.12) 0%, transparent 62%),
    linear-gradient(165deg, var(--brand-dark) 0%, var(--brand) 135%);
}

/* Constelación: puntos sueltos unidos por una línea cuando se acercan. También
   es lienzo, y por el mismo motivo — cada punto lleva su propia trayectoria. El
   fondo es más frío y plano que el de topografía: las líneas son finas y sobre
   un degradado con mucho contraste se pierden. */
.hb-art--constelacion {
  background-image:
    radial-gradient(ellipse 90% 130% at 88% 8%, rgba(255, 255, 255, 0.10) 0%, transparent 58%),
    linear-gradient(135deg, var(--brand-dark) 0%, var(--brand) 150%);
}

/* El lienzo va DEBAJO del velo y del contenido: es el primer hijo del banner y
   no lleva z-index, así que el orden del documento ya lo coloca. */
.hb-dots {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  pointer-events: none;
}

/* La muestra del desplegable no monta un canvas (habría uno por fila): imita el
   campo con dos rejillas de puntos desfasadas. Es la única regla que dibuja
   puntos en CSS, y por eso está acotada a `.idv-opt-swatch`. */
.idv-opt-swatch.hb-art--topografia {
  background-image:
    radial-gradient(circle, rgba(255, 255, 255, 0.35) 0.9px, transparent 1.1px),
    radial-gradient(circle, rgba(255, 255, 255, 0.18) 0.9px, transparent 1.1px),
    linear-gradient(165deg, var(--brand-dark) 0%, var(--brand) 135%);
  background-size: 5px 4px, 5px 4px, cover;
  background-position: 0 0, 2px 2px, 0 0;
}

/* Misma idea para la constelación: puntos más separados y grandes. Las líneas no
   se imitan —en 44×20 px serían un borrón— así que la muestra dice «puntos
   sueltos», que es la mitad honesta del dibujo. */
.idv-opt-swatch.hb-art--constelacion {
  background-image:
    radial-gradient(circle, rgba(255, 255, 255, 0.5) 1.1px, transparent 1.4px),
    linear-gradient(135deg, var(--brand-dark) 0%, var(--brand) 150%);
  background-size: 11px 9px, cover;
}

/* ---- Movimiento (opcional, `animated`) ----
   Se anima SIEMPRE `background-position`, nunca un elemento: el banner puede
   ocupar el ancho de la portada y mover una capa pintada es lo único que el
   compositor resuelve sin repintar la franja entera en cada fotograma.
   Cada arte lleva su propio `@keyframes` porque `background-position` es una
   lista por capa: un desplazamiento genérico movería también el degradado de
   base y el fondo entero se vería «temblar». Los desplazamientos son múltiplos
   exactos del mosaico, así que el bucle no da saltos. */
.hb-anim.hb-art--aurora {
  background-size: 180% 180%, 180% 180%, cover;
  animation: hb-anim-aurora calc(24s / var(--hb-spd, 1)) ease-in-out infinite alternate;
}

@keyframes hb-anim-aurora {
  from { background-position: 0% 50%, 100% 50%, 0 0; }
  to   { background-position: 65% 15%, 35% 85%, 0 0; }
}

.hb-anim.hb-art--malla { animation: hb-anim-malla calc(14s / var(--hb-spd, 1)) linear infinite; }

/* 22.63px = 16 × √2: el paso real del mosaico medido en horizontal cuando las
   líneas van a 45°. Con un número redondo el ciclo saltaría al reiniciarse. */
@keyframes hb-anim-malla {
  from { background-position: 0 0, 0 0, 0 0, 0 0; }
  to   { background-position: 22.63px 0, -22.63px 0, 0 0, 0 0; }
}

.hb-anim.hb-art--trama { animation: hb-anim-trama calc(18s / var(--hb-spd, 1)) linear infinite; }

@keyframes hb-anim-trama {
  from { background-position: 0 0, 0 0, 0 0; }
  to   { background-position: 14px 28px, -42px 42px, 0 0; }
}

.hb-anim.hb-art--olas {
  background-size: 200% 100%, 220% 100%, 240% 100%, cover;
  animation: hb-anim-olas calc(20s / var(--hb-spd, 1)) ease-in-out infinite alternate;
}

@keyframes hb-anim-olas {
  from { background-position: 0% 100%, 0% 100%, 0% 100%, 0 0; }
  to   { background-position: 100% 100%, 100% 100%, 100% 100%, 0 0; }
}

.hb-anim.hb-art--rayos { animation: hb-anim-rayos calc(16s / var(--hb-spd, 1)) linear infinite; }

/* El haz avanza siguiendo su propia dirección (72°), no en horizontal: cruzarlo
   en recto haría que las franjas parecieran deslizarse de lado. */
@keyframes hb-anim-rayos {
  from { background-position: 0 0, 0 0, 0 0; }
  to   { background-position: 70.4px -22.9px, 0 0, 0 0; }
}

.hb-anim.hb-art--circuito { animation: hb-anim-circuito calc(20s / var(--hb-spd, 1)) linear infinite; }

@keyframes hb-anim-circuito {
  from { background-position: 0 0, 0 0, 0 0, 0 0; }
  to   { background-position: 0 26px, 26px 0, 78px 78px, 0 0; }
}

/* Quien pide menos movimiento en el sistema lo pide para todo: el ajuste del
   panel no debe poder pasar por encima. */
@media (prefers-reduced-motion: reduce) {
  .hb-anim { animation: none !important; }
}

/* ---- Saludo + buscador (misma línea) ---- */
.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 también el saludo, el
   buscador quedaría descolgado respecto al título. */
.home-topline .home-welcome { margin-bottom: 0; }

/* Misma forma de píldora y misma lupa a la derecha que el buscador de todos los
   listados (`.contacts-search-input`). Aquí la lupa es un elemento y no una
   `background-image`: así un iconset puede sustituirla (`ui.search`), que en el
   canónico no se puede. */
.home-search {
  position: relative;
  display: flex;
  align-items: center;
  flex: 0 1 380px;
  min-width: 260px;
}

/* `z-index` obligatorio (bug 2026-07-31: la lupa desapareció DENTRO del banner y
   solo ahí). Ahí el input lleva `backdrop-filter`, y un elemento con filtro crea
   contexto de apilamiento y se pinta como si fuera `z-index:0` aunque no esté
   posicionado; como va DESPUÉS en el documento, tapaba a la lupa. Fuera del
   banner no hay filtro, el input no se promociona y la lupa se veía — de ahí que
   pareciera un fallo del icono y no del apilamiento. */
.home-search-ico {
  position: absolute;
  right: 14px;
  z-index: 1;
  display: flex;
  color: var(--muted-2);
  pointer-events: none;
}

/* El tamaño se fija aquí, no solo en el `width`/`height` del SVG de fábrica: un
   iconset del Marketplace puede sustituir `ui.search` por un SVG sin medidas, y
   un SVG sin tamaño dentro de un contenedor absoluto cae al default del
   navegador (300×150 px), que taparía el buscador entero. */
.home-search-ico svg {
  width: 16px;
  height: 16px;
  display: block;
}

/* Con texto escrito, la lupa deja el sitio a la ×: comparten esquina y de otro
   modo se pisarían. */
.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);
}

/* Mismo `z-index` que la lupa, y por el mismo motivo: el input con
   `backdrop-filter` se pinta encima de lo que va antes en el documento. */
.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);
}

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

.home-welcome-title {
  font-size: 1.875rem;
  font-weight: 800;
  color: var(--text-strong);
  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 ---- */
/* Cabecera de la rejilla: título + controles de orden y vista, con los mismos
   botones-icono (`.contacts-refresh-btn`) y el mismo desplegable (`.tb-menu-pop`)
   que la toolbar estándar de los listados. */
.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;
}

/* El menú de vistas lleva glifo + etiqueta, así que necesita más ancho que el
   de ordenar, que es solo texto. */
.tb-menu-pop--wide { min-width: 232px; }

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

/* Las filas del menú de vistas llevan glifo delante, así que dejan de ser
   `display:block` para poder alinearlo con la etiqueta. */
.tb-menu-pop--wide .tb-menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
}

.tb-menu-ico {
  display: inline-flex;
  align-items: center;
  color: var(--muted);
  flex: none;
}

.tb-menu-item.is-active .tb-menu-ico { color: inherit; }

.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);
}

.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 markup 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í muestran. */
.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 sin llegar al scroll. */
.mg--m .mod-desc { padding: 10px 12px 12px; font-size: 0.72rem; line-height: 1.38; }

/* Las cuatro vistas en fila comparten esqueleto: icono a la izquierda, texto a
   la derecha, sin el salto de la tarjeta 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 muestran el nombre: es el punto de esas 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;
  /* En línea el texto manda: sin tope de alto ni scroll propio. */
  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 markup (icono · nombre · badge · descripción)
   colocando el bloque de texto con grid en vez de envolverlo en otro div, que
   obligaría a un markup 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;
  background: rgba(255, 255, 255, 0.04);
  border-radius: 20px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  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);
  /* Badge SÓLIDO de marca (sigue el tema en claro y oscuro): un icono de iconset
     (monocromo, currentColor) se pinta blanco legible sobre el badge; los emoji
     multicolor del fallback lo ignoran. */
  color: #fff;
}
/* Un iconset provee un SVG monocromo → tamaño acorde al badge (el emoji se
   dimensiona 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);
  text-align: center;
  line-height: 1.35;
}

.maint-badge {
  font-size: 0.6875rem;
  font-weight: 600;
  color: #b45309;
  background: rgba(245, 158, 11, 0.08);
  border: 1px solid rgba(245, 158, 11, 0.22);
  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;
  /* El panel nunca puede pasar del alto de la tarjeta: `overflow: hidden` de
     .mod-card recortaría el texto contra el borde superior. Se topa al 100% y,
     si la descripción no cabe (tarjetas estrechas, textos largos), scrollea. */
  box-sizing: border-box;
  max-height: 100%;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  background: linear-gradient(160deg, var(--brand-dark) 0%, var(--brand-dark) 100%);
  color: rgba(255, 255, 255, 0.92);
  font-size: 0.775rem;
  font-weight: 400;
  line-height: 1.55;
  text-align: center;
  /* +2px extra para que el borde superior del panel no asome como una línea
     azul en el fondo de la card cuando está oculto (subpixel rounding). */
  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, var(--bg) 0%, var(--panel-2) 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: var(--muted);
  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: var(--text-strong);
}

.page-header h1 {
  font-size: 1rem;
  font-weight: 700;
  color: var(--text-strong);
}

.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(var(--brand-rgb),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-dark); }
.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(var(--brand-rgb),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 / .page-info se retiraron con el pager viejo de Contactos: ahora
   usa el bloque canónico (buscar "PAGINACIÓN ESTÁNDAR"). */

/* ---- 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, var(--brand-dark) 0%, var(--brand) 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
   ============================================================ */

/* Cabecera de cada pestaña de Usuarios: solo el título con su tooltip. La
   toolbar de verdad (.tickets-toolbar) va justo debajo, y este margen es el
   aire que las separa — no lo pises con un style inline. */
.users-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 18px;
}

/* Un solo envoltorio con el padding del modal de Departamentos. Sin él, cada
   bloque es hijo directo de .modal-card, hereda `padding: 0 24px` y pierde su
   propio padding vertical → todo pegado a los bordes. */
.dept-modal-body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-bottom: 4px;
}

/* Fila "¿Eliminar?" dentro de una celda de acciones. */
.pg-actions-ask { font-size: 0.8rem; color: var(--muted); }
/* Marcador de "sin acciones disponibles" en una fila. */
.pg-actions-empty { color: var(--muted-2); }

/* .users-filterbar / .users-filter-* se retiraron: el módulo usa la toolbar
   estándar y el alta de departamentos vive en su propio modal con .form-field. */

.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 */
.badge {
  display: inline-flex;
  align-items: center;
  padding: 3px 9px;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 600;
}

.badge-active  { background: rgba(16,185,129,0.12); color: #059669; }
.badge-blocked { background: rgba(239,68,68,0.12);  color: #dc2626; }
.badge-warn    { background: rgba(245,158,11,0.15); color: #b45309; }

.badge-role        { border-radius: 6px; }
.badge-owner       { background: rgba(139,92,246,0.12); color: #7c3aed; }
.badge-supervisor  { background: rgba(59,130,246,0.12);  color: #1d4ed8; }
.badge-operator    { background: rgba(16,185,129,0.12);  color: #059669; }
.badge-marketing   { background: rgba(245,158,11,0.12);  color: #b45309; }
.badge-guest       { background: rgba(148,163,184,0.2);  color: var(--muted); }

/* 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;
}
/* Estado deshabilitado base: sin esto, un `.btn-action` con `disabled` (p. ej. el
   "Siguiente →" de un wizard con validación pendiente) se veía plenamente clicable.
   Los modificadores que ya definen su propio `:disabled` (--send, --danger, …) ganan
   por venir después en la cascada; esto solo cubre los que no lo tenían. */
.btn-action:disabled { opacity: 0.5; cursor: not-allowed; }

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

/* .btn-invite se retiró: en la toolbar de Usuarios las acciones secundarias
   usan .btn-secondary, como en Tickets. */

.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 / .btn-unblock / .btn-perms se retiraron: las acciones de fila de
   Usuarios usan .pg-btn, neutro salvo lo destructivo. */

.btn-delete  { background: rgba(239,68,68,0.08); color: #dc2626; border-color: rgba(239,68,68,0.2); 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(var(--brand-rgb),0.08); color: var(--brand); border-color: rgba(var(--brand-rgb),0.2); }
.btn-view:hover { background: rgba(var(--brand-rgb),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; }
/* La tarjeta no tiene padding horizontal (0 en los lados) para que el scroll del
   body llegue al borde; cada hijo directo (cabecera y cuerpo) pone su propio
   padding lateral para no chocar con los bordes del modal (#5/#10). */
.modal-card.survey-res > div:not(.modal-header):not(.modal-footer) { padding-left: 22px; padding-right: 22px; }
.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-pill--ok   { background: rgba(16,185,129,0.12); color: #059669; }
.survey-res-pill--warn { background: rgba(245,158,11,0.14); color: #b45309; }

.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; }

.app-header h1 {
  font-size: 1.0625rem;
  font-weight: 700;
  color: var(--text-strong);
  letter-spacing: -0.01em;
}

.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: var(--text-strong); 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 / .perms-filter-* se retiraron: las pestañas de permisos y el
   modal de overrides usan la toolbar estándar (ver `perms_toolbar`). */

.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(var(--brand-rgb),0.14); color: var(--brand-soft-fg); }
.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: var(--muted); }

.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
   ============================================================ */

/* El segmented NO envuelve: si las pestañas superan el ancho, se hace scroll
   horizontal dentro de la barra (rueda con Shift o arrastre táctil, pero también
   con la propia barra de scroll — no todo el mundo conoce Shift+rueda). La barra
   es no invasiva estilo sidebar: carril propio abajo, transparente hasta hover. */
.control-tabs {
  display: flex;
  flex-wrap: nowrap;
  gap: 3px;
  margin-bottom: 28px;
  overflow-x: auto;
  overflow-y: hidden;
  background: var(--surface-2);
  border-radius: 999px;                        /* pill moderno */
  padding: 5px;
  width: 100%;
  max-width: 100%;
  /* Scrollbar OCULTO: un carril de scroll dentro de un pill segmentado redondeado
     se ve raro y reservaba un espacio fantasma arriba aunque el thumb estuviera
     invisible. La barra sigue siendo scrolleable con rueda/trackpad/drag; sin
     carril reservado = look limpio del pill en todo momento. */
  scrollbar-width: none;                       /* Firefox */
  -ms-overflow-style: none;                     /* IE/Edge legacy */
}
.control-tabs::-webkit-scrollbar { display: none; height: 0; }              /* WebKit */
/* Ya no se voltea el contenedor (antes rotateX(180deg) subía el scrollbar): sin
   scrollbar visible, el flip solo complicaba y no aporta. Se retira el
   contra-flip de las tabs (regla `.control-tabs > .control-tab`) más abajo. */

.control-tab {
  appearance: none;
  border: 0;
  border-radius: 999px;                        /* pill moderno */
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font-size: 0.8125rem;
  font-weight: 600;
  font-family: inherit;
  padding: 8px 18px;
  white-space: nowrap;
  flex-shrink: 0;                              /* no se comprimen: fuerzan el scroll */
  transition: background 0.15s, color 0.15s;
}
/* (El contra-flip de .control-tabs > .control-tab se retiró junto con el flip del
   contenedor: ya no hay rotateX en la barra, así que las tabs se ven normales sin
   necesidad de contra-voltearlas.) */

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

/* Estado activo autosuficiente (no depende de la global .active): sólido de marca
   + texto blanco en oscuro; el override light-mode lo suaviza. Tokens sólidos que
   siempre resuelven (evita el fallback a violeta-sólido con texto invisible). */
.control-tab.active {
  background: var(--brand-dark) !important;
  color: #fff !important;
  box-shadow: 0 1px 4px rgba(0,0,0,0.12) !important;
}

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

/* ── Centro de Control: tabs en 2 niveles (#10) ──────────────────────────────
   Nivel 1 = GRUPOS (segmented fuerte, centrado, solo 3 → fit-content). */
.cc-group-tabs {
  width: fit-content; max-width: 100%;
  margin-left: 0; margin-right: auto; margin-bottom: 18px;
}
/* Nivel 2 = SUBTABS del grupo activo: texto plano con SUBRAYADO en la activa,
   alineadas a la IZQUIERDA y "con menos fuerza" para que resalte el segmented
   de arriba. Separadas del nivel-1 (margin del grupo) y con línea base tipo pestañas.
   Nota: el global `.active { background:!important; color:!important }` (línea 98)
   le ganaba en especificidad → la activa salía como pill sólido azul. Por eso
   background/color van con !important aquí. */
.cc-subtabs {
  display: flex; justify-content: flex-start; flex-wrap: wrap;
  gap: 2px; margin: 0 0 24px;
  border-bottom: 1px solid var(--border-soft);
}
.cc-subtab {
  appearance: none; border: 0; border-radius: 0; background: transparent !important;
  cursor: pointer; font-family: inherit; font-size: 0.8rem; font-weight: 500;
  color: var(--muted) !important;
  padding: 7px 13px; border-bottom: 2px solid transparent; margin-bottom: -1px;
  display: inline-flex; align-items: center; gap: 5px; white-space: nowrap;
  box-shadow: none !important;
  transition: color 0.15s, border-color 0.15s;
}
.cc-subtab:hover:not(.active):not(:disabled) { color: var(--text) !important; }
.cc-subtab.active {
  color: var(--brand) !important; border-bottom-color: var(--brand); font-weight: 600;
}
.cc-subtab:disabled { opacity: 0.4; cursor: not-allowed; }
/* El tooltip de las subtabs se pinta flotante (script .cc-tab-tip) igual que en las
   tabs; se oculta el texto inline por defecto. */
.cc-subtabs .info-tooltip-text { display: none; }

.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 de token pressable + popover (columna Token de Canales) ──────────────
   El badge dice solo el estado (Validado / Inválido / Sin verificar) y al pulsarlo
   abre un popover con la fecha de la última verificación y un botón para re-verificar
   (el resultado se avisa por toast, no en la celda). */
/* ── Compartir canal: enlace público + QR ─────────────────────────────────── */
.cc-share-gen { margin-top: 12px; width: 100%; }
.cc-share-result { margin-top: 16px; display: flex; flex-direction: column; gap: 10px; }
/* El QR necesita fondo claro para escanearse en cualquier tema — excepción
   intencional al tema, igual que .totp-qr-container. */
.cc-share-qr {
  display: flex; justify-content: center;
  padding: 14px; background: #fff; border-radius: 12px;
  border: 1px solid var(--border);
}
.cc-share-qr img { width: 200px; height: 200px; display: block; }
.cc-share-linkrow { display: flex; gap: 8px; align-items: center; }
.cc-share-linkrow .form-input { flex: 1 1 auto; min-width: 0; }
.cc-share-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.cc-share-actions .btn-action,
.cc-share-actions .btn-secondary { text-decoration: none; text-align: center; }

/* ── Identidad Visual › Códigos QR ──────────────────────────────────────────── */
.qr-editor-grid {
  display: grid;
  grid-template-columns: minmax(260px, 1fr) minmax(220px, 280px);
  gap: 24px; align-items: start; margin-top: 12px;
}
.qr-editor-controls { display: flex; flex-direction: column; gap: 10px; }
.qr-editor-colors { display: flex; gap: 16px; }
.qr-editor-color { display: flex; flex-direction: column; gap: 4px; }
.qr-color-input {
  width: 56px; height: 34px; padding: 2px; cursor: pointer;
  border: 1px solid var(--control-border); border-radius: 8px; background: var(--control-bg);
}
.qr-range { width: 100%; accent-color: var(--brand); }
.qr-editor-logo-upload { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.qr-editor-save { display: flex; align-items: center; gap: 12px; margin-top: 8px; }
.qr-saved { font-size: .8125rem; color: var(--badge-success-fg); }
.qr-editor-preview { display: flex; flex-direction: column; gap: 8px; }
.qr-preview-box {
  display: flex; align-items: center; justify-content: center;
  min-height: 220px; padding: 16px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 12px;
}
.qr-preview-box img { width: 100%; max-width: 240px; height: auto; display: block; }
@media (max-width: 720px) { .qr-editor-grid { grid-template-columns: 1fr; } }

.cc-token-wrap { position: relative; display: inline-block; }
.cc-token-badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 9px; border-radius: 999px;
  font-size: 0.72rem; font-weight: 600; font-family: inherit;
  border: 1px solid transparent; cursor: default;   /* estado, NO botón (#5) */
  transition: filter 0.15s ease, box-shadow 0.15s ease;
}
.cc-token-wrap:hover .cc-token-badge { filter: brightness(1.05); box-shadow: 0 0 0 3px rgba(var(--brand-rgb),0.10); }
.cc-token-badge:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.cc-token-caret { opacity: 0.7; flex-shrink: 0; }
.cc-token-badge--ok      { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.cc-token-badge--bad     { background: var(--badge-danger-bg);  color: var(--badge-danger-fg); }
.cc-token-badge--unknown { background: var(--surface-2);        color: var(--muted); }

/* position: fixed → el popover escapa el overflow del .users-table-wrap (que recorta
   por su overflow-x:auto). El wrap no tiene transform, así que fixed sale de la tabla
   y va por encima (#7). Un script (index.html) fija top/left desde el rect del badge;
   el elemento NO se mueve en el DOM, así el botón "Verificar" conserva su listener.
   Se REVELA al HOVER del wrap (#5): oculto por defecto, visible al pasar el cursor o
   al enfocar por teclado (focus-within). El script lo ancla pegado al badge (gap 0)
   para que el cursor pueda entrar al popover y pulsar "Verificar" sin perder el hover. */
.cc-token-pop {
  position: fixed; z-index: 1000;
  min-width: 220px; display: none; flex-direction: column; gap: 10px;
  padding: 12px; background: var(--surface-overlay);
  border: 1px solid var(--border); border-radius: 10px; box-shadow: var(--shadow-md);
}
.cc-token-wrap:hover .cc-token-pop,
.cc-token-wrap:focus-within .cc-token-pop { display: flex; }
.cc-token-pop-row { display: flex; flex-direction: column; gap: 2px; }
.cc-token-pop-label {
  font-size: 0.68rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--muted);
}
.cc-token-pop-val { font-size: 0.82rem; color: var(--text); }
.cc-token-pop-err {
  font-size: 0.74rem; color: var(--badge-danger-fg); background: var(--badge-danger-bg);
  padding: 6px 8px; border-radius: 6px; word-break: break-word;
}
.cc-token-verify { align-self: flex-start; }

/* Popover informativo al HOVER (#9): usado en columnas de la Base de conocimiento
   (Canales / Estado / Actualizado). position:fixed para escapar el overflow de la
   tabla; un script (index.html) lo ancla al rect del disparador. */
.hovpop { position: relative; display: inline-flex; cursor: default; }
.hovpop__panel {
  position: fixed; z-index: 1000;
  visibility: hidden; opacity: 0;
  min-width: 160px; max-width: 300px;
  display: flex; flex-direction: column; gap: 4px;
  padding: 10px 12px; background: var(--surface-overlay);
  border: 1px solid var(--border); border-radius: 10px; box-shadow: var(--shadow-md);
  transition: opacity 0.15s ease;
}
.hovpop:hover .hovpop__panel,
.hovpop:focus-within .hovpop__panel { visibility: visible; opacity: 1; }
.hovpop__row { font-size: 0.8rem; color: var(--text); word-break: break-word; }
.hovpop__row--label { font-size: 0.68rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }

/* Fila de la tabla de system prompts: clickeable → abre el modal de detalle/edición.
   La celda de acciones corta la propagación (sus botones no abren el modal). */
.control-row-click { cursor: pointer; }
.control-row-click:hover > td { background: var(--control-bg-hover); }

/* Botón de acción deshabilitado dentro de .tb-icon-wrap: sin captura de ratón, así
   el envoltorio recibe el hover y muestra su tooltip + cursor de bloqueo. */
.tb-icon-wrap.is-disabled .pg-btn:disabled { pointer-events: none; }

.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;
  /* min 140px: la etiqueta más larga ("Documentos") necesita aire para no rozar
     el borde de su toggle en el modal angosto. */
  grid-template-columns: repeat(auto-fill, minmax(140px, 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: var(--brand);
  color: var(--brand-dark);
  box-shadow: 0 0 0 3px rgba(var(--brand-rgb),0.1);
}

.output-toggle input[type="checkbox"] {
  accent-color: var(--brand);
  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;
  min-width: 0;
}

.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;
}

/* ID del canal: empujado a la derecha y en gris tenue → dato de referencia, no
   protagonista. */
.readonly-info-pair--id { margin-left: auto; text-align: right; }
.readonly-info-pair--id strong { color: var(--muted-2); font-weight: 500; }

.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: var(--panel-2);
  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(var(--brand-rgb),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;                        /* pill moderno */
  padding: 4px;
  width: fit-content;
  max-width: 100%;
  flex-wrap: wrap;
  overflow-x: auto;
}

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

/* Campos de modelos apilados verticalmente (#11): un campo encima de otro,
   alineados a la izquierda (no lado a lado como el grid anterior). */
.llm-model-fields { display: flex; flex-direction: column; gap: 14px; }
/* Campos de modelo con tamaño fijo — no se estiran a lo ancho del panel (#11 fix). */
.llm-model-fields .model-input-wrap { width: 100%; max-width: 460px; }
.control-form-panel .form-field input.control-timeout-input { max-width: 220px; }

/* Proveedor activo como selector principal: centrado y separado del resto (#11 fix). */
.llm-provider-field { align-items: center; text-align: center; }
.provider-model-tabs--main {
  margin: 6px auto 22px;
  padding: 5px;
  gap: 4px;
}
.provider-model-tabs--main .control-tab { padding: 9px 22px; font-size: 0.9rem; }

/* Botón "catálogo de modelos" (icono libro) DENTRO del campo, a la derecha (#11b).
   Sin caja; una línea divisoria lo separa del texto; con hover. Fuera de un
   .model-input-wrap (p. ej. Multimedia aún sin reestructurar) queda como icono inline. */
.model-catalog-btn {
  background: transparent; border: 0; cursor: pointer; color: var(--muted);
  padding: 4px 6px; display: inline-flex; align-items: center;
  transition: color 0.15s ease;
}
.model-catalog-btn:hover { color: var(--brand); }
.model-input-wrap { position: relative; display: block; }
.model-input-wrap .model-catalog-btn {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  padding: 4px 8px; border-left: 1px solid var(--control-border); border-radius: 0;
  height: 60%;
}
/* Press leve: conservar el centrado vertical, solo un pequeño scale (antes el
   :active global lo empujaba hacia abajo perdiendo el translateY). */
.model-input-wrap .model-catalog-btn:active { transform: translateY(-50%) scale(0.94); }
.control-form-panel .form-field input.model-input-with-btn { padding-right: 46px; }

.llm-keys-section {
  margin-top: 24px;
  padding: 16px 24px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
}
/* API Keys colapsable (#11d). */
.llm-keys-head {
  display: flex; align-items: center; justify-content: space-between;
  cursor: pointer; user-select: none;
}
.llm-keys-caret { color: var(--muted); transition: transform 0.2s ease; }
.llm-keys-caret.is-open { transform: rotate(180deg); }
.llm-keys-body { margin-top: 12px; }
/* Colapso suave (grid-template-rows 0fr→1fr anima a altura auto sin JS). */
.llm-keys-collapse { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.22s ease; }
.llm-keys-collapse.is-open { grid-template-rows: 1fr; }
.llm-keys-collapse-inner { overflow: hidden; }

/* Bloque de contenido grande dentro del modal de detalle (Base de conocimiento):
   contenedor interno propio, no una fila más de .detail-row. */
.detail-content-block { margin-top: 16px; }
.detail-content-title {
  display: block; font-size: 0.78rem; font-weight: 600; letter-spacing: 0.02em;
  text-transform: uppercase; color: var(--muted); margin-bottom: 8px;
}
.detail-content-box {
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 8px;
  padding: 14px 16px; max-height: 340px; overflow-y: auto;
  white-space: pre-wrap; word-break: break-word; line-height: 1.55;
  color: var(--text); font-size: 0.9rem;
}
.detail-content-box--muted { color: var(--muted); font-style: italic; }
.detail-content-box.is-empty { color: var(--muted); font-style: italic; }

/* Modal de detalle de Personalidad (#3): KPIs (puntos clave) arriba en grid + los
   contenedores con el contenido completo (personalidad / conocimiento) debajo. */
.pers-kpi-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 10px; margin-bottom: 20px;
}
.pers-kpi {
  display: flex; flex-direction: column; gap: 3px;
  background: var(--surface-2); border: 1px solid var(--border-soft);
  border-radius: 10px; padding: 10px 12px;
}
.pers-kpi-label {
  font-size: 0.66rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.04em; color: var(--muted);
}
.pers-kpi-val { font-size: 0.92rem; font-weight: 600; color: var(--text-strong); word-break: break-word; }
.pers-sections { display: flex; flex-direction: column; gap: 16px; }
.pers-section { display: flex; flex-direction: column; gap: 8px; }
.pers-section-title {
  font-size: 0.78rem; font-weight: 700; letter-spacing: 0.02em;
  text-transform: uppercase; color: var(--muted);
}

/* Modal de detalle de Encuesta (#7): acciones rápidas (participación/resultados) +
   apartado dedicado a las preguntas. */
.survey-detail-actions { display: flex; gap: 8px; flex-wrap: wrap; margin: 16px 0; }
.survey-detail-actions .pg-btn { display: inline-flex; align-items: center; gap: 6px; }
.survey-q-section { margin-top: 8px; }
.survey-q-list {
  list-style: none; counter-reset: sq; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 6px;
}
.survey-q-item {
  counter-increment: sq;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  background: var(--surface-2); border: 1px solid var(--border-soft);
  border-radius: 8px; padding: 10px 12px;
}
.survey-q-item::before {
  content: counter(sq); flex: 0 0 auto;
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 999px;
  background: var(--brand-soft-bg); color: var(--brand-soft-fg);
  font-size: 0.72rem; font-weight: 700;
}
.survey-q-label { flex: 1 1 auto; color: var(--text); font-size: 0.9rem; word-break: break-word; }
.survey-q-meta { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px; }
.survey-q-type {
  font-size: 0.68rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--muted); background: var(--surface-3); border-radius: 6px; padding: 2px 7px;
}
.survey-q-req {
  font-size: 0.66rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em;
  color: var(--badge-warn-fg); background: var(--badge-warn-bg); border-radius: 6px; padding: 2px 7px;
}

/* Tabs internos del modal de detalle (Base de conocimiento: Detalle | Historial).
   Segmented pill simple, sin el flip/scroll de .control-tabs. Borde/artefacto
   eliminados (#6): sin border ni box-shadow heredados; el pill activo lo pinta
   .control-tab.active (fade de marca) sin sombra dura. */
/* Underline limpio (mismo lenguaje que los subtabs #10 y los ticket-monitor-subtabs):
   texto plano con subrayado de marca en la activa. Antes era un pill segmentado sobre
   una banda surface-2 → la inactiva mostraba la banda y parecían dos botones iguales
   (bug reportado). background/color con !important para ganarle al global
   `.active{background!important}`. */
.detail-modal-tabs {
  display: flex; gap: 2px; padding: 0; margin: 0 0 16px;
  background: transparent; border: 0; border-bottom: 1px solid var(--border-soft);
  border-radius: 0; width: 100%;
}
.detail-modal-tabs .control-tab {
  border: 0; border-radius: 0; box-shadow: none !important;
  background: transparent !important; color: var(--muted) !important;
  padding: 8px 16px; border-bottom: 2px solid transparent; margin-bottom: -1px; font-weight: 500;
}
.detail-modal-tabs .control-tab:hover:not(.active) { color: var(--text) !important; }
.detail-modal-tabs .control-tab.active {
  background: transparent !important; color: var(--brand) !important;
  border-bottom-color: var(--brand); font-weight: 600;
}

/* Modal de detalle de la Base de conocimiento con TAMAÑO FIJO (#6): cambiar de tab
   (Detalle ↔ Historial) no reajusta el modal; el cuerpo scrollea internamente. */
.kn-detail-modal { display: flex; flex-direction: column; height: 80vh; max-height: 740px; overflow: hidden; }
.kn-detail-modal .modal-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }

/* Cabecera del contenedor de contenido: título + botón «expandir en grande». */
.detail-content-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; }
.detail-content-head .detail-content-title { margin-bottom: 0; }

/* Contenido del índice EXPANDIDO en un modal apilado POR ENCIMA del de detalle (#6). */
.modal-backdrop--stacked { z-index: 200; }
.kn-content-modal { display: flex; flex-direction: column; height: 80vh; max-height: 760px; overflow: hidden; }
.kn-content-modal .modal-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.kn-content-box-lg { max-height: none; height: 100%; box-sizing: border-box; }

/* Historial como TABLA (antes filas <details> desplegables) (#6). */
.kn-hist-table-wrap { margin-top: 4px; }
.kn-hist-table .kn-hist-changes { font-size: 0.82rem; }

/* Cambiar key (#11d.2): botón siempre visible; el input+Guardar/Cancelar van en un
   popover flotante (position:fixed, anclado por JS) para escapar el overflow del
   colapsable. Verificar/Cambiar nunca mutan a Guardar/Cancelar. */
.key-change-anchor { position: relative; display: inline-block; }
.btn-edit.is-active { background: var(--brand-soft-bg); color: var(--brand-soft-fg); }
.key-change-pop {
  position: fixed; z-index: 1200; top: 0; left: 0;
  width: 260px; box-sizing: border-box;
  background: var(--surface-overlay); border: 1px solid var(--border);
  border-radius: 10px; box-shadow: var(--shadow-lg); padding: 12px;
  display: flex; flex-direction: column; gap: 8px;
}
/* Multimedia (#11f): toggle con título arriba + tooltip al lado, toggle debajo;
   al apagar, el cuerpo de config se atenúa y bloquea. */
.mm-toggle-field { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; margin-bottom: 20px; }
.mm-toggle-title { display: inline-flex; align-items: center; gap: 6px; font-weight: 600; color: var(--text-strong); }
/* Toggle multimedia: DEBAJO del proveedor, SIN contenedor visible y alineado a
   la IZQUIERDA. Título arriba e interruptor debajo, como el resto de ajustes de
   sí/no del panel: con los dos en la misma línea era el único que se leía de
   derecha a izquierda. */
.mm-toggle-inline {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  margin: 18px 0 24px;
}
.mm-config-body { transition: opacity 0.2s ease; }
.mm-config-body.is-locked { opacity: 0.45; pointer-events: none; user-select: none; }
.mm-free-section { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); }

.key-change-label { font-size: 0.78rem; font-weight: 600; color: var(--muted); }
.key-change-input {
  width: 100%; box-sizing: border-box; padding: 8px 10px;
  background: var(--control-bg); border: 1px solid var(--control-border);
  border-radius: 6px; color: var(--text); font-size: 0.88rem;
}
.key-change-input:focus { outline: none; border-color: var(--brand); }
.key-change-actions { display: flex; justify-content: flex-end; gap: 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(var(--brand-rgb),0.05);
}
.btn-verify:disabled { opacity: 0.45; cursor: not-allowed; }

/* 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: rgba(var(--brand-rgb),0.05); }
.notif-tab--active {
  color: var(--brand);
  border-bottom-color: var(--brand);
  background: rgba(var(--brand-rgb),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(var(--brand-rgb),0.08);
  color: var(--brand);
  border: 1.5px solid rgba(var(--brand-rgb),0.25);
  cursor: pointer;
  transition: all 0.12s;
  white-space: nowrap;
  line-height: 1;
}
.var-chip:hover {
  background: rgba(var(--brand-rgb),0.18);
  border-color: var(--brand);
  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(var(--brand-rgb), .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
   ============================================================ */
/* La barra de filtros propia de Auditoría (.audit-filters / .audit-filter-*) se
   retiró: el módulo usa la toolbar estándar (.tickets-toolbar + embudo). */

.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(var(--brand-rgb),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--actions { 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: var(--brand-dark);
  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); }
/* La columna Módulo usa el mismo badge que Resultado, en morado neutro. */
.audit-badge--module { background: var(--badge-purple-bg); color: var(--badge-purple-fg); }

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

/* El detalle ya no expande la fila: se abre en modal (.audit-detail-modal), así
   que .audit-toggle-btn, .audit-row--expanded, .audit-row-detail y
   .audit-module-tag (que además fijaba colores a mano) quedaron sin uso. */
.audit-cell--module { white-space: nowrap; }

/* ── Modal de detalle del registro ── */
.audit-detail-modal { max-width: 640px; width: 100%; }

.audit-detail-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px 18px;
  margin-bottom: 14px;
}

.audit-module-tag {
  display: inline-block;
  font-family: 'Fira Code', 'Cascadia Code', monospace;
  font-size: 0.72rem;
  background: var(--badge-purple-bg);
  color: var(--badge-purple-fg);
  border: 1px solid rgba(var(--brand-rgb), 0.30);
  border-radius: 4px;
  padding: 2px 7px;
  white-space: nowrap;
}

.audit-detail-item {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
  word-break: break-word;
}

.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: var(--badge-danger-fg); }

/* Separa cada bloque de texto largo de lo que tiene encima dentro del modal. */
.audit-detail-section + .audit-detail-section { margin-top: 12px; }

.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(--badge-danger-bg);
  border-color: var(--badge-danger-bg);
  color: var(--badge-danger-fg);
}

/* Layout del pager en el bloque canónico (buscar "PAGINACIÓN ESTÁNDAR"). */

/* ============================================================
   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: var(--text-strong);
  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: var(--panel-2); color: var(--text-strong); }

.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: var(--text-strong);
  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) ── */
/* SEGMENTED: estilo en el bloque canónico. Aquí solo su posición en la cabecera. */
/* La barra vive DENTRO del main (como en Centro de Control), así que no lleva
   gutter propio: los 40px de antes la desalineaban del contenido de abajo. */
.metrics-tabs { margin: 0 0 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: var(--text);
  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: var(--text);
  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, var(--brand), var(--brand-soft-fg));
  border-radius: 999px;
  transition: width 0.4s ease;
  min-width: 2px;
}

/* ── Agent sub-tabs (pill-group) ── */
/* SEGMENTED: estilo en el bloque canónico. */
.metrics-agent-tabs { border-bottom: none; }

/* ── 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: var(--brand);
  box-shadow: 0 0 0 3px rgba(var(--brand-rgb), 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: var(--brand);
  box-shadow: 0 0 0 3px rgba(var(--brand-rgb), 0.15);
}


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

/* Badge variants (--modifier on base .badge) */
.badge--warn    { background: rgba(245,158,11,0.15);  color: #b45309; border: 1px solid rgba(245,158,11,0.3); }
.badge--success { background: rgba(16,185,129,0.12);  color: #059669; border: 1px solid rgba(16,185,129,0.25); }
.badge--danger  { background: rgba(239,68,68,0.12);   color: #dc2626; border: 1px solid rgba(239,68,68,0.25); }
.badge--info    { background: rgba(var(--brand-rgb),0.12);  color: var(--brand-soft-fg); border: 1px solid rgba(var(--brand-rgb),0.25); }
.badge--locked  { background: rgba(239,68,68,0.10);   color: #b91c1c; border: 1px solid rgba(239,68,68,0.22); }
.badge--ticket-active { background: rgba(var(--brand-rgb),0.10); color: var(--brand-soft-fg); border: 1px solid rgba(var(--brand-rgb),0.22); }

/* 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: flex;
  align-items: stretch;
  height: calc(100vh - 60px);
  overflow: hidden;
  background: var(--bg);
}

/* ── Bandeja (izquierda) — ancho por estilo inline (redimensionable) ─────── */
.livechat-sidebar {
  position: relative;               /* ancla del popover de filtros */
  flex: 0 0 auto;
  width: 320px;                     /* fallback; el inline manda */
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border-right: 1px solid var(--border-soft);
  overflow: hidden;
  transition: width 0.22s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Arrastrando el resizer el ancho debe seguir al puntero al instante. */
.livechat-sidebar.is-resizing { transition: none; }
.livechat-sidebar--collapsed { width: 48px !important; }

/* Barra superior de la bandeja: búsqueda + embudo + colapsar */
.lc-topbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 12px;
  border-bottom: 1px solid rgba(255,255,255,0.08);
  flex-shrink: 0;
}
.lc-topbar .lc-search { flex: 1 1 auto; min-width: 0; }
/* Toolbar estándar dentro de la bandeja: la pastilla manda el ancho y los
   iconos van pegados (mismo espaciado que .contacts-search-form). */
.lc-topbar { gap: 2px; }
.lc-topbar .contacts-search-input { flex: 1 1 auto; min-width: 0; }
.lc-topbar--collapsed { justify-content: center; padding: 12px 4px; }

/* Riel de la bandeja colapsada: los avatares siguen visibles y clicables. */
.lc-rail-list {
  list-style: none; margin: 0; padding: 6px 0;
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  overflow-y: auto; flex: 1 1 auto; min-height: 0;
  scrollbar-width: thin; scrollbar-color: transparent transparent;
}
.lc-rail-list:hover { scrollbar-color: rgba(255,255,255,0.20) transparent; }
.lc-rail-list::-webkit-scrollbar { width: 6px; }
.lc-rail-list::-webkit-scrollbar-track { background: transparent; }
.lc-rail-list::-webkit-scrollbar-thumb { background: transparent; border-radius: 6px; }
.lc-rail-list:hover::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.20); }
.lc-rail-item {
  position: relative;
  display: flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; padding: 0;
  border: none; border-radius: 10px; background: transparent;
  cursor: pointer; transition: background 0.12s ease;
}
.lc-rail-item:hover { background: var(--control-bg-hover); }
.lc-rail-item.is-selected { background: var(--brand-soft-bg); box-shadow: inset 0 0 0 1px var(--brand); }
.lc-rail-dot {
  position: absolute; top: 3px; right: 3px;
  width: 7px; height: 7px; border-radius: 50%; background: #f59e0b;
}

/* Botones cuadrados de la barra (embudo, colapsar) */
.lc-filter-btn,
.lc-collapse-btn {
  position: relative;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px; height: 34px;
  border: 1px solid var(--control-border);
  border-radius: 9px;
  background: var(--control-bg);
  color: var(--text);
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.lc-filter-btn:hover,
.lc-collapse-btn:hover { background: var(--control-bg-hover); }
.lc-filter-btn.is-active { border-color: var(--brand); color: var(--brand); }
.lc-filter-count {
  position: absolute; top: -5px; right: -5px;
  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;
}

/* Popover de filtros (empaquetados tras el embudo) */
.lc-filters-backdrop {
  position: fixed; inset: 0; z-index: 40;
  background: transparent;
}
.lc-filters-popover {
  position: absolute; top: 58px; left: 8px; right: 8px; z-index: 41;
  display: flex; flex-direction: column; gap: 10px;
  padding: 12px;
  background: var(--surface-overlay);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow-md);
}

/* Wrapper scrollable de la lista (se oculta al colapsar) */
.lc-list-wrap {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}
.livechat-sidebar--collapsed .lc-list-wrap { display: none; }

/* ── Resizer entre paneles ─────────────────────────────────── */
.lc-resizer {
  flex: 0 0 auto;
  width: 5px;
  cursor: col-resize;
  background: transparent;
  transition: background 0.15s;
}
.lc-resizer:hover { background: var(--brand); }

.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,
.lc-filters-popover 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: var(--muted);
  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,
.lc-filters-popover select:focus {
  border-color: rgba(99,179,237,0.5);
  background-color: rgba(255,255,255,0.1);
}

.livechat-filters select option,
.lc-filters-popover select option { background: var(--panel-2); }

.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: var(--text);
}

.filter-pill--active {
  background: rgba(var(--brand-rgb),0.2) !important;
  border-color: rgba(var(--brand-rgb),0.4) !important;
  color: var(--brand-soft-fg) !important;
}

.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(var(--brand-rgb),0.18) !important;
  border: 1px solid rgba(var(--brand-rgb),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); }
/* Comentarios de IG: mismo degradado pero con anillo punteado — distingue a simple
   vista un comentario público de un DM privado en la lista de conversaciones. */
.conv-channel-badge--igc  {
  background: linear-gradient(135deg, #833AB4, #E1306C, #F77737);
  outline: 2px dashed var(--badge-warn-fg);
  outline-offset: 1px;
}
.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: var(--text);
  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: var(--text);
}

.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 {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: var(--surface-3);
  border-right: 1px solid var(--border);
  overflow: hidden;
}

/* Nombre del contacto en la cabecera del chat → abre la ficha derecha */
.mh-contact-name {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  max-width: 260px;
  padding: 5px 8px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  color: var(--text-strong);
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 700;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.mh-contact-name:hover { background: var(--control-bg); border-color: var(--control-border); }
.mh-contact-name-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mh-contact-name-caret { flex-shrink: 0; opacity: 0.6; }

.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: var(--surface-3);
  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(var(--brand-rgb),0.1);
  color: var(--brand-dark);
  border: 1px solid rgba(var(--brand-rgb),0.25);
}
.btn-action--assign:hover:not(:disabled) { background: rgba(var(--brand-rgb),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-dark); }

.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: var(--surface-3);
  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: var(--text);
  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: var(--muted-2); 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(var(--brand-rgb),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(var(--brand-rgb),0.1);
  padding: 5px 10px;
  border-radius: 6px;
}
.msg-location-link:hover { background: rgba(var(--brand-rgb),0.18); }
.msg-location-addr {
  font-size: 0.78rem;
  color: var(--muted);
}

/* ── Ficha del contacto (derecha) ───────────────────────── */
.livechat-contact-panel {
  flex: 0 0 auto;
  width: 320px;                     /* fallback; el inline manda */
  display: flex;
  flex-direction: column;
  background: var(--surface-3);
  overflow-y: auto;
  padding: 20px;
}
/* Barra superior de la ficha (título + X para cerrar) */
.lc-contact-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 12px;
}
.lc-contact-topbar-title {
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--muted-2);
}
.lc-contact-close {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px; height: 30px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.lc-contact-close:hover { background: var(--control-bg); border-color: var(--control-border); color: var(--text); }

/* Tabs de la ficha del contacto — scroll horizontal si el panel es angosto.
   La barra de scroll va ARRIBA del strip (truco de flip vertical) y usa el mismo
   estilo overlay auto-oculto de la sidebar. */
.lc-contact-tabs-wrap { display: flex; flex-direction: column; gap: 10px; }
.lc-tabs {
  display: flex;
  gap: 3px;
  padding: 4px;
  background: var(--surface-2);
  border-radius: 10px;
  overflow-x: auto;
  transform: scaleY(-1);            /* voltea → la barra (abajo) queda arriba */
  scrollbar-width: thin;            /* Firefox */
  scrollbar-color: transparent transparent;
}
.lc-tabs > * { transform: scaleY(-1); }   /* restaura el contenido */
.lc-tabs:hover { scrollbar-color: rgba(255, 255, 255, 0.20) transparent; }
.lc-tabs::-webkit-scrollbar { height: 8px; }
.lc-tabs::-webkit-scrollbar-track { background: transparent; }
.lc-tabs::-webkit-scrollbar-thumb {
  background: transparent;
  border: 2px solid transparent;
  background-clip: padding-box;
  border-radius: 8px;
  transition: background-color 0.2s ease;
}
.lc-tabs:hover::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.20); background-clip: padding-box; }
.lc-tabs:hover::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.34); background-clip: padding-box; }
html.light-mode .lc-tabs:hover { scrollbar-color: rgba(0, 0, 0, 0.22) transparent; }
html.light-mode .lc-tabs:hover::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, 0.18); background-clip: padding-box; }
html.light-mode .lc-tabs:hover::-webkit-scrollbar-thumb:hover { background: rgba(0, 0, 0, 0.30); background-clip: padding-box; }
.lc-tab {
  flex: 1 0 auto;
  white-space: nowrap;              /* no romper el texto → desborda y hace scroll */
  padding: 7px 10px;
  border: none;
  border-radius: 7px;
  background: transparent;
  color: var(--muted);
  font-family: inherit;
  font-size: 0.74rem;
  font-weight: 700;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.lc-tab:hover { color: var(--text); }
.lc-tab.is-active { background: var(--brand-dark); color: #fff; }
.lc-tab-panel { display: flex; flex-direction: column; gap: 12px; }
.lc-tab-panel.is-hidden { display: none; }

.livechat-contact-panel::-webkit-scrollbar { width: 4px; }
.livechat-contact-panel::-webkit-scrollbar-track { background: transparent; }
.livechat-contact-panel::-webkit-scrollbar-thumb { background: var(--muted-2); 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(var(--brand-rgb), 0.10);
  color: var(--brand);
  border: 1px solid rgba(var(--brand-rgb), 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(var(--brand-rgb),.1); color:var(--brand);
  border: 1px solid rgba(var(--brand-rgb),.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 { color:#b91c1c; border-color: rgba(239,68,68,.4); }

/* ── 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; }

/* Stickers + galería base del system prompt (SystemPromptModal). Rejilla de tarjetas:
   miniatura + campos (nombre/descripción/URL) + botón de quitar. */
.sp-media-grid {
  display:grid;
  grid-template-columns:repeat(auto-fill, minmax(260px, 1fr));
  gap:12px; margin-bottom:12px;
}
.sp-media-card {
  display:flex; align-items:flex-start; gap:10px; position:relative;
  padding:10px; border:1px solid var(--border-soft); border-radius:10px;
  background:var(--surface-2);
}
.sp-media-thumb {
  flex:0 0 52px; width:52px; height:52px; border-radius:8px; overflow:hidden;
  background:var(--control-bg); display:flex; align-items:center; justify-content:center;
}
.sp-media-thumb img { width:100%; height:100%; object-fit:cover; }
.sp-media-kind { font-size:10px; font-weight:700; letter-spacing:0.06em; color:var(--muted); }
.sp-media-fields { flex:1 1 auto; min-width:0; display:flex; flex-direction:column; gap:6px; }
.sp-media-fields .form-input { width:100%; box-sizing:border-box; }
.sp-media-del {
  flex:0 0 auto; border:none; background:transparent; cursor:pointer;
  color:var(--muted); font-size:14px; line-height:1; padding:2px 5px; border-radius:6px;
}
.sp-media-del:hover { color:var(--badge-danger-fg, #ef4444); background:var(--badge-danger-bg); }
.sp-media-add { display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.sp-media-newurl { flex:1 1 240px; min-width:180px; }
.sp-media-upload { cursor:pointer; display:inline-flex; align-items:center; }
.sp-media-upload.is-busy { opacity:0.6; pointer-events:none; }
.sp-media-msg { margin-top:8px; font-size:0.8rem; color:var(--muted); }

.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:var(--brand); background: var(--surface);
  box-shadow: 0 0 0 3px rgba(var(--brand-rgb),.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:var(--brand); font-weight:600; background: rgba(var(--brand-rgb),.08); }
.kn-step.active .kn-step-dot { background:var(--brand-dark); 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:var(--brand); background: rgba(255,255,255,0.08); }
.kn-tipo-card.selected { border-color:var(--brand); background: rgba(var(--brand-rgb),0.12); box-shadow: 0 0 0 3px rgba(var(--brand-rgb),.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: var(--brand); background: var(--surface-2); color: var(--brand); }
.kn-channel-chip.active {
  border-color: var(--brand); background: rgba(var(--brand-rgb),.08);
  color: var(--brand); font-weight: 700;
  box-shadow: 0 0 0 2px rgba(var(--brand-rgb),.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 {
  display:inline-flex; align-items:center; justify-content:center;
  width:17px; height:17px; border-radius:50%;
  background: var(--control-bg-hover); color: var(--muted); font-size:0.68rem; font-weight:700;
  cursor: help; flex-shrink:0;
}
.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(var(--brand-rgb), 0.08);
  border: 1px solid rgba(var(--brand-rgb), 0.25);
}
.cc-creds-actions { margin-top: 12px; display: flex; justify-content: flex-end; }
/* margin-bottom 24px: el CTA es lo último visible del modal Crear (el bloque no
   guiado va oculto), así que sin este aire chocaría con el borde inferior. */
.tg-cta { margin:4px 0 24px; padding:18px; border:1px dashed #38bdf8; border-radius:12px; background:rgba(56,189,248,.06); text-align:center; }
.tg-cta-title { display:inline-flex; align-items:center; justify-content:center; gap:6px; margin:0 0 14px; font-weight:700; color:#0369a1; }
.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:var(--brand); }

/* 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:var(--brand); 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:var(--brand); }
.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;
  }

  .app-header, .page-header {
    padding: 0 16px;
  }

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

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

  /* En móvil el buscador baja bajo el saludo y ocupa el ancho: a 300px de base
     compartiría línea con el título y ninguno de los dos se leería. */
  .home-search {
    flex: 1 1 100%;
  }

  .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;
}

/* Los avisos del módulo salen por el toast global (ver .toast-host). */

/* ── Tabs: SEGMENTED estándar, estilo en el bloque canónico ── */
/* Icono (iconset) o emoji de la pestaña, alineado con el texto del label. */
.camp-tab svg { vertical-align: -0.15em; }

/* ── 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; }
.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 ── */
.badge {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 20px;
  font-size: 0.76rem;
  font-weight: 600;
  white-space: nowrap;
}

.badge-green  { background: rgba(16,185,129,0.15); color: #34d399; }
.badge-yellow { background: rgba(245,158,11,0.16);  color: #fbbf24; }
.badge-red    { background: rgba(239,68,68,0.15);   color: #f87171; }
.badge-blue   { background: rgba(59,130,246,0.16);  color: #60a5fa; }
.badge-gray   { background: rgba(148,163,184,0.18); color: var(--muted); }
.badge-type   { background: var(--badge-purple-bg);  color: var(--badge-purple-fg); }

/* ── 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, var(--brand), var(--brand-dark));
  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: var(--brand);
}

@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); color: #fff; border-color: var(--brand); }
.camp-btn--primary:hover:not(:disabled) { background: var(--brand-dark); }

.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: var(--brand);
  box-shadow: 0 0 0 3px rgba(var(--brand-rgb),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: var(--brand);
  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(var(--brand-rgb), 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); }
.toggle-switch--lg {
  --switch-width: 60px;
  --switch-height: 32px;
  --switch-knob-size: 24px;
  --switch-knob-offset: 4px;
}
.toggle-switch--lg input:checked + .toggle-slider::before { transform: translateX(28px); }

/* ── 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 */
/* padding horizontal = el del resto de modales estándar (no toca los bordes). */
.tools-create-form { display: flex; flex-direction: column; gap: 14px; padding: 4px 24px 8px; }
.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; }
/* Toggle + etiqueta en una fila (autenticación / habilitado del modal MCP). */
.tools-inline-toggle {
  display: flex; align-items: center; gap: 10px; cursor: pointer;
  font-size: 0.82rem; font-weight: 600; color: var(--text-strong);
}
.tools-inline-toggle > span { display: inline-flex; align-items: center; gap: 6px; }

/* ── Métodos de pago: lista compacta de campos + editor por chips ─────────── */
.pm-field-list { display: flex; flex-direction: column; gap: 8px; }
.pm-field-row {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface-2); cursor: pointer;
}
.pm-field-row:hover { border-color: var(--brand); }
.pm-field-name { font-weight: 600; color: var(--text-strong); flex: 1 1 auto; }
.pm-field-del { margin-left: auto; }
/* Chips de opciones (tag input: escribir + Enter) */
.tag-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.tag-chips:empty { display: none; }
.tag-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 6px 3px 10px; border-radius: 999px;
  background: var(--brand-soft-bg); color: var(--brand-soft-fg);
  font-size: 0.8rem; font-weight: 600;
}
.tag-chip-x {
  border: 0; background: transparent; cursor: pointer; color: inherit;
  font-size: 1rem; line-height: 1; padding: 0 2px;
}
.tag-chip-x:hover { color: var(--badge-danger-fg); }
/* Checkboxes con estilo de la app (checkbox + texto sin chocar) */
.pm-check-grid { display: flex; flex-wrap: wrap; gap: 10px 20px; }
.pm-toggle-group { display: flex; flex-direction: column; gap: 10px; }
.pm-check {
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  font-size: 0.86rem; color: var(--text);
}
/* Checkbox custom con estilo de la app (caja + check de marca), no el nativo. */
.pm-check input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  width: 18px; height: 18px; margin: 0; flex-shrink: 0;
  border: 1.5px solid var(--control-border); border-radius: 5px;
  background: var(--control-bg); cursor: pointer;
  display: inline-grid; place-content: center;
  transition: background 0.15s, border-color 0.15s;
}
.pm-check input[type="checkbox"]::before {
  content: ""; width: 11px; height: 11px; transform: scale(0);
  transition: transform 0.12s ease; background: #fff;
  clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
}
.pm-check input[type="checkbox"]:checked { background: var(--brand); border-color: var(--brand); }
.pm-check input[type="checkbox"]:checked::before { transform: scale(1); }
.pm-check input[type="checkbox"]:hover:not(:checked) { border-color: var(--brand); }
.pm-check > span { display: inline-flex; align-items: center; gap: 6px; }

/* ── Correo & Alertas: editor + vista previa lado a lado, divisor arrastrable ── */
/* El modal debe ser ancho: el global `.modal-card{max-width:480px}` ganaba al width
   inline (max-width pisa a width) → se quedaba angosto y la preview no cabía. */
.modal-card.mail-modal {
  width: min(1180px, 96vw); max-width: min(1180px, 96vw); max-height: 94vh; overflow-y: auto;
}
.mail-split { display: flex; align-items: stretch; gap: 0; }
/* Editor: ancho controlado por --mail-ew (el divisor JS lo ajusta). SIN overflow
   propio → el dropdown de autocompletado no se recorta. */
.mail-editor-pane { flex: 0 0 var(--mail-ew, 480px); min-width: 300px; }
/* Divisor arrastrable (col-resize); el JS de index.html ajusta --mail-ew. */
.mail-divider {
  flex: 0 0 6px; align-self: stretch; margin: 0 10px;
  background: var(--border); border-radius: 3px; cursor: col-resize;
  transition: background 0.15s;
}
.mail-divider:hover { background: var(--brand); }
.mail-preview-pane { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; }
.mail-preview-head {
  font-size: 0.8125rem; font-weight: 600; color: var(--text-strong);
  margin-bottom: 10px; padding-bottom: 8px; border-bottom: 1px solid var(--border);
}
.mail-preview-subject {
  background: var(--surface-2); padding: 8px 12px; border-radius: 6px;
  margin-bottom: 10px; font-size: 0.8125rem; word-break: break-word; border: 1px solid var(--border);
}
.mail-preview-subject strong { color: var(--muted); font-size: 0.72rem; text-transform: uppercase; letter-spacing: .04em; }
.mail-preview-frame { width: 100%; flex: 1 1 auto; min-height: 460px; border: 1px solid var(--border); border-radius: 8px; background: #fff; }
.mail-preview-note { margin: 6px 0 0; font-size: 0.72rem; color: var(--muted); text-align: center; }
.mail-preview-note code { background: var(--surface-2); padding: 1px 3px; border-radius: 3px; }
/* Autocompletado de {{variables}} */
.mail-ac-field { position: relative; }
.mail-ac-menu {
  position: absolute; z-index: 60; left: 0; right: 0; top: 100%;
  margin-top: 2px; max-height: 240px; overflow-y: auto;
  background: var(--surface-overlay); border: 1px solid var(--border);
  border-radius: 10px; box-shadow: var(--shadow-lg); padding: 4px;
}
.mail-ac-item {
  display: flex; flex-direction: column; gap: 1px; width: 100%; text-align: left;
  background: transparent; border: 0; border-radius: 7px; padding: 6px 10px; cursor: pointer;
}
.mail-ac-item:hover { background: var(--control-bg-hover); }
.mail-ac-name { font-family: ui-monospace, Consolas, monospace; font-size: 0.8rem; color: var(--brand); font-weight: 600; }
.mail-ac-desc { font-size: 0.72rem; color: var(--muted); }
@media (max-width: 860px) {
  .mail-split { flex-direction: column; }
  .mail-editor-pane { flex: 1 1 auto; min-width: 0; padding-bottom: 14px; }
  .mail-divider { display: none; }
  .mail-preview-pane { padding-top: 14px; border-top: 1px solid var(--border); }
}

/* ── Límites: cada opción = título + tooltip arriba, control debajo ───────── */
.limit-opt { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; }
.limit-opt-title {
  display: inline-flex; align-items: center; gap: 6px;
  font-weight: 600; color: var(--text-strong); font-size: 0.95rem;
}

.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: flex-start;
  padding: 14px 18px; gap: 12px; flex-wrap: wrap;
}
.tools-card-head.is-clickable { cursor: pointer; }
.tools-card-head.is-clickable:hover { background: var(--surface-2); }
/* Chevron a la derecha (sin caja); gira 180° al expandir. */
.tools-card-chevron {
  display: inline-flex; align-items: center; color: var(--muted);
  transition: transform 0.18s ease; flex-shrink: 0;
}
.tools-card-chevron.is-open { transform: rotate(180deg); }
.tools-card-title { flex: 1 1 auto; 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: 8px 24px 12px; 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, var(--brand-dark) 0%, var(--brand-dark) 65%, var(--brand-dark) 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); }

/* La toolbar estándar dentro de Contactos conserva el respiro y el sangrado que
   tenía la vieja .contacts-toolbar (si no, queda pegada al header y desalineada
   respecto a la tabla). */
.page-container > .tickets-toolbar { margin: 16px 32px 0; }

.contacts-toolbar {
  position: relative;               /* ancla del popover de filtros */
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  /* Padding horizontal = el de .contacts-content (32px) para que la toolbar
     quede alineada con la tabla de abajo. Sin padding inferior: la separación
     con la tabla la pone .contacts-content y así queda en los 16px del resto
     de módulos (antes se sumaban los dos y daba 40px). */
  padding: 16px 32px 0;
}

/* ── TOOLBAR ESTÁNDAR ─────────────────────────────────────────────────────────
   Un solo dialecto para todos los módulos: barra de búsqueda redondeada con la
   lupa decorativa dentro, y a su derecha los iconos de acción SIN contenedor
   (filtros, limpiar filtros, refrescar). El hover levanta el icono, no pinta
   una caja detrás. Añadir un módulo = reusar estas clases, no crear otras. */
.contacts-search-form {
  display: flex;
  align-items: center;
  gap: 2px;
  width: 100%;
  max-width: 520px;
}

/* Botón de filtros (embudo) — ancla del contador de filtros activos */
.contacts-filter-btn { position: relative; }
/* Estado ENCENDIDO de cualquier icono-interruptor de la toolbar (embudo con
   filtros activos, modo selección). Estaba solo bajo `.ec-toolbar`, así que el
   botón de modo selección de la toolbar estándar no se iluminaba en ningún
   módulo salvo Ecommerce. Va sobre `.contacts-refresh-btn`, que es la clase
   base de todos los iconos de la barra. */
.contacts-refresh-btn.is-active,
.contacts-filter-btn.is-active { color: var(--brand); }
.contacts-refresh-btn.is-active svg,
.contacts-filter-btn.is-active svg { transform: translateY(-2px); }
/* Tinte de fondo: un interruptor encendido tiene que leerse de un vistazo, no
   solo por el color del trazo. El botón es 34×34 sin borde, así que basta con
   redondearlo. */
.contacts-refresh-btn.is-active {
  background: var(--brand-soft-bg);
  border-radius: 8px;
}
/* Refresco en curso: el icono gira. Es el único acuse de recibo posible cuando
   la recarga devuelve exactamente los mismos datos — sin él, el botón parece
   roto aunque la petición haya salido y vuelto. */
.contacts-refresh-btn.is-spinning svg {
  animation: tb-refresh-spin 0.7s linear infinite;
  transform-origin: 50% 50%;
}

@keyframes tb-refresh-spin {
  to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
  .contacts-refresh-btn.is-spinning svg { animation: none; opacity: 0.5; }
}

.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 de limpiar: recibe el hover (y con él el tooltip y el
   cursor) cuando el botón está deshabilitado y no genera eventos propios. */
.tb-icon-wrap { display: inline-flex; }
.tb-icon-wrap.is-disabled { cursor: not-allowed; }

/* Popover de filtros (canal + estado) */
.contacts-filters-popover {
  position: absolute; top: 62px; left: 32px; z-index: 41;
  width: min(420px, calc(100% - 64px));
  display: flex; flex-direction: column; gap: 14px;
  padding: 14px;
  background: var(--surface-overlay);
  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);
}
/* Chips dentro del popover: sin banda propia, permiten envolver */
.contacts-filters-popover .contacts-channel-bar {
  background: transparent; border: none; padding: 0;
  flex-wrap: wrap; overflow: visible;
}
.contacts-filters-popover .contacts-sc-wrap { flex-wrap: wrap; }

/* Barra de búsqueda: pastilla redondeada. La lupa es decorativa y va DENTRO,
   pegada a la derecha, como background-image — así no hay que tocar el marcado
   de cada módulo. Es gris neutro a propósito: se lee igual en ambos temas. */
.contacts-search-input {
  background: var(--control-bg);
  border: 1px solid var(--control-border);
  border-radius: 999px;
  color: var(--text);
  font-family: inherit;
  font-size: 0.875rem;
  outline: none;
  flex: 1;
  min-width: 0;
  padding: 10px 40px 10px 18px;
  transition: background 0.15s, border-color 0.15s, box-shadow 0.15s;
  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;
}
.contacts-search-input::placeholder { color: var(--muted-2); }
.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 de la toolbar: sin caja. Solo el icono, y el hover lo
   levanta y lo tiñe de marca. Sirve para filtros, limpiar y refrescar. */
.contacts-refresh-btn {
  align-items: center;
  background: none;
  border: none;
  padding: 0;
  color: var(--muted);
  cursor: pointer;
  display: flex;
  height: 34px;
  width: 34px;
  justify-content: center;
  flex-shrink: 0;
}
.contacts-refresh-btn svg { transition: transform 0.15s ease, color 0.15s ease; }
.contacts-refresh-btn:hover:not(:disabled) { color: var(--brand); }
.contacts-refresh-btn:hover:not(:disabled) svg { transform: translateY(-2px); }
.contacts-refresh-btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 8px; }
/* Deshabilitado: no captura el ratón, así el envoltorio muestra el tooltip. */
.contacts-refresh-btn:disabled { opacity: 0.35; cursor: not-allowed; pointer-events: none; }

/* ── Channel chips bar ── */
.contacts-channel-bar {
  background: var(--surface-3);
  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: var(--brand);
  color: var(--brand-dark);
  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(var(--brand-rgb),0.15); }

/* ── Status sub-bar ── */
.contacts-subbar {
  background: var(--surface-3);
  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: var(--brand-dark);
  border-color: var(--brand-dark);
  color: white;
  font-weight: 600;
}

.contacts-count-label {
  color: var(--muted);
  font-size: 0.8125rem;
  font-weight: 500;
}

/* ── Content wrapper ── */
.contacts-content {
  padding: 16px 32px 24px;
  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;
}

/* ── Vista TARJETAS de contactos ──────────────────────────────────────────────
   Secundaria: la tabla sigue siendo la vista de trabajo. La tarjeta existe para
   RECONOCER a alguien (cara, nombre, canal), así que lleva menos datos a
   propósito. `auto-fit` —no `auto-fill`— para que las tarjetas estiren y llenen
   la fila en vez de dejar columnas fantasma (misma razón que en Métricas). */
.contact-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 12px;
}
/* Las dos vistas se montan a la vez y se alterna cuál se muestra: cambiar de
   vista no vuelve a pedir datos ni pierde la selección en curso. */
.contact-cards.is-hidden,
.table-wrapper.is-hidden,
.users-table-wrap.is-hidden { display: none; }

.contact-card {
  display: flex; flex-direction: column; gap: 12px;
  padding: 14px;
  border: 1px solid var(--border); border-radius: 12px;
  background: var(--surface);
  cursor: pointer;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.contact-card:hover { border-color: var(--brand); box-shadow: var(--shadow-sm); }
/* El bloqueado se marca con una barra lateral, no tiñendo la tarjeta entera:
   el tinte compite con el de selección y se vuelven indistinguibles. */
.contact-card.row-blocked { box-shadow: inset 3px 0 0 var(--badge-danger-fg); }

.contact-card-head { display: flex; align-items: center; gap: 12px; min-width: 0; }
.contact-avatar--lg { width: 46px; height: 46px; font-size: 1rem; }
.contact-card-id { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.contact-card-name {
  color: var(--text-strong); font-size: 0.9rem; font-weight: 700;
  /* Sin esto un nombre largo ensancha la celda del grid y descuadra la fila. */
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.contact-card-phone { color: var(--muted); font-size: 0.75rem; }

.contact-card-meta {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; flex-wrap: wrap;
}

/* Las acciones se separan abajo y quedan siempre a la misma altura, aunque una
   tarjeta tenga teléfono y la de al lado no. En modo selección se ocultan solas
   (`.row-selectmode .pg-actions`), igual que en la tabla. */
.contact-card .pg-actions {
  display: flex; gap: 6px; margin-top: auto;
  padding-top: 10px; border-top: 1px solid var(--border-soft);
}

/* Selección: en la tabla el fondo lo pinta la CELDA, aquí lo pinta la tarjeta.
   Misma lectura visual —tinte de marca + barra a la izquierda— para que el modo
   selección se reconozca igual en las dos vistas. */
.contact-card.row-selected {
  background: var(--brand-soft-bg);
  border-color: var(--brand);
  box-shadow: inset 3px 0 0 var(--brand);
}

/* ── 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--blocked  { background: rgba(239,68,68,0.1);  color: #dc2626; }
.contact-sbadge--verified { background: rgba(16,185,129,0.1); color: #059669; }
.contact-sbadge--pending  { background: var(--surface-2); color: var(--muted); }
.contact-sbadge--paused   { background: rgba(245,158,11,0.12); color: #d97706; }

.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;
}

/* Acciones de fila de Contactos: ver .pg-actions / .pg-btn. */

/* ── 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: var(--brand-dark);
  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 var(--control-border);
  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);
}

/* ── Canal de correo en Campañas ─────────────────────────────────────────────
   Solo tokens semánticos: el conmutador y las tarjetas heredan el tema claro y
   el oscuro sin una sola regla `html.light-mode` propia. */

/* Conmutador WhatsApp / Correo del formulario de nueva campaña. */
.camp-kind-switch {
  display: inline-flex;
  gap: 4px;
  padding: 4px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
}
.camp-kind-opt {
  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 20px;
  transition: background 0.15s, color 0.15s;
}
.camp-kind-opt:hover:not(.camp-kind-opt--active) {
  background: var(--control-bg-hover);
  color: var(--text);
}
/* `--brand-dark` es SIEMPRE la variante sobre la que se apoya texto blanco. */
.camp-kind-opt--active {
  background: var(--brand-dark);
  color: #fff;
}
.camp-kind-opt:disabled { opacity: 0.55; cursor: default; }

/* Cabecera de las pestañas de configuración de correo. */
.camp-config-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.camp-config-head .camp-hint { max-width: 62ch; }

/* Tarjeta contenedora de los formularios de canal y plantilla. */
.camp-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 18px;
  margin-bottom: 18px;
  box-shadow: var(--shadow-sm);
}

/* Pie de las tarjetas KPI del panel de resultados de correo. */
.metrics-kpi-sub {
  color: var(--muted);
  font-size: 0.75rem;
  line-height: 1.4;
}

/* ── Sub-pestañas de canal (Plantillas, Configuración, Resultados) ───────────
   Deliberadamente MÁS DISCRETAS que `.camp-tab`: subrayado en vez de píldora
   rellena. Si se vieran igual, la barra parecería dos filas de pestañas del mismo
   nivel y se perdería la jerarquía «qué gestiono» → «de qué canal». */
.camp-subtabs {
  display: flex;
  gap: 4px;
  margin: -6px 0 18px;
  border-bottom: 1px solid var(--border);
}
.camp-subtab {
  appearance: none;
  background: transparent;
  border: 0;
  border-bottom: 2px solid transparent;
  color: var(--muted);
  cursor: pointer;
  font-family: inherit;
  font-size: 0.8125rem;
  font-weight: 600;
  padding: 9px 16px;
  margin-bottom: -1px;      /* el borde activo se apoya en el del contenedor */
  transition: color 0.15s, border-color 0.15s;
}
.camp-subtab:hover:not(.camp-subtab--active) {
  color: var(--text);
}
.camp-subtab--active {
  color: var(--brand);
  border-bottom-color: var(--brand);
}

/* Cadena de reenganche: los saltos de una campaña y sus hijas, en fila.
   Scroll horizontal propio para que una cadena larga no ensanche la página. */
.camp-chain {
  display: flex;
  gap: 10px;
  align-items: stretch;
  overflow-x: auto;
  padding: 10px 0 4px;
}
.camp-chain-step {
  flex: 0 0 auto;
  min-width: 220px;
  padding: 12px 14px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
  position: relative;
}
/* La flecha que une un salto con el siguiente. */
.camp-chain-step + .camp-chain-step::before {
  content: "→";
  position: absolute;
  left: -16px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--muted-2);
}
.camp-chain-step--active {
  border-color: var(--brand);
  box-shadow: inset 3px 0 0 var(--brand);
}
.camp-chain-depth {
  font-size: 0.7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted-2);
  margin-bottom: 4px;
}

/* ── 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: var(--brand); }

.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: var(--brand-dark);
  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: var(--brand); }
.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 ── */
.badge--paused { background: rgba(245,158,11,0.15); color: #b45309; }

/* ============================================================
   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: var(--brand);
}

.ticket-picker-top {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
}

.ticket-picker-ref {
  font-size: 0.72rem;
  font-weight: 700;
  color: var(--brand);
  background: rgba(var(--brand-rgb),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(var(--brand-rgb),0.20); }
.badge--ticket-open { background: rgba(var(--brand-rgb),0.22); outline: 2px solid rgba(var(--brand-rgb),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: var(--brand);
}
.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;
}
.lc-close-modal-x:hover { background: var(--muted-2); 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);
  background: var(--surface);
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
  cursor: pointer;
}
.lc-close-select:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px rgba(var(--brand-rgb),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);
}
.lc-close-textarea:focus {
  border-color: var(--brand);
  box-shadow: 0 0 0 3px rgba(var(--brand-rgb),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;
}

.ticket-detail-body {
  padding: 0 24px;
  overflow-y: auto;
  max-height: 62vh;
  display: flex;
  flex-direction: column;
}

.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; }

.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;
}

/* Detalle simple clave→valor (modales de detalle: tickets, tareas, canales,
   personalidad, encuestas…). Genérico para no repetir el layout por módulo. */
.detail-row {
  display: grid;
  grid-template-columns: 170px 1fr;
  gap: 14px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
  align-items: start;
}
.detail-row:last-child { border-bottom: none; }
.detail-label {
  font-size: 0.74rem;
  font-weight: 600;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.detail-value { font-size: 0.88rem; color: var(--text); line-height: 1.5; word-break: break-word; }
.detail-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.detail-chip {
  display: inline-flex;
  align-items: center;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 3px 10px;
  font-size: 0.78rem;
  color: var(--text);
}

/* 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-soft-fg); border-color: rgba(var(--brand-rgb), 0.35); }
.btn-detail:hover { background: rgba(var(--brand-rgb), 0.18); }

/* ============================================================
   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-dark); 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);
}
/* Hover en oscuro: aclarar levemente SIN perder el texto (antes #cbd5e1 dejaba
   texto claro sobre fondo claro = ilegible). En claro lo pisa el override de 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 ──
   Dos niveles, como el Centro de Control: el nivel 1 usa .control-tabs /
   .control-tab y el nivel 2 .cc-subtabs / .cc-subtab (estilos en el bloque de
   Centro de Control). Aquí solo queda la alineación a la izquierda. */
.profile-main .cc-group-tabs { margin-bottom: 14px; }
.profile-tabs { justify-content: flex-start; }

/* ── 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(var(--brand-dark-rgb),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(var(--brand-rgb),0.3);
  background: rgba(var(--brand-rgb),0.07);
  color: var(--brand-dark);
  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;
}

/* Las barras de filtros propias de Monitor (.monitor-filters /
   .monitor-filter-field) se retiraron: las cuatro pestañas usan la toolbar
   estándar (.tickets-toolbar + embudo). */

.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: var(--surface-3);
  color: var(--text);
  border: 1px solid var(--border);
  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: rgba(var(--brand-rgb), 0.35);
  color: var(--brand-soft-fg);
  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;
}

/* ── PAGINACIÓN ESTÁNDAR ──────────────────────────────────────────────────────
   Anterior / info / Siguiente centrados bajo la tabla. El de Pagos es el
   canónico; Monitor, Tickets, Contactos y Marketplace se cuelgan de aquí.
   Añadir un módulo = sumar su clase a estas listas, no crear otro pager.
   Centrado (no pegado a la derecha) para que el bloque quede simétrico con la
   tabla, que ocupa el ancho completo. */
.monitor-pagination,
.pg-pager,
.ticket-pagination,
.audit-pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  margin-top: 14px;
  flex-wrap: wrap;
}

.monitor-page-info,
.pg-pager > span,
.ticket-pagination-info,
.ticket-pagination-page,
.audit-page-info {
  color: var(--muted);
  font-size: 0.82rem;
}

/* Los extremos se ven bloqueados, sin texto que lo explique. */
.monitor-pagination button:disabled,
.pg-pager button:disabled,
.ticket-pagination button:disabled,
.audit-pagination button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.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: var(--brand);
  box-shadow: 0 14px 34px rgba(var(--brand-dark-rgb),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-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: var(--brand-soft-fg); 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: var(--brand-dark); }
.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: var(--brand);
  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: var(--muted-2);
  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;
}

.wf-toggle-btn.active {
  background: var(--panel-2) !important;
  color: var(--text) !important;
  border-color: var(--text-strong);
}

/* 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: var(--muted-2); border-radius: 2px; }

/* Empty state */
.wf-empty-state {
  text-align: center;
  padding: 48px 20px;
  color: var(--muted);
  background: var(--surface-3);
  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; }
.wf-badge--running { background: rgba(79,110,247,0.2);  color: #6c8af7; }
.wf-badge--done    { background: rgba(34,197,94,0.15);  color: #22c55e; }
.wf-badge--error   { background: rgba(239,68,68,0.15);  color: #ef4444; }

/* 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: var(--text); 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(var(--brand-rgb), 0.30);
  background: rgba(var(--brand-rgb), 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; }
/* Cabecera del apartado (barra 1): plegado + título + tooltip + conteo. El conteo
   se ve siempre, también con el apartado colapsado. */
.mm-sec-head { display: flex; align-items: center; gap: 8px; }
.mm-sec-head .mm-section-title { margin: 0; display: inline-flex; align-items: center; gap: 6px; }
.mm-sec-toggle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0;
  border: 1px solid var(--control-border); border-radius: 8px;
  background: var(--control-bg); color: var(--text);
  cursor: pointer;
}
.mm-sec-toggle:hover { background: var(--control-bg-hover); }
.mm-caret { transition: transform 0.15s ease; }
.mm-caret.is-open { transform: rotate(90deg); }
.mm-count {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 22px; padding: 0 7px;
  border-radius: 999px;
  background: var(--brand-soft-bg); color: var(--brand-soft-fg);
  font-size: 0.75rem; font-weight: 700;
}
.mm-buckets {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 12px;
  margin-top: 16px;
}
/* Menú ⋮ de una tarjeta (disco, carpeta o archivo): SIEMPRE visible, no solo en
   hover — es el único acceso a "Eliminar". */
.mm-menu { position: absolute; top: 8px; right: 8px; }
.mm-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);
  cursor: pointer;
}
.mm-dots:hover { background: var(--control-bg-hover); color: var(--text); border-color: var(--control-border); }
.mm-menu-pop {
  position: absolute; top: 30px; right: 0; z-index: 60;
  min-width: 168px; padding: 5px;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface-overlay);
  box-shadow: var(--shadow-lg);
}
.mm-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;
}
.mm-menu-item:hover { background: var(--control-bg-hover); }
.mm-menu-item.is-danger { color: #ef4444; }
.mm-menu-item.is-danger:hover { background: rgba(239, 68, 68, 0.12); }

/* El menú de orden y el segmented de vista los aporta la toolbar estándar
   (.tb-sort / .tb-viewseg en components/toolbar.rs). Aquí solo queda el estado
   activo del menú ⋮ y la separación de la toolbar dentro de la tarjeta. */
.mm-menu-item.is-active { color: var(--brand); }
.mm-card .tb { margin-top: 14px; }

/* ── Discos colapsados: tira horizontal de píldoras ─────────────
   Permite seleccionar/borrar sin desplegar el apartado. Scroll en X cuando no
   caben; el nombre se trunca con ellipsis (completo en el `title`). */
.mm-chips {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
  padding-bottom: 4px;
  overflow-x: auto;
  scrollbar-width: thin;
}
.mm-chips-empty { color: var(--muted); font-size: 0.82rem; }
.mm-chip {
  position: relative;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  max-width: 190px;
  padding: 6px 4px 6px 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  cursor: pointer;
  transition: box-shadow 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}
/* Sin `transform` en hover: un ancestro transformado ancla los `position: fixed`
   y el desplegable ⋮ volvería a recortarse contra el scroll de la tira. */
.mm-chip:hover { border-color: var(--brand); box-shadow: var(--shadow-md); }
.mm-chip--active {
  border-color: var(--brand);
  background: rgba(var(--brand-rgb), 0.06);
  box-shadow: 0 0 0 1px var(--brand) inset;
}
.mm-chip-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text);
}
/* El ⋮ va en el flujo de la píldora (no absoluto como en la tarjeta). Su
   desplegable escapa del recorte del scroll con `position: fixed`, pero las
   coordenadas las calcula `menu_pop_style` (CardMenu fixed=true) desde el rect
   del botón: sin ellas caería al final del flujo, lejos del ⋮. */
.mm-chips .mm-menu { position: static; }
.mm-chips .mm-dots { width: 22px; height: 22px; }

/* Colapso animado del apartado de Discos: el contenido NO se desmonta (si lo
   hiciera no habría transición de salida); se anima su altura con grid. */
.mm-collapse {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transition: grid-template-rows 0.22s ease, opacity 0.18s ease;
}
.mm-collapse.is-open { grid-template-rows: 1fr; opacity: 1; }
.mm-collapse-inner { overflow: hidden; min-height: 0; }
/* Ya abierto no recorta: si no, el desplegable ⋮ de la última fila se corta contra
   el borde del contenedor. Al cerrar vuelve a `hidden` y la altura sigue animando. */
.mm-collapse.is-open .mm-collapse-inner { overflow: visible; }

/* Entrada del listado al navegar entre carpetas. */
@keyframes mm-fade-up {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}
.mm-objects-anim { animation: mm-fade-up 0.18s ease both; }

/* Esqueletos mientras carga el directorio. */
.mm-skeleton {
  height: 108px; border-radius: 12px;
  border: 1px solid var(--border);
  background: linear-gradient(90deg, var(--surface-2) 25%, var(--control-bg-hover) 37%, var(--surface-2) 63%);
  background-size: 400% 100%;
  animation: mm-shimmer 1.2s ease-in-out infinite;
}
@keyframes mm-shimmer {
  from { background-position: 100% 50%; }
  to   { background-position: 0 50%; }
}
.mm-explorer-status {
  display: flex; align-items: center; gap: 12px;
  margin: 12px 0 4px; font-size: 0.8rem; color: var(--muted);
}
.mm-loading { display: inline-flex; align-items: center; gap: 7px; }
.mm-spinner {
  width: 13px; height: 13px; border-radius: 50%;
  border: 2px solid var(--control-border); border-top-color: var(--brand);
  animation: mm-spin 0.7s linear infinite;
}
@keyframes mm-spin { to { transform: rotate(360deg); } }

/* Zona de arrastre: la tarjeta entera del explorador acepta archivos. */
.mm-card.mm-dropzone {
  border-color: var(--brand);
  box-shadow: 0 0 0 2px rgba(var(--brand-rgb), 0.18) inset;
}
.mm-file-hidden { display: none; }
/* Modal de detalles: pares etiqueta/valor, el valor puede ser una ruta larga. */
.mm-details { margin: 4px 0 6px; padding: 0; display: grid; gap: 2px; }
.mm-details-row {
  display: grid;
  grid-template-columns: 116px minmax(0, 1fr);
  gap: 10px;
  padding: 7px 0;
  border-bottom: 1px solid var(--border-soft);
  font-size: 0.84rem;
}
.mm-details-row:last-child { border-bottom: 0; }
.mm-details dt { color: var(--muted); }
.mm-details dd { margin: 0; color: var(--text); overflow-wrap: anywhere; }
.mm-details-path {
  margin: 0 0 10px;
  font-size: 0.8rem;
  color: var(--muted);
  overflow-wrap: anywhere;
}

.mm-upload-list {
  margin: 0 0 4px; padding: 10px 12px 10px 26px;
  max-height: 190px; overflow-y: auto;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface-2);
  font-size: 0.82rem; color: var(--text);
}

/* ── Vista de lista: FILAS de verdad, tipo explorador de archivos ──────────────
   No son tarjetas estiradas: sin caja propia, sin relleno de miniatura, icono
   pequeño a la izquierda, nombre que ocupa el ancho y metadatos a la derecha.
   Solo las separa una línea y el hover pinta la fila entera. */
.mm-buckets.is-list,
.mm-objects.is-list {
  display: block;
  border: 1px solid var(--border);
  border-radius: 10px;
  /* `overflow: hidden` recortaría el desplegable ⋮ de las últimas filas; el
     redondeo se consigue en la primera y la última fila. */
  overflow: visible;
  background: var(--surface);
}
.mm-buckets.is-list .mm-bucket:first-child,
.mm-objects.is-list .mm-object:first-child { border-radius: 9px 9px 0 0; }
.mm-buckets.is-list .mm-bucket:last-child,
.mm-objects.is-list .mm-object:last-child { border-radius: 0 0 9px 9px; }
.mm-buckets.is-list .mm-bucket,
.mm-objects.is-list .mm-object {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 12px;
  border: 0;
  border-bottom: 1px solid var(--border-soft);
  border-radius: 0;
  background: transparent;
  box-shadow: none;
  text-align: left;
  /* Nada de elevación/escala en filas: desalinea la lista. */
  transform: none;
}
.mm-buckets.is-list .mm-bucket:last-child,
.mm-objects.is-list .mm-object:last-child { border-bottom: 0; }
.mm-buckets.is-list .mm-bucket:hover,
.mm-objects.is-list .mm-object:hover {
  transform: none;
  box-shadow: none;
  border-color: var(--border-soft);
  background: var(--control-bg-hover);
}
.mm-buckets.is-list .mm-bucket--active {
  background: var(--brand-soft-bg);
  box-shadow: inset 3px 0 0 var(--brand);
}

/* Icono/miniatura de la fila: cuadrado pequeño, sin fondo de tarjeta. */
.mm-objects.is-list .mm-fileicon,
.mm-objects.is-list .mm-thumb {
  flex: 0 0 26px;
  width: 26px;
  height: 26px;
  min-height: 0;
  border-radius: 5px;
  font-size: 0.58rem;
  letter-spacing: 0.02em;
  background: transparent;
  object-fit: cover;
}
.mm-objects.is-list .mm-thumb { background: var(--panel-2); }
.mm-objects.is-list .mm-foldericon { font-size: 1.05rem; background: transparent; }

/* Nombre a la izquierda ocupando el hueco, metadatos alineados a la derecha. */
.mm-objects.is-list .mm-object-info {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding: 0;
}
.mm-objects.is-list .mm-object-key { flex: 1 1 auto; padding-right: 0; }
.mm-objects.is-list .mm-item-desc {
  flex: 0 0 auto;
  text-align: right;
  font-size: 0.78rem;
  white-space: nowrap;
}

/* Discos en fila: nombre + uso + etiquetas en una sola línea. */
.mm-buckets.is-list .mm-bucket-name { flex: 1 1 auto; min-width: 0; padding-right: 0; }
.mm-buckets.is-list .mm-usage {
  flex: 0 0 auto;
  flex-direction: row;
  align-items: center;
  gap: 8px;
  margin: 0;
  width: 240px;
}
.mm-buckets.is-list .mm-usage-track { width: 90px; flex: 0 0 90px; }
.mm-buckets.is-list .mm-usage-text { white-space: nowrap; }
.mm-buckets.is-list .mm-bucket-tags { flex: 0 0 auto; margin: 0; }

/* El ⋮ deja de flotar en la esquina y cierra la fila. */
.mm-buckets.is-list .mm-menu,
.mm-objects.is-list .mm-menu { position: relative; top: auto; right: auto; flex: 0 0 auto; order: 9; }
.mm-buckets.is-list .mm-menu .mm-menu-pop,
.mm-objects.is-list .mm-menu .mm-menu-pop { top: 30px; right: 0; }

/* Esqueletos de carga en modo lista: barras, no tarjetas. */
.mm-objects.is-list.mm-skeletons { padding: 0; }
.mm-objects.is-list .mm-skeleton { height: 40px; border: 0; border-radius: 0; border-bottom: 1px solid var(--border-soft); }

.mm-bucket {
  position: relative;                          /* ancla del menú ⋮ */
  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(var(--brand-rgb), 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;
}
/* Realce al pasar el ratón: leve elevación + escala, como las tarjetas de disco.
   `position: relative` ancla el menú ⋮ de la tarjeta. */
.mm-object:hover { transform: translateY(-2px) scale(1.02); box-shadow: var(--shadow-md); border-color: var(--brand); }
.mm-object .mm-object-key { padding-right: 26px; }
.mm-object {
  position: relative;
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: visible;
  background: var(--surface);
  display: flex;
  flex-direction: column;
  cursor: pointer;
  transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}
.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%, var(--surface-3) 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 ─────── */
/* padding-right: deja libre la esquina del menú ⋮ (nombres largos no se le meten debajo). */
.mm-bucket-name { font-weight: 700; color: var(--text); padding-right: 30px; }
.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(var(--brand-rgb), 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(var(--brand-rgb), 0.14), rgba(var(--brand-rgb), 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);
}
/* El modal apila un campo por línea; la única fila de dos columnas es número +
   unidad, y la unidad no se estira. */
.mm-modal { overflow-x: hidden; }
.mm-modal .mm-input, .mm-modal .mm-select { width: 100%; min-width: 0; box-sizing: border-box; }
.mm-field-row--unit { display: flex; gap: 8px; align-items: center; flex-wrap: nowrap; }
.mm-field-row--unit .mm-input { flex: 1 1 auto; min-width: 0; }
.mm-field-row--unit .mm-unit { flex: 0 0 88px; width: 88px; }
.mm-modal .switch-field { margin: 2px 0 4px; }

.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; }
.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); color: #fff; border-color: var(--brand); }
.qa-btn--primary:hover:not(:disabled) { background: var(--brand-dark); }
.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: var(--brand); }
.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: var(--brand-soft-fg); border: 1px solid rgba(var(--brand-rgb), 0.35); }
.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(var(--brand-dark-rgb),0.12);  color: var(--brand-soft-fg);  border-color: rgba(var(--brand-rgb),0.28); }
.btn-detail:hover:not(:disabled)  { background: rgba(var(--brand-dark-rgb),0.22);  border-color: rgba(var(--brand-rgb),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: var(--muted);
}

.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: var(--text);
  font: inherit;
  font-size: 0.82rem;
}

.input-req-row select option { background: var(--panel-2); color: var(--text); }

.input-req-row select:focus,
.input-req-row input[type="text"]:focus {
  outline: none;
  border-color: rgba(var(--brand-rgb),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
   ============================================================ */

.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;
}

/* Marca (izquierda del header en /home): logo + nombre del panel. */
.ph-brand {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.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: var(--text-strong);
}

.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;
}
/* Un iconset provee un SVG monocromo → tamaño acorde al emoji del header
   (el emoji se dimensiona por font-size; hereda color via currentColor). */
.ph-icon svg { width: 1.1875rem; height: 1.1875rem; display: block; }

.ph-title-wrap {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}

.ph-title {
  font-size: 0.9375rem;
  font-weight: 700;
  color: var(--text-strong);
  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: var(--text-strong);
}

.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(var(--brand-rgb), 0.1);
  border-color: rgba(var(--brand-rgb), 0.18);
  color: var(--brand-soft-fg);
}

.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);
  /* Clickeable → Mi Perfil. Reset de botón + mismo hover que los vecinos. */
  cursor: pointer;
  font-family: inherit;
  text-align: left;
  transition: background 0.18s, border-color 0.18s, transform 0.15s, box-shadow 0.18s;
}

.ph-user-avatar {
  width: 28px;
  height: 28px;
  border-radius: 7px;
  background: linear-gradient(135deg, var(--brand) 0%, var(--brand-dark) 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: var(--text-strong);
  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, transform 0.15s, box-shadow 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 */

/* Cuadrado, coherente con la campana de notificaciones (misma forma). */
/* El botón de guía comparte estilo con el de tema: son hermanos en la fila de
   controles del header y deben leerse como el mismo tipo de control. */
.ph-theme-btn,
.ph-guide-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 10px;
  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, box-shadow 0.18s;
  flex-shrink: 0;
}
.ph-theme-btn:hover,
.ph-guide-btn:hover {
  background: rgba(255,255,255,0.12);
  border-color: rgba(255,255,255,0.22);
}

/* El de ayuda va un punto más marcado que el de tema. No es capricho: el de tema
   se busca cuando se quiere, mientras que este tiene que ENCONTRARLO alguien que
   está perdido — y quien está perdido no rastrea una fila de iconos tenues.
   Sigue por debajo de la campana, que avisa de cosas que sí urgen. */
.ph-guide-btn {
  color: #fff;
  border-color: rgba(255,255,255,0.28);
  background: rgba(255,255,255,0.14);
}
.ph-guide-btn:hover {
  background: rgba(255,255,255,0.24);
  border-color: rgba(255,255,255,0.42);
}
.ph-guide-btn:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

/* Hover unificado de los botones de la derecha del header (tema, campana, chip de
   usuario, salir): aumento de escala + leve iluminación. */
.ph-theme-btn:hover,
.ph-notif-btn:hover,
.ph-user-chip:hover,
.ph-logout:hover {
  transform: scale(1.08);
  box-shadow: 0 0 0 1px rgba(255,255,255,0.12), 0 3px 12px rgba(0,0,0,0.28);
}
.ph-user-chip:hover {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.14);
}

/* ── Header con color del tema (switch de identidad visual, owner) ──────────
   La barra adopta el brand en vez de la superficie neutra; el contenido pasa a
   texto claro de alto contraste sobre la marca. */
.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-theme-btn,
.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-theme-btn:hover,
.ph--themed .ph-user-chip:hover { background: rgba(255, 255, 255, 0.22); }

/* 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:                #eef1f7;
  --bg-2:              #e6ebf1;
  --surface:           #fbfcfd;
  --surface-2:         #eef1f7;
  --surface-3:         #e6ebf1;
  --surface-overlay:   rgba(251,252,253,0.98);
  --panel:             rgba(251,252,253,0.96);
  --panel-2:           rgba(238,241,247,0.92);
  --control-bg:        #fbfcfd;
  --control-bg-hover:  #e6ebf1;
  --control-border:    rgba(87,45,75,0.16);
  --scrim:             rgba(32,24,35,0.45);
  --text:              #332c3a;
  --text-strong:       #201823;
  --muted:             #6b6575;
  --muted-2:           #9c9ba9;
  --border:            rgba(87,45,75,0.12);
  --border-soft:       rgba(87,45,75,0.07);
  /* Marca en CLARO: la ciruela pura es el acento (contraste 10.5:1 sobre #fbfcfd)
     y --brand-dark es su versión más profunda para hover/estados activos. Es la
     inversión exacta del par de :root (ver comentario allí). */
  --brand:             #572d4b;
  --brand-dark:        #3f2036;
  --brand-rgb:         87, 45, 75;
  --brand-dark-rgb:    63, 32, 54;
  --brand-soft-bg:     rgba(87,45,75,0.10);
  --brand-soft-fg:     #572d4b;
  --accent:            #201823;
  /* Chrome de navegación en CLARO: mismo mecanismo que en :root, pero el tinte de
     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). */
  --nav-bg:            #f4f2f5;
  --nav-bg:            color-mix(in srgb, var(--brand) 4%, var(--surface));
  --nav-bg-2:          #f0edf2;
  --nav-bg-2:          color-mix(in srgb, var(--brand) 7%, var(--surface));
  --nav-border:        rgba(87,45,75,0.12);
  /* En claro el velo es mucho más suave: sobre superficie clara, un 30% de negro
     pintaría un panel gris sucio en vez de un escalón de profundidad. */
  --nav-shade:         rgba(0,0,0,0.055);
  --tooltip-bg:        #2b1f27;
  --tooltip-fg:        #fbfcfd;
  --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:  #e6ebf1; --badge-neutral-fg: #6b6575;
  --badge-purple-bg:   #f3e8ef; --badge-purple-fg:  #572d4b;
  --shadow-sm:  0 1px 2px rgba(32,24,35,0.05);
  --shadow-md:  0 4px 6px rgba(32,24,35,0.07), 0 2px 4px rgba(32,24,35,0.06);
  --shadow-lg:  0 10px 25px rgba(32,24,35,0.12), 0 4px 8px rgba(32,24,35,0.06);
  /* Gráficas · claro. Los mismos tonos, bajados de claridad: los del modo oscuro
     están pensados para brillar sobre carbón y sobre blanco se lavan. */
  --chart-1:        #2563eb;
  --chart-2:        #0e8a63;
  --chart-3:        #b45309;
  --chart-4:        #6d4aff;
  --chart-5:        #dc2626;
  --chart-6:        #64748b;
  --chart-grid:      #e2e6ed;
  --chart-axis:      #5a6270;
  --chart-legend:    #332c3a;
  --chart-datalabel: #ffffff;
}

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:           #332c3a;
  --text-strong:    #201823;
  --muted:          #6b6575;
  --muted-2:        #9c9ba9;
  --border:         rgba(87,45,75,0.12);
  --border-soft:    rgba(87,45,75,0.07);
  --surface:        #fbfcfd;
  --surface-2:      #eef1f7;
  --control-bg:     #fbfcfd;
  --control-bg-hover: #e6ebf1;
  --control-border: rgba(87,45,75,0.16);
  /* La tarjeta es clara en ambos temas → su marca debe ser la variante CLARA
     (ciruela pura), no la aclarada de :root, que sobre blanco no contrasta. */
  --brand:          #572d4b;
  --brand-dark:     #3f2036;
  --brand-rgb:      87, 45, 75;
  --brand-dark-rgb: 63, 32, 54;
  --brand-soft-bg:  rgba(87,45,75,0.10);
  --brand-soft-fg:  #572d4b;
}

html.light-mode .page-container { background: var(--bg); }

/* .app-header / .ph / .module-sidebar / .home-sidebar NO se overridean aquí:
   sus tokens --nav-* ya tienen valor propio por tema (ver bloque html.light-mode). */
html.light-mode .app-header {
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
}

html.light-mode .app-header::after {
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(var(--brand-rgb), 0.2) 25%,
    rgba(var(--brand-rgb), 0.28) 50%,
    rgba(var(--brand-rgb), 0.2) 75%,
    transparent 100%
  );
}

html.light-mode .app-title {
  color: var(--text-strong);
}

html.light-mode .home-container {
  background: var(--bg);
}


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(var(--brand-rgb), 0.07);
  color: var(--brand-dark);
}

html.light-mode .home-welcome-title {
  color: var(--text-strong);
}

html.light-mode .home-welcome-sub {
  color: var(--muted);
}

/* Dentro del banner el saludo va SOBRE una imagen o un degradado de marca, no
   sobre el fondo del panel: sigue siendo blanco también en tema claro. Hay que
   repetirlo aquí con el prefijo `html.light-mode` porque las dos reglas de
   arriba son más específicas que `.home-banner--overlay .home-welcome-title` y
   pintaban el texto oscuro sobre el banner oscuro. */
html.light-mode .home-banner--overlay .home-welcome-title,
html.light-mode .home-banner--overlay .home-welcome-sub {
  color: #fff;
}

html.light-mode .mod-card {
  background: var(--surface);
  border-color: rgba(226, 232, 240, 0.8);
  box-shadow: 0 1px 3px rgba(0,0,0,0.06), 0 4px 16px rgba(0,0,0,0.04);
}
html.light-mode .mod-name { color: var(--text-strong); }

html.light-mode .ph {
  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: var(--brand); }
html.light-mode .ph-divider { background: rgba(0,0,0,0.1); }

html.light-mode .ph-back {
  color: var(--muted);
  border-color: rgba(0,0,0,0.08);
  background: rgba(0,0,0,0.03);
}
html.light-mode .ph-back:hover {
  color: var(--text-strong);
  background: rgba(0,0,0,0.07);
}

/* Tema y chip de usuario: misma superficie que la campana (--control-bg = #ffffff
   en claro). Antes usaban un negro translúcido que sobre el header se leía sucio. */
html.light-mode .ph-theme-btn,
html.light-mode .ph-user-chip {
  background: var(--control-bg);
  border-color: var(--control-border);
  color: var(--text);
}
html.light-mode .ph-theme-btn:hover,
html.light-mode .ph-user-chip:hover {
  background: var(--control-bg-hover);
  border-color: var(--control-border);
}

/* Salir sigue siendo rojo en claro (igual que en oscuro), solo se oscurece el
   tinte para que contraste sobre fondo blanco. */
html.light-mode .ph-logout {
  background: rgba(239, 68, 68, 0.08);
  border-color: rgba(239, 68, 68, 0.28);
  color: #dc2626;
}
html.light-mode .ph-logout:hover {
  background: rgba(239, 68, 68, 0.16);
  border-color: rgba(239, 68, 68, 0.42);
  color: #b91c1c;
}

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(var(--brand-rgb),0.08);
  color: var(--brand);
}

/* (la superficie del chip se define arriba, junto a la del botón de tema) */
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(var(--brand-rgb),0.15);
  color: var(--brand);
}

html.light-mode .ticket-panel,
html.light-mode .camp-content,
html.light-mode .users-table-wrap,
html.light-mode .perms-table,
html.light-mode .control-form-panel,
html.light-mode .tools-card,
html.light-mode .table-wrapper,
html.light-mode .contact-detail-panel {
  background: var(--panel) !important;
  border-color: rgba(0,0,0,0.08) !important;
  box-shadow: 0 2px 16px rgba(0,0,0,0.06);
}

/* SEGMENTED en tema claro: misma bandeja para todas las barras de tabs. Si añades
   una barra nueva al bloque canónico, súmala también aquí. */
html.light-mode .ticket-tabs,
html.light-mode .camp-tabs,
html.light-mode .metrics-tabs,
html.light-mode .metrics-agent-tabs,
html.light-mode .notif-tabs,
html.light-mode .mir-tabs,
html.light-mode .mir-dtabs,
html.light-mode .control-tabs {
  background: var(--panel);
  border-color: rgba(0,0,0,0.08);
}
html.light-mode .ticket-tabs button,
html.light-mode .camp-tab,
html.light-mode .metrics-tab,
html.light-mode .metrics-subtab,
html.light-mode .notif-tabs button,
html.light-mode .mir-tab,
html.light-mode .mir-dtab,
html.light-mode .control-tab { color: var(--muted); }

/* :not(...-active) obligatorio: sin él, pasar el ratón por el tab ACTIVO le pone
   texto oscuro encima del pill sólido de marca → texto invisible en claro. */
html.light-mode .ticket-tabs button:hover:not(.active),
html.light-mode .camp-tab:hover:not(.camp-tab--active),
html.light-mode .metrics-tab:hover:not(.active),
html.light-mode .metrics-subtab:hover:not(.active),
html.light-mode .notif-tabs button:hover:not(.active),
html.light-mode .control-tab:hover:not(.active) {
  background: rgba(0,0,0,0.04);
  color: var(--text-strong);
}
/* La pill activa va SÓLIDA de marca también en claro (antes usaba el tinte
   translúcido --brand-soft-bg y se leía como "sin seleccionar"). Mismo aspecto
   que el resto de barras segmented del panel. */
html.light-mode .control-tab.active {
  background: var(--brand-dark) !important;
  color: #fff !important;
}

html.light-mode .contacts-table th {
  background: rgba(0,0,0,0.04);
  color: var(--muted);
  border-bottom-color: rgba(0,0,0,0.09);
}
html.light-mode .contacts-table td {
  color: var(--text-strong);
  border-bottom-color: rgba(0,0,0,0.05);
}
html.light-mode .contacts-table tr:hover td {
  background: rgba(var(--brand-rgb),0.04);
}
html.light-mode .contact-row:hover td {
  background: var(--brand-soft-bg);
}

html.light-mode .users-table th {
  background: rgba(0,0,0,0.04);
  color: var(--muted);
  border-bottom-color: rgba(0,0,0,0.09);
}
html.light-mode .users-table td {
  color: var(--text-strong);
  border-bottom-color: rgba(0,0,0,0.05);
}
html.light-mode .users-table tr:hover td {
  background: rgba(var(--brand-rgb),0.04);
}

html.light-mode .camp-table td {
  border-bottom-color: rgba(0,0,0,0.05);
}
html.light-mode .camp-table tr:hover td {
  background: rgba(var(--brand-rgb),0.04);
}

html.light-mode .perms-table th {
  background: rgba(0,0,0,0.04);
  color: var(--muted);
}
html.light-mode .perms-table td {
  border-bottom-color: rgba(0,0,0,0.05);
}
html.light-mode .perms-table tr:hover td {
  background: rgba(var(--brand-rgb),0.04);
}

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: var(--panel) !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(var(--brand-rgb),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: var(--panel);
  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; }

html.light-mode .home-card,
html.light-mode .mod-card {
  background: var(--panel);
  border-color: rgba(0,0,0,0.08);
  box-shadow: 0 2px 12px rgba(0,0,0,0.06);
}
html.light-mode .home-card:hover,
html.light-mode .mod-card:hover {
  background: var(--surface);
  box-shadow: 0 4px 20px rgba(0,0,0,0.1);
}
html.light-mode .mod-card-title,
html.light-mode .home-card-title { color: var(--text-strong); }
html.light-mode .mod-card-desc,
html.light-mode .home-card-desc  { color: var(--muted); }

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: var(--text); }
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: var(--brand-dark); }
html.light-mode .messages-list          { background: var(--surface-2); }
html.light-mode .livechat-sidebar       { background: var(--surface); border-right-color: var(--text); }
html.light-mode .livechat-filters       { border-bottom-color: var(--text); }
html.light-mode .lc-topbar              { border-bottom-color: var(--text); }
html.light-mode .livechat-filters select,
html.light-mode .lc-filters-popover select { background: var(--surface); border-color: var(--border); color: var(--text); 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,
html.light-mode .lc-filters-popover select option { background: var(--surface); }
html.light-mode .livechat-filters select:focus,
html.light-mode .lc-filters-popover select:focus  { border-color: var(--brand); background-color: var(--surface); }
html.light-mode .filter-pill            { background: var(--surface-2); border-color: var(--border); color: var(--muted); }
html.light-mode .filter-pill:hover      { background: var(--surface-2); color: var(--text); }
html.light-mode .filter-pill--active    { background: rgba(var(--brand-rgb),0.1) !important; border-color: rgba(var(--brand-rgb),0.35) !important; color: var(--brand-dark) !important; }
html.light-mode .conv-item:hover        { background: var(--surface-2); }
html.light-mode .conv-item--selected    { background: rgba(var(--brand-rgb),0.08) !important; border-color: rgba(var(--brand-rgb),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 .ticket-summary-card    { background: var(--surface); }
html.light-mode .contacts-channel-bar   { background: var(--surface); }
html.light-mode .contacts-subbar        { background: var(--surface); }
html.light-mode .contacts-filters-popover .contacts-channel-bar { background: transparent; }
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 .metrics-kpi-card       { background: var(--surface); }
html.light-mode .metrics-kpi-value      { color: var(--text-strong); }
html.light-mode .metrics-chart-card     { background: var(--surface); }
html.light-mode .metrics-chart-title    { color: var(--text-strong); }
html.light-mode .contact-card           { background: var(--surface); }
html.light-mode .monitor-health-card    { background: var(--surface); }
html.light-mode .qa-card                { background: var(--surface); box-shadow: 0 1px 4px rgba(0,0,0,0.04); }
html.light-mode .qa-btn                 { background: var(--surface); }
html.light-mode .qa-btn:hover:not(:disabled) { background: var(--surface-2); }
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 grupo SEGMENTED de tema claro más arriba.
   Estaban duplicados aquí y, al ir después, se comían la bandeja unificada. */

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); }

html.light-mode .badge-green  { background: var(--badge-success-bg); color: var(--badge-success-fg); }
html.light-mode .badge-yellow { background: var(--badge-warn-bg); color: var(--badge-warn-fg); }
html.light-mode .badge-red    { background: var(--badge-danger-bg); color: var(--badge-danger-fg); }
html.light-mode .badge-blue   { background: var(--badge-info-bg); color: var(--badge-info-fg); }
html.light-mode .badge-gray   { background: var(--surface-2); color: var(--muted); }
html.light-mode .badge-type   { background: var(--badge-purple-bg); color: var(--badge-purple-fg); }
html.light-mode .chip-active  { background: var(--badge-success-bg); color: var(--badge-success-fg); }
html.light-mode .chip-off     { background: var(--badge-danger-bg); color: var(--badge-danger-fg); }

/* Controles translúcidos (diseñados sobre oscuro) que se camuflan en claro */
html.light-mode .btn-secondary {
  background: var(--surface);
  border-color: rgba(0,0,0,0.12);
  color: var(--text-strong);
}
html.light-mode .btn-secondary:hover:not(:disabled) { background: var(--surface-2); }
html.light-mode .metrics-refresh-btn {
  background: var(--surface);
  border-color: rgba(0,0,0,0.12);
  color: var(--text-strong);
}
html.light-mode .metrics-refresh-btn:hover { background: var(--surface-2); }
/* .contacts-refresh-btn y .contacts-search-input ya no necesitan excepción: la
   toolbar estándar se define con tokens. Y un `background` en corto aquí
   borraría la lupa del buscador, que va como background-image. */
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 .kn-tipo-card           { background: var(--surface); border-color: var(--border); }
html.light-mode .kn-tipo-card:hover     { background: var(--surface-2); border-color: var(--brand); }
html.light-mode .kn-tipo-card.selected  { background: var(--surface-2); border-color: var(--brand); }
html.light-mode .camp-preview-bubble    { background: var(--surface); color: var(--text-strong); 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%;
  /* Neutro: hereda el color del contexto (texto de la tab). Sobre la tab activa
     (fondo de marca, texto blanco) el ícono se vuelve blanco → visible; sobre las
     inactivas usa el color atenuado. Adapta a claro/oscuro sin color de marca fijo. */
  background: color-mix(in srgb, currentColor 16%, transparent);
  color: inherit;
  opacity: 0.85;
  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;
  /* El globo es una FRASE, no una etiqueta: hereda del título donde se ancla, y
     esos títulos van en versalitas espaciadas (`.idv-field-label` y compañía).
     Sin este reseteo el texto de ayuda salía en mayúsculas: parecía un grito. */
  text-transform: none;
  letter-spacing: normal;
  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;
}

/* Tooltips de las tabs del Centro de Control (#8): la barra tiene scroll horizontal
   (recorta) y está volteada por transform (#1) → un tooltip descendiente NUNCA puede
   escapar por CSS. Se oculta el tooltip in-DOM y un script (index.html) pinta uno
   flotante `.cc-tab-tip` colgado de <body> con posición fixed, inmune a ambos. */
.control-tabs .info-tooltip-text { display: none; }

.cc-tab-tip {
  position: fixed;
  z-index: 2000;
  background: var(--tooltip-bg);
  color: var(--tooltip-fg);
  font-size: 12px;
  font-weight: 400;
  line-height: 1.45;
  padding: 9px 11px;
  border-radius: 8px;
  max-width: min(280px, calc(100vw - 32px));
  white-space: normal;
  box-shadow: var(--shadow-md);
  pointer-events: none;
  opacity: 0;
  transform: translateX(-50%);
  transition: opacity 0.15s ease;
}
.cc-tab-tip.is-visible { opacity: 1; }
.cc-tab-tip::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);
}

/* ── 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; }

.pg-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 12px; margin-bottom: 18px; }
.pg-card { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; padding: 14px 18px; box-shadow: var(--shadow-sm); }
.pg-card-n { font-size: 1.6rem; font-weight: 700; color: var(--text); line-height: 1.1; }
.pg-card-l { font-size: 0.78rem; color: var(--muted); margin-top: 4px; }
.pg-card--ok { border-color: rgba(16,185,129,0.45); background: var(--badge-success-bg); }

/* Pagos: KPIs de estado (clicables, filtran la tabla) separados por una divisoria
   del KPI de monto validado, que es solo lectura y va a la derecha. */
.pagos-page .pg-kpis { display: flex; align-items: stretch; gap: 14px; margin-bottom: 18px; flex-wrap: wrap; }
.pagos-page .pg-kpis > .pg-cards { flex: 1 1 480px; margin-bottom: 0; }
.pagos-page .pg-kpi-sep { flex: 0 0 1px; align-self: stretch; background: var(--border); }
.pagos-page .pg-kpi-total { flex: 0 0 auto; min-width: 190px; display: flex; flex-direction: column; justify-content: center; }
.pagos-page .pg-kpi-total-n { font-size: 1rem; }
/* Al envolver, la divisoria quedaría suelta como una línea de 1px: se oculta. */
@media (max-width: 720px) { .pagos-page .pg-kpi-sep { display: none; } }

.pg-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; }
.pg-input:focus { outline: 2px solid var(--brand-soft-fg); outline-offset: -1px; }

.pg-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; }
.pg-btn:hover:not(:disabled) { background: var(--control-bg-hover); }
/* Deshabilitado: se ve bloqueado sin necesidad de texto que lo explique. */
.pg-btn:disabled { opacity: 0.4; cursor: not-allowed; }
.pg-btn--primary { background: var(--brand); color: #fff; border-color: var(--brand); }
.pg-btn--primary:hover:not(:disabled) { background: var(--brand-dark); }
.pg-btn--danger { color: var(--badge-danger-fg); border-color: rgba(239,68,68,0.45); }
.pg-btn--danger:hover:not(:disabled) { background: var(--badge-danger-bg); }
.pg-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. */
.pg-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; }
/* Pagos: 8 columnas (sin la de SAE) y celda de acciones para 2 botones. */
.pagos-page .pg-row { grid-template-columns: 92px 1.2fr 110px 1.4fr 95px 1fr 110px 180px; min-width: 820px; }
/* El modo selección ya NO añade columna: se marca haciendo clic en la fila, como
   en Contactos y Campañas. La columna de casillas era de este módulo solo. */
/* La fila entera abre el detalle (la celda de acciones corta la propagación). */
.pagos-page .pg-row--click { cursor: pointer; }
.pagos-page .pg-row--click:hover { background: var(--control-bg-hover); }
/* E-commerce: tablas con columnas parejas (nº de columnas varía por tab, así que
   no se usa la grid fija de .pg-row global). Checkbox inline en el toolbar. */
.ecommerce-page .pg-row { display: flex; grid-template-columns: none; min-width: 720px; }
.ecommerce-page .pg-row > span { flex: 1 1 0; }
/* Preview de imagen dentro del drawer de producto (pane Imagen). */
.ec-img-preview { margin-top: 8px; max-width: 180px; max-height: 140px; border-radius: 8px; border: 1px solid var(--border); object-fit: cover; }

/* Título de un toggle (mir-switch-row) con su tooltip a la derecha. */
.ec-switch-title { display: inline-flex; align-items: center; gap: 6px; }

/* Bloque de imagen al inicio de la tab Datos: etiqueta + dropzone + preview apilados. */
.ec-img-block { display: flex; flex-direction: column; gap: 8px; margin-bottom: 14px; }
/* Dropzone de imagen: borde punteado, hover con color de marca y leve escala. */
.ec-dropzone { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 6px; padding: 26px 18px; text-align: center; cursor: pointer;
    border: 2px dashed var(--border); border-radius: 12px; background: var(--surface-2);
    color: var(--muted); transition: border-color .15s ease, background .15s ease, transform .15s ease, box-shadow .15s ease; }
.ec-dropzone:hover { border-color: var(--brand); color: var(--text); background: var(--brand-soft-bg);
    transform: scale(1.02); box-shadow: var(--shadow-sm); }
.ec-dropzone.is-drag { border-color: var(--brand); background: var(--brand-soft-bg); color: var(--text); transform: scale(1.03); }
.ec-dropzone-input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.ec-dropzone-ic { width: 34px; height: 34px; color: var(--brand); }
.ec-dropzone-text { font-weight: 600; font-size: 0.9rem; }
.ec-dropzone-hint { font-size: 0.78rem; color: var(--muted-2); }

/* Miniatura en la celda de producto (config mostrar_miniaturas). */
.ec-prod-cell { display: inline-flex; align-items: center; gap: 8px; }
.ec-thumb { width: 30px; height: 30px; border-radius: 6px; object-fit: cover; border: 1px solid var(--border); flex: 0 0 auto; }
/* Hueco invisible del mismo tamaño que la miniatura: reserva el espacio para que
   todas las filas midan igual, pero SIN dibujar un cuadro (sin fondo ni borde). */
.ec-thumb--empty { background: transparent; border-color: transparent; }
/* Integración MIR (EM1): badge de producto externo, hint y card del enlace. */
.ec-badge { display: inline-flex; align-items: center; padding: 1px 7px; border-radius: 999px;
    font-size: 11px; font-weight: 600; line-height: 1.6; }
.ec-badge--ext { background: var(--badge-purple-bg); color: var(--badge-purple-fg); }
.ec-badge--ok  { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.ec-badge--warn { background: var(--badge-warn-bg); color: var(--badge-warn-fg); }
.ec-badge--danger { background: var(--badge-danger-bg); color: var(--badge-danger-fg); }
.ec-hint { color: var(--muted); font-size: 12px; margin: 6px 0; }
.ec-link-card { display: flex; flex-direction: column; gap: 6px; padding: 12px;
    border: 1px solid var(--border); border-radius: 8px; background: var(--surface-2);
    grid-column: 1 / -1; }
.ec-link-card .pg-btn { align-self: flex-start; }
/* Tarjeta de estado de integración (Config › Integraciones, handshake §5.4). */
.ec-integ-card .ec-integ-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.ec-resv-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }

/* Editor de items al crear un pedido. */
.ec-items-editor { margin-top: 12px; }
.ec-items-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; gap: 8px; }
.ec-item-del { color: var(--badge-danger-fg); }

/* Acción destructiva (botón de borrado en tarjetas y filas). */
.ec-danger { color: var(--badge-danger-fg); }
/* Detalle de pedido (drawer): tabla de items, totales, acciones y datos read-only. */
.ec-items { margin-bottom: 14px; }
/* E8-pesaje: input de cantidad real por item + acciones. */
/* `min-width: 0` es obligatorio: `.pg-input` trae `min-width: 140px`, más de lo que le
   toca a la celda en la fila, así que el campo se salía por encima de «Subtotal». */
.ec-real-input {
  width: 100%; min-width: 0; max-width: 100%; flex: 1 1 auto;
  box-sizing: border-box; padding: 2px 6px; font-size: 0.82rem;
}
/* La celda del peso necesita algo más de sitio que las de texto (lleva campo + unidad). */
.ecommerce-page .ec-items .pg-row > span:has(.ec-real-input) { flex: 1.3 1 0; min-width: 0; }
/* El input y su unidad, en línea: el peso se teclea sabiendo si son kilos o gramos
   (el placeholder que lo decía desaparece justo al empezar a escribir). */
.ec-weigh-cell { display: flex; align-items: center; gap: 5px; min-width: 0; width: 100%; }
.ec-unit-suffix { font-size: 0.75rem; color: var(--muted); white-space: nowrap; flex: 0 0 auto; }
/* Celda de dos líneas: el valor y, debajo, de dónde sale (la conversión estimada). */
.ec-cell-2l { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.ec-cell-note { font-size: 0.7rem; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Semáforo de pesaje: SOLO el campo «Real» se tiñe (no la fila entera). Rojo =
   falta pesar, amarillo = escrito pero sin guardar. Si ya tiene peso y no hay
   cambios, sin marca (estado normal). El color acompaña al propio valor del campo. */
.ec-items .ec-weigh-cell.ec-weigh-pend  .ec-real-input {
    border-color: var(--badge-danger-fg); background: var(--badge-danger-bg);
}
.ec-items .ec-weigh-cell.ec-weigh-dirty .ec-real-input {
    border-color: var(--badge-warn-fg); background: var(--badge-warn-bg);
}

/* Botón con cambios pendientes: se tiñe de aviso para que "hay algo sin guardar"
   se vea sin leer. Apagado = no hay diferencias respecto a lo guardado. */
.ec-btn-dirty {
  background: var(--badge-warn-bg) !important;
  border-color: var(--badge-warn-fg) !important;
  color: var(--badge-warn-fg) !important;
  font-weight: 600;
}
/* Acción destructiva/irreversible (cerrar como pagado, cancelar pedido). */
.ec-btn-danger {
  background: var(--danger); border-color: var(--danger); color: #fff; font-weight: 600;
}
.ec-btn-danger:hover:not(:disabled) { filter: brightness(1.08); }
/* Acción de avance (listo para cobrar). */
.ec-btn-ok {
  background: var(--success); border-color: var(--success); color: #fff; font-weight: 600;
}
.ec-btn-ok:hover:not(:disabled) { filter: brightness(1.08); }
/* Iconos de acción coloreados en la fila (listo=verde, cancelar=rojo). Solo tiñen el
   icono; el fondo lo deja el .ec-icon-btn. Deshabilitados quedan en gris por :disabled. */
.ec-ic-ok:not(:disabled)     { color: var(--badge-success-fg); }
.ec-ic-danger:not(:disabled) { color: var(--badge-danger-fg); }

/* Cifras con signo: verde si sube, rojo si baja. */
.ec-num-up   { color: var(--badge-success-fg); }
.ec-num-down { color: var(--badge-danger-fg); }

/* Historial: fecha y hora en columnas propias y estrechas (el resto se reparte). */
.ec-hist .pg-row > span:nth-child(1) { flex: 0 0 104px; }
.ec-hist .pg-row > span:nth-child(2) { flex: 0 0 64px; }

/* Capa de cierre de popovers que viven DENTRO de un modal: `mir-pop-dismiss` (19)
   queda por debajo del backdrop del modal (100) y nunca recibía el clic. */
.ec-pop-dismiss { position: fixed; inset: 0; z-index: 2099; background: transparent; border: none; padding: 0; }

/* Confirmación sobre el detalle: no reemplaza al modal, se apila encima. */
.ec-confirm-backdrop {
  position: fixed; inset: 0; z-index: 2200; display: flex; align-items: center; justify-content: center;
  padding: 16px; background: rgba(15,23,42,0.55); backdrop-filter: blur(3px);
}
.ec-confirm-card {
  width: min(440px, 100%); max-height: calc(100vh - 32px); overflow-y: auto; box-sizing: border-box;
  display: flex; flex-direction: column; gap: 12px; padding: 20px;
  background: var(--surface-overlay); border: 1px solid var(--border); border-radius: 14px;
  box-shadow: var(--shadow-lg);
}
.ec-confirm-title { margin: 0; font-size: 1rem; color: var(--text-strong); }
.ec-confirm-card .ec-totals { margin: 0; }
.ec-confirm-actions { display: flex; justify-content: flex-end; gap: 8px; }
/* Caja de mensaje al cliente dentro del modal de confirmación. */
.ec-confirm-msg-label { display: flex; flex-direction: column; gap: 6px; font-size: 0.8rem; color: var(--muted); }
.ec-confirm-msg-label textarea { resize: vertical; }

/* Footer del detalle con las acciones de flujo: resumen de asignados a la izquierda,
   botones a la derecha. Envuelve en pantallas chicas. */
.ec-order-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ec-actions-spacer { flex: 1 1 auto; }
.ec-assignees { font-size: 0.8rem; color: var(--muted); font-weight: 600; white-space: nowrap; }
/* Tab Responsables (detalle de pedido): lista de operadores que tomaron el pedido. */
.ec-resp-pane { display: flex; flex-direction: column; gap: 8px; padding-top: 6px; }
.ec-resp-list { display: flex; flex-direction: column; gap: 8px; }
.ec-resp-item { display: flex; flex-direction: column; gap: 2px; padding: 10px 12px;
    background: var(--surface-2); border: 1px solid var(--border); border-radius: 10px; }
.ec-resp-name { font-weight: 700; color: var(--text-strong); }
.ec-resp-when { font-size: 0.76rem; color: var(--muted); }
/* Shell del modal de detalle mientras carga (aparece al instante, sin esperar el fetch). */
.ec-detail-loading { display: flex; align-items: center; justify-content: center;
    min-height: 200px; color: var(--muted); font-size: 0.9rem; }
/* Card del detalle YA cargado: no re-anima al reemplazar al shell (evita el efecto de
   "cerrar y abrir otro modal"). El shell sí anima la apertura inicial. */
.ecommerce-page .modal-card.ec-detail-loaded { animation: none; }
/* Aviso de que las notas van al cliente (bajo el textarea correspondiente). */
.ec-cli-note-hint { font-size: 0.72rem; color: var(--brand); margin-top: 2px; }
/* Bloque de pesaje: cabecera con botón "Guardar pesos" a la derecha (coherente con notas). */
.ec-weigh-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; margin-bottom: 6px; }
/* Cierre forzado: aparece solo si la diferencia supera la tolerancia (aviso + botón). */
.ec-settle-force { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap;
  margin-top: 8px; padding: 8px 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface-2); }
.ec-totals { display: flex; flex-direction: column; gap: 6px; margin: 4px 0 16px; padding: 12px 14px; background: var(--surface-2); border-radius: 10px; }
.ec-totals > div { display: flex; justify-content: space-between; font-size: 0.85rem; color: var(--text); }
.ec-totals span { color: var(--muted); }
/* Detalle de impuesto por producto (tab Pedido): tag "IVA X%" / "Exento" junto al subtotal. */
.ec-sub-cell { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.ec-tax-tag {
  font-size: 0.68rem; font-weight: 600; line-height: 1; padding: 2px 6px; border-radius: 999px;
  background: var(--badge-info-bg); color: var(--badge-info-fg); white-space: nowrap;
}
.ec-tax-tag.ec-tax-exento { background: var(--badge-neutral-bg); color: var(--badge-neutral-fg); }
/* Marcador "+imp" en la columna Monto de la tabla de pedidos: el total ya trae impuesto;
   el hover (title) muestra el desglose. Discreto para no competir con la cifra. */
.ec-monto-tax { cursor: help; }
.ec-tax-mark {
  font-size: 0.6rem; font-weight: 600; color: var(--badge-info-fg);
  background: var(--badge-info-bg); border-radius: 4px; padding: 0 3px;
  margin-left: 3px; vertical-align: super; white-space: nowrap;
}
/* Montos (tab Pedido) v2: desglose chico arriba, TOTAL destacado, nota al pie. */
.ec-totals2 { margin: 4px 0 16px; padding: 12px 14px; background: var(--surface-2); border-radius: 10px; }
.ec-totals-break { display: flex; flex-direction: column; gap: 5px; padding-bottom: 8px; border-bottom: 1px solid var(--border); }
.ec-totals-break > div { display: flex; justify-content: space-between; font-size: 0.82rem; }
.ec-totals-break span { color: var(--muted); }
.ec-totals-break b { color: var(--text); font-weight: 600; }
/* Total a cobrar: el número protagonista. */
.ec-total-hero { margin-top: 8px; }
.ec-total-line { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.ec-total-line span { color: var(--muted); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600; }
.ec-total-line strong { color: var(--text-strong); font-size: 1.6rem; font-weight: 800; line-height: 1.1; }
.ec-total-bs { text-align: right; color: var(--muted); font-size: 0.85rem; margin-top: 2px; }
/* Nota al pie: estimado + diferencia (contexto del pesaje). Color heredado del contenedor
   para que `.ec-num-up/.ec-num-down` gane en la diferencia (no hay selector `span`). */
.ec-totals-foot {
  display: flex; gap: 6px; flex-wrap: wrap; align-items: center;
  border-top: 1px dashed var(--border); margin-top: 8px; padding-top: 6px;
  font-size: 0.78rem; color: var(--muted);
}
.ec-totals-foot .ec-foot-sep { opacity: 0.5; }
/* Equivalente en Bs (E8a): tasa de rates_service, separado de los totales base. */
.ec-bs-row { border-top: 1px dashed var(--border); margin-top: 2px; padding-top: 6px; }
/* `--accent` solo está definido en `:root` (tema oscuro) y vale #111827 — casi negro.
   Como no se redefine en `html.light-mode`, en OSCURO el equivalente en Bs quedaba
   negro sobre fondo oscuro, ilegible. Se usa el token de texto fuerte, que sí
   cambia con el tema. */
.ec-bs-row strong { color: var(--text-strong); }
.ec-bs { display: block; font-size: 0.78rem; color: var(--muted); margin-top: 2px; }
/* Cobro (E8b): cotización + pagos + cierre en el detalle del pedido. */
.ec-cobro { display: flex; flex-direction: column; gap: 12px; padding: 4px 0; }
.ec-cobro-head { display: flex; gap: 16px; flex-wrap: wrap; padding: 10px 12px; background: var(--surface-2); border-radius: 10px; }
.ec-cobro-head > div { display: flex; flex-direction: column; }
.ec-cobro-head span { color: var(--muted); font-size: 0.78rem; }
.ec-cobro-cov { font-size: 0.9rem; color: var(--text); }
.ec-cobro-note { font-size: 0.75rem; color: var(--muted); margin-top: -2px; }
/* Misma razón que `.ec-bs-row strong`: `--accent` es casi negro y no cambia con el
   tema. Aquí además el par vigente/vencido se lee mejor como verde/rojo. */
.ec-credit { color: var(--badge-success-fg); font-weight: 600; }
.ec-loss { color: var(--badge-danger-fg); font-weight: 600; }
.ec-muted { color: var(--muted); }
/* Columna "#" angosta en la tabla de cotizaciones; número legible por pedido. */
.ec-pays-quotes .pg-row > span:first-child { flex: 0 0 44px; }
.ec-quote-seq { font-weight: 700; color: var(--text-strong); }
/* Referencia de cotización aplicada a un pago (columna Cotización). */
.ec-quote-ref { color: var(--brand); font-weight: 600; }
/* Cabecera de sub-sección de cobro (Pagos / Cotizaciones) con acciones a la derecha. */
.ec-pays-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; margin: 10px 0 4px; }
.ec-pays-actions { display: flex; gap: 8px; flex-shrink: 0; }
.ec-inline-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 4px; }
/* Notas del operador (detalle pedido): botón Guardar en la esquina superior derecha. */
.ec-notes-block { display: flex; flex-direction: column; gap: 6px; }
.ec-notes-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
/* Notas del operador (ancho completo) y, debajo, el cambio de estado. */
.ec-pedido-edit {
  display: flex; flex-direction: column; gap: 14px; margin-top: 4px;
}
.ec-estado-block { display: flex; flex-direction: column; gap: 8px; }
/* El título "Cambiar estado" va encima del desplegable, no a su lado. */
.ec-estado-block > label { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; }
.ec-estado-block > label .pg-input { width: 100%; max-width: 320px; }
/* Bloque de notas con cambios sin guardar: el contenedor entero se tiñe (no solo el botón)
   para dar coherencia con el estado "amarillo = pendiente de guardar". */
.ec-notes-block.ec-notes-dirty {
  background: var(--badge-warn-bg); border: 1px solid var(--badge-warn-fg);
  border-radius: 10px; padding: 10px; margin: -1px;
}
/* Popover de cambio de estado rápido (tabla de pedidos): en Portal, position:fixed
   (escapa del overflow de la tabla). Se ancla a la derecha del botón vía `left` + transform. */
.ec-quick-pop {
  position: fixed; z-index: 2100; min-width: 190px; width: 210px; max-width: calc(100vw - 16px);
  max-height: calc(100vh - 16px); overflow-y: auto; overflow-x: hidden; box-sizing: border-box;
  background: var(--surface-overlay); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: var(--shadow-lg); padding: 12px; display: flex; flex-direction: column; gap: 10px;
}
.ec-quick-pop label { display: flex; flex-direction: column; gap: 4px; font-size: 0.8rem; color: var(--muted); }
/* Calculadora del margen de pesaje (Config › Pedidos). La pantalla es una cuenta:
   estimado + margen = tope. Todo lo demás (rótulos, unidades, atajos) acompaña a esa
   línea; nada compite con ella. */
.ec-calc-pop { width: 340px; }
/* `.pg-input` trae `min-width: 140px` y `flex: 1 1 auto` (pensados para formularios
   anchos): tres campos en fila pedían 420 px y la ecuación se salía del popover. */
.ec-calc-pop .pg-input { min-width: 0; max-width: 100%; box-sizing: border-box; }
.ec-calc-title { font-size: 0.85rem; font-weight: 700; color: var(--text-strong); }
.ec-calc-hint { font-size: 0.76rem; color: var(--muted); line-height: 1.35; text-align: center; }
/* Clave-valor en una línea: la unidad se elige una vez y no forma parte de la cuenta. */
.ec-calc-kv { display: flex; align-items: center; gap: 8px; }
.ec-calc-kv-k { font-size: 0.78rem; color: var(--muted); white-space: nowrap; }
.ec-calc-kv-v { flex: 1; min-width: 0; padding: 5px 8px; font-size: 0.8rem; }
/* La ecuación. Los campos comparten ancho; los operadores solo ocupan lo suyo. */
.ec-calc-eq { display: flex; align-items: flex-start; gap: 5px; }
.ec-calc-field { display: flex; flex-direction: column; align-items: center; gap: 3px; flex: 1; min-width: 0; }
.ec-calc-cap { font-size: 0.68rem; color: var(--muted); white-space: nowrap; }
.ec-calc-box { position: relative; display: block; width: 100%; }
.ec-calc-box .pg-input { width: 100%; flex: none; padding: 6px 8px; text-align: center; font-size: 0.85rem; }
.ec-calc-pct { padding-right: 18px !important; }
.ec-calc-sfx {
  position: absolute; right: 7px; top: 50%; transform: translateY(-50%);
  pointer-events: none; font-size: 0.7rem; color: var(--muted);
}
/* La unidad va DEBAJO del campo, no dentro: dentro competía con el número. El alto
   mínimo mantiene alineadas las tres columnas aunque la del medio (%) no lleve nada. */
.ec-calc-u { font-size: 0.7rem; color: var(--muted); min-height: 0.9rem; }
.ec-calc-op { font-size: 0.9rem; font-weight: 700; color: var(--muted); flex: 0 0 auto; padding-top: 22px; }
/* Atajos: los escenarios típicos, ya resueltos. Texto, no botonera: son una ayuda para
   decidir, no la acción principal. Pulsar uno aplica ese margen. */
.ec-calc-ex { display: flex; justify-content: space-between; gap: 6px; }
.ec-calc-exbtn {
  flex: 1; padding: 3px 2px; border: none; background: none; cursor: pointer;
  font-family: inherit; font-size: 0.72rem; color: var(--muted); border-radius: 6px;
  white-space: nowrap;
}
.ec-calc-exbtn:hover { background: var(--control-bg-hover); color: var(--text); }
.ec-calc-exbtn.is-active { color: var(--brand); font-weight: 700; }
.ec-calc-foot { display: flex; justify-content: center; }
/* Campo de margen + botón «Calcular» en la misma línea. */
.ec-margen-row { display: flex; gap: 6px; align-items: center; }
.ec-margen-row .pg-input { flex: 1; min-width: 0; }

/* Detalle (modal) solo-lectura: grid de campos etiqueta/valor. */
.ec-view-img { display: block; width: 100%; max-width: 260px; max-height: 220px; object-fit: cover; border-radius: 12px; border: 1px solid var(--border); margin: 4px auto 16px; }
.ec-view-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 18px; }
.ec-view-grid > div { min-width: 0; }
.ec-view-grid span { display: block; font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.03em; color: var(--muted); font-weight: 700; }
.ec-view-grid p { margin: 2px 0 0; color: var(--text); font-size: 0.9rem; word-break: break-word; }
.ec-view-full { grid-column: 1 / -1; }

/* Typeahead de cliente (buscar escribiendo). */
.ec-typeahead { position: relative; display: flex; flex-direction: column; }
.ec-typeahead-list { position: absolute; top: 100%; left: 0; right: 0; z-index: 70; margin: 4px 0 0; padding: 4px;
  list-style: none; max-height: 240px; overflow-y: auto; background: var(--surface-overlay);
  border: 1px solid var(--border); border-radius: 10px; box-shadow: var(--shadow-md); }
.ec-typeahead-list li { padding: 8px 10px; border-radius: 7px; font-size: 0.86rem; color: var(--text); cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ec-typeahead-list li:hover { background: var(--control-bg-hover); }

/* Items del pedido: filas compactas (sin scroll lateral, todo en el ancho del drawer). */
.ec-items-empty { padding: 14px; text-align: center; color: var(--muted); font-size: 0.84rem; border: 1px dashed var(--border); border-radius: 10px; }
.ec-oi-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 10px 12px; margin-bottom: 8px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 10px; }
.ec-oi-main { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.ec-oi-name { font-weight: 600; font-size: 0.88rem; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ec-oi-meta { font-size: 0.78rem; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ec-oi-actions { display: flex; gap: 4px; flex: 0 0 auto; }

/* Pista de conversión en el modal de item. */
.ec-conv-hint { font-size: 0.82rem; color: var(--muted); background: var(--surface-2); border-radius: 8px; padding: 8px 10px; }
.ec-conv-hint strong { color: var(--text); }

/* ── Config del módulo: agrupación por contenedor ──────────────────────────────
   Cada bloque de ajustes va en su propia tarjeta con título. El "para qué sirve"
   vive SIEMPRE en el tooltip del título, nunca como párrafo suelto. Aplica a
   todas las secciones (general, productos, pedidos, integraciones). */
.ec-cfg-group { background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
                padding: 18px 22px; display: flex; flex-direction: column; gap: 16px; }
.ec-cfg-group-title { font-weight: 700; font-size: 0.92rem; color: var(--text-strong);
                      display: inline-flex; align-items: center; gap: 6px; }
/* Las secciones con contenedores necesitan más ancho que el .mir-config-section
   base (460px), sobre todo la de avisos (editor + vista previa lado a lado).
   Se cualifica con `.mir-config-section` A PROPÓSITO: esa regla se define MÁS
   ABAJO en este archivo, así que con un solo selector de clase ganaba por orden
   y el ancho extra no se aplicaba nunca. Subir la especificidad lo hace inmune a
   dónde quede cada bloque. */
.mir-config-section.ec-cfg-wide { max-width: 1180px; }

/* Config de e-commerce: aunque el contenedor (grupo) sea ancho, los CAMPOS no se
   estiran a todo el ancho — los inputs de texto y las filas de toggle se limitan a un
   ancho cómodo y quedan a la izquierda. Antes el toggle era un <label> a todo el ancho,
   así que clicar a la derecha del switch igual lo activaba/desactivaba; al acotar el
   ancho, el área clicable queda solo sobre el campo. Aplica a todas las secciones de
   config (General, Productos, Pedidos, Integraciones). No toca ColsManager ni los
   editores de avisos (no son hijos directos de .mir-form-grid). */
.ecommerce-page .mir-config-section .mir-form-grid > label,
.ecommerce-page .mir-config-section .mir-form-grid > .mir-switch-row {
  max-width: 460px;
}

/* ── Plantillas de avisos al cliente ───────────────────────────────────────── */
/* Botones de inserción de comodines: separados, no pegados. */
.ec-tpl-vars { display: flex; flex-wrap: wrap; gap: 8px; }
/* Editor a la izquierda, flecha al centro, vista previa a la derecha; apilados en
   pantallas chicas. La columna del medio es `auto`: solo ocupa lo que mide el icono. */
.ec-tpl-split { display: grid; grid-template-columns: minmax(0,1fr) auto minmax(0,1fr);
                gap: 18px; align-items: stretch; }
/* Apilado: la flecha pasa a apuntar hacia abajo, que es como fluye el contenido. */
@media (max-width: 760px) {
    .ec-tpl-split { grid-template-columns: 1fr; gap: 10px; }
    .ec-tpl-arrow { transform: rotate(90deg); padding: 0; }
}
.ec-tpl-pane { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.ec-tpl-label { font-size: 12px; color: var(--muted); }
/* Se alinea con las cajas, no con las etiquetas: de ahí el padding superior, que
   compensa la altura de la fila de `.ec-tpl-label`. */
.ec-tpl-arrow { display: flex; align-items: center; justify-content: center;
                color: var(--muted-2); padding-top: 22px; }
.ec-tpl-preview { flex: 1; font-size: 0.85rem; color: var(--text); background: var(--surface-2);
                  border: 1px solid var(--border-soft); border-radius: 8px; padding: 12px 14px;
                  white-space: pre-wrap; overflow-wrap: anywhere; min-height: 96px;
                  line-height: 1.5; }
.ec-tpl-preview--default { color: var(--muted); font-style: italic; }
/* Comodín mal escrito: rojo, para que no pase desapercibido. */
.ec-tpl-warn { font-size: 0.82rem; color: var(--badge-danger-fg); background: var(--badge-danger-bg);
               border: 1px solid var(--badge-danger-bg); border-radius: 8px; padding: 8px 10px; }
/* Autocompletado mientras se escribe `{...`. Panel flotante → --surface-overlay. */
.ec-tpl-ac-wrap { position: relative; display: flex; flex-direction: column; gap: 6px; }
.ec-tpl-ac { position: absolute; top: 100%; left: 0; right: 0; z-index: 40; margin-top: 4px;
             background: var(--surface-overlay); border: 1px solid var(--border); border-radius: 10px;
             box-shadow: var(--shadow-lg); max-height: 190px; overflow-y: auto; padding: 4px; }
.ec-tpl-ac-item { display: block; width: 100%; text-align: left; padding: 7px 9px; border: 0;
                  border-radius: 7px; background: transparent; color: var(--text); cursor: pointer;
                  font-size: 0.85rem; }
.ec-tpl-ac-item:hover { background: var(--control-bg-hover); }
.ec-tpl-ac-key { font-weight: 700; color: var(--text-strong); }
.ec-tpl-ac-label { color: var(--muted); margin-left: 6px; }

.pg-empty { padding: 26px; text-align: center; color: var(--muted); }
/* Celda de acciones común a Pagos, Contactos y Tickets: botones inline, un solo
   clic, mismo tamaño en los tres módulos. flex-wrap evita que se desborden en
   columnas estrechas. */
.pg-actions { display: flex; gap: 4px; flex-wrap: wrap; white-space: nowrap; }

/* Acciones como iconos (Ver/Editar/Eliminar/Activar) en las tablas del ecommerce. */
.ec-icon-btn { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; padding: 0; }
.ec-ic { width: 15px; height: 15px; }

/* Botón de acción SOLO-icono compartido (estandarización): mismo look que
   .ec-icon-btn pero con nombre genérico para reusar en Contactos/Tickets/Pagos/
   Centro de Control. Se combina con .pg-btn .pg-btn--sm. El tooltip va en title=.
   .icon-btn-danger tiñe el icono en rojo (hover incluido). .icon-ic dimensiona SVG. */
.icon-btn { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; padding: 0; }
.icon-ic { width: 15px; height: 15px; }
.icon-btn-danger { color: var(--badge-danger-fg); }
.icon-btn-danger:hover:not(:disabled) { color: var(--badge-danger-fg); border-color: var(--badge-danger-fg); }

/* Tabs siempre montadas: la inactiva se oculta (no se desmonta → sin re-fetch/flicker). */
.ec-hidden { display: none; }

/* Toast minimalista fijo (reemplaza el banner que empujaba el layout). */
.ec-toast {
  position: fixed; right: 20px; bottom: 20px; z-index: 2000;
  display: flex; align-items: center; gap: 10px;
  max-width: min(360px, 90vw); padding: 11px 14px;
  background: var(--surface-overlay); color: var(--text);
  border: 1px solid var(--border); border-left: 3px solid var(--brand);
  border-radius: 10px; box-shadow: var(--shadow-lg); font-size: 0.85rem;
  animation: ecToastIn 0.25s ease;
}
.ec-toast-x { border: 0; background: transparent; color: var(--muted); cursor: pointer;
  font-size: 0.9rem; line-height: 1; padding: 2px 4px; border-radius: 6px; flex: 0 0 auto; }
.ec-toast-x:hover { background: var(--control-bg-hover); color: var(--text); }
@keyframes ecToastIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }

/* Modales del ecommerce: tamaño fijo grande + scroll interno. No cambian de
   tamaño según el contenido ni al cambiar de tab; responsivos en móvil. */
.ecommerce-page .modal-card {
  width: 100%;
  max-width: min(920px, 95vw);
  height: min(85vh, 720px);
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.ecommerce-page .modal-card > .modal-header,
.ecommerce-page .modal-card > .modal-footer { flex: 0 0 auto; }
.ecommerce-page .modal-card > div:not(.modal-header):not(.modal-footer) {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}
/* Modales de FORMULARIO de e-commerce (antes drawers de crear/editar): más angostos
   que el modal de detalle (que es ancho por sus tablas) y altura al contenido. Los
   campos van apilados (uno debajo de otro) — `.mir-form-grid` ya es de una columna. */
.ecommerce-page .modal-card.ec-modal-form { max-width: 620px; height: auto; }
.ecommerce-page .modal-card.ec-modal-form > .ec-modal-body { padding-top: 12px; padding-bottom: 12px; }
@media (max-width: 640px) {
  .ecommerce-page .modal-card { height: 90vh; max-width: 100%; }
}
/* Excepción: modales pequeños (confirmaciones) vuelven a altura automática. */
.ecommerce-page .modal-card.ec-modal-auto { height: auto; max-height: 90vh; }
.ec-confirm-msg { color: var(--text); font-size: 0.9rem; line-height: 1.5; margin: 0; }
/* Fila clicable (pedidos del cliente → abre en la tab Pedidos). */

/* Columnas configurables (en Config): orden ↑/↓ + on/off. */
.ec-cols-config { margin-top: 18px; border-top: 1px solid var(--border); padding-top: 14px; max-width: 460px; }
.ec-cols-title { font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; color: var(--muted); }
.ec-cols-row { display: flex; align-items: center; gap: 10px; padding: 5px 0; transition: opacity 0.15s ease; }
.ec-cols-row.is-off { opacity: 0.42; }
.ec-cols-ord { display: inline-flex; gap: 2px; }
.ec-cols-ord .ec-icon-btn { padding: 2px 7px; line-height: 1; }
.ec-cols-name { flex: 1 1 auto; font-size: 0.88rem; color: var(--text); }
.ec-cols-check { display: inline-flex; align-items: center; }
.ec-cols-check input[type="checkbox"] { width: auto; }
.ec-cols-check[title]:not([title=""]) { cursor: help; }

/* Columnas personalizadas (G2). */
.ec-cols-actions { display: inline-flex; gap: 2px; margin-left: 4px; }
.ec-cols-actions .ec-icon-btn { padding: 2px 7px; line-height: 1; }
.ec-col-badge { display: inline-block; margin-left: 8px; padding: 1px 7px; border-radius: 999px;
  font-size: 0.62rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
  background: var(--brand-soft-bg); color: var(--brand); vertical-align: middle; }
/* Fila "agregar columna": bordes punteados con hover de escala + color. */
.ec-cols-addrow { display: flex; align-items: center; justify-content: center; gap: 8px; margin-top: 8px;
  padding: 9px 0; border: 1.5px dashed var(--border); border-radius: 10px; color: var(--muted);
  cursor: pointer; user-select: none; font-size: 0.86rem;
  transition: transform 0.12s ease, border-color 0.12s ease, color 0.12s ease, background 0.12s ease; }
.ec-cols-addrow:hover, .ec-cols-addrow:focus-visible { transform: scale(1.02); border-color: var(--brand);
  color: var(--brand); background: var(--brand-soft-bg); outline: none; }
.ec-cols-addrow-plus { font-size: 1.05rem; font-weight: 700; line-height: 1; }
/* Popover crear/editar columna adicional (en Portal, fixed). */
.ec-col-pop { position: fixed; z-index: 2100; min-width: 230px; width: 250px; max-width: calc(100vw - 16px);
  max-height: calc(100vh - 16px); overflow-y: auto; overflow-x: hidden; box-sizing: border-box;
  background: var(--surface-overlay); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: var(--shadow-lg); padding: 14px; display: flex; flex-direction: column; gap: 10px; }
/* Dentro del popover el label del checkbox debe envolver (no nowrap → sin scroll horizontal). */
.ec-col-pop .ec-extra-req-chk, .ec-quick-pop .ec-extra-req-chk { white-space: normal; align-items: flex-start; }
.ec-col-pop .pg-input, .ec-quick-pop .pg-input { max-width: 100%; box-sizing: border-box; }
/* Descripción viva del rol de flujo seleccionado (bajo el selector en el popover). */
.ec-col-pop-title { font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; color: var(--muted); }
.ec-col-pop-field { display: flex; flex-direction: column; gap: 4px; font-size: 0.8rem; color: var(--muted); }
.ec-col-pop-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 2px; }
.ec-extra-req-chk { display: inline-flex; align-items: center; gap: 5px; font-size: 0.82rem; color: var(--text); white-space: nowrap; }
.ec-extra-req-chk input[type="checkbox"] { width: auto; }
/* Bloque de campos personalizados en los formularios de crear/editar. */
.ec-extra-fields { margin-top: 6px; border-top: 1px dashed var(--border); padding-top: 10px; }
/* Aire entre el título de la sección y el primer campo (antes casi se tocaban). */
.ec-extra-fields .ec-cols-title { margin-bottom: 12px; }
.ec-req { color: var(--danger, #d33); font-weight: 700; }
/* Validación inline de campos obligatorios: borde rojo + aviso bajo el campo. */
.ec-field-err, .ec-field-err:focus { border-color: var(--danger) !important; }
.ec-req-msg { display: block; color: var(--danger); font-size: 0.72rem; margin-top: 3px; }

/* `.ec-toolbar` desapareció: Productos y Pedidos ya usan la toolbar estándar
   (`.tickets-toolbar`, con su propio margen). Con ella se fue también la regla del
   `.mir-icon` del modo selección, que era del icono propio del módulo. */

/* Fila clicable → abre el detalle (se eliminó la acción "Ver"). */
.pg-row.ec-row-click { cursor: pointer; }
.pg-row.ec-row-click:hover { background: var(--control-bg-hover); }

/* ── Vista CATÁLOGO de Productos (tarjetas) ────────────────────────────────────
   Secundaria: la tabla sigue siendo la vista de trabajo. Aquí manda la foto, que
   es lo que el dueño de la tienda reconoce. `auto-fit` para que las tarjetas
   estiren y llenen la fila (con `auto-fill` quedarían columnas fantasma). */
/* Tarjeta de ANCHO ACOTADO, no elástica, y `auto-fill` en vez de `auto-fit`.
   Es lo contrario de la regla de las gráficas de Métricas, por un motivo
   concreto: la tarjeta lleva foto. `auto-fit` colapsa las columnas vacías y
   reparte el ancho entre las que hay —tres productos en una pantalla ancha =
   tarjetas de ~400px— y como la foto es 1:1, la tarjeta crece otro tanto a lo
   alto. El `1fr` tampoco vale: aunque `auto-fill` conserve las columnas, un `1fr`
   les reparte el sobrante y siguen creciendo. Con el tope en 200px la tarjeta
   mide lo mismo con 3 productos que con 300; el mínimo de 160px es para que en
   una columna estrecha encoja en vez de desbordar.
   `justify-content: start` deja el hueco sobrante a la derecha en vez de repartir
   separaciones distintas entre tarjeta y tarjeta. */
.ec-cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(160px, 200px));
  justify-content: start;
  gap: 14px;
}
.ec-card {
  display: flex; flex-direction: column;
  border: 1px solid var(--border); border-radius: 12px;
  background: var(--surface); overflow: hidden; cursor: pointer;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.ec-card:hover { border-color: var(--brand); box-shadow: var(--shadow-sm); }

/* Relación fija 1:1 y `object-fit: cover`: las fotos de producto llegan en
   cualquier proporción y sin esto cada tarjeta tendría una altura distinta.
   El `max-height` es el tope duro: en una rejilla estrecha la columna puede pasar
   de 240px de ancho, y sin él la foto se llevaría media pantalla de alto. Con
   `cover` recorta, no deforma. */
.ec-card-img {
  position: relative;
  aspect-ratio: 1 / 1;
  max-height: 200px;
  background: var(--surface-2);
}
.ec-card-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ec-card-img--empty { display: block; width: 100%; height: 100%; }
/* El estado va sobre la foto, así que necesita su propia superficie: el color del
   estado lo elige el usuario en la configuración y puede coincidir con cualquier
   cosa que haya en la imagen (un «Activo» verde sobre una camisa clara
   desaparecía). La píldora usa `--surface-overlay` —la superficie casi opaca de
   los elementos flotantes— y deja el color para el texto, que es donde significa
   algo. */
.ec-card-estado {
  position: absolute;
  top: 8px;
  left: 8px;
  max-width: calc(100% - 16px);
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--surface-overlay);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  font-size: 0.7rem;
  line-height: 1.5;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.ec-card-body { display: flex; flex-direction: column; gap: 4px; padding: 10px 12px 12px; }
.ec-card-name {
  color: var(--text-strong); font-size: 0.85rem; font-weight: 700;
  /* Dos líneas como máximo: un nombre largo no debe descuadrar la rejilla. */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.ec-card-sku { color: var(--muted-2); font-size: 0.7rem; font-family: ui-monospace, monospace; }
.ec-card-foot {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 8px; margin-top: 4px;
}
.ec-card-precio { color: var(--text-strong); font-size: 0.95rem; font-weight: 700; }
.ec-card-stock { color: var(--muted); font-size: 0.75rem; }
/* Interruptor bloqueado por configuración (hoy: «aplica impuesto» sin impuesto configurado).
   El candado y el `not-allowed` van en la FILA, no en el input: el input deshabilitado no
   dispara hover, así que el tooltip del `title` no llegaría a verse nunca. */
.ec-switch-locked { cursor: not-allowed; }
.ec-switch-locked .ec-switch-title { color: var(--muted); }
.ec-switch-locked input[type="checkbox"] { pointer-events: none; opacity: 0.55; }
.ec-card .pg-actions {
  display: flex; gap: 6px; margin-top: 10px;
  padding-top: 10px; border-top: 1px solid var(--border-soft);
}

/* La selección se pinta sobre la tarjeta entera, con el mismo tinte y barra que
   la fila, para que el modo selección se lea igual en las dos vistas. */
.ec-card.ec-selectmode { user-select: none; }
.ec-card.ec-row-sel {
  background: var(--brand-soft-bg);
  border-color: var(--brand);
  box-shadow: inset 3px 0 0 var(--brand);
}

/* Selección múltiple (estilo MIR): fila clicable en modo selección + marcada. */
.pg-row.ec-selectmode { cursor: pointer; user-select: none; }
.pg-row.ec-selectmode:hover { background: var(--control-bg-hover); }
.pg-row.ec-row-sel,
.row-selected { background: var(--brand-soft-bg); box-shadow: inset 3px 0 0 var(--brand); }
.pg-row.ec-row-sel:hover,
.row-selected:hover { background: var(--brand-soft-bg); }
/* En modo selección la fila marca/desmarca: se ocultan sus acciones inline para
   que un clic no dispare otra cosa (mismo criterio que .ec-hidden del Ecommerce). */
.row-selectmode .pg-actions { display: none; }
/* `user-select:none` es obligatorio: Shift+clic para marcar un rango dispara
   ADEMÁS la selección de texto nativa del navegador y todo el rango queda pintado
   de azul. Se apaga solo en modo selección; fuera de él el texto se copia normal. */
/* En las tablas <table> reales el fondo lo pinta la CELDA (`… tr:hover td`), así
   que un background en la fila no se ve: la selección se repite sobre los td y
   la barra de marca va en la primera celda. */
.users-table tr.row-selected td,
.audit-table tr.row-selected td,
.camp-table tr.row-selected td { background: var(--brand-soft-bg); }
.users-table tr.row-selected td:first-child,
.audit-table tr.row-selected td:first-child,
.camp-table tr.row-selected td:first-child { box-shadow: inset 3px 0 0 var(--brand); }

.row-selectmode,
tr.row-selectmode,
.pg-row.row-selectmode {
    cursor: pointer;
    -webkit-user-select: none;
    user-select: none;
}
/* Estilos de celda cuando .pg-table se usa sobre un <table> REAL (catálogo de
   órdenes SAE). Las demás .pg-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 .pg-table base: el scroll horizontal lo
   maneja SOLO .ticket-table-wrap (evita doble scroll y el apretado). */
table.pg-table { border-collapse: separate; border-spacing: 0; width: auto; min-width: 100%; overflow: visible; }
.pg-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;
}
.pg-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;
}
.pg-table tbody tr:last-child td { border-bottom: none; }
.pg-table tbody tr:hover td { background: var(--surface-2); }
.pg-table th.pg-cell--center, .pg-table td.pg-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). */
.pg-table thead th, .pg-table tbody td { min-width: 5.5rem; }
.pg-table thead th:first-child, .pg-table tbody td:first-child { min-width: 12rem; }   /* Detalle */
.pg-table thead th:nth-child(2),  .pg-table tbody td:nth-child(2)  { min-width: 10rem; }   /* Tipo / grupo */
.pg-table th.pg-cell--center, .pg-table td.pg-cell--center { min-width: 6.5rem; }          /* toggles con aire */
/* Los controles de fila (select/input) heredan el ancho justo, no todo el td. */
.pg-table tbody td .pg-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); }

/* Layout en el bloque canónico (buscar "PAGINACIÓN ESTÁNDAR"). */

/* 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; }
  .pg-input { flex: 1 1 100%; }
}

/* ── Modal de detalle del pago ─────────────────────────────────────────────── */
.pg-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);
}
.pg-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);
}
.pg-modal-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid var(--border);
}
.pg-modal-head h3 { margin: 0; font-size: 1.05rem; color: var(--text); }
.pg-modal-close {
  border: none; background: transparent; cursor: pointer;
  font-size: 1.1rem; color: var(--muted); line-height: 1; padding: 4px 8px; border-radius: 8px;
}
.pg-modal-close:hover { background: var(--control-bg-hover); color: var(--text); }
.pg-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".
   ═══════════════════════════════════════════════════════════════ */
/* Shell en COLUMNA: header global arriba a lo ancho, debajo la fila
   [sidebar | contenido]. El header (.ph) es sticky top:0 dentro del shell. */
.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: 252px;                                /* cabe "Gestión de Tickets" sin cortar */
  /* bg/borde tokenizados (identidad visual): sidebar theme-aware en claro/oscuro. */
  background: var(--nav-bg-2);
  border-right: 1px solid var(--nav-border);
  padding: 14px 10px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  position: sticky;
  /* La sidebar ahora vive BAJO el header (60px): pega justo debajo. */
  top: 60px;
  align-self: flex-start;
  height: calc(100vh - 60px);
  overflow-y: auto;
  transition: width 0.18s ease;
  z-index: 30;
  /* Scrollbar overlay: reserva su propio carril (no pisa iconos) y se oculta
     hasta que el puntero entra a la sidebar. */
  scrollbar-gutter: stable;
  scrollbar-width: thin;                       /* Firefox */
  scrollbar-color: transparent transparent;
}
.module-sidebar:hover { scrollbar-color: rgba(255, 255, 255, 0.20) transparent; }
.module-sidebar::-webkit-scrollbar { width: 8px; }
.module-sidebar::-webkit-scrollbar-track { background: transparent; }
.module-sidebar::-webkit-scrollbar-thumb {
  background: transparent;
  border: 2px solid transparent;               /* inset → carril propio, no toca iconos */
  background-clip: padding-box;
  border-radius: 8px;
  transition: background-color 0.2s ease;
}
.module-sidebar:hover::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.20); background-clip: padding-box; }
.module-sidebar:hover::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.34); background-clip: padding-box; }
.module-sidebar--collapsed { width: 64px; }
/* Colapso provocado por navegación: instantáneo, no se ve cerrarse (module_sidebar.rs). */
.module-sidebar--no-anim { transition: none; }

.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: var(--text);
  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: var(--muted);
  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; }
.module-sidebar-label { overflow: hidden; text-overflow: ellipsis; }
.module-sidebar-dot {
  width: 7px; height: 7px; border-radius: 50%;
  background: #f59e0b; margin-left: auto; flex-shrink: 0;
}
/* `position: relative` para que el punto de «sección nueva» se sitúe respecto
   al botón (ver .module-sidebar-new-dot). */
.module-sidebar--collapsed .module-sidebar-item { justify-content: center; padding: 10px 0; position: relative; }
.module-sidebar--collapsed .module-sidebar-label,
.module-sidebar--collapsed .module-sidebar-dot { display: none; }

/* 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 = riel de iconos (64px), NO oculta:
   el toggle vive dentro de la sidebar (ya no hay hamburguesa en el header), así
   que debe seguir alcanzable para poder re-expandirla. */
@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: 64px; }
}

/* ── Light mode: sidebar global ── */
html.light-mode .module-sidebar:hover { scrollbar-color: rgba(0, 0, 0, 0.22) transparent; }
html.light-mode .module-sidebar:hover::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, 0.18); background-clip: padding-box; }
html.light-mode .module-sidebar:hover::-webkit-scrollbar-thumb:hover { background: rgba(0, 0, 0, 0.30); background-clip: padding-box; }
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); }

/* ═══════════════════════════════════════════════════════════════
   Subsidebar de tabs (hover sobre una fila de la sidebar)
   Mismo lenguaje que .module-sidebar (por eso repite sus hex: es una
   extensión de la misma superficie, no una card en flujo), un tono más
   oscura y pegada a su borde derecho. Solo aparece en hover.
   ═══════════════════════════════════════════════════════════════ */
.module-subsidebar {
  position: fixed;
  left: 252px;                                 /* = ancho de .module-sidebar */
  top: 60px;                                   /* bajo el header global */
  bottom: 0;
  width: 244px;
  /* MISMO color que la sidebar (--nav-bg-2, tokenizado por la identidad visual)
     con una capa de oscurecimiento encima para la profundidad. Antes era un hex
     fijo (#0e1420) y quedaba fuera del tema al cambiar los tokens de nav. */
  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 el header */
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.20) transparent;
  /* Entrada/salida suave (140 ms). El panel no se desmonta: `is-open` lo muestra,
     y `visibility` se retrasa hasta el final del fundido para poder animar la salida. */
  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 colapsada */

/* Flecha "hay más": SIEMPRE visible en las filas con tabs — es el indicador de
   que ese módulo despliega subsidebar. 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: rgba(255, 255, 255, 0.07); color: #fff; }
.module-subsidebar-item.is-active { background: var(--brand-dark); color: #fff; }

@media (max-width: 860px) {
  /* La sidebar pasa a overlay desde top:0 — la subsidebar la acompaña. */
  .module-subsidebar { top: 0; }
}

/* ── Light mode: subsidebar ── */
/* El color base y el velo ya son tokens (--nav-bg-2 / --nav-shade), así que en
   claro solo queda el borde de separación. */
html.light-mode .module-subsidebar {
  box-shadow: 1px 0 0 rgba(0, 0, 0, 0.03);
}
html.light-mode .module-subsidebar-title { color: var(--muted); }
html.light-mode .module-subsidebar-item { color: var(--muted); }
html.light-mode .module-subsidebar-item:hover { background: rgba(0, 0, 0, 0.05); color: var(--text-strong); }
html.light-mode .module-subsidebar-item.is-active { background: var(--brand-dark); color: #fff; }

/* ── Módulos MIR (Reservas) y Cinema (Cine) ──────────────────────────────── */
/* Tabs superiores estilo píldora (igual que módulo Tickets). */
/* .mir-tabs / .mir-tab (Reservas, Cine y Ecommerce) están registradas en el
   bloque canónico «SEGMENTED CONTROL ESTÁNDAR»: repetían sus reglas y se
   quedaron fuera del grupo de tema claro (bandeja invisible). */

.mir-toolbar { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-bottom: 14px; }
.mir-toolbar .pg-input { min-width: 200px; }

.mir-form { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.mir-form label { display: flex; flex-direction: column; gap: 4px; font-size: 0.82rem; color: var(--muted); }
.mir-form .mir-check { flex-direction: row; align-items: center; gap: 8px; color: var(--text); }
.mir-form .mir-check input { width: auto; }

.pg-modal-foot { display: flex; justify-content: flex-end; gap: 8px; padding: 14px 20px;
  border-top: 1px solid var(--border); }

.mir-config-editor { width: 100%; min-height: 220px; font-family: ui-monospace, Menlo, monospace;
  font-size: 0.82rem; padding: 12px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface-2); color: var(--text); box-sizing: border-box; margin-bottom: 12px; }

/* Config con selector lateral de secciones (estilo panel). */
.mir-config { display: flex; gap: 18px; align-items: flex-start; }
.mir-config-nav { flex: 0 0 190px; display: flex; flex-direction: column; gap: 4px;
  border-right: 1px solid var(--border-soft); padding-right: 12px; }
.mir-config-navitem { text-align: left; padding: 9px 12px; border: 1px solid transparent; border-radius: 9px;
  background: transparent; color: var(--text-1); font-size: 0.88rem; font-weight: 600; cursor: pointer; }
.mir-config-navitem:hover { background: var(--surface-2); }
.mir-config-navitem.is-active { background: var(--brand-soft-bg); color: var(--brand-dark); border-color: var(--border-soft); }
.mir-config-content { flex: 1; min-width: 0; }
.mir-config-section { display: flex; flex-direction: column; gap: 18px; max-width: 460px; }
.mir-config-hint { color: var(--muted); font-size: 12px; margin: 0; }
.mir-config-row { display: flex; flex-direction: column; gap: 6px; }
.mir-config-rowhead { display: inline-flex; align-items: center; gap: 6px; }
.mir-config-rowtitle { font-weight: 700; font-size: 0.92rem; color: var(--text-strong); }
.mir-config-input { max-width: 200px; }
.mir-config-actions { display: flex; }

.mir-capacity { margin-bottom: 16px; }

/* Insignias por estado de reserva */
.mir-st--hold      { background: rgba(180,83,9,0.12);  color: #b45309; border: 1px solid rgba(180,83,9,0.25); }
.mir-st--confirmed { background: rgba(29,78,216,0.12); color: #1d4ed8; border: 1px solid rgba(29,78,216,0.25); }
.mir-st--completed { background: rgba(4,120,87,0.12);  color: #047857; border: 1px solid rgba(4,120,87,0.25); }
.mir-st--cancelled { background: rgba(185,28,28,0.12); color: #b91c1c; border: 1px solid rgba(185,28,28,0.25); }
.mir-st--expired   { background: rgba(71,85,105,0.12); color: #475569; border: 1px solid rgba(71,85,105,0.25); }

/* Cinema: salas */
.cinema-rooms-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; margin-bottom: 18px; }
.cinema-room-card { background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
  padding: 14px; cursor: pointer; box-shadow: var(--shadow-sm); transition: box-shadow 0.15s; }
.cinema-room-card:hover { box-shadow: var(--shadow-md); border-color: var(--brand); }
.cinema-room-title { font-weight: 700; color: var(--text); margin-bottom: 6px; }
.cinema-room-meta { font-size: 0.8rem; color: var(--muted); }
.cinema-room-next { font-size: 0.8rem; color: var(--brand-dark); margin-top: 6px; }
.cinema-day { margin-top: 18px; }
.cinema-day h3 { font-size: 1rem; color: var(--text); margin: 0 0 10px; }

/* Cinema: mapa de asientos */
.cinema-seatmap { display: flex; flex-wrap: wrap; gap: 6px; }
.cinema-seat { display: inline-flex; align-items: center; justify-content: center; min-width: 38px;
  height: 32px; padding: 0 6px; border-radius: 6px; font-size: 0.72rem; font-weight: 600; border: 1px solid var(--border); }
.cinema-seat--free      { background: var(--control-bg); color: var(--muted); }
.cinema-seat--hold      { background: rgba(180,83,9,0.18);  color: #b45309; }
.cinema-seat--confirmed { background: rgba(29,78,216,0.18); color: #1d4ed8; }
.cinema-seat--completed { background: rgba(4,120,87,0.18);  color: #047857; }
.cinema-general { padding: 16px; background: var(--panel-2); border-radius: 8px; font-size: 0.95rem; color: var(--text); }
.cinema-uuid { font-family: ui-monospace, Menlo, monospace; font-size: 0.72rem; color: var(--muted); }

/* ── MIR: modales de formulario (antes drawers laterales) ────────────────────
   Misma convención que Ecommerce: crear/editar viven en un modal centrado, no en
   un drawer. Los `.mir-drawer*` se retiraron al no quedar ningún uso. */
.mir-page .modal-card {
  width: 100%;
  max-width: min(920px, 95vw);
  max-height: 90vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.mir-page .modal-card > .modal-header,
.mir-page .modal-card > .modal-footer { flex: 0 0 auto; }
.mir-page .modal-card > div:not(.modal-header):not(.modal-footer) {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
}
/* Formularios: más angostos que un modal de detalle y de ALTURA FIJA — no
   siguen a su contenido. Con altura automática la caja crece y encoge al
   cambiar de tab o al desplegar un campo condicional, y las tabs (que están
   arriba) se mueven bajo el cursor. El scroll vive en el cuerpo. */
.mir-page .modal-card.mir-modal-form { max-width: 620px; height: min(80vh, 660px); }
.mir-page .modal-card.mir-modal-form > .mir-modal-body { padding-top: 12px; padding-bottom: 12px; }
/* Sub-modal (definir un campo del agente): se abre ENCIMA del formulario. */
.mir-submodal-backdrop { z-index: 120; }
.mir-page .modal-card.mir-modal-sub { max-width: 520px; height: min(72vh, 580px); }
/* Tooltips dentro del modal: abren HACIA ABAJO para no cortarse contra la
   cabecera, y por encima del resto del contenido. */
.mir-modal-form .mir-tip-bubble { top: calc(100% + 10px); bottom: auto; transform: translateX(-50%) translateY(-4px); z-index: 130; }
.mir-modal-form .mir-tip:hover .mir-tip-bubble,
.mir-modal-form .mir-tip:focus-visible .mir-tip-bubble { transform: translateX(-50%) translateY(0); }

/* Integración MIR→E-commerce: lo que el recurso ya tiene a la venta + acciones.
   Reusa a propósito los primitivos `.ec-seg` / `.ec-res-*` del picker inverso: es
   el mismo control, no un dialecto nuevo por módulo. */
.mir-integ-links { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px;
  padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-2); }
.mir-integ-links-title { font-size: 0.72rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.03em; color: var(--muted); }
.mir-integ-link { display: flex; align-items: center; gap: 8px; }
.mir-integ-link-name { font-weight: 600; color: var(--text); flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mir-integ-link-sku { font-size: 0.72rem; color: var(--muted); font-family: ui-monospace, Menlo, monospace; }
.mir-integ-link-price { font-size: 0.8rem; color: var(--text-strong); font-weight: 700; }
.mir-integ-empty-acts { display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.mir-integ-cancel { margin-top: 12px; }

/* Tabs internos de los modales de formulario: mismo lenguaje visual que las tabs principales. */
.mir-dtabs { display: inline-flex; gap: 3px; margin-bottom: 18px; padding: 5px;
  background: var(--surface-2); border: 1px solid var(--border-soft); border-radius: 12px; flex-wrap: wrap; }
.mir-dtab { appearance: none; border: 0; border-radius: 8px; padding: 8px 16px; background: transparent;
  cursor: pointer; font-family: inherit; font-size: 0.8125rem; font-weight: 600; color: var(--muted);
  white-space: nowrap; transition: all 0.15s; }
.mir-dtab:hover { background: var(--control-bg-hover); color: var(--text); }
.mir-dtab.active { background: var(--brand-dark); color: #fff; box-shadow: 0 1px 4px rgba(0,0,0,0.12); }

/* Campos del drawer — apilados uno encima de otro (como el front viejo), no lado a lado */
.mir-form-grid { display: grid; grid-template-columns: 1fr; gap: 12px; margin-bottom: 12px; }
.mir-form-grid label, .mir-form-full label { display: flex; flex-direction: column; gap: 4px;
  font-size: 0.82rem; color: var(--muted); }
.mir-form-full { display: block; margin-bottom: 12px; }
.mir-form-full > label { width: 100%; }
/* Toggle switch apilado: etiqueta arriba, switch debajo (coherente con los campos de texto). */
.mir-switch-row { display: flex; flex-direction: column; align-items: flex-start; gap: 8px;
  font-size: 0.85rem; color: var(--text); padding: 6px 0; margin-bottom: 4px; }
.mir-switch-row > span { display: inline-flex; }
/* El fondo del interruptor se fuerza con !important: ningún estado (focus/active/hover)
   ni pintado nativo del navegador puede blanquearlo. Solo depende de checked. */
.mir-switch-row input[type="checkbox"] { appearance: none !important; -webkit-appearance: none !important; position: relative;
  width: 42px; height: 24px; min-width: 42px; border-radius: 999px; background: var(--switch-off, var(--muted-2)) !important;
  border: 1px solid var(--border); cursor: pointer; transition: background 0.15s ease; flex: 0 0 auto; margin: 0; box-shadow: none; }
.mir-switch-row input[type="checkbox"]::after { content: ""; position: absolute; top: 2px; left: 2px;
  width: 18px; height: 18px; border-radius: 50%; background: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.25);
  transition: transform 0.15s ease; }
.mir-switch-row input[type="checkbox"]:checked { background: var(--brand) !important; }
.mir-switch-row input[type="checkbox"]:checked::after { transform: translateX(18px); }
/* Focus/active: nunca cambian el fondo; solo un anillo accesible en teclado. */
.mir-switch-row input[type="checkbox"]:focus,
.mir-switch-row input[type="checkbox"]:active,
.mir-switch-row input[type="checkbox"]:hover { box-shadow: none; outline: none; }
.mir-switch-row input[type="checkbox"]:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.mir-help-text { font-size: 0.8rem; color: var(--muted); margin: 0 0 12px; }
.mir-dpane-grid-full { grid-column: 1 / -1; }
.mir-inline-note { padding: 10px 12px; border-radius: 10px; background: var(--surface-2); color: var(--text);
  border: 1px solid var(--border-soft); font-size: 0.82rem; }

/* ── Chips de días de la semana (tab Repetición del bloque de tiempo) ── */
.mir-wd-row { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.mir-wd-chip { display: inline-flex; align-items: center; gap: 5px; padding: 5px 10px;
  border: 1px solid var(--control-border); border-radius: 999px; background: var(--control-bg);
  cursor: pointer; font-size: 0.8rem; user-select: none; }
.mir-wd-chip:hover { background: var(--control-bg-hover); }
.mir-wd-chip input { accent-color: var(--brand); }

/* ── Tarjeta de integración compartida (colapsable, MIR + E-commerce) ── */
.integ-card { border: 1px solid var(--border-soft); border-radius: 12px; background: var(--surface);
  overflow: hidden; }
.integ-card-head { display: flex; align-items: center; gap: 10px; width: 100%; padding: 12px 14px;
  background: var(--surface-2); border: 0; cursor: pointer; text-align: left; color: var(--text); }
.integ-card-head:hover { background: var(--control-bg-hover); }
.integ-card-title { font-weight: 700; color: var(--text-strong); flex: 1; }
.integ-card-chevron { color: var(--muted); font-size: 0.9rem; transition: transform 0.25s ease; }
.integ-card.is-open .integ-card-chevron { transform: rotate(180deg); }
/* Animación suave: grid-template-rows 0fr→1fr (no salta como max-height). */
.integ-card-body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.25s ease; }
.integ-card-body.is-open { grid-template-rows: 1fr; }
.integ-card-body-inner { overflow: hidden; display: flex; flex-direction: column; gap: 10px;
  padding: 0 14px; }
.integ-card-body.is-open .integ-card-body-inner { padding: 12px 14px; }
.integ-card-status { display: flex; flex-wrap: wrap; gap: 6px; }

.ec-integ-cell { display: inline-flex; align-items: center; gap: 6px; }
.ec-integ-mod { font-size: 0.75rem; color: var(--muted); }
.ec-integ-note { padding: 10px 12px; border-radius: 10px; background: var(--brand-soft-bg);
  color: var(--brand-soft-fg); font-size: 0.82rem; margin-bottom: 10px; }

/* ── Picker de slots de reserva (item de pedido, Fase 4) ── */
.ec-slots { display: flex; flex-wrap: wrap; gap: 6px; }
.ec-slot { display: inline-flex; flex-direction: column; align-items: flex-start; gap: 2px;
  padding: 6px 10px; border: 1px solid var(--control-border); border-radius: 8px;
  background: var(--control-bg); cursor: pointer; color: var(--text); font-variant-numeric: tabular-nums; }
.ec-slot:hover:not(:disabled) { background: var(--control-bg-hover); border-color: var(--brand); }
.ec-slot.is-sel { border-color: var(--brand); background: var(--brand-soft-bg); color: var(--brand-soft-fg); }
.ec-slot:disabled { opacity: 0.45; cursor: not-allowed; }
.ec-slot-rem { font-size: 0.68rem; color: var(--muted); }

/* ── Crear recurso nuevo inline (par producto↔recurso, Fase 5) ── */

.mir-field-label { display: inline-flex; align-items: center; gap: 6px; color: var(--text); font-weight: 600; }
/* Validación de campos obligatorios (marca en rojo, sin usar el banner superior). */
.mir-req-star { color: var(--danger); font-weight: 700; margin-left: 2px; }
/* Spinner en línea para botones (Creando…/Guardando…). */
.mir-spinner { display: inline-block; width: 13px; height: 13px; vertical-align: -2px;
  border: 2px solid currentColor; border-top-color: transparent; border-radius: 50%;
  animation: mir-spin 0.7s linear infinite; }
@keyframes mir-spin { to { transform: rotate(360deg); } }
.mir-field-err { display: block; color: var(--danger); font-size: 0.75rem; margin-top: 4px; }
/* Botón extra-pequeño (acciones inline: cambiar contacto, enlazar pago). */
.pg-btn--xs { padding: 3px 10px; font-size: 0.75rem; line-height: 1.2; }
/* Picker de titular (contacto obligatorio) en el form de reserva. */
.mir-contact-search { position: relative; }
.mir-contact-results { margin-top: 4px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface); box-shadow: var(--shadow-md); max-height: 220px; overflow-y: auto; }
.mir-contact-result { display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
  width: 100%; text-align: left; padding: 8px 12px; background: none; border: none; cursor: pointer;
  border-bottom: 1px solid var(--border-soft); color: var(--text-strong); }
.mir-contact-result:last-child { border-bottom: none; }
.mir-contact-result:hover { background: var(--control-bg-hover); }
.mir-contact-chip { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 8px 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface-2); }
.mir-contact-chip-info { display: flex; flex-direction: column; gap: 2px; }
.mir-contact-chip-sub { color: var(--muted); font-size: 0.78rem; }
/* Sección Pago en el detalle de reserva. */
.mir-pago-section { margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); }
.mir-pago-title { margin: 0 0 6px; font-size: 0.9rem; color: var(--text-strong); }
.mir-pago-empty { display: flex; flex-direction: column; gap: 8px; padding: 8px 0; }
.mir-pago-warn { color: var(--badge-warn-fg); font-size: 0.82rem; }
.mir-pago-link { display: flex; flex-direction: column; gap: 8px; }
.mir-pago-cands { display: flex; flex-direction: column; gap: 4px; }
.mir-pago-cands-label { color: var(--muted); font-size: 0.78rem; font-weight: 600; }
.mir-pago-cand { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  font-size: 0.82rem; padding: 4px 0; }
.mir-pago-manual { display: flex; gap: 8px; align-items: center; }
.mir-pago-manual .pg-input { flex: 1; }
/* Aviso suave (única fuente de cupos por rama). */
.mir-inline-warn { border-left: 3px solid var(--danger); background: var(--badge-danger-bg); color: var(--badge-danger-fg); }
/* Modales de detalle (recurso/bloque/reserva): filas etiqueta→valor. */
.mir-detail-modal { max-width: 460px; width: 100%; }
.mir-detail-row { display: flex; justify-content: space-between; gap: 16px; padding: 8px 0; border-bottom: 1px solid var(--border-soft); font-size: 0.88rem; }
.mir-detail-row:last-child { border-bottom: none; }
.mir-detail-k { color: var(--muted); font-weight: 600; flex: 0 0 auto; }
.mir-detail-v { color: var(--text-strong); text-align: right; word-break: break-word; }
/* Ficha del recurso con pestañas (Datos · Bloques): la de Bloques trae el
   calendario completo dentro, así que necesita el ancho de un mes y scroll
   propio en lugar de crecer sin límite. */
.mir-detail-modal--tabs { max-width: min(860px, 96vw); display: flex; flex-direction: column;
  height: min(86vh, 740px); max-height: 88vh; }
.mir-detail-modal--tabs > .pg-modal-body { overflow-y: auto; }
.mir-detail-cal { display: flex; flex-direction: column; gap: 10px; }
/* Cabecera de mes sin menú de salto (aquí el calendario es de solo lectura). */
.mir-cal-title--static { font-weight: 700; color: var(--text-strong); padding: 6px 10px; cursor: default; }
.mir-cal-title--static:hover { background: transparent; border-color: transparent; }
/* Bloque de solo lectura: mismo aspecto que el clicable, sin afordancia de clic. */
.mir-day-block--ro { cursor: default; }
/* Tarjeta de reserva: cabecera con título + botón de detalle. */
.mir-kcard-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 6px; }
.mir-kcard-top .mir-kcard-title { flex: 1 1 auto; }
/* Bloque en vista día: el contenedor entero abre DETALLES; editar es un botón
   segmentado DENTRO del mismo bloque (separador a la izquierda y hover propio).
   Antes el botón de detalle colgaba fuera del bloque y el clic abría el editor:
   lo contrario de lo que espera cualquiera al pulsar una tarjeta. */
.mir-day-bedit {
  appearance: none; position: relative; flex: 0 0 auto;
  margin-left: 7px; width: 24px; height: 24px; border-radius: 7px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid transparent; background: transparent; color: var(--muted-2);
  cursor: pointer;
  transition: color 0.14s ease, background 0.14s ease, border-color 0.14s ease,
              transform 0.14s ease, box-shadow 0.14s ease;
}
/* Filete que lo separa del contenido del bloque: "dentro, pero es otra acción". */
.mir-day-bedit::before {
  content: ""; position: absolute; left: -4px; top: 3px; bottom: 3px;
  width: 1px; background: var(--border-soft);
}
/* En reposo se apaga; al pasar por el bloque se insinúa (hay algo pulsable). */
.mir-day-block:hover .mir-day-bedit { color: var(--muted); }
/* Hover propio: el par --brand-soft-bg/-fg es el que garantiza contraste en los
   DOS temas (con --brand-dark el lápiz quedaba ciruela sobre ciruela y no se
   leía en oscuro). Se levanta 1px, se remarca con borde de marca y sombra corta,
   y el lápiz se inclina como al cogerlo. */
.mir-day-block .mir-day-bedit:hover {
  color: var(--brand-soft-fg);
  background: var(--brand-soft-bg);
  border-color: var(--brand);
  transform: translateY(-1px);
  box-shadow: var(--shadow-sm);
}
.mir-day-bedit .mir-icon { transition: transform 0.14s ease; }
.mir-day-bedit:hover .mir-icon { transform: rotate(-10deg); }
.mir-day-bedit:active { transform: translateY(0); box-shadow: none; }
.mir-day-bedit:focus-visible {
  outline: none; color: var(--brand-soft-fg); background: var(--brand-soft-bg);
  border-color: var(--brand); box-shadow: 0 0 0 2px var(--brand-soft-bg);
}
.pg-input.is-err { border-color: var(--danger); box-shadow: 0 0 0 1px var(--danger) inset; }
.mir-dtp-err .mir-dtp-btn { border-color: var(--danger); box-shadow: 0 0 0 1px var(--danger) inset; }
.mir-icon { width: 16px; height: 16px; display: inline-block; flex: 0 0 auto; }
.mir-icon--xs { width: 14px; height: 14px; }
.mir-icon--lg { width: 26px; height: 26px; }
.mir-icon-placeholder { width: 16px; height: 16px; display: inline-block; }
.mir-tip { position: relative; display: inline-flex; align-items: center; color: var(--muted); }
.mir-tip:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; border-radius: 999px; }
.mir-tip-ic { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px;
  border-radius: 999px; border: 1px solid var(--border); background: var(--surface); color: var(--muted); }
.mir-tip-bubble { position: absolute; left: 50%; bottom: calc(100% + 10px); transform: translateX(-50%) translateY(4px);
  min-width: 180px; max-width: 260px; padding: 10px 12px; border-radius: 10px; border: 1px solid var(--border);
  background: var(--surface); color: var(--text); box-shadow: var(--shadow-lg); font-size: 0.78rem; line-height: 1.4;
  opacity: 0; pointer-events: none; transition: opacity 0.16s ease, transform 0.16s ease; z-index: 30; font-weight: 500; }
.mir-tip:hover .mir-tip-bubble, .mir-tip:focus-visible .mir-tip-bubble { opacity: 1; transform: translateX(-50%) translateY(0); }
/* Burbuja flotante fixed (nueva): sale de cualquier contenedor, aparece al instante. */
.mir-tip-pop { position: fixed; z-index: 9999; min-width: 160px; max-width: 260px; padding: 9px 11px;
  border-radius: 10px; border: 1px solid var(--border); background: var(--surface-overlay); color: var(--text);
  box-shadow: var(--shadow-lg); font-size: 0.78rem; line-height: 1.4; font-weight: 500;
  pointer-events: none; white-space: normal; }

.mir-modal-shell { animation: mir-modal-in 0.18s ease forwards; }
.mir-modal-shell.is-closing { animation: mir-modal-out 0.18s ease forwards; }
/* Sin `forwards`: al terminar no conserva transform → los tooltips fixed escapan del modal. */
.mir-modal-shell .pg-modal { animation: mir-modal-panel-in 0.18s ease; transform-origin: center top; }
.mir-modal-shell.is-closing .pg-modal { animation: mir-modal-panel-out 0.18s ease forwards; }
@keyframes mir-modal-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes mir-modal-out { from { opacity: 1; } to { opacity: 0; } }
@keyframes mir-modal-panel-in { from { opacity: 0; transform: translateY(8px) scale(0.97); } to { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes mir-modal-panel-out { from { opacity: 1; transform: translateY(0) scale(1); } to { opacity: 0; transform: translateY(8px) scale(0.97); } }
.mir-modal-context { margin-bottom: 14px; padding: 10px 12px; border-radius: 10px; background: var(--surface-2); color: var(--text); }
.mir-modal-headerline { display: flex; align-items: center; gap: 8px; margin-bottom: 12px; }
.mir-modal-headerline-title { font-weight: 700; color: var(--text); }

/* ── MIR: modal chooser "¿qué crear?" ────────────────────────────────────── */
.mir-chooser { max-width: 560px; }
/* El cuerpo del modal permite scroll SOLO vertical (nunca lateral) si hay muchas cards. */
.mir-chooser .pg-modal-body { overflow-x: hidden; }
.mir-chooser-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 8px; }
.mir-chooser-grid--triple { grid-template-columns: repeat(3, 1fr); }
/* Cards = cuadrados perfectos (aspect-ratio 1/1), contenido centrado. */
.mir-chooser-card { position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; text-align: center; aspect-ratio: 1 / 1; padding: 18px;
  border: 1px solid var(--border); border-radius: 16px; background: var(--surface-2);
  cursor: pointer; transition: border-color 0.15s, box-shadow 0.15s, transform 0.15s; font-family: inherit; }
.mir-chooser-card:hover { border-color: var(--brand); box-shadow: var(--shadow-md); transform: translateY(-2px); }
.mir-chooser-card.is-disabled, .mir-chooser-card:disabled { opacity: 0.6; cursor: not-allowed; transform: none; box-shadow: none; }
/* Icono dentro de una pastilla, como en el front original. */
.mir-chooser-card .mir-icon--lg { box-sizing: border-box; width: 52px; height: 52px; padding: 13px;
  border-radius: 14px; background: var(--brand-soft-bg); color: var(--brand); }
.mir-chooser-tip { position: absolute; top: 10px; right: 10px; }
/* La burbuja del tooltip abre HACIA ABAJO y anclada a la derecha para no cortarse
   contra el borde de la card ni forzar scroll lateral (fix imagen 3). */
.mir-chooser-tip .mir-tip-bubble { bottom: auto; top: calc(100% + 8px); left: auto; right: 0;
  transform: translateY(-4px); }
.mir-chooser-tip .mir-tip:hover .mir-tip-bubble,
.mir-chooser-tip .mir-tip:focus-visible .mir-tip-bubble { transform: translateY(0); }
.mir-chooser-title { font-weight: 700; color: var(--text-strong); font-size: 1rem; }
@media (max-width: 680px) { .mir-chooser-grid--triple { grid-template-columns: 1fr; } .mir-chooser-card { aspect-ratio: auto; } }
@media (max-width: 520px) { .mir-chooser-grid { grid-template-columns: 1fr; } .mir-chooser-card { aspect-ratio: auto; } }

/* ── MIR: schema fields del agente + sub-drawer ──────────────────────────── */
.mir-sf-head { display: flex; align-items: center; justify-content: space-between; gap: 8px;
  margin: 16px 0 6px; }
.mir-sf-head h4 { margin: 0; font-size: 0.9rem; color: var(--text-strong); }
.mir-sf-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; }
.mir-sf-row { display: flex; align-items: center; gap: 8px; padding: 8px 10px;
  border: 1px solid var(--border); border-radius: 8px; background: var(--surface-2); }
.mir-sf-grp { font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--brand-dark); background: var(--brand-soft-bg); padding: 2px 7px; border-radius: 999px; }
.mir-sf-lbl { font-weight: 600; color: var(--text); flex: 1; }
.mir-sf-type { font-size: 0.78rem; color: var(--muted); }
.mir-sf-req { font-size: 0.7rem; color: var(--badge-warn-fg); background: var(--badge-warn-bg);
  padding: 2px 7px; border-radius: 999px; }
.mir-sf-acts { display: flex; gap: 4px; }
/* Responsive: en móvil los modales ocupan casi toda la pantalla. */
@media (max-width: 560px) {
  .mir-page .modal-card,
  .mir-page .modal-card.mir-modal-form,
  .mir-page .modal-card.mir-modal-sub { max-width: 100%; height: 88vh; }
}

/* ── MIR: árbol de recursos ──────────────────────────────────────────────── */
.mir-tree { display: flex; flex-direction: column; gap: 3px; overflow: hidden; }
.mir-tree-row { display: flex; align-items: stretch; gap: 8px; padding: 8px 10px;
  border: 1px solid var(--border-soft); border-radius: 8px; background: var(--surface);
  animation: mir-tree-row-in 0.28s cubic-bezier(0.22, 0.9, 0.22, 1) both;
  animation-delay: calc(var(--mir-depth, 0) * 22ms); transform-origin: top center;
  transition: background-color 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease; }
.mir-tree-row:hover { background: var(--surface-2); }
@keyframes mir-tree-row-in {
  from { opacity: 0; transform: translateY(-6px) scaleY(0.94); }
  60% { opacity: 1; transform: translateY(1px) scaleY(1.01); }
  to { opacity: 1; transform: none; }
}
.mir-tree-twirl { display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: none; cursor: pointer; color: var(--muted);
  width: 22px; min-width: 22px; height: auto; padding: 0; border-radius: 6px; align-self: stretch; }
.mir-tree-twirl:hover { color: var(--text); background: var(--surface-2); }
.mir-tree-twirl .mir-icon { width: 15px; height: 15px; transition: transform 0.22s ease; margin: auto; }
.mir-tree-twirl.is-open .mir-icon { transform: rotate(90deg); }
.mir-tree-twirl--empty { cursor: default; }
/* Región clicable de la fila: al pulsarla se expande/colapsa (como el front viejo). */
.mir-tree-main { display: flex; align-items: center; gap: 8px; flex: 1; min-width: 0; min-height: 40px; padding: 8px 4px; border-radius: 6px;
  transition: background-color 0.18s ease, transform 0.18s ease; }
.mir-tree-main.is-expandable { cursor: pointer; }
.mir-tree-main.is-expandable:hover { background: var(--surface-2); transform: translateX(1px); }
.mir-tree-icon { font-size: 1rem; flex: 0 0 auto; }
.mir-tree-label { font-weight: 600; color: var(--text); flex: 0 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Indicador sutil de que la fila tiene hijos: nº de recursos hijos directos. */
.mir-tree-count { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 3px;
  font-size: 0.7rem; font-weight: 600; color: var(--muted);
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 999px;
  padding: 1px 8px; white-space: nowrap; }
.mir-tree-inv { font-size: 0.74rem; color: var(--muted); white-space: nowrap; }
.mir-tree-actions { display: flex; gap: 6px; margin-left: auto; align-items: center; }
/* Codo ↳ de las filas hijas: la sangría sola no basta cuando el padre queda
   fuera de pantalla o hay varias ramas con el mismo nombre de hoja. */
.mir-tree-branch { flex: 0 0 auto; display: inline-flex; align-items: center; align-self: center;
  color: var(--muted-2); }
.mir-tree-branch .mir-icon { width: 15px; height: 15px; }
.mir-tree-row.is-child:hover .mir-tree-branch { color: var(--brand); }
/* Selección múltiple: barra lateral izquierda + tinte de marca, SIN casillas
   (mismo lenguaje que Ecommerce/Contactos: la fila entera es el control). */
.mir-tree-row.is-selected { background: var(--brand-soft-bg); border-color: var(--brand);
  box-shadow: inset 3px 0 0 var(--brand); }
/* Modo selección: toda la fila es seleccionable. */
.mir-tree-row.is-selectmode { cursor: pointer; user-select: none; }
.mir-tree-row.is-selectmode:hover { background: var(--control-bg-hover); }
.mir-tree-row.is-selectmode.is-selected:hover { background: var(--brand-soft-bg); }
.mir-tree-pub-btn { min-height: 36px; display: inline-flex; align-items: center; justify-content: center; }
.pg-input--sm { padding: 4px 8px; font-size: 0.8rem; }

/* Barra flotante de selección múltiple (`SelectionBar`, común a todos los
   módulos; MIR era el último con una propia y ya la usa). */
.tb-selbar { position: fixed; left: 50%; bottom: 24px; transform: translateX(-50%); z-index: 800;
  display: flex; align-items: center; gap: 10px; padding: 8px 12px; border-radius: 14px; flex-wrap: wrap;
  background: var(--surface); border: 1px solid var(--border); box-shadow: var(--shadow-lg); max-width: min(96vw, 1120px); }
.tb-selbar-count { font-size: 0.85rem; color: var(--text); white-space: nowrap; font-weight: 600; }
.tb-selbar-sep { width: 1px; height: 22px; background: var(--border); }

/* Modal de publicación / despublicación en cascada */
.mir-pub-box { width: min(620px, 100%); }
.mir-pub-intro { margin: 0 0 12px; font-size: 0.88rem; color: var(--muted); line-height: 1.45; }
.mir-pub-summary { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 12px; }
.mir-pub-chip { padding: 3px 10px; border-radius: 99px; font-size: 0.74rem; font-weight: 700; border: 1px solid transparent; }
/* Colores por estado con tokens del panel (se adaptan a claro/oscuro). */
.mir-pub-chip.is-ready { color: var(--badge-success-fg); background: var(--badge-success-bg); border-color: var(--badge-success-bg); }
.mir-pub-chip.is-err { color: var(--badge-danger-fg); background: var(--badge-danger-bg); border-color: var(--badge-danger-bg); }
.mir-pub-chip.is-live { color: var(--badge-neutral-fg); background: var(--badge-neutral-bg); border-color: var(--badge-neutral-bg); }
.mir-pub-chip.is-warn { color: var(--badge-warn-fg); background: var(--badge-warn-bg); border-color: var(--badge-warn-bg); }
.mir-pub-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; max-height: 46vh; overflow-y: auto; }
.mir-pub-row { display: flex; align-items: center; gap: 10px; padding: 9px 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface); }
.mir-pub-dot { width: 9px; height: 9px; border-radius: 50%; flex-shrink: 0; background: var(--muted); }
.mir-pub-row.is-ready .mir-pub-dot { background: var(--badge-success-fg); }
.mir-pub-row.is-live .mir-pub-dot { background: var(--badge-neutral-fg); }
.mir-pub-row.is-err .mir-pub-dot { background: var(--badge-danger-fg); }
.mir-pub-row.is-warn .mir-pub-dot { background: var(--badge-warn-fg); }
.mir-pub-row.is-off .mir-pub-dot { background: var(--muted); }
.mir-pub-row.is-ready { border-color: var(--badge-success-bg); background: var(--badge-success-bg); }
.mir-pub-row.is-err { border-color: var(--badge-danger-bg); background: var(--badge-danger-bg); }
.mir-pub-row.is-warn { border-color: var(--badge-warn-bg); background: var(--badge-warn-bg); }
.mir-pub-main { flex: 1; min-width: 0; }
.mir-pub-name { font-size: 0.9rem; color: var(--text); font-weight: 500; }
.mir-pub-state { font-size: 0.76rem; font-weight: 700; flex-shrink: 0; color: var(--muted); }
.mir-pub-row.is-ready .mir-pub-state { color: var(--badge-success-fg); }
.mir-pub-row.is-err .mir-pub-state { color: var(--badge-danger-fg); }
.mir-pub-row.is-warn .mir-pub-state { color: var(--badge-warn-fg); }
.mir-pub-progress { flex: 1; display: flex; align-items: center; gap: 12px; padding: 10px 12px; border: 1px solid var(--border);
  border-radius: 10px; background: var(--surface-2); color: var(--text); font-size: 0.85rem; font-weight: 600; min-width: 0; }
.mir-progress-track { position: relative; flex: 1; min-width: 120px; height: 10px; border-radius: 999px; overflow: hidden;
  background: var(--control-bg); border: 1px solid var(--border-soft); }
.mir-progress-fill { position: absolute; inset: 0 auto 0 0; width: 0; border-radius: inherit;
  background: linear-gradient(90deg, var(--brand), var(--brand-dark)); transition: width 0.18s ease; }
.mir-progress-label { white-space: nowrap; }
.mir-rstatus { font-size: 0.7rem; padding: 2px 8px; border-radius: 999px; font-weight: 600; white-space: nowrap; }
.mir-rstatus--draft { background: var(--badge-neutral-bg); color: var(--badge-neutral-fg); }
.mir-rstatus--ready { background: var(--badge-info-bg); color: var(--badge-info-fg); }
.mir-rstatus--live { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.mir-rstatus--paused { background: var(--badge-warn-bg); color: var(--badge-warn-fg); }
.mir-rstatus--archived { background: var(--badge-neutral-bg); color: var(--muted); }

/* ── MIR: popovers de toolbar (filtros / ordenar) ────────────────────────── */
/* Ancho FIJO (no flex-grow) para que la barra de búsqueda sea idéntica en las 4
   tabs; antes flex:1 la hacía crecer distinto según los botones/spacer vecinos. */
.mir-toolbar-search { flex: 0 0 auto; width: 360px; max-width: 100%; }
.mir-pop-wrap { position: relative; display: inline-block; }
.mir-pop-dismiss { position: fixed; inset: 0; z-index: 19; background: transparent; border: none; padding: 0; }
.mir-pop { position: absolute; top: calc(100% + 4px); left: 0; z-index: 20; min-width: 220px;
  background: var(--surface-overlay); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: var(--shadow-lg); padding: 12px; display: flex; flex-direction: column; gap: 10px; }
.mir-pop label { display: flex; flex-direction: column; gap: 4px; font-size: 0.8rem; color: var(--muted); }
.mir-pop--sort { min-width: 200px; padding: 6px; }
.mir-sort-opt { text-align: left; padding: 7px 10px; background: transparent; border: none;
  border-radius: 6px; cursor: pointer; font-family: inherit; font-size: 0.85rem; color: var(--text); }
.mir-sort-opt:hover { background: var(--surface-2); }
.mir-sort-opt.is-active { background: var(--brand-soft-bg); color: var(--brand-dark); font-weight: 600; }
.pg-btn.is-active { border-color: var(--brand); color: var(--brand-dark); }
.mir-toolbar .pg-btn { display: inline-flex; align-items: center; gap: 6px; }
/* Empuja los botones de acción (limpiar / carga / nuevo) hacia la derecha. */
.mir-toolbar-spacer { flex: 1 1 auto; }
/* Botones solo-icono del módulo: conservar comportamiento general. */
.mir-icon-btn { position: relative; }
/* Descendiente (no `>`): el <Icon> envuelve el svg en spans display:contents. */
.mir-icon-btn .mir-icon { margin: 0; }
/* Acciones de fila en recursos: los iconos ESTÁNDAR del panel (`.icon-btn`), un
   pelo más grandes porque la fila del árbol es más alta que la de una tabla. */
.mir-tree-actions .icon-btn { width: 34px; min-width: 34px; height: 34px; }
/* Contador de filtros activos sobre el botón solo-icono. */
.mir-btn-badge { position: absolute; top: -6px; right: -6px; min-width: 16px; height: 16px;
  padding: 0 4px; display: inline-flex; align-items: center; justify-content: center;
  font-size: 0.65rem; font-weight: 700; line-height: 1; color: #fff; background: var(--brand);
  border-radius: 999px; }

/* ── MIR: bloques (vista lista + agenda/calendario) ──────────────────────── */
.mir-viewswitch { display: inline-flex; gap: 2px; }
.mir-row--off { opacity: 0.55; }
.mir-agenda { display: flex; flex-direction: column; gap: 16px; }
.mir-agenda-date { font-weight: 700; color: var(--text-strong); font-size: 0.9rem;
  margin-bottom: 6px; padding-bottom: 4px; border-bottom: 1px solid var(--border); }
.mir-agenda-item { display: flex; align-items: center; gap: 12px; padding: 8px 10px;
  border: 1px solid var(--border-soft); border-radius: 8px; background: var(--surface);
  cursor: pointer; margin-bottom: 4px; }
.mir-agenda-item:hover { background: var(--surface-2); }
.mir-agenda-time { font-weight: 600; color: var(--brand-dark); min-width: 48px; }
.mir-agenda-name { font-weight: 600; color: var(--text); flex: 1; }
.mir-agenda-res { font-size: 0.8rem; color: var(--muted); }

/* ── MIR: bloques — calendario por mes ───────────────────────────────────── */
/* Barra de mes: ‹ Junio 2026 › + Hoy */
.mir-cal-bar { display: flex; align-items: center; gap: 6px; margin-bottom: 12px; }
.mir-cal-nav { border: 1px solid var(--border); background: var(--surface); color: var(--text);
  width: 30px; height: 30px; border-radius: 8px; cursor: pointer; font-size: 1.05rem; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; }
.mir-cal-nav:hover { background: var(--control-bg-hover); }
.mir-cal-title { border: 1px solid transparent; background: transparent; cursor: pointer;
  font-weight: 700; color: var(--text-strong); font-size: 1.05rem; padding: 4px 10px; border-radius: 8px;
  min-width: 150px; text-align: center; }
.mir-cal-title:hover { background: var(--control-bg-hover); border-color: var(--border); }
.mir-cal-today { margin-left: 4px; }
/* Dropdown de mes/año */
.mir-cal-menu { min-width: 240px; padding: 10px; }
.mir-cal-menu-year { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.mir-cal-menu-year > span { font-weight: 700; color: var(--text-strong); }
.mir-cal-menu-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.mir-cal-menu-m { border: 1px solid var(--border); background: var(--surface); color: var(--text);
  border-radius: 8px; padding: 8px 4px; cursor: pointer; text-transform: capitalize; font-size: 0.82rem; }
.mir-cal-menu-m:hover { background: var(--control-bg-hover); }
.mir-cal-menu-m.is-sel { background: var(--brand); border-color: var(--brand); color: #fff; font-weight: 700; }
/* Cabecera de días de la semana */
.mir-cal-dow { display: grid; grid-template-columns: repeat(7, 1fr); gap: 8px; margin-bottom: 8px; }
.mir-cal-dow > span { text-align: center; font-size: 0.72rem; font-weight: 700; color: var(--muted);
  text-transform: uppercase; letter-spacing: 0.04em; }
/* Rejilla de días */
.mir-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 8px; }
.mir-cal-cell { position: relative; min-height: 92px; border: 1px solid var(--border);
  border-radius: 12px; background: var(--surface); padding: 6px 8px; cursor: pointer;
  transition: border-color 0.12s ease, box-shadow 0.12s ease, transform 0.12s ease; display: flex; flex-direction: column; }
.mir-cal-cell:hover { border-color: var(--brand); box-shadow: var(--shadow-md); transform: translateY(-1px); }
.mir-cal-cell--empty { background: transparent; border: none; cursor: default; min-height: 0; }
.mir-cal-cell--empty:hover { box-shadow: none; transform: none; }
.mir-cal-cell.is-today { border-color: var(--brand); box-shadow: inset 0 0 0 1px var(--brand); }
.mir-cal-cell-top { display: flex; align-items: center; justify-content: space-between; }
.mir-cal-daynum { font-weight: 700; color: var(--text); font-size: 0.9rem; }
.mir-cal-cell.is-today .mir-cal-daynum { color: var(--brand-dark); }
.mir-cal-add { opacity: 0; border: 1px solid var(--border); background: var(--surface); color: var(--brand-dark);
  width: 22px; height: 22px; border-radius: 6px; cursor: pointer; line-height: 1; font-size: 1rem;
  display: inline-flex; align-items: center; justify-content: center; transition: opacity 0.12s ease; }
.mir-cal-cell:hover .mir-cal-add { opacity: 1; }
.mir-cal-add:hover { background: var(--brand); border-color: var(--brand); color: #fff; }
/* Señal sutil de "hay bloques" (no se pintan los bloques enteros) */
.mir-cal-hint { margin-top: auto; display: inline-flex; align-items: center; gap: 6px;
  font-size: 0.72rem; color: var(--muted); font-weight: 600; }
.mir-cal-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--brand); flex: 0 0 auto; }
@media (max-width: 640px) {
  .mir-cal-cell { min-height: 64px; padding: 4px 6px; }
  .mir-cal-cnt { display: none; }
  .mir-cal-add { opacity: 1; }
}

/* ── MIR: bloques — vista día (drill) con efecto hacia delante ────────────── */
.mir-day { animation: mir-day-in 0.22s cubic-bezier(0.2, 0.7, 0.2, 1); }
@keyframes mir-day-in { from { opacity: 0; transform: scale(0.96) translateX(14px); } to { opacity: 1; transform: none; } }
/* Salida: inversa a la entrada (se aleja hacia la derecha y desvanece). */
.mir-day.is-closing { animation: mir-day-out 0.2s cubic-bezier(0.4, 0, 1, 1) forwards; }
@keyframes mir-day-out { from { opacity: 1; transform: none; } to { opacity: 0; transform: scale(0.96) translateX(14px); } }
.mir-day-head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; }
.mir-day-title { margin: 0; font-size: 1.02rem; color: var(--text-strong); flex: 1; text-transform: capitalize; }
/* Lista de horas contenida y con scroll (no se extiende indefinidamente).
   Barra estilo sidebar: fina, sin carril reservado y solo visible en hover. */
.mir-day-hours { display: flex; flex-direction: column; max-height: calc(100vh - 300px); min-height: 200px;
  overflow-y: auto; border: 1px solid var(--border-soft); border-radius: 10px;
  scrollbar-width: thin; scrollbar-color: transparent transparent; }
.mir-day-hours:hover { scrollbar-color: var(--control-border) transparent; }
.mir-day-hours::-webkit-scrollbar { width: 8px; }
.mir-day-hours::-webkit-scrollbar-track { background: transparent; }
.mir-day-hours::-webkit-scrollbar-thumb {
  background: transparent; border: 2px solid transparent; background-clip: padding-box;
  border-radius: 8px; transition: background-color 0.2s ease;
}
.mir-day-hours:hover::-webkit-scrollbar-thumb { background: var(--control-border); background-clip: padding-box; }
.mir-day-hours:hover::-webkit-scrollbar-thumb:hover { background: var(--muted-2); background-clip: padding-box; }
.mir-day-hour { display: flex; align-items: stretch; gap: 10px; border-top: 1px solid var(--border-soft);
  min-height: 44px; padding: 4px 0; }
.mir-day-hour:last-child { border-bottom: 1px solid var(--border-soft); }
.mir-day-hlabel { flex: 0 0 48px; font-size: 0.74rem; color: var(--muted); font-weight: 600; padding-top: 4px; }
.mir-day-hbody { flex: 1; display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-width: 0; }
.mir-day-block { display: inline-flex; align-items: center; gap: 8px; padding: 6px 10px;
  border: 1px solid var(--border); border-left: 3px solid var(--brand); border-radius: 8px;
  background: var(--surface); cursor: pointer; font-family: inherit; text-align: left; }
.mir-day-block:hover { background: var(--surface-2); }
.mir-day-btime { font-weight: 700; color: var(--brand-dark); font-size: 0.8rem; }
.mir-day-bname { font-weight: 600; color: var(--text); font-size: 0.84rem; }
.mir-day-bres { font-size: 0.76rem; color: var(--muted); }
.mir-day-hadd { opacity: 0; border: 1px dashed var(--border); background: transparent; color: var(--muted);
  width: 26px; height: 26px; border-radius: 6px; cursor: pointer; line-height: 1; font-size: 1rem;
  display: inline-flex; align-items: center; justify-content: center; transition: opacity 0.12s ease; }
.mir-day-hour:hover .mir-day-hadd { opacity: 1; }
.mir-day-hadd:hover { border-style: solid; border-color: var(--brand); color: var(--brand-dark); background: var(--surface); }

/* ── MIR: selector fecha+hora propio (MirDateTime) ───────────────────────── */
.mir-dtp { position: relative; }
.mir-dtp-btn { width: 100%; text-align: left; border: 1px solid var(--border); background: var(--surface);
  color: var(--text); border-radius: 8px; padding: 8px 10px; cursor: pointer; font-family: inherit; font-size: 0.86rem; }
.mir-dtp-btn:hover { border-color: var(--brand); }
.mir-dtp-btn.is-empty { color: var(--muted); }
.mir-dtp-pop { position: absolute; top: calc(100% + 4px); left: 0; z-index: 20; width: 260px;
  background: var(--surface-overlay); border: 1px solid var(--border); border-radius: 12px; box-shadow: var(--shadow-lg); padding: 10px; }
.mir-dtp-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px; }
.mir-dtp-title { font-weight: 700; color: var(--text-strong); font-size: 0.86rem; }
.mir-dtp-dow { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; margin-bottom: 4px; }
.mir-dtp-dow > span { text-align: center; font-size: 0.66rem; font-weight: 700; color: var(--muted); }
.mir-dtp-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.mir-dtp-day { border: none; background: transparent; color: var(--text); border-radius: 7px;
  aspect-ratio: 1 / 1; cursor: pointer; font-size: 0.8rem; display: inline-flex; align-items: center; justify-content: center; }
.mir-dtp-day:hover { background: var(--control-bg-hover); }
.mir-dtp-day--empty { background: transparent; cursor: default; }
.mir-dtp-day--empty:hover { background: transparent; }
.mir-dtp-day.is-sel { background: var(--brand); color: #fff; font-weight: 700; }
.mir-dtp-foot { display: flex; align-items: center; gap: 6px; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border-soft); }
.mir-dtp-foot-lbl { font-size: 0.78rem; color: var(--muted); font-weight: 600; margin-right: 2px; }
.mir-dtp-sel { padding: 5px 6px; min-width: 62px; }
.mir-dtp-colon { color: var(--muted); font-weight: 700; }

/* ── Reservas: Tablero (kanban) ── */
/* Scroll horizontal con barra estilo sidebar (fina, sin carril reservado, solo
   en hover). Se retiró el doble-flip vertical que la subía arriba: existía
   porque la barra era gruesa y molestaba abajo; con la barra auto-oculta el
   truco solo complicaba (invertía el eje de todo el tablero). */
.mir-kanban-wrap {
  overflow-x: auto; overflow-y: hidden; padding: 2px 0;
  scrollbar-width: thin; scrollbar-color: transparent transparent;
}
.mir-kanban-wrap:hover { scrollbar-color: var(--control-border) transparent; }
.mir-kanban-wrap::-webkit-scrollbar { height: 8px; }
.mir-kanban-wrap::-webkit-scrollbar-track { background: transparent; }
.mir-kanban-wrap::-webkit-scrollbar-thumb {
  background: transparent; border: 2px solid transparent; background-clip: padding-box;
  border-radius: 8px; transition: background-color 0.2s ease;
}
.mir-kanban-wrap:hover::-webkit-scrollbar-thumb { background: var(--control-border); background-clip: padding-box; }
.mir-kanban-wrap:hover::-webkit-scrollbar-thumb:hover { background: var(--muted-2); background-clip: padding-box; }
.mir-kanban { display: flex; gap: 12px; align-items: stretch; }
/* Altura fija responsiva: cubre el alto de la pantalla actual; el cuerpo hace scroll interno. */
.mir-kcol { flex: 0 0 240px; min-width: 240px; background: var(--surface-2); border: 1px solid var(--border-soft);
  border-radius: 12px; display: flex; flex-direction: column;
  height: calc(100vh - 250px); min-height: 420px; }
.mir-kcol.is-drop { border-color: var(--brand); box-shadow: 0 0 0 2px var(--brand-soft-bg) inset; }
.mir-kcol-head { display: flex; align-items: center; gap: 8px; padding: 10px 12px;
  border-bottom: 1px solid var(--border-soft); border-radius: 12px 12px 0 0; }
.mir-kcol-name { font-weight: 700; font-size: 0.85rem; color: var(--text); flex: 1; }
/* Cabecera pintada del color de su estado. */
.mir-kcol-head[data-status="HOLD"]      { background: var(--badge-warn-bg); }
.mir-kcol-head[data-status="HOLD"] .mir-kcol-name      { color: var(--badge-warn-fg); }
.mir-kcol-head[data-status="CONFIRMED"] { background: var(--badge-info-bg); }
.mir-kcol-head[data-status="CONFIRMED"] .mir-kcol-name { color: var(--badge-info-fg); }
.mir-kcol-head[data-status="COMPLETED"] { background: var(--badge-success-bg); }
.mir-kcol-head[data-status="COMPLETED"] .mir-kcol-name { color: var(--badge-success-fg); }
.mir-kcol-head[data-status="CANCELLED"] { background: var(--badge-danger-bg); }
.mir-kcol-head[data-status="CANCELLED"] .mir-kcol-name { color: var(--badge-danger-fg); }
.mir-kcol-head[data-status="EXPIRED"]   { background: var(--badge-neutral-bg); }
.mir-kcol-head[data-status="EXPIRED"] .mir-kcol-name   { color: var(--badge-neutral-fg); }
.mir-kcol-count { font-size: 0.75rem; font-weight: 700; background: var(--control-bg); color: var(--muted);
  border-radius: 999px; padding: 1px 8px; min-width: 22px; text-align: center; }
.mir-kcol-body { padding: 8px; display: flex; flex-direction: column; gap: 8px; overflow-y: auto; flex: 1;
  scrollbar-width: thin; scrollbar-color: transparent transparent; }
.mir-kcol-body:hover { scrollbar-color: var(--control-border) transparent; }
.mir-kcol-body::-webkit-scrollbar { width: 8px; }
.mir-kcol-body::-webkit-scrollbar-track { background: transparent; }
.mir-kcol-body::-webkit-scrollbar-thumb {
  background: transparent; border: 2px solid transparent; background-clip: padding-box;
  border-radius: 8px; transition: background-color 0.2s ease;
}
.mir-kcol-body:hover::-webkit-scrollbar-thumb { background: var(--control-border); background-clip: padding-box; }
.mir-kcol-body:hover::-webkit-scrollbar-thumb:hover { background: var(--muted-2); background-clip: padding-box; }
.mir-kcolempty { font-size: 0.78rem; color: var(--muted); text-align: center; padding: 16px 4px; }
.mir-kcard { background: var(--surface); border: 1px solid var(--border-soft); border-radius: 10px;
  padding: 10px; cursor: pointer; box-shadow: var(--shadow-sm); user-select: none;
  transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease; }
.mir-kcard:hover { border-color: var(--brand); box-shadow: var(--shadow-md); transform: translateY(-2px); }
.mir-kcard-title { font-weight: 600; font-size: 0.85rem; color: var(--text); }
.mir-kcard-holder { font-size: 0.8rem; color: var(--text-1); margin-top: 2px; }
.mir-kcard-meta { font-size: 0.75rem; color: var(--muted); margin-top: 2px; }
.mir-kcard-actions { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 8px; }

/* ── Reservas / MIR: Tab Exportar ── */
.mir-export { padding: 4px 0; }
.mir-export-hint { font-size: 0.85rem; color: var(--muted); margin: 0 0 14px; }
.mir-export-cards { display: flex; flex-wrap: wrap; gap: 14px; }
.mir-export-card { flex: 0 0 240px; background: var(--surface); border: 1px solid var(--border-soft);
  border-radius: 12px; padding: 16px; display: flex; flex-direction: column; gap: 8px; box-shadow: var(--shadow-sm); }
.mir-export-ico { font-size: 1.8rem; }
.mir-export-name { font-weight: 700; font-size: 0.95rem; color: var(--text); flex: 1;
  display: inline-flex; align-items: center; gap: 6px; }
.mir-export-card .pg-btn { margin-top: 6px; }

/* ── MIR: Carga masiva (importar CSV) ── */
.mir-bulk-modal { width: min(760px, 100%); }
.mir-bulk-actions { display: flex; justify-content: flex-end; margin-bottom: 12px; }
.mir-bulk-filerow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 12px; }
.mir-bulk-filerow .mir-bulk-file { flex: 1 1 200px; margin-bottom: 0; }
.mir-bulk-file { display: flex; align-items: center; gap: 8px; border: 1.5px dashed var(--control-border);
  border-radius: 10px; padding: 12px; cursor: pointer; background: var(--control-bg); margin-bottom: 12px;
  transition: transform 0.15s ease, border-color 0.15s ease, background 0.15s ease; }
.mir-bulk-file:hover { transform: scale(1.015); border-color: var(--brand); background: var(--control-bg-hover); }
.mir-bulk-file.is-drag { transform: scale(1.03); border-color: var(--brand); border-style: solid;
  background: var(--brand-soft-bg); box-shadow: 0 0 0 3px var(--brand-soft-bg); }
.mir-bulk-file input[type="file"] { display: none; }
.mir-bulk-file span { font-size: 0.85rem; color: var(--text-1); }
.mir-bulk-empty { font-size: 0.82rem; color: var(--muted); padding: 6px 0; }
.mir-bulk-legend { border: 1px solid var(--border-soft); border-radius: 10px; background: var(--surface-2);
  padding: 10px 12px; margin-bottom: 12px; }
.mir-bulk-legend-title { font-weight: 700; font-size: 0.82rem; color: var(--text); margin-bottom: 6px; }
.mir-bulk-legend ul { margin: 0; padding-left: 16px; display: flex; flex-direction: column; gap: 3px; }
.mir-bulk-legend li { font-size: 0.78rem; color: var(--muted); line-height: 1.4; }
.mir-bulk-legend strong { color: var(--text); }
.mir-bulk-legend em { color: var(--badge-warn-fg); font-style: normal; font-weight: 600; }
.mir-bulk-summary { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 10px; }
.mir-bulk-chip { font-size: 0.78rem; font-weight: 700; border-radius: 999px; padding: 3px 10px;
  background: var(--badge-neutral-bg); color: var(--badge-neutral-fg); }
.mir-bulk-chip--new { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.mir-bulk-chip--edit { background: var(--badge-info-bg); color: var(--badge-info-fg); }
.mir-bulk-chip--del { background: var(--badge-danger-bg); color: var(--badge-danger-fg); }
.mir-bulk-warns { display: flex; flex-direction: column; gap: 4px; margin-bottom: 10px; }
.mir-bulk-warn { font-size: 0.78rem; color: var(--badge-warn-fg); background: var(--badge-warn-bg);
  border-radius: 8px; padding: 6px 10px; }
.mir-bulk-errors { display: flex; flex-direction: column; gap: 4px; margin-bottom: 10px;
  border: 1px solid var(--badge-danger-fg); border-radius: 10px; padding: 8px 10px; background: var(--badge-danger-bg); }
.mir-bulk-errors-title { font-size: 0.8rem; font-weight: 700; color: var(--badge-danger-fg); }
.mir-bulk-error { font-size: 0.78rem; color: var(--badge-danger-fg); }
.mir-bulk-lists { display: flex; flex-direction: column; gap: 12px; margin-top: 10px; }
.mir-bulk-group h4 { margin: 0 0 6px; font-size: 0.82rem; color: var(--muted); }
.mir-bulk-item { font-size: 0.82rem; color: var(--text); padding: 4px 8px; border-radius: 6px;
  background: var(--surface-2); margin-bottom: 3px; display: flex; align-items: baseline; gap: 8px;
  justify-content: space-between; }
.mir-bulk-item-name { font-weight: 600; }
.mir-bulk-item-meta { font-size: 0.75rem; color: var(--muted); text-align: right; }
.mir-bulk-item--del { color: var(--badge-danger-fg); text-decoration: line-through; }

.mir-delete-modal { width: min(620px, 100%); }
.mir-delete-lead { margin: 0 0 12px; color: var(--text); }
.mir-delete-summary { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; margin-bottom: 14px; }
.mir-delete-stat { padding: 12px; border-radius: 12px; background: var(--surface-2); border: 1px solid var(--border); color: var(--text); font-size: 0.84rem; }
.mir-delete-list { margin-top: 12px; }
.mir-delete-list h4 { margin: 0 0 8px; font-size: 0.82rem; color: var(--muted); }
.mir-delete-item { padding: 7px 10px; border-radius: 8px; background: var(--surface-2); color: var(--text); margin-bottom: 6px; font-size: 0.82rem; }
.mir-delete-loading { margin-top: 12px; color: var(--muted); font-size: 0.82rem; }
.mir-delete-arm { margin-top: 12px; padding: 12px; border-radius: 12px; background: rgba(220,38,38,0.08); color: var(--danger); border: 1px solid rgba(220,38,38,0.35); font-size: 0.84rem; }
.mir-res-actions { display: flex; flex-wrap: wrap; gap: 8px; padding-top: 10px; margin-top: 6px; border-top: 1px solid var(--border-soft); }
@media (max-width: 640px) { .mir-delete-summary { grid-template-columns: 1fr; } }

/* ═══════════════════════════════════════════════════════════════════════════
   MARKETPLACE (pages/marketplace.rs) — tokens only, ver reglas de theming
   ═══════════════════════════════════════════════════════════════════════════ */

.mk-page { min-height: 100vh; background: var(--bg); }
.mk-body { padding: 20px 24px; max-width: 1100px; margin: 0 auto; }

.mk-install-card { display: flex; justify-content: space-between; align-items: center; gap: 16px;
  flex-wrap: wrap; background: var(--surface); border: 1px solid var(--border);
  border-radius: 12px; padding: 16px 18px; margin-bottom: 14px; box-shadow: var(--shadow-sm); }
.mk-install-title { margin: 0 0 4px; font-size: 0.95rem; color: var(--text-strong); }
.mk-install-hint { margin: 0; font-size: 0.8rem; color: var(--muted); max-width: 560px; }
.mk-install-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.mk-force { display: flex; align-items: center; gap: 6px; font-size: 0.78rem; color: var(--muted);
  cursor: pointer; user-select: none; }
.mk-upload-btn { display: inline-flex; align-items: center; cursor: pointer; }
.mk-upload-btn.is-busy { opacity: 0.7; cursor: wait; }

.mk-banner { padding: 10px 14px; border-radius: 10px; font-size: 0.84rem; margin-bottom: 12px; }
.mk-banner--error { background: var(--badge-danger-bg); color: var(--badge-danger-fg); }
.mk-banner--ok { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.mk-banner--warn { background: var(--badge-warn-bg); color: var(--badge-warn-fg); }
.mk-banner--info { background: var(--badge-info-bg); color: var(--badge-info-fg); }

/* Módulos activables (eje activo/catalogable) */
.mk-modules { max-width: 720px; }
.mk-mod-hint { color: var(--muted); font-size: 0.85rem; margin: 0 0 14px; line-height: 1.45; }
.mk-mod-list { display: flex; flex-direction: column; gap: 8px; }
.mk-mod-row { display: flex; align-items: center; gap: 12px; padding: 10px 14px;
    background: var(--surface); border: 1px solid var(--border); border-radius: 10px; }
.mk-mod-icon { font-size: 1.1rem; width: 1.4rem; text-align: center; }
.mk-mod-name { flex: 1; color: var(--text); font-weight: 500; }
.mk-mod-btn { min-width: 104px; }

/* Funcionalidades (SMTP) */
.mk-feat-block { margin-bottom: 22px; }
.mk-feat-title { font-size: 0.9rem; color: var(--text-strong); margin: 0 0 8px; }
.mk-feat-main { flex: 1; display: flex; flex-direction: column; gap: 2px; }
.mk-feat-sub { font-size: 0.78rem; color: var(--muted); }
.mk-feat-input { background: var(--control-bg); border: 1px solid var(--control-border);
    color: var(--text); border-radius: 8px; padding: 6px 10px; font-size: 0.84rem; width: 200px; }
.mk-feat-hint { color: var(--muted); font-size: 0.8rem; margin: 8px 0 0; }

.mk-table { margin-bottom: 10px; }
.mk-row { display: grid; grid-template-columns: 1.6fr 110px 90px 1fr 130px 210px; gap: 8px;
  padding: 10px 14px; border-bottom: 1px solid var(--border); font-size: 0.83rem;
  color: var(--text); align-items: center; }
.mk-row:last-child { border-bottom: none; }
.mk-row > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mk-row--head { font-weight: 700; background: var(--surface-2); color: var(--muted);
  text-transform: uppercase; font-size: 0.68rem; letter-spacing: 0.03em; }
.mk-name { font-weight: 600; color: var(--text-strong); }
.mk-mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.78rem; }
.mk-tag--theme { background: var(--badge-purple-bg); color: var(--badge-purple-fg); }
.mk-tag--module { background: var(--badge-info-bg); color: var(--badge-info-fg); }
.mk-footnote { font-size: 0.75rem; color: var(--muted-2); margin-top: 6px; }

/* ── Marketplace F4: tabs + catálogo + modal de publicación ─────────────── */
.mk-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border);
    margin-bottom: 18px; }
.mk-tab { appearance: none; border: none; background: transparent; cursor: pointer;
    padding: 10px 16px; font-size: 0.85rem; color: var(--muted); font-weight: 600;
    border-bottom: 2px solid transparent; margin-bottom: -1px; }
.mk-tab:hover { color: var(--text); }
.mk-tab.active { color: var(--brand); border-bottom-color: var(--brand); }

.mk-catalog-bar { display: flex; justify-content: space-between; align-items: center;
    gap: 16px; margin-bottom: 16px; flex-wrap: wrap; }

.mk-catalog-grid { display: grid; gap: 16px;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }

.mk-card { display: flex; flex-direction: column; background: var(--surface);
    border: 1px solid var(--border); border-radius: 14px; overflow: hidden; }
.mk-card-logo { height: 120px; display: flex; align-items: center; justify-content: center;
    background: var(--surface-2); border-bottom: 1px solid var(--border); }
.mk-card-logo img { max-width: 100%; max-height: 100%; object-fit: contain; }
.mk-card-logo-ph { font-size: 2.4rem; opacity: 0.7; }
.mk-card-body { padding: 14px 16px; flex: 1; }
.mk-card-head { display: flex; align-items: center; justify-content: space-between;
    gap: 8px; margin-bottom: 6px; }
.mk-card-title { margin: 0; font-size: 0.95rem; color: var(--text-strong);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mk-card-summary { margin: 0 0 10px; font-size: 0.82rem; color: var(--muted);
    line-height: 1.4; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; }
.mk-card-meta { display: flex; align-items: center; justify-content: space-between;
    gap: 8px; font-size: 0.76rem; color: var(--muted-2); }
.mk-card-pub { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mk-card-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.mk-chip { font-size: 0.7rem; padding: 2px 8px; border-radius: 999px;
    background: var(--surface-2); color: var(--muted); border: 1px solid var(--border); }
.mk-card-actions { padding: 12px 16px; border-top: 1px solid var(--border);
    display: flex; justify-content: flex-end; }

.mk-modal-backdrop { position: fixed; inset: 0; background: var(--scrim);
    display: flex; align-items: flex-start; justify-content: center; z-index: 1000;
    padding: 5vh 20px; overflow-y: auto; }
.mk-modal { background: var(--surface-overlay); border: 1px solid var(--border);
    border-radius: 16px; box-shadow: var(--shadow-lg); width: 100%; max-width: 520px;
    max-height: 90vh; overflow-y: auto; padding: 22px 24px; margin: auto; }
/* Modal de formulario: sin recorte para que las tooltips salgan fuera del modal
   (el scroll pasa al backdrop). */
.mk-modal--form { overflow: visible; max-height: none; }
.mk-modal-head { display: flex; align-items: center; justify-content: space-between;
    margin-bottom: 4px; }
.mk-modal-head h3 { margin: 0; font-size: 1.02rem; color: var(--text-strong); }
.mk-modal-x { appearance: none; border: none; background: transparent; cursor: pointer;
    font-size: 1rem; color: var(--muted); padding: 4px 8px; border-radius: 8px; }
.mk-modal-x:hover { background: var(--control-bg-hover); color: var(--text); }
.mk-field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 14px; }
.mk-field > span { font-size: 0.78rem; color: var(--muted); font-weight: 600; }
.mk-modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 8px;
    flex-wrap: wrap; align-items: center; }
/* Una acción NUNCA parte su etiqueta en dos renglones: un botón a media palabra
   se lee como un fallo de maqueta. Si no caben, envuelve la fila (arriba). */
.mk-modal-actions .pg-btn, .mk-modal-actions .mk-linkbtn { white-space: nowrap; }
/* El enlace-acción se pinta como botón: sin el subrayado global de los <a>. */
.mk-modal-actions a.pg-btn { text-decoration: none; display: inline-flex;
    align-items: center; }
.mk-modal--sm { max-width: 420px; }
/* Modal de confirmación con TRES acciones (aviso de tools): a 420 px la tercera
   se salía y las etiquetas se partían. */
.mk-modal--acts3 { max-width: 540px; }
.mk-confirm-msg { margin: 4px 0 18px; font-size: 0.88rem; color: var(--muted); line-height: 1.5; }
/* Secciones plegables de la ficha (Herramientas, Versiones). `<details>` nativo:
   sin JS, accesible con teclado y recordando su estado mientras la ficha vive.
   Cerradas por defecto — son detalle, no lo primero que se mira. */
.mk-fold { border-top: 1px solid var(--border); padding: 14px 0 0; margin-top: 18px; }
.mk-fold-head { display: flex; align-items: center; gap: 10px; cursor: pointer;
    list-style: none; padding: 2px 0; user-select: none; }
.mk-fold-head::-webkit-details-marker { display: none; }   /* triángulo nativo */
.mk-fold-head h3 { margin: 0; font-size: 0.94rem; color: var(--text-strong); }
.mk-fold-head:hover h3 { color: var(--brand); }
.mk-fold-arrow { display: inline-block; font-size: 1.1rem; line-height: 1;
    color: var(--muted); transition: transform 0.16s ease; }
.mk-fold[open] .mk-fold-arrow { transform: rotate(90deg); }
.mk-fold-badge { min-width: 20px; padding: 1px 7px; border-radius: 999px;
    background: var(--brand-soft-bg); color: var(--brand-soft-fg);
    font-size: 0.72rem; font-weight: 600; text-align: center; }
.mk-fold-body { padding-top: 12px; }

/* Apertura/cierre animados. Dos capas, y hacen falta las dos:
   · `::details-content` + `interpolate-size` anima la altura REAL en los dos
     sentidos (abrir y cerrar), pero solo existe en navegadores recientes;
   · el keyframe de respaldo cubre al resto — solo puede animar la apertura,
     porque al cerrar el contenido desaparece del árbol antes de poder animarlo.
   Van separados por `@supports` para que no se animen a la vez y salga doble. */
@keyframes mk-fold-in {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}
.mk-fold[open] > .mk-fold-body { animation: mk-fold-in 0.18s ease-out; }

@supports selector(details::details-content) {
    .mk-fold[open] > .mk-fold-body { animation: none; }
    .mk-fold { interpolate-size: allow-keywords; }
    .mk-fold::details-content {
        block-size: 0;
        overflow: hidden;
        opacity: 0;
        transition: block-size 0.22s ease, content-visibility 0.22s allow-discrete,
                    opacity 0.18s ease;
    }
    .mk-fold[open]::details-content { block-size: auto; opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .mk-fold[open] > .mk-fold-body { animation: none; }
    .mk-fold::details-content { transition: none; }
}

/* Tools del agente en la ficha del módulo. */
.mk-tools { display: flex; flex-direction: column; gap: 10px; }
.mk-tool-row { background: var(--surface-2); border: 1px solid var(--border-soft);
    border-radius: 10px; padding: 10px 12px; }
.mk-tool-head { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }
.mk-tool-desc { margin: 0; font-size: 0.84rem; color: var(--muted); line-height: 1.45; }
.mk-chip--on { background: var(--badge-success-bg); color: var(--badge-success-fg); }

/* Lista de tools del agente que trae un módulo recién instalado (aviso).
   Viñetas, una por línea: de corrido y separadas por puntos no se leen como
   una lista de cosas que el agente podrá hacer, que es lo que son. */
.mk-tools-ul { margin: 0 0 18px; padding: 10px 12px 10px 28px; list-style: disc;
    background: var(--surface-2); border: 1px solid var(--border-soft);
    border-radius: 8px; font-size: 0.82rem; color: var(--text); }
.mk-tools-ul li { margin: 2px 0; word-break: break-word; }
/* Check de purga al desinstalar un módulo. */
.mk-purge { display: flex; gap: 10px; align-items: flex-start; margin: 0 0 18px;
    padding: 10px 12px; background: var(--surface-2);
    border: 1px solid var(--border-soft); border-radius: 10px; cursor: pointer; }
.mk-purge input { margin-top: 2px; flex: 0 0 auto; }
.mk-purge span { display: flex; flex-direction: column; gap: 3px; }
.mk-purge strong { font-size: 0.84rem; font-weight: 600; color: var(--text-strong); }
.mk-purge em { font-style: normal; font-size: 0.78rem; color: var(--muted); line-height: 1.45; }

/* Salida neutra de un modal: texto, sin caja. No compite con las acciones. */
/* Sin subrayado en reposo: junto a dos botones reales, un texto subrayado se leía
   como un enlace roto. Aparece al pasar por encima, que es cuando hace falta la
   señal de "esto se pulsa". */
.mk-linkbtn { background: none; border: none; padding: 6px 4px; margin-right: auto;
    font: inherit; font-size: 0.84rem; color: var(--muted); cursor: pointer;
    text-decoration: none; text-underline-offset: 3px; }
.mk-linkbtn:hover:not(:disabled) { color: var(--text); text-decoration: underline; }
.mk-linkbtn:disabled { opacity: 0.5; cursor: default; }

/* ── Catálogo v2: cards compactas expandibles ──────────────────────────── */
.mk-cards { display: grid; gap: 14px; align-items: start;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); }
.mk-card2 { display: flex; background: var(--surface); border: 1px solid var(--border);
    border-radius: 14px; overflow: hidden; cursor: pointer;
    transition: transform 0.16s ease, box-shadow 0.16s ease, border-color 0.16s ease; }
.mk-card2:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg);
    border-color: var(--brand); }
.mk-card2-main { flex: 1 1 auto; min-width: 0; padding: 14px 16px;
    display: flex; flex-direction: column; gap: 8px; }
.mk-card2-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.mk-card2-title { font-weight: 600; color: var(--text-strong);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mk-card2-sub { display: flex; align-items: center; gap: 8px; font-size: 0.78rem; color: var(--muted); }
.mk-card2-actions { display: flex; align-items: center; gap: 8px; margin-top: 6px; }
/* Acciones de un paquete (instalar / actualizar / desinstalar). Cuáles salen
   depende del estado, así que NO pueden tener posición fija: con `margin-left:auto`
   un solo botón se pegaba al extremo dejando un hueco muerto, y con dos la fila
   quedaba descentrada. Ahora reparten el ancho entre los que haya: 1 botón ocupa
   todo, 2 van a mitades, 3 a tercios. */
.mk-act { flex: 1 1 0; min-width: 0; text-align: center; justify-content: center; }
/* En la ficha de detalle NO se estiran: ahí conviven con el título y estirarlos
   daría botones enormes. Solo se agrupan a la izquierda, sin hueco delante. */
.mk-detail-actions .mk-act { flex: 0 0 auto; }
.mk-push { margin-left: auto; }
.mk-update { background: var(--brand-soft-bg); color: var(--brand-soft-fg); }
.mk-update:hover { background: var(--brand-soft-bg); filter: brightness(1.08); }
/* Panel lateral que aparece al expandir la card hacia la derecha. */
.mk-card2-more { flex: 0 0 0; width: 0; overflow: hidden; opacity: 0;
    background: var(--surface-2); border-left: 0 solid var(--border);
    transition: width 0.2s ease, opacity 0.2s ease, padding 0.2s ease; }
.mk-card2.is-expanded { grid-column: span 2; border-color: var(--brand); }
.mk-card2.is-expanded .mk-card2-more { flex: 0 0 250px; width: 250px; opacity: 1;
    padding: 14px 16px; border-left: 1px solid var(--border); }
.mk-card2-logo { max-width: 100%; max-height: 90px; object-fit: contain; border-radius: 8px;
    margin-bottom: 10px; display: block; }
.mk-card2-summary { margin: 0 0 10px; font-size: 0.82rem; color: var(--text); line-height: 1.45; }
.mk-card2-kv { display: flex; justify-content: space-between; gap: 8px;
    font-size: 0.76rem; color: var(--muted-2); margin-bottom: 8px; }
.mk-card2-kv > span:last-child { color: var(--muted); }

/* ── Tab Subida: tabla técnica ─────────────────────────────────────────── */
.mk-up-table { margin-bottom: 10px; }
.mk-up-row { display: grid; grid-template-columns: 1.3fr 1.4fr 80px 90px 90px 190px; gap: 8px;
    align-items: center; padding: 10px 12px; border-bottom: 1px solid var(--border); }
.mk-up-row:last-child { border-bottom: none; }
.mk-up-row > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mk-up-row--head { font-weight: 700; background: var(--surface-2); color: var(--muted);
    font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.04em; }
.mk-up-tags { display: flex; flex-wrap: wrap; gap: 4px; white-space: normal; }
.mk-up-link { color: var(--brand); cursor: pointer; }
.mk-up-link:hover { text-decoration: underline; }
.mk-up-row .pg-actions { display: flex; gap: 6px; white-space: normal; }

/* ── Rejilla de CATEGORÍAS (primera vista del catálogo) ────────────────────── */
.mk-cat-grid { display: grid; gap: 18px; align-items: start;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
.mk-cat { appearance: none; cursor: pointer; text-align: left; display: flex;
    flex-direction: column; gap: 8px; padding: 22px 20px; border-radius: 16px;
    border: 1px solid var(--border);
    background: linear-gradient(150deg, var(--brand-soft-bg), var(--surface) 78%);
    transition: transform 0.16s ease, box-shadow 0.16s ease, border-color 0.16s ease; }
.mk-cat:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); border-color: var(--brand); }
/* En «Paquetes instalados» las categorías FILTRAN la lista de abajo en vez de
   entrar a otra pantalla, así que van más bajas: comparten sitio con la toolbar
   y la rejilla, y a tamaño completo se comerían la vista. */
.mk-cat-grid--sm { gap: 12px; margin-bottom: 16px;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); }
.mk-cat-grid--sm .mk-cat { padding: 14px 16px; gap: 4px; border-radius: 12px; }
.mk-cat-grid--sm .mk-cat-emoji { font-size: 1.5rem; }
.mk-cat-grid--sm .mk-cat-emoji svg { width: 1.5rem; height: 1.5rem; }
.mk-cat-grid--sm .mk-cat-label { font-size: 0.94rem; }
.mk-cat-grid--sm .mk-cat-count { font-size: 0.74rem; }
/* Filtro aplicado: se marca la tarjeta, que es el control que lo activó. */
.mk-cat.is-active { border-color: var(--brand); box-shadow: 0 0 0 1px var(--brand) inset; }
.mk-cat-emoji { font-size: 2.4rem; line-height: 1; color: var(--brand); display: inline-flex; }
/* Icono del iconset en la card de categoría (si hay iconset activo que lo cubra);
   si no, cae al emoji de fallback (texto) — de ahí el font-size de arriba. */
.mk-cat-emoji svg { width: 2.4rem; height: 2.4rem; display: block; }
.mk-cat-label { font-size: 1.15rem; font-weight: 700; color: var(--text-strong); }
.mk-cat-count { font-size: 0.8rem; color: var(--muted); }

/* ── Catálogo v3: cards CUADRADAS (imagen arriba) ──────────────────────────── */
.mk-grid { display: grid; gap: 16px; align-items: start; justify-content: start;
    grid-template-columns: repeat(auto-fill, minmax(180px, 200px)); }
/* Los módulos del código y los paquetes del registry se pintan en dos bloques
   distintos del `view!`, pero deben compartir UNA rejilla: si cada bloque abre su
   propia `.mk-grid`, el primero cierra su última fila a medias y el segundo empieza
   otra, y las tarjetas dejan de cuadrar entre secciones. `display: contents` hace
   que las tarjetas de dentro sean hijas directas de la rejilla de fuera. */
.mk-grid-part { display: contents; }

/* ── Funcionalidades del panel (SMTP y futuras) ────────────────────────────
   No son módulos con pantalla propia, así que no van en la rejilla de tarjetas:
   se listan como filas con su descripción y su botón de encendido. */
.mk-feats { margin-top: 28px; }
.mk-feat { display: flex; gap: 16px; align-items: flex-start; justify-content: space-between;
    background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
    padding: 16px 18px; }
.mk-feat-main { flex: 1 1 auto; min-width: 0; }
.mk-feat-head { display: flex; align-items: center; gap: 10px; margin-bottom: 6px; }
.mk-feat-name { font-weight: 600; color: var(--text-strong); }
.mk-feat-actions { flex: 0 0 auto; }
@media (max-width: 640px) {
    .mk-feat { flex-direction: column; align-items: stretch; }
}
/* Avisos y estados vacíos ocupan la fila entera; si no, la rejilla los encajaría
   en una columna de 200px. */
.mk-grid > .mk-banner, .mk-grid > .pg-empty { grid-column: 1 / -1; }
/* Cuadro PERFECTO: la card entera es 1:1; la imagen ocupa el espacio restante
   sobre el cuerpo (nombre/versión/acciones). */
.mk-sq { display: flex; flex-direction: column; aspect-ratio: 1 / 1; background: var(--surface);
    border: 1px solid var(--border); border-radius: 14px; overflow: hidden; cursor: pointer;
    transition: transform 0.16s ease, box-shadow 0.16s ease, border-color 0.16s ease; }
.mk-sq:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); border-color: var(--brand); }
.mk-sq-thumb { position: relative; flex: 1 1 auto; min-height: 0; background: var(--surface-2);
    display: flex; align-items: center; justify-content: center; overflow: hidden; }
.mk-sq-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.mk-sq-ph { font-size: 3rem; font-weight: 800; color: var(--muted-2); text-transform: uppercase; }
.mk-sq-ph--lg { font-size: 4.5rem; }
.mk-sq-type { position: absolute; top: 8px; left: 8px; }
.mk-sq-body { flex: 0 0 auto; padding: 10px 12px; display: flex; flex-direction: column; gap: 6px; }
.mk-sq-name { font-weight: 600; color: var(--text-strong);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mk-sq-sub { display: flex; align-items: center; gap: 8px; font-size: 0.78rem; color: var(--muted); }
.mk-sq-actions { display: flex; align-items: stretch; gap: 8px; margin-top: 2px; }
.mk-sq-actions .mk-push { margin-left: 0; }

/* ── Pantalla de detalle (tipo store) ──────────────────────────────────────── */
.mk-detail { display: flex; flex-direction: column; gap: 18px; }
.mk-back { align-self: flex-start; appearance: none; border: 1px solid var(--border);
    background: var(--control-bg); color: var(--text); cursor: pointer; font-weight: 600;
    padding: 7px 14px; border-radius: 999px; display: inline-flex; align-items: center; gap: 4px;
    margin-bottom: 14px;
    transition: background 0.15s ease, border-color 0.15s ease, transform 0.15s ease; }
.mk-back:hover { background: var(--control-bg-hover); border-color: var(--brand); transform: translateX(-2px); }
.mk-back-arrow { font-size: 1.2rem; line-height: 1; }
.mk-detail-hero { display: flex; gap: 20px; align-items: center; }
.mk-detail-cover { flex: 0 0 140px; width: 140px; height: 140px; border-radius: 18px;
    overflow: hidden; background: var(--surface-2); display: flex; align-items: center; justify-content: center; }
.mk-detail-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
.mk-detail-headinfo { display: flex; flex-direction: column; gap: 10px; min-width: 0; }
.mk-detail-title { margin: 0; font-size: 1.5rem; color: var(--text-strong); }
.mk-detail-meta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 0.85rem; color: var(--muted); }
.mk-detail-actions { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 4px; }
.mk-muted { color: var(--muted); }
.mk-detail-section { display: flex; flex-direction: column; gap: 10px; }
.mk-detail-section h3 { margin: 0; font-size: 0.95rem; color: var(--text-strong); }
.mk-detail-desc { margin: 0; font-size: 0.9rem; color: var(--text); line-height: 1.6; white-space: pre-wrap; }
.mk-vers { display: flex; flex-direction: column; border: 1px solid var(--border); border-radius: 10px; overflow: hidden; }
.mk-ver-row { display: grid; grid-template-columns: 100px 1fr auto; gap: 10px; align-items: center;
    padding: 8px 12px; border-bottom: 1px solid var(--border); font-size: 0.82rem; }
.mk-ver-row:last-child { border-bottom: none; }

/* Carrusel de imágenes de vista previa (scroll lateral). */
.mk-shots { display: flex; gap: 12px; overflow-x: auto; padding-bottom: 6px; scroll-snap-type: x mandatory; }
.mk-shot { flex: 0 0 auto; appearance: none; border: 1px solid var(--border); background: var(--surface-2);
    border-radius: 12px; overflow: hidden; cursor: pointer; padding: 0; scroll-snap-align: start;
    transition: border-color 0.15s ease, transform 0.15s ease; }
.mk-shot:hover { border-color: var(--brand); transform: translateY(-2px); }
.mk-shot img { height: 200px; width: auto; max-width: 360px; object-fit: cover; display: block; }

/* Lightbox (imagen ampliada en modal). */
.mk-lightbox { position: fixed; inset: 0; z-index: 1100; background: var(--scrim, rgba(0,0,0,0.8));
    display: flex; align-items: center; justify-content: center; padding: 32px; cursor: zoom-out; }
.mk-lightbox img { max-width: 92vw; max-height: 88vh; object-fit: contain; border-radius: 10px;
    box-shadow: var(--shadow-lg); cursor: default; }
.mk-lightbox-x { position: absolute; top: 18px; right: 22px; appearance: none; border: none;
    background: rgba(0,0,0,0.5); color: #fff; font-size: 1.1rem; width: 40px; height: 40px;
    border-radius: 50%; cursor: pointer; }
.mk-lightbox-x:hover { background: rgba(0,0,0,0.75); }

/* ── Form de subida: tooltips, imagen centrada, chips de preview ───────────── */
.mk-flabel { display: inline-flex; align-items: center; gap: 6px; font-size: 0.78rem;
    color: var(--muted); font-weight: 600; }
.mk-field--center { align-items: center; text-align: center; }
.mk-imgpick { position: relative; display: inline-flex; align-items: center; justify-content: center; cursor: pointer;
    width: 120px; height: 120px; border: 2px dashed var(--border); border-radius: 16px; overflow: hidden;
    background: var(--surface-2); color: var(--muted); font-size: 0.78rem; text-align: center;
    padding: 8px; transition: border-color 0.15s ease, color 0.15s ease; }
.mk-imgpick:hover { border-color: var(--brand); color: var(--text); }
.mk-imgpick-preview { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* Miniaturas de imágenes de vista previa en el form. */
.mk-promo-grid { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }
.mk-promo-thumb { position: relative; width: 84px; height: 84px; border-radius: 10px; overflow: hidden;
    border: 1px solid var(--border); background: var(--surface-2); }
.mk-promo-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.mk-promo-thumb .mk-promo-x { position: absolute; top: 3px; right: 3px; width: 20px; height: 20px;
    border-radius: 50%; background: rgba(0,0,0,0.6); color: #fff; border: none; cursor: pointer;
    font-size: 0.7rem; display: flex; align-items: center; justify-content: center; padding: 0; }
.mk-promo-thumb .mk-promo-x:hover { background: rgba(0,0,0,0.85); }

/* Modal ancho de tamaño FIJO (vista previa de la página del paquete): grande,
   responsivo y con scroll interno — no se adapta al contenido. */
.mk-modal--wide { width: min(920px, 94vw); max-width: none; height: 84vh; max-height: 84vh;
    overflow: hidden; display: flex; flex-direction: column; margin: 0 auto; }
.mk-modal-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden;
    margin-top: 12px; }
.mk-ph-tag { opacity: 0.7; }
.mk-ph-note { font-size: 0.72rem; color: var(--muted); align-self: center; }
.mk-back:disabled { cursor: default; opacity: 0.6; }
.mk-back:disabled:hover { transform: none; border-color: var(--border); background: var(--control-bg); }
.mk-tip { display: inline-flex; align-items: center; justify-content: center; width: 16px; height: 16px;
    border-radius: 50%; background: var(--control-bg); color: var(--muted); border: 1px solid var(--border);
    font-size: 0.68rem; font-weight: 700; cursor: help; position: relative; }
.mk-tip:hover { color: var(--text); border-color: var(--brand); }
.mk-tip::after { content: attr(data-tip); position: absolute; bottom: 130%; left: 50%;
    transform: translateX(-50%); width: max-content; max-width: 240px; white-space: normal;
    background: var(--tooltip-bg); color: var(--tooltip-fg); font-size: 0.72rem; font-weight: 500;
    line-height: 1.4; padding: 7px 10px; border-radius: 8px; box-shadow: var(--shadow-md);
    opacity: 0; pointer-events: none; transition: opacity 0.15s ease; z-index: 50; }
.mk-tip:hover::after { opacity: 1; }
.mk-promo-list { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.mk-promo-chip { display: inline-flex; align-items: center; gap: 6px; font-size: 0.74rem;
    background: var(--surface-2); border: 1px solid var(--border); border-radius: 999px; padding: 3px 6px 3px 10px; }
.mk-promo-x { appearance: none; border: none; background: transparent; color: var(--muted);
    cursor: pointer; font-size: 0.72rem; padding: 2px 4px; border-radius: 50%; }
.mk-promo-x:hover { background: var(--control-bg-hover); color: var(--text); }

@media (max-width: 640px) {
    .mk-detail-hero { flex-direction: column; align-items: flex-start; }
}

/* ── Identidad Visual (F6.1) — selección de tema base ─────────────────────── */
.identity-theme-list { display: flex; flex-direction: column; gap: 8px; max-width: 520px; }
.identity-theme-option { display: flex; align-items: center; gap: 12px; cursor: pointer;
    padding: 12px 14px; border: 1px solid var(--border); border-radius: 10px;
    background: var(--control-bg); transition: border-color .15s, background .15s; }
.identity-theme-option:hover { border-color: var(--brand); background: var(--control-bg-hover); }
.identity-theme-option.is-active { border-color: var(--brand); background: var(--brand-soft-bg); }
.identity-theme-option input[type="radio"] { accent-color: var(--brand); margin: 0; cursor: pointer; }
.identity-theme-option input:disabled { cursor: not-allowed; }
.identity-theme-name { font-weight: 600; color: var(--text-strong); }
.identity-theme-ver { margin-left: auto; font-size: 0.78rem; color: var(--muted); }

/* Escala de fuente (F6.3): botonera de valores discretos. */
.identity-scale-btns { display: flex; flex-wrap: wrap; gap: 8px; }
.identity-scale-btn { padding: 8px 16px; border: 1px solid var(--border); border-radius: 8px;
    background: var(--control-bg); color: var(--text); font-weight: 600; cursor: pointer;
    transition: border-color .15s, background .15s, color .15s; }
.identity-scale-btn:hover:not(:disabled) { border-color: var(--brand); background: var(--control-bg-hover); }
.identity-scale-btn.is-active { border-color: var(--brand); background: var(--brand-soft-bg); color: var(--brand-soft-fg); }
.identity-scale-btn:disabled { opacity: 0.55; cursor: not-allowed; }
.profile-subsection-title { margin: 0 0 12px; font-size: 0.95rem; font-weight: 700; color: var(--text-strong); }

/* Iconos de iconset (F6.4): el <span> contiene un <svg> reconstruido por el
   componente Icon. Se dimensiona al hueco y hereda el color del texto. */
.module-sidebar-icon svg { width: 1.25em; height: 1.25em; display: block; }

/* ═══════════════════════════════════════════════════════════════════════════
   MOTOR SDUI (src/sdui/) — tokens only; clases sdui-* para módulos instalados
   ═══════════════════════════════════════════════════════════════════════════ */

.sdui-page { min-height: 100vh; background: var(--bg); }
.sdui-page-body { padding: 20px 24px; max-width: 1200px; margin: 0 auto; }
.sdui-page-msg { padding: 40px; text-align: center; color: var(--muted); }
.sdui-view-title { font-size: 1.15rem; color: var(--text-strong); margin: 0 0 14px; }

.sdui-card { background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  padding: 16px; box-shadow: var(--shadow-sm); }
.sdui-placeholder { border: 1px dashed var(--border); border-radius: 8px; padding: 10px 12px;
  color: var(--muted-2); font-size: 0.8rem; background: var(--surface-2); }
.sdui-placeholder code { color: var(--muted); }

.sdui-heading { color: var(--text-strong); margin: 0; }
.sdui-text { color: var(--text); margin: 0; font-size: 0.88rem; }
.sdui-text--muted { color: var(--muted); }

.sdui-badge { display: inline-block; padding: 2px 9px; border-radius: 999px;
  font-size: 0.72rem; font-weight: 600; }
.sdui-badge--primary { background: var(--brand-soft-bg); color: var(--brand-soft-fg); }
.sdui-badge--info    { background: var(--badge-info-bg);    color: var(--badge-info-fg); }
.sdui-badge--success { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.sdui-badge--warning { background: var(--badge-warn-bg);    color: var(--badge-warn-fg); }
.sdui-badge--danger  { background: var(--badge-danger-bg);  color: var(--badge-danger-fg); }
.sdui-badge--gray    { background: var(--badge-neutral-bg); color: var(--badge-neutral-fg); }

.sdui-alert { display: flex; gap: 10px; align-items: flex-start; padding: 12px 14px;
  border-radius: 10px; border: 1px solid var(--border-soft); font-size: 0.85rem; }
.sdui-alert--info    { background: var(--badge-info-bg);    color: var(--badge-info-fg); }
.sdui-alert--success { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.sdui-alert--warning { background: var(--badge-warn-bg);    color: var(--badge-warn-fg); }
.sdui-alert--danger  { background: var(--badge-danger-bg);  color: var(--badge-danger-fg); }
.sdui-alert-title { display: block; margin-bottom: 2px; }
.sdui-alert-body { flex: 1; }
.sdui-alert-close { background: none; border: none; cursor: pointer; color: inherit; font-size: 0.9rem; }

.sdui-divider { border: none; border-top: 1px solid var(--border); margin: 10px 0; }
.sdui-divider--labeled { display: flex; align-items: center; gap: 10px; color: var(--muted-2);
  font-size: 0.75rem; margin: 10px 0; }
.sdui-divider--labeled::before, .sdui-divider--labeled::after {
  content: ""; flex: 1; border-top: 1px solid var(--border); }

.sdui-empty { text-align: center; padding: 34px 16px; color: var(--muted); }
.sdui-empty-icon { font-size: 2rem; margin-bottom: 6px; }
.sdui-empty-title { font-weight: 600; color: var(--text-strong); margin-bottom: 4px; }
.sdui-empty-text { font-size: 0.83rem; margin-bottom: 12px; }

.sdui-kv { margin: 0; display: grid; gap: 6px; }
.sdui-kv-row { display: flex; gap: 12px; font-size: 0.85rem; }
.sdui-kv-row dt { color: var(--muted); min-width: 140px; }
.sdui-kv-row dd { margin: 0; color: var(--text); }

.sdui-tabs-header { display: flex; gap: 4px; border-bottom: 1px solid var(--border);
  margin-bottom: 14px; flex-wrap: wrap; }
.sdui-tab { padding: 8px 14px; border: none; background: none; cursor: pointer;
  color: var(--muted); font-size: 0.86rem; font-weight: 600; font-family: inherit;
  border-bottom: 2px solid transparent; }
.sdui-tab.is-active { color: var(--brand); border-bottom-color: var(--brand); }

.sdui-modal-overlay { position: fixed; inset: 0; z-index: 1000; background: var(--scrim);
  backdrop-filter: blur(2px); display: flex; align-items: center; justify-content: center; }
.sdui-modal { background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  width: min(480px, 92vw); max-height: 86vh; overflow: auto; box-shadow: var(--shadow-lg); }
.sdui-modal--lg { width: min(760px, 94vw); }
.sdui-modal-head { display: flex; justify-content: space-between; align-items: center;
  padding: 14px 18px; border-bottom: 1px solid var(--border); }
.sdui-modal-head h3 { margin: 0; font-size: 0.95rem; color: var(--text-strong); }
.sdui-modal-close { background: none; border: none; cursor: pointer; color: var(--muted); }
.sdui-modal-body { padding: 16px 18px; }
.sdui-modal-footer { padding: 12px 18px; border-top: 1px solid var(--border);
  display: flex; gap: 8px; justify-content: flex-end; }

.sdui-stat { background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  padding: 14px 16px; box-shadow: var(--shadow-sm); }
.sdui-stat-head { display: flex; gap: 6px; align-items: center; color: var(--muted);
  font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.03em; }
.sdui-stat-value { font-size: 1.5rem; font-weight: 700; color: var(--text-strong); margin: 4px 0 2px; }
.sdui-stat-sub { font-size: 0.76rem; color: var(--muted-2); }
.sdui-stat-sub--good { color: var(--badge-success-fg); }
.sdui-stat-sub--warn { color: var(--badge-warn-fg); }

.sdui-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; }
.sdui-btn:hover:not(:disabled) { background: var(--control-bg-hover); }
.sdui-btn:disabled { opacity: 0.45; cursor: not-allowed; }
.sdui-btn--primary { background: var(--brand); color: #fff; border-color: var(--brand); }
.sdui-btn--primary:hover:not(:disabled) { background: var(--brand-dark); }
.sdui-btn--danger { color: var(--badge-danger-fg); border-color: rgba(239,68,68,0.45); }
.sdui-btn--danger:hover:not(:disabled) { background: var(--badge-danger-bg); }
.sdui-btn--ghost { background: transparent; }

.sdui-field { display: flex; flex-direction: column; gap: 4px; }
.sdui-label { font-size: 0.76rem; color: var(--muted); font-weight: 600; }
.sdui-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); }
.sdui-input:focus { outline: 2px solid var(--brand); outline-offset: -1px; }

.sdui-toggle { display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  font-size: 0.84rem; color: var(--text); user-select: none; }
.sdui-toggle input { display: none; }
.sdui-toggle-track { width: 34px; height: 19px; border-radius: 999px; background: var(--control-border);
  position: relative; transition: background 0.15s; flex-shrink: 0; }
.sdui-toggle input:checked + .sdui-toggle-track { background: var(--brand); }
/* knob blanco fijo en ambos temas (excepción intencional, igual que los toggles del panel) */
.sdui-toggle-knob { position: absolute; top: 2px; left: 2px; width: 15px; height: 15px;
  border-radius: 50%; background: #fff; transition: left 0.15s; }
.sdui-toggle input:checked + .sdui-toggle-track .sdui-toggle-knob { left: 17px; }

.sdui-form { display: flex; flex-direction: column; gap: 10px; max-width: 480px; }

.sdui-table-wrap { background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
  overflow-x: auto; box-shadow: var(--shadow-sm); }
.sdui-table { width: 100%; border-collapse: collapse; font-size: 0.83rem; }
.sdui-table th { padding: 10px 14px; background: var(--surface-2); color: var(--muted);
  font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.03em; text-align: left; }
.sdui-table td { padding: 9px 14px; border-top: 1px solid var(--border); color: var(--text); }
.sdui-row--clickable { cursor: pointer; }
.sdui-row--clickable:hover td { background: var(--surface-2); }
.sdui-table-msg { text-align: center; color: var(--muted); padding: 24px !important; }
.sdui-table-msg--error { color: var(--badge-danger-fg); }
.sdui-mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 0.78rem; }
.sdui-nowrap { white-space: nowrap; }

.sdui-spinner-wrap { display: flex; gap: 10px; align-items: center; justify-content: center; padding: 14px; }
.sdui-spinner { border: 3px solid var(--border); border-top-color: var(--brand); border-radius: 50%;
  animation: sdui-spin 0.8s linear infinite; }
.sdui-spinner--sm { width: 14px; height: 14px; }
.sdui-spinner--md { width: 22px; height: 22px; }
.sdui-spinner--lg { width: 34px; height: 34px; }
.sdui-spinner-label { color: var(--muted); font-size: 0.83rem; }
@keyframes sdui-spin { to { transform: rotate(360deg); } }

.sdui-pagination { display: flex; gap: 12px; align-items: center; justify-content: center; }
.sdui-pagination-info { color: var(--muted); font-size: 0.83rem; }

.sdui-toast { position: fixed; bottom: 24px; right: 24px; z-index: 1100; padding: 12px 18px;
  border-radius: 10px; font-size: 0.86rem; font-weight: 600; box-shadow: var(--shadow-lg);
  background: var(--tooltip-bg); color: var(--tooltip-fg); }
.sdui-toast--success { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.sdui-toast--warning { background: var(--badge-warn-bg); color: var(--badge-warn-fg); }
.sdui-toast--danger  { background: var(--badge-danger-bg); color: var(--badge-danger-fg); }

.sdui-chart { width: 100%; }

/* ── SDUI · kanban (tablero por columnas con drag & drop) ── */
.sdui-kanban { width: 100%; }
.sdui-kanban-msg { text-align: center; color: var(--muted); padding: 24px; }
.sdui-kanban-msg--error { color: var(--badge-danger-fg); }
.sdui-kanban-cols { display: flex; gap: 14px; overflow-x: auto; padding-bottom: 8px;
  align-items: flex-start; }
.sdui-kanban-col { flex: 0 0 288px; width: 288px; background: var(--surface-2);
  border: 1px solid var(--border); border-radius: 12px; display: flex; flex-direction: column;
  max-height: 100%; }
.sdui-kanban-col-head { display: flex; align-items: center; justify-content: space-between;
  gap: 8px; padding: 10px 12px; border-top: 3px solid var(--brand);
  border-top-left-radius: 12px; border-top-right-radius: 12px; }
.sdui-kanban-col-label { font-weight: 700; font-size: 0.84rem; color: var(--text-strong);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sdui-kanban-col-count { flex: 0 0 auto; min-width: 20px; text-align: center; padding: 1px 7px;
  border-radius: 999px; font-size: 0.7rem; font-weight: 700; color: var(--muted);
  background: var(--control-bg); border: 1px solid var(--border-soft); }
.sdui-kanban-col-body { display: flex; flex-direction: column; gap: 8px; padding: 10px;
  overflow-y: auto; min-height: 48px; }
.sdui-kanban-col-body.sdui-kanban-dragover { background: var(--brand-soft-bg); }
.sdui-kanban-col-empty { text-align: center; color: var(--muted-2); font-size: 0.78rem;
  padding: 14px 6px; }
.sdui-kanban-card { background: var(--surface); border: 1px solid var(--border);
  border-radius: 10px; padding: 10px 12px; cursor: grab; box-shadow: var(--shadow-sm);
  display: flex; flex-direction: column; gap: 4px; }
.sdui-kanban-card:hover { border-color: var(--brand); }
.sdui-kanban-card:active { cursor: grabbing; }
.sdui-kanban-card[draggable="false"] { cursor: default; }
.sdui-kanban-card-title { font-weight: 600; font-size: 0.84rem; color: var(--text-strong); }
.sdui-kanban-card-sub { font-size: 0.78rem; color: var(--muted); }
.sdui-kanban-card-badges { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 2px; }
.sdui-kanban-card-meta { font-size: 0.72rem; color: var(--muted-2); margin-top: 2px; }

/* ── SDUI · calendar (calendario mensual de eventos) ── */
.sdui-cal { width: 100%; }
.sdui-cal-head { display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.sdui-cal-title { font-weight: 700; font-size: 0.95rem; color: var(--text-strong);
  min-width: 150px; }
.sdui-cal-nav { width: 30px; height: 30px; border-radius: 8px; border: 1px solid var(--border);
  background: var(--control-bg); color: var(--text); cursor: pointer; font-size: 1rem; }
.sdui-cal-nav:hover { background: var(--control-bg-hover); }
.sdui-cal-today { padding: 5px 12px; border-radius: 8px; border: 1px solid var(--border);
  background: var(--control-bg); color: var(--text); cursor: pointer; font-size: 0.8rem; }
.sdui-cal-today:hover { background: var(--control-bg-hover); }
.sdui-cal-loading, .sdui-cal-error { font-size: 0.78rem; color: var(--muted); }
.sdui-cal-error { color: var(--badge-danger-fg); }
.sdui-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.sdui-cal-dow { text-align: center; font-size: 0.7rem; text-transform: uppercase;
  letter-spacing: 0.03em; color: var(--muted); padding: 4px 0; font-weight: 600; }
.sdui-cal-cell { min-height: 92px; background: var(--surface); border: 1px solid var(--border);
  border-radius: 8px; padding: 4px; display: flex; flex-direction: column; gap: 3px; overflow: hidden; }
.sdui-cal-empty { background: transparent; border: 1px dashed var(--border-soft); }
.sdui-cal-today { }
.sdui-cal-cell.sdui-cal-today { border-color: var(--brand); box-shadow: inset 0 0 0 1px var(--brand); }
.sdui-cal-daynum { font-size: 0.72rem; font-weight: 700; color: var(--muted); text-align: right;
  padding: 0 2px; }
.sdui-cal-events { display: flex; flex-direction: column; gap: 2px; overflow-y: auto; }
.sdui-cal-ev { font-size: 0.68rem; padding: 2px 5px; border-radius: 5px; cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border-left: 3px solid transparent; }
.sdui-cal-ev--vencido { background: var(--badge-danger-bg); color: var(--badge-danger-fg);
  border-left-color: var(--badge-danger-fg); }
.sdui-cal-ev--hoy { background: var(--badge-warn-bg); color: var(--badge-warn-fg);
  border-left-color: var(--badge-warn-fg); }
.sdui-cal-ev--proximo { background: var(--badge-info-bg); color: var(--badge-info-fg);
  border-left-color: var(--badge-info-fg); }
.sdui-cal-ev--done { background: var(--surface-2); color: var(--muted-2);
  border-left-color: var(--border); text-decoration: line-through; }

/* ── E-commerce · integración producto↔recurso (modal 2 cards + tab crear/enlazar) ── */
.ec-integ-tab { display: flex; flex-direction: column; gap: 12px; }
.ec-seg { display: inline-flex; padding: 3px; border-radius: 10px; background: var(--surface-2); border: 1px solid var(--border-soft); width: fit-content; }
.ec-seg-btn { appearance: none; border: 0; background: transparent; color: var(--muted); cursor: pointer;
  padding: 7px 16px; border-radius: 8px; font-size: 0.85rem; font-weight: 600; transition: background .15s, color .15s; }
.ec-seg-btn.active { background: var(--surface-overlay); color: var(--text-strong); box-shadow: var(--shadow-sm); }
.ec-integ-field { display: flex; flex-direction: column; gap: 6px; }
.ec-integ-unlink { align-self: flex-start; }

/* Dropdown de recurso: buscable + paginado (mismo patrón que el selector de cliente) */
.ec-res-picker { position: relative; }
.ec-res-picker-btn { width: 100%; text-align: left; cursor: pointer; }
/* Capa invisible que captura los clics fuera del dropdown de recursos para cerrarlo.
   z-index bajo el drop (40) y sobre el resto del contenido del drawer. */
.ec-res-dismiss { position: fixed; inset: 0; z-index: 39; background: transparent; border: none; padding: 0; cursor: default; }
.ec-res-drop { position: absolute; z-index: 40; top: calc(100% + 4px); left: 0; right: 0;
  background: var(--surface-overlay); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: var(--shadow-lg); padding: 8px; }
.ec-res-search { width: 100%; margin-bottom: 6px; }
.ec-res-list { display: flex; flex-direction: column; max-height: 240px; overflow-y: auto; }
.ec-res-opt { appearance: none; border: 0; background: transparent; color: var(--text); cursor: pointer;
  text-align: left; padding: 8px 10px; border-radius: 8px; font-size: 0.88rem; }
.ec-res-opt:hover { background: var(--control-bg-hover); }
.ec-res-more { appearance: none; border: 0; background: transparent; color: var(--brand); cursor: pointer;
  padding: 8px 10px; font-size: 0.82rem; font-weight: 600; }

/* Modal de integración (pre-form): el dropdown de recurso debe ESCAPAR del modal (mismo criterio
   que el chooser: sin overflow que lo recorte; su único límite es la pantalla). El modal no se
   aplasta con poco contenido (min-height), y el segmented Crear/Enlazar va en pill redondo. */
.ec-integ-modal.pg-modal, .ec-integ-modal .pg-modal-body { overflow: visible; }
.ec-integ-modal.pg-modal { min-height: 320px; }
.ec-integ-modal .ec-seg { border-radius: 999px; }
.ec-integ-modal .ec-seg-btn { border-radius: 999px; }
/* El dropdown de recurso escapa hacia abajo → el modal se fija ARRIBA (no centrado) para dejarle
   toda la pantalla debajo, y la lista se limita al alto del viewport para no pasar del borde. */
.ec-integ-overlay { align-items: flex-start; }
.ec-integ-overlay .pg-modal { margin-top: 7vh; }
.ec-integ-modal .ec-res-list { max-height: min(240px, 42vh); }

/* Chips de día seleccionados (repetición de bloque L-V…) */
.mir-wd-chip.is-on { background: var(--brand-soft-bg); border-color: var(--brand); color: var(--brand-soft-fg); font-weight: 600; }

/* ── Popover tipo tooltip saliendo de una card (chooser) ──────────────────────── */
/* La celda envuelve la card y ancla el popover; la card llena la celda. */
.chooser-cell { position: relative; display: flex; }
.chooser-cell > .mir-chooser-card { width: 100%; }
.card-pop { position: absolute; z-index: 60; left: 50%; bottom: calc(100% + 12px); transform: translateX(-50%);
  min-width: 210px; background: var(--surface-overlay); border: 1px solid var(--border); border-radius: 12px;
  box-shadow: var(--shadow-lg); padding: 8px; display: flex; flex-direction: column; gap: 6px; }
.card-pop::after { content: ""; position: absolute; top: 100%; left: 50%; transform: translateX(-50%);
  border: 7px solid transparent; border-top-color: var(--surface-overlay); }
.card-pop-title { font-size: 0.76rem; color: var(--muted); padding: 2px 6px 4px; }
.card-pop-opt { appearance: none; border: 1px solid var(--control-border); background: var(--control-bg); color: var(--text);
  cursor: pointer; text-align: left; padding: 8px 10px; border-radius: 8px; font-size: 0.86rem; font-weight: 600; }
.card-pop-opt:hover { background: var(--control-bg-hover); border-color: var(--brand); }

/* Segmento de días — chips (reutilizado del bloque L-V) */
.mir-seg { display: inline-flex; padding: 3px; border-radius: 10px; background: var(--surface-2); border: 1px solid var(--border-soft); width: fit-content; margin-bottom: 8px; }
.mir-seg-btn { appearance: none; border: 0; background: transparent; color: var(--muted); cursor: pointer; padding: 7px 16px; border-radius: 8px; font-size: 0.85rem; font-weight: 600; }
.mir-seg-btn.is-on { background: var(--surface-overlay); color: var(--text-strong); box-shadow: var(--shadow-sm); }

/* El popover-tooltip del chooser debe poder salirse del cuerpo del modal (no recortar). */
.mir-chooser, .mir-chooser .pg-modal-body { overflow: visible; }

/* ── MIR: selector con buscador + paginado (recursos / bloques) ───────────────
   Un `<select>` nativo con miles de asientos es inusable y no se puede buscar.
   Mismo patrón que `ec-res-picker` (integración E-commerce) e `IdvSelect`. */
.mir-pick { position: relative; }
.mir-pick-field {
  width: 100%; display: flex; align-items: center; gap: 8px;
  text-align: left; cursor: pointer;
}
.mir-pick-value { flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mir-pick-value.is-empty { color: var(--muted); }
.mir-pick-caret { flex: 0 0 auto; color: var(--muted); font-size: 0.8rem; }
/* Capa a pantalla completa: cierra el desplegable al pulsar fuera. Va por debajo
   del propio desplegable, no de los tooltips. */
.mir-pick-dismiss { position: fixed; inset: 0; z-index: 199; background: transparent; border: none; padding: 0; cursor: default; }
/* `fixed` + Portal: el desplegable se monta fuera del modal y su posición la
   calcula `pick_drop_style_for` (left/top/width/max-height en el atributo
   style). Ningún contenedor con overflow puede recortarlo. */
.mir-pick-drop {
  position: fixed; z-index: 200;
  display: flex; flex-direction: column; min-height: 0;
  background: var(--surface-overlay); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: var(--shadow-lg); padding: 8px;
}
.mir-pick-search { width: 100%; margin-bottom: 6px; flex: 0 0 auto; }
.mir-pick-list {
  /* El alto lo manda el max-height del desplegable; la lista rellena lo que quede. */
  display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; overflow-y: auto;
  scrollbar-width: thin; scrollbar-color: transparent transparent;
}
.mir-pick-list:hover { scrollbar-color: var(--control-border) transparent; }
.mir-pick-list::-webkit-scrollbar { width: 8px; }
.mir-pick-list::-webkit-scrollbar-track { background: transparent; }
.mir-pick-list::-webkit-scrollbar-thumb {
  background: transparent; border: 2px solid transparent; background-clip: padding-box;
  border-radius: 8px; transition: background-color 0.2s ease;
}
.mir-pick-list:hover::-webkit-scrollbar-thumb { background: var(--control-border); background-clip: padding-box; }
.mir-pick-opt {
  appearance: none; border: 0; background: transparent; color: var(--text); cursor: pointer;
  text-align: left; padding: 7px 10px; border-radius: 8px;
  display: flex; flex-direction: column; gap: 1px;
}
.mir-pick-opt:hover { background: var(--control-bg-hover); }
.mir-pick-opt.is-active { background: var(--brand-soft-bg); color: var(--brand-soft-fg); }
.mir-pick-opt.is-disabled { opacity: 0.55; cursor: not-allowed; }
.mir-pick-opt.is-disabled:hover { background: transparent; }
.mir-pick-opt-main { display: flex; align-items: baseline; gap: 6px; }
.mir-pick-opt-label { font-size: 0.86rem; font-weight: 600; }
.mir-pick-opt-hint { font-size: 0.72rem; color: var(--muted); }
/* Rama de ancestros: sin ella, dos «Asiento A1» de salas distintas se leen igual. */
.mir-pick-opt-sub { font-size: 0.73rem; color: var(--muted); }
.mir-pick-more {
  appearance: none; border: 0; background: transparent; color: var(--brand); cursor: pointer;
  padding: 8px 10px; font-size: 0.8rem; font-weight: 600; text-align: center;
}
.mir-pick-more:hover { background: var(--control-bg-hover); border-radius: 8px; }
.mir-pick-empty { padding: 12px 10px; font-size: 0.8rem; color: var(--muted); text-align: center; }

/* ── MIR: velo de carga sobre el contenido de una tab ─────────────────────────
   El giro del icono de «Refrescar» dice que se está recargando; esto dice QUÉ.
   Se pinta aunque los datos vuelvan idénticos, con un suelo de visibilidad en
   el código (si no, una respuesta de 40 ms sería un parpadeo ilegible). */
.mir-loadwrap { position: relative; }
/* El velo hace TODO el trabajo (no se toca la opacidad de los hijos: dependía
   de que las filas fueran hijas directas y en el árbol de Recursos no se
   apagaban). Difumina y atenúa el fondo, bloquea el clic y deja un solo punto
   de atención: la píldora con el spinner. */
.mir-loadveil {
  position: absolute; inset: 0; z-index: 6;
  display: flex; align-items: flex-start; justify-content: center;
  padding-top: 52px;
  border-radius: inherit;
  background: var(--scrim);
  backdrop-filter: blur(3px) saturate(0.55);
  -webkit-backdrop-filter: blur(3px) saturate(0.55);
  pointer-events: auto; cursor: progress;
  animation: mir-veil-in 0.16s ease-out;
}
@keyframes mir-veil-in { from { opacity: 0; } to { opacity: 1; } }
.mir-loadcard {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 10px 16px; border-radius: 999px;
  background: var(--surface-overlay);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  color: var(--text-strong); font-size: 0.85rem; font-weight: 600;
}
.mir-spinner {
  width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid var(--control-border); border-top-color: var(--brand);
  animation: mir-spin 0.7s linear infinite;
}
@keyframes mir-spin { to { transform: rotate(360deg); } }

/* Tarjeta de reserva arrastrable desde el primer píxel (sin retardo de "armado"). */
.mir-kcard { cursor: grab; }
.mir-kcard:active { cursor: grabbing; }

/* ============================================================================
   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; }

/* ── 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/guias/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;                        /* pill moderno */
  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;
}

/* TEMA CLARO: los overrides `html.light-mode .<modulo>-tab.active` (0,3,1) le ganaban a
   la regla de arriba (0,2,0) y repintaban un fondo propio translúcido + texto de MARCA.
   Como el pill de detrás es un sólido de marca, quedaba texto de marca sobre fondo de
   marca = invisible (bug: tabs del centro de control y de tickets en claro). El pill es
   el único resaltado, así que sobre él el texto va blanco en AMBOS temas, igual que en
   oscuro. La clase se repite (.slide-tabs.slide-tabs) para mantener la especificidad
   en 0,4,1 y ganarle a esos overrides sin depender del orden del archivo.
   Ya no hay excepciones: camp-tabs tenía un pill claro propio y se unificó con el
   resto al estandarizar el segmented control. */
html.light-mode .slide-tabs.slide-tabs > .active,
html.light-mode .slide-tabs.slide-tabs > .is-active,
html.light-mode .slide-tabs.slide-tabs > [class*="--active"] {
  background: transparent !important;
  box-shadow: none !important;
  color: #fff !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, transform 0.15s, box-shadow 0.18s;
}
.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; }
}
/* El menú no se desmonta: `is-open` anima despliegue y colapso (140 ms). El cierre
   al pulsar fuera lo hace un listener de window, no un backdrop `fixed` — el header
   lleva `backdrop-filter` y eso vuelve al header containing block de sus hijos
   `fixed`, así que el backdrop solo cubría los 60px de la cabecera. */
.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;
  transform-origin: top right;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px) scale(0.97);
  pointer-events: none;
  transition: opacity 0.14s ease, transform 0.14s ease, visibility 0s linear 0.14s;
}
.ph-notif-menu.is-open {
  opacity: 1;
  visibility: visible;
  transform: none;
  pointer-events: auto;
  transition: opacity 0.14s ease, transform 0.14s 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;
}
/* Scrollbar estilo sidebar: fina, sin carril gris reservado y solo visible
   cuando el puntero está dentro del menú. */
.ph-notif-menu-list {
  max-height: 380px;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: transparent transparent;
}
.ph-notif-menu-list:hover { scrollbar-color: rgba(255, 255, 255, 0.20) transparent; }
.ph-notif-menu-list::-webkit-scrollbar { width: 8px; }
.ph-notif-menu-list::-webkit-scrollbar-track { background: transparent; }
.ph-notif-menu-list::-webkit-scrollbar-thumb {
  background: transparent;
  border: 2px solid transparent;               /* carril propio, no pisa el texto */
  background-clip: padding-box;
  border-radius: 8px;
  transition: background-color 0.2s ease;
}
.ph-notif-menu-list:hover::-webkit-scrollbar-thumb { background: rgba(255, 255, 255, 0.20); background-clip: padding-box; }
.ph-notif-menu-list:hover::-webkit-scrollbar-thumb:hover { background: rgba(255, 255, 255, 0.34); background-clip: padding-box; }
html.light-mode .ph-notif-menu-list:hover { scrollbar-color: rgba(0, 0, 0, 0.22) transparent; }
html.light-mode .ph-notif-menu-list:hover::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, 0.18); background-clip: padding-box; }
html.light-mode .ph-notif-menu-list:hover::-webkit-scrollbar-thumb:hover { background: rgba(0, 0, 0, 0.30); background-clip: padding-box; }
.ph-notif-empty { padding: 24px; text-align: center; color: var(--muted); font-size: 0.85rem; }
/* Fila = <button>: hay que anular el chrome del navegador (borde claro y fondo
   propio), si no se ve un contorno blanco por fila. */
.ph-notif-row {
  display: block;
  width: 100%;
  appearance: none;
  border: none;
  border-bottom: 1px solid var(--border-soft);
  background: transparent;
  color: inherit;
  font-family: inherit;
  text-align: left;
  cursor: pointer;
  padding: 10px 14px;
  transition: background 0.12s ease;
}
.ph-notif-row:last-child { border-bottom: none; }
.ph-notif-row:hover { background: var(--control-bg-hover); }
.ph-notif-row--unread { background: var(--brand-soft-bg); }
.ph-notif-row--unread:hover { background: var(--control-bg-hover); }

/* "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; }
.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: #1e2129; --skel-hi: #2a2e38; }
html.light-mode { --skel-base: #e0e4ec; --skel-hi: #f2f4f9; }

.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 / .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; }   /* alineadas a la izquierda */

.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); }
/* Hover de fila: el mismo del popover de la campana (marca dónde está el ratón). */
.notif-item { transition: background 0.12s ease; }
.notif-item:hover,
.notif-item--unread:hover { background: var(--control-bg-hover); }
.notif-item-btn { cursor: pointer; }
.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 y paginación usan los bloques canónicos: TOOLBAR ESTÁNDAR
   (.tickets-toolbar + .contacts-search-form + embudo) y PAGINACIÓN ESTÁNDAR
   (.pg-pager). Aquí solo queda el scroll de la tabla. */
.notif-table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.notif-table-scroll .notif-table { min-width: 520px; }

/* ── Responsive: pantallas pequeñas ── */
@media (max-width: 640px) {
  .notif-page { padding-left: 12px; padding-right: 12px; }
  .notif-main { padding: 14px 12px 24px; }
  .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 (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; }
.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); }

/* ============================================================
   Identidad Visual / Personalización de perfil — filas + dropdown
   con búsqueda + barra Guardar fija. Sin líneas separadoras.
   ============================================================ */
/* El panel es más ancho que la columna de 560px que tenía: la previa del banner
   vive aquí dentro y con una columna estrecha mentía sobre las proporciones
   reales (un tercio de 560 px no se parece a un tercio del ancho de la portada).
   Los controles siguen acotados aparte para que un select no se estire. */
.idv-panel {
  display: flex;
  flex-direction: column;
  gap: 22px;
  max-width: 920px;
  padding-bottom: 88px; /* deja aire para la barra fija de Guardar */
}

/* Ajustes agrupados por tipo, con el mismo contenedor que la config de
   e-commerce (`.ec-cfg-group`): son muchos y en una columna plana no se
   distinguía dónde acababa el color y empezaba el banner. */
.idv-group {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 18px 22px;
  display: flex;
  flex-direction: column;
  gap: 18px;
}

.idv-group-title {
  font-weight: 700;
  font-size: 0.92rem;
  color: var(--text-strong);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.idv-row { display: flex; flex-direction: column; gap: 8px; }
.idv-row-head { display: flex; align-items: center; gap: 6px; }
.idv-row-title { font-size: 0.9rem; font-weight: 600; color: var(--text-strong); }
/* Los controles no crecen con el panel: un desplegable de 900 px de ancho para
   elegir «Fábrica» es ilegible. Quien sí usa todo el ancho es la previa del
   banner, que está fuera de esta clase. */
.idv-row-control { max-width: 420px; display: flex; flex-direction: column; gap: 10px; }
/* Toggle pegado a la izquierda de su fila (sin texto al lado: lo explica el
   tooltip del título). */
.idv-row-switch { align-self: flex-start; justify-content: flex-start; }
/* Fila que rompe el ancho del panel: el editor de paleta necesita más aire que un
   select, si no los 6 campos quedan en una columna larguísima. */
.idv-row--stack { width: 100%; }

/* ============================================================
   Editor de paleta (.tep — theme editor palette)
   Compartido por Identidad Visual y Perfil → Apariencia.
   ============================================================ */

/* Conmutador «Tema predefinido» / «Personalizado». Son excluyentes (el custom
   REEMPLAZA al preset, no se apila), así que se pintan como un segmented control
   y no como dos casillas independientes. */
.tep-source {
  display: inline-flex;
  gap: 3px;
  padding: 5px;
  /* Pastilla completa, como el resto de segmented controls del panel. */
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  width: fit-content;
  /* Aire propio: pegaba con el título de la fila y con el select de abajo. */
  margin: 4px 0 6px;
}
.tep-source-btn {
  border: none;
  background: transparent;
  color: var(--muted);
  font-family: inherit;
  font-size: 0.82rem;
  font-weight: 600;
  padding: 8px 18px;
  border-radius: 999px;
  cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.tep-source-btn:hover:not(:disabled):not(.is-active) { color: var(--text-strong); }
.tep-source-btn.is-active { background: var(--brand-dark); color: #fff; }
.tep-source-btn:disabled { opacity: 0.55; cursor: not-allowed; }

.tep {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 18px;
  border-radius: 14px;
  background: var(--surface-2);
  border: 1px solid var(--border);
}

/* Aviso de «estás editando el modo X»: el editor solo toca un tema a la vez. */
.tep-mode {
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--brand-soft-fg);
  background: var(--brand-soft-bg);
  border: 1px solid rgba(var(--brand-rgb), 0.28);
  border-radius: 10px;
  padding: 10px 12px;
}

.tep-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 14px;
}

.tep-field { display: flex; flex-direction: column; gap: 6px; }
.tep-field-head { display: flex; flex-direction: column; gap: 1px; }
.tep-field-label { font-size: 0.82rem; font-weight: 600; color: var(--text-strong); }
.tep-field-hint { font-size: 0.72rem; color: var(--muted); }
.tep-field-control { display: flex; align-items: center; gap: 8px; }

/* El swatch nativo: se le quita el chrome del navegador para que sea un cuadro de
   color limpio. Los pseudo-elementos son específicos de cada motor. */
.tep-swatch {
  width: 40px;
  height: 34px;
  flex-shrink: 0;
  padding: 0;
  border: 1px solid var(--control-border);
  border-radius: 8px;
  background: none;
  cursor: pointer;
}
.tep-swatch::-webkit-color-swatch-wrapper { padding: 3px; }
.tep-swatch::-webkit-color-swatch { border: none; border-radius: 5px; }
.tep-swatch::-moz-color-swatch { border: none; border-radius: 5px; }
.tep-swatch:disabled { opacity: 0.5; cursor: not-allowed; }

.tep-hex {
  width: 100%;
  min-width: 0;
  padding: 8px 10px;
  border-radius: 8px;
  border: 1px solid var(--control-border);
  background: var(--control-bg);
  color: var(--text);
  font-family: 'Fira Code', 'Cascadia Code', ui-monospace, monospace;
  font-size: 0.8rem;
  text-transform: lowercase;
}
.tep-hex:focus { outline: none; border-color: var(--brand); }

.tep-auto {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 0.8rem;
  color: var(--muted);
  cursor: pointer;
  white-space: nowrap;
}

.tep-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding-top: 4px;
  border-top: 1px solid var(--border-soft);
}
.tep-count { font-size: 0.75rem; color: var(--muted-2); }
.tep-reset { font-size: 0.8rem; padding: 7px 14px; }
.idv-name-input {
  width: 100%;
  box-sizing: border-box;
  padding: 10px 14px;
  border-radius: 10px;
  border: 1px solid var(--control-border);
  background: var(--control-bg);
  color: var(--text);
  font-size: 0.875rem;
  font-family: inherit;
}
.idv-name-input:focus { outline: none; border-color: var(--brand); }
.idv-name-input:disabled { opacity: 0.55; cursor: not-allowed; }

/* ---- Banner de Inicio (Identidad Visual) ----
   La vista previa reutiliza `.home-banner` y `.hb-*` de la portada: si un día
   cambia una forma, cambia en los dos sitios a la vez. Aquí solo se acota la
   altura y se añade el marcador de encuadre. */
.hb-preview { margin-bottom: 4px; }

/* Solo con imagen: sin ella no hay nada que colocar. `touch-action: none` es lo
   que impide que el navegador se quede el gesto para hacer scroll en móvil. */
.hb-preview.is-draggable {
  cursor: grab;
  touch-action: none;
  user-select: none;
}

.hb-preview.is-draggable:active { cursor: grabbing; }

/* Saludo y buscador de muestra dentro de la previa. Usan las clases reales
   (`hb-slot`, `home-welcome-title`, `home-search`) para que la colocación sea
   la de verdad y no una aproximación dibujada aparte; lo único propio es que
   nada de esto recibe el ratón: encima está el gesto de encuadre de la imagen.
   El buscador es un `<span>`, no un `<input>`: un campo de texto dentro de un
   panel de ajustes invita a escribir en él. */
.hb-ghost, .hb-ghost * { pointer-events: none; }

.hb-ghost .home-search-input {
  display: block;
  color: inherit;
  opacity: 0.75;
}

.hb-focus {
  position: absolute;
  width: 18px;
  height: 18px;
  margin: -9px 0 0 -9px;
  border-radius: 50%;
  border: 2px solid #fff;
  box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.45), inset 0 0 0 2px rgba(0, 0, 0, 0.35);
  pointer-events: none;
}

.idv-field {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: 100%;
  max-width: 420px; /* mismo motivo que `.idv-row-control` */
  margin-top: 12px;
}

/* Los ajustes de sí/no del banner NO tienen variante en fila: el interruptor va
   debajo de su etiqueta como en el resto del panel. Ponerlo al lado dejaba una
   sola config leyéndose distinto de todas las demás. */

/* Botón de subida: se muestra solo cuando el fondo elegido es «Imagen propia». */
.idv-upload {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  padding: 8px 14px;
  border-radius: 999px;
  border: 1px dashed var(--control-border);
  background: var(--control-bg);
  color: var(--text);
  font-size: 0.8125rem;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}

.idv-upload:hover {
  background: var(--control-bg-hover);
  border-color: var(--brand);
}

.idv-field-label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  align-self: flex-start;
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.idv-hint {
  font-size: 0.75rem;
  color: var(--muted-2);
  margin: 0;
}

/* Campo de texto del saludo. Comparte medidas con `.idv-select` para que la
   columna de controles del panel quede pareja. */
.idv-input {
  width: 100%;
  padding: 8px 12px;
  border-radius: 8px;
  border: 1px solid var(--control-border);
  background: var(--control-bg);
  color: var(--text);
  font-family: inherit;
  font-size: 0.875rem;
  outline: none;
}

.idv-input:focus {
  border-color: var(--brand);
  background: var(--control-bg-hover);
}

.idv-input:disabled { opacity: 0.6; cursor: not-allowed; }

/* Comodines insertables. Se pintan como fichas y no como texto de ayuda porque
   además de documentar, SE PULSAN: escribirlos a mano es donde se cuelan las
   erratas que dejan un `{nombe}` literal en la portada. */
.idv-vars {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.idv-var {
  border: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--muted);
  border-radius: 999px;
  padding: 2px 10px;
  font-family: inherit;
  font-size: 0.72rem;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}

.idv-var:hover:not(:disabled) {
  background: var(--brand-soft-bg);
  color: var(--brand-soft-fg);
  border-color: var(--brand);
}

.idv-var:disabled { opacity: 0.5; cursor: not-allowed; }

/* Muestra del dibujo en el desplegable de fondo (campo cerrado y cada fila):
   el mismo `.hb-art--*` de la portada, en miniatura. «Aurora» o «Trama» no
   dicen nada hasta que se ven. Rectangular y no cuadrada porque en 22×22 una
   trama cabe en menos de un mosaico y todos los fondos se parecen. */
.idv-opt-swatch {
  width: 44px;
  height: 20px;
  border-radius: 5px;
  flex: none;
}

/* «Imagen propia» no tiene dibujo: se marca como hueco a rellenar. */
.hb-art--custom {
  background-color: var(--control-bg);
  background-image:
    repeating-linear-gradient(45deg,
      rgba(var(--brand-rgb), 0.28) 0 5px, transparent 5px 10px);
  box-shadow: inset 0 0 0 1px var(--control-border);
}

.idv-range {
  width: 100%;
  max-width: 320px;
  accent-color: var(--brand);
}

/* Selector de celda del banner: un mapa 3×3 en miniatura. Elegir «arriba a la
   derecha» en un desplegable obliga a traducir mentalmente; en el mapa se
   señala. La celda ocupada por el otro elemento va deshabilitada. */
/* Los dos selectores van UNO DEBAJO DEL OTRO, no en fila. En fila, el segundo
   se iba al extremo derecho del panel (la fila es ancha y las rejillas miden
   ~100 px), y dos controles idénticos separados por medio panel no se leen como
   pareja. Apilados comparten borde izquierdo con el resto de los campos. */
.idv-slotrow {
  display: flex;
  flex-direction: column;
  gap: 16px;
  width: 100%;
}

.idv-slots {
  display: grid;
  grid-template-columns: repeat(3, 30px);
  grid-template-rows: repeat(3, 22px);
  gap: 4px;
}

.idv-slot {
  border: 1px solid var(--control-border);
  border-radius: 5px;
  background: var(--control-bg);
  cursor: pointer;
  padding: 0;
  transition: background 0.15s, border-color 0.15s;
}

.idv-slot:hover:not(:disabled) {
  background: var(--control-bg-hover);
  border-color: var(--brand);
}

.idv-slot.is-active {
  background: var(--brand);
  border-color: var(--brand);
}

/* Ocupada por el otro elemento: se ve que existe pero no se puede elegir. */
.idv-slot:disabled {
  cursor: not-allowed;
  opacity: 0.4;
  border-style: dashed;
}

/* Dropdown con búsqueda (componente IdvSelect) */
.idv-select { position: relative; width: 100%; }
.idv-select-field {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 14px;
  border-radius: 10px;
  border: 1px solid var(--control-border);
  background: var(--control-bg);
  color: var(--text);
  font-size: 0.875rem;
  font-family: inherit;
  cursor: pointer;
  transition: border-color 0.15s, background 0.15s;
}
.idv-select-field:hover:not(:disabled) { background: var(--control-bg-hover); }
.idv-select-field:disabled { opacity: 0.55; cursor: not-allowed; }
.idv-select.is-open .idv-select-field { border-color: var(--brand); }
.idv-select-value { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.idv-select-caret { color: var(--muted); font-size: 0.7rem; flex-shrink: 0; }

.idv-select-backdrop { position: fixed; inset: 0; z-index: 60; }
.idv-select-panel {
  position: absolute;
  z-index: 61;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  background: var(--surface-overlay);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow-lg);
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.idv-select-search {
  width: 100%;
  box-sizing: border-box;
  padding: 8px 12px;
  border-radius: 8px;
  border: 1px solid var(--control-border);
  background: var(--control-bg);
  color: var(--text);
  font-size: 0.85rem;
  font-family: inherit;
}
.idv-select-search:focus { outline: 2px solid var(--brand); outline-offset: -1px; }
.idv-select-list {
  max-height: 240px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.idv-select-opt {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  text-align: left;
  padding: 8px 12px;
  border: 0;
  border-radius: 8px;
  background: transparent;
  color: var(--text);
  font-size: 0.85rem;
  font-family: inherit;
  cursor: pointer;
  transition: background 0.12s;
}
.idv-select-opt:hover { background: var(--control-bg-hover); }
.idv-select-opt.is-active {
  background: var(--brand-soft-bg);
  color: var(--brand-soft-fg);
  font-weight: 600;
}
.idv-opt-label { flex: 1; }
.idv-opt-sub { font-size: 0.75rem; color: var(--muted); }
.idv-select-opt.is-active .idv-opt-sub { color: var(--brand-soft-fg); }
.idv-select-empty { padding: 10px 12px; font-size: 0.8rem; color: var(--muted); text-align: center; }

/* Barra Guardar — fija en la esquina inferior derecha (siempre visible al hacer scroll) */
.idv-savebar {
  position: fixed;
  right: 32px;
  bottom: 24px;
  z-index: 90;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 8px 10px;
  background: var(--surface-overlay);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: var(--shadow-lg);
}
.idv-saved { font-size: 0.82rem; color: var(--badge-success-fg); font-weight: 600; }
.idv-save-btn { white-space: nowrap; }

/* ═══════════════════════════════════════════════════════════════════════════
   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 ─────────────────────────────────── */
.flx-sidebar {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 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); }
.flx-stage-actions { display: inline-flex; gap: 4px; flex: 0 0 auto; }
.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) ─────────────────────────────── */
.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; }

.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); }

/* 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; }
/* ── 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; }
/* Tabs DENTRO del panel izquierdo. Fuera del panel dejaban una franja vacía a lo ancho
   de la página, justo encima del mapa. Los avisos del módulo salen por el toast global
   (`.toast-host`), no por un banner aquí: el banner empujaba el lienzo y el mapa
   saltaba en cada guardado.

   El colapsar es una PESTAÑA en la costura entre el panel y el mapa. Dentro de la fila
   de tabs les quitaba el ancho justo que necesitan para caber las cuatro (y salía una
   barra de scroll horizontal); en una fila propia encima, se veía suelto. */
/* La pestaña cuelga de `.mapa-body` y se coloca con un `left` EXPLÍCITO, calculado desde
   el ancho del panel (330 px, o 62 px colapsado — los mismos números que usa el aside).
   Dos intentos anteriores la dejaron invisible: dentro del aside la recortaba su
   `overflow-y: auto` (que en CSS vuelve `auto` también el eje X), y en un envoltorio flex
   con `left: 100%` tampoco aparecía. Anclarla al contenedor que YA define las dos
   columnas quita de en medio los dos misterios. */
/* `left` = ancho EXACTO del panel: la pestaña arranca donde el panel termina y sale
   entera hacia el hueco. Antes empezaba 12 px antes y quedaba medio montada sobre la
   esquina del panel, que se leía como un botón encima y no como una pestaña. */
.mapa-collapse-tab { position: absolute; top: 18px; left: 330px; z-index: 20;
    width: 24px; height: 44px; display: flex; align-items: center; justify-content: center;
    padding: 0; cursor: pointer; color: var(--text);
    background: var(--surface-overlay); border: 1px solid var(--border); border-left: 0;
    border-radius: 0 10px 10px 0; box-shadow: 3px 0 8px rgba(0,0,0,0.22);
    transition: left .18s ease, color .15s ease, background .15s ease; }
.mapa-body--collapsed .mapa-collapse-tab { left: 62px; }
.mapa-collapse-tab:hover { color: var(--brand); background: var(--control-bg-hover); }
/* Las 4 pestañas se reparten el ancho del panel y no desbordan. La barra de scroll
   queda por si el idioma alarga las etiquetas, pero SIN ocupar sitio ni verse: reservada
   siempre, partía el segmented en dos y se leía como un control roto. */
.mapa-tabs { width: 100%; margin-bottom: 0; padding: 4px;
    scrollbar-width: none; -ms-overflow-style: none; }
.mapa-tabs::-webkit-scrollbar { width: 0; height: 0; display: none; }
.mapa-tabs .mir-tab { flex: 1 1 0; min-width: 0; padding-left: 6px; padding-right: 6px;
    text-align: center; white-space: nowrap; }
/* El buscador ocupa su fila entero. Cuando la pestaña no tiene nada que buscar la fila
   no se pinta y el contenido sube: un hueco donde debería haber un buscador se lee como
   que algo no cargó. */
.mapa-search-row .contacts-search-input { flex: 1 1 auto; min-width: 0; }

/* Altura FIJA basada en viewport → el mapa no crece con la lista; ambas columnas
   tienen scroll interno propio. Se descuenta solo la cabecera de la página: la fila
   de tabs y la de avisos ya no están fuera del panel (antes eran 60 px más). No se
   usa `flex:1` porque `.mapa-page` hereda `height:100%` de un padre sin altura
   definida, y entonces el lienzo colapsaría a 0. */
/* `position: relative` para que la pestaña de colapsar se ancle AQUÍ: este es el
   contenedor que define las dos columnas, así que sus coordenadas son las únicas fiables
   para colocarla en la costura. */
/* El `gap` es la COSTURA donde vive la pestaña de colapsar: con los 14 px de antes no
   cabía (mide 24) y quedaba pisando el borde del mapa, medio escondida. */
.mapa-body { display: flex; gap: 32px; height: calc(100dvh - 150px); min-height: 460px;
    position: relative; }
.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; }
/* SIN `text-transform: uppercase`: el nombre del estado se muestra tal como lo escribió
   quien creó la sede. Forzar mayúsculas convertía "Distrito Capital" en un grito y, peor,
   hacía indistinguibles dos grafías distintas del mismo sitio en la lista. */
.mapa-office-estado { font-size: 0.8rem; font-weight: 700; color: var(--text-strong);
    letter-spacing: 0.2px; 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; }
/* La fila es ahora un contenedor en columna: arriba el grueso (nombre + flags) como
   botón que selecciona la sede, más el "⋮"; debajo, en flujo, su desplegable de
   opciones. En flujo —no flotante— nunca lo recorta el scroll del panel. */
.mapa-office-row { display: flex; flex-direction: column; width: 100%;
    border-radius: 8px; border: 1px solid transparent; }
.mapa-office-row:hover, .mapa-office-row.is-open { background: var(--control-bg-hover); border-color: var(--border-soft); }
.mapa-office-row-top { display: flex; align-items: center; gap: 4px; }
.mapa-office-main { flex: 1; min-width: 0; display: flex; align-items: center; justify-content: space-between; gap: 8px;
    padding: 7px 4px 7px 10px; background: transparent; border: none; color: var(--text);
    cursor: pointer; text-align: left; font-size: 0.86rem; }
.mapa-office-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mapa-office-flags { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }

/* Botón "⋮" y su desplegable de opciones (accordion en flujo). */
.mapa-office-menu-btn { flex-shrink: 0; width: 26px; height: 26px; margin-right: 4px; border-radius: 6px;
    border: 1px solid transparent; background: transparent; color: var(--muted); cursor: pointer;
    font-size: 1rem; line-height: 1; display: flex; align-items: center; justify-content: center; }
.mapa-office-menu-btn:hover, .mapa-office-row.is-open .mapa-office-menu-btn {
    background: var(--control-bg); border-color: var(--control-border); color: var(--text); }
.mapa-office-menu { display: flex; flex-direction: column; gap: 2px; margin: 0 6px 6px; padding: 4px;
    border-radius: 8px; background: var(--surface-2); border: 1px solid var(--border-soft); }
.mapa-office-menu-item { display: block; width: 100%; text-align: left; padding: 8px 10px; border-radius: 6px;
    background: transparent; border: none; color: var(--text); cursor: pointer; font-size: 0.82rem;
    text-decoration: none; }
.mapa-office-menu-item:hover { background: var(--control-bg-hover); }
.mapa-office-menu-item[disabled] { opacity: 0.6; cursor: default; }
.mapa-office-menu-empty { padding: 8px 10px; font-size: 0.78rem; color: var(--muted); }

/* Modal del QR de una sede: QR centrado sobre fondo blanco fijo (ambos temas). */
.mapa-qr-modal { max-width: 340px; }
.mapa-qr-modal-body { display: flex; flex-direction: column; align-items: center; gap: 10px; text-align: center; }
.mapa-qr-modal-body .mapa-qr-img { width: 240px; max-width: 100%; }
.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-badge--ok { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.mapa-pin--miss { color: var(--badge-warn-fg); }

/* ── Zonas de cobertura y probador de ubicación ─────────────────────────────── */
/* El punto de color es la única forma de reconocer una zona en la lista sin abrirla:
   el mismo color con el que se pinta su polígono en el mapa. */
.mapa-zone-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0;
    border: 1px solid var(--border); }
.mapa-zone-vertices { color: var(--muted); font-size: 0.7rem; }
.mapa-check { display: flex; align-items: center; gap: 7px; margin-top: 10px;
    font-size: 0.82rem; color: var(--text); cursor: pointer; }
.mapa-draw-status { display: flex; align-items: center; justify-content: space-between; gap: 8px;
    margin-top: 10px; padding: 7px 10px; border-radius: 8px; font-size: 0.78rem;
    background: var(--brand-soft-bg); color: var(--brand-soft-fg); }
.mapa-probe-result { margin-top: 10px; padding: 10px; border-radius: 10px;
    background: var(--surface-2); border: 1px solid var(--border-soft);
    display: flex; flex-direction: column; gap: 6px; }
.mapa-probe-row { display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
    font-size: 0.8rem; }
.mapa-probe-row span { color: var(--muted); }
.mapa-probe-row b { text-align: right; }
.mapa-hint { margin: 2px 0 0; font-size: 0.74rem; color: var(--muted); line-height: 1.45; }
/* Asa invisible de arrastre sobre cada vértice: el círculo visible es un
   circleMarker (que no arrastra), así que el marker de encima solo aporta el área
   de agarre. Sin cursor propio no se adivina que se puede mover. */
.mapa-vertex-handle { cursor: grab; }
.mapa-vertex-handle:active { cursor: grabbing; }

/* ── Panel izquierdo: cabecera + toolbar + colapso ──────────────────────────── */
/* Mismo cromo que el panel de Flujos de Trabajo (`.flx-sidebar-head`, `.flx-btn-new`,
   `.lc-topbar`): son las mismas piezas, así que se reutilizan sus clases y aquí solo
   va lo propio de este módulo. */
.mapa-head-actions { display: flex; align-items: center; gap: 6px; }
/* El aside ya separa sus hijos con `gap: 14px`; el margen propio de la cabecera se
   sumaba y abría un hueco doble entre el título y el buscador. */
.mapa-controls .flx-sidebar-head { margin-bottom: 0; }
/* El popover de filtros se ancla al panel, no a la página. */
.mapa-controls { position: relative; }
.mapa-controls .lc-topbar { margin: 0; padding: 0; border-bottom: 0; }
.mapa-controls .lc-filters-popover { top: 92px; }
/* Zona scrolleable: la cabecera y la toolbar se quedan fijas arriba. */
.mapa-panel-body { flex: 1 1 auto; min-height: 0; overflow-y: auto;
    display: flex; flex-direction: column; gap: 14px;
    scrollbar-width: thin; scrollbar-color: transparent transparent; }
.mapa-panel-body:hover { scrollbar-color: var(--control-border) transparent; }
.mapa-panel-body::-webkit-scrollbar { width: 6px; }
.mapa-panel-body::-webkit-scrollbar-thumb { background: transparent; border-radius: 6px; }
.mapa-panel-body:hover::-webkit-scrollbar-thumb { background: var(--control-border); }
/* Colapso: el panel se reduce a un riel y el mapa se queda con el ancho. La
   transición va sobre el ancho del aside (el body es flex, no grid como Flujos). */
.mapa-controls { transition: width .18s ease, padding .18s ease; }
.mapa-controls--collapsed { width: 62px; padding: 10px 8px; overflow: hidden; }

/* ── Controles sobre el propio mapa ─────────────────────────────────────────── */
/* z-index 500: por encima de los panes de Leaflet (≤400) y por debajo de sus
   popups (700). */
.mapa-style-picker { position: absolute; top: 12px; right: 12px; z-index: 500; }
.mapa-style-picker .mapa-select { min-width: 150px; background: var(--surface-overlay);
    box-shadow: var(--shadow-md); }
/* Barra de dibujo: mientras se traza una zona el formulario está escondido, así que
   sus controles tienen que estar aquí, sobre el mapa. */
.mapa-draw-bar { position: absolute; left: 50%; bottom: 14px; transform: translateX(-50%);
    z-index: 500; display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    max-width: calc(100% - 24px); padding: 8px 12px; border-radius: 12px;
    background: var(--surface-overlay); border: 1px solid var(--border);
    box-shadow: var(--shadow-lg); }
.mapa-draw-count { font-weight: 700; font-size: 0.82rem; color: var(--text-strong); }
.mapa-draw-bar .mapa-hint { margin: 0; }
.mapa-btn--sm { padding: 5px 10px; font-size: 0.78rem; }
.mapa-place-hint .mapa-btn--sm { background: rgba(255,255,255,0.18); border-color: rgba(255,255,255,0.5);
    color: #fff; margin-left: 10px; }

/* ── Modales de sede y zona ─────────────────────────────────────────────────── */
.mapa-modal { width: min(560px, 94vw); }
.mapa-modal-body { display: flex; flex-direction: column; padding: 0 22px; }
.mapa-modal-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* Empuja las acciones normales a la derecha y deja "Eliminar" solo a la izquierda:
   el botón destructivo no debe quedar pegado a "Guardar". */
.mapa-modal-spacer { flex: 1 1 auto; }

/* ── Combo de Estado/Región ─────────────────────────────────────────────────── */
/* No es un <select>: hay que poder escribir uno nuevo Y elegir uno ya usado. El
   desplegable lista los existentes con su propio buscador y paginado, que es lo que
   evita acabar con "Carabobo", "carabobo" y "Edo. Carabobo" como tres grupos. */
.mapa-combo { position: relative; }
/* Backdrop propio para cerrar al pulsar fuera. Vive DENTRO de `.modal-card`, que ya
   frena la propagación del clic, así que cerrarlo no cierra el modal.
   El input se sube POR ENCIMA del backdrop (`z-index` mayor): si no, el backdrop se come
   los clics del campo y se puede abrir el desplegable pero no seguir escribiendo. */
.mapa-combo-backdrop { position: fixed; inset: 0; z-index: 10; }
.mapa-combo.is-open .mapa-input { position: relative; z-index: 11; }
.mapa-combo-pop { position: absolute; top: 38px; left: 0; right: 0; z-index: 12;
    background: var(--surface-overlay); border: 1px solid var(--border); border-radius: 10px;
    box-shadow: var(--shadow-lg); padding: 8px; }
.mapa-combo-list { display: flex; flex-direction: column; gap: 2px; }
.mapa-combo-item { text-align: left; width: 100%; padding: 6px 8px; border-radius: 7px;
    border: 1px solid transparent; background: transparent; color: var(--text);
    font-size: 0.85rem; cursor: pointer; }
.mapa-combo-item:hover { background: var(--control-bg-hover); border-color: var(--border-soft); }
.mapa-combo-pager { display: flex; align-items: center; justify-content: center; gap: 10px;
    margin-top: 6px; font-size: 0.76rem; color: var(--muted); }

/* ── Selector de CÓMO se indica la ubicación ────────────────────────────────── */
/* Se pregunta la forma antes de enseñar campos: las tres maneras de decir lo mismo
   puestas a la vez es lo que hacía tedioso dar de alta una sede. Arranca sin nada
   seleccionado a propósito. */
/* Usa el segmented ESTÁNDAR (`.mir-tabs`/`.mir-tab`, bloque canónico de arriba); aquí
   solo se le dice que ocupe el ancho y reparta los tres botones. Antes era una copia con
   sus propios tamaños y colores, justo lo que ese bloque existe para evitar. */
.mapa-seg { width: 100%; margin-bottom: 8px; padding: 4px;
    scrollbar-width: none; -ms-overflow-style: none; }
.mapa-seg::-webkit-scrollbar { width: 0; height: 0; display: none; }
.mapa-seg .mir-tab { flex: 1 1 0; min-width: 0; padding-left: 6px; padding-right: 6px;
    text-align: center; white-space: nowrap; }
.mapa-coord-pick, .mapa-link-pick { display: flex; flex-direction: column; gap: 8px; margin-bottom: 8px; }
.mapa-coord-pick { flex-direction: row; align-items: center; }
.mapa-coord-echo { font-size: 0.8rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.mapa-link-pick .mapa-input { margin-bottom: 0; }
.mapa-link-pick .mapa-hint { margin: 0; }

/* ── Área de la zona: campo obligatorio, no acción suelta ───────────────────── */
/* Sin área el backend rechaza la zona. El aviso es un punto rojo junto a la etiqueta y
   el borde de los botones — nada más. Un párrafo explicando lo que ya dice el color es
   texto que nadie lee, y encima aleja el control de su etiqueta. */
.mapa-label--req { display: flex; align-items: center; gap: 6px; margin-top: 12px; }
.mapa-req-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--badge-danger-fg); }
.mapa-area-ok { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.mapa-area-pts { font-size: 0.8rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.mapa-area-actions { display: flex; gap: 8px; flex-wrap: wrap; }
/* Botón de un campo obligatorio todavía vacío: se distingue del resto sin ser un
   botón destructivo (que es lo que significa el rojo sólido en este panel). */
.mapa-btn--need { border-color: var(--badge-danger-fg); color: var(--badge-danger-fg); }
.mapa-btn--need:hover { background: var(--badge-danger-bg); }

/* ── Importar límite administrativo (OpenStreetMap) ─────────────────────────── */
/* Estado vacío: icono y una línea, centrado en el hueco de la lista. La lista vacía no
   es el sitio para explicar el módulo — quien llega ahí solo necesita ver que no hay
   nada, no leerse un párrafo. */
.mapa-empty { flex: 1 1 auto; min-height: 160px; display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 10px; color: var(--muted-2); }
.mapa-empty svg { opacity: .55; }
.mapa-empty span { font-size: 0.82rem; }
/* La lista tiene que ocupar el alto disponible o el vacío no queda centrado en nada.
   (La regla base con `gap` está más arriba; aquí solo se le añade el crecimiento.) */
.mapa-office-list { flex: 1 1 auto; min-height: 0; }

.mapa-import { margin-top: 10px; padding: 10px; border-radius: 10px;
    background: var(--surface-2); border: 1px solid var(--border-soft);
    display: flex; flex-direction: column; gap: 8px; }
.mapa-import .mapa-hint { margin: 0; }
.mapa-import-row { display: flex; gap: 8px; align-items: center; }
.mapa-import-row .mapa-input { margin-bottom: 0; flex: 1 1 auto; min-width: 0; }
.mapa-import-hit { display: flex; flex-direction: column; gap: 2px; text-align: left; width: 100%;
    padding: 7px 9px; border-radius: 8px; border: 1px solid var(--border-soft);
    background: var(--control-bg); color: var(--text); cursor: pointer; }
.mapa-import-hit:hover { background: var(--control-bg-hover); }
.mapa-import-name { font-size: 0.82rem; line-height: 1.35; }
.mapa-import-kind { font-size: 0.7rem; color: var(--muted); text-transform: capitalize; }

/* ── Contenido de la burbuja de Leaflet ─────────────────────────────────────── */
/* La ficha de una sede/zona es LA BURBUJA ANCLADA, no una tarjeta en una esquina: va
   pegada al punto y se mueve con el mapa. Llegó a haber las dos a la vez —la del bridge
   y una propia— mostrando lo mismo dos veces. */
/* Los tokens de `.leaflet-popup-*` de más abajo NO se aplicaban: en index.html el
   `style.css` se enlaza ANTES que el CSS de Leaflet, así que a igual especificidad
   ganaba el de Leaflet y la burbuja salía blanca sobre el panel oscuro. Se recupera
   añadiendo el contenedor del mapa al selector (0,2,0 contra 0,1,0). */
.mapa-canvas .leaflet-popup-content-wrapper,
.mapa-canvas .leaflet-popup-tip { background: var(--surface-overlay); color: var(--text);
    box-shadow: var(--shadow-lg); }
.mapa-canvas .leaflet-popup-content { color: var(--text); margin: 12px 14px; }
.mapa-canvas .leaflet-popup-content strong { color: var(--text-strong); }
.mapa-canvas .leaflet-popup-content small { color: var(--muted); }

/* La ✕ es NUESTRA y la de Leaflet se oculta: Leaflet la coloca absoluta en la esquina
   del wrapper, fuera de nuestro marcado, así que poner el ⋮ "a su lado" era adivinar su
   tamaño y su margen — y las dos veces acabaron encimados. En la misma barra flex, la
   geometría la decide un solo contenedor. */
.mapa-canvas .leaflet-popup-close-button { display: none; }
.mapa-pop { position: relative; min-width: 200px; padding-right: 52px; }
.mapa-pop-tools { position: absolute; top: -3px; right: -4px;
    display: flex; align-items: center; gap: 2px; }
.mapa-pop-menu-btn, .mapa-pop-close-btn { width: 24px; height: 24px; flex: none;
    display: flex; align-items: center; justify-content: center;
    padding: 0; border: 0; border-radius: 6px; background: transparent;
    color: var(--muted); cursor: pointer; line-height: 1; }
.mapa-pop-menu-btn { font-size: 1.05rem; }
.mapa-pop-close-btn { font-size: 0.8rem; }
.mapa-pop-menu-btn:hover, .mapa-pop-close-btn:hover {
    background: var(--control-bg-hover); color: var(--text-strong); }
/* El menú nace oculto y lo abre el bridge con `.is-open`: dentro de un popup de Leaflet
   el DOM se recrea en cada apertura, así que su estado no puede vivir en Leptos. */
.mapa-pop-menu { display: none; position: absolute; top: 26px; right: 0; z-index: 3;
    min-width: 128px; flex-direction: column; padding: 4px; border-radius: 9px;
    background: var(--surface-overlay); border: 1px solid var(--border); box-shadow: var(--shadow-lg); }
.mapa-pop-menu.is-open { display: flex; }
.mapa-pop-menu button { text-align: left; padding: 7px 9px; border: 0; border-radius: 6px;
    background: transparent; color: var(--text); font-size: 0.83rem; cursor: pointer; }
.mapa-pop-menu button:hover { background: var(--control-bg-hover); }
.mapa-pop-menu button.is-danger { color: var(--badge-danger-fg); }
.mapa-pop a { color: var(--brand-dark); }

/* Centrar en mi ubicación: misma columna que el selector de estilo, justo debajo. */
.mapa-me-btn { position: absolute; top: 56px; right: 12px; z-index: 500;
    width: 34px; height: 34px; display: flex; align-items: center; justify-content: center;
    padding: 0; cursor: pointer; color: var(--text);
    background: var(--surface-overlay); border: 1px solid var(--border);
    border-radius: 9px; box-shadow: var(--shadow-md); }
.mapa-me-btn:hover { color: var(--brand); }

/* ── Probador de ubicación: control del mapa, no pestaña ────────────────────── */
/* Ocupaba una de las cuatro pestañas del panel izquierdo, y para consultar un punto había
   que abandonar la lista de sedes o zonas. Probar una ubicación es mirar el mapa, así que
   vive sobre el mapa: mismo cromo y misma columna que "mi ubicación", justo debajo. */
.mapa-probe-btn { position: absolute; top: 98px; right: 12px; z-index: 500;
    width: 34px; height: 34px; display: flex; align-items: center; justify-content: center;
    padding: 0; cursor: pointer; color: var(--text);
    background: var(--surface-overlay); border: 1px solid var(--border);
    border-radius: 9px; box-shadow: var(--shadow-md); }
.mapa-probe-btn:hover { color: var(--brand); }
.mapa-probe-btn.is-active { color: var(--brand); border-color: var(--brand); }
/* Anclado al botón que lo abre, hacia la izquierda: a la derecha no cabe (está pegado al
   borde) y hacia abajo taparía justo la parte del mapa que se está consultando.
   `max-height` + scroll propio porque el resultado crece con la sede más cercana y su
   enlace, y sin tope se sale del lienzo en pantallas bajas. */
.mapa-probe-pop { position: absolute; top: 98px; right: 54px; z-index: 501;
    width: min(320px, calc(100% - 70px)); max-height: calc(100% - 120px); overflow-y: auto;
    display: flex; flex-direction: column;
    padding: 12px; border-radius: 12px;
    background: var(--surface-overlay); border: 1px solid var(--border);
    box-shadow: var(--shadow-lg); }
.mapa-probe-head { display: flex; align-items: center; justify-content: space-between;
    gap: 10px; margin-bottom: 10px; }
.mapa-probe-head span { font-size: 0.82rem; font-weight: 700; color: var(--text-strong); }
.mapa-probe-close { padding: 0 4px; background: transparent; border: 0; cursor: pointer;
    color: var(--muted); font-size: 0.9rem; line-height: 1; }
.mapa-probe-close:hover { color: var(--text-strong); }

.mapa-confirm { width: min(420px, 94vw); }
.mapa-confirm-text { margin: 0; font-size: 0.88rem; line-height: 1.5; color: var(--text); }

/* Enlace de Maps del probador: es EL MISMO que recibe el agente, y verlo aquí es la
   forma de comprobar que apunta donde debe antes de que llegue a un cliente. */
.mapa-probe-link { display: inline-block; margin-top: 6px; font-size: 0.8rem;
    color: var(--brand); text-decoration: underline; }

/* Enlace + botón "Generar QR" en la misma fila del resultado del probador. */
.mapa-probe-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 6px; }
.mapa-probe-actions .mapa-probe-link { margin-top: 0; }

/* Caja del QR generado. Fondo blanco fijo (el QR se dibuja sobre blanco en ambos
   temas); centrado y acotado para no romper el ancho del popover del probador. */
.mapa-qr-box { margin-top: 10px; padding: 10px; border-radius: 10px;
    border: 1px solid var(--border); background: var(--surface-2);
    display: flex; flex-direction: column; align-items: center; gap: 8px; }
.mapa-qr-img { width: 180px; max-width: 100%; height: auto; display: block;
    background: #fff; border-radius: 8px; padding: 6px; }
.mapa-qr-actions { display: flex; gap: 8px; flex-wrap: wrap; justify-content: center; }
.mapa-qr-box .mapa-hint { text-align: center; }

/* 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; }
    /* Apilado, el panel ocupa todo el ancho: la pestaña caería en mitad de la lista y
       colapsar no aporta nada (no hay columna que ensanchar). */
    .mapa-collapse-tab { display: none; }
    .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) */
  padding: 18px 22px 14px;                     /* #11c: que el contenido no toque los bordes */
}
.model-picker-loading { font-size: 0.85rem; color: var(--muted); align-self: center; }

/* Toolbar canónica del catálogo de modelos: búsqueda redonda + embudo (filtros
   empaquetados en popover) + limpiar. Mismo patrón que Contactos/Auditoría. */
.model-picker-toolbar {
  position: relative;
  display: flex; flex-wrap: wrap; gap: 10px; align-items: center;
  justify-content: flex-start; margin-bottom: 12px;
}
/* Mismo ancho que en Contactos (pastilla 520px + iconos pegados): sin esto la
   forma crecía a todo el ancho y separaba los iconos del buscador (hueco raro). */
.model-picker-toolbar .contacts-search-form { flex: 0 1 520px; max-width: 520px; width: 100%; position: static; }
/* El popover del embudo se ancla a la toolbar (position:relative de arriba). */
.model-picker-fpop { min-width: 260px; }
.model-picker-fpop .contacts-fpop-section { display: flex; flex-direction: column; gap: 6px; }
.model-picker-fpop-ctrl {
  width: 100%; box-sizing: border-box; padding: 8px 12px; border-radius: 8px;
  border: 1px solid var(--control-border); background: var(--control-bg);
  color: var(--text); font-size: 0.88rem;
}

.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: 2;
  /* OPACO (no --surface-2, que es translúcido): si no, las filas se ven a través del
     header sticky y parece que se solapan (bug del catálogo, #8). */
  background: var(--surface-overlay);
  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 thead th.model-picker-action-col,
.model-picker-table td.model-picker-action { text-align: center; white-space: nowrap; }
.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; }

/* ═══════════════════════════════════════════════════════════════════════════
   Centro de Comunicaciones — asistente de líneas
   Solo tokens semánticos (tema claro/oscuro). El modal flota → --surface-overlay.
   ═══════════════════════════════════════════════════════════════════════════ */

.comms-page { padding: 0 4px; }

.comms-alert {
  padding: 12px 16px; border-radius: 10px; margin: 12px 0;
  font-size: 0.9rem; border: 1px solid var(--border);
}
.comms-alert--error { background: var(--badge-danger-bg); color: var(--badge-danger-fg); border-color: transparent; }
.comms-alert--info  { background: var(--badge-info-bg);   color: var(--badge-info-fg);   border-color: transparent; }

.comms-toolbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 16px; margin: 16px 0 20px; flex-wrap: wrap;
}
.comms-h2 { margin: 0; font-size: 1.15rem; color: var(--text-strong); }
.comms-sub { margin: 4px 0 0; font-size: 0.85rem; color: var(--muted); }
.comms-hint { margin: 6px 0 0; font-size: 0.78rem; color: var(--muted-2); line-height: 1.45; }

.comms-empty {
  text-align: center; padding: 48px 24px; color: var(--muted);
  background: var(--surface-2); border-radius: 14px; border: 1px dashed var(--border);
}
.comms-empty__icon { font-size: 2.4rem; margin-bottom: 8px; }

/* ── Lista de líneas ── */
.comms-lines { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px; }
.comms-line-card {
  display: flex; align-items: center; gap: 14px; padding: 16px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 12px;
}
.comms-line-card__main { flex: 1; min-width: 0; }
.comms-line-card__side { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; }
.comms-line-phone { font-weight: 700; font-size: 1.05rem; color: var(--text-strong); }
.comms-line-name { font-size: 0.85rem; color: var(--muted); margin-top: 2px; }
.comms-line-stage { font-size: 0.75rem; color: var(--muted-2); }

/* ── Badges que faltaban (solo tokens) ── */
.badge-success { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.badge-warn    { background: var(--badge-warn-bg);    color: var(--badge-warn-fg); }
.badge-info    { background: var(--badge-info-bg);    color: var(--badge-info-fg); }
.badge-neutral { background: var(--badge-neutral-bg); color: var(--badge-neutral-fg); }

/* ── Botón fantasma / select (faltaban) ── */
.btn-ghost {
  background: transparent; color: var(--muted); border: 1px solid var(--border);
  border-radius: 8px; padding: 6px 12px; cursor: pointer; font-size: 0.85rem;
}
.btn-ghost:hover:not(:disabled) { background: var(--control-bg-hover); color: var(--text); }
.form-select {
  width: 100%; padding: 10px 12px; border-radius: 8px;
  background: var(--control-bg); color: var(--text); border: 1px solid var(--control-border);
  font-size: 0.9rem;
}
.form-select:focus { outline: none; border-color: var(--brand); }

/* ── Modal del asistente (flota → --surface-overlay) ── */
.comms-modal-backdrop {
  position: fixed; inset: 0; background: var(--scrim);
  display: flex; align-items: center; justify-content: center; z-index: 1000; padding: 20px;
}
.comms-modal {
  background: var(--surface-overlay); border: 1px solid var(--border);
  border-radius: 16px; width: 100%; max-width: 560px; max-height: 90vh;
  overflow-y: auto; box-shadow: var(--shadow-lg);
}
.comms-modal__head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 22px; border-bottom: 1px solid var(--border);
}
.comms-modal__head h3 { margin: 0; font-size: 1.05rem; color: var(--text-strong); }
.comms-modal__close {
  background: none; border: none; font-size: 1.2rem; color: var(--muted);
  cursor: pointer; padding: 4px 8px; border-radius: 6px;
}
.comms-modal__close:hover { background: var(--control-bg-hover); color: var(--text); }
.comms-modal__body { padding: 24px 22px; }

/* ── Pasos ── */
.comms-step { text-align: center; }
.comms-step__num {
  width: 34px; height: 34px; border-radius: 50%; margin: 0 auto 12px;
  background: var(--brand-soft-bg); color: var(--brand-soft-fg);
  display: flex; align-items: center; justify-content: center; font-weight: 700;
}
.comms-step h4 { margin: 0 0 6px; color: var(--text-strong); font-size: 1.05rem; }
.comms-field { text-align: left; margin: 18px 0; }
.comms-field--muted { padding: 14px; background: var(--surface-2); border-radius: 10px; }

/* ── Selección de número ── */
.comms-numeros { display: flex; flex-direction: column; gap: 8px; margin: 16px 0; }
.comms-numero-opt {
  display: flex; align-items: center; gap: 10px; padding: 12px 14px;
  border: 1px solid var(--border); border-radius: 10px; cursor: pointer;
  background: var(--surface); transition: border-color 0.15s;
}
.comms-numero-opt:hover { border-color: var(--brand); }
.comms-numero-phone { font-weight: 600; color: var(--text-strong); }
.comms-numero-costo { margin-left: auto; font-size: 0.8rem; color: var(--muted); }

/* ── Progreso en vivo ── */
.comms-progreso { text-align: center; padding: 12px 0; }
.comms-progreso h4 { margin: 14px 0 6px; color: var(--text-strong); }
.comms-progress-bar {
  height: 8px; background: var(--surface-3); border-radius: 999px; overflow: hidden; margin-bottom: 20px;
}
.comms-progress-fill {
  height: 100%; background: var(--brand); border-radius: 999px; transition: width 0.6s ease;
}
.comms-spinner {
  width: 40px; height: 40px; margin: 0 auto; border-radius: 50%;
  border: 4px solid var(--surface-3); border-top-color: var(--brand);
  animation: comms-spin 0.8s linear infinite;
}
@keyframes comms-spin { to { transform: rotate(360deg); } }
.comms-check {
  width: 64px; height: 64px; margin: 0 auto 8px; border-radius: 50%;
  background: var(--badge-success-bg); color: var(--badge-success-fg);
  display: flex; align-items: center; justify-content: center; font-size: 2rem; font-weight: 700;
}
.comms-warn-icon {
  width: 56px; height: 56px; margin: 0 auto 8px; border-radius: 50%;
  background: var(--badge-warn-bg); color: var(--badge-warn-fg);
  display: flex; align-items: center; justify-content: center; font-size: 1.6rem;
}
.comms-progreso--ok .comms-line-phone { margin: 10px 0 18px; font-size: 1.3rem; }
.comms-error-msg { color: var(--muted); font-size: 0.9rem; margin: 8px 0 16px; line-height: 1.5; }
.comms-recover { display: flex; flex-direction: column; gap: 12px; align-items: center; }

/* ═══════════════════════════════════════════════════════════════════════════
   AGENTE-GUÍA ILUSTRADO  ·  .ga-* (personaje)  ·  .gt-* (escenario del tour)
   ---------------------------------------------------------------------------
   Sustituye al tour anterior (.tut-*), que se borró al migrar las 15 páginas.

   COLOR: solo tokens. Los locales del personaje se declaran una vez en `.ga` y
   ahí se retematiza todo. No hay overrides por tema para la silueta: --brand,
   --brand-dark y --bg ya se invierten solos (:root ~20 ↔ html.light-mode ~10951).

   MOVIMIENTO: en bucle infinito SOLO respira el personaje (~1 % de escala). Todo
   lo demás es de un disparo o finito (≤3 iteraciones). Es deliberado: con un
   público de atención corta, el movimiento tiene que llamar y soltar. El tour
   anterior latía para siempre y encima animaba un box-shadow de 9999px: un
   repintado de pantalla completa a 60 fps que no paraba nunca.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Capas del escenario ────────────────────────────────────────────────────
   2400-2404: por encima del tour viejo (2000-2002) y por DEBAJO del modal de
   error crítico (.crit-overlay, 3000) y de los toasts — un fallo de sesión debe
   poder tapar la guía. */

.gt-blocker {
  position: fixed;
  inset: 0;
  z-index: 2400;
  background: transparent;
}
/* Sin objetivo que resaltar, el velo lo pone el bloqueador. Con objetivo lo pone
   la sombra gigante del agujero, que además recorta el hueco. */
.gt-blocker--dim { background: var(--scrim); }

/* El foco. Es una caja VACÍA del overlay colocada encima del objetivo, cuya
   sombra gigante oscurece todo lo demás.
   Frente a la técnica anterior (poner la clase sobre el elemento de la página):
     · no toca el DOM ajeno — adiós al position/z-index/pointer-events !important
       y al caso especial que el motor anterior necesitaba para el header;
     · al ser fixed no lo recorta ningún overflow:hidden, así que por fin se puede
       resaltar una fila de tabla o algo dentro de un panel con scroll;
     · se puede ANIMAR: el foco se desliza de un elemento al siguiente.
   Contrapartida: el elemento resaltado queda por debajo del velo y no es
   clicable. Los pasos que piden pulsar el elemento real no pintan el bloqueador
   (Advance::ClickTarget). */
.gt-hole {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 2401;
  pointer-events: none;
  border-radius: 12px;
  box-shadow: 0 0 0 100vmax var(--scrim);
  transition:
    transform     .34s cubic-bezier(.22, 1, .36, 1),
    width         .34s cubic-bezier(.22, 1, .36, 1),
    height        .34s cubic-bezier(.22, 1, .36, 1),
    border-radius .2s ease;
}
/* Anillo de marca en un pseudo-elemento aparte para que el pulso sea
   transform+opacity (compositor) y no un box-shadow de pantalla completa. */
.gt-hole::after {
  content: '';
  position: absolute;
  inset: -3px;
  border-radius: inherit;
  border: 3px solid rgba(var(--brand-rgb), .95);
  animation: gt-ring 1.8s ease-out 3;
}
@keyframes gt-ring {
  0%   { transform: scale(1);    opacity: 1; }
  70%  { transform: scale(1.08); opacity: 0; }
  100% { transform: scale(1.08); opacity: 0; }
}

/* Flecha. Sin viewBox a propósito: 1 unidad = 1 px CSS, así no hay que
   remapear coordenadas al redimensionar. */
.gt-link {
  position: fixed;
  inset: 0;
  z-index: 2402;
  width: 100vw;
  height: 100vh;
  pointer-events: none;
  overflow: visible;
}
.gt-link-line,
.gt-link-tip {
  fill: none;
  stroke: var(--brand);
  stroke-width: 3;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* El trazo avanza DEL personaje AL objetivo: la animación lleva dirección, que
   es justo el vector de atención que se busca. Un disparo. */
.gt-link-line {
  stroke-dasharray: var(--gt-len, 400);
  stroke-dashoffset: var(--gt-len, 400);
  animation: gt-draw .5s ease-out forwards;
}
.gt-link-tip { opacity: 0; animation: gt-tip .2s ease-out .42s forwards; }
@keyframes gt-draw { to { stroke-dashoffset: 0; } }
@keyframes gt-tip  { to { opacity: 1; } }

/* Colocación del personaje. Este div SOLO posiciona y funde; la respiración va
   en el <svg> de dentro — si estuvieran en el mismo elemento se pisarían la
   propiedad `transform`. */
.gt-avatar {
  position: fixed;
  z-index: 2403;
  pointer-events: none;
  transition: left .32s cubic-bezier(.22, 1, .36, 1),
              top  .32s cubic-bezier(.22, 1, .36, 1),
              opacity .15s ease;
}
/* Mientras se recoloca se desvanece: arrastrar al personaje media pantalla hace
   que el usuario lo persiga a él en vez de mirar el destino. */
.gt-avatar--moving { opacity: 0; }

/* ── Tarjeta ────────────────────────────────────────────────────────────────
   --surface-overlay (casi opaca) porque es un panel FLOTANTE. Con --surface, que
   es translúcida, sobre el velo se vuelve ilegible en oscuro. */
.gt-card {
  position: fixed;
  z-index: 2404;
  width: min(380px, calc(100vw - 24px));
  background: var(--surface-overlay);
  border: 1px solid var(--border);
  border-radius: 18px;
  padding: 20px 22px 16px;
  box-shadow: var(--shadow-lg);
  animation: gt-card-in .26s ease-out;
}
/* Sin objetivo (o sin hueco en ningún lado): centrada abajo, como el tour
   clásico. Es una posición que el usuario ya reconoce. */
.gt-card--centered {
  left: 50%;
  bottom: 40px;
  top: auto;
  transform: translateX(-50%);
}
.gt-card:focus-visible { outline: 2px solid var(--brand); outline-offset: 3px; }
@keyframes gt-card-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}
/* La variante centrada ya usa `transform` para centrarse: su entrada no puede
   pisarlo o saltaría media tarjeta a la derecha. */
.gt-card--centered { animation: gt-card-in-centered .26s ease-out; }
@keyframes gt-card-in-centered {
  from { opacity: 0; transform: translateX(-50%) translateY(10px); }
  to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}

.gt-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}
.gt-eyebrow {
  font-size: .6875rem;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--brand);
}
.gt-counter { font-size: .75rem; font-weight: 600; color: var(--muted-2); }
/* Guía de novedades: la cabecera se distingue de la guía normal para que quien
   ya conoce la pantalla entienda de un vistazo por qué le vuelve a salir. */
.gt-eyebrow--news {
  background: var(--brand-soft-bg);
  color: var(--brand-soft-fg);
  padding: 2px 8px;
  border-radius: 999px;
}

/* Progreso explícito, no cinco puntitos: "voy por 2 de 5" es información, y para
   quien se pierde con facilidad es la diferencia entre seguir y abandonar. */
.gt-progress {
  height: 4px;
  border-radius: 2px;
  background: var(--control-bg-hover);
  overflow: hidden;
  margin-bottom: 14px;
}
.gt-progress-fill {
  display: block;
  height: 100%;
  border-radius: 2px;
  background: var(--brand);
  transition: width .3s cubic-bezier(.22, 1, .36, 1);
}

.gt-title {
  font-size: 1.0625rem;
  font-weight: 700;
  color: var(--text-strong);
  letter-spacing: -.01em;
  margin: 0 0 8px;
}
.gt-body {
  font-size: .9rem;
  line-height: 1.55;
  color: var(--muted);
  margin: 0 0 18px;
}

/* ── Ejemplo de llenado ─────────────────────────────────────────────────────
   Maqueta INERTE de un formulario: campo → valor de ejemplo. Solo aparece en
   modo «con detalle». Deliberadamente NO parece un formulario editable (sin
   inputs, sin bordes de campo) para que nadie intente escribir en él. */
.gt-example {
  margin: 0 0 18px;
  padding: 12px 14px;
  border: 1px dashed var(--border);
  border-radius: 12px;
  background: var(--surface-2);
}
.gt-example-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 10px;
}
.gt-example-title {
  font-size: .8125rem;
  font-weight: 700;
  color: var(--text-strong);
}
.gt-example-badge {
  font-size: .625rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--badge-info-fg);
  background: var(--badge-info-bg);
  padding: 2px 8px;
  border-radius: 999px;
  white-space: nowrap;
}
.gt-example-fields {
  display: grid;
  grid-template-columns: minmax(0, auto) 1fr;
  gap: 4px 12px;
  margin: 0;
}
.gt-example-row {
  display: contents;
}
.gt-example-label {
  font-size: .8125rem;
  font-weight: 600;
  color: var(--muted-2);
  white-space: nowrap;
}
.gt-example-value {
  margin: 0;
  font-size: .8125rem;
  color: var(--text);
  /* Se ve como "dato ya escrito", no como campo por rellenar. */
  font-variant-numeric: tabular-nums;
  word-break: break-word;
}
.gt-example-note {
  margin: 10px 0 0;
  font-size: .75rem;
  line-height: 1.5;
  color: var(--muted);
}

/* ── Botón "¿Qué hace cada botón?" ──────────────────────────────────────────
   Va en la cabecera de un modal/apartado con muchos botones y abre su guía
   efímera. Pastilla discreta: ayuda a mano sin competir con las acciones. */
.gt-modal-help {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 12px 5px 8px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--control-bg);
  color: var(--muted);
  font: inherit;
  font-size: .8125rem;
  font-weight: 600;
  cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
}
.gt-modal-help:hover {
  background: var(--control-bg-hover);
  color: var(--text);
  border-color: var(--brand);
}
.gt-modal-help-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--brand-dark);
  color: #fff;
  font-size: .75rem;
  font-weight: 800;
  line-height: 1;
}

.gt-actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.gt-btn-group { display: flex; align-items: center; gap: 8px; }
.gt-btn-skip {
  font: inherit;
  font-size: .8125rem;
  font-weight: 500;
  color: var(--muted-2);
  background: none;
  border: none;
  cursor: pointer;
  padding: 6px 2px;
  transition: color .15s;
}
.gt-btn-skip:hover { color: var(--muted); }
.gt-btn-prev,
.gt-btn-next {
  padding: 8px 16px;
  border-radius: 10px;
  border: none;
  cursor: pointer;
  font: inherit;
  font-size: .875rem;
  font-weight: 600;
  transition: background .15s;
}
.gt-btn-prev { background: var(--surface-2); color: var(--muted); }
.gt-btn-prev:hover { background: var(--control-bg-hover); }
/* --brand-dark es la variante que aguanta texto blanco en AMBOS temas. */
.gt-btn-next { background: var(--brand-dark); color: #fff; }
.gt-btn-next:hover { background: var(--brand); }
.gt-hint {
  font-size: .8125rem;
  font-weight: 600;
  color: var(--brand);
}

/* ── Personaje ──────────────────────────────────────────────────────────────
   --ga-body  = --brand      : variante "sobre el fondo del tema" → legible en
                               claro y en oscuro sin duplicar reglas.
   --ga-shade = --brand-dark : más profunda en ambos temas → el brazo en reposo
                               recede sin inventar un color.
   --ga-ink   = --bg         : ojos y boca del color del lienzo → contraste
                               automático al cambiar de tema.
   --ga-halo  = --bg         : contorno tipo pegatina; en claro despega la
                               silueta del velo, en oscuro es invisible. */
.ga {
  --ga-body:  var(--brand);
  --ga-shade: var(--brand-dark);
  --ga-ink:   var(--bg);
  --ga-halo:  var(--bg);
  --ga-swing: 420ms;
  --ga-ease:  cubic-bezier(.34, 1.28, .48, 1);

  display: block;
  height: var(--ga-size, 124px);
  width: auto;
  transform-origin: 50% 91%;
  animation: ga-breathe 4.6s ease-in-out infinite;
  /* Único bucle permanente del sistema → la capa de composición se justifica.
     No copiar esto en el resto de clases: una capa GPU eterna para una animación
     de entrada de 0,3 s es memoria de vídeo tirada. */
  will-change: transform;
}

.ga-solid {
  fill: var(--ga-body);
  stroke: var(--ga-halo);
  stroke-width: 4;
  stroke-linejoin: round;
  paint-order: stroke fill;
}
.ga-shadow { fill: rgba(var(--brand-dark-rgb), .18); }
.ga-leg    { fill: var(--ga-shade); }
.ga-neck   { fill: var(--ga-shade); }
.ga-eye    { fill: var(--ga-ink); }
.ga-mouth  { fill: none; stroke: var(--ga-ink); stroke-width: 2; stroke-linecap: round; }

/* Lentes: el avatar de las guías «con detalle». Ocultos por defecto; los enciende
   `.ga--glasses` en el `<svg>`. Mismo `--ga-ink` que ojos y boca → legible sobre la
   cabeza en claro y en oscuro sin una regla por tema. Lentes sin relleno para que
   los ojos se vean a través. */
.ga-glasses { display: none; }
.ga--glasses .ga-glasses { display: inline; }
.ga-glass-lens {
  fill: none;
  stroke: var(--ga-ink);
  stroke-width: 1.8;
}
.ga-glass-bar {
  fill: none;
  stroke: var(--ga-ink);
  stroke-width: 1.8;
  stroke-linecap: round;
}

/* Micro-desplazamiento de la mirada hacia donde señala: dos reglas que refuerzan
   mucho el "mira allí". */
.ga-face { transition: transform var(--ga-swing) var(--ga-ease); }
.ga--face-left  .ga-face { transform: translateX(-2px); }
.ga--face-right .ga-face { transform: translateX(2px); }

/* Brazos. `transform-box: view-box` hace que transform-origin use unidades del
   viewBox.
   OJO: esta `transition` abreviada SUSTITUYE a la regla global de style.css:109
   en estos elementos, por eso stroke/fill se repiten aquí — si no, el personaje
   dejaría de fundir su color al cambiar de tema. Y `stroke` NO está en la lista
   global, así que los brazos (dibujados con stroke) hay que declararlos a mano
   en cualquier caso. */
.ga-arm,
.ga-arm-think {
  transform-box: view-box;
  transition: transform var(--ga-swing) var(--ga-ease),
              stroke .3s ease, fill .3s ease, opacity .2s ease;
}
.ga-arm--r, .ga-arm-think { transform-origin: 99px 62px; }
.ga-arm--l                { transform-origin: 61px 62px; }

.ga-limb-halo { fill: none; stroke: var(--ga-halo);  stroke-width: 16;   stroke-linecap: round; }
.ga-limb      { fill: none; stroke: var(--ga-shade); stroke-width: 10.5; stroke-linecap: round; }
.ga-hand, .ga-fist { fill: var(--ga-shade); }

/* El brazo que señala se adelanta de color: el gesto se ilumina. */
.ga--point-right .ga-arm--r .ga-limb, .ga--point-right .ga-arm--r .ga-hand,
.ga--point-left  .ga-arm--l .ga-limb, .ga--point-left  .ga-arm--l .ga-hand,
.ga--point-up    .ga-arm--r .ga-limb, .ga--point-up    .ga-arm--r .ga-hand,
.ga--point-down  .ga-arm--r .ga-limb, .ga--point-down  .ga-arm--r .ga-hand {
  stroke: var(--ga-body);
  fill: var(--ga-body);
}

/* Ángulos. En SVG rotate() positivo es horario y el brazo en reposo cuelga hacia
   abajo (90° de pantalla): -88° ≈ horizontal derecha, -168° ≈ arriba, -35° ≈
   abajo-derecha. */
.ga--point-right .ga-arm--r { transform: rotate(-88deg); }
.ga--point-left  .ga-arm--l { transform: rotate(88deg); }
.ga--point-up    .ga-arm--r { transform: rotate(-168deg); }
.ga--point-down  .ga-arm--r { transform: rotate(-35deg); }
/* Mirando a la izquierda, arriba/abajo usan el brazo de ese lado. */
.ga--face-left.ga--point-up   .ga-arm--r { transform: none; }
.ga--face-left.ga--point-up   .ga-arm--l { transform: rotate(168deg); }
.ga--face-left.ga--point-down .ga-arm--r { transform: none; }
.ga--face-left.ga--point-down .ga-arm--l { transform: rotate(35deg); }
.ga--face-left.ga--point-up   .ga-arm--l .ga-limb,
.ga--face-left.ga--point-down .ga-arm--l .ga-limb { stroke: var(--ga-body); }

/* Pensar: la mano va a la barbilla, no es una rotación → brazo aparte. */
.ga-arm-think { opacity: 0; visibility: hidden; }
.ga--think .ga-arm-think { opacity: 1; visibility: visible; }
.ga--think .ga-arm--r { opacity: 0; }
.ga-bubble { opacity: 0; visibility: hidden; fill: var(--ga-body); }
.ga--think .ga-bubble { opacity: 1; visibility: visible; }
.ga--think .ga-bubble circle { animation: ga-dots 1.8s ease-in-out 3; }
.ga--think .ga-bubble circle:nth-child(2) { animation-delay: .18s; }
.ga--think .ga-bubble circle:nth-child(3) { animation-delay: .36s; }

/* Saludar y celebrar: finitos. Los keyframes INCLUYEN el ángulo base porque una
   `animation` sobre transform sustituye por completo al de la `transition`; sin
   él, el brazo daría un salto al empezar. */
.ga--wave .ga-arm--r { animation: ga-wave-r .9s ease-in-out 2; }
.ga--face-left.ga--wave .ga-arm--r { animation: none; }
.ga--face-left.ga--wave .ga-arm--l { animation: ga-wave-l .9s ease-in-out 2; }
.ga--celebrate .ga-arm--r { animation: ga-cheer-r .7s ease-in-out 2; }
.ga--celebrate .ga-arm--l { animation: ga-cheer-l .7s ease-in-out 2; }
/* Sustituye a ga-breathe mientras dura: dos animaciones sobre la misma
   propiedad no se componen, gana la última. */
.ga--celebrate { animation: ga-hop .5s ease-in-out 3; }
.ga-sparks { opacity: 0; fill: var(--brand); }
.ga--celebrate .ga-sparks { opacity: 1; }
.ga--celebrate .ga-spark {
  animation: ga-spark 1.1s ease-out 2;
  transform-box: fill-box;
  transform-origin: 50% 50%;
}
.ga--celebrate .ga-spark:nth-child(2) { animation-delay: .2s; }
.ga--celebrate .ga-spark:nth-child(3) { animation-delay: .4s; }

/* Respiración: ~0,9 px y 1,2 % de escala en 4,6 s. Por debajo del umbral que
   captura la atención — se lee como "está vivo", no como "algo se mueve". */
@keyframes ga-breathe {
  0%, 100% { transform: translateY(0)      scaleY(1); }
  50%      { transform: translateY(-1.2px) scaleY(1.012); }
}
@keyframes ga-wave-r  { 0%,100% { transform: rotate(-142deg); } 50% { transform: rotate(-166deg); } }
@keyframes ga-wave-l  { 0%,100% { transform: rotate(142deg);  } 50% { transform: rotate(166deg);  } }
@keyframes ga-cheer-r { 0%,100% { transform: rotate(-145deg); } 50% { transform: rotate(-128deg); } }
@keyframes ga-cheer-l { 0%,100% { transform: rotate(145deg);  } 50% { transform: rotate(128deg);  } }
@keyframes ga-hop     { 0%,100% { transform: translateY(0);   } 45% { transform: translateY(-7px); } }
@keyframes ga-dots    { 0%,100% { opacity: .25; } 50% { opacity: 1; } }
@keyframes ga-spark {
  0%   { opacity: 0; transform: scale(.4); }
  40%  { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.25); }
}

/* En claro el --scrim del proyecto tiene α .45 y deja poco foco para un tour. La
   misma sombra se declara dos veces: al componerse sobre sí misma el alfa se
   acumula (≈.70) sin hardcodear ningún color nuevo. Si el velo claro se quedara
   corto en TODOS los modales, lo correcto sería subir --scrim en
   html.light-mode (~10964), no parchear aquí. */
html.light-mode .gt-hole {
  box-shadow: 0 0 0 100vmax var(--scrim), 0 0 0 100vmax var(--scrim);
}

/* ── Tarjeta "Primeros pasos" del Inicio ────────────────────────────────────
   Un solo ítem destacado a la vez: el primero que falta. Los demás quedan en
   gris y sin explicación. Seis botones iguales son seis decisiones. */

.fs-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 20px 22px 16px;
  /* Separación arriba Y abajo. La tarjeta va detrás de la rejilla de módulos del
     Inicio, y esa sección no lleva `margin-bottom`: el ritmo vertical de la página
     lo dan los bloques de arriba empujando hacia abajo (banner 24px, cabecera 32px,
     barra de módulos 18px). Como la tarjeta es el ÚLTIMO bloque, su margen inferior
     no separaba de nada y arriba quedaba pegada a las tarjetas de módulos.
     El margen va aquí y no en la sección para que, cuando la tarjeta no se muestra
     (descartada, o el usuario no es owner/supervisor), no quede un hueco suelto. */
  margin-top: 28px;
  margin-bottom: 28px;
}
.fs-card--done {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 14px 20px;
}
.fs-done-text { color: var(--text-strong); font-weight: 600; font-size: .9375rem; }

.fs-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 10px;
}
.fs-title { font-size: 1.0625rem; font-weight: 700; color: var(--text-strong); margin: 0; }
.fs-count { font-size: .8125rem; font-weight: 600; color: var(--muted-2); }

.fs-progress {
  height: 5px;
  border-radius: 3px;
  background: var(--control-bg-hover);
  overflow: hidden;
  margin-bottom: 16px;
}
.fs-progress-fill {
  display: block;
  height: 100%;
  border-radius: 3px;
  background: var(--brand);
  transition: width .35s cubic-bezier(.22, 1, .36, 1);
}

.fs-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 2px; }
.fs-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 9px 10px;
  border-radius: 10px;
}
/* El pendiente en curso: el único con fondo, explicación y botón fuerte. */
.fs-item--next { background: var(--brand-soft-bg); }
.fs-item--done .fs-item-label { color: var(--muted-2); text-decoration: line-through; }

.fs-check {
  flex: 0 0 20px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  border: 2px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: .75rem;
  font-weight: 700;
  color: #fff;
}
.fs-item--done .fs-check { background: var(--brand-dark); border-color: var(--brand-dark); }

.fs-item-text { display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; min-width: 0; }
.fs-item-label { font-size: .9375rem; font-weight: 600; color: var(--text); }
.fs-item-why { font-size: .8125rem; color: var(--muted); }

.fs-go {
  flex: 0 0 auto;
  padding: 6px 14px;
  border-radius: 9px;
  border: 1px solid var(--control-border);
  background: var(--control-bg);
  color: var(--muted);
  font: inherit;
  font-size: .8125rem;
  font-weight: 600;
  cursor: pointer;
  transition: background .15s, color .15s;
}
.fs-go:hover { background: var(--control-bg-hover); color: var(--text); }
.fs-go--primary {
  background: var(--brand-dark);
  border-color: transparent;
  color: #fff;
  padding: 8px 20px;
  font-size: .875rem;
}
.fs-go--primary:hover { background: var(--brand); color: #fff; }

.fs-foot {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 14px;
  margin-top: 14px;
}
.fs-tour {
  background: none;
  border: none;
  padding: 4px 2px;
  font: inherit;
  font-size: .8125rem;
  font-weight: 600;
  color: var(--brand);
  cursor: pointer;
}
.fs-tour:hover { text-decoration: underline; }
.fs-dismiss {
  background: none;
  border: none;
  padding: 4px 2px;
  font: inherit;
  font-size: .8125rem;
  color: var(--muted-2);
  cursor: pointer;
}
.fs-dismiss:hover { color: var(--muted); }

/* ── Elección de cuánto explicar ────────────────────────────────────────────
   Se pregunta una sola vez en la vida del usuario. Dos opciones grandes y una
   salida: tres decisiones son ya demasiadas para una pregunta que nadie pidió. */

.gt-card--ask { width: min(440px, calc(100vw - 24px)); }
.gt-avatar--ask { left: 50%; bottom: 300px; transform: translateX(-50%); }

.gt-modes { display: flex; flex-direction: column; gap: 10px; margin-bottom: 16px; }
.gt-mode {
  display: flex;
  flex-direction: column;
  gap: 3px;
  align-items: flex-start;
  padding: 12px 16px;
  border-radius: 12px;
  border: 1px solid var(--control-border);
  background: var(--control-bg);
  cursor: pointer;
  font: inherit;
  text-align: left;
  transition: background .15s, border-color .15s;
}
.gt-mode:hover { background: var(--control-bg-hover); border-color: var(--brand); }
.gt-mode-name { font-size: .9375rem; font-weight: 700; color: var(--text-strong); }
.gt-mode-desc { font-size: .8125rem; color: var(--muted); }

/* Cambiar de nivel de detalle sin salir de la guía. Va junto a "Salir": es donde
   mira quien está a punto de abandonar porque no se entera. */
.gt-left-actions { display: flex; align-items: center; gap: 12px; }
.gt-btn-mode {
  background: none;
  border: none;
  padding: 6px 2px;
  font: inherit;
  font-size: .8125rem;
  font-weight: 600;
  color: var(--brand);
  cursor: pointer;
}
.gt-btn-mode:hover { text-decoration: underline; }

/* ── Perfil › Guías ─────────────────────────────────────────────────────────*/

.gp-modes { display: flex; gap: 6px; }
.gp-mode {
  padding: 7px 14px;
  border-radius: 9px;
  border: 1px solid var(--control-border);
  background: var(--control-bg);
  color: var(--muted);
  font: inherit;
  font-size: .8125rem;
  font-weight: 600;
  cursor: pointer;
  transition: background .15s, color .15s, border-color .15s;
}
.gp-mode:hover { background: var(--control-bg-hover); color: var(--text); }
.gp-mode.is-on {
  background: var(--brand-dark);
  border-color: transparent;
  color: #fff;
}

.gp-list {
  list-style: none;
  margin: 12px 0 0;
  padding: 8px;
  max-height: 320px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface-2);
}
.gp-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 7px 10px;
  border-radius: 8px;
}
.gp-item:hover { background: var(--control-bg); }
.gp-item-name { font-size: .875rem; color: var(--text); }
.gp-item-btn {
  background: none;
  border: none;
  padding: 2px 4px;
  font: inherit;
  font-size: .8125rem;
  font-weight: 600;
  color: var(--brand);
  cursor: pointer;
}
.gp-item-btn:hover { text-decoration: underline; }
.gp-item-pending { font-size: .75rem; color: var(--muted-2); }

/* ── Boceto de un módulo del código, en el Catálogo ─────────────────────────
   Esquema, no captura: responde a «¿a qué se parece esto?» sin necesitar 13
   imágenes que mantener y que envejecen mal. Todo con tokens, así que sirve en
   claro y en oscuro sin duplicar reglas. */

.mb {
  display: block;
  width: 100%;
  height: auto;
  background: var(--surface-2);
}
/* Dentro de la miniatura cuadrada del catálogo, el boceto la llena igual que
   haría el logo de un paquete: si no, la tarjeta de un módulo se vería con un
   hueco donde las demás tienen imagen. */
.mk-sq-thumb .mb { width: 100%; height: 100%; object-fit: contain; padding: 10px; }
.mk-detail-cover--boceto { padding: 16px; background: var(--surface-2); }
.mk-detail-cover--boceto .mb { background: none; }
.mb-marco { fill: none; stroke: var(--border); stroke-width: 1.5; }
/* Los bloques normales insinúan contenido: han de leerse como «hay algo aquí»,
   no competir con el nombre del módulo que va debajo. */
.mb rect:not(.mb-marco) { fill: var(--control-bg-hover); }
.mb .mb-fuerte { fill: var(--brand); opacity: .75; }
.mb .mb-suave { fill: var(--control-bg-hover); stroke: none; }
.mb .mb-linea {
  fill: none;
  stroke: var(--brand);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: .75;
}
.mb circle { fill: var(--brand); opacity: .75; }

/* Marca de los módulos que vienen con el panel: no se instalan ni tienen versión
   que elegir, así que se distinguen de los paquetes del Marketplace. */
.mk-incluido {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 9px;
  border-radius: 999px;
  background: var(--badge-info-bg);
  color: var(--badge-info-fg);
  font-size: .6875rem;
  font-weight: 700;
}
.mk-siempre-al-dia { font-size: .75rem; color: var(--muted-2); }

/* El correo saliente no tiene boceto de módulo —no es una pantalla— así que su
   miniatura es el icono, centrado y a media altura para que no compita con los
   bocetos vecinos, que sí dibujan una interfaz. */
.mk-sq-thumb--feat svg {
  width: 46%;
  height: 46%;
  color: var(--brand);
  opacity: .85;
}
.mk-detail-cover--boceto > svg {
  width: 100%;
  height: 100%;
  color: var(--brand);
  opacity: .85;
}

/* Nota bajo la rejilla cuando en Módulos solo hay lo que trae el panel. Va
   fuera del grid: dentro ocuparía una celda y rompería la cuadrícula. */
.mk-nota-terceros {
  margin: 14px 2px 0;
  font-size: .8125rem;
  color: var(--muted-2);
}

.mk-feat-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 10px;
  flex-wrap: wrap;
}
.mk-feat-row .pg-input { flex: 1 1 240px; max-width: 380px; }

/* ── Centro de Control › Guías: apariencia del agente ───────────────────────
   Una tarjeta por gesto. La vista previa muestra la imagen al tamaño y con el
   recorte con que se verá de verdad en la guía, no una miniatura genérica. */

.gi-intro, .gi-foot { max-width: 70ch; }
.gi-foot { margin-top: 18px; }

/* Segmented que elige el modo de guía cuyas imágenes se editan («al grano» /
   «con detalle»). Cada modo tiene su propio juego de avatares. */
.gi-modo {
  display: inline-flex;
  gap: 4px;
  margin-top: 16px;
  padding: 4px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface-2);
}
.gi-modo-btn {
  border: none;
  background: none;
  font: inherit;
  font-size: .8125rem;
  font-weight: 600;
  color: var(--muted);
  padding: 6px 16px;
  border-radius: 999px;
  cursor: pointer;
}
.gi-modo-btn:hover { color: var(--text-strong); }
/* Activo = pastilla de marca con texto blanco (--brand-dark es siempre la variante
   sobre la que se apoya texto blanco, en ambos temas). */
.gi-modo-btn--active { background: var(--brand-dark); color: #fff; }
.gi-modo-btn--active:hover { color: #fff; }

.gi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 14px;
  margin-top: 18px;
}

.gi-card {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--surface-2);
}

/* Alto fijo para que las tarjetas queden alineadas aunque las imágenes que
   suban tengan proporciones distintas. */
.gi-preview {
  flex: 0 0 96px;
  height: 104px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
.gi-img { max-height: 104px; max-width: 96px; width: auto; object-fit: contain; }

.gi-meta { flex: 1 1 auto; min-width: 0; }
.gi-name { font-size: .9375rem; font-weight: 600; color: var(--text-strong); }
.gi-help { font-size: .8125rem; color: var(--muted); margin-top: 2px; }
.gi-state { font-size: .75rem; color: var(--muted-2); margin-top: 6px; }

.gi-actions { display: flex; flex-direction: column; align-items: stretch; gap: 6px; }
/* El input real se oculta y el <label> hace de botón: un input de archivo nativo
   no se puede estilar y rompe la coherencia de la pantalla. */
.gi-file { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.gi-btn { cursor: pointer; text-align: center; font-size: .8125rem; padding: 7px 14px; }
.gi-clear {
  background: none;
  border: none;
  padding: 2px;
  font: inherit;
  font-size: .75rem;
  color: var(--muted-2);
  cursor: pointer;
}
.gi-clear:hover { color: var(--badge-danger-fg); }
.gi-busy { font-size: .75rem; color: var(--muted-2); text-align: center; }

/* Marca "Nuevo" en la barra lateral, hasta la primera visita al módulo.
   Dos formas para los dos estados de la barra:
     · desplegada → etiqueta, que dice de qué avisa;
     · contraída  → punto, porque ahí solo hay sitio para el icono y la etiqueta
       desbordaba la columna descuadrando la lista entera.
   Misma gramática que el indicador de la campana: un punto que late significa
   «hay algo sin ver», y eso ya se entiende sin leer nada. */
.module-sidebar-new {
  margin-left: auto;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--brand-dark);
  color: #fff;
  font-size: .625rem;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.module-sidebar-new-dot { display: none; }

.module-sidebar--collapsed .module-sidebar-new { display: none; }
.module-sidebar--collapsed .module-sidebar-new-dot {
  display: block;
  position: absolute;
  top: 6px;
  right: 8px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--brand);
  /* El halo va en el pseudo-elemento para que lo anime el compositor: el punto
     en sí no se mueve, así que no arrastra al resto de la fila. */
}
.module-sidebar--collapsed .module-sidebar-new-dot::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--brand);
  animation: notif-pulse 1.8s ease-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  .module-sidebar--collapsed .module-sidebar-new-dot::after { animation: none; }
}

@media (prefers-reduced-motion: reduce) {
  /* Se apaga el MOVIMIENTO, no el mensaje: la pose es un transform estático, así
     que el personaje sigue señalando el elemento correcto. */
  .fs-progress-fill { transition: none; }
  .ga { animation: none; }
  .ga-arm, .ga-arm-think, .ga-face { transition-duration: .01ms; }
  .ga--wave .ga-arm--r, .ga--wave .ga-arm--l,
  .ga--celebrate .ga-arm--r, .ga--celebrate .ga-arm--l { animation: none; }
  /* Sin animación los keyframes ya no aplican el ángulo: hay que fijarlo. */
  .ga--wave .ga-arm--r { transform: rotate(-142deg); }
  .ga--face-left.ga--wave .ga-arm--l { transform: rotate(142deg); }
  .ga--celebrate .ga-arm--r { transform: rotate(-145deg); }
  .ga--celebrate .ga-arm--l { transform: rotate(145deg); }
  .ga--think .ga-bubble circle,
  .ga--celebrate .ga-spark { animation: none; opacity: 1; }
  .ga--celebrate .ga-spark { transform: none; }

  .gt-avatar { transition: opacity .01ms; }
  .gt-hole { transition: none; }
  .gt-hole::after { animation: none; }   /* el anillo se queda fijo y visible */
  .gt-link-line { animation: none; stroke-dashoffset: 0; }
  .gt-link-tip  { animation: none; opacity: 1; }
  .gt-card, .gt-card--centered { animation: none; }
  .gt-progress-fill { transition: none; }
}
/* Casilla de confirmación dentro de un formulario del Marketplace (p. ej. aceptar
   un downgrade al subir una versión anterior a la publicada). */
.mk-check-row {
  flex-direction: row; align-items: center; gap: 8px;
  font-size: 0.82rem; color: var(--text);
}
.mk-check-row input[type="checkbox"] { flex: 0 0 auto; margin: 0; }


/* ═══════════════════════════════════════════════════════════════════════════
   FLUJOS — rediseño del Constructor (2026-08-03)
   Izquierda: toolbar de bandeja (buscador + filtros + colapsar) y paginado.
   Derecha: 3 etapas como tarjetas navegables con drill animado.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Panel izquierdo ──────────────────────────────────────────────────────── */

/* 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; }

/* Ramas (bifurcaciones): sub-sección en la etapa de fases. Misma identidad que las
   tarjetas de disparador (borde, radio, superficie) y los botones-icono de acción. */
.flx-ramas {
  border: 1px solid var(--border-soft); border-radius: 12px;
  background: var(--surface); padding: 12px 14px; margin-bottom: 14px;
}
.flx-ramas-head { display: flex; align-items: center; gap: 10px; margin-bottom: 10px; }
.flx-ramas-title {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 12.5px; font-weight: 700; color: var(--text-strong);
}
.flx-ramas-head .flx-btn-new { margin-left: auto; }
.flx-ramas-list { display: flex; flex-direction: column; gap: 8px; }
.flx-rama-card {
  display: flex; align-items: center; gap: 10px;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface-2); padding: 9px 12px;
}
.flx-rama-card.is-off { opacity: .6; border-style: dashed; }
.flx-rama-card-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
.flx-rama-card-name {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 12.5px; font-weight: 600; color: var(--text-strong);
}
.flx-rama-card-crit {
  font-size: 11.5px; color: var(--muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 52ch;
}
.flx-rama-tt { display: flex; gap: 8px; flex-wrap: wrap; }
.flx-rama-tt .form-input { flex: 1 1 160px; min-width: 130px; }

/* La toolbar va DEBAJO del título + botón. `.lc-topbar` ya trae la pastilla de
   búsqueda y los iconos sin caja; aquí solo se ajusta el espaciado. */
.flx-sidebar .lc-topbar { margin: 0 0 10px; padding: 0; }
.flx-sidebar .lc-filters-popover { top: 92px; }

/* 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 .lc-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 ──────────────────────────────────────────── */
.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; }

/* Cierra el menú ⋮ al pulsar fuera sin oscurecer la página. */
.flx-menu-backdrop { position: fixed; inset: 0; z-index: 59; }
.flx-flow-header-actions.mm-menu { position: relative; }

/* ── Etapas como tarjetas navegables ──────────────────────────────────────── */
.flx-stagebar { gap: 10px; }
.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 — misma entrada/salida que la vista día de MIR. */
.flx-drill { animation: flx-drill-in .22s cubic-bezier(0.2, 0.7, 0.2, 1); }
@keyframes flx-drill-in {
  from { opacity: 0; transform: scale(0.96) translateX(14px); }
  to   { opacity: 1; transform: none; }
}
.flx-drill.is-closing { animation: flx-drill-out .2s cubic-bezier(0.4, 0, 1, 1) forwards; }
@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 disparador, 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-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;
}

/* ── (2) Vista "Flujo": 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; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   FLUJOS — ajustes del Constructor (2026-08-03, 2ª pasada)
   ═══════════════════════════════════════════════════════════════════════════ */

/* (1) La toolbar heredaba el `border-bottom` de `.lc-topbar` (bandeja de
   Livechat) y, al quitarle el padding, la línea quedaba pegada al buscador.
   Aquí la separación la da el margen, no una regla. */
.flx-sidebar .lc-topbar { border-bottom: 0; margin: 0 0 10px; padding: 0; }

/* (2) 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 {
  position: static;
  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": lienzo libre 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 / 22px 22px;
  /* `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;
}
/* 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;
}
/* Dos clases de arista, y la diferencia importa: `seq` es lo que pasa SIEMPRE
   —el paso siguiente— y `gate`/`pick` es lo que pasa SI se cumple algo. Va
   punteado porque una línea sólida hacia una rama se lee como «y después esto»,
   que es justo lo que no es. */
.flx-flowlinks line.is-gate,
.flx-flowlinks line.is-pick {
  stroke: var(--chart-3);
  stroke-dasharray: 6 5;
  opacity: 0.8;
}
/* El color base de la punta vive más abajo, junto al resto del lienzo. */
.flx-flowarrow.is-gate, .flx-flowarrow.is-pick { fill: var(--chart-3); opacity: 0.8; }

/* Leyenda del lienzo. Sin ella el punteado y el rombo son decoración: nadie
   adivina que una línea discontinua significa «solo si se cumple la regla». */
.flx-flow-leyenda {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  margin: -4px 0 10px;
  font-size: .68rem;
  color: var(--muted-2);
}
.flx-leg { display: inline-flex; align-items: center; gap: 6px; }
.flx-leg-line { width: 22px; height: 0; border-top: 2px solid var(--brand); opacity: .7; }
.flx-leg-line.is-gate { border-top-style: dashed; border-top-color: var(--chart-3); opacity: 1; }
.flx-leg-box { width: 13px; height: 13px; border-radius: 3px; border: 1px solid var(--border); }
.flx-leg-box.is-gate { border-color: var(--chart-3); border-left-width: 3px; }
.flx-leg-box.is-fin { border-style: dashed; border-color: var(--badge-success-fg); }
.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; }

/* ── Caja de BIFURCACIÓN ─────────────────────────────────────────────────────
   Una fase que parte el recorrido y una que no se pintaban EXACTAMENTE igual:
   la compuerta no aparecía por ninguna parte del lienzo. El borde izquierdo
   grueso es lo que las separa de un vistazo; el contenido de abajo dice según
   qué se parte y hacia dónde. */
.flx-node.is-gate {
  border-left: 3px solid var(--chart-3);
}
.flx-node-gate-ico {
  margin-left: auto;
  font-size: 15px;
  line-height: 1;
  color: var(--chart-3);
}
.flx-node-gate {
  margin-top: 8px;
  padding-top: 7px;
  border-top: 1px dashed var(--border);
}
.flx-node-gate-tit {
  font-size: .7rem;
  font-weight: 600;
  color: var(--chart-3);
}
.flx-node-gate-sub { font-size: .66rem; color: var(--muted-2); margin-top: 1px; }
.flx-node-gate-outs { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 5px; }
.flx-node-out {
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--control-bg);
  font-size: .65rem;
  font-weight: 600;
  color: var(--text);
}

/* Cinta de rama: dice QUIÉN recorre la caja. En el lienzo, una fase de rama y
   una del tronco eran indistinguibles, y eso es lo primero que hay que saber. */
.flx-node-rama {
  display: inline-block;
  margin-bottom: 5px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--control-bg);
  font-size: .63rem;
  font-weight: 600;
  color: var(--muted);
}
/* El color va en el borde y NUNCA solo: la caja lleva siempre el nombre de la
   rama escrito, para que el mapa se siga leyendo sin distinguir colores. */
.flx-node.is-rama { border-top-width: 3px; }
.flx-node.is-rama.r0 { border-top-color: var(--chart-1); }
.flx-node.is-rama.r1 { border-top-color: var(--chart-2); }
.flx-node.is-rama.r2 { border-top-color: var(--chart-3); }
.flx-node.is-rama.r3 { border-top-color: var(--chart-4); }
.flx-node.is-rama.r4 { border-top-color: var(--chart-5); }
.flx-node.is-rama.r5 { border-top-color: var(--chart-6); }

.flx-tag.is-fin { background: var(--badge-success-bg); color: var(--badge-success-fg); }

.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; }


/* ═══════════════════════════════════════════════════════════════════════════
   FLUJOS — palabras clave como badges y grupos (2026-08-03, 3ª pasada)
   ═══════════════════════════════════════════════════════════════════════════ */

/* 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); }
.flx-btn-ghost:disabled { opacity: .55; cursor: not-allowed; }

/* ── Documento JSON del flujo (importar/exportar todas las fases+ramas) ── */
.flx-doc-modal { max-width: 760px; width: 92vw; }
.flx-doc-help { margin: 0 0 12px; color: var(--muted); font-size: 12.5px; line-height: 1.5; }
.flx-doc-textarea {
  width: 100%; min-height: 260px; resize: vertical;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: 12.5px; line-height: 1.5; tab-size: 2; white-space: pre;
}
.flx-doc-parse-err {
  margin-top: 10px; padding: 8px 12px; border-radius: 9px;
  background: var(--badge-danger-bg); color: var(--badge-danger-fg);
  border: 1px solid var(--badge-danger-fg); font-size: 12.5px;
}
.flx-doc-plan {
  margin-top: 14px; padding: 12px 14px; border-radius: 12px;
  background: var(--surface-2); border: 1px solid var(--border);
}
.flx-doc-plan-head { font-size: 12.5px; color: var(--muted); margin-bottom: 10px; }
.flx-doc-plan-head b { color: var(--text-strong); }
.flx-doc-resumen { display: flex; flex-wrap: wrap; gap: 8px; }
.flx-doc-chip {
  display: inline-flex; align-items: center; padding: 3px 10px; border-radius: 999px;
  font-size: 12px; font-weight: 600;
  background: var(--badge-neutral-bg); color: var(--badge-neutral-fg);
}
.flx-doc-chip.is-crear   { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.flx-doc-chip.is-upd     { background: var(--badge-info-bg);    color: var(--badge-info-fg); }
.flx-doc-chip.is-ret     { background: var(--badge-danger-bg);  color: var(--badge-danger-fg); }
.flx-doc-chip.is-desact  { background: var(--badge-warn-bg);    color: var(--badge-warn-fg); }
.flx-doc-chip.is-reord   { background: var(--badge-purple-bg);  color: var(--badge-purple-fg); }
.flx-doc-block { margin-top: 12px; }
.flx-doc-block-title {
  font-size: 11.5px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em;
  color: var(--muted-2); margin-bottom: 6px;
}
.flx-doc-block ul { margin: 0; padding-left: 0; list-style: none; }
.flx-doc-block li { font-size: 12.5px; color: var(--text); line-height: 1.6; }
.flx-doc-errores li { color: var(--badge-danger-fg); }
.flx-doc-errores code, .flx-doc-acciones code {
  font-size: 11.5px; padding: 1px 5px; border-radius: 5px;
  background: var(--control-bg); color: var(--muted);
}
.flx-doc-avisos li { color: var(--badge-warn-fg); }
.flx-doc-acciones li { display: flex; align-items: center; gap: 8px; }
.flx-doc-acc-dot { width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; background: var(--muted-2); }
.flx-doc-acc-dot.is-crear      { background: var(--badge-success-fg); }
.flx-doc-acc-dot.is-actualizar { background: var(--badge-info-fg); }
.flx-doc-acc-dot.is-retirar    { background: var(--badge-danger-fg); }
.flx-doc-acc-dot.is-desactivar { background: var(--badge-warn-fg); }
.flx-doc-acc-tipo { font-weight: 600; text-transform: capitalize; }
.flx-doc-footer { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.flx-doc-footer-right { display: flex; align-items: center; gap: 10px; }

/* ── Drawer del asistente IA (chat del constructor de Flujos) ── */
.flx-btn-ia { color: var(--brand); border-color: var(--brand-soft-bg, var(--control-border)); }
.flx-btn-ia:hover { background: var(--brand-soft-bg); color: var(--brand-dark, var(--brand)); }

.flx-chat-backdrop { position: fixed; inset: 0; background: var(--scrim); z-index: 1400; }
.flx-chat-drawer {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 1401;
  width: min(440px, 96vw); display: flex; flex-direction: column;
  background: var(--surface-overlay); border-left: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
}
.flx-chat-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px; border-bottom: 1px solid var(--border); flex: 0 0 auto;
}
.flx-chat-title { font-weight: 700; color: var(--text-strong); }
.flx-chat-head-actions { display: flex; align-items: center; gap: 8px; }
.flx-chat-nuevo { padding: 4px 10px; font-size: 11.5px; }
.flx-chat-unavailable {
  margin: 12px 16px 0; padding: 10px 12px; border-radius: 10px; font-size: 12.5px;
  background: var(--badge-warn-bg); color: var(--badge-warn-fg);
  border: 1px solid var(--badge-warn-fg);
}
/* Aviso de apertura: ventana flotante CENTRADA sobre el chat, no una franja de
   lado a lado. El `box-shadow` gigante hace de velo — el split tiene
   `overflow:hidden`, así que se recorta a la caja del chat. */
.flx-chat-notice {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 3;
  width: min(420px, calc(100% - 48px)); max-height: calc(100% - 48px); overflow-y: auto;
  padding: 18px 20px; border-radius: 14px;
  background: var(--surface-overlay); border: 1px solid var(--border);
  box-shadow: var(--shadow-lg), 0 0 0 9999px var(--scrim);
}
.flx-chat-notice-title { font-weight: 700; color: var(--text-strong); margin-bottom: 8px; }
.flx-chat-notice-list { margin: 0 0 12px; padding-left: 18px; display: flex; flex-direction: column; gap: 7px; }
.flx-chat-notice-list li { font-size: 12.5px; line-height: 1.5; color: var(--text); }
.flx-chat-notice-ok { width: 100%; }
.flx-chat-body { flex: 1 1 auto; overflow-y: auto; padding: 16px; display: flex; flex-direction: column; gap: 12px; }
.flx-chat-empty { color: var(--muted); font-size: 13px; line-height: 1.6; text-align: center; margin: auto 8px; }

.flx-chat-msg { display: flex; flex-direction: column; gap: 6px; max-width: 90%; }
.flx-chat-msg.is-user { align-self: flex-end; align-items: flex-end; }
.flx-chat-msg.is-bot { align-self: flex-start; align-items: flex-start; }
.flx-chat-msg.is-sys { align-self: center; align-items: center; max-width: 96%; }
.flx-chat-bubble {
  padding: 9px 13px; border-radius: 14px; font-size: 13.5px; line-height: 1.5;
  white-space: pre-wrap; word-break: break-word;
}
.is-user .flx-chat-bubble { background: var(--brand); color: #fff; border-bottom-right-radius: 4px; }
.is-bot .flx-chat-bubble { background: var(--surface-2); color: var(--text); border: 1px solid var(--border); border-bottom-left-radius: 4px; }
.is-sys .flx-chat-bubble { background: transparent; color: var(--muted); font-size: 12px; font-style: italic; text-align: center; }
.flx-chat-tools { font-size: 11px; color: var(--muted-2); font-style: italic; }
.flx-chat-thinking { padding: 9px 13px; border-radius: 14px; background: var(--surface-2); color: var(--muted); font-size: 13px; }

.flx-chat-widget-btns { display: flex; gap: 8px; flex-wrap: wrap; }
.flx-chat-opciones { display: flex; flex-direction: column; gap: 6px; width: 100%; }
.flx-chat-opcion {
  text-align: left; padding: 9px 12px; border-radius: 10px; cursor: pointer;
  background: var(--control-bg); border: 1px solid var(--control-border); color: var(--text);
  display: flex; flex-direction: column; gap: 2px; font-family: inherit; transition: background .12s, border-color .12s;
}
.flx-chat-opcion:hover { background: var(--control-bg-hover); border-color: var(--brand); }
.flx-chat-opcion-t { font-weight: 600; font-size: 13px; }
.flx-chat-opcion-d { font-size: 12px; color: var(--muted); }

.flx-chat-preview {
  padding: 11px 13px; border-radius: 12px; background: var(--surface-2);
  border: 1px solid var(--border); border-left: 3px solid var(--brand); width: 100%;
}
.flx-chat-preview-head { font-weight: 600; color: var(--text-strong); font-size: 13.5px; display: flex; align-items: center; gap: 8px; }
.flx-chat-preview-obj { font-size: 12.5px; color: var(--text); margin-top: 4px; line-height: 1.5; }
.flx-chat-preview-meta { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 8px; font-size: 11.5px; color: var(--muted); }

.flx-chat-plan { width: 100%; margin-top: 4px; }
.flx-chat-plan-actions { display: flex; gap: 8px; margin-top: 12px; }

.flx-chat-input { flex: 0 0 auto; display: flex; gap: 8px; padding: 12px 16px; border-top: 1px solid var(--border); align-items: flex-end; }
.flx-chat-textarea { flex: 1 1 auto; resize: none; font-size: 13.5px; }
.flx-chat-send { flex: 0 0 auto; }

/* Grupo de palabras clave: acciones a la derecha y estado apagado. */
.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); }

/* Los tooltips dentro de un `label`/`h3` no deben empujar el texto. */
.form-label .info-tooltip-wrapper,
.kn-wizard-head h3 .info-tooltip-wrapper,
.kn-check .info-tooltip-wrapper { margin-left: 6px; vertical-align: middle; }


/* ═══════════════════════════════════════════════════════════════════════════
   FLUJOS — el lienzo como espacio de trabajo (2026-08-03, 4ª pasada)
   ═══════════════════════════════════════════════════════════════════════════ */

/* 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. */
.flx-flowcanvas {
  min-height: 560px;
  resize: vertical;             /* el usuario puede darse más alto si quiere */
  background-size: 24px 24px;
}
/* Barras de scroll discretas: el lienzo se desplaza cuando se arrastra una
   caja fuera de la vista, no como forma normal de navegarlo. */
.flx-flowcanvas { 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); }

/* Punta de flecha del conector: mismo color que la línea, sin borde. */
.flx-flowarrow { fill: var(--brand); opacity: 0.55; }

/* 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;
}


/* ═══════════════════════════════════════════════════════════════════════════
   FLUJOS — señales del arrastre en el lienzo (2026-08-03, 5ª pasada)
   Antes no había NADA: soltabas a ciegas y solo lo notabas por el resultado.
   ═══════════════════════════════════════════════════════════════════════════ */

/* 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; }


/* ═══════════════════════════════════════════════════════════════════════════
   FLUJOS — formularios de una pantalla con ajustes avanzados plegados
   ═══════════════════════════════════════════════════════════════════════════ */

/* Disclosure de "Ajustes avanzados": no es un botón de acción, así que no
   compite con Guardar. Deja claro que hay algo debajo sin llamar la atención. */
.flx-adv-toggle {
  align-self: flex-start;
  margin-top: 4px;
  padding: 6px 2px;
  border: 0;
  background: transparent;
  color: var(--muted);
  font-size: 12.5px;
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  transition: color .12s;
}
.flx-adv-toggle:hover { color: var(--brand); }

.flx-adv-box {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface-2);
}
/* Subtítulo dentro de avanzados (agrupa los topes de abandono). */
.flx-adv-sub {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted-2);
  padding-top: 4px;
  border-top: 1px solid var(--border);
}
.flx-adv-box .kn-form-group:first-child { margin-top: 0; }

/* La caja de palabras clave dentro del formulario de proceso hereda el mismo
   aspecto que la del formulario de grupos: es el mismo gesto. */
.kn-form-group > .flx-kwbox { margin-top: 2px; }


/* ═══════════════════════════════════════════════════════════════════════════
   FLUJOS — lienzo con envoltorio, menú ⋮ por caja y acuse del intercambio
   (2026-08-03, 6ª pasada)
   ═══════════════════════════════════════════════════════════════════════════ */

/* El scroll y el marco pasan al ENVOLTORIO. Antes scrolleaba el mismo elemento
   que pintaba la cuadrícula, y el fondo de un contenedor con scroll se queda
   en la parte visible: al desplazarse a la derecha las cajas aparecían fuera
   del espacio de trabajo, sobre el fondo del panel. */
.flx-flowwrap {
  position: relative;
  width: 100%;
  overflow: auto;
  min-height: 560px;
  resize: vertical;             /* el usuario puede darse más alto si quiere */
  border: 1px dashed var(--border);
  border-radius: 14px;
  /* El arrastre con el dedo es del lienzo, no del scroll del navegador. */
  touch-action: none;
  scrollbar-width: thin;
  scrollbar-color: transparent transparent;
}
.flx-flowwrap:hover { scrollbar-color: var(--control-border) transparent; }
.flx-flowwrap::-webkit-scrollbar { width: 8px; height: 8px; }
.flx-flowwrap::-webkit-scrollbar-thumb { background: transparent; border-radius: 8px; }
.flx-flowwrap:hover::-webkit-scrollbar-thumb { background: var(--control-border); }

/* El lienzo ya solo dibuja: crece con las cajas (ancho/alto en línea desde el
   componente) y nunca es más estrecho que su envoltorio. */
.flx-flowcanvas {
  overflow: visible;
  border: 0;
  border-radius: 0;
  resize: none;
  min-height: 0;
  min-width: 100%;
}
.flx-flowwrap:has(.flx-node--free.dragging) { cursor: grabbing; }

/* ── Menú ⋮ dentro de una caja del lienzo ───────────────────────────────── */
.flx-node-menu {
  position: absolute;
  top: 6px;
  right: 6px;
  z-index: 5;
}
/* Deja sitio al ⋮ para que no se le monte encima al nombre de la fase. */
.flx-node--free .flx-node-head { padding-right: 26px; }
/* Discreto en reposo; se afirma al pasar por encima de la caja. */
.flx-node-menu .mm-dots { opacity: .45; cursor: pointer; }
.flx-node--free:hover .flx-node-menu .mm-dots,
.flx-node-menu .mm-dots:hover { opacity: 1; }
/* El menú tiene que quedar por encima de SU PROPIO backdrop (`.flx-menu-backdrop`,
   z-index 59), que es el que cierra el desplegable al pulsar fuera. Con un valor
   por debajo, el backdrop —transparente y a pantalla completa— se queda delante
   de las opciones: el menú se ve, pero los clics de "Editar" y "Eliminar" caen en
   el fondo y solo lo cierran. El valor base de `.mm-menu-pop` (60) ya lo resuelve;
   aquí solo hace falta no bajarlo. */
.flx-node-menu .mm-menu-pop { z-index: 61; }

/* Además hay que levantar la CAJA. `.flx-node--free` tiene z-index propio, así que
   crea contexto de apilado: sin esto, el menú de una caja se dibuja por debajo de
   las cajas vecinas y de la que esté desplegada (z-index 2), y las de al lado
   tapan las opciones aunque el clic sí llegue. */
.flx-node--free:has(.mm-menu-pop) { z-index: 8; }

/* ── Acuse del intercambio ──────────────────────────────────────────────────
   Al soltar, las dos cajas cambian de contenido y se separan un poco. Sin este
   destello el gesto terminaba en una escena idéntica a la de antes y no había
   forma de saber que había pasado algo. */
.flx-node--free.just-swapped {
  /* El desplazamiento se anima para que se vea el "se apartan", no un salto. */
  transition: left .28s cubic-bezier(.22,.61,.36,1),
              top  .28s cubic-bezier(.22,.61,.36,1);
  animation: flx-swap-flash .9s ease-out 1;
}
@keyframes flx-swap-flash {
  0%   { border-color: var(--brand); box-shadow: 0 0 0 4px var(--brand-soft-bg), var(--shadow-md); }
  60%  { border-color: var(--brand); box-shadow: 0 0 0 4px var(--brand-soft-bg), var(--shadow-md); }
  100% { border-color: var(--border); box-shadow: none; }
}
/* Respeta a quien pide menos movimiento: el color sigue avisando, el
   desplazamiento no se anima. */
@media (prefers-reduced-motion: reduce) {
  .flx-node--free.just-swapped { transition: none; }
}


/* ═══════════════════════════════════════════════════════════════════════════
   FLUJOS — Auditoría con toolbar estándar y subtabs (2026-08-03, 7ª pasada)
   ═══════════════════════════════════════════════════════════════════════════ */

/* Las subtabs usan el cromo compartido `.cc-subtabs` de Centro de Control; aquí
   solo hace falta separarlas de la toolbar que va justo debajo. */
.metrics-content > .cc-subtabs { margin-bottom: 12px; }

/* Las dos fechas del popover de filtros, en una línea con su flecha. */
.flx-daterange {
  display: flex;
  align-items: center;
  gap: 8px;
}
.flx-daterange .crm-input { flex: 1 1 0; min-width: 0; }

/* Etiqueta pequeña pegada a un dato dentro de una celda (fase desactivada,
   recordatorios con error). No es un badge de estado de la fila. */
.flx-tag-inline {
  margin-left: 6px;
  font-size: 10px;
  vertical-align: middle;
}

/* ── Bitácora ──────────────────────────────────────────────────────────────
   Es la tabla más densa del módulo: muchas filas cortas. La fecha en tabular
   para que las columnas no bailen, y el detalle JSON acotado para que una
   entrada larga no estire la tabla entera. */
.flx-log-when {
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
  color: var(--muted);
  font-size: 12px;
}
.flx-log-detail {
  max-width: 340px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px;
  color: var(--muted);
}

/* La nota de alcance va pegada a la toolbar: dice qué flujo y qué periodo se
   está mirando, y eso manda sobre TODOS los bloques de la pestaña. */
.metrics-content > .flx-rep-note { margin: 10px 0 16px; }

/* El botón de exportar de Tickets dentro de la toolbar estándar: el ancla del
   desplegable tiene que ser el contenedor, no la barra entera. */
.tb-actions .tickets-export { position: relative; }


/* ═══════════════════════════════════════════════════════════════════════════
   FLUJOS — Personas: elección de vista, y paginación de las tablas largas
   (2026-08-03, 8ª pasada)
   ═══════════════════════════════════════════════════════════════════════════ */

/* Dos tarjetas grandes: "quién se quedó por el camino" y "todos los contactos".
   Son preguntas distintas y una necesita elegir flujo, así que se preguntan
   antes de traer nada en vez de apilar las dos tablas. */
/* Flex centrado, NO grid de 1fr: con `1fr` las dos tarjetas se estiran hasta
   el ancho del panel y quedan como dos franjas. Aquí el ancho lo fija la
   tarjeta y el hueco sobrante se reparte a los lados. */
.flx-pick-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 16px;
  margin-top: 24px;
}
.flx-pick-card {
  flex: 0 0 auto;
  width: 300px;
  max-width: 100%;
  min-height: 132px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 8px;
  padding: 22px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--surface);
  text-align: left;
  font-family: inherit;
  cursor: pointer;
  transition: border-color .14s, box-shadow .14s, transform .14s;
}
.flx-pick-card:hover {
  border-color: var(--brand);
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}
/* El detalle largo vive en el tooltip del título: la tarjeta es una elección
   entre dos, no un sitio donde leer dos párrafos. */
.flx-pick-title {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 15px;
  font-weight: 700;
  color: var(--text-strong);
}
/* Condición de uso de la tarjeta (p. ej. "hay que elegir un flujo"): se lee
   ANTES de pulsar, no después en forma de pantalla vacía. */
.flx-pick-meta {
  margin-top: auto;
  padding-top: 6px;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted-2);
}

/* Elegir flujo antes del listado. Caja centrada y estrecha: es una decisión
   de una sola cosa, no una pantalla que deba ocupar todo el ancho. */
.flx-choose-flow {
  width: 100%;
  max-width: 420px;
  margin: 24px auto 0;
  padding: 20px;
  border: 1px dashed var(--border);
  border-radius: 14px;
  background: var(--surface-2);
}
.flx-choose-flow-title {
  margin: 0 0 12px;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--text-strong);
}
/* Buscador propio, dentro de la caja: filtra la lista de flujos por nombre.
   No es el buscador de la toolbar (ese busca filas de una tabla que aquí
   todavía no existe). */
.flx-choose-flow-search { width: 100%; margin-bottom: 10px; }
/* Lista vertical: los flujos se leen en columna, uno debajo de otro. Antes
   era una fila de píldoras que envolvía, y con varios flujos había que
   rastrear el nombre en zigzag. */
.flx-choose-flow-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 320px;
  overflow-y: auto;
}
.flx-choose-flow-item {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px;
  border: 1px solid var(--control-border);
  border-radius: 10px;
  background: var(--control-bg);
  color: var(--text);
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
  transition: border-color .12s, background .12s;
}
.flx-choose-flow-item:hover { border-color: var(--brand); background: var(--control-bg-hover); }

/* La caja pasó de ser el paso previo de UNA tabla a ser la puerta de entrada de
   toda la pestaña Auditoría, así que se ensancha y explica POR QUÉ hay que
   elegir: sin el motivo, la pantalla se lee como una pared. */
.flx-choose-flow { max-width: 520px; text-align: center; }
.flx-choose-flow-ico { font-size: 2rem; line-height: 1; margin-bottom: 8px; }
.flx-choose-flow-sub {
  margin: 0 0 14px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--muted);
}
/* El buscador y la lista vuelven a alinearse a la izquierda: centrar nombres de
   longitud distinta obliga a buscar el principio de cada uno en un sitio. */
.flx-choose-flow-search, .flx-choose-flow-list { text-align: left; }

/* ── Barra de ALCANCE de Auditoría ───────────────────────────────────────────
   Flujo y periodo mandan sobre las seis subpestañas, así que van a la vista y
   no dentro del desplegable de filtros de la toolbar, donde quedaban al mismo
   nivel que un filtro que solo afecta a una tabla. */
.flx-aud-scope {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 10px 18px;
  margin-bottom: 12px;
  padding: 10px 12px;
  border: 1px solid var(--border-soft);
  border-radius: 12px;
  background: var(--surface-2);
}
.flx-aud-scope-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.flx-aud-scope-lbl {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--muted-2);
}
/* El selector de flujo es lo que más se usa de la barra y el nombre de un
   proceso es largo: se le da sitio antes que a las fechas, que son fijas. */
.flx-aud-scope-item:first-child .crm-input { min-width: 240px; }
/* La casilla de «Alcance» tiene que alinearse con la base de los <select> de al
   lado, no con la etiqueta: sin esto sube y la fila se ve escalonada. */
.flx-aud-scope-check {
  display: flex;
  align-items: center;
  gap: 6px;
  min-height: 34px;
  margin: 0;
  font-size: 12.5px;
  white-space: nowrap;
}

/* Filtro de persona de la Bitácora. Pastilla y no <select>: se llega a ella
   desde el listado de Personas, y un desplegable con todos los contactos del
   proceso sería una lista larguísima para algo que casi nunca se elige aquí. */
.flx-aud-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 34px;
  padding: 0 6px 0 12px;
  border-radius: 999px;
  background: var(--brand-soft-bg);
  color: var(--brand-soft-fg);
  font-size: 12.5px;
  font-weight: 600;
}
.flx-aud-pill-x {
  border: 0;
  background: transparent;
  color: inherit;
  font-size: 15px;
  line-height: 1;
  padding: 2px 6px;
  border-radius: 999px;
  cursor: pointer;
  opacity: .7;
}
.flx-aud-pill-x:hover { opacity: 1; background: var(--control-bg-hover); }

/* «Ver ›» de cada fila del listado: el único salto entre subpestañas. Discreto
   —es una columna más, no una acción destacada— pero con afordancia de botón. */
.flx-ver-bitacora {
  padding: 3px 10px;
  border: 1px solid var(--control-border);
  border-radius: 999px;
  background: var(--control-bg);
  color: var(--text);
  font-family: inherit;
  font-size: 11.5px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: border-color .12s, background .12s;
}
.flx-ver-bitacora:hover { border-color: var(--brand); background: var(--control-bg-hover); }

/* ── Paginador de las tablas largas ─────────────────────────────────────────
   El rango y el total salen de la BASE (`COUNT(*) OVER ()`), así que dice
   "51–100 de 4.312" de verdad, no "de las que traje". */
.flx-pager {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 12px;
  flex-wrap: wrap;
  padding: 12px 2px 0;
}
.flx-pager-btn {
  padding: 7px 16px;
  border: 1px solid var(--control-border);
  border-radius: 999px;
  background: var(--control-bg);
  color: var(--text);
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
  transition: border-color .12s, background .12s;
}
.flx-pager-btn:hover:not(:disabled) { border-color: var(--brand); background: var(--control-bg-hover); }
/* Deshabilitado sin desaparecer: los extremos del recorrido deben seguir
   ocupando su sitio para que la barra no salte al llegar a la última página. */
.flx-pager-btn:disabled { opacity: .4; cursor: default; }
.flx-pager-info {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* Aviso de que el buscador acota la tabla pero no las cifras agregadas. */
.flx-scope-warn {
  margin: -8px 0 14px;
  font-size: 12px;
  color: var(--badge-warn-fg);
  background: var(--badge-warn-bg);
  padding: 7px 12px;
  border-radius: 9px;
}

/* ═══════════════════════════════════════════════════════════════════════════
   FLUJOS — casilla destacada del formulario de paso (2026-08-04, 9ª pasada)
   ═══════════════════════════════════════════════════════════════════════════ */

/* "Con este paso el proceso termina" vive FUERA de «Ajustes avanzados»: no es
   un matiz, es lo que hace que el flujo pueda cerrarse. Se le da caja propia
   para que no se lea como una nota al pie del bloque de objetivos. */
.kn-check.flx-check-main {
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface-2);
  font-weight: 600;
  color: var(--text-strong);
}


/* ══════════════════════════════════════════════════════════════════════════
   E-commerce · Categorías y carga masiva del catálogo
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Selector de categoría (components/category_select.rs) ────────────────
   El CAMPO hereda el chasis de `.idv-select`; el PANEL no puede: vive dentro
   del drawer de producto, que recorta con overflow y tiene su propio z-index,
   así que se monta en un Portal colgado del <body> con coordenadas fijas
   calculadas desde el campo. */
.ec-cat-panel {
  position: fixed;
  z-index: 2501;                 /* por encima de CUALQUIER modal o drawer del módulo */
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px;                  /* mismo respiro que `.idv-select-panel` */
  box-sizing: border-box;
  max-height: 320px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--surface-overlay);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.ec-cat-panel .idv-select-list { overflow-y: auto; }
/* Capa de descarte del panel: justo POR DEBAJO de él y por encima del backdrop del
   modal de producto (2000), que era quien se comía el clic. */
.ec-cat-dismiss {
  position: fixed; inset: 0; z-index: 2500;
  background: transparent; border: none; padding: 0;
}
.ec-cat-opt--raiz .idv-opt-label { font-weight: 600; color: var(--text-strong); }
.ec-cat-opt--hija { padding-left: 26px; }
.ec-cat-opt--hija .idv-opt-label::before {
  content: "└ ";
  color: var(--muted-2);
}
/* Categoría padre mostrada solo para dar contexto a una subcategoría que sí
   coincidió con la búsqueda: se ve, pero no se puede elegir. */
.ec-cat-panel .idv-select-opt.is-context {
  opacity: 0.6;
  cursor: default;
  background: transparent;
}
.ec-cat-panel .idv-select-opt.is-context:hover { background: transparent; }
.ec-cat-empty { color: var(--muted); font-style: italic; }
.ec-cat-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 6px;
  border-top: 1px solid var(--border-soft);
}
.ec-cat-pager-info { font-size: 0.78rem; color: var(--muted); }

/* ── Celda «Categoría» de la tabla de productos ───────────────────────────── */
.ec-cat-cell { display: inline-flex; align-items: center; gap: 4px; }
.ec-cat-raiz { color: var(--muted); }
.ec-cat-sep { color: var(--muted-2); }

/* ── Gestor del árbol (Configuración › Productos) ─────────────────────────── */
.ec-cat-manager { display: flex; flex-direction: column; gap: 10px; }
/* Buscador pegado a la izquierda y botón a la derecha. El buscador NO se estira:
   el árbol no necesita una barra de ancho completo. */
.ec-cat-bar { display: flex; align-items: center; gap: 8px; }
.ec-cat-search { width: 240px; max-width: 100%; flex: 0 0 auto; }
.ec-cat-bar > .pg-btn { margin-left: auto; }
.ec-cat-tree {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface-2);
  overflow: hidden;
}
.ec-cat-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
}
.ec-cat-row + .ec-cat-row { border-top: 1px solid var(--border-soft); }
.ec-cat-row--hija { padding-left: 28px; }
/* Fila de contexto: la categoría padre de una subcategoría encontrada al buscar. */
.ec-cat-row--ctx { opacity: 0.65; }
.ec-cat-bullet { color: var(--muted-2); font-size: 0.75rem; flex-shrink: 0; }
.ec-cat-name { color: var(--text-strong); font-weight: 500; }
.ec-cat-row--hija .ec-cat-name { font-weight: 400; }
/* Número de productos de la fila: empuja las acciones al extremo derecho. */
.ec-cat-count {
  margin-left: auto;
  min-width: 26px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--badge-neutral-bg);
  color: var(--badge-neutral-fg);
  font-size: 0.72rem;
  text-align: center;
}
.ec-cat-actions { display: flex; gap: 4px; flex-shrink: 0; }
/* Popover de alta/renombrado (Portal). Una fila nueva NO aparece en el árbol
   hasta que la categoría existe de verdad en la base. */
.ec-cat-pop { width: 260px; }
.ec-cat-pop-title { font-weight: 600; color: var(--text-strong); font-size: 0.85rem; }

/* ── Carga masiva ─────────────────────────────────────────────────────────── */
.ec-bulk-card { width: min(760px, 94vw); }
.ec-bulk-body {
  padding: 14px 18px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  max-height: 68vh;
  overflow-y: auto;
}
.ec-bulk-steps { display: flex; flex-direction: column; gap: 16px; }
.ec-bulk-step { display: flex; flex-direction: column; gap: 8px; }
.ec-bulk-step-title {
  display: flex;
  align-items: center;
  gap: 8px;
  font-weight: 600;
  color: var(--text-strong);
}
/* Número del paso en pastilla: sustituye a la lista numerada y deja el título
   alineado con su tooltip. */
.ec-bulk-step-n {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 999px;
  background: var(--brand-dark);
  color: #fff;
  font-size: 0.72rem;
  flex-shrink: 0;
}
.ec-bulk-dl { display: flex; gap: 8px; }
.ec-bulk-summary {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border-soft);
}
.ec-bulk-delete {
  padding: 8px 10px;
  border: 1px solid var(--badge-danger-fg);
  border-radius: 10px;
  background: var(--badge-danger-bg);
}

/* Pestañas del resumen. Llevan el color del tipo y su propio contador: una fila
   de badges encima repetía exactamente la misma información. */
.ec-bulk-tabs { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.ec-bulk-tab {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: var(--control-bg);
  color: var(--muted);
  font-size: 0.82rem;
  font-weight: 500;
  cursor: pointer;
  transition: background .15s ease, color .15s ease, border-color .15s ease;
}
.ec-bulk-tab:hover { background: var(--control-bg-hover); }
.ec-bulk-tab-n {
  min-width: 20px;
  padding: 0 6px;
  border-radius: 999px;
  background: var(--surface-3);
  color: var(--text-strong);
  font-size: 0.76rem;
  font-weight: 700;
  text-align: center;
}
/* Activa: el color del tipo pasa al fondo y el contador se invierte para que
   siga leyéndose (es el dato importante de la pestaña). */
.ec-bulk-tab--new.is-active { background: var(--badge-success-bg); color: var(--badge-success-fg); border-color: var(--badge-success-fg); }
.ec-bulk-tab--upd.is-active { background: var(--badge-info-bg);    color: var(--badge-info-fg);    border-color: var(--badge-info-fg); }
.ec-bulk-tab--del.is-active { background: var(--badge-danger-bg);  color: var(--badge-danger-fg);  border-color: var(--badge-danger-fg); }
.ec-bulk-tab--err.is-active { background: var(--badge-warn-bg);    color: var(--badge-warn-fg);    border-color: var(--badge-warn-fg); }
.ec-bulk-tab--new .ec-bulk-tab-n { color: var(--badge-success-fg); }
.ec-bulk-tab--upd .ec-bulk-tab-n { color: var(--badge-info-fg); }
.ec-bulk-tab--del .ec-bulk-tab-n { color: var(--badge-danger-fg); }
.ec-bulk-tab--err .ec-bulk-tab-n { color: var(--badge-warn-fg); }
.ec-bulk-tab.is-active .ec-bulk-tab-n { background: var(--surface-overlay); }
.ec-bulk-nochange { margin-left: auto; font-size: 0.78rem; color: var(--muted-2); }

.ec-bulk-list {
  max-height: 240px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface-2);
  padding: 8px 10px;
}
.ec-bulk-list ul { margin: 0; padding-left: 16px; display: flex; flex-direction: column; gap: 6px; }
.ec-bulk-list li { font-size: 0.84rem; }
.ec-bulk-diff { color: var(--muted); font-size: 0.78rem; margin-top: 2px; }

/* Aviso inline de consecuencia (borrados, filas con error). */
.ec-warn { color: var(--badge-danger-fg); font-weight: 500; }

/* ── Centro de Control → Panel → Asistente (§4) ─────────────────────────────── */
.assistant-cards { display: flex; flex-direction: column; gap: 20px; }
.assistant-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 14px; padding: 20px 22px;
}
.assistant-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.assistant-card-title { margin: 0 0 4px; font-size: 1.15rem; color: var(--text-strong); }
.assistant-card-desc { margin: 0; color: var(--muted); font-size: 0.9rem; max-width: 62ch; }
.assistant-motivo {
  margin: 10px 0 0; padding: 8px 12px; border-radius: 8px; font-size: 0.85rem;
  background: var(--badge-warn-bg); color: var(--badge-warn-fg);
}
.assistant-section { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--border-soft); }
.assistant-section-label {
  display: block; font-size: 0.8rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.03em; color: var(--muted-2); margin-bottom: 8px;
}
.assistant-scope { color: var(--text); font-size: 0.9rem; }
.assistant-scope strong { color: var(--text-strong); }

.assistant-caps { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 18px; margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--border-soft); }
.assistant-list { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 4px; }
.assistant-list li { font-size: 0.88rem; color: var(--text); }
.assistant-list-ok li::marker { content: "✓  "; color: var(--badge-success-fg); }
.assistant-list-no li::marker { content: "✕  "; color: var(--badge-warn-fg); }

.assistant-model-editor { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.assistant-provider-tag {
  font-size: 0.8rem; padding: 3px 10px; border-radius: 999px;
  background: var(--brand-soft-bg); color: var(--brand-soft-fg); font-weight: 600;
}
.assistant-model-row { display: flex; align-items: center; gap: 10px; }
.assistant-model-current { display: flex; flex-direction: column; }
.assistant-model-name {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 0.9rem;
  color: var(--text-strong); background: var(--surface-2); padding: 4px 10px; border-radius: 6px;
}
.assistant-model-editor .form-input { max-width: 380px; }

.assistant-key-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.assistant-key-provider { max-width: 170px; }
.assistant-key-row .form-input[type="password"] { flex: 1; min-width: 220px; }

.assistant-tools-table { width: 100%; }
.assistant-tool-desc { color: var(--muted); font-size: 0.85rem; max-width: 40ch; }
.assistant-tools-table code {
  font-size: 0.82rem; background: var(--surface-2); padding: 2px 6px; border-radius: 5px; color: var(--text-strong);
}

.assistant-prompt-details { margin-top: 4px; }
.assistant-prompt-details summary { cursor: pointer; color: var(--brand); font-size: 0.88rem; }
.assistant-prompt-meta { font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--muted); }
.assistant-prompt {
  margin: 10px 0 0; padding: 14px 16px; border-radius: 10px; max-height: 340px; overflow: auto;
  background: var(--surface-2); border: 1px solid var(--border-soft);
  color: var(--text); font-size: 0.82rem; line-height: 1.5; white-space: pre-wrap; word-break: break-word;
}

.assistant-consumo { display: flex; gap: 26px; flex-wrap: wrap; }
.assistant-kpi { display: flex; flex-direction: column; }
.assistant-kpi-num { font-size: 1.5rem; font-weight: 700; color: var(--text-strong); }
.assistant-kpi-lbl { font-size: 0.8rem; color: var(--muted); }

/* ── Asistentes: LISTADO (tarjetas / lista) ──────────────────────────────────
   La vista de entrada ya no es un asistente sino el conjunto: una tarjeta por
   asistente con lo mínimo para elegir (nombre, descripción, módulo, estado).
   `auto-fill` a propósito: con un solo asistente la tarjeta conserva su ancho
   de tarjeta en vez de estirarse a todo el módulo. */
.asst-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 290px));
  gap: 14px; margin-top: 16px;
}
/* Tarjeta compacta: 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.
   Sin `aspect-ratio`: la altura la marca el contenido, así no queda un hueco
   muerto en el centro; el ancho lo acota la rejilla. */
.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, ancladas abajo a la izquierda: nunca una
   debajo de otra. Si el nombre del 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 .badge { flex: 0 0 auto; font-size: 0.7rem; padding: 2px 8px; }
.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;
}

.asst-list { display: flex; flex-direction: column; gap: 8px; margin-top: 16px; }
.asst-row {
  display: flex; align-items: center; gap: 14px; cursor: pointer;
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  padding: 12px 16px;
  transition: transform 0.16s ease, box-shadow 0.16s ease, border-color 0.16s ease;
}
.asst-row:hover { transform: translateY(-2px); box-shadow: var(--shadow-sm); border-color: var(--brand); }
.asst-row-name { font-weight: 600; color: var(--text-strong); flex: 0 0 auto; }
.asst-row-desc {
  flex: 1; min-width: 0; font-size: 0.85rem; color: var(--muted);
  white-space: nowrap; overflow: hidden;
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 48px), transparent 100%);
          mask-image: linear-gradient(90deg, #000 calc(100% - 48px), transparent 100%);
}

/* Acción de módulo bloqueada (crear asistentes aún no existe). El `title` y el
   cursor viven en el envoltorio: un <button disabled> no dispara ninguno. */
.asst-locked-wrap { display: inline-flex; cursor: not-allowed; }
.asst-btn-locked { pointer-events: none; opacity: 0.45; filter: grayscale(1); }

/* ── Asistentes: DETALLE ──────────────────────────────────────────────────
   Jerarquía en tres escalones y nada más: (1) volver, (2) identidad —quién es
   este asistente—, (3) cuatro secciones cerradas con su resumen. Al entrar no
   hay ningún cuerpo abierto: se elige qué mirar en vez de recibirlo todo. */
.asst-detail { display: block; }
.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: separadas, no apiladas
   contra una línea. */
.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. Sin máscara —
   degradaba el final aunque el texto cupiera entero y se leía como cortado. */
.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; }

/* Dentro de una sección: etiqueta pequeña arriba, valor debajo. 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); }

.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-head .assistant-prompt-meta { font-size: 0.78rem; }
.asst-prompt-block .assistant-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); }
/* Segmented archivo/vista previa: mismo control que el de la toolbar, en pequeño. */
.asst-seg { margin-left: 4px; }
.asst-seg .tb-viewseg-btn { width: 26px; height: 26px; }

/* Vista previa del system prompt: el Markdown ya aplicado dentro de 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, monospace; font-size: 0.82em;
  background: var(--surface-3, 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); }

.asst-prompt-modal { display: flex; flex-direction: column; }
.asst-prompt-full { max-height: 72vh; margin: 0 22px 20px; }

/* 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; }

/* ── Chat del asistente de Flujos: vista PARTIDA (estado en vivo + chat, §operaciones) ── */
.flx-chat-split {
  position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 1401;
  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);
}
/* El chat es el protagonista: ocupa el ancho entero del split. El panel de fases
   entra por la derecha solo cuando se pide (cerrado por defecto). */
.flx-chat-drawer {
  position: relative; top: auto; right: auto; bottom: auto; z-index: auto;
  width: auto; box-shadow: none; border-left: none;
  flex: 1 1 auto; min-width: 0;
}
/* Colapsa animando `flex-basis`: el panel 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. */
.flx-chat-live {
  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;
}
.flx-chat-live.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. */
.flx-chat-live > * { flex: 0 0 auto; width: 360px; }
.flx-chat-live > .flx-live-body { flex: 1 1 auto; }
.flx-live-toggle { padding: 4px 10px; font-size: 11.5px; }
.flx-live-toggle.is-active { background: var(--brand-soft-bg); color: var(--brand-soft-fg); border-color: transparent; }
.flx-live-head {
  flex: 0 0 auto; padding: 14px 16px; border-bottom: 1px solid var(--border);
  display: flex; align-items: flex-start; justify-content: space-between; gap: 10px;
}
.flx-live-titlewrap { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; min-width: 0; }
.flx-live-title { font-weight: 700; color: var(--text-strong); font-size: 15px; }
.flx-live-badge { font-size: 11px; padding: 2px 8px; border-radius: 999px; font-weight: 600; }
.flx-live-badge.is-on { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.flx-live-badge.is-draft { background: var(--badge-neutral-bg); color: var(--badge-neutral-fg); }
.flx-live-body { flex: 1 1 auto; overflow-y: auto; padding: 14px 16px; }
.flx-live-empty { color: var(--muted); font-size: 13px; text-align: center; margin-top: 24px; line-height: 1.6; }
.flx-live-muted { color: var(--muted); font-size: 12.5px; }
.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-tag { font-size: 10.5px; padding: 1px 7px; border-radius: 999px; background: var(--badge-neutral-bg); color: var(--badge-neutral-fg); }
.flx-live-fase-obj { margin-top: 6px; font-size: 12.5px; color: var(--text); line-height: 1.45; }

/* Tarjeta de operación propuesta por el asistente (crear/editar/eliminar/reordenar). */
.flx-chat-op { background: var(--surface-2); border: 1px solid var(--border); border-radius: 12px; padding: 12px; margin-top: 4px; }
.flx-chat-op-head { font-weight: 700; color: var(--text-strong); font-size: 13px; }
.flx-chat-op-resumen { margin-top: 4px; font-size: 12.5px; color: var(--text); line-height: 1.45; }
.flx-chat-op-detalle { margin: 8px 0 0; padding-left: 18px; display: flex; flex-direction: column; gap: 3px; }
.flx-chat-op-detalle li { font-size: 12px; color: var(--muted); }
.flx-chat-op-actions { display: flex; gap: 8px; margin-top: 10px; }
.flx-chat-op-done { margin-top: 8px; font-size: 12.5px; font-weight: 600; color: var(--badge-success-fg); }

@media (max-width: 860px) {
  .flx-chat-split { flex-direction: column; width: 96vw; height: 92vh; }
  /* En vertical el panel va DEBAJO del chat: colapsa en alto, no en ancho. */
  .flx-chat-live { width: auto; border-left: none; border-top: 1px solid transparent; }
  .flx-chat-live > * { width: auto; }
  .flx-chat-live.is-open { flex-basis: 45%; border-left-color: transparent; border-top-color: var(--border); }
  .flx-chat-drawer { flex: 1 1 auto; }
}

/* Vista "Flujo" del panel en vivo del chat: cadena vertical de nodos con conectores. */
.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);
}
/* La tarjeta entera abre la fase. */
.flx-live-node { cursor: pointer; transition: border-color 0.16s ease, box-shadow 0.16s ease; }
.flx-live-node:hover { border-color: var(--brand); }
.flx-live-node-head { display: flex; align-items: center; gap: 8px; width: 100%; }
.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-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-node.is-open { border-color: var(--brand); box-shadow: var(--shadow-md); }
.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-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.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-arrow { text-align: center; color: var(--brand); font-size: 16px; line-height: 1.2; margin: 3px 0; }

/* Lista de operaciones propuestas (varias tarjetas) + «Aplicar todo». */
.flx-chat-ops { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; }
.flx-chat-ops-all { display: flex; justify-content: flex-end; }
.flx-chat-op-dismiss { margin-top: 8px; font-size: 12.5px; color: var(--muted); font-style: italic; text-decoration: line-through; }

/* ══════════════════════════════════════════════════════════════════════════
   Bitácora de Flujos — línea de tiempo legible
   ══════════════════════════════════════════════════════════════════════════
   Rejilla de tres columnas (cuándo · llave · texto) para que la del medio se lea
   como una línea de tiempo vertical.

   La LLAVE es lo que hace el trabajo: los eventos que el agente marcó en una
   misma acción caen en el mismo segundo, y presentarlos como cuatro filas
   sueltas hace pensar que dudó cuatro veces. Agrupados bajo una llave con
   «N a la vez», se leen como UN movimiento.

   Todo con tokens: nada de hex literales (ver CLAUDE.md, «Theming»). */

.flx-bit { display: flex; flex-direction: column; gap: 2px; }

.flx-bit-dia {
    margin: 18px 0 6px;
    font-size: .78rem;
    font-weight: 600;
    color: var(--muted);
    letter-spacing: .04em;
}
.flx-bit-dia:first-child { margin-top: 4px; }

.flx-bit-grupo {
    display: grid;
    grid-template-columns: 92px 14px 1fr;
    align-items: stretch;
    padding: 2px 0;
}

.flx-bit-cuando {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    justify-content: center;
    padding-right: 10px;
    gap: 2px;
}
.flx-bit-hora {
    font-variant-numeric: tabular-nums;   /* las horas se alinean en columna */
    font-size: .82rem;
    color: var(--muted);
}
/* Solo aparece cuando hay más de un evento: en un grupo de uno no aporta nada
   y añadiría una línea a cada fila. */
.flx-bit-juntos {
    font-size: .68rem;
    color: var(--brand);
    white-space: nowrap;
}

/* La llave se dibuja SOLO en los grupos de más de uno (`is-multi`). En un grupo
   suelto una línea vertical sugeriría una agrupación que no existe. */
.flx-bit-llave { position: relative; }
.flx-bit-grupo.is-multi .flx-bit-llave::before {
    content: "";
    position: absolute;
    left: 5px;
    top: 10px;
    bottom: 10px;
    width: 2px;
    border-radius: 1px;
    background: var(--brand);
    opacity: .45;
}

.flx-bit-eventos { display: flex; flex-direction: column; gap: 6px; padding: 4px 0; }

.flx-bit-ev { display: flex; align-items: flex-start; gap: 8px; }

/* El icono va coloreado por TONO para ver de un vistazo si la conversación fue
   bien sin leer nada. */
.flx-bit-icono {
    flex: 0 0 auto;
    width: 20px; height: 20px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%;
    font-size: .72rem;
    line-height: 1;
}
.flx-bit-icono.is-ok   { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.flx-bit-icono.is-warn { background: var(--badge-warn-bg);    color: var(--badge-warn-fg); }
.flx-bit-icono.is-bad  { background: var(--badge-danger-bg);  color: var(--badge-danger-fg); }
.flx-bit-icono.is-info { background: var(--badge-info-bg);    color: var(--badge-info-fg); }

.flx-bit-txt { min-width: 0; }
.flx-bit-frase {
    color: var(--text-strong);
    font-size: .88rem;
    line-height: 1.35;
}
.flx-bit-quien { color: var(--muted); font-size: .76rem; }
/* De quién es el hecho. Solo sale SIN filtro de persona: ahí la línea de tiempo
   mezcla a todo el mundo y sin el nombre es una lista de cosas que le pasaron a
   alguien. Con la persona ya elegida se repetiría en cada línea sin añadir nada. */
.flx-bit-contacto { color: var(--text-strong); font-weight: 600; }
.flx-bit-fase { color: var(--muted-2); }

.flx-bit-toggle { margin-left: auto; }

@media (max-width: 640px) {
    /* Por debajo de este ancho la columna de la hora se come el texto. Se apila y
       la llave desaparece: el rótulo «N a la vez» sigue diciendo lo mismo. */
    .flx-bit-grupo { grid-template-columns: 1fr; }
    .flx-bit-cuando { flex-direction: row; align-items: baseline; justify-content: flex-start; gap: 8px; }
    .flx-bit-llave { display: none; }
}

/* ── Constructor de Flujos: capacidades por fase ────────────────────────────
   Ayudas y selectores añadidos con las herramientas por fase, la compuerta de
   enrutamiento, los canales y la derivación entre procesos. Solo tokens. */

/* Párrafo de ayuda bajo un control. Existe porque varias de estas opciones
   NO hacen lo que su etiqueta sugiere a primera vista: «Activable por el
   agente» parecía una preferencia de presentación y en realidad el motor
   rechaza el arranque; una casilla sin esta explicación se marca al revés. */
.flx-hint {
    margin: 6px 0 0;
    font-size: .78rem;
    line-height: 1.45;
    color: var(--muted);
}

.flx-canales {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 16px;
    padding: 8px 10px;
    border: 1px solid var(--border-soft);
    border-radius: 8px;
    background: var(--surface-2);
}

/* Lista de herramientas del agente con sus dos casillas. Se hace scrollable en
   vez de crecer: el catálogo pasa de treinta tools y empujaría el pie del modal
   fuera de la pantalla, dejando el botón de guardar inalcanzable. */
.flx-tools-grid {
    display: flex;
    flex-direction: column;
    max-height: 260px;
    overflow-y: auto;
    border: 1px solid var(--border-soft);
    border-radius: 8px;
    background: var(--surface-2);
}

.flx-tool-row {
    display: grid;
    grid-template-columns: 1fr auto auto auto;
    align-items: center;
    gap: 10px;
    padding: 6px 10px;
    border-bottom: 1px solid var(--border-soft);
}
.flx-tool-row:last-child { border-bottom: none; }

.flx-tool-name {
    font-size: .82rem;
    color: var(--text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.flx-tool-mcp {
    font-size: .7rem;
    color: var(--muted-2);
    padding: 1px 6px;
    border-radius: 999px;
    background: var(--control-bg);
}
/* Las del propio módulo de Flujos: se puede sugerir pero NO esconder. Se dice
   en vez de dejar el hueco vacío, que se lee como un fallo de render. */
.flx-tool-lock {
    font-size: .7rem;
    color: var(--muted-2);
    font-style: italic;
}

@media (max-width: 560px) {
    .flx-tool-row { grid-template-columns: 1fr; gap: 2px; }
}

/* Peldaño del temporizador: los minutos delante y el mensaje al lado, porque se
   lee «a los 30 minutos, esto». Apilados se pierde de vista a qué umbral
   corresponde cada texto en cuanto hay tres. */
.flx-seg-fields {
    display: grid;
    grid-template-columns: 90px auto 1fr;
    align-items: start;
    gap: 6px;
    flex: 1;
    min-width: 0;
}
.flx-seg-unidad {
    padding-top: 7px;
    font-size: .75rem;
    color: var(--muted);
    white-space: nowrap;
}

@media (max-width: 560px) {
    .flx-seg-fields { grid-template-columns: 90px auto; }
    .flx-seg-fields > .flx-obj-desc-input { grid-column: 1 / -1; }
}

/* ── Compuerta de enrutamiento ──────────────────────────────────────────────
   Una regla se lee como una frase: «Si <campo> <operador> <valor> → <rama>».
   Por eso va en una sola línea de grid y no en un formulario de cuatro campos
   apilados: el orden de lectura ES el significado. */
.flx-enr-reglas {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: 6px;
}

.flx-enr-regla {
    display: grid;
    grid-template-columns: auto minmax(120px, 1.4fr) minmax(110px, 1fr) minmax(90px, 1fr) auto minmax(110px, 1fr) auto;
    align-items: center;
    gap: 6px;
    padding: 6px 8px;
    border: 1px solid var(--border-soft);
    border-radius: 8px;
    background: var(--surface-2);
}

.flx-enr-si,
.flx-enr-then {
    font-size: .78rem;
    color: var(--muted);
    white-space: nowrap;
}

/* Los inputs de la fila son estrechos a propósito: la fila entera tiene que
   caber sin scroll horizontal dentro del modal. */
.flx-enr-regla .form-input {
    min-width: 0;
    padding: 5px 7px;
    font-size: .78rem;
}

.flx-enr-probar {
    margin-top: 12px;
    padding: 10px;
    border: 1px solid var(--border-soft);
    border-radius: 8px;
    background: var(--surface-2);
}

.flx-enr-probar-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 6px;
    font-size: .82rem;
    color: var(--text-strong);
}

.flx-btn-link {
    background: none;
    border: none;
    padding: 0;
    font-size: .76rem;
    color: var(--brand);
    cursor: pointer;
    text-decoration: underline;
}

.flx-mono {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: .76rem;
}

/* Resultado de la simulación. Sin rama NO es un error —el contacto sigue el
   tronco, que es un desenlace legítimo—, así que el estado neutro es el
   normal y el verde solo aparece cuando de verdad enruta. */
.flx-enr-res {
    margin-top: 8px;
    padding: 8px 10px;
    border-radius: 8px;
    border: 1px solid var(--border-soft);
    background: var(--surface-3);
}
.flx-enr-res.is-ok {
    border-color: var(--badge-success-fg);
    background: var(--badge-success-bg);
}
.flx-enr-res-titular {
    font-size: .82rem;
    color: var(--text-strong);
    margin-bottom: 4px;
}
.flx-enr-res-lista {
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: .76rem;
}
.flx-enr-res-lista li {
    display: flex;
    gap: 6px;
    align-items: baseline;
    padding: 1px 0;
    color: var(--muted);
}
.flx-enr-res-si { color: var(--text); }
.flx-enr-res-no { color: var(--muted-2); }
.flx-enr-res-marca { font-weight: 700; }
.flx-enr-res-si .flx-enr-res-marca { color: var(--badge-success-fg); }
.flx-enr-res-no .flx-enr-res-marca { color: var(--muted-2); }

.flx-hint-warn { color: var(--badge-warn-fg); }
.flx-hint-error { color: var(--badge-danger-fg); }

/* ── Mapa de recorridos: el flujograma ──────────────────────────────────────
   Sustituye a las columnas de antes (`.flx-mapa-col*`, borradas). Aquellas
   contaban qué pasos tiene cada recorrido pero no DÓNDE se decide entre ellos:
   la compuerta era un renglón dentro de una caja y el punto de bifurcación —lo
   único que hay que entender de un flujo con ramas— no se veía.

   El scroll horizontal vive en `.flx-fc-ramas` y NO en la página: un flujo con
   seis ramas no debe empujar el ancho del panel entero. */
.flx-fc {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 6px 2px 14px;
}

/* Píldora de entrada: da un punto de partida al ojo. Sin ella el flujograma
   empieza en el aire y el primer paso se lee como si fuera opcional. */
.flx-fc-inicio {
    padding: 5px 16px;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--surface-2);
    font-size: .76rem;
    color: var(--muted);
}

/* Conector vertical con punta. Es un elemento propio y no un ::after de la caja
   porque tiene que poder ir también DESPUÉS de un rombo, que no es una caja. */
.flx-fc-conector {
    position: relative;
    width: 1px;
    height: 22px;
    background: var(--border);
    flex: 0 0 auto;
}
.flx-fc-conector::after {
    content: "";
    position: absolute;
    bottom: -1px;
    left: 50%;
    transform: translateX(-50%);
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    border-top: 6px solid var(--border);
}

.flx-fc-espina {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
}

.flx-fc-paso {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
    max-width: 320px;
}
.flx-fc-paso .flx-mapa-caja { width: 100%; }

/* La compuerta: rombo a la izquierda, salidas a la derecha. En fila para que la
   condición quede pegada a su destino — apiladas, con tres o cuatro reglas ya no
   se sabe cuál lleva a dónde. */
.flx-fc-gate {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 10px;
    width: 100%;
}

/* Rombo por `clip-path` y no por `rotate(45deg)`: rotar obliga a contrarrotar el
   texto y a fijar el tamaño a mano, y el rótulo de la compuerta es de largo
   variable. El padding lateral generoso es lo que mantiene el texto dentro de la
   parte ancha de la figura. */
.flx-fc-rombo {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
    min-width: 132px;
    padding: 20px 34px;
    clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
    background: var(--badge-info-bg);
    border: 0;
    text-align: center;
}
.flx-fc-rombo.is-ancho {
    min-width: 300px;
    max-width: 460px;
    padding: 22px 56px;
    background: var(--brand-soft-bg);
}
.flx-fc-rombo-txt {
    font-size: .72rem;
    font-weight: 600;
    line-height: 1.3;
    color: var(--badge-info-fg);
    word-break: break-word;
}
.flx-fc-rombo.is-ancho .flx-fc-rombo-txt { color: var(--brand); }

/* Salvedad del rombo de criterio: se dibuja en un punto, pero el motor no lo ata
   a ninguno. Sin esta línea el flujograma promete un orden que no existe. */
.flx-fc-nota {
    max-width: 62ch;
    margin: 8px 0 0;
    font-size: .68rem;
    line-height: 1.45;
    color: var(--muted-2);
    text-align: center;
    font-style: italic;
}

.flx-fc-salidas {
    display: flex;
    flex-direction: column;
    gap: 5px;
    min-width: 0;
    flex: 1 1 auto;
}
.flx-fc-salida {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    font-size: .7rem;
}
.flx-fc-cond {
    padding: 2px 7px;
    border-radius: 6px;
    background: var(--control-bg);
    color: var(--muted);
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: .66rem;
}
/* La salida por defecto no es una regla: es lo que pasa cuando NINGUNA casa.
   Punteada para que no se lea como una condición más de la lista. */
.flx-fc-cond.is-defecto {
    background: transparent;
    border: 1px dashed var(--border);
    font-family: inherit;
    font-style: italic;
}
.flx-fc-flecha { color: var(--muted-2); }
.flx-fc-destino {
    padding: 2px 8px;
    border-radius: 999px;
    font-weight: 600;
    background: var(--control-bg);
    color: var(--text);
}
.flx-fc-aviso {
    font-size: .7rem;
    color: var(--badge-warn-fg);
}

/* Ramas, una columna cada una. */
.flx-fc-ramas {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    gap: 14px;
    margin-top: 18px;
    width: 100%;
    overflow-x: auto;
    padding-bottom: 6px;
}
.flx-fc-rama {
    display: flex;
    flex-direction: column;
    align-items: center;
    flex: 0 0 auto;
    min-width: 236px;
    max-width: 300px;
    padding: 10px;
    border: 1px solid var(--border-soft);
    border-top-width: 3px;
    border-radius: 10px;
    background: var(--surface-2);
}
.flx-fc-rama-head { width: 100%; }
.flx-fc-rama-nom {
    font-size: .84rem;
    font-weight: 600;
    color: var(--text-strong);
}
/* Quién decide la rama es una diferencia de COMPORTAMIENTO, no de presentación:
   una que decide la compuerta se toma en un punto exacto; una que elige el
   agente puede tomarla desde el primer turno. */
.flx-fc-rama-quien {
    display: inline-block;
    margin-top: 3px;
    padding: 1px 7px;
    border-radius: 999px;
    font-size: .64rem;
    background: var(--control-bg);
    color: var(--muted-2);
}
.flx-fc-rama-quien.is-gate {
    background: var(--badge-info-bg);
    color: var(--badge-info-fg);
}
.flx-fc-rama-crit {
    width: 100%;
    margin: 6px 0 10px;
    font-size: .7rem;
    line-height: 1.4;
    color: var(--muted);
}
.flx-fc-rama-crit.is-warn { color: var(--badge-warn-fg); }
.flx-fc-derivacion {
    width: 100%;
    margin-top: 8px;
    padding-top: 6px;
    border-top: 1px solid var(--border-soft);
    font-size: .7rem;
    color: var(--brand);
}

/* Color por rama. Sale de la rampa de gráficas para que las ramas sigan al tema
   y, sobre todo, a las paletas de accesibilidad: si el único distintivo de una
   rama fuera un color fijo, un daltónico no las separaría. Por eso el color
   NUNCA va solo — la rama siempre lleva además su nombre escrito. */
.flx-fc-rama.r0 { border-top-color: var(--chart-1); }
.flx-fc-rama.r1 { border-top-color: var(--chart-2); }
.flx-fc-rama.r2 { border-top-color: var(--chart-3); }
.flx-fc-rama.r3 { border-top-color: var(--chart-4); }
.flx-fc-rama.r4 { border-top-color: var(--chart-5); }
.flx-fc-rama.r5 { border-top-color: var(--chart-6); }
.flx-fc-destino.r0, .flx-node-out.r0 { color: var(--chart-1); }
.flx-fc-destino.r1, .flx-node-out.r1 { color: var(--chart-2); }
.flx-fc-destino.r2, .flx-node-out.r2 { color: var(--chart-3); }
.flx-fc-destino.r3, .flx-node-out.r3 { color: var(--chart-4); }
.flx-fc-destino.r4, .flx-node-out.r4 { color: var(--chart-5); }
.flx-fc-destino.r5, .flx-node-out.r5 { color: var(--chart-6); }
/* r9 = la regla apunta a una rama que no existe: un callejón sin salida. */
.flx-fc-destino.r9, .flx-node-out.r9 {
    background: var(--badge-danger-bg);
    color: var(--badge-danger-fg);
}

.flx-mapa-caja {
    position: relative;
    padding: 7px 9px;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--surface);
    cursor: pointer;
    transition: border-color .12s, box-shadow .12s;
}
.flx-mapa-caja.is-fin { border-color: var(--badge-success-fg); }

/* Afordancia del doble clic. Sin ella el gesto es invisible: nada en una caja
   plana dice que responde. El `:focus-visible` es la misma señal para quien
   navega con el tabulador, que es como se llega aquí sin ratón.

   Cada figura la señala como puede: la caja tiene borde, la cabecera de rama y
   el rombo NO (el rombo se recorta con `clip-path`, que además se come cualquier
   `outline`), así que esos dos cambian de fondo. */
.flx-mapa-caja:hover { border-color: var(--brand); }
.flx-mapa-caja:focus-visible,
.flx-fc-rama-head:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 2px;
}
.flx-fc-rama-head {
    cursor: pointer;
    padding: 2px 4px;
    border-radius: 6px;
    transition: background .12s;
}
.flx-fc-rama-head:hover { background: var(--control-bg-hover); }
.flx-fc-rombo.is-clic { cursor: pointer; transition: background .12s; }
.flx-fc-rombo.is-clic:hover { background: var(--brand-soft-bg); }
.flx-fc-rombo.is-clic:hover .flx-fc-rombo-txt { color: var(--brand); }

/* ── Ficha del mapa ───────────────────────────────────────────────────────
   Solo lectura; el botón «Editar» del pie aparece únicamente con permiso y
   abre el wizard de siempre. */
.flx-ficha { max-width: 620px; width: 100%; }
.flx-ficha-nombre {
    margin-left: 8px;
    font-weight: 500;
    color: var(--muted);
}
.flx-ficha-body {
    max-height: 62vh;
    overflow-y: auto;
    padding: 4px 2px 8px;
}
.flx-ficha-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    margin-bottom: 10px;
}
/* Rejilla de dos columnas para los datos cortos: en una sola columna la ficha
   se alarga y obliga a desplazar para llegar a lo que sí es texto. */
.flx-ficha-datos {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 4px 16px;
    margin-bottom: 12px;
}
.flx-ficha-fila {
    display: flex;
    gap: 8px;
    font-size: .76rem;
}
.flx-ficha-lbl { color: var(--muted-2); flex: 0 0 auto; }
.flx-ficha-val { color: var(--text); word-break: break-word; }

.flx-ficha-sec {
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px solid var(--border-soft);
}
.flx-ficha-sec-tit {
    margin-bottom: 6px;
    font-size: .74rem;
    font-weight: 600;
    color: var(--text-strong);
}
.flx-ficha-texto {
    margin: 0;
    font-size: .78rem;
    line-height: 1.5;
    color: var(--text);
}
.flx-ficha-off { color: var(--muted-2); font-style: italic; }
.flx-ficha-lista,
.flx-ficha-salidas {
    margin: 0;
    padding-left: 18px;
    font-size: .76rem;
    line-height: 1.6;
    color: var(--text);
}
.flx-ficha-lista li { margin-bottom: 3px; }
.flx-ficha-url {
    display: block;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: .68rem;
    color: var(--muted-2);
    word-break: break-all;
}
.flx-chip-bloq {
    background: var(--badge-danger-bg);
    color: var(--badge-danger-fg);
}

.flx-mapa-caja-nombre {
    font-size: .8rem;
    color: var(--text);
}
.flx-mapa-caja-num {
    display: inline-block;
    min-width: 17px;
    margin-right: 5px;
    padding: 0 4px;
    border-radius: 5px;
    background: var(--control-bg);
    color: var(--muted-2);
    font-size: .66rem;
    text-align: center;
}
.flx-mapa-caja-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 8px;
    margin-top: 3px;
    font-size: .68rem;
    color: var(--muted-2);
}
.flx-mapa-tag {
    padding: 0 6px;
    border-radius: 999px;
    background: var(--control-bg);
}
.flx-mapa-tag.is-fin {
    background: var(--badge-success-bg);
    color: var(--badge-success-fg);
}

.flx-mapa-vacia {
    font-size: .72rem;
    color: var(--muted-2);
    font-style: italic;
}

.flx-mapa-huerfanas {
    margin-top: 12px;
    padding: 10px;
    border: 1px dashed var(--badge-warn-fg);
    border-radius: 10px;
    background: var(--surface-2);
}
/* Las huérfanas NO se encadenan: no forman un recorrido, son pasos sueltos que
   el motor no le enseña a nadie. */
.flx-mapa-col-cuerpo {
    display: flex;
    flex-direction: column;
    padding: 10px 0 0;
    gap: 8px;
}
.flx-mapa-col-titulo {
    font-size: .84rem;
    font-weight: 600;
    color: var(--text-strong);
}

/* Compuerta que se evalúa y nunca reparte: el fallo no da error en ninguna parte,
   así que se señala en la propia fila o no se ve. */
.flx-badge-warn {
    display: inline-block;
    margin-left: 6px;
    padding: 1px 7px;
    border-radius: 999px;
    font-size: .68rem;
    background: var(--badge-warn-bg);
    color: var(--badge-warn-fg);
}

@media (max-width: 720px) {
    .flx-enr-regla { grid-template-columns: 1fr; gap: 4px; }
    .flx-enr-si, .flx-enr-then { display: none; }
}

/* ══════════════════════════════════════════════════════════════════════════════
   ACCESIBILIDAD — paletas alternativas
   ══════════════════════════════════════════════════════════════════════════════

   Se activan con una clase en <html> (`a11y-cvd`, `a11y-mono`, `a11y-acro`,
   `a11y-broma`) que pone el botón de accesibilidad del header y, antes del
   primer paint, el script de `index.html`. El daltonismo lleva ADEMÁS una
   clase de tipo (`a11y-cvd-deuteranopia`…): la base pone las superficies y el
   tipo, los colores de estado.

   ## Por qué CSS estático y no tokens inyectados desde Rust

   El resto de capas de color (tema del Marketplace, tema del usuario, preview)
   se inyectan como `<style>` desde `theme.rs`, y su espejo pre-paint en
   `index.html` repite la lógica. Para las paletas de accesibilidad eso obligaría
   a duplicar TRES tablas de color en JavaScript, con la garantía de que se
   separarían. Con una clase, el pre-paint son dos líneas y el color vive en un
   solo sitio: aquí.

   ## Especificidad

   Ganan a TODO, incluida la previsualización del editor de identidad:

     :root                                     0,1,0   panel · oscuro
     html.light-mode                           0,1,1   panel · claro
     html:root:root                            0,2,1   usuario · oscuro
     html.light-mode:root:root                 0,3,1   usuario · claro
     html:root:root:root:root                  0,4,1   preview · oscuro
     html.light-mode:root:root:root:root       0,5,1   preview · claro
     html.a11y-X:root:root:root:root:root      0,6,1   ← accesibilidad · oscuro
     html.a11y-X.light-mode:root:…:root        0,7,1   ← accesibilidad · claro

   Una necesidad de acceso no la puede pisar el tema que eligió el operador ni
   una previsualización a medio guardar. Por eso van arriba del todo.
   ══════════════════════════════════════════════════════════════════════════════ */

/* ── (a) Daltonismo — base común ─────────────────────────────────────────────────────────────
   Paleta de Okabe–Ito: colores distinguibles en deuteranopía, protanopía y
   tritanopía. El cambio que de verdad importa NO es que los colores sean más
   bonitos: es que «éxito» deja de ser verde y «error» rojo —el par que un
   deuteranope ve igual— y pasan a verde-azulado (#009E73) y bermellón
   (#D55E00), que se separan por tono Y por luminosidad.
   Referencia: Okabe & Ito, «Color Universal Design» (2008).                   */
html.a11y-cvd:root:root:root:root:root {
    --bg:               #12131a !important;
    --bg-2:             #171922 !important;
    --surface:          #1c1f2a !important;
    --surface-2:        #22252f !important;
    --surface-3:        #282c37 !important;
    --surface-overlay:  #1c1f2a !important;
    --panel:            #1c1f2a !important;
    --panel-2:          #22252f !important;
    --nav-bg:           #12131a !important;
    --nav-bg-2:         #171922 !important;
    --nav-border:       #3a3f4d !important;
    --nav-shade:        #0d0e14 !important;

    --control-bg:       #262a35 !important;
    --control-bg-hover: #30353f !important;
    --control-border:   #4a505f !important;
    --scrim:            rgba(0,0,0,0.66) !important;

    --text:             #eceff4 !important;
    --text-strong:      #ffffff !important;
    --muted:            #b6bcc9 !important;
    --muted-2:          #8f96a5 !important;

    --border:           #3a3f4d !important;
    --border-soft:      #2b2f3a !important;

    /* Azul Okabe–Ito aclarado: es el acento y necesita contraste sobre oscuro. */
    --brand:            #56b4e9 !important;
    --brand-dark:       #0072b2 !important;
    --brand-rgb:        86,180,233 !important;
    --brand-dark-rgb:   0,114,178 !important;
    --brand-soft-bg:    rgba(86,180,233,0.16) !important;
    --brand-soft-fg:    #8fcdf1 !important;
    --accent:           #56b4e9 !important;

    /* Verde-azulado y bermellón, NO verde y rojo. */
    --success:          #009e73 !important;
    --danger:           #d55e00 !important;
    --badge-success-bg: rgba(0,158,115,0.20) !important;
    --badge-success-fg: #4ecfa8 !important;
    --badge-warn-bg:    rgba(230,159,0,0.20) !important;
    --badge-warn-fg:    #f0b74a !important;
    --badge-danger-bg:  rgba(213,94,0,0.22) !important;
    --badge-danger-fg:  #f08a4b !important;
    --badge-info-bg:    rgba(0,114,178,0.22) !important;
    --badge-info-fg:    #6fbde8 !important;
    --badge-neutral-bg: rgba(150,156,168,0.20) !important;
    --badge-neutral-fg: #c3c8d2 !important;
    --badge-purple-bg:  rgba(204,121,167,0.20) !important;
    --badge-purple-fg:  #dfa3c4 !important;

    --tooltip-bg:       #f2f4f8 !important;
    --tooltip-fg:       #14161c !important;

    --chart-grid:        #2b2f3a !important;
    --chart-axis:        #b6bcc9 !important;
    --chart-legend:      #eceff4 !important;
    --chart-datalabel:   #ffffff !important;
}

html.a11y-cvd.light-mode:root:root:root:root:root {
    --bg:               #ffffff !important;
    --bg-2:             #f4f6f9 !important;
    --surface:          #ffffff !important;
    --surface-2:        #f1f4f8 !important;
    --surface-3:        #e7ebf1 !important;
    --surface-overlay:  #ffffff !important;
    --panel:            #ffffff !important;
    --panel-2:          #f1f4f8 !important;
    --nav-bg:           #ffffff !important;
    --nav-bg-2:         #f4f6f9 !important;
    --nav-border:       #c8cfd9 !important;
    --nav-shade:        #e7ebf1 !important;

    --control-bg:       #f1f4f8 !important;
    --control-bg-hover: #e4e9f0 !important;
    --control-border:   #b3bcc9 !important;
    --scrim:            rgba(16,20,28,0.42) !important;

    --text:             #14181f !important;
    --text-strong:      #000000 !important;
    --muted:            #4a5260 !important;
    --muted-2:          #656d7c !important;

    --border:           #c8cfd9 !important;
    --border-soft:      #dfe4ea !important;

    --brand:            #0072b2 !important;
    --brand-dark:       #004e7c !important;
    --brand-rgb:        0,114,178 !important;
    --brand-dark-rgb:   0,78,124 !important;
    --brand-soft-bg:    rgba(0,114,178,0.12) !important;
    --brand-soft-fg:    #004e7c !important;
    --accent:           #0072b2 !important;

    --success:          #006f51 !important;
    --danger:           #a34700 !important;
    --badge-success-bg: rgba(0,158,115,0.16) !important;
    --badge-success-fg: #00614a !important;
    --badge-warn-bg:    rgba(230,159,0,0.20) !important;
    --badge-warn-fg:    #7a5300 !important;
    --badge-danger-bg:  rgba(213,94,0,0.16) !important;
    --badge-danger-fg:  #8f3f00 !important;
    --badge-info-bg:    rgba(0,114,178,0.14) !important;
    --badge-info-fg:    #00456e !important;
    --badge-neutral-bg: rgba(90,98,112,0.14) !important;
    --badge-neutral-fg: #3c4351 !important;
    --badge-purple-bg:  rgba(204,121,167,0.16) !important;
    --badge-purple-fg:  #7d3d5e !important;

    --tooltip-bg:       #14181f !important;
    --tooltip-fg:       #ffffff !important;

    --chart-grid:        #dfe4ea !important;
    --chart-axis:        #4a5260 !important;
    --chart-legend:      #14181f !important;
    --chart-datalabel:   #ffffff !important;
}


/* ── Tipos de daltonismo ────────────────────────────────────────────────────────
   Bloques GENERADOS (tabla de color + contraste medido). Retocar un hex aquí es
   correcto; si se rehace la tabla entera, hay que rehacer también la comprobación
   de contraste que se describe abajo.

   La clase base `a11y-cvd` pone las SUPERFICIES (grises fríos, sin croma) y una
   clase de tipo `a11y-cvd-<tipo>` pone solo los ~21 tokens que codifican ESTADO.
   Separarlo evita repetir 46 tokens seis veces, que es donde se cuelan las
   erratas.

   Especificidad: la base va en (0,6,1)/(0,7,1) como el resto de accesibilidad y
   el tipo un escalón por encima —(0,7,1)/(0,8,1)—, para que gane sin depender del
   orden en la hoja, que es la regla de todo el sistema de temas.

   ## Qué eje usa cada familia, y por qué NO vale una sola paleta

   · protan / deutan → falla el eje ROJO-VERDE. Eje seguro: azul vs naranja.
     Protan además percibe el rojo MÁS OSCURO de lo que es: un rojo oscuro le
     llega casi negro, así que su «peligro» es naranja brillante y nunca burdeos.
   · tritan → falla el eje AZUL-AMARILLO. Eje seguro: rojo vs cian. Aquí la
     paleta Okabe-Ito (que se apoya en azul y naranja) es justo la MALA, y por eso
     no se reutiliza: el amarillo se sustituye por rosa.
   · «-anomalía» = el cono existe pero desplazado: conserva algo de tono, así que
     admite la paleta rica (verde-azulado, naranja, azul).
   · «-opia» = el cono NO existe: dentro del eje perdido el tono no separa nada,
     así que los estados se apoyan en DOS tonos del eje que sobrevive por DOS
     niveles de claridad.

   ## El texto del badge NO es el color del estado

   Se aclara (oscuro) u oscurece (claro) hasta 4.5:1 contra el fondo REAL del
   badge, que es el color del estado con alfa COMPUESTO sobre la superficie — no
   la superficie a secas. Sin componer, el cálculo promete un contraste que la
   pantalla no tiene: `#0072b2` como texto sobre `#1c1f2a` da 2.97:1 y se lee mal,
   que es justo lo que esta paleta viene a arreglar.
   ─────────────────────────────────────────────────────────────────────────────── */

/* deuteranomalia */
html.a11y-cvd-deuteranomalia:root:root:root:root:root:root {
    --brand:             #56b4e9 !important;
    --brand-dark:        #0072b2 !important;
    --brand-rgb:         86,180,233 !important;
    --brand-dark-rgb:    0,114,178 !important;
    --brand-soft-bg:     rgba(86,180,233,0.16) !important;
    --brand-soft-fg:     #56b4e9 !important;
    --accent:            #56b4e9 !important;
    --success:           #009e73 !important;
    --danger:            #d55e00 !important;
    --badge-success-bg:  rgba(0,158,115,0.22) !important;
    --badge-success-fg:  #33b18f !important;
    --badge-warn-bg:     rgba(230,159,0,0.22) !important;
    --badge-warn-fg:     #e69f00 !important;
    --badge-danger-bg:   rgba(213,94,0,0.22) !important;
    --badge-danger-fg:   #e08640 !important;
    --badge-info-bg:     rgba(0,114,178,0.22) !important;
    --badge-info-fg:     #59a3cd !important;
    --badge-neutral-bg:  rgba(150,156,168,0.22) !important;
    --badge-neutral-fg:  #a0a6b1 !important;
    --badge-purple-bg:   rgba(204,121,167,0.22) !important;
    --badge-purple-fg:   #d48db4 !important;

    --chart-1:           #56b4e9 !important;
    --chart-2:           #009e73 !important;
    --chart-3:           #f0b02a !important;
    --chart-4:           #cc79a7 !important;
    --chart-5:           #d55e00 !important;
    --chart-6:           #c0c5cd !important;
}
html.a11y-cvd-deuteranomalia.light-mode:root:root:root:root:root:root {
    --brand:             #0072b2 !important;
    --brand-dark:        #004e7c !important;
    --brand-rgb:         0,114,178 !important;
    --brand-dark-rgb:    0,78,124 !important;
    --brand-soft-bg:     rgba(0,114,178,0.12) !important;
    --brand-soft-fg:     #004e7c !important;
    --accent:            #0072b2 !important;
    --success:           #006f51 !important;
    --danger:            #a34700 !important;
    --badge-success-bg:  rgba(0,111,81,0.15) !important;
    --badge-success-fg:  #006f51 !important;
    --badge-warn-bg:     rgba(122,83,0,0.15) !important;
    --badge-warn-fg:     #7a5300 !important;
    --badge-danger-bg:   rgba(163,71,0,0.15) !important;
    --badge-danger-fg:   #a34700 !important;
    --badge-info-bg:     rgba(0,69,110,0.15) !important;
    --badge-info-fg:     #00456e !important;
    --badge-neutral-bg:  rgba(90,98,112,0.15) !important;
    --badge-neutral-fg:  #5a6270 !important;
    --badge-purple-bg:   rgba(125,61,94,0.15) !important;
    --badge-purple-fg:   #7d3d5e !important;

    --chart-1:           #0072b2 !important;
    --chart-2:           #00795c !important;
    --chart-3:           #c98600 !important;
    --chart-4:           #a3567f !important;
    --chart-5:           #8f2d00 !important;
    --chart-6:           #8e949c !important;
}

/* protanomalia */
html.a11y-cvd-protanomalia:root:root:root:root:root:root {
    --brand:             #56b4e9 !important;
    --brand-dark:        #0072b2 !important;
    --brand-rgb:         86,180,233 !important;
    --brand-dark-rgb:    0,114,178 !important;
    --brand-soft-bg:     rgba(86,180,233,0.16) !important;
    --brand-soft-fg:     #56b4e9 !important;
    --accent:            #56b4e9 !important;
    --success:           #009e73 !important;
    --danger:            #f07818 !important;
    --badge-success-bg:  rgba(0,158,115,0.22) !important;
    --badge-success-fg:  #33b18f !important;
    --badge-warn-bg:     rgba(240,194,68,0.22) !important;
    --badge-warn-fg:     #f0c244 !important;
    --badge-danger-bg:   rgba(240,120,24,0.22) !important;
    --badge-danger-fg:   #f2862f !important;
    --badge-info-bg:     rgba(0,114,178,0.22) !important;
    --badge-info-fg:     #59a3cd !important;
    --badge-neutral-bg:  rgba(150,156,168,0.22) !important;
    --badge-neutral-fg:  #a0a6b1 !important;
    --badge-purple-bg:   rgba(204,121,167,0.22) !important;
    --badge-purple-fg:   #d48db4 !important;

    --chart-1:           #56b4e9 !important;
    --chart-2:           #009e73 !important;
    --chart-3:           #f0c244 !important;
    --chart-4:           #cc79a7 !important;
    --chart-5:           #f07818 !important;
    --chart-6:           #c0c5cd !important;
}
html.a11y-cvd-protanomalia.light-mode:root:root:root:root:root:root {
    --brand:             #0072b2 !important;
    --brand-dark:        #004e7c !important;
    --brand-rgb:         0,114,178 !important;
    --brand-dark-rgb:    0,78,124 !important;
    --brand-soft-bg:     rgba(0,114,178,0.12) !important;
    --brand-soft-fg:     #004e7c !important;
    --accent:            #0072b2 !important;
    --success:           #006f51 !important;
    --danger:            #a85300 !important;
    --badge-success-bg:  rgba(0,111,81,0.15) !important;
    --badge-success-fg:  #006f51 !important;
    --badge-warn-bg:     rgba(107,74,0,0.15) !important;
    --badge-warn-fg:     #6b4a00 !important;
    --badge-danger-bg:   rgba(168,83,0,0.15) !important;
    --badge-danger-fg:   #a04f00 !important;
    --badge-info-bg:     rgba(0,69,110,0.15) !important;
    --badge-info-fg:     #00456e !important;
    --badge-neutral-bg:  rgba(90,98,112,0.15) !important;
    --badge-neutral-fg:  #5a6270 !important;
    --badge-purple-bg:   rgba(125,61,94,0.15) !important;
    --badge-purple-fg:   #7d3d5e !important;

    --chart-1:           #0072b2 !important;
    --chart-2:           #00795c !important;
    --chart-3:           #d4a100 !important;
    --chart-4:           #a3567f !important;
    --chart-5:           #9c3800 !important;
    --chart-6:           #8e949c !important;
}

/* deuteranopia */
html.a11y-cvd-deuteranopia:root:root:root:root:root:root {
    --brand:             #56b4e9 !important;
    --brand-dark:        #0072b2 !important;
    --brand-rgb:         86,180,233 !important;
    --brand-dark-rgb:    0,114,178 !important;
    --brand-soft-bg:     rgba(86,180,233,0.16) !important;
    --brand-soft-fg:     #56b4e9 !important;
    --accent:            #56b4e9 !important;
    --success:           #8fd3f4 !important;
    --danger:            #e07b18 !important;
    --badge-success-bg:  rgba(143,211,244,0.22) !important;
    --badge-success-fg:  #8fd3f4 !important;
    --badge-warn-bg:     rgba(245,215,110,0.22) !important;
    --badge-warn-fg:     #f5d76e !important;
    --badge-danger-bg:   rgba(224,123,24,0.22) !important;
    --badge-danger-fg:   #e58f3b !important;
    --badge-info-bg:     rgba(0,114,178,0.22) !important;
    --badge-info-fg:     #59a3cd !important;
    --badge-neutral-bg:  rgba(150,156,168,0.22) !important;
    --badge-neutral-fg:  #a0a6b1 !important;
    --badge-purple-bg:   rgba(154,167,184,0.22) !important;
    --badge-purple-fg:   #9fabbc !important;

    --chart-1:           #4a9fd4 !important;
    --chart-2:           #c2e8fb !important;
    --chart-3:           #ffe9a8 !important;
    --chart-4:           #12587f !important;
    --chart-5:           #e07b18 !important;
    --chart-6:           #8a8f99 !important;
}
html.a11y-cvd-deuteranopia.light-mode:root:root:root:root:root:root {
    --brand:             #0072b2 !important;
    --brand-dark:        #004e7c !important;
    --brand-rgb:         0,114,178 !important;
    --brand-dark-rgb:    0,78,124 !important;
    --brand-soft-bg:     rgba(0,114,178,0.12) !important;
    --brand-soft-fg:     #004e7c !important;
    --accent:            #0072b2 !important;
    --success:           #004e7c !important;
    --danger:            #a34700 !important;
    --badge-success-bg:  rgba(0,78,124,0.15) !important;
    --badge-success-fg:  #004e7c !important;
    --badge-warn-bg:     rgba(107,74,0,0.15) !important;
    --badge-warn-fg:     #6b4a00 !important;
    --badge-danger-bg:   rgba(163,71,0,0.15) !important;
    --badge-danger-fg:   #a34700 !important;
    --badge-info-bg:     rgba(0,45,79,0.15) !important;
    --badge-info-fg:     #002d4f !important;
    --badge-neutral-bg:  rgba(90,98,112,0.15) !important;
    --badge-neutral-fg:  #5a6270 !important;
    --badge-purple-bg:   rgba(76,86,102,0.15) !important;
    --badge-purple-fg:   #4c5666 !important;

    --chart-1:           #0f7fbe !important;
    --chart-2:           #7cc4ec !important;
    --chart-3:           #d9b300 !important;
    --chart-4:           #003a5c !important;
    --chart-5:           #8a3600 !important;
    --chart-6:           #8a9099 !important;
}

/* protanopia */
html.a11y-cvd-protanopia:root:root:root:root:root:root {
    --brand:             #56b4e9 !important;
    --brand-dark:        #0072b2 !important;
    --brand-rgb:         86,180,233 !important;
    --brand-dark-rgb:    0,114,178 !important;
    --brand-soft-bg:     rgba(86,180,233,0.16) !important;
    --brand-soft-fg:     #56b4e9 !important;
    --accent:            #56b4e9 !important;
    --success:           #8fd3f4 !important;
    --danger:            #f59237 !important;
    --badge-success-bg:  rgba(143,211,244,0.22) !important;
    --badge-success-fg:  #8fd3f4 !important;
    --badge-warn-bg:     rgba(245,215,110,0.22) !important;
    --badge-warn-fg:     #f5d76e !important;
    --badge-danger-bg:   rgba(245,146,55,0.22) !important;
    --badge-danger-fg:   #f59237 !important;
    --badge-info-bg:     rgba(0,114,178,0.22) !important;
    --badge-info-fg:     #59a3cd !important;
    --badge-neutral-bg:  rgba(150,156,168,0.22) !important;
    --badge-neutral-fg:  #a0a6b1 !important;
    --badge-purple-bg:   rgba(154,167,184,0.22) !important;
    --badge-purple-fg:   #9fabbc !important;

    --chart-1:           #4a9fd4 !important;
    --chart-2:           #c2e8fb !important;
    --chart-3:           #ffe9a8 !important;
    --chart-4:           #12587f !important;
    --chart-5:           #ef8118 !important;
    --chart-6:           #8a8f99 !important;
}
html.a11y-cvd-protanopia.light-mode:root:root:root:root:root:root {
    --brand:             #0072b2 !important;
    --brand-dark:        #004e7c !important;
    --brand-rgb:         0,114,178 !important;
    --brand-dark-rgb:    0,78,124 !important;
    --brand-soft-bg:     rgba(0,114,178,0.12) !important;
    --brand-soft-fg:     #004e7c !important;
    --accent:            #0072b2 !important;
    --success:           #004e7c !important;
    --danger:            #b35a00 !important;
    --badge-success-bg:  rgba(0,78,124,0.15) !important;
    --badge-success-fg:  #004e7c !important;
    --badge-warn-bg:     rgba(107,74,0,0.15) !important;
    --badge-warn-fg:     #6b4a00 !important;
    --badge-danger-bg:   rgba(179,90,0,0.15) !important;
    --badge-danger-fg:   #a15100 !important;
    --badge-info-bg:     rgba(0,45,79,0.15) !important;
    --badge-info-fg:     #002d4f !important;
    --badge-neutral-bg:  rgba(90,98,112,0.15) !important;
    --badge-neutral-fg:  #5a6270 !important;
    --badge-purple-bg:   rgba(76,86,102,0.15) !important;
    --badge-purple-fg:   #4c5666 !important;

    --chart-1:           #0f7fbe !important;
    --chart-2:           #7cc4ec !important;
    --chart-3:           #d9b300 !important;
    --chart-4:           #003a5c !important;
    --chart-5:           #a04200 !important;
    --chart-6:           #8a9099 !important;
}

/* tritanomalia */
html.a11y-cvd-tritanomalia:root:root:root:root:root:root {
    --brand:             #00b3bd !important;
    --brand-dark:        #007d85 !important;
    --brand-rgb:         0,179,189 !important;
    --brand-dark-rgb:    0,125,133 !important;
    --brand-soft-bg:     rgba(0,179,189,0.16) !important;
    --brand-soft-fg:     #00b3bd !important;
    --accent:            #00b3bd !important;
    --success:           #00a37a !important;
    --danger:            #e8455f !important;
    --badge-success-bg:  rgba(0,163,122,0.22) !important;
    --badge-success-fg:  #33b595 !important;
    --badge-warn-bg:     rgba(255,133,179,0.22) !important;
    --badge-warn-fg:     #ff85b3 !important;
    --badge-danger-bg:   rgba(232,69,95,0.22) !important;
    --badge-danger-fg:   #ee7487 !important;
    --badge-info-bg:     rgba(0,160,168,0.22) !important;
    --badge-info-fg:     #33b3b9 !important;
    --badge-neutral-bg:  rgba(150,156,168,0.22) !important;
    --badge-neutral-fg:  #a0a6b1 !important;
    --badge-purple-bg:   rgba(176,110,204,0.22) !important;
    --badge-purple-fg:   #c08bd6 !important;

    --chart-1:           #1c7f9c !important;
    --chart-2:           #00c2a0 !important;
    --chart-3:           #ffb08c !important;
    --chart-4:           #ff85b3 !important;
    --chart-5:           #e8455f !important;
    --chart-6:           #9aa3ad !important;
}
html.a11y-cvd-tritanomalia.light-mode:root:root:root:root:root:root {
    --brand:             #00747a !important;
    --brand-dark:        #00494d !important;
    --brand-rgb:         0,116,122 !important;
    --brand-dark-rgb:    0,73,77 !important;
    --brand-soft-bg:     rgba(0,116,122,0.12) !important;
    --brand-soft-fg:     #00494d !important;
    --accent:            #00747a !important;
    --success:           #00614a !important;
    --danger:            #a3122c !important;
    --badge-success-bg:  rgba(0,97,74,0.15) !important;
    --badge-success-fg:  #00614a !important;
    --badge-warn-bg:     rgba(161,31,92,0.15) !important;
    --badge-warn-fg:     #a11f5c !important;
    --badge-danger-bg:   rgba(163,18,44,0.15) !important;
    --badge-danger-fg:   #a3122c !important;
    --badge-info-bg:     rgba(0,95,102,0.15) !important;
    --badge-info-fg:     #005f66 !important;
    --badge-neutral-bg:  rgba(90,98,112,0.15) !important;
    --badge-neutral-fg:  #5a6270 !important;
    --badge-purple-bg:   rgba(107,45,133,0.15) !important;
    --badge-purple-fg:   #6b2d85 !important;

    --chart-1:           #046b8c !important;
    --chart-2:           #3aab90 !important;
    --chart-3:           #e08a4a !important;
    --chart-4:           #c2185b !important;
    --chart-5:           #a8102f !important;
    --chart-6:           #5f6672 !important;
}

/* tritanopia */
html.a11y-cvd-tritanopia:root:root:root:root:root:root {
    --brand:             #00c3cf !important;
    --brand-dark:        #00838c !important;
    --brand-rgb:         0,195,207 !important;
    --brand-dark-rgb:    0,131,140 !important;
    --brand-soft-bg:     rgba(0,195,207,0.16) !important;
    --brand-soft-fg:     #00c3cf !important;
    --accent:            #00c3cf !important;
    --success:           #7fe3d0 !important;
    --danger:            #d92040 !important;
    --badge-success-bg:  rgba(127,227,208,0.22) !important;
    --badge-success-fg:  #7fe3d0 !important;
    --badge-warn-bg:     rgba(255,158,196,0.22) !important;
    --badge-warn-fg:     #ff9ec4 !important;
    --badge-danger-bg:   rgba(217,32,64,0.22) !important;
    --badge-danger-fg:   #e66e83 !important;
    --badge-info-bg:     rgba(0,160,168,0.22) !important;
    --badge-info-fg:     #33b3b9 !important;
    --badge-neutral-bg:  rgba(150,156,168,0.22) !important;
    --badge-neutral-fg:  #a0a6b1 !important;
    --badge-purple-bg:   rgba(201,143,224,0.22) !important;
    --badge-purple-fg:   #cc95e2 !important;

    --chart-1:           #2f7f95 !important;
    --chart-2:           #7fe3d0 !important;
    --chart-3:           #ffb08c !important;
    --chart-4:           #c76a9a !important;
    --chart-5:           #d92040 !important;
    --chart-6:           #9aa3ad !important;
}
html.a11y-cvd-tritanopia.light-mode:root:root:root:root:root:root {
    --brand:             #00696e !important;
    --brand-dark:        #00424a !important;
    --brand-rgb:         0,105,110 !important;
    --brand-dark-rgb:    0,66,74 !important;
    --brand-soft-bg:     rgba(0,105,110,0.12) !important;
    --brand-soft-fg:     #00424a !important;
    --accent:            #00696e !important;
    --success:           #00524a !important;
    --danger:            #8f0f24 !important;
    --badge-success-bg:  rgba(0,82,74,0.15) !important;
    --badge-success-fg:  #00524a !important;
    --badge-warn-bg:     rgba(143,26,82,0.15) !important;
    --badge-warn-fg:     #8f1a52 !important;
    --badge-danger-bg:   rgba(143,15,36,0.15) !important;
    --badge-danger-fg:   #8f0f24 !important;
    --badge-info-bg:     rgba(0,74,82,0.15) !important;
    --badge-info-fg:     #004a52 !important;
    --badge-neutral-bg:  rgba(90,98,112,0.15) !important;
    --badge-neutral-fg:  #5a6270 !important;
    --badge-purple-bg:   rgba(92,36,122,0.15) !important;
    --badge-purple-fg:   #5c247a !important;

    --chart-1:           #05566e !important;
    --chart-2:           #4cc0a4 !important;
    --chart-3:           #f0a06a !important;
    --chart-4:           #a8306e !important;
    --chart-5:           #b00d33 !important;
    --chart-6:           #7b828c !important;
}

/* ── (b) Blanco y negro ─────────────────────────────────────────────────────────
   Sin tono: TODO se separa por luminosidad. Es la comprobación más dura que
   tiene el panel — lo que aquí deja de distinguirse es que dependía solo del
   color, y eso falla también para quien ve bien (una impresión en blanco y
   negro, una pantalla con poco brillo, sol directo sobre el móvil).
   Los seis estados se reparten la escala de grises en escalones amplios; si dos
   badges se ven iguales aquí, hay que separar sus grises, no volver al color.  */
html.a11y-mono:root:root:root:root:root {
    --bg:               #000000 !important;
    --bg-2:             #0a0a0a !important;
    --surface:          #141414 !important;
    --surface-2:        #1e1e1e !important;
    --surface-3:        #282828 !important;
    --surface-overlay:  #141414 !important;
    --panel:            #141414 !important;
    --panel-2:          #1e1e1e !important;
    --nav-bg:           #000000 !important;
    --nav-bg-2:         #0a0a0a !important;
    --nav-border:       #4d4d4d !important;
    --nav-shade:        #000000 !important;

    --control-bg:       #232323 !important;
    --control-bg-hover: #333333 !important;
    --control-border:   #666666 !important;
    --scrim:            rgba(0,0,0,0.78) !important;

    --text:             #f2f2f2 !important;
    --text-strong:      #ffffff !important;
    --muted:            #b8b8b8 !important;
    --muted-2:          #8f8f8f !important;

    --border:           #4d4d4d !important;
    --border-soft:      #333333 !important;

    --brand:            #ffffff !important;
    --brand-dark:       #4d4d4d !important;
    --brand-rgb:        255,255,255 !important;
    --brand-dark-rgb:   77,77,77 !important;
    --brand-soft-bg:    rgba(255,255,255,0.14) !important;
    --brand-soft-fg:    #ffffff !important;
    --accent:           #ffffff !important;

    --success:          #e0e0e0 !important;
    --danger:           #9c9c9c !important;
    --badge-success-bg: rgba(255,255,255,0.26) !important;
    --badge-success-fg: #ffffff !important;
    --badge-warn-bg:    rgba(255,255,255,0.20) !important;
    --badge-warn-fg:    #dcdcdc !important;
    --badge-danger-bg:  rgba(255,255,255,0.34) !important;
    --badge-danger-fg:  #000000 !important;
    --badge-info-bg:    rgba(255,255,255,0.14) !important;
    --badge-info-fg:    #c4c4c4 !important;
    --badge-neutral-bg: rgba(255,255,255,0.09) !important;
    --badge-neutral-fg: #a0a0a0 !important;
    --badge-purple-bg:  rgba(255,255,255,0.17) !important;
    --badge-purple-fg:  #cfcfcf !important;

    --tooltip-bg:       #ffffff !important;
    --tooltip-fg:       #000000 !important;

    --chart-1:           #d4d4d4 !important;
    --chart-2:           #a8a8a8 !important;
    --chart-3:           #eeeeee !important;
    --chart-4:           #7d7d7d !important;
    --chart-5:           #ffffff !important;
    --chart-6:           #5c5c5c !important;
    --chart-grid:        #333333 !important;
    --chart-axis:        #c9c9c9 !important;
    --chart-legend:      #ffffff !important;
    --chart-datalabel:   #000000 !important;
}

html.a11y-mono.light-mode:root:root:root:root:root {
    --bg:               #ffffff !important;
    --bg-2:             #f5f5f5 !important;
    --surface:          #ffffff !important;
    --surface-2:        #f0f0f0 !important;
    --surface-3:        #e4e4e4 !important;
    --surface-overlay:  #ffffff !important;
    --panel:            #ffffff !important;
    --panel-2:          #f0f0f0 !important;
    --nav-bg:           #ffffff !important;
    --nav-bg-2:         #f5f5f5 !important;
    --nav-border:       #999999 !important;
    --nav-shade:        #e4e4e4 !important;

    --control-bg:       #f0f0f0 !important;
    --control-bg-hover: #e0e0e0 !important;
    --control-border:   #8a8a8a !important;
    --scrim:            rgba(0,0,0,0.45) !important;

    --text:             #000000 !important;
    --text-strong:      #000000 !important;
    --muted:            #3d3d3d !important;
    --muted-2:          #5c5c5c !important;

    --border:           #999999 !important;
    --border-soft:      #d4d4d4 !important;

    --brand:            #000000 !important;
    --brand-dark:       #000000 !important;
    --brand-rgb:        0,0,0 !important;
    --brand-dark-rgb:   0,0,0 !important;
    --brand-soft-bg:    rgba(0,0,0,0.10) !important;
    --brand-soft-fg:    #000000 !important;
    --accent:           #000000 !important;

    --success:          #2b2b2b !important;
    --danger:           #000000 !important;
    --badge-success-bg: rgba(0,0,0,0.20) !important;
    --badge-success-fg: #000000 !important;
    --badge-warn-bg:    rgba(0,0,0,0.12) !important;
    --badge-warn-fg:    #2b2b2b !important;
    --badge-danger-bg:  #000000 !important;
    --badge-danger-fg:  #ffffff !important;
    --badge-info-bg:    rgba(0,0,0,0.07) !important;
    --badge-info-fg:    #4a4a4a !important;
    --badge-neutral-bg: rgba(0,0,0,0.05) !important;
    --badge-neutral-fg: #5c5c5c !important;
    --badge-purple-bg:  rgba(0,0,0,0.15) !important;
    --badge-purple-fg:  #1f1f1f !important;

    --tooltip-bg:       #000000 !important;
    --tooltip-fg:       #ffffff !important;

    /* Las sombras del tema claro llevan un tinte ciruela — `rgba(32,24,35,…)`—
       que a un 5-12 % de alfa no se ve, pero en una paleta que se llama «blanco
       y negro» no pinta nada. Las otras paletas SÍ las heredan a propósito: son
       neutras y no codifican ningún estado. */
    --shadow-sm:  0 1px 2px rgba(0,0,0,0.10) !important;
    --shadow-md:  0 4px 6px rgba(0,0,0,0.12), 0 2px 4px rgba(0,0,0,0.10) !important;
    --shadow-lg:  0 10px 25px rgba(0,0,0,0.18), 0 4px 8px rgba(0,0,0,0.10) !important;

    --chart-1:           #5e5e5e !important;
    --chart-2:           #8a8a8a !important;
    --chart-3:           #3b3b3b !important;
    --chart-4:           #a8a8a8 !important;
    --chart-5:           #111111 !important;
    --chart-6:           #c2c2c2 !important;
    --chart-grid:        #dcdcdc !important;
    --chart-axis:        #3d3d3d !important;
    --chart-legend:      #111111 !important;
    --chart-datalabel:   #ffffff !important;
}


/* ── Acromatopsia (daltonismo total) ────────────────────────────────────────────
   NO es la paleta «blanco y negro» con otro nombre, y por eso no la reutiliza.

   La acromatopsia congénita casi siempre viene con FOTOFOBIA: el mismo defecto
   que quita el color deja la visión dependiendo de los bastones, que se saturan
   con luz que a otra persona le parece normal. Un panel blanco brillante —o
   negro puro con texto blanco puro, que es el par de máximo deslumbramiento— no
   ayuda, molesta.

   Por eso:
   · Fondo gris muy oscuro (#161616), NO negro puro.
   · Texto gris claro (#d8d8d8), NO blanco puro. El par da ~11:1, de sobra para
     leer, sin el brillo del 21:1.
   · Ignora el modo claro a propósito: el mismo bloque sirve para los dos. Ofrecer
     una variante clara sería ofrecer justo lo que hay que evitar.
   · Los seis estados se separan por CLARIDAD en escalones amplios, como en la
     paleta monocroma — con el color no queda nada más de donde tirar.
   ─────────────────────────────────────────────────────────────────────────────── */
html.a11y-acro:root:root:root:root:root,
html.a11y-acro.light-mode:root:root:root:root:root {
    --bg:               #161616 !important;
    --bg-2:             #1b1b1b !important;
    --surface:          #202020 !important;
    --surface-2:        #262626 !important;
    --surface-3:        #2d2d2d !important;
    --surface-overlay:  #202020 !important;
    --panel:            #202020 !important;
    --panel-2:          #262626 !important;
    --nav-bg:           #161616 !important;
    --nav-bg-2:         #1b1b1b !important;
    --nav-border:       #454545 !important;
    --nav-shade:        #121212 !important;

    --control-bg:       #2a2a2a !important;
    --control-bg-hover: #343434 !important;
    --control-border:   #565656 !important;
    --scrim:            rgba(0,0,0,0.72) !important;

    /* Gris claro, no blanco: el blanco puro sobre gris muy oscuro es el par de
       máximo deslumbramiento, y es justo lo que hay que evitar aquí. */
    --text:             #d8d8d8 !important;
    --text-strong:      #ececec !important;
    --muted:            #a5a5a5 !important;
    --muted-2:          #838383 !important;

    --border:           #454545 !important;
    --border-soft:      #313131 !important;

    --brand:            #cfcfcf !important;
    --brand-dark:       #555555 !important;
    --brand-rgb:        207,207,207 !important;
    --brand-dark-rgb:   85,85,85 !important;
    --brand-soft-bg:    rgba(207,207,207,0.14) !important;
    --brand-soft-fg:    #dcdcdc !important;
    --accent:           #cfcfcf !important;

    --success:          #cfcfcf !important;
    --danger:           #8e8e8e !important;
    /* Seis estados repartidos por claridad, con el fondo del badge marcando el
       escalón grueso y el texto el fino. */
    --badge-success-bg: rgba(255,255,255,0.24) !important;
    --badge-success-fg: #ededed !important;
    --badge-warn-bg:    rgba(255,255,255,0.17) !important;
    --badge-warn-fg:    #cccccc !important;
    --badge-danger-bg:  rgba(255,255,255,0.32) !important;
    --badge-danger-fg:  #1a1a1a !important;
    --badge-info-bg:    rgba(255,255,255,0.11) !important;
    --badge-info-fg:    #b0b0b0 !important;
    --badge-neutral-bg: rgba(255,255,255,0.07) !important;
    --badge-neutral-fg: #949494 !important;
    --badge-purple-bg:  rgba(255,255,255,0.14) !important;
    --badge-purple-fg:  #c0c0c0 !important;

    --tooltip-bg:       #ececec !important;
    --tooltip-fg:       #161616 !important;

    --shadow-sm:  0 1px 2px rgba(0,0,0,0.40) !important;
    --shadow-md:  0 4px 6px rgba(0,0,0,0.45), 0 2px 4px rgba(0,0,0,0.40) !important;
    --shadow-lg:  0 12px 28px rgba(0,0,0,0.55), 0 4px 8px rgba(0,0,0,0.45) !important;

    --chart-1:           #c7c7c7 !important;
    --chart-2:           #a0a0a0 !important;
    --chart-3:           #dcdcdc !important;
    --chart-4:           #7c7c7c !important;
    --chart-5:           #ededed !important;
    --chart-6:           #5a5a5a !important;
    --chart-grid:        #3a3a3a !important;
    --chart-axis:        #c0c0c0 !important;
    --chart-legend:      #ededed !important;
    --chart-datalabel:   #1a1a1a !important;
}

/* ── (c) «Anti-daltónicos» — BROMA ──────────────────────────────────────────────
   Es un chiste y está etiquetado como tal en el menú. Hace justo lo contrario de
   (a): apoya todos los estados en el par rojo/verde que un deuteranope ve
   idéntico, y con luminosidades casi iguales para que tampoco el contraste los
   separe.
   Va en su propia sección del menú, bajo su rótulo de broma y separada de las
   opciones reales, para que nadie que necesite (a) la pulse por error.
   El mismo bloque sirve para claro y oscuro: la gracia es que no cambie nada.  */
html.a11y-broma:root:root:root:root:root,
html.a11y-broma.light-mode:root:root:root:root:root {
    --bg:               #2a2f1e !important;
    --bg-2:             #313620 !important;
    --surface:          #363b22 !important;
    --surface-2:        #3b4026 !important;
    --surface-3:        #414629 !important;
    --surface-overlay:  #363b22 !important;
    --panel:            #363b22 !important;
    --panel-2:          #3b4026 !important;
    --nav-bg:           #2a2f1e !important;
    --nav-bg-2:         #313620 !important;
    --nav-border:       #6d7a3a !important;
    --nav-shade:        #232817 !important;

    --control-bg:       #46512a !important;
    --control-bg-hover: #4f5a2f !important;
    --control-border:   #7a6b3a !important;
    --scrim:            rgba(40,45,25,0.7) !important;

    /* Oliva sobre oliva: el contraste justo para que se lea… poco. */
    --text:             #b9a94e !important;
    --text-strong:      #c9b84f !important;
    --muted:            #8f8a45 !important;
    --muted-2:          #7d7a3f !important;

    --border:           #6d7a3a !important;
    --border-soft:      #5b6531 !important;

    --brand:            #9a8f3d !important;
    --brand-dark:       #6f6a2c !important;
    --brand-rgb:        154,143,61 !important;
    --brand-dark-rgb:   111,106,44 !important;
    --brand-soft-bg:    rgba(154,143,61,0.25) !important;
    --brand-soft-fg:    #b9a94e !important;
    --accent:           #9a8f3d !important;

    /* Los seis estados, en rojo y verde de la MISMA luminosidad. */
    --success:          #6f9c3d !important;
    --danger:           #9c6f3d !important;
    --badge-success-bg: rgba(111,156,61,0.28) !important;
    --badge-success-fg: #7fa84a !important;
    --badge-warn-bg:    rgba(140,140,55,0.28) !important;
    --badge-warn-fg:    #8f8f42 !important;
    --badge-danger-bg:  rgba(156,111,61,0.28) !important;
    --badge-danger-fg:  #a8804a !important;
    --badge-info-bg:    rgba(125,140,60,0.28) !important;
    --badge-info-fg:    #869145 !important;
    --badge-neutral-bg: rgba(130,130,70,0.24) !important;
    --badge-neutral-fg: #8a8a4c !important;
    --badge-purple-bg:  rgba(150,120,60,0.26) !important;
    --badge-purple-fg:  #9a854a !important;

    --tooltip-bg:       #46512a !important;
    --tooltip-fg:       #b9a94e !important;

    --chart-1:           #6f9c3d !important;
    --chart-2:           #7d9440 !important;
    --chart-3:           #8f8f42 !important;
    --chart-4:           #87883f !important;
    --chart-5:           #9c6f3d !important;
    --chart-6:           #94773d !important;
}

/* ── Botón y panel de accesibilidad ────────────────────────────────────────────
   El botón vive en el header, junto al de guías. El panel es un popover anclado
   a él. Usa `--surface-overlay` y no `--surface`: flota sobre el contenido y con
   la superficie translúcida se veía casi invisible en oscuro.                  */
.ph-a11y-wrap { position: relative; display: inline-flex; }

.ph-a11y-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 9px;
    border: 1px solid var(--control-border);
    background: var(--control-bg);
    color: var(--text);
    cursor: pointer;
    transition: background .15s ease, border-color .15s ease;
}
.ph-a11y-btn:hover { background: var(--control-bg-hover); }
.ph-a11y-btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
/* Encendido = hay una paleta de accesibilidad activa. Sin esta marca, el único
   indicio de que el panel está en otra paleta es el color — que es justo lo que
   estas opciones cambian. */
.ph-a11y-btn.is-on {
    background: var(--brand-soft-bg);
    border-color: var(--brand);
    color: var(--brand-soft-fg);
}

.ph-a11y-panel {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 1200;
    width: 292px;
    padding: 12px;
    border-radius: 12px;
    border: 1px solid var(--border);
    background: var(--surface-overlay);
    box-shadow: var(--shadow-lg);
    /* Con los seis tipos de daltonismo desplegados el panel pasa de la altura de
       una pantalla baja. Scrollea por dentro en vez de crecer: si crece, la
       escala de letra y el botón de reiniciar quedan fuera de la vista, y son
       justo lo que busca quien abre esto. */
    max-height: min(76vh, 620px);
    overflow-y: auto;
    overscroll-behavior: contain;
}

.ph-a11y-title {
    font-size: .74rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--muted);
    margin: 0 0 6px;
}
.ph-a11y-title + .ph-a11y-title { margin-top: 14px; }

.ph-a11y-opt {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    width: 100%;
    padding: 7px 8px;
    border: 1px solid transparent;
    border-radius: 9px;
    background: none;
    color: var(--text);
    text-align: left;
    cursor: pointer;
}
.ph-a11y-opt:hover { background: var(--control-bg); }
.ph-a11y-opt:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.ph-a11y-opt.is-on {
    background: var(--brand-soft-bg);
    border-color: var(--brand);
}

/* Muestra de la paleta: tres cuadros con los colores que de verdad cambian.
   Un nombre solo no dice nada — «daltonismo» no explica qué va a pasar. */
.ph-a11y-swatches { display: flex; gap: 3px; flex: 0 0 auto; margin-top: 2px; }
.ph-a11y-sw {
    width: 12px;
    height: 12px;
    border-radius: 3px;
    border: 1px solid var(--border-soft);
}

/* Tipos de daltonismo: cuelgan de «Daltonismo», así que se sangran y llevan una
   guía a la izquierda. Sin la sangría se leen como cuatro paletas más al mismo
   nivel, y son una elección DENTRO de una. */
.ph-a11y-opt.is-sub {
    margin-left: 10px;
    padding-left: 10px;
    border-left: 2px solid var(--border-soft);
    border-radius: 0 9px 9px 0;
}
.ph-a11y-opt.is-sub.is-on { border-left-color: var(--brand); }

/* Familia del tipo (rojo-verde / azul-amarillo). Es el dato que decide la
   paleta —qué eje de color se pierde—, así que encabeza su grupo. */
.ph-a11y-fam {
    margin: 8px 0 3px 20px;
    font-size: .68rem;
    color: var(--muted-2);
}

/* Leyenda de las muestras. Alineada con la columna de cuadritos (10px de padding
   de la fila) para que se lea como su cabecera y no como un texto suelto. */
.ph-a11y-hint {
    margin: -2px 0 6px 10px;
    font-size: .64rem;
    letter-spacing: .02em;
    color: var(--muted-2);
}

.ph-a11y-opt-txt { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.ph-a11y-opt-name { font-size: .82rem; }
.ph-a11y-opt-desc { font-size: .7rem; color: var(--muted); line-height: 1.35; }

/* Escala de letra. El valor va en el medio y los botones a los lados: es un
   control de «más/menos», no una lista de tamaños. */
.ph-a11y-scale {
    display: grid;
    grid-template-columns: 38px 1fr 38px;
    align-items: center;
    gap: 8px;
}
.ph-a11y-scale-btn {
    height: 34px;
    border-radius: 9px;
    border: 1px solid var(--control-border);
    background: var(--control-bg);
    color: var(--text);
    cursor: pointer;
    font-size: .95rem;
}
.ph-a11y-scale-btn:hover:not(:disabled) { background: var(--control-bg-hover); }
.ph-a11y-scale-btn:disabled { opacity: .4; cursor: default; }
.ph-a11y-scale-val {
    text-align: center;
    font-size: .84rem;
    color: var(--text-strong);
    font-variant-numeric: tabular-nums;
}

.ph-a11y-reset {
    width: 100%;
    margin-top: 12px;
    padding: 7px;
    border-radius: 9px;
    border: 1px solid var(--control-border);
    background: none;
    color: var(--muted);
    font-size: .76rem;
    cursor: pointer;
}
.ph-a11y-reset:hover { background: var(--control-bg); color: var(--text); }

/* Backdrop invisible: cierra al pulsar fuera sin robar el foco ni oscurecer. */
.ph-a11y-backdrop {
    position: fixed;
    inset: 0;
    z-index: 1199;
    background: transparent;
    border: none;
    cursor: default;
}

/* ── Constructor de plantillas de Meta (Campañas → Plantillas) ──────────────────
   Formulario con tokens del tema; la burbuja imita WhatsApp con sus colores fijos
   (excepción intencional, como la tarjeta de login), para que la previsualización
   se lea igual que en la app en los dos temas. */
.tpl-builder { max-width: 960px; }
.tpl-builder-grid {
    display: grid;
    grid-template-columns: 1.2fr 0.8fr;
    gap: 18px;
    padding: 4px;
}
@media (max-width: 760px) { .tpl-builder-grid { grid-template-columns: 1fr; } }

.tpl-form { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.tpl-lbl {
    font-size: 0.8rem;
    font-weight: 600;
    color: var(--text-strong);
    margin-top: 8px;
}
.tpl-hint { font-size: 0.72rem; color: var(--muted); margin: 2px 0 4px; }
.tpl-row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.tpl-body { font-family: inherit; resize: vertical; }
.tpl-ex { margin-top: 4px; }
.tpl-examples { display: flex; flex-direction: column; gap: 4px; }
.tpl-addvar { align-self: flex-start; font-size: 0.76rem; margin-top: 2px; }

.tpl-btns-head {
    display: flex; align-items: center; justify-content: space-between;
    margin-top: 8px;
}
.tpl-btn-row { display: flex; gap: 6px; align-items: center; margin-top: 4px; }
.tpl-btn-type { flex: 0 0 130px; }
.tpl-btn-del { flex: 0 0 auto; }
.tpl-row-actions { display: flex; gap: 4px; align-items: center; flex-wrap: wrap; }
.tpl-reject { color: var(--badge-danger-fg); font-size: 0.72rem; }

.tpl-builder-foot {
    display: flex; justify-content: flex-end; gap: 8px;
    margin-top: 14px; padding: 10px 4px 2px;
    border-top: 1px solid var(--border);
}

/* Previsualización — imita el chat de WhatsApp (colores fijos, a propósito). */
.tpl-preview { display: flex; flex-direction: column; gap: 6px; }
.tpl-phone {
    background: #e5ddd5;                 /* fondo de chat de WhatsApp */
    border-radius: 12px;
    padding: 16px 12px;
    min-height: 180px;
}
.tpl-bubble {
    background: #ffffff;                 /* burbuja entrante (plantilla), blanca */
    color: #111b21;
    border-radius: 10px;
    padding: 10px 12px;
    max-width: 100%;
    box-shadow: 0 1px 1px rgba(0,0,0,0.15);
    word-break: break-word;
}
.tpl-bubble-header { font-weight: 700; margin-bottom: 6px; white-space: pre-wrap; }
.tpl-bubble-body { white-space: pre-wrap; line-height: 1.4; }
.tpl-bubble-empty { color: #667781; font-style: italic; }
.tpl-bubble-footer { font-size: 0.78rem; color: #667781; margin-top: 8px; white-space: pre-wrap; }
.tpl-bubble-btns { display: flex; flex-direction: column; gap: 4px; margin-top: 6px; }
.tpl-bubble-btn {
    background: #ffffff;
    color: #027eb5;                      /* azul de acción de WhatsApp */
    text-align: center;
    border-radius: 8px;
    padding: 7px;
    font-size: 0.86rem;
    font-weight: 500;
    box-shadow: 0 1px 1px rgba(0,0,0,0.15);
/* ── Instagram · publicaciones, comentarios e insights (pages/instagram.rs) ──
   Solo tokens de tema. Los únicos colores fijos son los del degradado sobre
   la foto (texto blanco sobre sombra negra): van sobre la imagen, no sobre
   una superficie del tema, así que no cambian entre claro y oscuro. */
.ig-page { padding: 28px 32px; display: flex; flex-direction: column; gap: 16px; }
.ig-error { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.ig-topbar { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.ig-select, .ig-search {
  background: var(--control-bg); border: 1px solid var(--control-border); color: var(--text);
  border-radius: 10px; padding: 8px 12px; font-size: 14px;
}
.ig-select:hover, .ig-search:hover { background: var(--control-bg-hover); }
.ig-search { min-width: 260px; flex: 1; }
.ig-account-card {
  display: flex; align-items: center; gap: 18px; flex: 1; min-width: 320px; padding: 16px 20px;
  border: 1px solid var(--border); border-radius: 16px; background: var(--surface); box-shadow: var(--shadow-sm);
}
.ig-avatar { width: 64px; height: 64px; border-radius: 50%; object-fit: cover; background: var(--panel-2); flex: none; }
.ig-avatar-ph { display: flex; align-items: center; justify-content: center; font-size: 28px; }
.ig-account-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.ig-username { font-weight: 700; font-size: 18px; color: var(--text-strong); }
.ig-name { color: var(--muted); font-size: 13px; }
.ig-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 4px; }
.ig-chip {
  display: inline-flex; align-items: center; gap: 4px; padding: 2px 9px; border-radius: 999px;
  font-size: 11.5px; font-weight: 600; background: var(--badge-neutral-bg); color: var(--badge-neutral-fg);
}
.ig-chip--ok { background: var(--badge-success-bg); color: var(--badge-success-fg); }
.ig-chip--warn { background: var(--badge-warn-bg); color: var(--badge-warn-fg); }
.ig-chip--off { background: var(--badge-danger-bg); color: var(--badge-danger-fg); }
.ig-stats { display: flex; gap: 22px; }
.ig-stat { text-align: center; }
.ig-stat-n { font-size: 20px; font-weight: 700; color: var(--text-strong); }
.ig-stat-l { font-size: 11.5px; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; }
.ig-tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--border); }
.ig-tab {
  background: none; border: none; border-bottom: 2px solid transparent; padding: 10px 14px;
  color: var(--muted); font-weight: 600; cursor: pointer; font-size: 14px;
}
.ig-tab:hover { color: var(--text); }
.ig-tab.active { color: var(--brand); border-bottom-color: var(--brand); }
.ig-toolbar { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.ig-check { display: inline-flex; align-items: center; gap: 6px; color: var(--muted); font-size: 13px; cursor: pointer; }
.ig-refresh { margin-left: auto; }
.ig-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 14px; }
.ig-card {
  border: 1px solid var(--border); border-radius: 14px; background: var(--surface); overflow: hidden;
  cursor: pointer; transition: transform .15s ease, box-shadow .15s ease; display: flex; flex-direction: column;
}
.ig-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); }
.ig-thumb-wrap { position: relative; aspect-ratio: 1 / 1; background: var(--panel-2); }
.ig-thumb { width: 100%; height: 100%; object-fit: cover; display: block; }
.ig-thumb-ph { display: flex; align-items: center; justify-content: center; font-size: 40px; color: var(--muted); }
.ig-type-badge {
  position: absolute; top: 8px; left: 8px; padding: 2px 8px; border-radius: 999px; font-size: 11px; font-weight: 600;
  background: var(--surface-overlay); color: var(--text); box-shadow: var(--shadow-sm);
}
.ig-type-badge--inline { position: static; }
.ig-agent-badge {
  position: absolute; top: 8px; right: 8px; padding: 2px 8px; border-radius: 999px; font-size: 11px; font-weight: 700;
  background: var(--brand-dark); color: #fff;
}
.ig-card-overlay {
  position: absolute; left: 0; right: 0; bottom: 0; display: flex; gap: 12px; padding: 6px 10px;
  font-size: 12px; font-weight: 600; color: #fff; background: linear-gradient(transparent, rgba(0, 0, 0, .55));
}
.ig-card-body { padding: 10px 12px 12px; display: flex; flex-direction: column; gap: 4px; }
.ig-caption { font-size: 13px; color: var(--text); line-height: 1.35; }
.ig-meta { font-size: 12px; color: var(--muted); }
.ig-more { display: flex; justify-content: center; padding: 8px 0 4px; }
.ig-empty {
  padding: 36px 16px; text-align: center; color: var(--muted); border: 1px dashed var(--border);
  border-radius: 14px; background: var(--surface);
}
.ig-empty--hero { padding: 56px 16px; }
.ig-empty-icon { font-size: 40px; margin-bottom: 8px; }
.ig-empty h3 { color: var(--text-strong); margin: 0 0 6px; }
.ig-empty p { margin: 0; }
.ig-skeleton {
  min-height: 280px; border-color: transparent;
  background: linear-gradient(90deg, var(--skel-base), var(--skel-hi), var(--skel-base));
  background-size: 200% 100%; animation: ig-shimmer 1.2s infinite;
}
.ig-skeleton-card { min-height: 96px; }
@keyframes ig-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

.ig-modal-backdrop {
  position: fixed; inset: 0; background: var(--scrim); display: flex; align-items: center; justify-content: center;
  z-index: 120; padding: 20px;
}
.ig-modal {
  position: relative; width: min(1100px, 100%); max-height: 92vh; display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(320px, .9fr); grid-template-rows: minmax(0, 1fr);
  background: var(--surface-overlay); border: 1px solid var(--border); border-radius: 18px;
  box-shadow: var(--shadow-lg); overflow: hidden;
}
.ig-modal--loading { display: block; width: min(420px, 100%); padding: 20px; }
.ig-modal-close {
  position: absolute; top: 10px; right: 10px; z-index: 2; border: none; background: var(--control-bg);
  color: var(--text); width: 32px; height: 32px; border-radius: 50%; cursor: pointer;
}
.ig-modal-close:hover { background: var(--control-bg-hover); }
.ig-modal-media { background: var(--panel-2); display: flex; flex-direction: column; min-height: 0; }
.ig-modal-img, .ig-modal-video { width: 100%; flex: 1; max-height: 78vh; object-fit: contain; background: var(--bg-2); }
.ig-modal-ph { flex: 1; font-size: 64px; }
.ig-carousel-strip { display: flex; gap: 6px; padding: 8px; overflow-x: auto; background: var(--surface-2); }
.ig-carousel-dot {
  width: 56px; height: 56px; flex: none; border-radius: 8px; overflow: hidden; border: 2px solid transparent;
  background: var(--panel-2); padding: 0; cursor: pointer;
}
.ig-carousel-dot img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ig-carousel-dot.active { border-color: var(--brand); }
.ig-carousel-vid { display: flex; align-items: center; justify-content: center; height: 100%; }
.ig-modal-side { padding: 18px 20px; min-height: 0; max-height: 92vh; overflow-y: auto; display: flex; flex-direction: column; gap: 12px; }
.ig-modal-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding-right: 36px; }
.ig-modal-caption { margin: 0; white-space: pre-wrap; font-size: 14px; color: var(--text); line-height: 1.45; }
.ig-link-btn {
  background: none; border: none; padding: 0; color: var(--brand); font-weight: 600; cursor: pointer;
  text-decoration: none; font-size: 13px;
}
.ig-link-btn:hover { text-decoration: underline; }
.ig-insights, .ig-totals { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 8px; }
.ig-insight { padding: 10px 12px; border-radius: 12px; background: var(--surface-2); border: 1px solid var(--border-soft); }
.ig-insight-n { font-size: 18px; font-weight: 700; color: var(--text-strong); }
.ig-insight-l { font-size: 11.5px; color: var(--muted); }
.ig-note { font-size: 12.5px; color: var(--muted); padding: 8px 10px; border-radius: 10px; background: var(--surface-2); }
.ig-section-title {
  margin: 6px 0 0; font-size: 13px; font-weight: 700; color: var(--text-strong); text-transform: uppercase;
  letter-spacing: .05em; display: flex; align-items: center; gap: 8px;
}
.ig-count { font-weight: 600; color: var(--muted); }
.ig-comments, .ig-agent-list { display: flex; flex-direction: column; gap: 8px; }
.ig-comment, .ig-agent-item {
  padding: 10px 12px; border-radius: 12px; background: var(--surface-2); border: 1px solid var(--border-soft);
  display: flex; flex-direction: column; gap: 4px;
}
.ig-comment--own { border-color: rgba(var(--brand-rgb), .45); background: var(--brand-soft-bg); }
.ig-comment-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.ig-comment-user { font-weight: 700; font-size: 13px; color: var(--text-strong); }
.ig-comment-text { font-size: 13.5px; color: var(--text); white-space: pre-wrap; }
.ig-replies { margin-top: 6px; padding-left: 12px; border-left: 2px solid var(--border); display: flex; flex-direction: column; gap: 6px; }
.ig-agent-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
.ig-more-comments { align-self: flex-start; }
.ig-metrics { display: flex; flex-direction: column; gap: 14px; }
.ig-chart-card { padding: 14px 16px; border: 1px solid var(--border); border-radius: 14px; background: var(--surface); }
.ig-chart-head { display: flex; justify-content: space-between; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 10px; }
.ig-bars { display: flex; align-items: flex-end; gap: 3px; height: 140px; }
.ig-bar { flex: 1; height: 100%; display: flex; align-items: flex-end; }
.ig-bar-fill { width: 100%; border-radius: 4px 4px 0 0; background: var(--chart-1); min-height: 2px; transition: height .2s ease; }
.ig-bar:hover .ig-bar-fill { background: var(--chart-accent); }
@media (max-width: 860px) {
  .ig-modal { grid-template-columns: 1fr; grid-template-rows: auto auto; overflow-y: auto; }
  .ig-modal-side { max-height: none; overflow: visible; }
  .ig-modal-img, .ig-modal-video { max-height: 50vh; }
  .ig-stats { width: 100%; justify-content: space-around; }
}
