/* ========================================================================
   Aivacy
   Chrome de marca Aivacy: identidad cyberblue + acción naranja sobre neutros
   warm-grey (AIV-144). Cada tenant sobrescribe en runtime las dos familias de
   acento — --accent* (identidad) y --accent-2* (acción) — desde el config del
   cliente; layout/main.html inyecta las 8 variables en el <body>.
   ======================================================================== */

/* Tipografía de marca — autohospedada (la CSP exige font-src 'self').
   Ficheros variables: un woff2 por familia/estilo cubre todos los pesos. */
@font-face {
  font-family: "Nunito";
  src: url("/fonts/nunito-vf.woff2") format("woff2");
  font-weight: 200 1000;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Open Sans";
  src: url("/fonts/open-sans-vf.woff2") format("woff2");
  font-weight: 300 800;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Open Sans";
  src: url("/fonts/open-sans-italic-vf.woff2") format("woff2");
  font-weight: 300 800;
  font-style: italic;
  font-display: swap;
}
@font-face {
  font-family: "Lora";
  src: url("/fonts/lora-vf.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

:root {
  /* Neutros warm-grey de marca (superficies y chrome Aivacy). Los nombres
     --aivacy-* se conservan por compatibilidad con el chrome existente; los
     valores pasan de grafito/plata frío a la escala cálida de la nueva marca. */
  --aivacy-ink:          #2B2926;   /* casi negro cálido */
  --aivacy-graphite:     #4B4845;   /* warm grey dark */
  --aivacy-silver-dark:  #6D655D;
  --aivacy-silver:       #968C83;   /* warm grey */
  --aivacy-silver-light: #CBC4BC;   /* warm grey light */
  --aivacy-mist:         #ECE7E1;   /* off-white cálido */

  /* Alias semánticos de los neutros (nomenclatura de las guidelines) */
  --warm-grey-light: var(--aivacy-silver-light);  /* #CBC4BC */
  --warm-grey:       var(--aivacy-silver);        /* #968C83 */
  --warm-grey-dark:  var(--aivacy-graphite);      /* #4B4845 */
  --gold:      #AF8D5D;   /* oro viejo (complementario) */
  --limestone: #CFC6B4;   /* caliza (complementario) */
  --topbar:    #000000;   /* negro de la topbar */

  /* Acento primario / identidad (default = cyberblue Aivacy; cada tenant lo pisa).
     -light inicia degradados, -dark hover/bordes, -soft fondos tintados. */
  --accent:       #00A499;   /* cyberblue base — Pantone 315 C */
  --accent-light: #00A3AD;
  --accent-dark:  #004147;
  --accent-soft:  #DDF8F6;

  /* Acento secundario / acción-UX (default = burnt orange; cada tenant lo pisa).
     Se usa en CTAs, botones, iconos y links de acción, callouts de atención.
     Para TEXTO/links de acción usar --accent-2-dark (contraste AA); el gradiente
     light→base queda reservado a fills de botón con texto blanco. */
  --accent-2:       #F28C48;   /* burnt orange base — Pantone 158 U */
  --accent-2-light: #F7A335;
  --accent-2-dark:  #91542B;
  --accent-2-soft:  #F6E8DF;

  /* Alias semánticos de rol (legibilidad): identidad vs. acción */
  --brand:  var(--accent);
  --action: var(--accent-2);

  /* Color fijo de las referencias/citas del chat (AIV-107). NO se themea por
     tenant: con acentos vivos el número parecía un error y el ámbar de las citas
     débiles perdía su sentido de cautela. Neutro cálido → el ámbar weak es la
     única señal con mensaje. */
  --cite:      #4B4845;
  --cite-soft: #ECE7E1;

  /* Paleta de categorías para gráficos, liderada por la marca: cyberblue
     (primario) y burnt orange (secundario) abren la serie; el resto son
     colores de apoyo que armonizan con ese par. Se fijan en HEX (no
     var(--accent)) a propósito: la lectura de las series no cambia según el
     tenant, para que un gráfico sea comparable entre clientes.
     15 tonos porque el gráfico más ancho (por operación LLM) puede tener hasta
     11 series: así nunca se cicla la paleta (dos series con el mismo color).
     Validada con el script de dataviz (banda de luminosidad, chroma y CVD de
     pares adyacentes en el orden de la leyenda). Más allá de ~8 colores la
     distinción por color deja de ser fiable con daltonismo (límite del propio
     espacio de color): la identidad la refuerzan siempre la leyenda y el
     tooltip de cada gráfico, no solo el color. */
  --chart-1:  #00A499;  /* cyberblue · primario */
  --chart-2:  #F28C48;  /* burnt orange · secundario */
  --chart-3:  #7B3FE4;  /* violeta */
  --chart-4:  #2E9E4A;  /* verde */
  --chart-5:  #E23B7A;  /* rosa */
  --chart-6:  #2F72E0;  /* azul */
  --chart-7:  #E4A11B;  /* oro */
  --chart-8:  #D6453A;  /* rojo teja */
  --chart-9:  #17A2B8;  /* cian */
  --chart-10: #9B59B6;  /* orquídea */
  --chart-11: #6B8E23;  /* oliva */
  --chart-12: #C2185B;  /* magenta */
  --chart-13: #3F51B5;  /* índigo */
  --chart-14: #B4531F;  /* siena */
  --chart-15: #00897B;  /* teal profundo */
  /* Tonos de avatar: la inicial de cada persona va en blanco sobre uno de estos fondos,
     elegido por AvatarSupport a partir de su correo. Son las mismas familias de color que la
     paleta de gráficos pero oscurecidas, porque aquí el color es fondo de texto y no relleno de
     una barra: todos pasan de 5,5:1 de contraste con el blanco. No usan var(--accent) a propósito
     —si todos los avatares fueran del acento del tenant no distinguirían a nadie, que es el
     estado del que se viene. Diez y no más: por encima, los tonos que caben en esta banda de
     luminosidad se empiezan a repetir a 22 px (los descartados fueron índigo y cian, a ΔE 10 y 13
     de azul y teal, que a ese tamaño son el mismo color). El peor par que queda está a ΔE 21, y
     el color nunca es la única señal: al lado va siempre el nombre. */
  --avatar-1:  #00615C;  /* teal profundo */
  --avatar-2:  #91542B;  /* burnt orange oscuro */
  --avatar-3:  #5B32A8;  /* violeta */
  --avatar-4:  #1F6B33;  /* verde */
  --avatar-5:  #A32458;  /* rosa */
  --avatar-6:  #1F51A8;  /* azul */
  --avatar-7:  #9E2C23;  /* rojo teja */
  --avatar-8:  #55701C;  /* oliva */
  --avatar-9:  #7A3E91;  /* orquídea */
  --avatar-10: #46596B;  /* pizarra */

  --chart-soft-1: #DDF8F6;
  --chart-soft-2: #FBE7D6;
  --chart-soft-3: #ECE6FC;
  --chart-soft-4: #DCF3E2;
  --chart-soft-5: #FBE0EC;

  /* Texto y superficies — escala cálida de marca (off-white cálido) */
  --text: #2B2926;
  --text-muted: #6D655D;
  --text-soft: #968C83;
  --border: #D8D2CB;
  --border-soft: #ECE7E1;
  --border-strong: #B9B1A8;
  --bg: #FFFFFF;
  --bg-soft: #FAF8F4;      /* off-white cálido */
  --bg-app: #F4F1EC;       /* superficie de plataforma, off-white cálido */
  --bg-code: #F7F4EF;

  /* Velo de marca de los fondos de layout (main/app/auth): un tinte muy tenue
     sobre el off-white cálido, sin llegar a color plano (alfas <= .07 para no
     alterar el contraste del texto). Cyberblue en entorno Aivacy puro; los
     tenants lo pisan por warm-grey en body:not([data-tenant="default"]) para
     no competir con su acento propio (el acento del cliente vive en el chrome,
     no en el lienzo). */
  --surface-gradient:
    radial-gradient(1100px 620px at 100% -5%, rgba(0,164,153,.07), transparent 60%),
    linear-gradient(158deg, rgba(0,164,153,.05) 0%, transparent 46%);

  --green: #1F883D;
  --amber: #D29922;
  --red: #CF222E;
  --blue: #0969DA;
  --green-soft: #E4F3E8;
  --amber-soft: #FAF0D9;
  --red-soft: #FBE6E7;
  /* Lo informativo de las tarjetas de indicadores. Fijo y no el acento del tenant:
     con un acento rojo todo se leía como error y con uno verde, como «todo bien». */
  --info: #4A4540;
  --info-soft: #EFEBE6;
  --purple: #8250DF;
  --shadow-sm: 0 1px 2px rgba(0,0,0,.05);
  --shadow: 0 4px 14px rgba(0, 0, 0, 0.08);
  --shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.14);
  --radius-sm: 4px;
  --radius: 6px;
  --radius-lg: 10px;
  --radius-pill: 999px;

  /* Tipografía (spec del creativo): titulares Nunito SemiBold,
     bloques de texto Open Sans, destacados Lora */
  --font-heading: "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-body: "Open Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", Helvetica, Arial, sans-serif;
  --font-accent: "Lora", Georgia, "Times New Roman", serif;

  /* Pesos tipográficos de marca. Nunca Open Sans Bold/Extrabold (700/800):
     los resaltados y titulares llegan hasta SemiBold (600). */
  --weight-light:    300;   /* Open Sans Light — bodycopy/display ligero */
  --weight-body:     400;   /* cuerpo por defecto para UI densa */
  --weight-medium:   500;   /* Nunito/Open Sans Medium — botones estáticos, nav */
  --weight-semibold: 600;   /* Nunito SemiBold / Open Sans Semibold — titulares y resaltados */
}

/* Tema demo: cliente sin marca propia → chrome 100% Aivacy.
   Ejemplos de override por cliente (se aplican poniendo data-tenant en <body>):
*/
body[data-tenant="ge-vernova"] {
  --accent:      #00A859;   /* verde GE Vernova */
  --accent-dark: #007E44;
  --accent-soft: #DCF5E7;
}
body[data-tenant="acme-bank"] {
  --accent:      #0B3A82;
  --accent-dark: #082A60;
  --accent-soft: #E2EAF6;
}

/* Entorno de cliente (cualquier tenant reconocido): el velo de los fondos pasa
   de cyberblue a warm-grey neutro, para que el lienzo no compita con el acento
   propio del tenant. Aivacy puro entra por data-tenant="default" y conserva el
   velo cyberblue de :root. */
body:not([data-tenant="default"]) {
  --surface-gradient:
    radial-gradient(1100px 620px at 100% -5%, rgba(150,140,131,.11), transparent 60%),
    linear-gradient(158deg, rgba(150,140,131,.08) 0%, transparent 46%);
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 14px;
  line-height: 1.5;
  color: var(--text);
  background: var(--surface-gradient), var(--bg-soft);
  background-attachment: fixed;
}

h1, h2, h3, h4 {
  font-family: var(--font-heading);
  font-weight: 600;
}

a { color: var(--accent); text-decoration: none; }
a:hover {
  text-decoration: underline;
  text-decoration-thickness: from-font;
  text-underline-offset: .18em;
}
/* Link de accion (CTA inline): burnt dark, cumple AA sobre fondos claros. */
a.link-action { color: var(--accent-2-dark); font-weight: var(--weight-medium); }

/* ========================================================================
   Superficies del navegador
   Selección, cursor, barras de desplazamiento, anillo de foco y controles
   nativos vienen con el color del sistema operativo, que no es de nadie. Se
   tiñen desde la paleta para que la parte de la pantalla que no dibujamos
   pertenezca también al producto.
   ======================================================================== */

::selection {
  background: var(--accent-soft);
  color: var(--accent-dark);
}

:root {
  --focus-ring: 0 0 0 2px var(--bg), 0 0 0 4px var(--accent);
}

input, textarea, [contenteditable] { caret-color: var(--accent); }

/* Marcas de formulario nativas (checkbox, radio, barra de progreso). */
input[type="checkbox"], input[type="radio"], progress { accent-color: var(--accent); }

/* Firefox toma la forma corta; WebKit necesita los pseudoelementos. La barra
   vive sobre superficies claras, así que el pulgar es el neutro cálido medio
   y no un gris del sistema. */
* {
  scrollbar-width: thin;
  scrollbar-color: var(--border-strong) transparent;
}
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb {
  background: var(--border-strong);
  border: 3px solid transparent;
  background-clip: content-box;
  border-radius: 999px;
}
::-webkit-scrollbar-thumb:hover { background-color: var(--warm-grey); background-clip: content-box; }
::-webkit-scrollbar-corner { background: transparent; }

/* Cifras comparables: en una columna de números la anchura variable de los
   dígitos proporcionales desalinea las unidades y obliga a releer. */
table, .kpi-card .value, .num, time, .asof {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* ========================================================================
   Standalone prototype page chrome — only seen on those pages themselves
   ======================================================================== */

.wf-topbar {
  background: white;
  border-bottom: 3px solid var(--aivacy-silver-light);
  padding: 14px 28px;
  display: flex;
  align-items: center;
  gap: 18px;
  position: sticky;
  top: 0;
  z-index: 200;
  box-shadow: var(--shadow-sm);
}
.wf-topbar .brand { display: flex; align-items: center; gap: 12px; color: inherit; text-decoration: none; }
.wf-topbar .brand img { height: 26px; }
.wf-topbar .brand .doc-title {
  font-size: 12px;
  color: var(--text-muted);
  border-left: 1px solid var(--border);
  padding-left: 12px;
  letter-spacing: .3px;
}
.wf-topbar .brand .doc-title strong {
  color: var(--aivacy-graphite);
  display: block;
  font-size: 13px;
  letter-spacing: 0;
}
.wf-topbar .wf-screen-title {
  font-size: 15px;
  font-weight: 600;
}
.wf-topbar .wf-screen-meta {
  font-size: 12px;
  color: var(--text-muted);
  margin-left: 4px;
}
.wf-topbar .wf-nav {
  margin-left: auto;
  display: flex;
  gap: 14px;
  align-items: center;
  font-size: 13px;
}
.wf-topbar .wf-nav a {
  color: var(--text-muted);
  font-weight: 500;
}
.wf-topbar .wf-nav a:hover { color: var(--aivacy-graphite); text-decoration: none; }
.wf-topbar .wf-nav .pill {
  background: var(--aivacy-mist);
  color: var(--aivacy-graphite);
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .4px;
}

.wf-stage {
  max-width: 1380px;
  margin: 24px auto 60px;
  padding: 0 24px;
}

.wf-callout {
  background: var(--aivacy-mist);
  border-left: 4px solid var(--aivacy-silver);
  padding: 12px 16px;
  border-radius: 4px;
  margin-bottom: 18px;
  font-size: 13px;
  color: var(--text);
}
.wf-callout strong { color: var(--aivacy-graphite); }

.wf-frame {
  background: white;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  overflow: hidden;
}

.wf-foot {
  margin-top: 20px;
  display: flex;
  justify-content: space-between;
  font-size: 12px;
  color: var(--text-muted);
}
.wf-foot a { color: var(--text-muted); }
.wf-foot a:hover { color: var(--aivacy-graphite); }

/* ========================================================================
   App chrome (header, sidebar, main)
   ======================================================================== */

.app {
  display: grid;
  grid-template-columns: 232px 1fr;
  grid-template-rows: auto 1fr;
  /* Shell fijado a la altura del viewport: el chrome (topbar + sidebar) queda anclado y
     el contenido desplaza dentro de .app-main. Así el menú de usuario del pie del sidebar
     (Opción C) es siempre alcanzable en lugar de caer al final de páginas largas. */
  height: 100vh;
  overflow: hidden;
  background: var(--surface-gradient), var(--bg-app);
}

/* App header — pieza de marca (Opción C): foto + logo calado + descriptivo del entorno.
   Sin controles funcionales: bajan al menú de usuario del pie del sidebar. La excepción es
   select-client (no tiene sidebar): allí la cabecera sí muestra el menú de usuario.
   La foto por defecto es la de Aivacy; un tenant la pisa con su hero vía --topbar-photo
   inyectada en línea. El scrim (gradiente oscuro a izquierda y derecha) garantiza el
   contraste AA del logo y el descriptivo sin oscurecer el centro de la foto. */
.app-header {
  grid-column: 1 / -1;
  height: 80px;
  padding: 0 28px;
  display: flex;
  align-items: center;
  gap: 18px;
  background-color: var(--topbar);
  background-image:
    linear-gradient(90deg, rgba(0,0,0,.62) 0%, rgba(0,0,0,.18) 34%,
                           rgba(0,0,0,.18) 60%, rgba(0,0,0,.62) 100%),
    var(--topbar-photo, url("/img/aivacy/brand/topbar-earth.jpg"));
  background-size: cover;
  background-position: center 38%;
}
.app-header .brand {
  display: flex; align-items: center;
  text-decoration: none;
}
.app-header .brand:hover { text-decoration: none; }
/* Logo protagonista Aivacy en cyberblue con degradado (spec del diseñador); el scrim asegura
   contraste sobre la foto. El logo dual protagonista/potenciador por tenant se afina en AIV-150. */
.app-header .brand-logo {
  height: 32px; display: block;
}
.topbar-descriptor {
  margin: 0 0 0 auto;
  font-family: var(--font-heading);
  font-size: 24px;
  font-weight: var(--weight-light);
  color: #fff;
  letter-spacing: .2px;
  white-space: nowrap;
}
/* Co-branding del tenant: descriptivo + logo Aivacy (potenciador) alineados a la derecha. */
.topbar-cobrand {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 16px;
}
.topbar-cobrand .topbar-descriptor {
  margin: 0;
  font-size: 18px;
}
.topbar-aivacy {
  height: 30px;
  display: block;
}
/* Chip con la identidad activa + enlace al selector. Funciona dentro de cualquier
   cabecera (`.app-header` en futuras pantallas operativas, `.clients-head` en la home
   stub). El cambio de identidad lo gestiona /auth/select-client — no hay dropdown ni
   query a BD por request. */
.client-switch {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 6px 12px;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-size: 13px;
  color: var(--text);
  background: var(--bg-soft);
}
.client-switch-change {
  display: inline-flex;
  align-items: center;
  margin-left: 4px;
  padding-left: 8px;
  border-left: 1px solid var(--border);
  color: var(--text-muted);
  line-height: 1;
}
.client-switch-change:hover { color: var(--accent-dark); text-decoration: none; }
.app-header .top-search {
  flex: 1;
  max-width: 480px;
  display: flex; align-items: center; gap: 8px;
  background: var(--bg-app);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  padding: 7px 12px;
  color: var(--text-muted);
  font-size: 13px;
}
.app-header .top-actions {
  margin-left: 16px;
  display: flex; align-items: center; gap: 10px;
  font-size: 13px;
  color: var(--text-muted);
}
.app-header .icon-btn {
  width: 34px; height: 34px;
  border: 0;
  background: transparent;
  border-radius: 8px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0;
}
.app-header .icon-btn:hover { background: var(--bg-app); color: var(--text); }
.app-header .icon-btn:focus { outline: none; }
.app-header .icon-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.app-header .avatar {
  width: 32px; height: 32px;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--accent-dark);
  font-weight: 600; font-size: 12px;
  display: inline-flex; align-items: center; justify-content: center;
}
img.avatar {
  object-fit: cover;
  display: inline-block;
  border: 1px solid var(--border-soft);
  box-shadow: 0 0 0 1px rgba(255,255,255,.6) inset;
}
.avatar-row {
  width: 32px; height: 32px;
  border-radius: 999px;
  object-fit: cover;
  display: inline-block;
  background: var(--bg-app);
  flex-shrink: 0;
}
.user-menu {
  position: relative;
}
.user-menu-trigger {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 4px 12px 4px 4px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: white;
  color: var(--text);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  line-height: 1;
}
.user-menu-trigger:hover { background: var(--bg-soft); }
.user-menu-trigger[aria-expanded="true"] {
  background: var(--bg-soft);
  border-color: var(--border-strong);
}
.user-menu-avatar {
  position: relative;
  width: 28px;
  height: 28px;
  border-radius: 999px;
  background: var(--avatar-bg, var(--accent));
  color: white;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
  overflow: hidden;
  flex-shrink: 0;
}
.user-menu-avatar img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
}
.user-menu-name {
  max-width: 160px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.user-menu-chevron {
  display: inline-flex;
  color: var(--text-muted);
}
.user-menu-dropdown {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  min-width: 240px;
  background: white;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 8px 0;
  z-index: 50;
}
.user-menu-dropdown[hidden] { display: none; }
.menu-section {
  display: flex;
  flex-direction: column;
  padding: 4px 0;
  margin: 0;
}
.menu-section-title {
  margin: 4px 16px 6px;
  font-size: 12px;
  font-weight: 700;
  color: var(--text);
  letter-spacing: 0;
  text-transform: none;
}
.menu-divider {
  height: 1px;
  background: var(--border-soft);
  margin: 4px 0;
}
.menu-item {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 16px;
  background: transparent;
  border: 0;
  text-align: left;
  font: inherit;
  font-size: 13px;
  color: var(--text);
  cursor: pointer;
}
.menu-item:hover { background: var(--bg-app); }
a.menu-item:hover { text-decoration: none; }
.menu-item-icon {
  display: inline-flex;
  width: 18px;
  height: 18px;
  align-items: center;
  justify-content: center;
  color: var(--text-muted);
  flex-shrink: 0;
}
.menu-item-icon-accent { color: var(--green); }
.lang-option.active { font-weight: 600; }
.menu-item-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.menu-item-sub { font-size: 11px; color: var(--text-muted); }

/* Menú de usuario en el pie del sidebar: trigger a todo el ancho y dropdown que se
   despliega hacia arriba (dropup), porque vive pegado al fondo. */
.app-sidebar .user-menu { position: relative; }
.app-sidebar .user-menu-trigger {
  width: 100%;
  justify-content: flex-start;
  background: var(--bg);
}
.app-sidebar .user-menu-name { flex: 1; text-align: left; max-width: none; }
.app-sidebar .user-menu-chevron { margin-left: auto; transform: rotate(180deg); }
.app-sidebar .user-menu-dropdown {
  top: auto;
  bottom: calc(100% + 8px);
  left: 0;
  right: 0;
  min-width: 0;
}

/* App sidebar */
/* El aside no desplaza: lo hace .sidebar-nav. Así el menú de usuario del pie queda
   anclado y es alcanzable aunque los grupos de navegación no quepan en el viewport. */
.app-sidebar {
  background: var(--bg-soft);
  border-right: 1px solid var(--border-soft);
  padding: 18px 12px 18px;
  font-size: 13px;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.app-sidebar .sidebar-nav {
  flex: 1 1 auto;
  /* min-height:0 permite que el hijo flexible encoja por debajo de su contenido; sin
     esto el nav crece hasta empujar el pie fuera del aside y nunca aparece el scroll. */
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
}
.app-sidebar .nav-group {
  margin-bottom: 18px;
}
.app-sidebar .nav-group h4 {
  margin: 0 0 6px 10px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .6px;
  color: var(--text-soft);
  text-transform: uppercase;
}
.app-sidebar .nav-item {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px;
  border-radius: 6px;
  color: var(--text);
  cursor: pointer;
  margin-bottom: 1px;
  text-decoration: none;
}
.app-sidebar .nav-item { transition: background-color .14s cubic-bezier(.22,1,.36,1), color .14s cubic-bezier(.22,1,.36,1); }
.app-sidebar .nav-item:hover { background: var(--bg-app); text-decoration: none; }
.app-sidebar .nav-item:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.app-sidebar .nav-item.inert {
  cursor: default;
  color: var(--text-soft);
}
.app-sidebar .nav-item.inert:hover { background: transparent; }
.app-sidebar .nav-item.inert .ico { color: var(--text-soft); }
/* Selección activa: teal fuerte (tono oscuro para que el texto blanco cumpla WCAG AA;
   el teal base #00A499 con blanco se queda en 3.1:1). */
.app-sidebar .nav-item.active {
  background: var(--accent-dark);
  color: #fff;
  font-weight: var(--weight-semibold);
}
.app-sidebar .nav-item.active .ico { color: #fff; }
.app-sidebar .nav-item.active:hover { background: var(--accent-dark); }
.app-sidebar .nav-item .ico {
  width: 16px; height: 16px;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-muted);
  font-size: 14px;
}
.app-sidebar .nav-item .badge {
  margin-left: auto;
  background: var(--accent);
  color: white;
  font-size: 10px;
  padding: 2px 6px;
  border-radius: 999px;
  font-weight: 600;
}
.app-sidebar .nav-divider {
  border-top: 1px solid var(--border-soft);
  margin: 14px 6px;
}
/* Pie del sidebar: menú de usuario. Fijo — nunca entra en el área desplazable. */
.app-sidebar .sidebar-foot {
  flex: 0 0 auto;
  margin-top: auto;
  padding-top: 14px;
  border-top: 1px solid var(--border-soft);
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* App main */
.app-main {
  padding: 24px 28px;
  overflow: auto;
}

.page-head {
  margin-bottom: 22px;
}
.page-head .crumbs {
  font-size: 12px;
  color: var(--text-muted);
  margin-bottom: 6px;
}
.page-head .crumbs a { color: var(--text-muted); }
/* Escalón real entre el título y el cuerpo: 22px sobre 14px apenas se leía
   como jerarquía y la pantalla arrancaba plana. */
.page-head h1 {
  margin: 0 0 4px;
  font-size: 26px;
  line-height: 1.2;
  letter-spacing: -.02em;
}
.page-head .subtitle {
  color: var(--text-muted);
  font-size: 13px;
  margin: 6px 0 0;
}
.page-head .head-row {
  display: flex; align-items: center; gap: 16px;
  flex-wrap: wrap;
}
.page-head .head-row .actions {
  margin-left: auto;
  display: flex; gap: 8px;
}

/* ========================================================================
   Components
   ======================================================================== */

/* Botones — capsula Nunito con padding horizontal generoso (ancho ~2x el texto).
   Estático: Nunito medium. Estados con transicion suave. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 9px 22px;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  background: white;
  color: var(--text);
  font-family: var(--font-heading);
  font-size: 13px;
  font-weight: var(--weight-medium);
  cursor: pointer;
  white-space: nowrap;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.btn:hover { background: var(--bg-soft); }
/* Foco visible consistente en todos los botones (no depende solo de color:
   anillo con offset). El anillo usa el acento de identidad. */
.btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Boton de accion / CTA: color de accion (naranja) segun la marca.
   Estatico: degradado light->burnt a 90deg + semibold · hover: naranja plano ·
   pulsado: gradiente -90deg.
   El naranja plano vive siempre en background-color; el gradiente es una capa
   background-image que se retira en hover. Asi se evita animar de gradiente a
   color (no interpolable), que provoca un parpadeo. */
.btn-primary {
  background-color: var(--accent-2);
  background-image: linear-gradient(90deg, var(--accent-2-light), var(--accent-2));
  color: white;
  border-color: transparent;
  font-weight: var(--weight-semibold);
  box-shadow: 0 1px 2px rgba(145, 84, 43, .28);
  transition: background-color .16s cubic-bezier(.22,1,.36,1),
              box-shadow .16s cubic-bezier(.22,1,.36,1);
}
.btn-primary:hover { background-color: var(--accent-2); background-image: none; box-shadow: 0 2px 8px rgba(145, 84, 43, .3); }
.btn-primary:active { background-color: var(--accent-2); background-image: linear-gradient(-90deg, var(--accent-2-light), var(--accent-2)); }
.btn-ghost { background: transparent; border-color: transparent; color: var(--text-muted); }
.btn-ghost:hover { color: var(--text); background: var(--bg-soft); }
.btn-danger { color: var(--red); border-color: var(--border); }
.btn-danger:hover { background: #fff0ef; border-color: #ffc1bd; }
.btn-sm { padding: 6px 16px; font-size: 12px; }
.btn-lg { padding: 12px 28px; font-size: 14px; }
.btn-block { width: 100%; }

.input, .select, .textarea {
  width: 100%;
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 8px 12px;
  font-size: 13px;
  background: white;
  color: var(--text);
  font-family: inherit;
}
.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
/* Controles nativos (check/radio) tenidos con el acento de identidad. */
input[type="checkbox"], input[type="radio"] { accent-color: var(--accent); }
.field { margin-bottom: 14px; }
/* Fila de campos en dos columnas (50/50); si un campo está oculto, el otro ocupa el ancho.
   En pantallas estrechas los campos se apilan (flex-wrap). */
.field-row { display: flex; flex-wrap: wrap; gap: 0 18px; }
.field-row > .field { flex: 1 1 220px; }
.field label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  color: var(--text);
  margin-bottom: 4px;
}
.field .hint { font-size: 12px; color: var(--text-muted); margin-top: 4px; }

/* Campo hex con muestra de color nativa sincronizada (color-picker + input hex). */
.color-input { display: flex; align-items: stretch; gap: 8px; }
.color-input .input { flex: 1 1 auto; }
.color-swatch {
  flex: 0 0 auto;
  width: 40px;
  height: auto;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: white;
  cursor: pointer;
}
.color-swatch::-webkit-color-swatch-wrapper { padding: 4px; }
.color-swatch::-webkit-color-swatch { border: none; border-radius: 3px; }
.color-swatch::-moz-color-swatch { border: none; border-radius: 3px; }

.card {
  background: white;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  padding: 18px;
}
.card.padded-lg { padding: 24px; }
.card .card-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 14px;
}
.card .card-head h3 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
}
.card .card-head .card-actions {
  display: flex; gap: 6px;
  font-size: 12px; color: var(--text-muted);
}

/* badges / chips / tags */
.tag {
  display: inline-flex; align-items: center;
  padding: 2px 8px;
  font-size: 11px;
  font-weight: 600;
  border-radius: 999px;
  background: var(--bg-app);
  color: var(--text-muted);
  letter-spacing: .2px;
  white-space: nowrap;
}
.tag.green   { background: #DCFCE7; color: #166534; }
.tag.amber   { background: #FEF3C7; color: #92400E; }
.tag.red     { background: #FEE2E2; color: #991B1B; }
.tag.blue    { background: #DBEAFE; color: #1E40AF; }
.tag.purple  { background: #EDE9FE; color: #5B21B6; }
.tag.coral   { background: var(--accent-soft); color: var(--accent-dark); }
.tag.gray    { background: #E5E7EB; color: #374151; }
/* Estado informativo (emitido, pendiente de que alguien lo coja): el grafito fijo de las tarjetas de
   indicadores y no el acento del tenant, que con un acento rojo se leería como algo vencido. */
.tag.info    { background: var(--info-soft); color: var(--info); }
/* Badge de accion/atencion: naranja tenue con texto burnt dark (AA >=4.5:1). */
.tag.action  { background: var(--accent-2-soft); color: var(--accent-2-dark); }

.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 10px;
  border-radius: var(--radius-pill);
  background: white;
  border: 1px solid var(--border);
  font-size: 12px;
  color: var(--text);
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.chip.solid { background: var(--accent); color: white; border-color: var(--accent); }
/* Chip de accion (filtro/CTA): naranja tenue con texto burnt dark (AA). */
.chip.action { background: var(--accent-2-soft); color: var(--accent-2-dark); border-color: transparent; }
.chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.chip .x { color: var(--text-muted); margin-left: 2px; cursor: pointer; }
.chip .x:hover { color: var(--text); }

/* Tables */
table.data {
  width: 100%;
  border-collapse: collapse;
  background: white;
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid var(--border-soft);
  font-size: 13px;
}
table.data thead th {
  background: var(--bg-soft);
  border-bottom: 1px solid var(--border);
  text-align: left;
  padding: 10px 14px;
  font-weight: 600;
  font-size: 12px;
  color: var(--text-muted);
  letter-spacing: .2px;
  text-transform: uppercase;
}
table.data tbody td {
  padding: 12px 14px;
  border-bottom: 1px solid var(--border-soft);
  vertical-align: middle;
}
table.data tbody tr:last-child td { border-bottom: none; }
table.data tbody tr { transition: background-color .12s ease-out; }
table.data tbody tr:hover { background: var(--bg-soft); }
table.data .col-id { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; color: var(--text-muted); font-size: 12px; }
/* Nombre del recurso auditado: manda sobre el id, que se queda de apoyo en la misma celda. */
.audit-target-name { font-family: var(--font-body); color: var(--text); font-size: 13px; }
table.data .row-actions { color: var(--text-muted); font-size: 12px; text-align: right; }
table.data .row-actions a:not(.menu-item) { color: var(--text-muted); margin-left: 10px; }
table.data .row-actions a:not(.menu-item):hover { color: var(--accent); }

/* KPI cards */
/* Una sola fila, sean 4, 5 o 6 tarjetas: el flujo por columnas crea una columna
   implícita por tarjeta en lugar de saltar de fila al pasar de un número fijo. */
.kpi-grid {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 14px;
  margin-bottom: 22px;
}
.kpi-card {
  background: white;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  padding: 18px;
  box-shadow: var(--shadow-sm);
  /* El pie (.asof) se empuja al fondo: si en alguna tarjeta el texto de cobertura
     ocupa dos líneas, las demás siguen alineadas entre sí. */
  display: flex;
  flex-direction: column;
}
.kpi-card .label {
  font-size: 12px;
  color: var(--text-muted);
  margin-bottom: 6px;
  font-weight: 500;
}
.kpi-card .value {
  font-family: var(--font-heading);
  font-size: 30px;
  font-weight: var(--weight-semibold);
  line-height: 1.1;
  letter-spacing: -.02em;
  margin-bottom: 4px;
}
/* Un indicador sin dato no es un indicador que vale «—»: es un hueco. Se
   mantiene legible pero deja de tener el cuerpo y el peso de una cifra, para
   que en un panel a medio poblar el ojo encuentre primero lo que sí se sabe. */
.kpi-card .value.value-empty {
  font-size: 20px;
  font-weight: var(--weight-body);
  letter-spacing: 0;
  color: var(--text-muted);
}
.kpi-card:has(.value-empty) {
  background: var(--bg-soft);
  border-color: var(--border-soft);
  box-shadow: none;
}
/* El denominador acompaña a la cifra sin disputarle el sitio: menor cuerpo y tono
   apagado, para que el ojo lea primero el número de la izquierda. */
.kpi-card .value .total {
  font-size: 18px;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--text-muted);
}
.kpi-card .delta {
  display: inline-flex; align-items: center; gap: 4px;
  align-self: flex-start;
  min-width: 0;
  font-size: 11px;
  font-weight: 600;
}
.kpi-card .delta.up { color: var(--green); }
.kpi-card .delta.down { color: var(--red); }
.kpi-card .delta.flat { color: var(--text-muted); }
.kpi-card .delta .vs { color: var(--text-muted); font-weight: 400; margin-left: 6px; }
/* El margen solo separa del delta («▲ 3  vs 31 ene»): si el texto es lo único del pie
   (cobertura, sin fuente), sangra respecto al resto de la tarjeta. */
.kpi-card .delta .vs:first-child { margin-left: 0; }

/* Tono de estado: fija el color que heredan el icono y el mini-gráfico. El color
   codifica el estado; sin tono, la tarjeta es informativa. Lo comparten las tarjetas
   de indicadores, las de tareas y las del selector de identidad. */
.kpi-card, .tone-info { --tone: var(--info); --tone-soft: var(--info-soft); }
.tone-ok    { --tone: var(--green);     --tone-soft: var(--green-soft); }
.tone-busy  { --tone: var(--amber);     --tone-soft: var(--amber-soft); }
.tone-alert { --tone: var(--red);       --tone-soft: var(--red-soft); }
.tone-empty { --tone: var(--text-soft); --tone-soft: var(--border-soft); }
.kpi-card.tone-alert .value { color: var(--red); }

.kpi-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; }
.kpi-head .label { min-width: 0; }
/* Con cinco o más tarjetas por fila hay etiquetas que caen en dos líneas: se reserva la
   segunda para que las cifras de toda la fila queden a la misma altura. */
.kpi-grid:has(> .kpi-card:nth-child(5)) .kpi-head .label { line-height: 1.35; min-height: 2.7em; }
.kpi-icon { flex: none; display: inline-flex; margin-top: -2px; color: var(--tone); }
.kpi-icon svg { display: block; }
.kpi-icon.is-spinning { animation: kpi-spin 1.6s linear infinite; }

.kpi-meter {
  position: relative;
  height: 6px;
  margin-top: 8px;
  border-radius: 3px;
  background: var(--border-soft);
  overflow: hidden;
}
.kpi-meter > span { display: block; height: 100%; border-radius: 3px; background: var(--tone); }
.kpi-meter.is-indeterminate::after {
  content: "";
  position: absolute; top: 0; bottom: 0; left: 0;
  width: 35%;
  border-radius: 3px;
  background: var(--tone);
  animation: kpi-slide 1.4s ease-in-out infinite;
}
.kpi-meter-caption { margin-top: 6px; font-size: 11px; color: var(--text-muted); }

.kpi-ring-wrap { display: flex; align-items: center; gap: 12px; }
.kpi-ring { flex: none; width: 44px; height: 44px; }
.kpi-ring .track { stroke: var(--border-soft); }
.kpi-ring .bar { stroke: var(--tone); }

.kpi-dots { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 10px; }
.kpi-dots > span { width: 8px; height: 8px; border-radius: 50%; background: var(--tone); }

.kpi-ok { display: flex; align-items: center; gap: 4px; margin-top: 8px; font-size: 11px; color: var(--green); }

/* El pie se empuja al fondo para que las fechas de todas las tarjetas queden alineadas. */
.kpi-card .asof { margin-top: auto; padding-top: 8px; font-size: 11px; color: var(--text-muted); }

@keyframes kpi-spin { to { transform: rotate(360deg); } }
@keyframes kpi-slide { from { left: -35%; } to { left: 100%; } }
@media (prefers-reduced-motion: reduce) {
  .kpi-icon.is-spinning, .kpi-meter.is-indeterminate::after { animation: none; }
}

/* Filter bar */
.filter-bar {
  display: flex; align-items: center; gap: 8px;
  flex-wrap: wrap;
  background: white;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  padding: 10px 12px;
  margin-bottom: 14px;
}
.filter-bar .filter-search {
  flex: 1;
  min-width: 240px;
  display: flex; align-items: center; gap: 8px;
  border: 1px solid var(--border-soft);
  border-radius: 6px;
  padding: 6px 10px;
  background: var(--bg-app);
  color: var(--text-muted);
  font-size: 13px;
}
.filter-bar .sep { width: 1px; background: var(--border-soft); align-self: stretch; }
.filter-bar .filter-date { display: flex; align-items: center; gap: 6px; }

/* Pantalla de costes: filtro de fechas. */
.costs-filter { align-items: flex-end; }
.field-inline { display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--text-muted); }

/* Selector de mes de las pantallas de cuotas y consumo. */
.period-filter { align-items: flex-end; }
.period-nav { display: flex; align-items: center; gap: 8px; }
.period-nav .btn { text-decoration: none; }
.period-nav .btn.is-disabled { opacity: 0.45; pointer-events: none; }
.period-current { font-size: 13px; min-width: 120px; text-align: center; }
.period-note { flex: 1; min-width: 220px; font-size: 12px; color: var(--text-muted); }

/* Pagination footer */
.pagination-bar {
  display: flex; justify-content: space-between; align-items: center;
  margin-top: 14px;
  font-size: 12px;
  color: var(--text-muted);
}
.pagination-pages { display: flex; align-items: center; gap: 6px; }
.pagination-pages .btn { text-decoration: none; }
.pagination-pages .btn.is-disabled {
  opacity: 0.45;
  pointer-events: none;
}
.pagination-ellipsis { padding: 0 2px; color: var(--text-muted); }

/* Empty state */
.empty {
  text-align: center;
  padding: 60px 20px;
  color: var(--text-muted);
}
.empty .ico-big {
  width: 64px; height: 64px;
  margin: 0 auto 16px;
  background: var(--accent-soft);
  color: var(--accent);
  border-radius: 16px;
  display: flex; align-items: center; justify-content: center;
  font-size: 30px;
}
.empty h2 { margin: 8px 0 6px; color: var(--text); font-weight: 600; font-size: 18px; }
.empty p { margin: 4px 0 18px; }

/* Status pill */
.dot { display: inline-block; width: 8px; height: 8px; border-radius: 999px; margin-right: 6px; vertical-align: 1px; }
.dot.green { background: var(--green); }
.dot.amber { background: var(--amber); }
.dot.red { background: var(--red); }
.dot.blue { background: var(--blue); }
.dot.gray { background: #9CA3AF; }

/* Auth screens (login etc.) */
.auth-page {
  min-height: 760px;
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  background: white;
}
.auth-side {
  background: linear-gradient(135deg, var(--aivacy-silver-dark) 0%, var(--aivacy-silver) 55%, var(--aivacy-silver-light) 100%);
  color: white;
  padding: 48px 56px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  position: relative;
  overflow: hidden;
}
/* sutil veteado tipo "metálico" en el fondo */
.auth-side::after {
  content: "";
  position: absolute; inset: 0;
  background:
    linear-gradient(60deg, rgba(255,255,255,.10) 0%, transparent 30%, transparent 70%, rgba(255,255,255,.08) 100%);
  pointer-events: none;
}
.auth-side > * { position: relative; z-index: 1; }
.auth-side .auth-logo {
  width: 132px;
  background: transparent;
  border-radius: 0;
  padding: 0;
}
.auth-side .auth-logo img { width: 100%; display: block; filter: brightness(0) invert(1); }
.auth-side .auth-powered {
  font-size: 11px;
  letter-spacing: .8px;
  text-transform: uppercase;
  opacity: .75;
  margin-bottom: 4px;
}
.auth-side .auth-pitch h2 {
  font-size: 32px;
  letter-spacing: -.5px;
  margin: 0 0 10px;
  line-height: 1.15;
}
.auth-side .auth-pitch p {
  font-size: 15px;
  line-height: 1.55;
  opacity: .92;
  margin: 0 0 18px;
  max-width: 460px;
}
.auth-side .auth-bullets li {
  margin-bottom: 8px;
  opacity: .94;
  font-size: 14px;
}
.auth-side .auth-foot {
  font-size: 12px;
  opacity: .8;
}
.auth-form-wrap {
  position: relative;
  min-width: 0;
  display: flex; align-items: center; justify-content: center;
  padding: 40px;
}
/* Firma del revendedor al pie del panel del formulario: texto discreto + su logo.
   Va fuera del flujo para quedar anclada abajo a la derecha sin descentrar el form. */
.auth-partner {
  position: absolute; right: 40px; bottom: 24px;
  display: flex; align-items: center; gap: 10px;
  font-size: 12px;
  color: var(--text-muted);
}
.auth-partner .auth-partner-logo {
  height: 22px;
  width: auto;
  display: block;
}
.auth-form {
  width: 100%; max-width: 380px;
  /* Ningún texto del formulario puede ensanchar la columna más allá de su sitio:
     el nombre del cliente viaja en el titular y en el subtítulo, y una razón social
     de una sola palabra larga desbordaría la página en móvil. Antes que eso, se parte. */
  overflow-wrap: anywhere;
}
.auth-form h1 {
  font-size: 24px;
  margin: 0 0 6px;
  letter-spacing: -.3px;
}
/* Encabezado de login en tres tramos: el fragmento .hl (nombre del entorno) va en
   el acento de identidad (mismo teal que los enlaces, var(--accent)); el resto en
   texto normal. Interlineado holgado porque el titular envuelve a 2-3 líneas.
   El titular envuelve libremente —el nombre del cliente puede ser largo y en móvil
   no cabe en una línea—; lo único que no se parte es el descriptor de marca, cosido
   con espacio duro y word joiner en los .properties. */
.auth-welcome {
  font-weight: var(--weight-medium);
  line-height: 1.28;
  margin-bottom: 12px;
}
.auth-welcome .hl { color: var(--accent); }
.auth-form .auth-sub {
  color: var(--text-muted);
  margin: 0 0 26px;
  font-size: 13px;
  line-height: 1.55;
}
.auth-form .auth-meta {
  margin-top: 22px;
  font-size: 13px;
  color: var(--text-muted);
  text-align: center;
}

/* Auth · cuenta bloqueada */
.auth-form.lock-card {
  max-width: 440px;
}
.lock-illu {
  width: 88px; height: 88px;
  background: #FEE2E2;
  border-radius: 22px;
  margin: 0 auto 20px;
  display: flex; align-items: center; justify-content: center;
  font-size: 38px;
  color: #B91C1C;
}
.auth-form.lock-card h1,
.auth-form.lock-card .auth-sub {
  text-align: center;
}
.lock-stat {
  background: var(--bg-soft);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  padding: 14px 16px;
  margin: 18px 0 4px;
  font-size: 13px;
  display: flex; align-items: center; gap: 14px;
}
.lock-stat-time {
  font-size: 22px;
  font-weight: 700;
  color: #B91C1C;
  white-space: nowrap;
}
.lock-stat-label {
  color: var(--text-muted);
}
.lock-stat-meta {
  font-weight: 600;
  margin-top: 2px;
}

/* Auth v2 — layout de autenticación (cliente + hero + powered by Aivacy) */
.auth-page-v2 {
  min-height: 100vh;
  display: flex; flex-direction: column;
  background: var(--surface-gradient), var(--bg-soft);
  background-attachment: fixed;
}
.auth-client-header {
  display: flex; align-items: center; gap: 14px;
  padding: 16px 32px;
  background: transparent;
  border-bottom: 1px solid var(--border-soft);
  font-size: 16px;
  min-width: 0;
}
.auth-client-header .client-name { font-weight: 700; min-width: 0; overflow-wrap: anywhere; }
.auth-client-header .brand-logo { height: 28px; display: block; }
.auth-client-header .client-tag {
  color: var(--text-muted); font-size: 12px;
  padding-left: 10px; border-left: 1px solid var(--border);
  margin-left: 4px;
}
.auth-client-header .login-meta {
  margin-left: auto;
  font-size: 12px; color: var(--text-muted);
}
.auth-body {
  flex: 1;
  display: grid;
  grid-template-columns: 1.15fr 1fr;
  min-height: 680px;
}
.auth-side-v2 {
  position: relative;
  overflow: hidden;
  background: linear-gradient(135deg, var(--aivacy-silver-dark), var(--aivacy-silver) 60%, var(--aivacy-silver-light));
  color: white;
}
.auth-side-v2 .auth-hero-img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
.auth-side-v2 .auth-hero-overlay {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,.12) 0%, rgba(0,0,0,.55) 100%);
}
.auth-side-v2 .auth-tagline {
  position: absolute; left: 48px; right: 48px; top: 56px;
  z-index: 1;
}
.auth-side-v2 .auth-tagline h2 {
  margin: 0;
  font-family: var(--font-heading);
  font-size: clamp(36px, 5vw, 52px);
  font-weight: 200;
  line-height: 1.1;
  letter-spacing: 1.5px;
  color: white;
  text-shadow: 0 2px 14px rgba(0,0,0,.25);
}
.auth-side-v2 .auth-tagline .lead {
  margin-top: 16px;
  font-size: 14px;
  opacity: .92;
  max-width: 380px;
  line-height: 1.55;
  text-shadow: 0 1px 6px rgba(0,0,0,.3);
}
.auth-side-v2 .auth-powered-row {
  position: absolute; right: 48px; bottom: 36px;
  display: flex; align-items: center; gap: 12px;
  z-index: 1;
}
.auth-side-v2 .auth-powered-row .auth-powered {
  font-size: 10px;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: white;
  opacity: .85;
}
.auth-side-v2 .auth-aivacy-sq {
  width: 64px;
  border-radius: 4px;
  display: block;
  box-shadow: 0 4px 16px rgba(0,0,0,.32);
}

/* Chat */
/* La pantalla de chat ocupa exactamente el alto disponible (sin scroll de página).
   El layout queda fijo y solo .chat-stream scrollea, dejando el input pegado al fondo. */
.chat-page .app { height: 100vh; min-height: 0; }
.chat-page .app-main { padding: 0; overflow: hidden; }
.chat-shell {
  display: grid;
  grid-template-columns: 280px 1fr;
  height: 100%;
  min-height: 0;
}
.chat-aside {
  background: white;
  border-right: 1px solid var(--border-soft);
  display: flex;
  flex-direction: column;
}
.chat-aside .new-chat {
  padding: 14px;
  border-bottom: 1px solid var(--border-soft);
}
.chat-aside .new-chat .btn { width: 100%; }
.chat-aside .conv-search {
  display: flex; align-items: center; gap: 8px; margin-top: 10px;
  background: var(--bg-app); border: 1px solid var(--border-soft);
  border-radius: 8px; padding: 6px 10px; color: var(--text-muted);
}
.chat-aside .conv-search:focus-within { border-color: var(--accent); }
.conv-search-ico { display: inline-flex; flex: none; }
.conv-search-input {
  border: 0; background: transparent; outline: none;
  font: inherit; font-size: 13px; color: var(--text); width: 100%; min-width: 0;
}
/* De dónde sale un resultado de la búsqueda (carpeta o archivadas): la búsqueda cruza las tres
   vistas del panel, así que la fila sola no lo diría. Va en su propia línea bajo el título, no a
   su lado: en un panel de 280 px robarle ancho al título es tapar lo que se ha venido a leer. */
.chat-aside .conv { flex-wrap: wrap; }
.conv-origin {
  flex: 0 0 100%; margin: 1px 0 0 24px;
  font-size: 10px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .3px; color: var(--text-soft);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chat-aside .conv.active .conv-origin { color: var(--accent-dark); }
/* Conversación que nació fuera del navegador: el canal, en un chip pequeño junto al título. Va en
   la misma línea y no debajo como .conv-origin porque es una palabra corta y no todas las filas lo
   llevan; el que se estrecha si no cabe es el título. */
.conv-channel {
  flex: none; margin-left: 6px; padding: 0 5px;
  border: 1px solid var(--border); border-radius: 8px;
  font-size: 9px; font-weight: 700; line-height: 15px;
  text-transform: uppercase; letter-spacing: .3px; color: var(--text-soft);
}
.chat-aside .conv.active .conv-channel { border-color: var(--accent); color: var(--accent-dark); }
.chat-aside .conv-list {
  flex: 1;
  overflow: auto;
  padding: 12px 8px;
}
/* Títulos de sección ("Sin carpeta") y nombres de carpeta: en el acento de identidad
   (teal en Aivacy, color del tenant si lo tiene configurado), como en la referencia. */
.chat-aside .group-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .8px;
  color: var(--accent);
  font-weight: 700;
  padding: 12px 10px 6px;
}
.chat-aside .conv {
  padding: 10px 10px;
  border-radius: 6px;
  cursor: pointer;
  font-size: 13px;
  color: var(--text);
  margin-bottom: 1px;
  display: flex; align-items: center; gap: 8px;
}
.chat-aside .conv:hover { background: var(--bg-app); }
.chat-aside .conv.active { background: var(--accent-soft); color: var(--accent-dark); font-weight: 600; }
.chat-aside .conv .ico { display: inline-flex; align-items: center; flex: none; color: var(--text-muted); }
.chat-aside .conv.active .ico { color: var(--accent-dark); }
.chat-aside .conv-title {
  flex: 1;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.chat-aside .conv .when { font-size: 11px; color: var(--text-soft); }

.chat-main { display: flex; flex-direction: column; background: var(--bg-app); height: 100%; min-height: 0; overflow: hidden; }
.chat-main .chat-head {
  padding: 14px 22px;
  border-bottom: 1px solid var(--border-soft);
  background: white;
  display: flex; align-items: center; gap: 14px;
}
.chat-main .chat-head .title { font-weight: 600; font-size: 14px; }
.chat-main .chat-head .skill {
  background: var(--accent-soft);
  color: var(--accent-dark);
  font-size: 11px;
  font-weight: 600;
  padding: 3px 8px;
  border-radius: 999px;
}
.chat-main .chat-head .head-actions { margin-left: auto; display: flex; gap: 6px; }

.chat-stream {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding: 22px 28px;
  display: flex; flex-direction: column; gap: 16px;
}
.msg { max-width: 760px; }
/* Bocadillo del usuario: una sola burbuja de fondo blanco con un borde en el acento de
   identidad (el del cliente si lo tiene, o el de Aivacy por defecto). Fondo blanco para el
   contraste AA del texto y para que los avisos internos (p. ej. PII ocultada) no queden
   como cajas sobre color. El contenido va directo en la burbuja (.msg-body sin caja propia). */
.msg.user {
  align-self: flex-end;
  background: white;
  color: var(--text);
  padding: 12px 16px;
  border: 1px solid var(--accent);
  border-radius: 14px 14px 4px 14px;
  font-size: 14px;
  line-height: 1.55;
  box-shadow: var(--shadow-sm);
}
.msg.user .who {
  display: flex; align-items: center; gap: 8px;
  margin-bottom: 8px;
  font-size: 12px;
  color: var(--text-muted);
  justify-content: flex-end;
}
.msg .who-name { font-weight: 600; }
/* Indicador "pensando" mientras la respuesta se genera y verifica. */
.typing-dots { display: inline-flex; gap: 4px; padding: 4px 0; }
.typing-dots i {
  width: 6px; height: 6px;
  border-radius: 999px;
  background: var(--text-muted);
  animation: typing-bounce 1.1s infinite ease-in-out;
}
.typing-dots i:nth-child(2) { animation-delay: 0.18s; }
.typing-dots i:nth-child(3) { animation-delay: 0.36s; }
@keyframes typing-bounce {
  0%, 60%, 100% { opacity: 0.35; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-3px); }
}
.msg .msg-avatar {
  position: relative;
  width: 22px; height: 22px;
  border-radius: 999px;
  background: var(--avatar-bg, var(--accent));
  color: white;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 10px; font-weight: 700;
  overflow: hidden; flex-shrink: 0;
}
.msg .msg-avatar img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover; border-radius: inherit;
}
.msg.assistant {
  align-self: flex-start;
  background: white;
  border: 1px solid var(--border-soft);
  border-radius: 14px 14px 14px 4px;
  padding: 14px 18px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--text);
}
.msg.assistant .who {
  display: flex; align-items: center; gap: 8px;
  margin-bottom: 8px;
  font-size: 12px;
  color: var(--text-muted);
}
/* El asistente se identifica con el logo «square» de la marca, no con una
   «A» sobre fondo grafito. Se resuelve por branding (logoSquareUrl). */
.msg.assistant .who .badge-ai {
  width: 22px; height: 22px;
  border-radius: 6px;
  object-fit: contain;
  background: white;
  display: inline-block;
  flex-shrink: 0;
}
.msg.assistant p { margin: 0 0 8px; }
.msg.assistant p:last-child { margin-bottom: 0; }
.msg.assistant ul { margin: 6px 0; padding-left: 18px; }
.msg.assistant ul li { margin-bottom: 4px; }
.msg.assistant .citations {
  margin-top: 12px;
  display: flex; flex-wrap: wrap; gap: 6px;
}
.msg.assistant .cite {
  display: inline-flex; align-items: center; gap: 8px;
  height: 28px;
  padding: 0 12px 0 0;
  border: 1px solid var(--border);
  background: var(--bg-soft);
  border-radius: 999px;
  font-size: 12px;
  color: var(--text);
  cursor: pointer;
  overflow: hidden;
}
.msg.assistant .cite:hover { border-color: var(--cite); color: var(--cite); }
.msg.assistant .cite .num {
  flex: none;
  width: 26px; height: 26px;
  border-radius: 999px;
  background: var(--cite-soft);
  color: var(--cite);
  font-size: 11px; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center;
}
.msg.assistant .meta-row {
  display: flex; gap: 14px; margin-top: 12px;
  font-size: 12px; color: var(--text-muted);
}
.msg.assistant .meta-row a { color: var(--text-muted); }
.msg.assistant .disclaimer {
  margin-top: 10px;
  font-size: 11px;
  color: var(--text-soft);
  font-style: italic;
}

/* Estilos del markdown ya parseado en las respuestas del asistente
   (encabezados, listas ordenadas, código, citas, tablas, enlaces). */
.msg.assistant .msg-body > *:first-child { margin-top: 0; }
.msg.assistant .msg-body > *:last-child { margin-bottom: 0; }
.msg.assistant .msg-body h1,
.msg.assistant .msg-body h2,
.msg.assistant .msg-body h3,
.msg.assistant .msg-body h4 { font-size: 14px; font-weight: 700; margin: 12px 0 6px; }
.msg.assistant .msg-body ol { margin: 6px 0; padding-left: 20px; }
.msg.assistant .msg-body ol li { margin-bottom: 4px; }
.msg.assistant .msg-body a { color: var(--accent-dark); text-decoration: underline; }
.msg.assistant .msg-body code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12.5px;
  background: var(--bg-soft);
  border: 1px solid var(--border-soft);
  border-radius: 4px;
  padding: 1px 5px;
}
.msg.assistant .msg-body pre {
  background: var(--bg-soft);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  padding: 10px 12px;
  overflow: auto;
  margin: 8px 0;
}
.msg.assistant .msg-body pre code { background: none; border: 0; padding: 0; }
/* Gráfico embebido en una respuesta (bloque aivacy-chart): reemplaza al <pre> del bloque. */
.msg.assistant .msg-body .chat-chart {
  width: 100%;
  height: 300px;
  margin: 8px 0;
}
/* Pasaje citado dentro de la respuesta: barra izquierda en el acento de identidad
   (la "barra teal" de la referencia). Los chips de fuentes citadas son otra cosa y
   siguen en gris neutro (AIV-107). */
.msg.assistant .msg-body blockquote {
  margin: 8px 0; padding: 2px 12px;
  border-left: 3px solid var(--accent);
  color: var(--text-muted);
}
/* Mismo estilo que las tablas del PDF de una respuesta: borde exterior, cabecera en el tono suave del
   acento con su línea debajo, y filas separadas solo por líneas horizontales. */
.msg.assistant .msg-body table {
  border-collapse: collapse; margin: 8px 0; font-size: 13px; border: 1px solid var(--border-soft);
}
.msg.assistant .msg-body th,
.msg.assistant .msg-body td {
  padding: 6px 10px; text-align: left; vertical-align: top;
  border-bottom: 1px solid var(--border-soft);
}
.msg.assistant .msg-body th {
  background: var(--accent-soft); font-weight: var(--weight-semibold);
  border-bottom: 2px solid var(--accent);
}
.msg.assistant .msg-body hr { border: 0; border-top: 1px solid var(--border-soft); margin: 12px 0; }

/* Referencias inline [[n]] del LLM convertidas en un superíndice clicable que
   abre el panel lateral de la fuente. Las que no resuelven a una cita real se descartan
   en el render (chat.js), no se pintan. El selector incluye .msg-body para ganar en
   especificidad al subrayado genérico de enlaces del cuerpo. */
.msg.assistant .msg-body .cite-ref {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 16px; height: 16px;
  padding: 0 4px; margin: 0 1px;
  vertical-align: super;
  font-size: 10px; font-weight: 700; line-height: 1;
  border-radius: 999px;
  background: var(--cite-soft);
  color: var(--cite);
  text-decoration: none;
  cursor: pointer;
}
.msg.assistant .msg-body a.cite-ref:hover { background: var(--cite); color: white; }

/* Cita de respaldo débil del detector de alucinación (AIV-71): cautela, no error → ámbar. Marca la
   cita concreta (chip y marcador [[n]] inline) en vez de un banner para todo el mensaje. */
.msg.assistant .cite.weak { border-color: var(--amber); }
.msg.assistant .cite.weak .num { background: #FEF3C7; color: #92400E; }
.msg.assistant .msg-body .cite-ref.weak { background: #FEF3C7; color: #92400E; }
.msg.assistant .msg-body a.cite-ref.weak:hover { background: var(--amber); color: white; }
/* Leyenda que explica el código ámbar de las citas débiles (AIV-116): el color por sí solo
   no comunica nada; aparece solo si el mensaje tiene al menos una cita débil. */
.msg.assistant .citations .cite-weak-note {
  flex-basis: 100%;
  margin: 2px 0 0;
  font-size: 12px;
  line-height: 1.4;
  color: #92400E;
}

/* Pestañas de la gestión documental (AIV-32): "Mi corpus" vs "Documentos de Aivacy". */
.tabs {
    display: flex;
    gap: 4px;
    border-bottom: 1px solid var(--border-soft);
    margin: 10px 0 0;
}
.tabs .tab {
    padding: 8px 14px;
    color: var(--text-soft);
    text-decoration: none;
    border-bottom: 2px solid transparent;
    font-weight: 500;
    margin-bottom: -1px;
}
.tabs .tab:hover { color: var(--text); }
.tabs .tab.active { color: var(--accent); border-bottom-color: var(--accent); }

/* Sello "Aivacy" en las citas del repositorio común (AIV-32): material curado por Aivacy, no por el
   cliente. Sutil pero inequívoco, en grafito de marca para distinguirlo del corpus propio. */
.msg.assistant .cite .cite-badge-common {
    margin-left: .35rem;
    padding: .05rem .35rem;
    border-radius: 4px;
    background: #2E2E2E;
    color: #fff;
    font-size: .68rem;
    font-weight: 600;
    letter-spacing: .02em;
    text-transform: none;
}

/* Al cargar una conversación los mensajes entran con un fade/slide suave
   (escalonado en los primeros). Se anula con prefers-reduced-motion. */
@keyframes msg-fade-in {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}
.chat-stream.conv-loaded .msg { animation: msg-fade-in .32s ease both; }
.chat-stream.conv-loaded .msg:nth-child(2) { animation-delay: .04s; }
.chat-stream.conv-loaded .msg:nth-child(3) { animation-delay: .08s; }
.chat-stream.conv-loaded .msg:nth-child(4) { animation-delay: .12s; }
.chat-stream.conv-loaded .msg:nth-child(n+5) { animation-delay: .15s; }
@media (prefers-reduced-motion: reduce) {
  .chat-stream.conv-loaded .msg { animation: none; }
}

.chat-input-bar {
  background: white;
  border-top: 1px solid var(--border-soft);
  padding: 14px 22px 18px;
  flex-shrink: 0;
}
.chat-input {
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 10px 12px;
  background: white;
  display: flex; align-items: center; gap: 10px;
  box-shadow: var(--shadow-sm);
}
.chat-input .input-text {
  flex: 1; border: none; outline: none;
  font-family: inherit; font-size: 14px;
  background: transparent; color: var(--text);
}
.chat-input .input-text::placeholder { color: var(--text-soft); }
.chat-input .send-btn {
  width: 36px; height: 36px;
  border-radius: 8px;
  background: var(--accent);
  color: white;
  display: inline-flex; align-items: center; justify-content: center;
  border: none;
  cursor: pointer;
}
.chat-input-footer {
  margin-top: 8px;
  display: flex; justify-content: space-between;
  font-size: 11px; color: var(--text-soft);
}

/* Drawer / side panel (used for citation detail, doc upload, etc.) */
.drawer {
  position: absolute; right: 0; top: 0; bottom: 0;
  width: 420px;
  background: white;
  border-left: 1px solid var(--border);
  box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column;
  z-index: 50;
}
.drawer .drawer-head {
  padding: 16px 20px;
  border-bottom: 1px solid var(--border-soft);
  display: flex; align-items: center; gap: 8px;
}
.drawer .drawer-head h3 { margin: 0; font-size: 14px; font-weight: 600; }
.drawer .drawer-head .close { margin-left: auto; color: var(--text-muted); cursor: pointer; }
.drawer .drawer-body { padding: 18px 20px; flex: 1; overflow: auto; }
.drawer .drawer-foot {
  padding: 14px 20px;
  border-top: 1px solid var(--border-soft);
  display: flex; gap: 8px; justify-content: flex-end;
}

/* Mock chart placeholders (we don't render real charts) */
.mock-chart {
  background:
    repeating-linear-gradient(180deg, var(--border-soft) 0 1px, transparent 1px 28px),
    linear-gradient(180deg, transparent 60%, var(--chart-soft-1) 100%);
  border: 1px solid var(--border-soft);
  border-radius: 6px;
  height: 220px;
  position: relative;
  overflow: hidden;
}
.mock-chart::before {
  /* trend line */
  content: "";
  position: absolute; inset: 16px 16px 28px 16px;
  background:
    linear-gradient(transparent 60%, var(--chart-soft-1) 100%);
  border-bottom: 2px solid var(--chart-1);
  clip-path: polygon(0 80%, 8% 70%, 18% 75%, 28% 60%, 40% 65%, 52% 50%, 64% 55%, 76% 35%, 88% 40%, 100% 20%, 100% 100%, 0 100%);
}
.mock-chart .axis {
  position: absolute; bottom: 6px; left: 16px; right: 16px;
  display: flex; justify-content: space-between;
  font-size: 10px; color: var(--text-soft);
}
.mock-chart-bars {
  display: flex; align-items: flex-end; gap: 14px;
  padding: 16px;
  height: 220px;
  border: 1px solid var(--border-soft);
  border-radius: 6px;
  background: white;
}
.mock-chart-bars .bar {
  flex: 1;
  background: var(--chart-1);
  border-radius: 4px 4px 0 0;
  position: relative;
}
.mock-chart-bars .bar.alt { background: var(--chart-soft-1); }
.mock-chart-bars .bar.cat-2 { background: var(--chart-2); }
.mock-chart-bars .bar.cat-3 { background: var(--chart-3); }
.mock-chart-bars .bar.cat-4 { background: var(--chart-4); }
.mock-chart-bars .bar.cat-5 { background: var(--chart-5); }
.mock-chart-bars .bar .lbl {
  position: absolute; bottom: -18px; left: 0; right: 0;
  text-align: center; font-size: 10px; color: var(--text-soft);
}

.mock-donut {
  width: 160px; height: 160px;
  border-radius: 999px;
  background:
    conic-gradient(var(--chart-1) 0 55%, var(--chart-2) 55% 75%, var(--chart-3) 75% 90%, var(--chart-4) 90% 100%);
  position: relative;
  margin: 0 auto;
}
.mock-donut.brand {
  /* tinte basado en accent del cliente */
  background:
    conic-gradient(var(--accent) 0 55%, var(--accent-dark) 55% 75%, var(--aivacy-silver-light) 75% 90%, var(--aivacy-mist) 90% 100%);
}
.mock-donut::after {
  content: ""; position: absolute; inset: 24px;
  background: white; border-radius: 999px;
}
.mock-donut .donut-center {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center;
}
.mock-donut .donut-center .v { font-size: 24px; font-weight: 700; }
.mock-donut .donut-center .l { font-size: 11px; color: var(--text-muted); margin-top: 2px; }

/* Tree (folders) */
.tree { font-size: 13px; }
.tree ul { list-style: none; padding-left: 18px; margin: 4px 0; }
.tree li { padding: 4px 0; }
.tree .folder { font-weight: 600; color: var(--text); display: flex; align-items: center; gap: 6px; }
.tree .file { color: var(--text-muted); display: flex; align-items: center; gap: 6px; }
.tree .file .v { color: var(--text-soft); font-size: 11px; }

/* Two-pane (list + detail) */
.two-pane {
  display: grid;
  grid-template-columns: 1fr 380px;
  gap: 18px;
}

/* Side-by-side editor (playbook) */
.editor-3col {
  display: grid;
  grid-template-columns: 220px 1fr 1fr;
  gap: 14px;
  height: 540px;
}
.editor-3col .pane {
  background: white;
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  overflow: hidden;
  display: flex; flex-direction: column;
}
.editor-3col .pane h4 {
  margin: 0; padding: 10px 14px;
  font-size: 12px; font-weight: 600;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border-soft);
  background: var(--bg-soft);
  text-transform: uppercase; letter-spacing: .3px;
}
.editor-3col .pane .body { padding: 14px; overflow: auto; flex: 1; font-size: 13px; line-height: 1.55; }
.editor-3col .clause-list { font-size: 13px; }
.editor-3col .clause-list .item {
  padding: 8px 10px; border-radius: 6px; cursor: pointer;
  border: 1px solid transparent;
}
.editor-3col .clause-list .item:hover { background: var(--bg-soft); }
.editor-3col .clause-list .item.active { background: var(--accent-soft); border-color: var(--accent); }
.editor-3col .clause-list .item .meta { font-size: 11px; color: var(--text-muted); }

/* Stat pill row */
.stat-row {
  display: flex; gap: 18px;
  padding: 14px 18px;
  border-radius: 8px;
  background: white;
  border: 1px solid var(--border-soft);
  margin-bottom: 18px;
}
.stat-row .stat .v { font-size: 18px; font-weight: 700; }
.stat-row .stat .l { font-size: 12px; color: var(--text-muted); }

/* Form grid */
.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
}
/* Campo que ocupa la fila entera: enumeraciones largas (sistemas, certificaciones) en una columna
   estrecha se leen peor que en una ancha. */
.form-grid .field.field-wide { grid-column: 1 / -1; }

/* Toggle */
.toggle {
  width: 36px; height: 20px;
  background: #C9CDD3;
  border-radius: 999px;
  position: relative;
  display: inline-block;
  vertical-align: middle;
}
.toggle::after {
  content: ""; position: absolute;
  width: 16px; height: 16px;
  background: white; border-radius: 999px;
  top: 2px; left: 2px;
  box-shadow: 0 1px 2px rgba(0,0,0,.2);
}
.toggle.on { background: var(--accent); }
.toggle.on::after { left: 18px; }

/* Banner */
.banner {
  display: flex; align-items: flex-start; gap: 12px;
  background: var(--accent-soft);
  border: 1px solid var(--border-soft);
  color: var(--text);
  border-radius: 8px;
  padding: 12px 14px;
  font-size: 13px;
  margin-bottom: 16px;
}
.banner .ico { color: var(--accent-dark); font-size: 18px; }
.banner.amber { background: #FEF3C7; border-color: #fde68a; }
.banner.amber .ico { color: #92400E; }
.banner.blue { background: #DBEAFE; border-color: #bfdbfe; }
.banner.blue .ico { color: #1E40AF; }

/* Stepper */
.stepper {
  display: flex; align-items: center; gap: 0;
  margin-bottom: 22px;
}
.stepper .step {
  display: flex; align-items: center; gap: 8px;
  font-size: 13px;
  color: var(--text-muted);
}
.stepper .step .num {
  width: 24px; height: 24px;
  border-radius: 999px;
  border: 1px solid var(--border-strong);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 600;
  background: white; color: var(--text-muted);
}
.stepper .step.active .num { background: var(--accent); color: white; border-color: var(--accent); }
.stepper .step.done .num { background: white; color: var(--accent); border-color: var(--accent); }
.stepper .step.active { color: var(--text); font-weight: 600; }
.stepper .gap {
  flex: 1; height: 1px; background: var(--border); margin: 0 12px;
}
@media (max-width: 620px) {
  /* En móvil las etiquetas de los 5 pasos desbordan: dejamos solo los círculos
     numerados (el «Paso X de N · …» del encabezado ya da el contexto textual). */
  .stepper .step > span:not(.num) { display: none; }
  .stepper .gap { margin: 0 8px; }
}

/* ========================================================================
   Selector de identidad
   Originalmente vivía en un <style> inline. Lo movemos aquí
   para reutilizarlo y para no inflar el HTML.
   ======================================================================== */

.clients-page {
  min-height: 100vh;
  background: var(--bg-app);
  padding: 64px 32px;
}
.clients-shell {
  max-width: 880px;
  margin: 0 auto;
}
.clients-head .brand-logo { height: 28px; display: block; margin-bottom: 20px; }
.clients-title { margin: 8px 0 8px; font-size: 26px; letter-spacing: -.3px; }
.clients-sub { color: var(--text-muted); margin: 0 0 28px; font-size: 14px; }
.client-card {
  background: white;
  border: 1px solid var(--border-soft);
  border-radius: 12px;
  padding: 18px 22px;
  display: grid;
  grid-template-columns: 60px 1fr auto;
  gap: 18px;
  align-items: center;
  margin-bottom: 12px;
  transition: border-color .12s, box-shadow .12s;
}
.client-card:hover { border-color: var(--aivacy-silver); box-shadow: var(--shadow); }
.client-card.platform { border-style: dashed; background: #f8fafc; }
/* No disponible: tono gris, sin sombra al pasar por encima y con el logo apagado. Ya no
   se baja la opacidad de toda la tarjeta, que dejaba el motivo casi ilegible. */
.client-card.disabled { background: var(--bg-soft); }
.client-card.disabled:hover { border-color: var(--border-soft); box-shadow: none; }
.client-card.disabled .logo { filter: grayscale(1); opacity: .6; }
.client-card-unavailable { display: flex; align-items: center; gap: 6px; max-width: 260px; color: var(--tone); }
.client-card-unavailable span { color: var(--text-muted); font-size: 13px; }
.client-card .logo {
  width: 60px; height: 60px;
  border-radius: 12px;
  /* Fondo blanco: los logos PNG con transparencia no deben mostrar el gris del lienzo
     (haría parecer el logo otra cosa). El gris se reserva para el icono genérico. */
  background: #fff;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
  font-size: 22px;
  font-weight: 700;
  color: var(--text);
}
.client-card .logo.platform { background: #374151; color: white; }
/* Logo de plataforma (baldosa Aivacy opaca): llena el cuadro de borde a borde. */
.client-card .logo.platform img { width: 100%; height: 100%; object-fit: cover; }
/* Logo de tenant (puede tener transparencia): encaja completo sobre el fondo blanco,
   sin recortar, con un pequeño margen. */
.client-card .logo:not(.platform) img {
  max-width: 100%; max-height: 100%;
  object-fit: contain;
  padding: 8px;
  box-sizing: border-box;
}
/* Icono genérico (cliente → company, revendedor → hierarchy) cuando no hay logo: en el tono
   informativo, el mismo de las tarjetas de indicadores. */
.client-card .logo.no-logo { background: var(--info-soft); color: var(--info); }
.client-card .info h3 {
  margin: 0 0 4px; font-size: 16px; font-weight: 600;
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
.client-card .info .meta { color: var(--text-muted); font-size: 13px; }
.client-card .info .meta strong { color: var(--text); font-weight: 600; }
.client-card .roles { display: flex; gap: 6px; margin-top: 8px; flex-wrap: wrap; }
.client-card .arrow {
  color: var(--text-muted); font-size: 14px;
  display: flex; align-items: center; gap: 4px;
}
.client-card .arrow form { margin: 0; }
.client-card .arrow .btn { padding: 8px 14px; font-weight: 600; }
.clients-foot {
  margin-top: 32px;
  text-align: center;
  font-size: 13px;
  color: var(--text-muted);
}
.clients-foot p { margin: 0; }
.clients-foot-logout {
  margin-top: 12px;
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  font-weight: var(--weight-medium);
  color: var(--accent-2-dark);
  text-decoration: underline;
  cursor: pointer;
}
.clients-foot-logout:hover { color: var(--accent-2); }

/* Alertas de página (banner verde/rojo arriba del contenido) ---------- */

.alert {
  padding: 12px 16px;
  border-radius: var(--radius);
  border: 1px solid transparent;
  margin-bottom: 14px;
  font-size: 13px;
  display: flex;
  align-items: flex-start;
  gap: 12px;
}
.alert > .alert-body { flex: 1; }
.alert .alert-close {
  background: transparent;
  border: 0;
  padding: 0 4px;
  margin: -2px -4px 0 0;
  color: inherit;
  opacity: .55;
  cursor: pointer;
  font-size: 18px;
  line-height: 1;
}
.alert .alert-close:hover { opacity: 1; }
.alert.alert-error  { background: #FEE2E2; border-color: #FCA5A5; color: #991B1B; }
.alert.alert-info   { background: #DBEAFE; border-color: #93C5FD; color: #1E3A8A; }
.alert.alert-warn   { background: #FEF3C7; border-color: #FCD34D; color: #92400E; }
.alert.alert-success { background: #DCFCE7; border-color: #86EFAC; color: #166534; }

/* ========================================================================
   Responsive — breakpoints para tablet portrait y móvil.

   - <= 900px: el split hero/form de las pantallas de auth se apila (hero
     fuera, formulario al 100%). El selector de clientes pasa a cards
     más compactas. Padding reducido en cabeceras.
   - <= 480px: ajustes finos de tipografía y padding para móvil estrecho.
   ======================================================================== */

@media (max-width: 900px) {
  .auth-body {
    grid-template-columns: 1fr;
    min-height: 0;
  }
  .auth-side-v2 { display: none; }
  .auth-form-wrap { padding: 28px 20px; flex-direction: column; gap: 24px; }
  /* Sin panel hero el alto lo marca el contenido: la firma entra en el flujo,
     debajo del formulario, para no montarse sobre él. */
  .auth-partner { position: static; align-self: flex-end; }
  .auth-form h1 { font-size: 22px; }

  .auth-client-header {
    padding: 12px 18px;
    gap: 10px;
    font-size: 14px;
  }
  .auth-client-header .brand-logo { height: 24px; }

  .clients-page { padding: 32px 16px; }
  .clients-title { font-size: 22px; }

  .client-card {
    grid-template-columns: 48px 1fr;
    gap: 12px;
    padding: 14px 16px;
  }
  .client-card .logo { width: 48px; height: 48px; font-size: 18px; }
  .client-card .arrow {
    grid-column: 1 / -1;
    justify-content: flex-end;
  }
  .client-card .arrow .btn { width: 100%; justify-content: center; }
}

@media (max-width: 480px) {
  .auth-client-header .login-meta { display: none; }
  .auth-form-wrap { padding: 24px 16px; }
  .auth-form h1 { font-size: 20px; }
  .auth-form .auth-sub { font-size: 13px; margin-bottom: 20px; }

  .clients-page { padding: 24px 12px; }
  .clients-title { font-size: 20px; }
  .clients-sub { font-size: 13px; }
}

/* === Password reset — barra de fortaleza y reglas === */
.pw-strength {
  display: flex;
  gap: 4px;
  margin-top: 6px;
}
.pw-strength span {
  flex: 1;
  height: 4px;
  background: var(--border);
  border-radius: 999px;
  transition: background 120ms ease;
}
.pw-strength span.on-w { background: #DC2626; }
.pw-strength span.on-m { background: #D97706; }
.pw-strength span.on-s { background: #16A34A; }
.pw-strength-label {
  font-size: 12px;
  margin: 4px 0 0;
  color: var(--text-muted);
}
.pw-rules {
  list-style: none;
  padding: 0;
  margin-top: 8px;
  font-size: 12px;
  color: var(--text-muted);
}
.pw-rules li { margin-bottom: 3px; }
.pw-rules li.ok { color: #16A34A; }

/* === Validación de formularios — patrón reutilizable === */
/* x-cloak evita el "flash" del mensaje de error mientras Alpine arranca. */
[x-cloak] { display: none !important; }

.field-error {
  display: block;
  color: #DC2626;
  font-size: 12px;
  margin-top: 4px;
}

.field.has-error .input {
  border-color: #DC2626;
}
.field.has-error .input:focus {
  outline-color: #DC2626;
  box-shadow: 0 0 0 2px rgba(220, 38, 38, 0.15);
}

/* Botón submit deshabilitado por validación (Alpine :disabled). */
/* Deshabilitado con superficie propia, no con opacidad: medio botón naranja con
   letra blanca al 50% sobre fondo claro dejaba el texto por debajo de 2:1, o
   sea ilegible justo cuando hay que explicar por qué no se puede pulsar. */
.btn[disabled],
.btn:disabled {
  background: var(--bg-app);
  background-image: none;
  border-color: var(--border-soft);
  color: var(--text-muted);
  box-shadow: none;
  cursor: not-allowed;
}

/* ========================================================================
   Onboarding de cliente (wizard)
   ===================================================================== */
.onboarding-subhead {
  font-size: 12px; text-transform: uppercase; color: var(--text-muted);
  letter-spacing: .4px; margin: 22px 0 10px;
}
.onboarding-actions {
  display: flex; gap: 8px; margin-top: 22px; justify-content: flex-end;
}
.onboarding-confirm {
  display: flex; align-items: flex-start; gap: 8px;
  margin-top: 18px; font-size: 13px;
}
.onboarding-confirm input { margin-top: 3px; }

/* Selección de roles del ADMIN (paso 2) */
.role-checks {
  display: grid; grid-template-columns: 1fr 1fr; gap: 8px;
}
.role-check {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 12px; font-size: 13px;
  border: 1px solid var(--border-soft); border-radius: 6px;
  cursor: pointer;
}
.role-check.on {
  border-color: var(--accent); background: var(--accent-soft);
}

/* Módulos a activar (paso 3) */
.module-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
}
.module-check {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; font-size: 13px;
  border: 1px solid var(--border-soft); border-radius: 6px;
  cursor: pointer;
}
.module-check:has(input:checked) {
  border-color: var(--accent); background: var(--accent-soft);
}
/* Fila de perfil: el nombre a la izquierda (lo marca/desmarca) y a la derecha el radio que decide
   cuál de los marcados es el predeterminado del cliente. Dos labels con su propio control, no uno
   anidado: si no, pulsar el radio alternaría también el checkbox. */
.skill-pick { justify-content: space-between; cursor: default; }
.skill-pick-name { display: flex; align-items: center; gap: 10px; cursor: pointer; min-width: 0; }
.skill-pick-default,
.skill-default-none {
  display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0;
  color: var(--text-muted); font-size: 12px; cursor: pointer;
}
.skill-pick-default:has(input:checked) { color: var(--accent-dark); font-weight: 600; }
.skill-pick-default:has(input:disabled) { opacity: .45; cursor: not-allowed; }
.skill-default-none { margin-top: 10px; }
/* Marca de capacidad con coste por servicio de IA. Solo la pinta la consola de plataforma: el
   revendedor gestiona cuotas, nunca dinero (AIV-190). */
.cost-mark { color: var(--text-muted); font-size: 12px; flex-shrink: 0; }

/* Icono de ayuda «?» con popover (Alpine), reutilizable vía fragments/help :: icon. */
.help-popover { position: relative; display: inline-flex; margin-left: auto; }
.help-trigger {
  width: 16px; height: 16px; padding: 0; flex-shrink: 0;
  border: 1px solid var(--border-soft); border-radius: 999px; background: transparent;
  color: var(--text-muted); font-size: 11px; font-weight: 700; line-height: 1; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
}
.help-trigger:hover, .help-trigger[aria-expanded="true"] {
  border-color: var(--accent); color: var(--accent-dark);
}
.help-bubble {
  position: absolute; top: calc(100% + 6px); right: 0; z-index: 30;
  width: 250px; padding: 10px 12px;
  background: white; border: 1px solid var(--border-soft); border-radius: 6px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12);
  font-size: 12px; font-weight: 400; line-height: 1.45; color: var(--text);
  white-space: normal; cursor: default; text-align: left;
}
.card-head .help-bubble { width: min(340px, 80vw); }
table.data.retrieval-table { overflow: visible; }
.retrieval-table thead th:first-child { border-top-left-radius: 8px; }
.retrieval-table thead th:last-child { border-top-right-radius: 8px; }
.retrieval-table thead th { white-space: nowrap; }
.retrieval-table th .help-popover { margin-left: 6px; vertical-align: middle; }
.retrieval-table th .help-bubble { text-transform: none; letter-spacing: normal; }

/* Bloques de revisión (paso 4) */
.review-block {
  background: white; border: 1px solid var(--border-soft);
  border-radius: 8px; padding: 16px 18px; margin-bottom: 12px;
}
.review-block .review-head {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 10px;
}
.review-block .review-head h4 {
  margin: 0; font-size: 13px; text-transform: uppercase;
  color: var(--text-muted); letter-spacing: .4px;
}
.review-block .review-head a { font-size: 12px; }
.review-block dl {
  display: grid; grid-template-columns: 1fr 1fr; gap: 6px 18px;
  margin: 0; font-size: 13px;
}
.review-block dt { color: var(--text-muted); }
.review-block dd { margin: 0; font-weight: 600; }

/* Listado de clientes (SUPERADMIN) */
.text-muted { color: var(--text-muted); }
.client-cell { display: flex; align-items: center; gap: 10px; }
.client-avatar {
  width: 36px; height: 36px; flex-shrink: 0;
  border-radius: 8px;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-soft); color: var(--text-muted);
  overflow: hidden;
}
.client-avatar.has-logo { background: #fff; border: 1px solid var(--border-soft); }
.client-avatar img { width: 100%; height: 100%; object-fit: contain; }
/* Avatar de persona: inicial en blanco sobre su tono. Cada clase .avatar-tone-N solo fija la
   variable, para que los tres tamaños (listado, cabecera de ficha, menú y burbuja de chat) la
   recojan sin depender del orden de las reglas, y para que sin tono se caiga al acento del tenant. */
.avatar-badge {
  border-radius: 999px;
  background: var(--avatar-bg, var(--accent));
  color: #fff;
  font-weight: 700;
  font-size: 13px;
  display: inline-flex; align-items: center; justify-content: center;
  flex: none;
  overflow: hidden;
}
.avatar-badge.avatar-lg { width: 38px; height: 38px; font-size: 15px; }
.avatar-tone-1  { --avatar-bg: var(--avatar-1); }
.avatar-tone-2  { --avatar-bg: var(--avatar-2); }
.avatar-tone-3  { --avatar-bg: var(--avatar-3); }
.avatar-tone-4  { --avatar-bg: var(--avatar-4); }
.avatar-tone-5  { --avatar-bg: var(--avatar-5); }
.avatar-tone-6  { --avatar-bg: var(--avatar-6); }
.avatar-tone-7  { --avatar-bg: var(--avatar-7); }
.avatar-tone-8  { --avatar-bg: var(--avatar-8); }
.avatar-tone-9  { --avatar-bg: var(--avatar-9); }
.avatar-tone-10 { --avatar-bg: var(--avatar-10); }
.client-meta { color: var(--text-muted); font-size: 12px; }
.usage-bar { height: 4px; background: var(--border-soft); border-radius: 999px; margin-top: 4px; }
.usage-bar > span { display: block; height: 100%; background: var(--accent); border-radius: 999px; }
.usage-bar.warn > span { background: var(--amber); }
.usage-bar.full > span { background: var(--red); }
.filter-bar .filter-search-input {
  border: 0; background: transparent; outline: none;
  font: inherit; color: var(--text); width: 100%;
}
.grace-note { font-size: 11px; color: var(--text-muted); margin-top: 4px; }

/* Tabla que aloja menús desplegables: sin overflow:hidden para que el dropdown no se recorte;
   las esquinas se redondean por celda en su lugar. */
.data.data-menu-host { overflow: visible; }
.data.data-menu-host thead tr th:first-child { border-top-left-radius: 8px; }
.data.data-menu-host thead tr th:last-child { border-top-right-radius: 8px; }
.data.data-menu-host tbody tr:last-child td:first-child { border-bottom-left-radius: 8px; }
.data.data-menu-host tbody tr:last-child td:last-child { border-bottom-right-radius: 8px; }

/* Botonera de fila (kebab) */
.row-menu { position: relative; display: inline-block; }
.row-menu-trigger {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px;
  border: 1px solid transparent; border-radius: 8px;
  background: transparent; color: var(--text-muted); cursor: pointer;
}
.row-menu-trigger:hover,
.row-menu-trigger[aria-expanded="true"] {
  background: var(--bg-soft); color: var(--text); border-color: var(--border-soft);
}
/* Kebab de cabecera (p. ej. detalle de cliente): va suelto en la página, sin fila que lo
   ancle visualmente — borde y fondo siempre visibles, como un botón ghost. */
.page-head .row-menu-trigger {
  width: 34px; height: 34px;
  background: white;
  border-color: var(--border-soft);
}
.row-menu-dropdown {
  position: absolute; top: calc(100% + 4px); right: 0;
  min-width: 220px;
  background: white;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 6px 0;
  z-index: 50;
  text-align: left;
}
.row-menu-dropdown[hidden] { display: none; }
.row-menu-dropdown .menu-section { padding: 0; }
.menu-item:disabled { opacity: .45; cursor: not-allowed; }
.menu-item:disabled:hover { background: transparent; }
.menu-item-danger,
.menu-item-danger .menu-item-icon { color: var(--red); }

/* Modal de confirmación fuerte (escribir el código) */
.modal-overlay {
  position: fixed; inset: 0; z-index: 1000;
  background: rgba(15, 23, 42, .45);
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
}
.modal {
  width: 100%; max-width: 460px;
  /* En pantallas bajas el modal no debe desbordar el overlay: scroll interno. */
  max-height: 100%; overflow-y: auto;
  background: white;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 24px;
}
.modal-title { margin: 0 0 10px; font-size: 18px; }
.modal-body { margin: 0 0 14px; font-size: 14px; color: var(--text); line-height: 1.5; }
.modal-prompt { margin: 0 0 8px; font-size: 13px; color: var(--text-muted); }
.modal-prompt code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 13px; font-weight: 700; color: var(--text);
  background: var(--bg-soft); padding: 1px 6px; border-radius: 4px;
}
.modal .input { width: 100%; }
.modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 16px; }

/* Visor de documentos: lo que se lee es un documento entero, no un aviso, así que el modal ocupa
   casi toda la ventana y el contenido va a sangre — la cabecera es lo único con margen. */
.modal.doc-viewer {
  max-width: 1080px; height: 92vh;
  padding: 0; overflow: hidden;
  display: flex; flex-direction: column;
}
.doc-viewer-head {
  display: flex; align-items: center; gap: 10px;
  padding: 12px 16px; border-bottom: 1px solid var(--border);
}
.doc-viewer-title {
  flex: 1; margin: 0; font-size: 15px; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.doc-viewer-frame { flex: 1; width: 100%; border: 0; background: var(--bg-soft); }
.doc-viewer-fallback {
  flex: 1; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 12px;
  padding: 32px; text-align: center; background: var(--bg-soft);
}
.doc-viewer-fallback-name { margin: 0; font-size: 15px; font-weight: 600; }
.doc-viewer-fallback-note { margin: 0; font-size: 13px; color: var(--text-muted); max-width: 44ch; }

/* En el móvil el documento se queda con toda la ventana: a ese ancho, el margen del overlay y las
   esquinas redondeadas se comen justo el espacio que hace falta para leer. */
@media (max-width: 640px) {
  .modal-overlay:has(.doc-viewer) { padding: 0; }
  .modal.doc-viewer { max-width: none; height: 100%; border-radius: 0; }
  .doc-viewer-head { padding: 10px 12px; gap: 6px; }
  .doc-viewer-title { font-size: 14px; }
  .doc-viewer-fallback { padding: 24px 16px; }
}

/* Árbol de carpetas de la gestión documental: la carpeta activa se marca
   como el nav del sidebar (accent-soft + accent-dark + negrita). */
.folder-tree a {
  display: flex; align-items: center; gap: 6px;
  padding: 6px 8px;
  border-radius: 6px;
  font-size: 13px;
  color: var(--text);
  text-decoration: none;
}
.folder-tree a:hover { background: var(--bg-soft); text-decoration: none; }
.folder-tree a.active { background: var(--accent-soft); color: var(--accent-dark); font-weight: 600; }
.folder-tree a .hint { margin-left: auto; font-size: 11px; }
.folder-tree a.active .hint { color: var(--accent-dark); }

/* Documento retirado en el índice documental: fila atenuada (el menú de acciones queda
   a plena opacidad para que "Reactivar" sea evidente). */
table.data tr.row-retired td:not(:last-child) { opacity: .55; }

/* Cascada de un grupo empresarial: los nombres comerciales que se caen con la matriz.
   El miembro que casa con la búsqueda se destaca con una barra de acento, que es la
   respuesta a "de qué grupo cuelga este tercero" — sin ella habría que releer la lista. */
.group-cascade { list-style: none; margin: 6px 0 0; padding: 0; }
.group-cascade li {
  padding: 4px 8px;
  border-left: 3px solid transparent;
  border-radius: 3px;
}
.group-cascade li.is-match { border-left-color: var(--accent); background: var(--accent-soft); }
.group-cascade .cascade-services {
  font-size: 12px;
  color: var(--text-muted);
  margin-top: 2px;
}

/* ── Chat ───────────────────────────────────────────────────────── */
.chat-page .app-main { padding: 0; }

/* El atributo `hidden` lo anularían los `display` de .cite-panel/.btn: lo restauramos. */
.cite-panel[hidden], #chat-stop[hidden] { display: none; }

.chat-shell {
  display: grid;
  grid-template-columns: 280px 1fr;
  height: 100%;
  min-height: 0;
  position: relative;
}

.chat-aside {
  display: flex;
  flex-direction: column;
  border-right: 1px solid var(--border-soft);
  background: var(--bg-soft);
  min-height: 0;
}
.chat-aside .new-chat { padding: 40px 14px 14px; }
.chat-aside .new-chat .btn { width: 100%; }
.conv-list { overflow-y: auto; padding: 0 8px 14px; flex: 1; min-height: 0; }
.conv-list .conv {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px; margin-bottom: 2px;
  border-radius: var(--radius); color: var(--text); font-size: 13px;
  text-decoration: none; cursor: pointer;
}
.conv-list .conv:hover { background: var(--bg-app); text-decoration: none; }
.conv-list .conv.active { background: var(--accent-soft); color: var(--accent-dark); font-weight: 600; }
.conv-list .conv .conv-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.conv-empty { color: var(--text-muted); font-size: 12px; padding: 8px 10px; }

/* Carpetas y archivado en el sidebar. */
.folder-new { display: flex; gap: 6px; padding: 4px 10px 10px; }
.folder-new input { flex: 1; min-width: 0; border: 1px solid var(--border); border-radius: var(--radius); padding: 5px 8px; font-size: 12px; }
.folder-new input:focus { outline: 0; border-color: var(--accent); }
.folder-new button { border: 1px solid var(--border); background: var(--bg); border-radius: var(--radius); width: 30px; cursor: pointer; color: var(--text-muted); }
.folder-new button:hover { border-color: var(--accent); color: var(--accent-dark); }

.group-label {
  display: flex; align-items: center; justify-content: space-between; gap: 6px;
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .3px;
  color: var(--text-muted); padding: 12px 10px 4px;
}
.group-label .folder-name { display: flex; align-items: center; gap: 6px; min-width: 0; }
.group-label .folder-name-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.group-label svg { flex: none; }
/* En la cabecera de carpeta abierta (group-label.folder-current) el kebab ancla su dropdown
   relativo a esta fila, igual que en .conv-row. */
.group-label.folder-current { position: relative; }

.conv-row { display: flex; align-items: center; gap: 4px; position: relative; }
.conv-row .conv { flex: 1; min-width: 0; }
.conv-row .conv-kebab { opacity: 0; transition: opacity .12s; flex: none; }
.conv-row:hover .conv-kebab,
.conv-row .conv-kebab[aria-expanded="true"] { opacity: 1; }
.folder-nav .conv-title { flex: 1; }
.folder-count { flex: none; font-size: 11px; font-weight: 600; color: var(--text-soft); }
.folder-back {
  display: flex; align-items: center; gap: 6px; width: 100%;
  border: 0; background: transparent; cursor: pointer; border-radius: 6px; outline: none;
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .3px;
  color: var(--text-muted); padding: 10px 10px 6px;
}
.folder-back:hover { color: var(--text); background: var(--bg-app); }
.folder-back:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.folder-back-caret {
  flex: none; width: 0; height: 0;
  border-style: solid; border-width: 4px 6px 4px 0;
  border-color: transparent currentColor transparent transparent;
}

/* Cierra el listado de conversaciones cuando el histórico sigue más allá de la página cargada:
   se sustituye a sí mismo por el tramo siguiente. */
.conv-more {
  display: block; width: 100%; margin-top: 4px;
  border: 0; background: transparent; cursor: pointer; border-radius: var(--radius); outline: none;
  font-size: 12px; color: var(--text-muted); padding: 8px 10px; text-align: left;
}
.conv-more:hover { color: var(--accent-dark); background: var(--bg-app); }
.conv-more:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.conv-more.htmx-request { opacity: .5; pointer-events: none; }

.modal-overlay[hidden] { display: none; }

.chat-main { display: flex; flex-direction: column; min-height: 0; }
.chat-stream { flex: 1; overflow-y: auto; padding: 40px 28px; min-height: 0; }
/* El lienzo vacío es la primera pantalla del día: el texto se centra en el
   hueco en vez de quedar pegado al borde superior de un vacío de 600px. */
.chat-empty {
  color: var(--text-muted);
  font-size: 15px;
  line-height: 1.6;
  text-align: center;
  text-wrap: pretty;
  margin: auto;
  max-width: 46ch;
}

/* Cada mensaje se ajusta a su contenido (no excede el texto), pegado a su lado —usuario a
   la derecha, asistente a la izquierda (align-self del bloque .msg)— con un tope máximo del
   94% de la columna: así una respuesta larga aprovecha el ancho sin llegar al borde (deja un
   margen del 6%), y un mensaje corto no genera una burbuja innecesariamente ancha. */
.chat-stream .msg { max-width: 94%; margin: 0 0 18px; font-size: 14px; line-height: 1.55; }
/* El contenido del mensaje de usuario va directo en la burbuja (sin caja propia): la
   burbuja es .msg.user (fondo blanco + borde de acento). */
.chat-stream .msg.user .msg-body { background: transparent; color: inherit; border: 0; border-radius: 0; padding: 0; }
.chat-stream .msg.assistant .msg-body {
  background: var(--bg); border: 1px solid var(--border-soft);
  border-radius: 12px 12px 12px 2px; padding: 12px 14px;
}
.chat-stream .msg.assistant.msg-error .msg-body { border-color: var(--red); color: var(--red); }
/* Aviso de respaldo débil del detector de alucinación: no es un error, solo una cautela. */
.msg-warning {
  margin-top: 6px; padding: 8px 12px;
  border: 1px solid var(--border-soft); border-left: 3px solid var(--accent);
  border-radius: 6px; background: var(--accent-soft);
  font-size: 12px; line-height: 1.4; color: var(--text-muted);
}
/* El aviso de PII es de privacidad: acento rojo para distinguirlo del de fidelidad. */
.msg-warning.msg-pii { border-left-color: var(--red); }
/* Acción de volver a pedir una respuesta que se cortó: pertenece al turno, bajo su burbuja. */
.msg-retry { margin: 8px 0 0; }
.chat-stream .who {
  display: flex; align-items: center; gap: 6px;
  font-size: 12px; color: var(--text-muted); margin-bottom: 4px;
}
.chat-stream .msg.user .who { justify-content: flex-end; }
/* El asistente se identifica con el logo «square» de la marca (es un <img>). */
.badge-ai {
  width: 20px; height: 20px; border-radius: 5px;
  object-fit: contain; background: #fff;
  display: inline-block; flex-shrink: 0;
}

.citations { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.citations .cite {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--border); border-radius: 999px;
  padding: 3px 10px 3px 4px; font-size: 12px; color: var(--text-muted);
  text-decoration: none; cursor: pointer; background: var(--bg);
}
.citations .cite:hover { border-color: var(--accent); color: var(--accent-dark); }
.citations .cite .num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 18px; height: 18px; border-radius: 999px;
  background: var(--accent-soft); color: var(--accent-dark); font-weight: 700;
}

.chat-input-bar { border-top: 1px solid var(--border-soft); padding: 14px 28px; background: var(--bg); flex-shrink: 0; }
.chat-input {
  display: flex; align-items: center; gap: 8px;
  border: 1px solid var(--border); border-radius: var(--radius-lg); padding: 6px 6px 6px 14px;
}
.chat-input:focus-within { border-color: var(--accent); }
.chat-input .input-text { flex: 1; border: 0; outline: 0; font-size: 14px; background: transparent; color: var(--text); }
.send-btn {
  border: 0; border-radius: 8px;
  background: var(--accent); color: #fff;
  width: 34px; height: 34px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background-color .16s cubic-bezier(.22,1,.36,1);
}
.send-btn:hover { background: var(--accent-dark); }
.send-btn:disabled {
  background: var(--border-soft);
  color: var(--text-soft);
  cursor: default;
}
.chat-input-footer {
  margin-top: 8px; display: flex; flex-direction: column; gap: 2px;
  font-size: 11px; color: var(--text-soft);
}

.cite-panel {
  position: absolute; top: 0; right: 0; bottom: 0; width: min(560px, 90vw);
  background: var(--bg); border-left: 1px solid var(--border);
  box-shadow: var(--shadow-lg); display: flex; flex-direction: column; z-index: 5;
}
.cite-panel-head { display: flex; align-items: center; gap: 10px; padding: 16px 18px; border-bottom: 1px solid var(--border-soft); }
.cite-panel-head h3 { flex: 1; margin: 0; font-size: 14px; }
.cite-panel-num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 999px;
  background: var(--cite-soft); color: var(--cite); font-weight: 700; font-size: 12px;
}
.cite-panel-close { border: 0; background: transparent; font-size: 20px; color: var(--text-muted); cursor: pointer; }
.cite-panel-body { padding: 18px; overflow-y: auto; }
.cite-panel-meta { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; margin: 0 0 16px; font-size: 13px; }
.cite-panel-meta dt { color: var(--text-muted); }
.cite-panel-meta dd { margin: 0; }
.cite-panel-note { font-size: 12px; color: var(--text-muted); background: var(--bg-soft); border-radius: var(--radius); padding: 12px 14px; }

/* Detalle de cita servido por fragmento. */
.cite-panel-loading { font-size: 13px; color: var(--text-muted); }
.cite-panel-doc-title { margin: 0 0 14px; font-size: 15px; line-height: 1.35; }
.cite-panel-section-h { margin: 18px 0 8px; font-size: 11px; text-transform: uppercase; letter-spacing: .3px; color: var(--text-muted); }
.doc-preview { background: var(--bg-soft); border: 1px solid var(--border-soft); border-radius: var(--radius); padding: 14px; font-size: 13px; line-height: 1.6; color: var(--text); overflow-x: auto; }
.doc-preview .pg-no { font-size: 11px; font-weight: 600; color: var(--text-muted); margin-bottom: 6px; }
.doc-preview p { margin: 0; white-space: pre-wrap; }
.doc-preview-table { width: max-content; border-collapse: collapse; font-size: 12px; }
.doc-preview-table td { border: 1px solid var(--border-soft); padding: 4px 8px; vertical-align: top; max-width: 340px; background: var(--bg); }
.doc-preview-table th { border: 1px solid var(--border-soft); padding: 4px 8px; text-align: left; white-space: nowrap; background: var(--bg-soft); font-weight: 600; }

/* Mapeo de columnas de importación (AIV-162): rejilla campo canónico ↔ columna del CSV + vista previa. */
.table-scroll { overflow-x: auto; max-width: 100%; }
.mapping-grid { display: flex; flex-direction: column; gap: 8px; margin: 16px 0 8px; }
.mapping-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; align-items: center; }
.mapping-row.mapping-head { font-size: 12px; color: var(--text-muted); font-weight: 600; text-transform: uppercase; letter-spacing: .04em; }
.mapping-row label { font-size: 14px; display: flex; align-items: center; }
.mapping-row .req { color: var(--accent); margin-left: 2px; }
.mapping-preview { margin-top: 24px; border-top: 1px solid var(--border-soft); padding-top: 16px; }
.mapping-preview-title { font-size: 15px; margin: 0 0 4px; }
.mapping-actions { display: flex; justify-content: flex-end; gap: 12px; margin-top: 20px; }
.cite-panel-perms { margin-top: 16px; font-size: 12px; color: var(--text-muted); background: var(--bg-soft); border-radius: var(--radius); padding: 12px 14px; }
.cite-panel-actions { display: flex; gap: 8px; margin-top: 16px; }
.cite-panel-actions .btn { flex: 1; text-align: center; text-decoration: none; }

/* Panel de ayuda in-app: drawer lateral derecho cargado por HTMX. Backdrop tenue para no
   perder de vista la pantalla mientras se consulta la ayuda. */
.help-drawer { position: fixed; inset: 0; z-index: 1000; pointer-events: none; }
.help-backdrop { position: absolute; inset: 0; background: rgba(0,0,0,.14); pointer-events: auto; }
.help-panel {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: min(460px, 94vw);
  background: var(--bg);
  border-left: 1px solid var(--border);
  box-shadow: -10px 0 30px rgba(0,0,0,.12);
  display: flex; flex-direction: column;
  pointer-events: auto;
}
.help-trans { transition: transform .22s ease, opacity .22s ease; }
.help-off { transform: translateX(100%); opacity: 0; }
.help-on { transform: translateX(0); opacity: 1; }

.help-panel-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px; border-bottom: 1px solid var(--border-soft); flex-shrink: 0;
}
.help-panel-title { margin: 0; font-size: 15px; font-weight: 600; color: var(--text); }
.help-panel-tools { display: flex; align-items: center; gap: 2px; }
.help-close, .help-panel-act {
  width: 32px; height: 32px; border-radius: var(--radius);
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-muted); background: transparent; border: 0; cursor: pointer;
}
.help-close:hover, .help-panel-act:hover:not(:disabled) { background: var(--bg-app); color: var(--text); }
.help-panel-act[hidden] { display: none; }
.help-panel-act:disabled { opacity: .5; cursor: default; }

.help-search {
  display: flex; align-items: center; gap: 8px;
  margin: 12px 16px;
  background: var(--bg-app); border: 1px solid var(--border-soft);
  border-radius: 8px; padding: 7px 12px; color: var(--text-muted); flex-shrink: 0;
}
.help-search-ico { display: inline-flex; }
.help-search-input {
  border: 0; background: transparent; outline: none;
  font: inherit; font-size: 13px; color: var(--text); width: 100%;
}

.help-body { flex: 1; min-height: 0; display: flex; flex-direction: column; overflow: hidden; }

/* Índice en árbol: cada guía (fichero) es el nodo padre colapsable y sus encabezados (H2/H3)
   los hijos. Custom (Alpine), no un <select> nativo, para poder anidar padres e hijos. */
.help-tree {
  flex-shrink: 0; max-height: 30%; overflow-y: auto;
  padding: 8px 8px 10px; border-bottom: 1px solid var(--border-soft);
}
.help-tree-row { display: flex; align-items: center; gap: 2px; }
.help-tree-toggle {
  width: 22px; height: 26px; flex-shrink: 0;
  border: 0; background: transparent; cursor: pointer; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--text-soft); border-radius: var(--radius);
}
.help-tree-toggle:hover { background: var(--bg-app); color: var(--text); }
.help-tree-toggle svg { transition: transform .15s ease; }
.help-tree-toggle[aria-expanded="false"] svg { transform: rotate(-90deg); }
.help-tree-toggle-empty { cursor: default; }
.help-tree-toggle-empty:hover { background: transparent; }
.help-tree-guide-name {
  flex: 1; min-width: 0;
  font-size: 13px; font-weight: 600; color: var(--text);
  padding: 5px 8px; border-radius: var(--radius); cursor: pointer;
}
.help-tree-guide-name:hover { background: var(--bg-soft); text-decoration: none; }
.help-tree-guide-name.active { background: var(--accent-soft); color: var(--accent-dark); }
.help-tree-children { list-style: none; margin: 0 0 4px; padding: 0; }
.help-tree-child {
  display: block; font-size: 12.5px; color: var(--text-muted);
  padding: 4px 8px 4px 8px; margin-left: 22px;
  border-left: 1px solid var(--border-soft); cursor: pointer;
}
.help-tree-child:hover { background: var(--bg-soft); color: var(--text); text-decoration: none; }

.help-content { flex: 1; min-height: 0; overflow-y: auto; padding: 18px 20px; }

/* Tipografía del markdown renderizado de las guías. */
.help-article { font-size: 13.5px; line-height: 1.6; color: var(--text); }
.help-article > :first-child { margin-top: 0; }
.help-article h1 { font-size: 19px; margin: 0 0 12px; }
.help-article h2 { font-size: 16px; margin: 24px 0 8px; padding-top: 16px; border-top: 1px solid var(--border-soft); }
.help-article h3 { font-size: 14px; margin: 16px 0 6px; }
.help-article p { margin: 0 0 10px; }
.help-article ul, .help-article ol { margin: 0 0 10px; padding-left: 20px; }
.help-article li { margin: 3px 0; }
.help-article li > ul, .help-article li > ol { margin: 3px 0; }
.help-article a { color: var(--accent-dark); }
.help-article strong { font-weight: 600; }
.help-article em { font-style: italic; }
.help-article code {
  background: var(--bg-code); border: 1px solid var(--border-soft);
  border-radius: 4px; padding: 1px 5px; font-size: 12px;
}
.help-article table { border-collapse: collapse; width: 100%; margin: 0 0 12px; font-size: 12.5px; }
.help-article th, .help-article td { border: 1px solid var(--border-soft); padding: 6px 8px; text-align: left; vertical-align: top; }
.help-article th { background: var(--bg-app); font-weight: 600; }
.help-article blockquote { margin: 0 0 10px; padding: 6px 12px; border-left: 3px solid var(--border); color: var(--text-muted); }

/* Sección a la que aterriza la ayuda al abrirse desde una pantalla: el destello dice "esto es lo
   que buscabas", sin él abrir a media guía parece un fallo de posición. */
.help-article .help-landed {
  margin-left: -12px; padding-left: 12px;
  margin-right: -8px; padding-right: 8px;
  border-radius: 4px;
  animation: help-landing 2.4s ease-out;
}
/* El fondo y la franja de acento son la misma caja —la franja va por dentro— para que tengan
   exactamente el mismo alto. El texto no se mueve: el hueco que abre el padding lo devuelve el
   margen negativo, y ambos van sin animar. */
@keyframes help-landing {
  0%, 55% { background-color: var(--accent-soft); box-shadow: inset 3px 0 0 0 var(--accent); }
  100% { background-color: transparent; box-shadow: inset 3px 0 0 0 transparent; }
}
@media (prefers-reduced-motion: reduce) {
  .help-article .help-landed { animation: none; }
}

/* Pestañas del panel: documentación navegable y asistente de uso. */
.help-tabs {
  display: flex; gap: 4px; flex-shrink: 0;
  padding: 8px 16px 0; border-bottom: 1px solid var(--border-soft);
}
.help-tab {
  border: 0; background: transparent; cursor: pointer;
  font: inherit; font-size: 13px; font-weight: 600; color: var(--text-muted);
  padding: 7px 12px; border-radius: 8px 8px 0 0;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
}
.help-tab:hover { color: var(--text); background: var(--bg-soft); }
.help-tab.active { color: var(--accent-dark); border-bottom-color: var(--accent); }

/* Chat embebido en un panel (asistente de uso del drawer de ayuda, chat de KPIs del cuadro de mando):
   hilo efímero + caja de envío anclada al pie. Mismo lenguaje de burbujas que el chat de trabajo
   (asimétricas, usuario a la derecha), a menor escala. Las reglas son compartidas a propósito: un chat
   embebido tiene que verse igual en todo el producto, y el panel que lo aloja aporta su propio
   posicionamiento.
   */
.mini-chat { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.mini-chat-thread {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: 16px; display: flex; flex-direction: column; gap: 12px;
}
.mini-chat-intro { margin: 0; color: var(--text-muted); font-size: 13px; line-height: 1.6; }

.mini-chat-msg { max-width: 92%; font-size: 13.5px; line-height: 1.6; }
.mini-chat-user {
  align-self: flex-end;
  background: white; color: var(--text);
  border: 1px solid var(--accent);
  border-radius: 12px 12px 4px 12px;
  padding: 9px 12px;
  box-shadow: var(--shadow-sm);
  white-space: pre-wrap;
}
.mini-chat-assistant {
  align-self: flex-start;
  background: white;
  border: 1px solid var(--border-soft);
  border-radius: 12px 12px 12px 4px;
  padding: 10px 13px;
}
/* Quien responde en estos paneles es Aivacy, no la empresa del usuario: la cabecera lleva el logo y el
   neutro de marca, nunca el acento del tenant (a diferencia del chat de trabajo). */
.mini-chat-who {
  display: flex; align-items: center; gap: 7px;
  margin-bottom: 6px;
  font-size: 11.5px; color: var(--text-muted);
}
.mini-chat-badge {
  width: 18px; height: 18px; border-radius: 5px;
  object-fit: contain; background: white; flex-shrink: 0;
}
.mini-chat-who-name { font-weight: 600; color: var(--cite); }
.mini-chat-failed .mini-chat-text { color: var(--red); }
/* Acción de volver a pedir una respuesta que se cortó, dentro de la burbuja del turno. */
.mini-chat-retry { margin: 10px 0 0; }
.mini-chat-retry .btn { width: 100%; justify-content: center; }

/* Gráfico embebido en una respuesta del panel (bloque aivacy-chart), algo más bajo que en el chat
   principal porque el drawer es estrecho. El alto es obligatorio: ECharts mide el contenedor al montar y
   en un div sin altura dibuja un lienzo de cero píxeles, así que el gráfico existe y no se ve. */
.mini-chat-text .chat-chart {
  width: 100%;
  height: 240px;
  margin: 8px 0;
}

/* Traslado de la pregunta al chat principal: acción del propio turno, dentro de la burbuja. */
.kpi-chat-handoff { margin: 10px 0 0; }
.kpi-chat-handoff .btn { width: 100%; justify-content: center; }

/* Tipografía del markdown de la respuesta (marked + DOMPurify), a la escala del drawer. */
.mini-chat-text > *:first-child { margin-top: 0; }
.mini-chat-text > *:last-child { margin-bottom: 0; }
.mini-chat-text p { margin: 0 0 8px; }
.mini-chat-text ul, .mini-chat-text ol { margin: 6px 0; padding-left: 18px; }
.mini-chat-text li { margin: 3px 0; }
.mini-chat-text strong { font-weight: 600; }
.mini-chat-text em { font-style: italic; }
.mini-chat-text h1, .mini-chat-text h2, .mini-chat-text h3 {
  font-size: 14px; font-weight: 600; margin: 12px 0 6px;
}
.mini-chat-text code {
  background: var(--bg-code); border: 1px solid var(--border-soft);
  border-radius: 4px; padding: 1px 5px; font-size: 12px;
}
.mini-chat-text pre {
  background: var(--bg-code); border: 1px solid var(--border-soft);
  border-radius: 6px; padding: 8px 10px; overflow-x: auto; font-size: 12px;
}
.mini-chat-text pre code { border: 0; background: none; padding: 0; }
.mini-chat-text blockquote {
  margin: 0 0 8px; padding: 4px 10px;
  border-left: 3px solid var(--border); color: var(--text-muted);
}

.mini-chat-form {
  display: flex; align-items: center; gap: 8px; flex-shrink: 0;
  padding: 12px 16px; border-top: 1px solid var(--border-soft);
}
.mini-chat-input {
  flex: 1; min-width: 0;
  border: 1px solid var(--border-soft); border-radius: 8px;
  background: var(--bg-app); padding: 9px 12px;
  font: inherit; font-size: 13px; color: var(--text); outline: none;
}
.mini-chat-input:focus { border-color: var(--accent); background: var(--bg); }
.mini-chat-input:disabled { opacity: .6; }
.mini-chat-send {
  width: 34px; height: 34px; flex-shrink: 0;
  border: 0; border-radius: 8px; cursor: pointer;
  background: var(--accent); color: #fff; font-size: 15px; line-height: 1;
}
.mini-chat-send:hover { background: var(--accent-dark); }
.mini-chat-send:disabled { opacity: .5; cursor: default; }

.help-empty, .help-results-msg { color: var(--text-muted); font-size: 13px; }
.help-results { display: flex; flex-direction: column; gap: 8px; }
.help-result {
  display: block; padding: 10px 12px; border: 1px solid var(--border-soft);
  border-radius: 8px; background: var(--bg); cursor: pointer; color: var(--text);
}
.help-result:hover { border-color: var(--border-strong); background: var(--bg-soft); text-decoration: none; }
.help-result-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 3px; flex-wrap: wrap; }
.help-result-guide { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--accent-dark); font-weight: 600; }
.help-result-section { font-size: 13px; font-weight: 600; }
.help-result-snippet { display: block; font-size: 12.5px; color: var(--text-muted); line-height: 1.5; }
.help-result-snippet mark, .help-article mark { background: var(--accent-soft); color: var(--accent-dark); padding: 0 2px; border-radius: 3px; }

/* ========================================================================
   Shell responsive (<= 900px): la nav lateral se convierte en drawer deslizable
   accionado por la hamburguesa del header, con overlay para cerrar. El drawer es
   un componente aparte del menú de usuario (que vive en su pie): el JS los trata
   por separado para que abrir uno no cierre el otro. En >900px todo esto queda
   inerte y el sidebar es la columna fija de escritorio.
   ======================================================================== */

/* Hamburguesa: oculta en escritorio; blanca porque va sobre la foto de la topbar. */
.nav-toggle {
  display: none;
  width: 40px; height: 40px;
  flex-shrink: 0;
  align-items: center; justify-content: center;
  padding: 0;
  border: 0; border-radius: 8px;
  background: transparent;
  color: #fff;
  cursor: pointer;
}
.nav-toggle:hover { background: rgba(255,255,255,.16); }

/* Overlay del drawer: el atributo hidden lo apaga; en móvil, al abrirse, se muestra.
   Fuera del breakpoint permanece oculto aunque se quede sin hidden tras un resize. */
.nav-backdrop {
  display: none;
  position: fixed; inset: 0; z-index: 980;
  background: rgba(0,0,0,.32);
}

@media (max-width: 900px) {
  /* Una sola columna; dvh evita que la barra de URL móvil recorte el shell. */
  .app { grid-template-columns: 1fr; height: 100dvh; }

  .nav-toggle { display: inline-flex; }

  .nav-backdrop:not([hidden]) { display: block; }

  /* El sidebar sale del grid y se desliza sobre el contenido desde la izquierda. */
  .app-sidebar {
    position: fixed; top: 0; left: 0; bottom: 0;
    width: min(280px, 82vw);
    z-index: 990;
    transform: translateX(-100%);
    transition: transform .22s ease;
    box-shadow: 6px 0 24px rgba(0,0,0,.18);
  }
  .app-sidebar.is-open { transform: translateX(0); }

  .app-header { padding: 0 16px; gap: 12px; }
  /* min-width:0 evita que el contenido no-envolvible estire el track 1fr por encima
     del viewport (el descriptor/co-brand del header, con white-space:nowrap). */
  .app-main { padding: 18px 16px; min-width: 0; }

  /* El descriptor del entorno y el co-branding «powered by» ocupan demasiado ancho en
     móvil y no aportan operativamente; se ocultan (el logo de marca se mantiene). */
  .topbar-descriptor, .topbar-cobrand { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .app-sidebar { transition: none; }
}

/* ========================================================================
   Chat responsive (<= 900px): el hilo ocupa todo el ancho; la lista de
   conversaciones pasa a drawer (mismo mecanismo data-drawer-* y overlay que
   el shell) accionado desde una barra superior propia del móvil; el panel de
   citas se muestra a pantalla completa. El input respeta el área segura para
   que el teclado virtual no lo tape (el shell del chat usa 100dvh).
   ======================================================================== */

/* Barra superior del chat: solo en móvil/tablet; en escritorio la lista es fija. */
.chat-mobile-head { display: none; }

@media (max-width: 900px) {
  .chat-page .app { height: 100dvh; }

  .chat-shell { grid-template-columns: 1fr; }

  .chat-mobile-head {
    display: flex; align-items: center; gap: 10px;
    padding: 10px 14px;
    background: white;
    border-bottom: 1px solid var(--border-soft);
    flex-shrink: 0;
  }
  .chat-convos-toggle {
    width: 36px; height: 36px;
    flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    padding: 0;
    border: 0; border-radius: 8px;
    background: transparent;
    color: var(--text);
    cursor: pointer;
  }
  .chat-convos-toggle:hover { background: var(--bg-app); }
  .chat-mobile-title { font-size: 14px; font-weight: 600; }

  /* Lista de conversaciones como drawer deslizable desde la izquierda. */
  .chat-aside {
    position: fixed; top: 0; left: 0; bottom: 0;
    width: min(300px, 84vw);
    z-index: 990;
    transform: translateX(-100%);
    transition: transform .22s ease;
    box-shadow: 6px 0 24px rgba(0,0,0,.18);
  }
  .chat-aside.is-open { transform: translateX(0); }

  /* Panel de citas a pantalla completa. */
  .cite-panel { position: fixed; inset: 0; width: 100%; z-index: 1000; }

  .chat-stream { padding: 16px; }
  .chat-input-bar {
    padding-left: 16px; padding-right: 16px;
    padding-bottom: calc(14px + env(safe-area-inset-bottom));
  }
}

@media (prefers-reduced-motion: reduce) {
  .chat-aside { transition: none; }
}

/* ========================================================================
   Dashboard responsive: los KPIs pasan de una fila a 2 columnas y a 1 (móvil
   estrecho). El corte está en 1200px y no en 900 porque con cinco tarjetas por
   debajo de ese ancho la tarjeta baja de ~175px y el pie (cobertura, «vs
   fecha») ya no cabe en una línea; es preferible colapsar antes a dos columnas
   anchas que dejar los pies partidos. Las filas de gráficos ya colapsan a 1
   columna y los charts reflowan solos (dashboard.js escucha resize); los
   controles de fecha ya envuelven (flex-wrap en .dash-controls / .head-row).
   ======================================================================== */
@media (max-width: 1200px) {
  .kpi-grid { grid-auto-flow: row; grid-template-columns: repeat(2, 1fr); }
  /* Número impar de tarjetas: la última ocupa la fila entera en lugar de quedar
     huérfana en media fila. */
  .kpi-grid > .kpi-card:last-child:nth-child(odd) { grid-column: 1 / -1; }
}

@media (max-width: 480px) {
  .kpi-grid { grid-auto-flow: row; grid-template-columns: 1fr; }
  .page-head h1 { font-size: 20px; }
}

/* ========================================================================
   Resto de pantallas (<= 900px): que no desborden en móvil sin rediseñarlas.
   - Grids de dos columnas de formularios/edición apilan a una sola.
   - Tablas de datos: scroll horizontal propio (display:block + nowrap) para no
     ensanchar la página; el scroll queda contenido en la tabla. En escritorio
     siguen intactas (esto solo aplica en el breakpoint).
   ======================================================================== */
@media (max-width: 900px) {
  .form-grid,
  .module-grid,
  .role-checks,
  .mapping-row,
  .review-block dl {
    grid-template-columns: 1fr;
  }

  /* El segundo selector iguala/supera la especificidad de `.data.data-menu-host`
     (overflow:visible para sus dropdowns en escritorio) para que en móvil también
     scrolleen; el dropdown de acciones se recorta aquí, aceptable en móvil. */
  table.data,
  table.data.data-menu-host {
    display: block;
    overflow-x: auto;
    white-space: nowrap;
  }
}

/* ========================================================================
   Feedback de calidad por respuesta (pulgar arriba/abajo). Táctil-first: los
   botones están siempre visibles (nada solo-hover, inútil en móvil); el panel de
   motivos es una expansión inline bajo el mensaje (no un popover flotante, que se
   cortaría en el ancho del stream). El control se pinta tanto en el histórico
   (fragmento Thymeleaf) como en vivo (clon del template).
   ======================================================================== */

.msg-feedback { margin-top: 8px; }

/* Aviso de brecha a la Oficina de Privacidad (AIV-578): el bloque de confirmación bajo el turno.
   Pesa más que el resto de avisos del turno a propósito — pide una decisión, no informa. */
.breach-report {
  margin-top: 10px; padding: 12px 14px;
  border: 1px solid var(--border-soft); border-left: 3px solid var(--red);
  border-radius: 8px; background: var(--bg-soft);
}
.breach-report-question { margin: 0 0 4px; font-size: 13px; font-weight: 600; color: var(--text); }
.breach-report-note { margin: 0 0 10px; font-size: 12px; line-height: 1.4; color: var(--text-muted); }
.breach-report-label {
  display: block; margin-bottom: 4px;
  font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted);
}
.breach-report-text {
  width: 100%; box-sizing: border-box; resize: vertical; min-height: 84px;
  padding: 8px 10px; border: 1px solid var(--border); border-radius: 6px;
  font: inherit; font-size: 13px; line-height: 1.45; color: var(--text); background: var(--bg);
}
.breach-report-text:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.breach-report-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.breach-report.breach-busy { opacity: .6; pointer-events: none; }
.breach-report-failed { margin: 8px 0 0; font-size: 12px; color: var(--red); }

/* Constancia de que se informó: sustituye al bloque y no vuelve a ofrecer nada. */
.breach-report-done {
  display: flex; align-items: center; gap: 6px; margin-top: 10px;
  font-size: 12px; color: var(--text-muted);
}
.breach-report-done svg { flex: 0 0 auto; color: var(--green); }
.breach-report-error { margin-top: 10px; font-size: 12px; color: var(--red); }

/* A ancho de móvil los dos botones ocupan la fila entera: el primario arriba, que es el que se pulsa. */
@media (max-width: 560px) {
  .breach-report-actions { flex-direction: column; align-items: stretch; }
  .breach-report-actions .btn { width: 100%; }
}


.fb-actions { display: flex; align-items: center; gap: 4px; }

.fb-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px;
  padding: 0;
  border: 0; border-radius: 8px;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.fb-btn:hover { background: var(--bg-app); color: var(--text); }
.fb-btn.is-active { background: var(--accent-soft); color: var(--accent-dark); }
.fb-btn[disabled] { cursor: default; }
/* Llevarse la respuesta a un documento: misma forma que los pulgares, pero es un enlace
   (abre el documento en otra pestaña), así que hay que apagarle el subrayado. */
.fb-btn.fb-export { text-decoration: none; }

.fb-thanks { margin-left: 6px; font-size: 12.5px; color: var(--text-muted); }

.msg-feedback.fb-busy { opacity: .6; pointer-events: none; }

/* El panel de motivos solo aparece al elegir 👎 (abierto localmente) o cuando el voto ya es DOWN. */
.fb-reasons {
  display: none;
  margin-top: 8px;
  padding: 12px;
  border: 1px solid var(--border-soft);
  border-radius: 10px;
  background: var(--bg-app);
}
.msg-feedback.fb-open .fb-reasons,
.msg-feedback[data-rating="DOWN"] .fb-reasons { display: block; }

.fb-reasons-prompt { margin: 0 0 8px; font-size: 12.5px; font-weight: 600; color: var(--text); }

.fb-reasons-list { display: flex; flex-wrap: wrap; gap: 6px; }

.fb-reason {
  font-size: 12.5px;
  padding: 6px 10px;
  border: 1px solid var(--border-soft); border-radius: 999px;
  background: white;
  color: var(--text);
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease, color .15s ease;
}
.fb-reason:hover { border-color: var(--accent); }
.fb-reason.is-active { background: var(--accent-soft); border-color: var(--accent); color: var(--accent-dark); }

/* Comentario libre: solo cuando el motivo es «Otro» (abierto localmente o ya confirmado). */
.fb-other { display: none; margin-top: 8px; gap: 8px; align-items: flex-start; }
.fb-other.is-open,
.msg-feedback.fb-other-open .fb-other { display: flex; }
.fb-other-input {
  flex: 1; min-width: 0;
  max-width: 100%;
  resize: vertical;
  font: inherit; font-size: 13px;
  padding: 8px 10px;
  border: 1px solid var(--border-soft); border-radius: 8px;
  background: white;
}
.fb-other-submit {
  flex-shrink: 0;
  font-size: 12.5px;
  padding: 8px 12px;
  border: 0; border-radius: 8px;
  background: var(--accent); color: white;
  cursor: pointer;
}
.fb-other-submit:hover { background: var(--accent-dark); }

@media (max-width: 900px) {
  /* Tap-targets cómodos en táctil (mismo criterio que la hamburguesa del shell). */
  .fb-btn { width: 40px; height: 40px; }
  .fb-reason { padding: 9px 14px; font-size: 13px; }
  .fb-other { flex-direction: column; }
  .fb-other-input { width: 100%; }
  .fb-other-submit { align-self: flex-end; }
}

/* Resumen de solo lectura del feedback en el visor del SUPERADMIN (inerte, no editable): los pulgares
   se muestran con el votado resaltado (mismo aspecto que en el chat), pero no son clicables. */
.msg-feedback-ro { margin-top: 8px; font-size: 12.5px; color: var(--text-muted); }
.msg-feedback-ro .fb-btn { cursor: default; }
.msg-feedback-ro .fb-btn:hover:not(.is-active) { background: transparent; color: var(--text-muted); }
.fb-ro-detail { margin-top: 6px; }
.fb-ro-detail span:first-child { font-weight: 600; }
.fb-ro-comment { margin: 4px 0 0; }
.fb-ro-comment span:first-child { font-weight: 600; }

/* Tablero Call-for-Action (kanban): carriles en columnas, tarjetas apiladas dentro */
.cfa-board {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
  align-items: start;
}
.cfa-col {
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--bg-app);
  border-color: var(--border-soft);
}
.cfa-col > h3 {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 2px;
  font-size: 14px;
}
.cfa-col > h3 .badge { margin-left: auto; }
.cfa-card {
  display: block;
  background: var(--bg);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  padding: 12px;
  text-decoration: none;
  color: var(--text);
  box-shadow: var(--shadow-sm);
  cursor: pointer;
  transition: border-color .12s ease, box-shadow .12s ease;
}
.cfa-card:hover { border-color: var(--border-strong); box-shadow: var(--shadow); text-decoration: none; }
.cfa-card:hover .cfa-card-title { text-decoration: none; }
.cfa-card-title { font-weight: 600; margin-bottom: 6px; }
.cfa-card-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.cfa-card .subtitle { margin: 8px 0 0; font-size: 12px; }
/* Estado de la tarea: franja del color de su tono en el canto de la ficha (vencida, vence pronto,
   completada) y, fuera de plazo, fecha límite en rojo. El padding compensa los 2px extra del
   borde para que el contenido no se desplace. */
.cfa-card.tone-alert, .cfa-card.tone-busy, .cfa-card.tone-ok { border-left: 3px solid var(--tone); padding-left: 10px; }
.cfa-card-title { display: flex; align-items: flex-start; gap: 6px; }
.cfa-card-status { flex: none; display: inline-flex; margin-top: 2px; color: var(--tone); }
.cfa-card-assignee { display: flex; align-items: center; gap: 4px; color: var(--text-muted); }
.cfa-card-assignee svg { flex: none; }
.tag.tone-info  { background: var(--info-soft); color: var(--info); }
.tag.tone-alert { background: var(--red-soft); color: #991B1B; }
.tag.tone-busy  { background: var(--amber-soft); color: #92400E; }
.cfa-due-late {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; font-weight: 700; letter-spacing: .2px;
  color: var(--red);
  white-space: nowrap;
}
.cfa-due-late svg { flex: none; }

/* Carriles por campaña del seguimiento, como los epics de un tablero de Jira: todos los carriles miden
   lo mismo, sus cuatro columnas se estiran a esa altura y, si no caben las tarjetas, la columna hace
   scroll por dentro. */
.cfa-close-offer { align-items: center; }
.cfa-close-offer form { display: flex; gap: 8px; margin-left: auto; flex: none; }
.cfa-lane { margin-bottom: 16px; }
.cfa-lane-head {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 4px; cursor: pointer; list-style: none;
}
.cfa-lane-head::-webkit-details-marker { display: none; }
.cfa-lane-chevron { display: inline-flex; color: var(--text-muted); transition: transform .12s ease; }
.cfa-lane:not([open]) .cfa-lane-chevron { transform: rotate(-90deg); }
.cfa-lane-name { font-weight: 600; }
.cfa-lane-head .subtitle { margin: 0; font-size: 12px; }
.cfa-lane-link { margin-left: auto; font-size: 12px; }
.cfa-lane .cfa-board { align-items: stretch; }
.cfa-lane .cfa-col { height: 340px; min-height: 0; }
.cfa-col-cards {
  flex: 1; min-height: 0; overflow-y: auto;
  display: flex; flex-direction: column; gap: 10px;
}

@media (max-width: 1080px) {
  .cfa-board { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 620px)  {
  .cfa-board { grid-template-columns: 1fr; }
  .cfa-lane .cfa-col { height: auto; max-height: 340px; }
}

/* Selector de miembros de una lista de audiencia (CFA): checkbox + nombre + metadatos de segmentación */
.member-picker {
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-height: 420px;
  overflow-y: auto;
}
/* .member-picker prefija todo para ganar en especificidad a `.field label { display:block }`. */
.member-picker .member-option {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 12px;
  margin: 0;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  cursor: pointer;
  font-size: 14px;
  font-weight: 400;
  color: var(--text);
}
.member-picker .member-option:hover { border-color: var(--border-strong); background: var(--bg-soft); }
.member-picker .member-option > input { flex: none; margin: 0; }
.member-info {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 6px 10px;
}
.member-name { font-weight: 600; }
.member-meta { display: flex; flex-wrap: wrap; gap: 6px; }

/* Selector con búsqueda en servidor: arriba lo elegido, debajo lo que devuelve la búsqueda. */
.member-picker-server { display: flex; flex-direction: column; gap: 10px; }
.member-selected .member-selected-empty { margin: 0; }
.member-chips { display: flex; flex-wrap: wrap; gap: 6px; list-style: none; margin: 0 0 4px; padding: 0; }
.member-chip {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%;
  padding: 4px 4px 4px 10px; border-radius: 999px;
  background: var(--bg-soft); border: 1px solid var(--border); font-size: 13px;
}
.member-chip-name { font-weight: 600; overflow-wrap: anywhere; }
.member-chip-meta { color: var(--text-muted); font-size: 12px; overflow-wrap: anywhere; }
.member-chip-remove {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border: 0; border-radius: 50%; background: transparent;
  color: var(--text-muted); cursor: pointer;
}
.member-chip-remove:hover { background: var(--border-soft); color: var(--text); }
.member-chip-remove:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.member-search .member-filter { width: 180px; flex: none; }
.member-results > p { margin: 0; }
.member-result-list { list-style: none; margin: 0; padding: 0; border: 1px solid var(--border-soft); border-radius: var(--radius); }
.member-result {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 8px 12px; border-bottom: 1px solid var(--border-soft);
}
.member-result:last-child { border-bottom: 0; }
.member-results .hint { margin: 6px 0 0; font-size: 12px; color: var(--text-muted); }

/* Barra de acciones al pie de un formulario/paso de wizard: separada del contenido y alineada a la derecha. */
.form-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 18px;
}

/* Modal ancho para el detalle de tarea (Seguimiento CFA), con cabecera y botón de cierre. */
.modal.modal-lg { max-width: 680px; max-height: 88vh; }
.modal-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.modal-close {
  flex: none;
  border: none;
  background: transparent;
  font-size: 22px;
  line-height: 1;
  cursor: pointer;
  color: var(--text-muted);
  padding: 0 4px;
}
.modal-close:hover { color: var(--text); }

/* Detalle de tarea CFA (modal / página): cabecera con etiquetas + acción, y secciones pulidas. */
.cfa-detail-top {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.cfa-detail-tags { display: flex; flex-wrap: wrap; gap: 6px; }
.cfa-detail-actions { display: flex; gap: 8px; flex: none; }
.cfa-detail .card { margin-bottom: 12px; }
.cfa-detail .card:last-child { margin-bottom: 0; }

.cfa-assistant-hint { align-items: center; }
.cfa-detail .cfa-assistant-hint { margin-bottom: 12px; }
.cfa-assistant-hint a { font-weight: 600; white-space: nowrap; }
.cfa-assistant-hint .ico { display: inline-flex; }

.cfa-evidence-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 12px; }
.cfa-evidence-item { display: flex; align-items: center; gap: 8px; }
.cfa-evidence-item .subtitle { margin-left: auto; }
.cfa-evidence-form { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 4px; }

.cfa-comment-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 12px; }
.cfa-comment { background: var(--bg-soft); border: 1px solid var(--border-soft); border-radius: var(--radius); padding: 8px 12px; }
.cfa-comment.mine { background: var(--accent-soft); border-color: var(--accent-soft); }
.cfa-comment-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 3px; }
.cfa-comment-author { font-size: 12px; font-weight: 600; color: var(--text); }
.cfa-comment-date { font-size: 12px; color: var(--text-muted); }
.cfa-comment-form { display: flex; align-items: center; gap: 8px; }
.cfa-comment-form .input { flex: 1; }

.cfa-timeline { display: flex; flex-direction: column; gap: 10px; }
.cfa-timeline-ev { display: flex; flex-direction: column; gap: 2px; font-size: 13px; }
.cfa-timeline-row { display: flex; gap: 12px; align-items: baseline; }
.cfa-timeline-date { color: var(--text-muted); font-size: 12px; white-space: nowrap; min-width: 130px; }
.cfa-timeline-actor { color: var(--text-muted); font-size: 12px; margin-left: auto; white-space: nowrap; }
.cfa-timeline-detail { padding-left: 142px; color: var(--text-muted); word-break: break-word; }

@media (max-width: 620px) {
  /* La fila fecha·evento·actor no cabe en una línea en móvil (el actor —a menudo
     un email— se recortaba contra el borde): la fecha pasa a su propia línea y el
     actor deja de empujarse al extremo derecho. */
  .cfa-timeline-row { flex-wrap: wrap; column-gap: 8px; row-gap: 2px; }
  .cfa-timeline-date { flex-basis: 100%; min-width: 0; }
  .cfa-timeline-actor { margin-left: 0; white-space: normal; word-break: break-word; }
  .cfa-timeline-detail { padding-left: 0; }
}

/* ========================================================================
   Asistente de campañas CFA — panel conversacional por turnos
   ======================================================================== */
/* Chevron de un botón que abre menú (p. ej. «Nueva campaña»): el hueco lo pone el gap del .btn. */
.btn-chevron { display: inline-flex; align-items: center; opacity: .8; }
.btn[aria-expanded="true"] .btn-chevron { transform: rotate(180deg); }

.assist-stream { display: flex; flex-direction: column; gap: 12px; margin-bottom: 16px; }
.assist-empty p { margin: 0 0 4px; }
.assist-msg {
  max-width: 680px;
  padding: 10px 14px;
  border-radius: 14px;
  font-size: 14px;
  line-height: 1.55;
  white-space: pre-line;
}
.assist-msg.user {
  align-self: flex-end;
  background: white;
  border: 1px solid var(--accent);
  border-bottom-right-radius: 4px;
}
.assist-msg.assistant {
  align-self: flex-start;
  background: var(--bg-soft);
  border: 1px solid var(--border);
  border-bottom-left-radius: 4px;
}
.assist-form { display: flex; flex-direction: column; gap: 8px; }
.assist-form-actions { display: flex; align-items: center; justify-content: flex-end; gap: 12px; }
.assist-waiting { margin: 0; }
.assist-draft { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: 8px 16px; margin: 0 0 12px; }
.assist-draft dt { color: var(--text-muted); font-size: 13px; }
.assist-draft dd { margin: 0; word-break: break-word; }
.assist-draft dd .tag { margin-right: 6px; }
.assist-draft dd.is-empty { color: var(--text-muted); }

@media (max-width: 620px) {
  .assist-draft { grid-template-columns: 1fr; gap: 2px; }
  .assist-draft dd { margin-bottom: 8px; }
}

/* Equivalencias de terceros: cada fila pendiente es una decisión independiente, así que
   se encierra en su propio bloque en vez de separarse con una raya. Dentro, tres niveles
   de lectura: qué dice el fichero (nombre), por qué llegó aquí (nota) y qué se puede
   hacer (candidatos y búsqueda). */
.match-row {
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  background: var(--bg-soft);
  padding: 14px 16px;
  margin-top: 12px;
}
.match-row-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px; }
.match-row-name {
  font-family: var(--font-heading);
  font-size: 15px;
  font-weight: var(--weight-semibold);
  overflow-wrap: anywhere;
}
/* Fila que no trae ni nombre ni valor: sin esto la cabecera se queda sin ancla de lectura. */
.match-row-name.is-unnamed { color: var(--text-muted); font-weight: var(--weight-medium); }
/* El origen se va al extremo: identifica la fila, pero no se lee hasta que hace falta. */
.match-row-origin { margin-left: auto; font-size: 12px; color: var(--text-muted); }

/* Por qué no emparejó y sobre qué valor se declarará: anotación al margen, no contenido. */
.match-why {
  margin-top: 10px;
  padding-left: 10px;
  border-left: 2px solid var(--border);
}
.match-why p { margin: 0 0 4px; font-size: 12.5px; line-height: 1.5; color: var(--text-muted); }
.match-why p:last-child { margin-bottom: 0; }
/* Fila sin nada sobre lo que declarar: no hay acción posible, y se avisa. */
.match-why.is-blocked { border-left-color: var(--amber); }

.match-note { margin: 10px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--text-muted); }

.match-caption {
  margin: 14px 0 6px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-muted);
}

.match-candidates { list-style: none; margin: 0; padding: 0; }
.match-candidates li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  padding: 9px 12px;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  margin-bottom: 6px;
  background: var(--bg);
  transition: border-color .15s ease;
}
.match-candidates li:last-child { margin-bottom: 0; }
.match-candidates li:hover { border-color: var(--border-strong); }
.match-candidate-id { display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px; min-width: 0; }
.match-candidate-id strong { font-size: 13.5px; font-weight: 600; overflow-wrap: anywhere; }
.match-candidate-domain { font-size: 12px; color: var(--text-muted); }
.match-candidate-actions { display: flex; gap: 6px; }
.match-candidate-actions form { margin: 0; }

/* Buscar a mano cierra la fila: separado de lo que Aivacy propone, porque es la salida
   cuando ninguna propuesta vale. */
.match-search { margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border-soft); }
.match-search label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 6px;
}
.match-search .input { max-width: 420px; }
.match-search .match-candidates,
.match-search .match-note { margin-top: 8px; }

/* Tabla de declaradas: el dato secundario de cada celda baja de línea y se apaga. */
.match-meta { display: block; margin-top: 2px; font-size: 12px; color: var(--text-muted); }
.match-declared-actions { text-align: right; white-space: nowrap; }
.match-declared-actions form { margin: 0; }

@media (max-width: 620px) {
  .match-row-origin { margin-left: 0; }
  .match-candidates li { align-items: flex-start; flex-direction: column; }
}

/* Campo de fecha suelta dentro de una barra de controles: el ancho de una fecha
   formateada, en vez del 100% que heredaría de .input/.select. */
.input-date { width: 150px; min-width: 150px; flex: 0 0 auto; }

/* Campo único de rango de fechas: cabe «01/09/2026 — 30/09/2026» sin recortarse, y no
   estira hasta el 100% que heredaría de .input/.select dentro de una barra de filtros. */
.input-daterange { width: 240px; min-width: 240px; flex: 0 0 auto; }

/* Canales externos vinculados del perfil: fila con el logo de la aplicación, su nombre y el
   espacio de trabajo. El logo va en su recuadro blanco para que los colores de marca no se
   peleen con el fondo cálido de la tarjeta. */
.channel-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.channel-row {
  display: flex; align-items: center; gap: 12px;
  border: 1px solid var(--border-soft);
  border-radius: var(--radius-lg);
  background: white;
  padding: 12px 14px;
}
.channel-logo {
  flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px;
  border: 1px solid var(--border-soft);
  border-radius: 9px;
  background: var(--bg-app);
}
.channel-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
.channel-name { font-weight: 600; font-size: 13px; }
.channel-meta { color: var(--text-muted); font-size: 12px; }
.channel-meta code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 11.5px;
}
.channel-actions { flex: none; display: flex; align-items: center; gap: 8px; }

@media (max-width: 620px) {
  .channel-row { align-items: flex-start; flex-wrap: wrap; }
  .channel-actions { width: 100%; justify-content: flex-end; }
}

.slack-brand-button {
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  border-radius: 4px;
  line-height: 0;
}
.slack-brand-button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
}
.slack-brand-button img { display: block; }

.slack-summary { margin: 0; display: grid; gap: 10px 24px; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.slack-summary dt { font-size: 11px; color: var(--text-muted); margin: 0 0 2px; }
.slack-summary dd { font-size: 13px; font-weight: 600; margin: 0; }

.col-channel { text-align: center; }
.channel-mark {
  display: inline-flex;
  color: var(--text-muted);
  cursor: default;
}
.channel-mark svg { display: block; }


/* Última palabra sobre el movimiento: quien pide menos movimiento en su
   sistema no recibe ninguna transición que no haya autorizado el resto de la
   hoja, incluidas las añadidas más arriba sin bloque propio. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Página de error: la persona lee primero qué le ha pasado y qué puede hacer;
   el código y la ruta quedan debajo, como dato para soporte. */
.error-explain { margin: 0; font-size: 14px; }
.error-detail {
  margin: 8px 0 0;
  display: flex; flex-wrap: wrap; gap: 4px 18px;
  font-size: 12px;
  opacity: .85;
}
.error-detail code { word-break: break-all; }

/* ── Auditorías ──────────────────────────────────────────────────────────────────── */
.inline-form { display: inline-flex; align-items: center; gap: 8px; margin: 0; }
.text-danger { color: var(--red); font-weight: 600; }

.audit-editor trix-toolbar .trix-button--icon-strike,
.audit-editor trix-toolbar .trix-button--icon-link,
.audit-editor trix-toolbar .trix-button--icon-code,
.audit-editor trix-toolbar .trix-button-group--file-tools { display: none; }
.audit-editor trix-toolbar .trix-button-row { flex-wrap: wrap; }
.audit-editor trix-toolbar .trix-button.trix-active { background: var(--accent-soft); color: var(--accent-dark); }
.audit-editor trix-toolbar .trix-button-group { border-color: var(--border); }
.audit-editor trix-editor {
  min-height: 140px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--bg);
  padding: 10px 12px;
}
.audit-editor trix-editor:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent-soft); }
.audit-editor trix-editor h1,
.trix-content h3 { font-size: 15px; margin: 8px 0 4px; }
.trix-content blockquote { border-left: 3px solid var(--accent-soft); margin: 6px 0; padding-left: 10px; color: var(--text-muted); }

.audit-save-status { font-size: 12px; color: var(--text-muted); }
.audit-texts-actions { align-items: center; flex-wrap: wrap; }
.audit-texts-actions .audit-save-status { margin-right: auto; }
.audit-texts-actions.is-dirty .audit-save-status.is-saved .state { display: none; }
.audit-texts-dirty { font-size: 12px; font-weight: 600; color: var(--amber); }
.modal .filter-bar { border: 0; padding: 0; background: none; }
.audit-save-status .saving { display: none; }
.audit-save-status.htmx-request .saving { display: inline; }
.audit-save-status.htmx-request .state { display: none; }
.audit-save-status.is-saved .state { color: var(--green); }
.audit-save-status.is-conflict .state,
.audit-save-status.is-frozen .state { color: var(--red); font-weight: 600; }

.audit-subject-options { list-style: none; margin: 8px 0 14px; padding: 0; border: 1px solid var(--border-soft); border-radius: var(--radius-sm); }
.audit-subject-options li { padding: 8px 12px; border-bottom: 1px solid var(--border-soft); }
.audit-subject-options li:last-child { border-bottom: 0; }

.modal.modal-wide { max-width: 620px; }
.modal .filter-bar { margin: 12px 0 0; }
.modal .filter-search { flex: 1; }
.audit-campaign-options { list-style: none; margin: 10px 0 0; padding: 0; max-height: 360px; overflow-y: auto;
  border: 1px solid var(--border-soft); border-radius: var(--radius-sm); }
.audit-campaign-options li { display: flex; align-items: center; justify-content: space-between; gap: 12px;
  min-height: 44px; padding: 8px 12px; border-bottom: 1px solid var(--border-soft); }
.audit-campaign-options li:last-child { border-bottom: 0; }
.audit-campaign-options li.is-already { background: var(--bg-soft); color: var(--text-muted); }
.audit-campaign-option-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.audit-campaign-option-text strong { overflow-wrap: anywhere; }
.audit-campaign-option-text .audit-choice-meta { font-size: 12px; color: var(--text-muted); display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }

.audit-facts { margin: 0; padding: 0; list-style: none; font-size: 13px; }
.audit-facts li { margin-bottom: 2px; }
.audit-facts .k { color: var(--text-muted); }
.audit-facts li.changed .v { font-weight: 700; }
.audit-task { border-bottom: 1px solid var(--border-soft); padding: 10px 0; }
.audit-task:last-child { border-bottom: 0; }
.audit-task .who { font-size: 12px; color: var(--text-muted); }
.audit-task .comment { margin-top: 6px; }
.audit-task .comment > div:last-child { white-space: pre-wrap; }
.audit-state-DONE { color: var(--green); font-weight: 600; }
.audit-state-OVERDUE { color: var(--red); font-weight: 600; }
.audit-state-PENDING { color: var(--amber); font-weight: 600; }
.audit-state-CANCELLED { color: var(--text-muted); font-weight: 600; }
.audit-page > .card + .card,
.audit-page > .alert-error + .card,
.audit-page > .banner + .card { margin-top: 14px; }
.audit-delete-list { margin: 4px 0 14px; padding-left: 20px; }
.audit-entry { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 8px; }
.audit-entry a:not(.btn) { color: var(--accent-dark); }
.dim-explore { margin: 8px 0 0; font-size: 13px; }
.dim-explore a { color: var(--accent-dark); }
.exp-result-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.exp-result-head .hint { margin: 0; }
.exp-result-audit { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; }
.exp-table th.exp-row-audit, .exp-table td.exp-row-audit { width: 1%; text-align: right; white-space: nowrap; padding-top: 3px; padding-bottom: 3px; }
.exp-row-audit .btn { display: inline-flex; align-items: center; gap: 5px; padding: 4px 10px; font-weight: 500; }
.audit-choice { border: 0; margin: 0 0 16px; padding: 0; }
.audit-choice legend { font-weight: 600; margin-bottom: 8px; }
.audit-choice-option {
  display: flex; align-items: center; gap: 10px;
  min-height: 44px; padding: 8px 12px;
  border: 1px solid var(--border-soft); border-radius: var(--radius-sm);
  cursor: pointer;
}
.audit-choice-option + .audit-choice-option { margin-top: 6px; }
.audit-choice-option:hover { border-color: var(--border); background: var(--bg-soft); }
.audit-choice-option:has(input:checked) { border-color: var(--accent); background: var(--accent-soft); }
.audit-choice-option:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
.audit-choice-option input { width: 18px; height: 18px; margin: 0; accent-color: var(--accent-dark); flex: none; }
.audit-choice-option .audit-choice-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.audit-choice-option .audit-choice-meta { font-size: 12px; color: var(--text-muted); }
.audit-choice-option.is-already { cursor: default; background: var(--bg-soft); color: var(--text-muted); }
.audit-choice-option.is-already:hover { border-color: var(--border-soft); }

/* Jerarquía de las pantallas de auditoría: el h2 de cada bloque por encima del texto, por debajo del h1. */
.audit-page .card .card-head h2 { margin: 0; font-size: 16px; font-weight: 600; }
.audit-measure { max-width: 75ch; }
/* Texto solo para lectores de pantalla (la cabecera de una columna de acciones, por ejemplo). */
.visually-hidden {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.campaign-task-stats { margin-bottom: 16px; }
.audit-hash { overflow-wrap: anywhere; }


.audit-strip {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 18px;
  list-style: none; margin: 8px 0 0; padding: 0;
  font-size: 13px; color: var(--text-muted);
}
.audit-strip li { display: inline-flex; align-items: center; gap: 4px; }
.audit-strip li + li::before { content: ""; width: 3px; height: 3px; border-radius: 50%; background: var(--border-strong); margin-right: 14px; }


.audit-ready { list-style: none; margin: 0 0 16px; padding: 0; display: grid; gap: 8px; }
.audit-ready li { display: flex; align-items: flex-start; gap: 10px; font-size: 14px; }
.audit-ready li svg { flex: none; margin-top: 2px; color: var(--green); }
.audit-ready li.is-warn svg { color: var(--amber); }
.audit-ready li.is-warn { color: var(--text); font-weight: 600; }
.audit-commit { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--border-soft);
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.audit-commit-note { display: flex; align-items: center; gap: 8px; margin: 0; font-size: 13px; color: var(--text-muted); max-width: 60ch; }
.audit-commit-note svg { flex: none; }

/* Una fila por elemento auditado en la versión finalizada: lo que cambió manda, lo demás se despliega. */
.audit-subject { padding: 14px 0; border-top: 1px solid var(--border-soft); }
.audit-subject:first-of-type { border-top: 0; padding-top: 0; }
.audit-subject-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.audit-subject-name { margin: 0 0 2px; font-size: 15px; font-weight: 600; }
.audit-subject-reason { margin: 6px 0 0; font-size: 13px; color: var(--text-muted); max-width: 75ch; }
.audit-diff { width: 100%; border-collapse: collapse; margin-top: 10px; font-size: 13px; font-variant-numeric: tabular-nums; }
.audit-diff th, .audit-diff td { text-align: left; padding: 7px 10px; border-bottom: 1px solid var(--border-soft); vertical-align: top; }
.audit-diff thead th { font-size: 12px; font-weight: 600; color: var(--text-muted); background: var(--bg-soft); }
.audit-diff tbody th { font-weight: 400; color: var(--text-muted); width: 34%; }
.audit-diff tr.is-changed td:last-child { font-weight: 600; color: var(--text); }
.audit-diff tr.is-changed { background: var(--amber-soft); }
.audit-diff-mark {
  display: inline-block; margin-left: 8px; padding: 1px 6px; border-radius: 999px;
  font-size: 11px; font-weight: 600; color: #7A5200; background: #F3DFA8;
}
.audit-diff-rest { margin-top: 10px; font-size: 13px; }
.audit-diff-rest summary { cursor: pointer; color: var(--text-muted); width: fit-content; }
.audit-diff-rest summary:hover { color: var(--text); }
.audit-facts-grid { display: grid; grid-template-columns: minmax(140px, 34%) 1fr; gap: 4px 12px; margin: 8px 0 0; }
.audit-facts-grid dt { color: var(--text-muted); }
.audit-facts-grid dd { margin: 0; }
.audit-campaign { padding: 14px 0; border-top: 1px solid var(--border-soft); }
.card-head + .audit-campaign, .card-head + .audit-subject { border-top: 0; padding-top: 0; }
.audit-kind-select { width: 220px; flex: none; }
.audit-campaign-name { margin: 0 0 4px; font-size: 15px; font-weight: 600; }

.audit-selection { margin: 0 0 16px; padding: 0; list-style: none; border: 1px solid var(--border-soft); border-radius: var(--radius-sm); }
.audit-selection li { display: flex; gap: 10px; padding: 7px 12px; border-bottom: 1px solid var(--border-soft); font-size: 13px; }
.audit-selection li:last-child { border-bottom: 0; }
.audit-selection .ref { color: var(--text-muted); font-variant-numeric: tabular-nums; min-width: 72px; }
.audit-reason-box { margin: 0 0 16px; padding: 12px 14px; border-radius: var(--radius-sm); background: var(--bg-soft); font-size: 13px; }
.audit-reason-box dt { font-weight: 600; }
.audit-reason-box dd { margin: 0 0 6px; color: var(--text); }
.audit-reason-box dd:last-child { margin-bottom: 0; }
.audit-disabled-hint { font-size: 12px; color: var(--text-muted); margin: 0; }

.audit-page table.data td.num, .audit-page table.data th.num { text-align: right; font-variant-numeric: tabular-nums; }

@media (max-width: 640px) {
  .audit-page table.audit-stack thead { display: none; }
  .audit-page table.audit-stack, .audit-page table.audit-stack tbody,
  .audit-page table.audit-stack tr, .audit-page table.audit-stack td { display: block; width: 100%; }
  .audit-page table.audit-stack tr { padding: 10px 0; border-bottom: 1px solid var(--border-soft); }
  .audit-page table.audit-stack td { border: 0; padding: 3px 0; text-align: left; white-space: normal; overflow-wrap: anywhere; }
  .audit-page table.audit-stack td.num { text-align: left; }
  .audit-page table.audit-stack td[data-label]::before {
    content: attr(data-label); display: block; font-size: 11px; font-weight: 600;
    color: var(--text-muted); text-transform: none;
  }
  .audit-diff thead { display: none; }
  .audit-diff tr { display: block; padding: 6px 0; border-bottom: 1px solid var(--border-soft); }
  .audit-diff tbody th, .audit-diff td { display: block; width: auto; border: 0; padding: 2px 10px; }
  .audit-diff tbody th { font-weight: 600; color: var(--text); }
  .audit-diff td[data-label]::before { content: attr(data-label) ": "; color: var(--text-muted); }
  .audit-facts-grid { grid-template-columns: 1fr; }
  .audit-facts-grid dd { margin-bottom: 6px; }
  .head-row .actions { flex-wrap: wrap; }
  .audit-commit { flex-direction: column; align-items: stretch; }
}
.audit-delete-list li { margin: 2px 0; }
