/* =====================================================================
   CRM FUNDACIÓN ACHE · Sistema visual
   Extensión directa de la identidad de fundacionache.com
   Saira · #050505 · Magenta #e6007e · Púrpura #7400b8 · Cyan #00aeef
   ===================================================================== */

/* ── 1. TOKENS ─────────────────────────────────────────────────────── */
:root {
  /* Marca */
  --ache-magenta: #e6007e;
  --ache-purpura: #7400b8;
  --ache-cyan:    #00aeef;

  --grad-marca:  linear-gradient(120deg, var(--ache-magenta) 0%, var(--ache-purpura) 50%, var(--ache-cyan) 100%);
  --grad-suave:  linear-gradient(120deg, rgba(230,0,126,.16), rgba(116,0,184,.14) 50%, rgba(0,174,239,.16));
  --grad-texto:  linear-gradient(92deg, var(--ache-magenta), var(--ache-purpura) 48%, var(--ache-cyan));

  /* Palomita de las casillas: va como máscara, así hereda el color. */
  --tic: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6L9 17l-5-5'/%3E%3C/svg%3E");

  /* Semánticos */
  --exito: #22c55e;  --alerta: #f5a524;  --peligro: #ef4444;  --info: #4361ee;

  /* Superficies (modo oscuro por defecto) */
  --fondo:        #050505;
  --fondo-alto:   #0b0b0f;
  /* EL FONDO DE LO QUE SE QUEDA PEGADO ARRIBA. Opaco del todo, y por eso
     es una variable propia y no un `color-mix` de las de arriba: una
     cabecera pegajosa que deja pasar aunque sea un 6 % enseña el renglón
     que va pasando por debajo, y entonces hay dos textos leyéndose a la
     vez justo donde hay que leer el título de la columna. */
  --fondo-fijo:   #0e0e14;
  --superficie:   rgba(255, 255, 255, .035);
  --superficie-2: rgba(255, 255, 255, .06);
  --borde:        rgba(255, 255, 255, .08);
  --borde-fuerte: rgba(255, 255, 255, .16);

  /* El canal de las barras de progreso. Va aparte de las superficies
     porque una superficie tiene que fundirse con la tarjeta y un canal
     tiene que CONTRASTAR con ella: son dos trabajos opuestos y con una
     sola variable uno de los dos temas siempre salía perdiendo. */
  --barra-canal: rgba(255, 255, 255, .13);
  --barra-borde: rgba(255, 255, 255, .10);

  /* Texto */
  --texto:      #ececf1;
  --texto-2:    #a8a8b8;
  --texto-3:    #6f6f7f;

  /* Geometría */
  --r-sm: 10px;  --r-md: 16px;  --r-lg: 22px;  --r-xl: 30px;  --r-full: 999px;
  --sombra-sm: 0 4px 16px rgba(0,0,0,.35);
  --sombra:    0 16px 44px rgba(0,0,0,.45);
  --sombra-lg: 0 30px 80px rgba(0,0,0,.6);
  --glow:      0 10px 34px rgba(230, 0, 126, .3);

  --sidebar-w: 264px;
  --header-h: 70px;
  --escala: 1;                  /* accesibilidad: la ajusta el usuario */
  --transicion: 260ms cubic-bezier(.22, 1, .36, 1);
}

/* ── 2. MODO CLARO ─────────────────────────────────────────────────── */
/* Respaldos de color-mix para el modo claro */
html[data-tema="light"] .sidebar,
html[data-tema="light"] .modal-caja,
html[data-tema="light"] .panel,
html[data-tema="light"] .toast,
html[data-tema="light"] .tabla thead th { background: #ffffff; }
html[data-tema="light"] .header { background: #f4f5f9; }
/* El anillo separa el punto de la línea del tiempo, así que tiene que
   ser del color del fondo de la página, no un halo de color. */
html[data-tema="light"] .tl-punto { box-shadow: 0 0 0 4px #f4f5f9; }

html[data-tema="light"] {
  --fondo:        #f4f5f9;
  --fondo-alto:   #ffffff;
  --fondo-fijo:   #ffffff;
  --superficie:   rgba(255, 255, 255, .82);
  --superficie-2: rgba(255, 255, 255, .96);
  --borde:        rgba(11, 11, 20, .10);
  --borde-fuerte: rgba(11, 11, 20, .2);
  --barra-canal:  rgba(11, 11, 20, .13);
  --barra-borde:  rgba(11, 11, 20, .12);
  --texto:        #14141c;
  --texto-2:      #4b4b5c;
  --texto-3:      #82828f;
  --sombra-sm: 0 4px 14px rgba(20, 20, 40, .07);
  --sombra:    0 16px 40px rgba(20, 20, 40, .10);
  --sombra-lg: 0 28px 70px rgba(20, 20, 40, .14);
  --grad-suave: linear-gradient(120deg, rgba(230,0,126,.09), rgba(116,0,184,.07) 50%, rgba(0,174,239,.09));
}

/* Alto contraste (a11y) */
html[data-contraste="1"] {
  --borde: rgba(255,255,255,.3);
  --texto-2: #d6d6e2;
  --texto-3: #b0b0c0;
  --barra-canal: rgba(255,255,255,.26);
  --barra-borde: rgba(255,255,255,.34);
}
html[data-tema="light"][data-contraste="1"] {
  --borde: rgba(0,0,0,.32);
  --texto-2: #22222c;
  --texto-3: #3a3a48;
  --barra-canal: rgba(0,0,0,.22);
  --barra-borde: rgba(0,0,0,.34);
}

/* ── 3. BASE ───────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }

html { font-size: calc(16px * var(--escala)); scroll-behavior: smooth; }

body {
  margin: 0;
  font-family: 'Saira', system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-weight: 400;
  background: var(--fondo);
  color: var(--texto);
  line-height: 1.65;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  transition: background var(--transicion), color var(--transicion);
}

/* Auroras de fondo: el sello visual de fundacionache.com */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -2;
  pointer-events: none;
  background:
    radial-gradient(48rem 34rem at 8% -8%,   rgba(230, 0, 126, .17), transparent 62%),
    radial-gradient(44rem 34rem at 106% 6%,  rgba(0, 174, 239, .15), transparent 60%),
    radial-gradient(40rem 34rem at 46% 116%, rgba(116, 0, 184, .18), transparent 62%);
  animation: auroras 26s ease-in-out infinite alternate;
}
html[data-tema="light"] body::before { opacity: .55; }

@keyframes auroras {
  0%   { transform: translate3d(0,0,0)      scale(1);    filter: hue-rotate(0deg); }
  50%  { transform: translate3d(1.5%,-2%,0) scale(1.07); filter: hue-rotate(14deg); }
  100% { transform: translate3d(-1.5%,2%,0) scale(1.03); filter: hue-rotate(-10deg); }
}

h1, h2, h3, h4, h5 { margin: 0; font-weight: 700; line-height: 1.25; letter-spacing: -.015em; }
h1 { font-size: 1.7rem; font-weight: 800; }
h2 { font-size: 1.28rem; }
h3 { font-size: 1.05rem; }
p  { margin: 0; }

a { color: var(--ache-cyan); text-decoration: none; transition: color var(--transicion); }
/* Un enlace se pone magenta al pasar por encima… salvo cuando no está
   disfrazado de enlace. El botón «Abrir» de las tarjetas del Directorio
   es un <a class="btn btn-primario">: al pasar el ratón, esta regla le
   ganaba en especificidad al blanco del botón y le pintaba el texto de
   magenta ENCIMA del degradado magenta-morado. De ahí el rojo apagado y
   sucio que se veía. Lo mismo les pasaba a los chips y a las tarjetas
   pulsables. Cada uno de esos ya tiene su propio color de hover; lo que
   sobraba era que este se lo pisara. */
a:not(.btn):not(.chip):not(.card):not(.nav-item):not(.alerta-item):hover {
  color: var(--ache-magenta);
}

::selection { background: rgba(230, 0, 126, .32); color: #fff; }

/* Scrollbars a juego */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
/* La esquina entre las dos barras se pintaba blanca por defecto: era ese
   cuadrito claro que salía abajo a la derecha del panel y de la página. */
::-webkit-scrollbar-corner { background: transparent; }
::-webkit-resizer { background: transparent; }
::-webkit-scrollbar-thumb {
  background: linear-gradient(180deg, rgba(230,0,126,.5), rgba(116,0,184,.5));
  border-radius: var(--r-full);
  border: 2px solid transparent;
  background-clip: padding-box;
}
::-webkit-scrollbar-thumb:hover { background: linear-gradient(180deg, var(--ache-magenta), var(--ache-purpura)); background-clip: padding-box; }

:focus-visible {
  outline: 2px solid var(--ache-cyan);
  outline-offset: 2px;
  border-radius: 6px;
}

/* ── 4. UTILIDADES DE MARCA ────────────────────────────────────────── */
.texto-grad {
  background: var(--grad-texto);
  background-size: 220% auto;
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
  animation: flujo 7s linear infinite;
}
@keyframes flujo { to { background-position: 220% center; } }

.borde-grad { position: relative; }
.borde-grad::before {
  content: ''; position: absolute; inset: 0; padding: 1px; border-radius: inherit;
  background: var(--grad-marca); background-size: 200% 200%;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor; mask-composite: exclude;
  opacity: 0; transition: opacity var(--transicion); pointer-events: none;
  animation: flujo 8s linear infinite;
}
.borde-grad:hover::before { opacity: 1; }

/* ── 5. TARJETAS (glassmorphism) ───────────────────────────────────── */
/* Un <button> o un <select> NO heredan el color del texto: usan el del
   sistema operativo, que es negro. Por eso las tres opciones de
   «Restablecer la contraseña» se leían en modo claro y desaparecían en
   modo oscuro: la tarjeta era oscura y el título también.
   Cualquier control que se disfrace de tarjeta hereda ahora el color de
   la aplicación, y de paso la tipografía y la alineación, que tenían el
   mismo problema por el mismo motivo. */
button.card, a.card, label.card {
  color: var(--texto);
  font: inherit;
  text-align: left;
}

.card {
  position: relative;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: var(--r-lg);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  box-shadow: var(--sombra-sm);
  transition: border-color var(--transicion), box-shadow var(--transicion),
              transform var(--transicion), background var(--transicion);
}
.card-p   { padding: 22px; }
.card-p-sm{ padding: 16px; }

.card:hover { border-color: var(--borde-fuerte); box-shadow: var(--sombra); }

/* Brillo que sigue al cursor (lo alimenta ui.js con --mx / --my) */
.card-luz::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(24rem 24rem at var(--mx, 50%) var(--my, 50%),
              rgba(230, 0, 126, .16), transparent 62%);
  opacity: 0; transition: opacity var(--transicion);
}
.card-luz:hover::after { opacity: 1; }

/* Inclinación 3D — los ángulos los calcula ui.js según el cursor */
.tilt {
  transform-style: preserve-3d;
  will-change: transform;
  transform: perspective(var(--perspectiva, 900px))
             rotateX(var(--rx, 0deg)) rotateY(var(--ry, 0deg))
             translateZ(0) scale(var(--sc, 1));
  transition: transform 120ms ease-out, box-shadow var(--transicion), border-color var(--transicion);
}
.tilt:hover { box-shadow: var(--sombra-lg); }
.tilt-hijo  { transform: translateZ(28px); }

/* ── 6. REVELADO AL HACER SCROLL ───────────────────────────────────── */
[data-reveal] {
  opacity: 0;
  transition: opacity 640ms cubic-bezier(.22,1,.36,1), transform 640ms cubic-bezier(.22,1,.36,1);
  transition-delay: var(--reveal-delay, 0ms);
  will-change: opacity, transform;
}
[data-reveal="up"]    { transform: translateY(34px); }
[data-reveal="down"]  { transform: translateY(-34px); }
[data-reveal="left"]  { transform: translateX(-40px); }
[data-reveal="right"] { transform: translateX(40px); }
[data-reveal="zoom"]  { transform: scale(.93); }
[data-reveal].visible { opacity: 1; transform: none; }

/* ── 7. BOTONES ────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 11px 20px;
  font: inherit; font-weight: 600; font-size: .9rem; line-height: 1;
  border: 1px solid transparent; border-radius: var(--r-full);
  cursor: pointer; white-space: nowrap; user-select: none;
  transition: transform var(--transicion), box-shadow var(--transicion),
              background var(--transicion), border-color var(--transicion), opacity var(--transicion);
}
.btn:active { transform: translateY(1px) scale(.985); }
.btn:disabled { opacity: .45; cursor: not-allowed; transform: none; }

.btn-primario {
  background: var(--grad-marca); background-size: 200% auto;
  color: #fff; box-shadow: var(--glow);
}
.btn-primario:hover:not(:disabled) { background-position: 100% center; transform: translateY(-2px); box-shadow: 0 14px 40px rgba(230,0,126,.42); }

.btn-fantasma { background: var(--superficie-2); color: var(--texto); border-color: var(--borde); }
.btn-fantasma:hover:not(:disabled) { border-color: var(--borde-fuerte); transform: translateY(-2px); }

.btn-exito   { background: rgba(34,197,94,.14);  color: var(--exito);   border-color: rgba(34,197,94,.34); }
.btn-peligro { background: rgba(239,68,68,.13);  color: var(--peligro); border-color: rgba(239,68,68,.32); }
.btn-exito:hover, .btn-peligro:hover { transform: translateY(-2px); }

.btn-sm  { padding: 7px 14px;  font-size: .8rem; }
.btn-xs  { padding: 5px 11px;  font-size: .74rem; }
.btn-ico { padding: 9px; width: 38px; height: 38px; border-radius: var(--r-full); }

/* ── 8. FORMULARIOS ────────────────────────────────────────────────── */
.campo { display: block; margin-bottom: 15px; }
.campo > label, .etiqueta-campo {
  display: block; margin-bottom: 6px;
  font-size: .78rem; font-weight: 600; letter-spacing: .02em;
  color: var(--texto-2); text-transform: uppercase;
}

.input, .select, .textarea,
input[type="text"], input[type="email"], input[type="password"], input[type="search"],
input[type="tel"], input[type="url"], input[type="number"], input[type="date"],
input[type="datetime-local"], input[type="time"], select, textarea {
  width: 100%;
  padding: 11px 14px;
  font: inherit; font-size: .92rem;
  color: var(--texto);
  background: rgba(0, 0, 0, .28);
  border: 1px solid var(--borde);
  border-radius: var(--r-sm);
  transition: border-color var(--transicion), box-shadow var(--transicion), background var(--transicion);
}
html[data-tema="light"] .input, html[data-tema="light"] .select, html[data-tema="light"] .textarea,
html[data-tema="light"] input, html[data-tema="light"] select, html[data-tema="light"] textarea {
  background: rgba(255, 255, 255, .9);
}
input:focus, select:focus, textarea:focus, .input:focus {
  outline: none;
  border-color: var(--ache-magenta);
  box-shadow: 0 0 0 3px rgba(230, 0, 126, .17);
}
textarea { resize: vertical; min-height: 92px; line-height: 1.6; }
select {
  appearance: none;
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238b8b98' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center; background-size: 15px;
  padding-right: 36px;
}
::placeholder { color: var(--texto-3); opacity: 1; }

/* ── 8.0 Campos de fecha y hora en iOS/iPadOS ────────────────────────
   Safari en iPhone y iPad no trata estos campos como un input normal:
   les da un ancho intrínseco propio (que se sale de la caja cuando la
   columna es estrecha) y empuja el valor contra el borde derecho. En
   escritorio no pasa, así que el fallo solo se ve en el iPad del
   cliente. Se corrige quitando la apariencia nativa y forzando la
   alineación de las piezas internas del valor.                        */
input[type="date"], input[type="datetime-local"],
input[type="time"], input[type="month"], input[type="week"] {
  -webkit-appearance: none; appearance: none;
  min-width: 0; max-width: 100%;
  box-sizing: border-box;
  text-align: left;
}
/* Solo iOS/iPadOS: ahí el valor no se centra en vertical sin esto, y
   `display:flex` en un input es una libertad que no hace falta tomarse
   en los navegadores donde el campo ya se pinta bien. */
@supports (-webkit-touch-callout: none) {
  input[type="date"], input[type="datetime-local"],
  input[type="time"], input[type="month"], input[type="week"] {
    display: flex; align-items: center;
    min-height: 46px;
  }
}
input[type="date"]::-webkit-date-and-time-value,
input[type="datetime-local"]::-webkit-date-and-time-value,
input[type="time"]::-webkit-date-and-time-value {
  text-align: left; margin: 0; min-width: 0;
}
input[type="date"]::-webkit-datetime-edit,
input[type="datetime-local"]::-webkit-datetime-edit,
input[type="time"]::-webkit-datetime-edit { padding: 0; }
/* El icono del calendario queda a la derecha y visible en ambos temas. */
input[type="date"]::-webkit-calendar-picker-indicator,
input[type="datetime-local"]::-webkit-calendar-picker-indicator,
input[type="time"]::-webkit-calendar-picker-indicator {
  margin-left: auto; margin-right: 0;
  opacity: .6; cursor: pointer; filter: invert(1);
}
input[type="date"]:hover::-webkit-calendar-picker-indicator,
input[type="datetime-local"]:hover::-webkit-calendar-picker-indicator,
input[type="time"]:hover::-webkit-calendar-picker-indicator { opacity: 1; }
html[data-tema="light"] input[type="date"]::-webkit-calendar-picker-indicator,
html[data-tema="light"] input[type="datetime-local"]::-webkit-calendar-picker-indicator,
html[data-tema="light"] input[type="time"]::-webkit-calendar-picker-indicator { filter: none; }

/* `hidden` tiene que ganarle a cualquier `display` del diseño.
   Sin esto, un `.pista[hidden]` seguía viéndose (como caja vacía)
   porque `.pista { display:flex }` pisaba la regla del navegador. */
[hidden] { display: none !important; }
/* ── 8.1 Casillas y radios propios ───────────────────────────────────
   El control nativo es un cuadrado gris de sistema: rompe la superficie
   de cristal y no responde al tema claro/oscuro. Se dibuja uno propio,
   del mismo tamaño y con el mismo comportamiento de teclado, con el
   check en SVG enmascarado para que herede el color. */
input[type="checkbox"], input[type="radio"] {
  appearance: none; -webkit-appearance: none;
  flex: none; width: 17px; height: 17px; margin: 0; padding: 0;
  position: relative; display: inline-grid; place-content: center;
  vertical-align: -3px; cursor: pointer;
  background: var(--superficie-2);
  border: 1.5px solid var(--borde-fuerte);
  border-radius: 5px;
  transition: background var(--transicion), border-color var(--transicion),
              box-shadow var(--transicion);
}
input[type="radio"] { border-radius: var(--r-full); }

input[type="checkbox"]::after {
  content: ''; width: 11px; height: 11px;
  transform: scale(0); transition: transform 120ms cubic-bezier(.3, 1.4, .5, 1);
  background: #fff;
  -webkit-mask: var(--tic) center / 11px 11px no-repeat;
          mask: var(--tic) center / 11px 11px no-repeat;
}
input[type="radio"]::after {
  content: ''; width: 7px; height: 7px; border-radius: var(--r-full);
  background: #fff; transform: scale(0);
  transition: transform 120ms cubic-bezier(.3, 1.4, .5, 1);
}

input[type="checkbox"]:hover, input[type="radio"]:hover { border-color: var(--ache-magenta); }

input[type="checkbox"]:checked, input[type="radio"]:checked {
  border-color: transparent;
  background-color: var(--ache-magenta);
  background-image: var(--grad-marca);
  background-size: 220% 100%;
  background-origin: border-box;
  background-repeat: no-repeat;
}
input[type="checkbox"]:checked::after,
input[type="radio"]:checked::after { transform: scale(1); }

/* Estado intermedio: la cabecera de "seleccionar todo" en el correo. */
input[type="checkbox"]:indeterminate {
  border-color: transparent;
  background-color: var(--ache-magenta);
  background-image: var(--grad-marca);
  background-size: 220% 100%;
}
input[type="checkbox"]:indeterminate::after {
  transform: scale(1);
  -webkit-mask: none; mask: none;
  width: 9px; height: 2px; border-radius: 2px;
}

input[type="checkbox"]:focus-visible, input[type="radio"]:focus-visible {
  outline: none; box-shadow: 0 0 0 3px rgba(230, 0, 126, .32);
}
input[type="checkbox"]:disabled, input[type="radio"]:disabled {
  opacity: .45; cursor: not-allowed;
}

/* Etiqueta pegada a la casilla, para no repetir el mismo flex 20 veces. */
.check {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: .84rem; color: var(--texto-2); cursor: pointer;
  user-select: none;
}
.check:hover { color: var(--texto); }

/* ── 9. INSIGNIAS Y PÍLDORAS ───────────────────────────────────────── */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px 10px;
  font-size: .7rem; font-weight: 700; letter-spacing: .03em;
  border-radius: var(--r-full);
  border: 1px solid currentColor;
  background: rgba(127,127,127,.14);                     /* respaldo */
  background: color-mix(in srgb, currentColor 13%, transparent);
  white-space: nowrap;
}
.badge-punto::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%;
  background: currentColor; box-shadow: 0 0 8px currentColor;
}

.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 13px; font-size: .8rem; font-weight: 600;
  color: var(--texto-2); background: var(--superficie);
  border: 1px solid var(--borde); border-radius: var(--r-full);
  cursor: pointer; transition: all var(--transicion);
}
.chip:hover { border-color: var(--borde-fuerte); color: var(--texto); transform: translateY(-1px); }
.chip.activo {
  background: var(--grad-marca); background-size: 180% auto;
  color: #fff; border-color: transparent; box-shadow: var(--glow);
}

/* ── 10. ESTRUCTURA ────────────────────────────────────────────────── */
.shell { display: flex; min-height: 100vh; }

.sidebar {
  position: fixed; top: 0; left: 0; bottom: 0; z-index: 60;
  width: var(--sidebar-w);
  display: flex; flex-direction: column;
  padding: 18px 14px;
  background: #0b0b0f;                                   /* respaldo */
  background: color-mix(in srgb, var(--fondo-alto) 88%, transparent);
  backdrop-filter: blur(22px); -webkit-backdrop-filter: blur(22px);
  border-right: 1px solid var(--borde);
  transition: transform var(--transicion);
  overflow-y: auto; overscroll-behavior: contain;
}
.sidebar-logo { display: flex; align-items: center; gap: 10px; padding: 8px 10px 20px; }
.sidebar-logo img { width: 130px; height: auto; filter: drop-shadow(0 6px 22px rgba(230,0,126,.4)); }

.nav-item {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 13px; margin-bottom: 3px;
  color: var(--texto-2); font-size: .88rem; font-weight: 500;
  border-radius: var(--r-sm); border: 1px solid transparent;
  position: relative; transition: all var(--transicion);
}
.nav-item:hover { background: var(--superficie); color: var(--texto); }
.nav-item.activo {
  color: #fff; background: var(--grad-suave);
  border-color: rgba(230, 0, 126, .3);
}
/* La barrita de degradado a la izquierda sobraba: el fondo suave, el borde
   magenta y el color del texto ya dicen dónde estás. Tres señales para lo
   mismo era ruido. */
html[data-tema="light"] .nav-item.activo { color: var(--texto); }
.nav-item svg { width: 18px; height: 18px; flex: 0 0 18px; }
.nav-grupo {
  padding: 16px 13px 7px; font-size: .66rem; font-weight: 800;
  letter-spacing: .13em; text-transform: uppercase; color: var(--texto-3);
}
.nav-contador {
  margin-left: auto; min-width: 21px; padding: 1px 6px;
  font-size: .68rem; font-weight: 800; text-align: center;
  color: #fff; background: var(--ache-magenta);
  border-radius: var(--r-full); box-shadow: 0 0 12px rgba(230,0,126,.55);
}

.principal { flex: 1; min-width: 0; margin-left: var(--sidebar-w); display: flex; flex-direction: column; }

.header {
  position: sticky; top: 0; z-index: 50;
  height: var(--header-h);
  display: flex; align-items: center; gap: 14px;
  padding: 0 22px;
  background: #050505;                                   /* respaldo */
  background: color-mix(in srgb, var(--fondo) 78%, transparent);
  backdrop-filter: blur(20px); -webkit-backdrop-filter: blur(20px);
  border-bottom: 1px solid var(--borde);
}
.contenido { flex: 1; padding: 24px 22px 60px; max-width: 1560px; width: 100%; }

.backdrop {
  position: fixed; inset: 0; z-index: 55;
  background: rgba(0, 0, 0, .6); backdrop-filter: blur(3px);
  opacity: 0; pointer-events: none; transition: opacity var(--transicion);
}
.backdrop.visible { opacity: 1; pointer-events: auto; }

@media (max-width: 1024px) {
  .sidebar { transform: translateX(-100%); box-shadow: var(--sombra-lg); }
  .sidebar.abierto { transform: translateX(0); }
  .principal { margin-left: 0; }
  .contenido { padding: 18px 14px 60px; }
  .header { padding: 0 14px; }
}

/* ── 11. REJILLAS ──────────────────────────────────────────────────── */
.grid       { display: grid; gap: 16px; }
/* `min(X, 100%)` en vez de `X` a secas: un mínimo fijo mayor que la caja
   no encoge, así que en un teléfono de 390 px una columna de 340 px
   desbordaba y aparecía scroll lateral. Con `min()` la columna baja al
   ancho disponible cuando hace falta. */
/* La tira de indicadores es una REJILLA, y se queda como rejilla.
   Se probó en su día pasarla a flex para que la última fila repartiera
   el ancho sobrante y no quedara un hueco. Sale mucho peor: en flex una
   tarjeta puede estirarse hasta ocupar la fila entera, y las tarjetas
   pasaban de ser tarjetas a ser barras de lado a lado. Un hueco al final
   de la última fila es infinitamente preferible a eso. La rejilla las
   mantiene todas del mismo tamaño, que es lo que las hace legibles de un
   vistazo. */
.grid-kpi   { grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr)); }
.grid-cards { grid-template-columns: repeat(auto-fill, minmax(min(280px, 100%), 1fr)); }
.grid-2     { grid-template-columns: repeat(auto-fit, minmax(min(340px, 100%), 1fr)); }
.grid-3     { grid-template-columns: repeat(auto-fit, minmax(min(250px, 100%), 1fr)); }

/* ── 12. KPI ───────────────────────────────────────────────────────── */
.kpi { position: relative; overflow: hidden; padding: 20px; }
.kpi::before {
  content: ''; position: absolute; top: 0; left: 0; right: 0; height: 2px;
  background: var(--grad-marca); background-size: 200% auto;
  opacity: .85; animation: flujo 6s linear infinite;
}
.kpi-etq {
  font-size: .72rem; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: var(--texto-3); margin-bottom: 8px;
}
.kpi-valor {
  font-size: 2.05rem; font-weight: 800; line-height: 1;
  letter-spacing: -.03em; font-variant-numeric: tabular-nums;
}
.kpi-pie { margin-top: 9px; font-size: .78rem; color: var(--texto-2); display: flex; align-items: center; gap: 6px; }
.delta-sube  { color: var(--exito); font-weight: 700; }
.delta-baja  { color: var(--peligro); font-weight: 700; }
.delta-igual { color: var(--texto-3); font-weight: 700; }

/* ── 13. TABLAS ────────────────────────────────────────────────────── */
.tabla-wrap { overflow-x: auto; border-radius: var(--r-md); }
.tabla { width: 100%; border-collapse: collapse; font-size: .87rem; }
.tabla thead th {
  position: sticky; top: 0; z-index: 2;
  padding: 11px 13px; text-align: left;
  font-size: .7rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase;
  color: var(--texto-3);
  /* OPACO DEL TODO, y ésa es la corrección.
     Antes ponía `color-mix(... 94%, transparent)`: la fila de títulos
     dejaba pasar un 6 % de lo que hubiera detrás. Suena a nada, y con
     texto oscuro sobre fondo claro se lee perfectamente el renglón que
     va pasando por debajo — se veían dos textos encima del otro justo
     donde hay que leer «OBSERVACIÓN».
     El resto de barras pegajosas del CRM son translúcidas A PROPÓSITO,
     pero llevan `backdrop-filter: blur()`, que emborrona lo de detrás
     hasta que no se lee. Ésta no lo lleva, así que translúcida era
     directamente un fallo. Y en una tabla, además, no se quiere el
     efecto: se quiere que la cabecera tape la fila. */
  background: var(--fondo-fijo);
  border-bottom: 1px solid var(--borde); white-space: nowrap;
}
.tabla tbody td { padding: 12px 13px; border-bottom: 1px solid var(--borde); vertical-align: middle; }
.tabla tbody tr { transition: background var(--transicion); }
.tabla tbody tr:hover { background: var(--superficie); }
.tabla tbody tr:last-child td { border-bottom: none; }
.num { font-variant-numeric: tabular-nums; text-align: right; }

/* ── 14. LÍNEA DE TIEMPO ───────────────────────────────────────────── */
.timeline { position: relative; padding-left: 34px; }
.timeline::before {
  content: ''; position: absolute; left: 12px; top: 6px; bottom: 6px; width: 2px;
  background: linear-gradient(180deg, var(--ache-magenta), var(--ache-purpura) 45%, var(--ache-cyan), transparent);
  opacity: .45;
}
.tl-item { position: relative; padding-bottom: 20px; }
/* ── Punto del historial ─────────────────────────────────────────────
   Antes: círculo de 20 px con borde de 2 px, un icono de 14 px que casi
   lo llenaba y un halo magenta fuerte heredado del color de marca. Se
   veía apretado, pesado y —lo que más cantaba— descentrado respecto a la
   línea del tiempo: el punto caía en el píxel 16 y la línea en el 13.

   Ahora: círculo algo mayor con el icono más pequeño dentro (la
   proporción que usan los iconos circulares que se leen bien), borde
   fino, relleno teñido con el color del canal en vez de halo de color, y
   centrado exacto sobre la línea.                                     */
.tl-punto {
  position: absolute; left: -34px; top: 1px;
  width: 26px; height: 26px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--fondo-alto);
  background: color-mix(in srgb, currentColor 14%, var(--fondo-alto));
  border: 1.5px solid currentColor;
  box-shadow: 0 0 0 4px var(--fondo);
  transition: transform var(--transicion), box-shadow var(--transicion);
}
/* El icono, holgado dentro del círculo y con el trazo del mismo grosor
   en todos los canales (venían con grosores distintos del SVG). */
.tl-punto svg { width: 13px; height: 13px; stroke-width: 2.1; }
.tl-item:hover .tl-punto {
  transform: scale(1.09);
  box-shadow: 0 0 0 4px var(--fondo), 0 0 0 6px color-mix(in srgb, currentColor 26%, transparent);
}
.tl-caja {
  position: relative;
  padding: 13px 16px; border-radius: var(--r-md);
  background: var(--superficie); border: 1px solid var(--borde);
  transition: all var(--transicion);
}
.tl-caja:hover { border-color: var(--borde-fuerte); transform: translateX(3px); }
/* Corregir y deshacer una gestión: discretos hasta que pasas por encima.
   Van juntos arriba a la derecha porque son las dos formas de tocar un
   registro ya hecho, y tenerlos separados invitaba a borrar cuando lo
   que se quería era arreglar una palabra. */
.tl-mandos {
  position: absolute; top: 8px; right: 8px;
  display: flex; gap: 4px;
  opacity: 0;
  transition: opacity var(--transicion);
}
.tl-caja:hover .tl-mandos,
.tl-mandos:focus-within { opacity: 1; }
@media (hover: none) { .tl-mandos { opacity: .75; } }

.tl-mando {
  display: grid; place-items: center;
  width: 26px; height: 26px; padding: 0;
  color: var(--texto-3); background: transparent;
  border: 1px solid transparent; border-radius: 7px;
  cursor: pointer;
  transition: color var(--transicion), background var(--transicion);
}
.tl-mando:hover { color: #fff; background: var(--ache-cyan); }
.tl-borrar:hover { color: #fff; background: var(--peligro); border-color: transparent; }

/* ¿FUE EFECTIVA? Se pidió así:
     «A simple vista no se sabe cuál fue o no fue efectiva.»

   Por eso no basta con cambiarle el color al texto, que es lo que había:
   sobre la tarjeta, dos textos de colores distintos se parecen demasiado
   al resto de etiquetas de la fila. Ésta lleva fondo propio y borde del
   mismo color, para que se lea como una RESPUESTA y no como una etiqueta
   más.

   Los tres casos se separan por tono y no solo por la palabra: verde lo
   que sirvió, rojo lo que no, y gris lo que nadie contestó. El gris es a
   propósito el más apagado — no es una respuesta, es que falta. */
.badge-efectiva {
  font-weight: 700;
  letter-spacing: .02em;
  border-width: 1px; border-style: solid;
}
.badge-efectiva.es-si {
  color: var(--exito);
  border-color: color-mix(in srgb, var(--exito) 45%, transparent);
  background: color-mix(in srgb, var(--exito) 13%, transparent);
}
.badge-efectiva.es-no {
  color: var(--peligro);
  border-color: color-mix(in srgb, var(--peligro) 45%, transparent);
  background: color-mix(in srgb, var(--peligro) 13%, transparent);
}
.badge-efectiva.es-sin {
  color: var(--texto-3);
  border-color: var(--borde);
  background: transparent;
}

/* «Corregida»: tiene que verse sin abrir nada. Si hubiera que entrar a
   mirar, quien lee la ficha daría por original un texto que no lo es, y
   eso es justo el riesgo de permitir editar. Es un botón, no una
   etiqueta: al pulsarlo se ve qué decía antes. */
.badge-editada {
  color: var(--alerta);
  border-color: color-mix(in srgb, var(--alerta) 40%, transparent);
  cursor: pointer;
  font: inherit;
  font-size: .68rem;
  font-weight: 700;
  display: inline-flex; align-items: center; gap: 4px;
}
.badge-editada:hover { background: color-mix(in srgb, var(--alerta) 14%, transparent); }
.tl-meta { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; font-size: .74rem; color: var(--texto-3); margin-top: 7px; }

/* Lo que la gestión dejó agendado, dentro de la propia gestión.
   Una llamada en la que además se programa el seguimiento es un solo
   hecho: separarlo en dos tarjetas obligaba a reconstruirlo a ojo. */
.tl-anexo {
  display: flex; gap: 10px; align-items: flex-start;
  margin-top: 10px; padding: 9px 11px;
  border-left: 3px solid #f5a524; border-radius: 0 var(--r-sm) var(--r-sm) 0;
  background: rgba(245, 165, 36, .09);
}
.tl-anexo-ico { color: #f5a524; flex: 0 0 auto; line-height: 0; margin-top: 2px; }
html[data-tema="light"] .tl-anexo { background: rgba(245, 165, 36, .13); }

/* ── 15. AVATAR ────────────────────────────────────────────────────── */
.avatar {
  display: inline-grid; place-items: center; flex: none;
  width: 38px; height: 38px; border-radius: 50%;
  font-size: .78rem; font-weight: 800; color: #fff;
  background: var(--grad-marca); background-size: 180% auto;
  border: 1px solid var(--borde); overflow: hidden;
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.avatar-sm { width: 28px; height: 28px; font-size: .66rem; }
.avatar-lg { width: 84px; height: 84px; font-size: 1.6rem; }

/* ── 16. TOASTS ────────────────────────────────────────────────────── */
#toasts {
  position: fixed; right: 20px; bottom: 20px; z-index: 9000;
  display: flex; flex-direction: column-reverse; gap: 10px;
  max-width: min(380px, calc(100vw - 40px)); pointer-events: none;
}
.toast {
  display: flex; align-items: flex-start; gap: 11px;
  padding: 13px 16px;
  background: #0b0b0f;                                   /* respaldo */
  background: color-mix(in srgb, var(--fondo-alto) 96%, transparent);
  border: 1px solid var(--borde); border-left: 3px solid var(--ache-cyan);
  border-radius: var(--r-md); box-shadow: var(--sombra);
  backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px);
  pointer-events: auto; cursor: pointer;
  animation: toast-in 380ms cubic-bezier(.22, 1, .36, 1);
}
.toast.saliendo { animation: toast-out 260ms ease-in forwards; }
.toast-exito   { border-left-color: var(--exito); }
.toast-error   { border-left-color: var(--peligro); }
.toast-alerta  { border-left-color: var(--alerta); }
.toast-titulo  { font-weight: 700; font-size: .87rem; margin-bottom: 2px; }
.toast-texto   { font-size: .8rem; color: var(--texto-2); line-height: 1.5; }
.toast-ico     { font-size: 1.05rem; line-height: 1.3; flex: none; }

/* X propia de cada aviso */
.toast-x {
  flex: none; display: grid; place-items: center;
  width: 22px; height: 22px; margin: -2px -4px 0 0; padding: 0;
  color: var(--texto-3); background: transparent;
  border: 0; border-radius: 6px; cursor: pointer;
  transition: color var(--transicion), background var(--transicion);
}
.toast-x:hover { color: var(--texto); background: var(--superficie-2); }

/* Barra de «Cerrar todas»: solo se dibuja cuando hay varias */
.toasts-barra {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 6px 8px 6px 12px;
  background: #0b0b0f;
  background: color-mix(in srgb, var(--fondo-alto) 96%, transparent);
  border: 1px solid var(--borde); border-radius: var(--r-full);
  box-shadow: var(--sombra);
  backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px);
  pointer-events: auto;
  animation: toast-in 300ms cubic-bezier(.22, 1, .36, 1);
}
.toasts-cuenta {
  font-size: .72rem; font-weight: 700; letter-spacing: .03em;
  color: var(--texto-3); text-transform: uppercase;
}
.toasts-todas {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px;
  font: inherit; font-size: .74rem; font-weight: 700;
  color: var(--texto); background: var(--superficie-2);
  border: 1px solid var(--borde); border-radius: var(--r-full);
  cursor: pointer; transition: all var(--transicion);
}
.toasts-todas:hover { color: #fff; background: var(--ache-magenta); border-color: transparent; }

@keyframes toast-in  { from { opacity: 0; transform: translateX(90px) scale(.94); } to { opacity: 1; transform: none; } }
@keyframes toast-out { to   { opacity: 0; transform: translateX(90px) scale(.94); } }

/* ── 17. MODALES ───────────────────────────────────────────────────── */
.modal {
  position: fixed; inset: 0; z-index: 8000;
  display: grid; place-items: center; padding: 20px;
  background: rgba(0, 0, 0, .68); backdrop-filter: blur(6px);
  opacity: 0; pointer-events: none; transition: opacity var(--transicion);
}
.modal.abierto { opacity: 1; pointer-events: auto; }
/* La caja es una columna: cabecera arriba, pie abajo y UNA sola zona con
   scroll en medio.
   Antes desplazaba la caja entera y, cuando el contenido traía además su
   propio `overflow` —la tabla del detalle del dashboard, por ejemplo—,
   salían dos barras verticales y el botón «Cerrar» quedaba fuera de la
   pantalla: había que hacer scroll para poder cerrar. Con esta estructura
   el pie está siempre a la vista, mande lo que mande el contenido. */
.modal-caja {
  width: 100%; max-width: 620px; max-height: 88vh;
  display: flex; flex-direction: column; overflow: hidden;
  padding: 26px;
  background: #0b0b0f;                                   /* respaldo */
  background: color-mix(in srgb, var(--fondo-alto) 97%, transparent);
  border: 1px solid var(--borde); border-radius: var(--r-xl);
  box-shadow: var(--sombra-lg);
  transform: translateY(22px) scale(.96); transition: transform var(--transicion);
}
.modal.abierto .modal-caja { transform: none; }
.modal-ancho .modal-caja { max-width: 900px; }
.modal-cabecera {
  flex: 0 0 auto;
  display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; margin-bottom: 18px;
}
/* El cuerpo es lo único que se desplaza. `min-height: 0` es imprescindible:
   sin él un hijo flex nunca se encoge por debajo de su contenido, la caja
   pasaría del 88vh y el pie volvería a salirse de la pantalla. */
.modal-caja > [data-cuerpo] {
  flex: 1 1 auto; min-height: 0;
  overflow: auto;
  overscroll-behavior: contain;
  margin-right: -8px; padding-right: 8px;   /* sitio para la barra */
}
.modal-caja > [data-pie] {
  flex: 0 0 auto;
  padding-top: 16px;
  border-top: 1px solid var(--borde);
}
/* Dentro de un modal las tablas ya no desplazan por su cuenta: crecen, y
   quien desplaza es el cuerpo. Así nunca hay dos barras.
   `overflow: visible` (no `auto`) a propósito: en cuanto un eje deja de ser
   visible el navegador convierte el otro en `auto` y el envoltorio vuelve a
   ser una zona de scroll —invisible, pero suficiente para que la cabecera
   pegajosa de la tabla se quede anclada a ella y deje de funcionar—. */
.modal-caja .tabla-wrap { max-height: none; overflow: visible; }

/* Filtros del detalle: se quedan arriba mientras se recorre la lista, que es
   justo lo que hacían antes cuando la tabla tenía su propio scroll.
   La cabecera de la tabla se pega debajo, a la altura que mida este bloque
   (la calcula el propio detalle y la deja en `--det-cab`). */
.detalle-fijo {
  position: sticky; top: 0; z-index: 4;
  padding-bottom: 10px;
  background: var(--fondo-fijo);
  /* Y TAN ANCHA COMO LA TABLA, no como la ventana.
     Aquí dentro la tabla puede ser más ancha que el modal —tiene que
     serlo, o la cabecera pegajosa dejaría de funcionar: en cuanto la
     tabla tiene su propia barra de desplazamiento, «pegarse arriba»
     se pega a esa caja, que no se mueve, y no a la ventana, que sí—.
     Esta banda medía lo que mide la ventana, así que a la derecha del
     todo no tapaba nada y por ahí se veían pasar las filas. Lo ancho
     que es la tabla lo mide el propio detalle y lo deja en
     `--det-ancho`; el `min-width` es para cuando la tabla cabe. */
  width: var(--det-ancho, auto);
  min-width: 100%;
}
.modal-caja .tabla thead th { top: var(--det-cab, 0px); }

/* ── 18. PANEL LATERAL ─────────────────────────────────────────────── */
.panel {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 70;
  width: min(420px, 100vw);
  padding: 20px;
  background: color-mix(in srgb, var(--fondo-alto) 97%, transparent);
  border-left: 1px solid var(--borde); box-shadow: var(--sombra-lg);
  backdrop-filter: blur(22px);
  transform: translateX(100%); transition: transform var(--transicion);
  overflow-y: auto; overscroll-behavior: contain;
}
.panel.abierto { transform: none; }

/* ── 19. BARRAS DE PROGRESO ────────────────────────────────────────── */
/* El canal NO usa --superficie-2. En modo claro esa variable vale
   rgba(255,255,255,.96) —blanco sobre la tarjeta blanca—, así que la
   barra existía pero no se veía: en oscuro se leía bien y en claro
   desaparecía. Aquí el canal es una tinta propia, con su propio valor en
   cada tema, y encima un borde de un pelo para que el extremo del
   recorrido se distinga aunque el relleno vaya al 2 %. */
.barra {
  height: 9px; border-radius: var(--r-full); overflow: hidden;
  background: var(--barra-canal);
  box-shadow: inset 0 0 0 1px var(--barra-borde);
}
.barra > span {
  display: block; height: 100%; border-radius: var(--r-full);
  background: var(--grad-marca); background-size: 200% auto;
  animation: flujo 5s linear infinite;
  transition: width 800ms cubic-bezier(.22, 1, .36, 1);
  /* Un relleno mínimo: al 1 % la barra tenía que poder decir «algo hay»
     y no «no hay nada», que es lo que enseña un span de medio píxel. */
  min-width: 3px;
}

/* ── 20. ESTADOS DE CARGA ──────────────────────────────────────────── */
.esqueleto {
  border-radius: var(--r-sm);
  background: linear-gradient(90deg, var(--superficie) 25%, var(--superficie-2) 50%, var(--superficie) 75%);
  background-size: 200% 100%;
  animation: brillo 1.4s ease-in-out infinite;
}
@keyframes brillo { to { background-position: -200% 0; } }

.spinner {
  width: 17px; height: 17px; border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, .22);
  border-top-color: var(--ache-magenta);
  animation: girar .68s linear infinite;
}
@keyframes girar { to { transform: rotate(360deg); } }

.cargando { position: relative; pointer-events: none; opacity: .55; }

/* Barra de progreso superior durante peticiones AJAX */
#progreso {
  position: fixed; top: 0; left: 0; z-index: 9999;
  height: 3px; width: 0;
  background: var(--grad-marca); background-size: 200% auto;
  box-shadow: 0 0 12px var(--ache-magenta);
  transition: width 240ms ease, opacity 300ms ease;
}

/* ── 21. VACÍOS ────────────────────────────────────────────────────── */
.vacio { padding: 52px 22px; text-align: center; color: var(--texto-3); }
.vacio-ico { font-size: 2.6rem; margin-bottom: 12px; opacity: .5; }

/* ── 22. UTILIDADES ────────────────────────────────────────────────── */
.flex   { display: flex; }
.entre  { justify-content: space-between; }
.centro { align-items: center; }
.wrap   { flex-wrap: wrap; }
.col    { flex-direction: column; }
.g-4 { gap: 4px; } .g-6 { gap: 6px; } .g-8 { gap: 8px; }
.g-10{ gap: 10px; } .g-12{ gap: 12px; } .g-14{ gap: 14px; } .g-16{ gap: 16px; } .g-20{ gap: 20px; }
.mt-4{margin-top:4px}.mt-8{margin-top:8px}.mt-12{margin-top:12px}
.mt-16{margin-top:16px}.mt-20{margin-top:20px}.mt-24{margin-top:24px}
.mb-8{margin-bottom:8px}.mb-12{margin-bottom:12px}.mb-16{margin-bottom:16px}.mb-20{margin-bottom:20px}
.crece { flex: 1; min-width: 0; }
.t-xs{font-size:.72rem}.t-sm{font-size:.8rem}.t-md{font-size:.88rem}.t-lg{font-size:1.05rem}
.t-2{color:var(--texto-2)}.t-3{color:var(--texto-3)}
.b6{font-weight:600}.b7{font-weight:700}.b8{font-weight:800}
.mono { font-variant-numeric: tabular-nums; }
.oculto { display: none !important; }
.truncar { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lineas-2 { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
.pointer { cursor: pointer; }
.sep { height: 1px; background: var(--borde); margin: 16px 0; border: 0; }

/* ── 23. ATAJOS DE TECLADO ─────────────────────────────────────────── */
kbd {
  display: inline-block; padding: 2px 7px; min-width: 22px; text-align: center;
  font-family: inherit; font-size: .7rem; font-weight: 700;
  color: var(--texto-2); background: var(--superficie-2);
  border: 1px solid var(--borde); border-bottom-width: 2px; border-radius: 6px;
}

/* ── 24. IMPRESIÓN ─────────────────────────────────────────────────── */
@media print {
  .sidebar, .header, .btn, #toasts, .no-imprimir { display: none !important; }
  .principal { margin-left: 0; }
  body { background: #fff; color: #000; }
  body::before { display: none; }
  .card { border: 1px solid #ddd; box-shadow: none; break-inside: avoid; backdrop-filter: none; }
}

/* ── 25. MOVIMIENTO REDUCIDO ───────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; scroll-behavior: auto !important;
  }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
}
html[data-animaciones="0"] [data-reveal] { opacity: 1 !important; transform: none !important; }
html[data-animaciones="0"] .tilt { transform: none !important; }
html[data-animaciones="0"] body::before { animation: none; }

/* =====================================================================
   26. CORRECCIONES Y COMPONENTES NUEVOS
   ===================================================================== */

/* ── 26.1 Degradados sin franja de color en el borde ────────────────
   El artefacto venía de la combinación por defecto de CSS:
     background-origin: padding-box  +  background-clip: border-box
   El degradado se posicionaba respecto a la caja de relleno pero se
   pintaba también bajo el borde de 1 px; como el mosaico se repite,
   en ese milímetro asomaba el extremo CYAN del degradado.
   Con origin en border-box y sin repetición, el relleno es continuo. */
.btn-primario,
.chip.activo,
.avatar,
.barra > span,
.kpi::before,
.tl-punto,
.fecha-dia.sel {
  background-origin: border-box;
  background-repeat: no-repeat;
}
.btn-primario {
  background-color: var(--ache-magenta);       /* respaldo si falla el degradado */
  background-image: var(--grad-marca);
  background-size: 220% 100%;
  background-position: 0% 50%;
  border-color: transparent;
}
.btn-primario:hover:not(:disabled) { background-position: 100% 50%; }

.chip.activo {
  background-color: var(--ache-magenta);
  background-image: var(--grad-marca);
  background-size: 200% 100%;
  background-position: 0% 50%;
  border-color: transparent;
}
.avatar {
  background-color: var(--ache-purpura);
  background-image: var(--grad-marca);
  background-size: 180% 100%;
  background-position: 0% 50%;
}
.barra > span { background-size: 220% 100%; }

/* ── 26.2 Iconos SVG ────────────────────────────────────────────────
   Sustituyen a los emojis: heredan color y tamaño, y se ven idénticos
   en Windows, macOS, Android e iOS. */
.ico {
  display: inline-block;
  vertical-align: -0.16em;
  flex: none;
  pointer-events: none;
}
.btn .ico, .chip .ico { margin-right: 1px; }
.btn-ico .ico, .btn-xs .ico { margin: 0; }
.ico-cir {
  display: inline-grid; place-items: center;
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--superficie-2); border: 1px solid var(--borde);
}

/* ── 26.3 Paneles flotantes opacos ──────────────────────────────────
   Antes heredaban la transparencia de .card y el contenido de detrás
   se colaba, dejando las notificaciones ilegibles. */
#panel-notificaciones,
#resultados-busqueda,
.pop-solido,
.fecha-pop {
  background: #0d0d12;
  background: color-mix(in srgb, var(--fondo-alto) 99%, transparent);
  border: 1px solid var(--borde-fuerte);
  box-shadow: var(--sombra-lg);
  backdrop-filter: blur(26px) saturate(180%);
  -webkit-backdrop-filter: blur(26px) saturate(180%);
}
html[data-tema="light"] #panel-notificaciones,
html[data-tema="light"] #resultados-busqueda,
html[data-tema="light"] .pop-solido,
html[data-tema="light"] .fecha-pop { background: #ffffff; }

#lista-notificaciones .tl-caja {
  background: var(--superficie-2);
  border-color: var(--borde);
}
#lista-notificaciones .tl-caja:hover { border-color: var(--ache-magenta); }
.notif-nueva { border-left: 3px solid var(--ache-magenta) !important; }

/* ── 26.4 Selector de fecha ─────────────────────────────────────────*/
.campo-fecha { position: relative; display: block; width: 100%; }
.campo-fecha > input { width: 100%; padding-right: 40px; }
/* Un campo de fecha que NO quiere la línea entera —los de las barras de
   filtros, que van en fila con los demás—. Lo pone `fecha.js` leyendo el
   ancho que pidió el campo: la regla vive junto al envoltorio, que es
   quien la incumplía, y no repetida en cada pantalla. */
.campo-fecha-suelto { display: inline-block; width: auto; vertical-align: middle; }
.campo-fecha-suelto > input { width: 100%; min-width: 0; }

/* Controles que forman UNA pregunta y no deben separarse al envolver:
   «qué fecha · desde · hasta» es una sola cosa, y un día colgando al
   final de una fila con su pareja en la siguiente no se lee como un
   rango. Se bajan los tres juntos. */
.filtro-grupo { display: inline-flex; align-items: center; gap: 8px; }
/* Se oculta el icono nativo (invisible sobre fondo oscuro) y se pone el propio */
.campo-fecha > input::-webkit-calendar-picker-indicator { display: none; opacity: 0; }
.campo-fecha > input::-webkit-inner-spin-button { display: none; }
.fecha-abrir {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  display: grid; place-items: center;
  width: 28px; height: 28px; padding: 0;
  color: var(--texto-2); background: transparent;
  border: 0; border-radius: 8px; cursor: pointer;
  transition: color var(--transicion), background var(--transicion);
}
.fecha-abrir:hover { color: var(--ache-magenta); background: var(--superficie-2); }

.fecha-pop {
  position: absolute; z-index: 9500;
  width: 292px; padding: 12px;
  border-radius: var(--r-md);
  opacity: 0; transform: translateY(-6px) scale(.98);
  transition: opacity 160ms ease, transform 160ms ease;
}
.fecha-pop.visible { opacity: 1; transform: none; }
.fecha-cab { display: flex; align-items: center; gap: 6px; margin-bottom: 10px; }
.fecha-cab select {
  flex: 1; padding: 7px 8px; font-size: .82rem;
  background: var(--superficie-2); border-radius: 8px;
}
.fecha-cab .btn-ico { width: 30px; height: 30px; padding: 0; }
.fecha-dias, .fecha-rejilla {
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px;
}
.fecha-dias span {
  text-align: center; font-size: .66rem; font-weight: 800;
  color: var(--texto-3); padding-bottom: 5px; letter-spacing: .04em;
}
.fecha-rejilla .fuera { height: 34px; }
.fecha-dia {
  height: 34px; border: 1px solid transparent; border-radius: 9px;
  font: inherit; font-size: .82rem; font-weight: 600;
  color: var(--texto); background: transparent; cursor: pointer;
  transition: background var(--transicion), color var(--transicion), border-color var(--transicion);
}
.fecha-dia:hover { background: var(--superficie-2); border-color: var(--borde-fuerte); }
.fecha-dia.hoy { border-color: var(--ache-cyan); color: var(--ache-cyan); }
.fecha-dia.sel {
  color: #fff; border-color: transparent;
  background-color: var(--ache-magenta);
  background-image: var(--grad-marca);
  background-size: 180% 100%;
}
/* Día fuera del rango permitido (p. ej. ya pasó) */
.fecha-dia.bloq,
.fecha-dia[disabled] {
  color: var(--texto-3); opacity: .34; cursor: not-allowed;
  background: transparent; border-color: transparent;
  text-decoration: line-through;
}
.fecha-dia.bloq:hover { background: transparent; border-color: transparent; }

/* La hora se ESCRIBE. Dos campos de dos dígitos, no un desplegable. */
.fecha-hora {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 12px; padding-top: 11px; border-top: 1px solid var(--borde);
}
.fecha-hora label { font-size: .72rem; font-weight: 700; color: var(--texto-3); text-transform: uppercase; }
.fecha-reloj {
  display: inline-flex; align-items: center; gap: 2px;
  padding: 3px 6px; border-radius: 9px;
  background: var(--superficie-2); border: 1px solid var(--borde);
}
.fecha-reloj:focus-within { border-color: var(--ache-magenta); }
.fecha-reloj b { font-weight: 800; color: var(--texto-3); }
.fecha-num {
  width: 2.4ch; padding: 4px 2px; margin: 0;
  font: inherit; font-size: .95rem; font-weight: 700; font-variant-numeric: tabular-nums;
  text-align: center; color: var(--texto);
  background: transparent; border: 0; border-radius: 6px;
}
.fecha-num:focus { outline: none; background: rgba(230, 0, 126, .16); }
.fecha-atajos { display: inline-flex; gap: 4px; flex-wrap: wrap; margin-left: auto; }
.fecha-atajos .btn-xs { padding: 3px 7px; font-size: .7rem; }
.fecha-nota {
  margin: 9px 0 0; padding: 6px 9px; border-radius: 8px;
  font-size: .74rem; line-height: 1.35;
  color: #ffd7ea; background: rgba(230, 0, 126, .14);
  border: 1px solid rgba(230, 0, 126, .35);
}
html[data-tema="light"] .fecha-nota { color: #8a0049; }
/* Campo con valor fuera de rango: se marca sin gritar. */
.campo-mal { border-color: var(--ache-magenta) !important; }
.fecha-pie {
  display: flex; gap: 6px; justify-content: flex-end;
  margin-top: 11px; padding-top: 10px; border-top: 1px solid var(--borde);
}

/* ── 26.5 Impresión y exportación ───────────────────────────────────
   El revelado al hacer scroll dejaba secciones invisibles al imprimir. */
@media print {
  [data-reveal] { opacity: 1 !important; transform: none !important; }
  .tilt { transform: none !important; }
  .card { break-inside: avoid; }
}

/* ── 26.6 Detalles varios ───────────────────────────────────────────*/
.cola-item { border-left: 3px solid transparent; }
.cola-item.sel {
  border-left-color: var(--ache-magenta);
  background: var(--grad-suave);
  border-color: var(--ache-magenta);
}
.pista {
  display: flex; align-items: flex-start; gap: 9px;
  padding: 11px 14px; border-radius: var(--r-md);
  background: var(--grad-suave); border: 1px solid rgba(230, 0, 126, .24);
  font-size: .82rem; color: var(--texto-2); line-height: 1.55;
}
.pista .ico { color: var(--ache-magenta); margin-top: 2px; }
.editable { cursor: text; border-bottom: 1px dashed var(--borde-fuerte); }
.editable:hover { border-bottom-color: var(--ache-magenta); color: var(--ache-magenta); }
.acciones-fila { display: flex; gap: 4px; flex-wrap: wrap; }

/* ── 27. SELECTOR DE PROYECTO ───────────────────────────────────────
   Todo lo que muestra el CRM pertenece al proyecto activo; el selector
   tiene que estar siempre a la vista para que nadie mezcle bases. */
.selector-proyecto { position: relative; margin: 4px 0 14px; }
.proy-boton {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 9px 11px; border-radius: var(--r-md);
  background: var(--superficie-2); border: 1px solid var(--borde);
  color: var(--texto); font: inherit; cursor: pointer; text-align: left;
  transition: border-color var(--transicion), background var(--transicion);
}
.proy-boton:hover { border-color: var(--ache-magenta); background: var(--grad-suave); }
.proy-punto {
  width: 10px; height: 10px; border-radius: 50%; flex: none;
  box-shadow: 0 0 0 3px rgba(255, 255, 255, .06);
}
.proy-lista {
  position: absolute; top: calc(100% + 7px); left: 0; right: 0; z-index: 90;
  padding: 7px; max-height: 60vh; overflow-y: auto;
  background: #0d0d12;
  background: color-mix(in srgb, var(--fondo-alto) 99%, transparent);
  border: 1px solid var(--borde-fuerte); box-shadow: var(--sombra-lg);
}
html[data-tema="light"] .proy-lista { background: #ffffff; }
.proy-item {
  display: flex; align-items: center; gap: 9px;
  padding: 8px 10px; border-radius: var(--r-sm);
  color: var(--texto-2); text-decoration: none; font-size: .84rem;
  transition: background var(--transicion), color var(--transicion);
}
.proy-item:hover { background: var(--superficie-2); color: var(--texto); }
.proy-item.activo { background: var(--grad-suave); color: var(--texto); }

/* La casilla de «trabajar también con este». Se le da tamaño de dedo
   porque va dentro de una fila que además es un enlace: si el área de
   la casilla fuera la de un ratón fino, en el móvil se acabaría
   cambiando de proyecto al intentar marcarla. */
.proy-casilla {
  flex: none; width: 17px; height: 17px; margin: 0; cursor: pointer;
  accent-color: var(--ache-magenta);
}

/* ── ETIQUETA DE ORIGEN ─────────────────────────────────────────────
   De qué proyecto salió un contacto, cuando se trabaja con varios a la
   vez. Lleva SIEMPRE el punto de color y el nombre, no solo el color:
   un distintivo que solo se distingue por el color no lo distingue
   quien no separa el magenta del morado, que es más gente de la que
   parece. El color acompaña; el que informa es el texto. */
.proy-origen {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 1px 8px 1px 6px; border-radius: var(--r-full);
  font-size: .62rem; font-weight: 700; letter-spacing: .02em;
  line-height: 1.7; white-space: nowrap; vertical-align: middle;
  color: var(--texto-2);
  background: var(--superficie-2);
  border: 1px solid var(--borde);
}
.proy-origen::before {
  content: ''; width: 7px; height: 7px; border-radius: 50%; flex: none;
  background: var(--origen, var(--ache-magenta));
}

/* ── 28. NOTIFICACIONES LEGIBLES ────────────────────────────────────
   El panel era tan translúcido que no se distinguía una notificación
   de otra. Ahora cada una es una tarjeta sólida con su icono en color. */
.notif-item {
  display: block; padding: 11px 12px; margin-bottom: 8px;
  border-radius: var(--r-md); cursor: pointer;
  background: var(--superficie-2); border: 1px solid var(--borde);
  border-left: 3px solid var(--ache-magenta);
  /* Sin esto, un remitente largo sin espacios —
     comunicacionesccinorte@infraestructura.org.co— se sale de la tarjeta
     y arrastra el panel entero a lo ancho. `min-width:0` deja encoger al
     hijo flexible; `overflow-wrap` le da permiso para partir la palabra. */
  min-width: 0; overflow: hidden;
  transition: border-color var(--transicion), background var(--transicion), transform var(--transicion);
}
.notif-item > .flex { min-width: 0; }
.notif-item [data-ir] { min-width: 0; }
.notif-item [data-ir] > div {
  overflow-wrap: anywhere; word-break: break-word; hyphens: auto;
}
.notif-item:hover { border-color: var(--ache-magenta); transform: translateX(2px); }
.notif-item.leida { border-left-color: var(--borde-fuerte); opacity: .62; }
.notif-ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 9px; flex: none;
  background: var(--superficie); border: 1px solid var(--borde);
  color: var(--ache-cyan);
}
.notif-tarea   { color: var(--alerta); }
.notif-cita    { color: var(--ache-cyan); }
.notif-acuerdo { color: var(--exito); }
.notif-correo  { color: var(--ache-magenta); }
.notif-sistema { color: var(--texto-3); }

/* ── 28.1 Panel de notificaciones: fuera del <header> ────────────────
   Vivía dentro del header (sticky, z-index 50), que crea su propio
   contexto de apilamiento: por muy alto que fuera su z-index, cualquier
   barra del contenido con z-index mayor se le ponía encima, y con ella
   sus botones seguían siendo pulsables. Ahora es fixed, se coloca por
   JS bajo la campana y se apoya en un velo que corta los clics. */
#velo-notif {
  position: fixed; inset: 0; z-index: 7000;
  background: rgba(0, 0, 0, .34);
  opacity: 0; visibility: hidden;
  transition: opacity 180ms ease, visibility 180ms;
}
html[data-tema="light"] #velo-notif { background: rgba(11, 11, 20, .22); }
#velo-notif.visible { opacity: 1; visibility: visible; }

#panel-notificaciones {
  position: fixed; z-index: 7010;
  width: min(380px, calc(100vw - 20px));
  max-width: calc(100vw - 20px);
  max-height: min(72vh, 620px);
  /* Nunca hacia los lados: el texto se parte, no se desborda. */
  overflow-y: auto; overflow-x: hidden;
  overscroll-behavior: contain;
  /* Opaco de verdad: el desenfoque solo, sobre la bandeja de correo,
     dejaba pasar el texto de debajo. */
  background: #101017;
  backdrop-filter: none; -webkit-backdrop-filter: none;
  box-shadow: 0 24px 70px rgba(0, 0, 0, .62);
}
/* En móvil ocupa el ancho útil y se ancla abajo, como una hoja. */
@media (max-width: 560px) {
  #panel-notificaciones {
    left: 10px !important; right: 10px;
    width: auto; max-height: 76vh;
  }
}
html[data-tema="light"] #panel-notificaciones {
  background: #ffffff;
  box-shadow: 0 24px 70px rgba(11, 11, 20, .22);
}
.notif-cab {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  position: sticky; top: -10px; z-index: 2;
  margin: -4px -4px 10px; padding: 8px 4px;
  background: inherit;
  border-bottom: 1px solid var(--borde);
}
.notif-cab .btn-xs.btn-ico { width: 27px; height: 27px; padding: 0; }

.notif-item .notif-x {
  flex: none; align-self: flex-start;
  display: grid; place-items: center;
  width: 22px; height: 22px; padding: 0;
  color: var(--texto-3); background: transparent;
  border: 0; border-radius: 6px; cursor: pointer;
  opacity: 0; transition: all var(--transicion);
}
.notif-item:hover .notif-x,
.notif-item .notif-x:focus-visible { opacity: 1; }
.notif-item .notif-x:hover { color: #fff; background: var(--peligro); }
.notif-item.saliendo {
  opacity: 0; transform: translateX(28px);
  transition: opacity 170ms ease, transform 170ms ease;
}
/* En pantallas táctiles no hay hover: la X se ve siempre. */
@media (hover: none) { .notif-item .notif-x { opacity: .8; } }

/* ── 29. MÓDULO DE CORREO ───────────────────────────────────────────
   Bandeja de tres paneles al estilo de un cliente de correo clásico:
   carpetas | lista | mensaje. Los dos divisores se arrastran y el reparto
   queda guardado en el navegador de cada usuario. */

.correo-shell {
  --col-carpetas: 226px;
  --col-lista: 380px;
  display: grid;
  grid-template-columns: var(--col-carpetas) 10px var(--col-lista) 10px minmax(0, 1fr);
  align-items: stretch;
  min-height: 60vh;
}
.correo-shell > .cpanel { min-width: 0; }
.correo-shell .col-carpetas { grid-column: 1; grid-row: 1; }
.correo-shell .div-carpetas { grid-column: 2; grid-row: 1; }
.correo-shell .col-lista    { grid-column: 3; grid-row: 1; }
.correo-shell .div-lista    { grid-column: 4; grid-row: 1; }
.correo-shell .col-mensaje  { grid-column: 5; grid-row: 1; }

/* Panel de lectura debajo de la lista. */
.correo-shell[data-vista="abajo"] {
  grid-template-columns: var(--col-carpetas) 10px minmax(0, 1fr);
  grid-template-rows: minmax(0, auto) 10px minmax(0, 1fr);
}
.correo-shell[data-vista="abajo"] .col-carpetas { grid-column: 1; grid-row: 1 / 4; }
.correo-shell[data-vista="abajo"] .div-carpetas { grid-column: 2; grid-row: 1 / 4; }
.correo-shell[data-vista="abajo"] .col-lista    { grid-column: 3; grid-row: 1; }
.correo-shell[data-vista="abajo"] .div-lista    { grid-column: 3; grid-row: 2; cursor: row-resize; }
.correo-shell[data-vista="abajo"] .col-mensaje  { grid-column: 3; grid-row: 3; }

/* Sin panel: la lista ocupa todo y el mensaje se abre en ventana. */
.correo-shell[data-vista="sin"] { grid-template-columns: var(--col-carpetas) 10px minmax(0, 1fr); }
.correo-shell[data-vista="sin"] .div-lista,
.correo-shell[data-vista="sin"] .col-mensaje { display: none; }

/* Carpetas plegadas a iconos. */
.correo-shell[data-carpetas="plegado"] { --col-carpetas: 64px; }
.correo-shell[data-carpetas="plegado"] .carpeta-texto,
.correo-shell[data-carpetas="plegado"] .buzon-item .crece { display: none; }
.correo-shell[data-carpetas="plegado"] .carpeta-item,
.correo-shell[data-carpetas="plegado"] .buzon-item { justify-content: center; padding: 9px 4px; }
.correo-shell[data-carpetas="plegado"] .carpeta-item .nav-contador { display: none; }

@media (max-width: 1150px) {
  .correo-shell,
  .correo-shell[data-vista="abajo"],
  .correo-shell[data-vista="sin"] {
    grid-template-columns: 1fr;
    grid-template-rows: auto;
    gap: 12px 0;
  }
  .correo-shell .divisor { display: none !important; }
  .correo-shell .cpanel,
  .correo-shell[data-vista="abajo"] .cpanel,
  .correo-shell[data-vista="sin"] .cpanel { grid-column: 1 !important; grid-row: auto !important; }
  .correo-shell[data-vista="sin"] .col-mensaje { display: block; }
  .correo-shell[data-carpetas="plegado"] { --col-carpetas: auto; }
  .correo-shell[data-carpetas="plegado"] .carpeta-texto,
  .correo-shell[data-carpetas="plegado"] .buzon-item .crece { display: block; }
}

/* ── Divisores arrastrables ──────────────────────────────────────── */
.divisor {
  position: relative;
  cursor: col-resize;
  background: transparent;
  border: 0; padding: 0;
  touch-action: none;
  align-self: stretch;
}
.divisor::before {
  content: '';
  position: absolute; top: 10px; bottom: 10px; left: 50%;
  width: 2px; margin-left: -1px;
  border-radius: 999px;
  background: var(--borde);
  transition: background var(--transicion), box-shadow var(--transicion), width var(--transicion);
}
.correo-shell[data-vista="abajo"] .div-lista::before {
  top: 50%; bottom: auto; left: 10px; right: 10px;
  width: auto; height: 2px; margin: -1px 0 0;
}
.divisor:hover::before, .divisor.arrastrando::before, .divisor:focus-visible::before {
  background: var(--ache-magenta);
  width: 3px; margin-left: -1.5px;
  box-shadow: 0 0 14px rgba(230, 0, 126, .6);
}
.correo-shell[data-vista="abajo"] .div-lista:hover::before,
.correo-shell[data-vista="abajo"] .div-lista.arrastrando::before {
  width: auto; height: 3px; margin: -1.5px 0 0;
}
.divisor:focus-visible { outline: none; }
body.redimensionando, body.redimensionando * { cursor: col-resize !important; user-select: none !important; }
body.redimensionando-v, body.redimensionando-v * { cursor: row-resize !important; user-select: none !important; }

/* ── Barra de herramientas ───────────────────────────────────────── */
.correo-tools {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 10px 14px; margin-bottom: 14px;
  border-radius: var(--r-lg);
  background: var(--superficie); border: 1px solid var(--borde);
  /* Crea su propio contexto de apilado para que los menús queden por
     encima de los paneles de la bandeja, que van después en el documento. */
  position: relative; z-index: 60;
}
.correo-tools .sep-v {
  width: 1px; height: 22px; background: var(--borde); flex: none; margin: 0 2px;
}
.correo-tools .buscador-correo {
  flex: 1 1 280px; min-width: 220px; position: relative;
}
.correo-tools .buscador-correo input { width: 100%; padding-left: 34px; padding-right: 30px; }
.correo-tools .buscador-correo .ico-lupa {
  position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  color: var(--texto-3); pointer-events: none;
}
.correo-tools .buscador-correo #btn-buscar { flex: none; }

/* Menú desplegable de la barra (Vista, Orden, Filtros). */
.menu-correo { position: relative; }
.menu-correo > .pop {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 120;
  min-width: 268px; padding: 12px;
  border-radius: var(--r-md);
  /* Opaco de verdad: un menú translúcido sobre la lista es ilegible. */
  background: #0d0d12 !important;
  border: 1px solid var(--borde-fuerte);
  box-shadow: var(--sombra-lg);
  backdrop-filter: none;
}
html[data-tema="light"] .menu-correo > .pop { background: #ffffff !important; }
.menu-correo .titulo-menu {
  font-size: .64rem; font-weight: 800; letter-spacing: .06em;
  text-transform: uppercase; color: var(--texto-3);
  margin: 10px 0 6px;
}
.menu-correo .titulo-menu:first-child { margin-top: 0; }
.menu-correo .fila-menu { display: flex; gap: 6px; flex-wrap: wrap; }

/* ── Carpetas y buzones ──────────────────────────────────────────── */
.carpeta-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 9px 12px; margin-bottom: 3px;
  border-radius: var(--r-md);
  background: transparent; border: 1px solid transparent;
  color: var(--texto-2); font: inherit; font-size: .85rem; font-weight: 600;
  cursor: pointer; text-align: left;
  transition: background var(--transicion), color var(--transicion);
}
.carpeta-item:hover { background: var(--superficie-2); color: var(--texto); }
.carpeta-item.activo {
  color: #fff; border-color: transparent;
  background-color: var(--ache-magenta);
  background-image: var(--grad-marca);
  background-size: 220% 100%; background-position: 0% 50%;
  background-origin: border-box; background-repeat: no-repeat;
  box-shadow: 0 6px 18px rgba(230, 0, 126, .25);
}
.carpeta-item.activo .nav-contador { background: rgba(255, 255, 255, .22); color: #fff; }
.carpeta-item .nav-contador { margin-left: auto; }

.buzon-item {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 8px 11px; margin-bottom: 3px; border-radius: var(--r-md);
  background: transparent; border: 1px solid transparent;
  color: var(--texto-2); font: inherit; font-size: .8rem;
  cursor: pointer; text-align: left;
}
.buzon-item:hover { background: var(--superficie-2); color: var(--texto); }
.buzon-item.activo { background: var(--grad-suave); border-color: var(--ache-magenta); color: var(--texto); }

/* ── Lista de mensajes ───────────────────────────────────────────── */
.msg-item {
  display: grid;
  grid-template-columns: auto auto 1fr auto;
  gap: 2px 9px;
  width: 100%; text-align: left; font: inherit;
  padding: 10px 12px; cursor: pointer;
  background: transparent; border: 1px solid transparent;
  border-bottom: 1px solid var(--borde);
  border-radius: var(--r-sm);
  color: var(--texto-2);
  transition: background var(--transicion);
}
.msg-item:hover { background: var(--superficie-2); }
.msg-item.sel {
  background: var(--grad-suave);
  border-color: var(--ache-magenta);
}
/* La casilla y la estrella comparten sitio en la rejilla, pero NO estilo:
   antes compartían la regla y el `background:none; border:0` pensado para
   la estrella borraba justo el fondo y el borde que hacen visible la
   casilla. Resultado: se podía marcar un correo sin verla. */
.msg-item .msg-check, .msg-item .msg-estrella {
  grid-row: 1 / 3; align-self: start; cursor: pointer;
}
.msg-item .msg-estrella {
  margin-top: 2px; padding: 2px; display: flex;
  background: none; border: 0; color: var(--texto-3);
}
.msg-item .msg-check { margin-top: 3px; }
.msg-item .msg-estrella:hover { color: var(--alerta); }
.msg-item .msg-estrella.on { color: var(--alerta); }
.msg-cabeza { grid-column: 3; display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.msg-de { font-size: .84rem; font-weight: 600; color: var(--texto-2); }
.msg-fecha { grid-column: 4; grid-row: 1; font-size: .7rem; color: var(--texto-3); white-space: nowrap; }
.msg-asunto { grid-column: 3 / 5; font-size: .85rem; font-weight: 600; }
.msg-extracto { grid-column: 3 / 5; font-size: .74rem; color: var(--texto-3); }
.msg-pie { grid-column: 3 / 5; display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin-top: 3px; }

.msg-item.nuevo { background: color-mix(in srgb, var(--ache-magenta) 6%, transparent); }
.msg-item.nuevo .msg-de,
.msg-item.nuevo .msg-asunto { color: var(--texto); font-weight: 800; }
.msg-item.nuevo::after {
  content: ''; position: absolute; left: 0; top: 12px;
  width: 3px; height: calc(100% - 24px); border-radius: 999px;
  background: var(--ache-magenta);
}
.msg-item { position: relative; }

/* Densidad compacta: caben muchos más mensajes en pantalla. */
.correo-shell[data-densidad="compacta"] .msg-item { padding: 6px 11px; gap: 0 8px; }
.correo-shell[data-densidad="compacta"] .msg-extracto { display: none; }
.correo-shell[data-densidad="compacta"] .msg-pie { margin-top: 1px; }
.correo-shell[data-densidad="compacta"] .carpeta-item { padding: 6px 11px; }

/* ── Cuerpo del mensaje ──────────────────────────────────────────────
   El cuerpo se pinta SIEMPRE sobre un lienzo claro, en los dos temas.
   No es un descuido del modo oscuro: el HTML de un correo se escribe
   dando por hecho que se leerá sobre blanco. Outlook, por ejemplo, manda
   el texto como `color:#000000` sin declarar fondo. Sobre el fondo oscuro
   del CRM eso era negro sobre negro. Gmail, Outlook web y Apple Mail
   hacen exactamente esto mismo y por el mismo motivo.
   El otro lado —correos que sí traen su propio fondo oscuro— lo resuelve
   `Mime::coloresLegibles()` en el servidor.
   Solo cambia el lienzo del mensaje: el resto de la pantalla sigue el
   tema que haya elegido el usuario.                                    */
.msg-cuerpo {
  font-size: var(--msg-tam, .9rem); line-height: 1.7;
  overflow: auto; word-break: break-word;
  background: #ffffff; color: #141418;
  border: 1px solid rgba(0, 0, 0, .10); border-radius: 14px;
  padding: 16px 18px;
  /* Que el navegador no invierta por su cuenta lo que va dentro. */
  color-scheme: light;
}
.msg-cuerpo img { max-width: 100%; height: auto; }
.msg-cuerpo a { color: #0b63c5; }
.msg-cuerpo table { max-width: 100%; border-collapse: collapse; }
.msg-cuerpo blockquote {
  margin: 10px 0; padding-left: 12px;
  border-left: 3px solid rgba(0, 0, 0, .18); color: #4a4a52;
}
.msg-cuerpo pre { white-space: pre-wrap; word-break: break-word; }
.msg-cuerpo hr { border: 0; border-top: 1px solid rgba(0, 0, 0, .12); }
/* Los avisos que pone el CRM dentro del cuerpo (mensaje vacío, resumen
   recuperado) también tienen que leerse sobre el lienzo claro. */
.msg-cuerpo .t-3, .msg-cuerpo .t-2 { color: #5b5b66; }

/* Imágenes remotas bloqueadas hasta que el usuario las pida. */
.aviso-imagenes {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 9px 13px; margin-bottom: 12px;
  border-radius: var(--r-md);
  background: rgba(245, 165, 36, .1);
  border: 1px solid rgba(245, 165, 36, .32);
  font-size: .78rem; color: var(--texto-2);
}

/* ── 30. DETALLE DE ACUERDO ─────────────────────────────────────────
   Antes solo se veía el valor: no había forma de saber de qué acuerdo
   se trataba. Ahora cada tarjeta despliega su ficha completa. */
.acuerdo-detalle {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 8px 18px; padding-top: 13px; border-top: 1px solid var(--borde);
}
.ac-fila { display: flex; gap: 8px; align-items: baseline; min-width: 0; }
.ac-etq {
  font-size: .64rem; font-weight: 800; letter-spacing: .05em;
  text-transform: uppercase; color: var(--texto-3); flex: none; min-width: 92px;
}
.ac-val { font-size: .84rem; color: var(--texto); min-width: 0; overflow-wrap: anywhere; }
.ac-val a { color: var(--ache-cyan); }

/* ── 31. REPARTO POR CANAL ───────────────────────────────────────────
   El donut ocupaba media tarjeta y dejaba un hueco muerto al lado. Ahora
   comparte fila con la lectura numérica del propio gráfico. */
.canal-reparto {
  display: grid;
  grid-template-columns: 190px minmax(0, 1fr) minmax(0, 1fr);
  gap: 24px; align-items: start;
}
.canal-anillo {
  position: relative; width: 190px; height: 190px;
  align-self: center; justify-self: center;
}
.canal-bloque { min-width: 0; }
.canal-bloque h3 { color: var(--texto-2); }
/* Chart.js escribe el tamaño en el atributo `style` del canvas; sin esto
   se quedaba en sus 300 px y asomaba fuera de la tarjeta en el móvil. */
.canal-anillo canvas { position: absolute; inset: 0; width: 100% !important; height: 100% !important; }
.canal-centro {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  pointer-events: none; text-align: center; line-height: 1.15;
}
.canal-centro strong {
  /* El degradado sobre el número quedaba sucio dentro del anillo: el
     texto recortado se mezclaba con los colores del propio donut y no se
     leía. Color plano, que es lo que una cifra necesita. */
  font-size: 1.6rem; font-weight: 800; font-variant-numeric: tabular-nums;
  color: var(--texto); line-height: 1;
}
.canal-centro span {
  font-size: .62rem; font-weight: 700; letter-spacing: .1em;
  text-transform: uppercase; color: var(--texto-3);
}

.canal-lista { list-style: none; margin: 0; padding: 0; }
/* La rejilla vive en `.canal-fila` y no en el `li` porque ahora cada
   renglón es un botón que abre a QUIÉNES corresponde esa barra. Si la
   rejilla se quedara en el `li`, su único hijo sería el botón y las
   cuatro columnas se colapsarían en una. */
.canal-lista li { padding: 0; }
.canal-lista li + li { border-top: 1px solid var(--borde); }
.canal-fila {
  display: grid; width: 100%;
  grid-template-columns: 18px minmax(0, 1fr) auto auto;
  grid-template-areas: 'ico nom pct n' '. barra barra barra';
  align-items: center; gap: 2px 8px;
  padding: 5px 6px; margin: 0;
  font: inherit; color: inherit; text-align: left;
  background: none; border: 0; border-radius: 8px; cursor: pointer;
  transition: background .14s ease;
}
.canal-fila:hover,
.canal-fila:focus-visible { background: var(--superficie-2); }
.canal-fila:hover .canal-nom { color: var(--texto); }

/* Embudo: el renglón abre la lista; la flecha lleva al Directorio. */
.embudo-fila { display: flex; align-items: center; gap: 4px; margin-bottom: 6px; }
.embudo-btn {
  display: flex; align-items: center; gap: 12px; flex: 1; min-width: 0;
  font: inherit; color: inherit; text-align: left;
  background: none; border: 0; border-radius: 8px; cursor: pointer;
  padding: 5px 6px; transition: background .14s ease;
}
.embudo-btn:hover,
.embudo-btn:focus-visible { background: var(--superficie-2); }
.embudo-ir {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; flex: none; border-radius: 7px;
  color: var(--texto-3); opacity: .55;
  transition: opacity .14s ease, color .14s ease;
}
.embudo-fila:hover .embudo-ir { opacity: 1; color: var(--ache-magenta); }
.canal-ico   { grid-area: ico; display: inline-flex; }
.canal-nom   { grid-area: nom; font-size: .82rem; color: var(--texto-2); }
.canal-pct   { grid-area: pct; font-size: .74rem; color: var(--texto-3); font-variant-numeric: tabular-nums; }
.canal-n     { grid-area: n; font-size: .84rem; min-width: 30px; text-align: right; font-variant-numeric: tabular-nums; }
.canal-barra { grid-area: barra; height: 4px; margin-top: 3px; }

@media (max-width: 1100px) {
  .canal-reparto { grid-template-columns: 170px minmax(0, 1fr); }
  .canal-reparto .canal-bloque:last-child { grid-column: 1 / -1; }
}
@media (max-width: 620px) {
  .canal-reparto { grid-template-columns: 1fr; }
  .canal-reparto .canal-bloque:last-child { grid-column: auto; }
  .canal-lista { width: 100%; }
}

/* Tarjeta de KPI consultable: al pulsarla se abre el detalle. */
.kpi-abrible {
  display: block; width: 100%; text-align: left;
  font: inherit; color: inherit; cursor: pointer;
}
.kpi-abrible:hover { border-color: var(--ache-magenta); }
.kpi-abrible:focus-visible { outline: 2px solid var(--ache-magenta); outline-offset: 2px; }
.kpi-lupa {
  display: inline-flex; vertical-align: -1px; margin-left: 6px;
  color: var(--texto-3); opacity: 0; transition: opacity var(--transicion);
}
.kpi-abrible:hover .kpi-lupa { opacity: 1; }
@media (hover: none) { .kpi-lupa { opacity: .6; } }

/* ── 32. VENTANA FLOTANTE DE REDACCIÓN ───────────────────────────────
   Antes era un modal: tapaba la pantalla y al cerrarlo se perdía lo
   escrito. Ahora vive abajo a la derecha, se minimiza, se agranda y se
   arrastra, y el texto se guarda solo. */
#correo-flotantes {
  position: fixed; right: 18px; bottom: 0; z-index: 6000;
  display: flex; flex-direction: row-reverse; align-items: flex-end; gap: 14px;
  pointer-events: none;
  max-width: calc(100vw - 36px);
}
#correo-flotantes > * { pointer-events: auto; }

.cwin {
  display: flex; flex-direction: column;
  width: min(510px, calc(100vw - 36px));
  max-height: min(600px, calc(100vh - 90px));
  border-radius: var(--r-md) var(--r-md) 0 0;
  background: #0f0f16;
  border: 1px solid var(--borde-fuerte); border-bottom: 0;
  box-shadow: 0 -8px 44px rgba(0, 0, 0, .55);
  opacity: 0; transform: translateY(24px);
  transition: opacity 180ms ease, transform 180ms cubic-bezier(.22, 1, .36, 1),
              width 180ms ease, max-height 180ms ease;
}
html[data-tema="light"] .cwin {
  background: #ffffff;
  box-shadow: 0 -8px 44px rgba(11, 11, 20, .18);
}
.cwin.visible { opacity: 1; transform: none; }
.cwin.arrastrando { transition: none; user-select: none; }

/* Arrastrada: se desancla del borde y va por coordenadas. */
.cwin.libre {
  position: fixed; right: auto; bottom: auto; margin: 0;
  border-radius: var(--r-md); border-bottom: 1px solid var(--borde-fuerte);
}
/* Minimizada: solo la barra de título, como en Gmail. */
.cwin.min { max-height: 42px; width: min(300px, 60vw); }
.cwin.min .cwin-cuerpo { display: none; }
/* Agrandada */
.cwin.max {
  width: min(880px, calc(100vw - 36px));
  max-height: calc(100vh - 60px);
}

.cwin-cab {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 8px 9px 14px; flex: none;
  color: #fff; cursor: grab;
  background-color: var(--ache-magenta);
  background-image: var(--grad-marca);
  background-size: 220% 100%; background-origin: border-box; background-repeat: no-repeat;
  border-radius: inherit; border-bottom-left-radius: 0; border-bottom-right-radius: 0;
}
.cwin.arrastrando .cwin-cab { cursor: grabbing; }
.cwin-titulo { flex: 1; min-width: 0; font-size: .82rem; font-weight: 700; }
.cwin-guardado {
  font-size: .66rem; opacity: 0; white-space: nowrap;
  transition: opacity var(--transicion);
}
.cwin-guardado.visible { opacity: .85; }
.cwin-botones { display: flex; gap: 2px; flex: none; }
.cwin-btn {
  display: grid; place-items: center;
  width: 26px; height: 26px; padding: 0;
  color: inherit; background: transparent;
  border: 0; border-radius: 7px; cursor: pointer;
  transition: background var(--transicion);
}
.cwin-btn:hover { background: rgba(255, 255, 255, .22); }
.cwin-pie .cwin-btn { color: var(--texto-3); }
.cwin-pie .cwin-btn:hover { color: var(--texto); background: var(--superficie-2); }

.cwin-cuerpo {
  display: flex; flex-direction: column; min-height: 0;
  padding: 10px 14px 12px;
}
.cwin-fila {
  display: flex; align-items: center; gap: 8px; flex: none;
  padding: 4px 0; border-bottom: 1px solid var(--borde);
}
.cwin-fila > span:first-child {
  flex: none; width: 46px;
  font-size: .72rem; font-weight: 700; color: var(--texto-3);
}
.cwin-fila input, .cwin-fila select {
  flex: 1; min-width: 0;
  padding: 5px 2px; font-size: .85rem;
  background: transparent; border: 0; border-radius: 0;
}
.cwin-fila input:focus, .cwin-fila select:focus { outline: none; box-shadow: none; }
.cwin-cc {
  flex: none; padding: 3px 8px;
  font: inherit; font-size: .68rem; font-weight: 700;
  color: var(--texto-3); background: transparent;
  border: 1px solid var(--borde); border-radius: var(--r-full); cursor: pointer;
}
.cwin-cc:hover { color: var(--ache-magenta); border-color: var(--ache-magenta); }

.cwin-plantillas {
  display: flex; gap: 5px; flex-wrap: wrap; flex: none;
  padding: 9px 0 7px;
}
.cwin-plantillas .chip { font-size: .68rem; padding: 3px 9px; }

.cwin-texto {
  flex: 1; min-height: 150px; resize: none;
  padding: 10px 0; margin: 0;
  font-size: .88rem; line-height: 1.6;
  background: transparent; border: 0; border-radius: 0;
}
.cwin-texto:focus { outline: none; box-shadow: none; }

.cwin-adjuntos {
  flex: none; max-height: 118px; overflow-y: auto;
  padding: 9px 0; border-top: 1px solid var(--borde);
}
/* Con qué firma sale el correo. Va justo encima del pie —lo último que
   se lee antes del botón de enviar— porque es ahí donde sirve de algo:
   verla después de enviar no arregla nada. */
.cwin-firma {
  display: flex; align-items: center; gap: 8px; flex: none;
  padding: 8px 0; border-top: 1px solid var(--borde);
}
.cwin-firma-etq {
  display: inline-flex; align-items: center; gap: 5px; flex: none;
  font-size: .72rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--texto-3);
}
.cwin-firma select {
  flex: 1; min-width: 0; width: auto;
  padding: 6px 28px 6px 10px; font-size: .8rem;
}
/* La previa se ve tal cual va a salir, sobre blanco: la firma trae sus
   propios colores, pensados para el correo del destinatario y no para
   el CRM en modo oscuro. Sobre el fondo negro se leería negro sobre
   negro y la previa mentiría justo en lo que se quiere comprobar. */
.cwin-firma-previa {
  flex: none; max-height: 190px; overflow: auto;
  padding: 12px; margin-top: 2px;
  border: 1px dashed var(--borde); border-radius: var(--r-sm);
  background: #ffffff; color: #333333;
  font-size: .8rem;
}
.cwin-firma-previa img { max-width: 100%; height: auto; }
.cwin-firma-previa table { max-width: 100%; }
.cwin-firma-previa a { color: #0b57d0; }

.cwin-pie {
  display: flex; align-items: center; gap: 8px; flex: none;
  padding-top: 10px; border-top: 1px solid var(--borde);
}
.cwin-sinbuzon { color: var(--alerta); line-height: 1.4; }
.cwin-sinbuzon a { color: var(--ache-cyan); }

@media (max-width: 700px) {
  #correo-flotantes { right: 0; left: 0; justify-content: center; }
  .cwin, .cwin.max { width: 100vw; max-height: calc(100vh - 56px); border-radius: 0; }
  .cwin.libre { position: fixed; left: 0 !important; top: auto !important; bottom: 0; }
}

/* Asunto del mensaje abierto: fila propia, a todo el ancho.
   Los asuntos automáticos de facturación son cadenas larguísimas sin
   espacios; si comparten fila con la botonera, se estrangulan. */
.msg-titulo {
  font-size: 1.15rem; line-height: 1.35; font-weight: 800;
  margin: 0 0 14px; padding-right: 4px;
  overflow-wrap: anywhere; word-break: break-word;
  /* Como mucho tres líneas: más que eso empuja el mensaje fuera de la
     pantalla. El asunto completo queda en el `title`. */
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ── 32.1 BLOQUE PLEGABLE «AVANZADO» ─────────────────────────────────
   Conectar un buzón debería ser correo + contraseña. Lo técnico existe,
   pero doblado: quien no sabe qué es IMAP no tiene por qué verlo. */
.bloque-avanzado {
  margin-top: 14px; padding: 0 14px;
  border: 1px solid var(--borde); border-radius: var(--r-md);
  background: var(--superficie-2);
}
.bloque-avanzado > summary {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 12px 0; cursor: pointer; list-style: none;
  font-size: .85rem; font-weight: 700; color: var(--texto-2);
}
.bloque-avanzado > summary::-webkit-details-marker { display: none; }
.bloque-avanzado > summary::after {
  content: '▾'; margin-left: auto; color: var(--texto-3);
  transition: transform var(--transicion);
}
.bloque-avanzado[open] > summary::after { transform: rotate(180deg); }
.bloque-avanzado > summary:hover { color: var(--texto); }
.bloque-avanzado[open] { padding-bottom: 14px; }
.bloque-avanzado h3 { color: var(--texto-3); }

/* ── 32.15 FILTROS PLEGADOS ──────────────────────────────────────────
   Seis desplegables y cinco casillas ocupaban más alto que la propia
   lista de empresas: había que hacer scroll para llegar a lo que uno
   viene a buscar. Plegados, la lista empieza casi arriba del todo y el
   contador del resumen dice cuántos filtros hay puestos sin abrirlos. */
.filtros-caja {
  border: 1px solid var(--borde); border-radius: var(--r-md);
  background: var(--superficie-2);
}
.filtros-caja > summary {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 12px; cursor: pointer; list-style: none;
  font-size: .8rem; font-weight: 700; color: var(--texto-2);
  transition: color var(--transicion);
}
.filtros-caja > summary::-webkit-details-marker { display: none; }
.filtros-caja > summary::after {
  content: '▾'; margin-left: auto; color: var(--texto-3);
  transition: transform var(--transicion);
}
.filtros-caja[open] > summary::after { transform: rotate(180deg); }
.filtros-caja > summary:hover { color: var(--texto); }
.filtros-num {
  min-width: 19px; padding: 1px 6px;
  font-size: .68rem; font-weight: 800; text-align: center;
  color: #fff; background: var(--ache-magenta); border-radius: var(--r-full);
}
.filtros-cuerpo { padding: 0 12px 12px; }
.filtros-rejilla {
  display: grid; gap: 6px;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
}
.filtros-rejilla select { padding: 8px 30px 8px 10px; font-size: .8rem; }
/* Casillas de filtro compactas: caben cinco en dos filas. */
.chip-xs {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px; font-size: .74rem;
}
.chip-xs input[type="checkbox"] { width: 15px; height: 15px; flex: 0 0 auto; }

/* ── 32.2 AGENDAR COMPROMISO ─────────────────────────────────────────
   La rejilla se parte sola cuando la columna es estrecha. Antes tenía
   `1fr 1fr` escrito en línea: en el iPad las dos columnas seguían ahí,
   apretadas, y el campo de fecha se salía por la derecha.             */
.rejilla-agenda {
  display: grid; gap: 0 14px;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}

/* Dos columnas que se vuelven una cuando la caja se estrecha. Se mide el
   sitio disponible, no el ancho de la ventana: el fallo del iPad estaba
   en un panel angosto dentro de una pantalla ancha, así que una consulta
   de medios no lo habría cazado. */
.rejilla-2 {
  display: grid; gap: 0 14px;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
/* Campo que ocupa toda la fila, tenga la rejilla las columnas que tenga.
   `1 / -1` y no `span 2`: con `auto-fit`, pedir dos columnas obliga a
   crear la segunda aunque no quepa, y eso era scroll lateral seguro. */
.rejilla-2 > .fila-completa,
.rejilla-agenda > .fila-completa { grid-column: 1 / -1; }

/* ── Red de seguridad SOLO para móvil ────────────────────────────────
   Las rejillas del CRM piden columnas de 250–340 px. En un teléfono de
   360–390 px eso no cabe y la página se movía de lado. Por debajo de
   700 px una sola columna es lo correcto en cualquier caso, así que se
   fuerza aquí y no tocando las rejillas: en escritorio nada cambia, que
   es donde estaba bien y no había que meter mano.                     */
@media (max-width: 700px) {
  /* `minmax(0, 1fr)` y no `1fr` a secas: `1fr` equivale a
     `minmax(auto, 1fr)`, y ese `auto` deja que la columna crezca hasta el
     contenido más ancho que tenga dentro. Una tarjeta con un correo
     largo estiraba la columna a 361 px dentro de una caja de 332. */
  .grid-2, .grid-3, .grid-kpi, .grid-cards,
  .grid[style*="1fr 1fr"] { grid-template-columns: minmax(0, 1fr) !important; }
  /* Y que el texto largo se parta en vez de empujar. */
  .grid > * { min-width: 0; }
  .grid > [style*="span 2"],
  .grid > [style*="span 3"] { grid-column: 1 / -1 !important; }
  /* Chart.js fija el tamaño del lienzo en el atributo `style`; sin esto
     el anillo se queda en sus 300 px y asoma fuera de la tarjeta. */
  .canal-anillo canvas { width: 100% !important; height: 100% !important; }
}

/* El selector de rango del dashboard va en una sola fila en escritorio,
   que es como estaba y como debe verse. Solo se parte cuando de verdad
   no cabe: los cinco campos suman ~700 px y en un teléfono forzaban
   scroll lateral. Se hace desde aquí y no con `wrap` en el marcado para
   no cambiar nada de lo que ya se veía bien. */
@media (max-width: 780px) {
  .rango-form { flex-wrap: wrap; margin-left: 0 !important; width: 100%; }
  .rango-form input[type="date"],
  .rango-form select { width: 100% !important; }
}

/* LOS DESPLEGABLES TIENEN QUE LEERSE ENTEROS.
   «Todas las bases» salía como «Todas l» y «Todo el equipo» como «Todo»,
   con media pantalla vacía al lado. No era falta de sitio: un <select>
   con `width: auto` y `appearance: none` no se mide por su opción más
   larga —el navegador le da un ancho propio bastante más corto—, así que
   se quedaba en 88 px cuando su texto pedía 167. Un filtro que no dice
   por qué está filtrando no sirve de nada: `fit-content` le da
   exactamente lo que necesita su opción más larga, ni un píxel más. */
.rango-form select {
  min-width: -webkit-fit-content;
  min-width: fit-content;
}

/* Y como ahora el formulario es más ancho, hay que decir dónde se parte.
   Entre 780 y 900 px vive dentro de una tarjeta bastante más estrecha
   que la ventana —el menú lateral se lleva su parte— y no cabe de
   ninguna manera; ahí sí se le deja envolver.

   El corte va por ancho de VENTANA y no de forma incondicional, y esa
   diferencia es la que se pagó cara: permitirle envolver siempre le
   cambia el ancho mínimo al formulario, la cabecera se lo estruja y la
   fila se parte TAMBIÉN en un monitor. Envolver no es gratis; solo se
   activa donde de verdad no cabe. */
@media (max-width: 900px) {
  .rango-form { flex-wrap: wrap; }
}

/* La Estación de Telemercadeo pedía 300 px fijos para la cola más lo que
   necesitara la ficha: en un teléfono eso sumaba 650 px dentro de una
   pantalla de 390 y la página se movía de lado. Apilado no hay overflow,
   y la cola deja de ser pegajosa porque ya no tiene una columna al lado
   contra la que quedarse quieta. */
@media (max-width: 900px) {
  #estacion { grid-template-columns: 1fr !important; }
  #estacion > .card { position: static !important; }
}

/* Campo de texto con un desplegable de atajos pegado a la derecha. */
.campo-con-atajos { display: flex; gap: 8px; align-items: stretch; }
.campo-con-atajos > input { flex: 1 1 auto; min-width: 0; }

/* ── 32.25 MENÚ FLOTANTE (pieza reutilizable) ────────────────────────
   DOS REGLAS QUE NO SE NEGOCIAN EN UN MENÚ, y que se han incumplido ya
   tres veces en este proyecto con tres menús distintos:

   1) FONDO OPACO PROPIO. `--superficie` es blanco al 3,5 %: sirve para
      una tarjeta apoyada en el fondo de la página, no para algo que se
      superpone a otro contenido. Un menú lleva su propio color sólido.

   2) NADA DE LO DE DETRÁS SE PUEDE PULSAR. Lo garantiza el velo
      (`#velo-menu`), no el `z-index`: un elemento posicionado no escapa
      del contexto de apilamiento de su padre, así que subir el z-index
      no asegura ni que se vea encima ni que intercepte el ratón.

   El JS (`ACHE_UI.MenuFlotante`) muda la lista a <body> al abrirla, así
   que estas reglas se aplican ya fuera de cualquier contexto ajeno.   */
.menu-flotante { position: relative; flex: 0 0 auto; }
.menu-flotante > summary {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  height: 100%; padding: 0 12px;
  font-size: .8rem; font-weight: 700; white-space: nowrap;
  color: var(--texto-2); background: var(--superficie-2);
  border: 1px solid var(--borde); border-radius: var(--r-sm);
  cursor: pointer; list-style: none;
  transition: border-color var(--transicion), color var(--transicion);
}
.menu-flotante > summary::-webkit-details-marker { display: none; }
.menu-flotante > summary:hover,
.menu-flotante[open] > summary { color: var(--texto); border-color: var(--ache-magenta); }

/* El velo: invisible pero sólido para el ratón. */
#velo-menu {
  position: fixed; inset: 0; z-index: 7600;
  background: transparent;
  visibility: hidden;
}
#velo-menu.visible { visibility: visible; }

.menu-flotante-lista {
  width: max-content; max-width: min(340px, calc(100vw - 24px));
  padding: 6px; display: flex; flex-direction: column; gap: 2px;
  border-radius: var(--r-md);
}
/* Mientras está mudada a <body>: opaca, por encima del velo y anclada
   con coordenadas de pantalla que calcula el JS. */
.menu-flotante-lista.flotando {
  position: fixed; z-index: 7610;
  overflow-y: auto; overscroll-behavior: contain;
  background: #14141c;                       /* opaco, sin transparencia */
  border: 1px solid rgba(255, 255, 255, .16);
  box-shadow: 0 22px 54px rgba(0, 0, 0, .62);
  backdrop-filter: none;                     /* ni desenfoque: se ve lo de atrás */
}
html[data-tema="light"] .menu-flotante-lista.flotando {
  background: #ffffff;
  border-color: rgba(11, 11, 20, .14);
  box-shadow: 0 22px 54px rgba(11, 11, 20, .18);
}
.menu-flotante-lista button {
  padding: 9px 11px; text-align: left; font: inherit; font-size: .82rem;
  color: var(--texto); background: none; border: 0; border-radius: var(--r-sm);
  cursor: pointer; white-space: normal;
}
.menu-flotante-lista.flotando button:hover,
.menu-flotante-lista.flotando button:focus-visible {
  background: rgba(255, 255, 255, .09); outline: none;
}
html[data-tema="light"] .menu-flotante-lista.flotando button:hover,
html[data-tema="light"] .menu-flotante-lista.flotando button:focus-visible {
  background: rgba(11, 11, 20, .06);
}
.menu-flotante-lista button.activo { color: var(--ache-magenta); font-weight: 700; }
/* Cerrada y en su sitio, no ocupa nada. */
.menu-flotante:not([open]) .menu-flotante-lista:not(.flotando) { display: none; }

@media (max-width: 560px) {
  .campo-con-atajos { flex-wrap: wrap; }
  .menu-flotante { width: 100%; }
  .menu-flotante > summary { padding: 10px 12px; }
}

/* ── 33. ADJUNTOS ────────────────────────────────────────────────────*/
.adjuntos-caja {
  padding: 10px 12px; border-radius: var(--r-md);
  background: var(--superficie-2); border: 1px solid var(--borde);
}
.adjunto-chip {
  display: inline-flex; align-items: center; gap: 8px;
  max-width: 260px; padding: 7px 10px;
  font: inherit; text-align: left;
  color: var(--texto); background: var(--superficie);
  border: 1px solid var(--borde); border-radius: var(--r-sm);
  cursor: pointer; transition: all var(--transicion);
}
.adjunto-chip:hover { border-color: var(--ache-cyan); transform: translateY(-1px); }
.adjunto-chip.pequeno { max-width: 220px; padding: 4px 8px; cursor: default; }
.adjunto-chip.pequeno:hover { transform: none; border-color: var(--borde); }
.adjunto-ico { flex: none; color: var(--ache-cyan); display: inline-flex; }
.adjunto-nom { display: block; font-size: .78rem; font-weight: 600; }
.adjunto-peso { display: block; font-size: .66rem; color: var(--texto-3); white-space: nowrap; }
.adjunto-chip.pequeno .adjunto-peso { display: inline; }
.adj-x {
  flex: none; display: grid; place-items: center;
  width: 17px; height: 17px; padding: 0;
  color: var(--texto-3); background: transparent;
  border: 0; border-radius: 5px; cursor: pointer;
}
.adj-x:hover { color: #fff; background: var(--peligro); }

/* ── 34. BÚSQUEDA Y PAPELERA EN EL CORREO ────────────────────────────*/
.buscador-correo { display: flex; align-items: center; gap: 6px; }
.buscador-correo .bc-campo { position: relative; flex: 1; min-width: 0; display: block; }
.buscador-correo .buscar-x {
  position: absolute; right: 7px; top: 50%; transform: translateY(-50%);
  display: grid; place-items: center;
  width: 20px; height: 20px; padding: 0;
  color: var(--texto-3); background: transparent;
  border: 0; border-radius: 5px; cursor: pointer;
}
.buscador-correo .buscar-x:hover { color: var(--texto); background: var(--superficie-2); }

.aviso-busqueda {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: 9px; padding: 7px 10px;
  font-size: .76rem; border-radius: var(--r-sm);
  color: var(--texto-2);
  background: rgba(0, 174, 239, .1);
  border: 1px solid rgba(0, 174, 239, .3);
}
.aviso-busqueda svg { vertical-align: -2px; color: var(--ache-cyan); }
.aviso-busqueda strong { color: var(--texto); }

.barra-papelera {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: 9px; padding: 7px 10px;
  border-radius: var(--r-sm);
  background: rgba(239, 68, 68, .09);
  border: 1px solid rgba(239, 68, 68, .28);
}

/* ── 34. DETALLE DE UN INDICADOR DEL DASHBOARD ───────────────────────
   Pulsar «Gestiones totales» abre 200 filas. Sin nada con qué acotarlas
   hay que leerlas todas, así que la tabla lleva su propia barra de
   búsqueda y filtros. Vale para los cuatro indicadores porque todos
   abren este mismo detalle.                                          */
.detalle-barra {
  display: flex; flex-wrap: wrap; gap: 8px; align-items: center;
  padding: 10px 12px; margin-bottom: 12px;
  background: var(--superficie-2); border: 1px solid var(--borde);
  border-radius: var(--r-md);
}
.detalle-barra select { width: auto; min-width: 130px; padding: 8px 30px 8px 10px; font-size: .8rem; }
.detalle-barra input[type="search"] { padding: 8px 12px; font-size: .82rem; }
@media (max-width: 700px) {
  .detalle-barra > * { width: 100% !important; min-width: 0 !important; }
}

/* ── 35. VISTAS DINÁMICAS (detallada · compacta · lista) ─────────────
   Las mismas tarjetas, tres densidades. No hay tres maquetaciones
   distintas ni tres plantillas que mantener: la lista lleva una clase
   —`vista-compacta` o `vista-lista`— y las piezas de cada tarjeta van
   marcadas según lo esenciales que sean:

     data-v="detalle"  información voluminosa: se retira en compacta y
                       en lista (teléfonos, descripciones, notas…).
     data-v="extra"    contexto útil pero prescindible: se retira solo
                       en lista, que es una fila por registro.

   Así, si mañana una tarjeta gana un campo, basta con marcarlo y las
   tres vistas siguen cuadrando.                                      */

.selector-vista {
  display: inline-flex; gap: 2px; padding: 3px;
  background: var(--superficie); border: 1px solid var(--borde);
  border-radius: var(--r-full);
}
.selector-vista button {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px; border: 0; border-radius: var(--r-full);
  background: transparent; color: var(--texto-3);
  font-family: inherit; font-size: .72rem; font-weight: 700; cursor: pointer;
  transition: background var(--transicion), color var(--transicion);
}
.selector-vista button:hover { color: var(--texto); }
.selector-vista button.activo {
  background: var(--superficie-2); color: var(--texto);
  box-shadow: 0 1px 4px rgba(0, 0, 0, .25);
}
.selector-vista svg { flex: none; }
/* En móvil solo los iconos: el nombre de la vista no cabe y tampoco
   hace falta, los tres dibujos se distinguen de sobra. */
@media (max-width: 620px) {
  .selector-vista button span { display: none; }
  .selector-vista button { padding: 6px 9px; }
}

/* ── Lo que cada vista esconde ─────────────────────────────────────── */
.vista-compacta [data-v="detalle"],
.vista-lista    [data-v="detalle"],
.vista-lista    [data-v="extra"] { display: none !important; }

/* ── Vista compacta: la misma tarjeta, más apretada ────────────────── */
.vista-compacta .card-p { padding: 13px 15px; }
.vista-compacta h3 { font-size: .95rem; min-height: 0 !important; }
.vista-compacta.grid-cards {
  grid-template-columns: repeat(auto-fill, minmax(min(232px, 100%), 1fr));
}
/* `grid-2` no se toca: en una pantalla estrecha ya se queda en una sola
   columna, y forzar dos allí hace las tarjetas más ALTAS, no más bajas.
   Lo comprobé midiéndolo: a 820px la «compacta» ocupaba más que la
   detallada. En compacta lo que encoge es el contenido, no la rejilla. */
.vista-compacta .sep { margin: 9px 0 !important; }
/* El pie de la tarjeta —estado a la izquierda, botones a la derecha— no
   cabe en una línea cuando la tarjeta se estrecha. Al no caber, el texto
   se estrujaba hasta partirse palabra por palabra («4 / gestiones / · /
   hace / 1 / d») y se metía por debajo de los botones.
   En compacta se le da su propia fila: el estado y el resumen arriba, los
   botones alineados a la derecha debajo. */
.vista-compacta [data-v="acciones"] { flex-wrap: wrap; row-gap: 10px; }
/* 190px es el ancho por debajo del cual el resumen deja de leerse. Si los
   dos bloques no caben con eso, el texto se baja a su propia fila; si
   caben —una tarjeta ancha, como la de Compromisos— se quedan en la misma
   línea de siempre y la tarjeta no crece. */
.vista-compacta .v-meta { flex: 1 1 190px; min-width: 0; }
.vista-compacta [data-v="acciones"] > .flex:last-child { margin-left: auto; }
/* Y el resumen no se parte: si no cabe entero, se recorta con puntos
   suspensivos, que se lee mucho mejor que una palabra por renglón. */
.vista-compacta .v-meta > .t-xs {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

/* ── Vista lista: una fila por registro ────────────────────────────── */
.vista-lista { grid-template-columns: 1fr !important; gap: 6px !important; }
.vista-lista .card { border-radius: var(--r-md); }
.vista-lista .card-p, .vista-lista .card-p-sm { padding: 9px 13px; }
/* El giro 3D de las tarjetas no tiene sentido en una fila —y además
   descoloca el texto al pasar por encima—. El `!important` es a
   propósito: lo pone el JS como estilo en línea. */
.vista-lista .tilt { transform: none !important; }
.vista-lista .card-luz::before { opacity: 0 !important; }
.vista-lista .v-cuerpo {
  display: flex; align-items: center; flex-wrap: wrap; gap: 6px 12px;
}
.vista-lista .v-cuerpo > * { margin-top: 0 !important; margin-bottom: 0 !important; }
.vista-lista .v-cuerpo h3 {
  font-size: .9rem; min-height: 0 !important;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* El título es quien se estira. En unas tarjetas es el propio <h3> y en
   otras el enlace que lo envuelve, así que se marcan los dos. */
.vista-lista .v-cuerpo > h3,
.vista-lista .v-cuerpo > .v-titulo { flex: 1 1 200px; min-width: 0; }
/* En compacta el título tampoco reserva dos líneas de alto: la tarjeta se
   ajusta a lo que de verdad ocupa el nombre. */
.vista-compacta .v-cuerpo h3 { min-height: 0 !important; }
/* El bloque de acciones se va siempre al extremo derecho, donde la vista
   detallada ya lo tenía: la mano sabe dónde buscarlo. */
.vista-lista .v-cuerpo > [data-v="acciones"] { flex: 0 0 auto; margin-left: auto; gap: 8px; }
.vista-lista .sep { display: none; }
.vista-lista .lineas-2 { -webkit-line-clamp: 1; }

/* ── Telemercadeo: la cola es una columna estrecha, no una rejilla ─── */
#cola.vista-compacta .cola-item { padding: 8px 10px; margin-bottom: 5px !important; }
#cola.vista-lista .cola-item {
  padding: 6px 10px; margin-bottom: 3px !important;
  border-radius: var(--r-sm);
}
#cola.vista-lista .cola-item > .flex { margin-bottom: 0 !important; }

@media (max-width: 620px) {
  /* En un teléfono la vista lista ya es lo que hay; forzar filas de una
     sola línea dejaría el nombre de la empresa cortado a la mitad. */
  .vista-lista .v-cuerpo > h3,
  .vista-lista .v-cuerpo > .v-titulo { flex-basis: 100%; }
  .vista-lista .v-cuerpo h3 { white-space: normal; }
}

/* ── 36. ANUNCIOS DEL DÍA Y PANEL DE ALERTAS ─────────────────────────
   Dos piezas que sirven para lo mismo: que no haya que acordarse de ir
   a mirar. El anuncio es una directriz que alguien escribió; la alerta
   es un compromiso que el propio CRM sabe que se acerca.            */

.anuncio {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 13px 15px; margin-bottom: 12px;
  background: color-mix(in srgb, var(--col, var(--ache-cyan)) 11%, var(--fondo-alto));
  border: 1px solid color-mix(in srgb, var(--col, var(--ache-cyan)) 38%, transparent);
  border-left-width: 4px;
  border-radius: var(--r-md);
  overflow: hidden;
  transition: opacity var(--transicion), transform var(--transicion),
              height var(--transicion), margin var(--transicion), padding var(--transicion);
}
.anuncio-ico { color: var(--col, var(--ache-cyan)); flex: none; margin-top: 1px; }
.anuncio-texto { font-size: .92rem; line-height: 1.55; }
/* Al cerrarlo se encoge en vez de desaparecer de golpe: así se entiende
   que se fue, y lo de abajo no da un salto. */
.anuncio-saliendo {
  opacity: 0; transform: translateY(-6px);
  height: 0 !important; margin-bottom: 0; padding-block: 0; border-width: 0;
}

.alertas-caja { border-color: color-mix(in srgb, var(--ache-magenta) 22%, var(--borde)); }
.alerta-col { min-width: 0; }
.alerta-item {
  display: block; padding: 8px 10px; margin-bottom: 6px;
  border-radius: var(--r-sm);
  border: 1px solid var(--borde);
  border-left: 3px solid var(--col, var(--ache-cyan));
  background: var(--superficie);
  color: inherit; text-decoration: none;
  transition: background var(--transicion), transform var(--transicion);
}
.alerta-item:hover { background: var(--superficie-2); transform: translateX(2px); }


/* ── 37. EL TABLERO: UN DASHBOARD POR PERSONA ────────────────────────
   Tres columnas y cada bloque ocupa 1, 2 o 3. El ancho llega como una
   variable en el `style` del elemento porque lo elige cada usuario y se
   guarda por bloque: una clase por combinación serían 27 clases muertas
   en la hoja para que ganen tres.

   `minmax(0, 1fr)` y no `1fr`: `1fr` es `minmax(auto, 1fr)`, y ese
   `auto` deja que una tabla ancha o un texto largo estiren su columna
   por encima del hueco. Con `0` el contenido se somete a la rejilla y
   se hace scroll dentro del bloque, que es lo correcto. */
.tablero {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px;
  /* `stretch`, no `start`. Con `start` cada bloque medía lo suyo y el
     resto de su fila se quedaba en blanco: si al lado de una gráfica de
     400 px caía el embudo con once estados y 900, quedaban 500 px de
     página vacía. Estirando, ese hueco pasa a ser interior de la
     tarjeta de al lado —que ya tiene borde y fondo— en vez de un
     agujero en la página. */
  align-items: stretch;
}

/* El ancho EFECTIVO (`--we`) puede no ser el elegido (`--w`): cuando una
   fila se queda coja, el último bloque de esa fila se estira para
   taparla. Lo calcula el JS; `--w` queda como respaldo si no corre. */
.wg {
  grid-column: span var(--we, var(--w, 1));
  min-width: 0;
  position: relative;
  display: flex;
  flex-direction: column;

  /* Ningún bloque puede hacer una fila de 900 px él solo. Sin tope, el
     más alto marca el alto de TODA su fila y los demás se quedan con
     medio metro de vacío dentro. Lo que pase de aquí se recorre dentro
     del propio bloque. */
  max-height: min(620px, 80vh);
}
.wg-cuerpo {
  flex: 1 1 auto;
  min-height: 0;          /* sin esto un hijo largo no deja encoger al padre */
  display: flex;
}
/* El contenido del bloque —sea una tarjeta o una rejilla de tarjetas—
   ocupa todo lo que le den y se recorre por dentro si no cabe. */
.wg-cuerpo > * {
  flex: 1 1 auto;
  min-width: 0;
  max-height: 100%;
  overflow: hidden auto;
}

/* Un bloque que hoy no tiene nada que enseñar (sin alertas pendientes,
   sin equipo que auditar) no puede quedarse ocupando su hueco: sería
   justo el agujero que se está intentando quitar. Se esconde solo, y
   reaparece al personalizar para poder moverlo o apartarlo a conciencia. */
.tablero:not(.tablero-editando) .wg[data-vacio] { display: none; }
.wg[data-vacio] .wg-cuerpo::after {
  content: 'Ahora mismo este bloque no tiene nada que enseñar, así que no se dibuja.';
  display: block;
  padding: 14px;
  border: 1px dashed var(--borde);
  border-radius: var(--r-md);
  color: var(--texto-3);
  font-size: .78rem;
}
/* Debajo de 1100 px la rejilla de tres no cabe: dos columnas, y lo que
   pedía tres sigue ocupando todo. Debajo de 760 px, una sola. Esto NO
   se guarda: la disposición elegida se respeta tal cual en cuanto
   vuelve a haber sitio. Lo que cambia es cómo se dibuja, no lo que se
   quiso. */
@media (max-width: 1100px) {
  .tablero { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .wg { grid-column: span min(var(--we, var(--w, 1)), 2); }
}
@media (max-width: 760px) {
  .tablero { grid-template-columns: minmax(0, 1fr); }
  .wg { grid-column: span 1; }
  /* En una sola columna no hay filas que cuadrar y el tope de alto
     sobra: aquí se hace scroll de la página, que es lo natural en un
     teléfono, y no scroll dentro de cada bloque. */
  .wg { max-height: none; }
  .wg-cuerpo > * { max-height: none; overflow: visible; }
}

/* ── Modo edición ──────────────────────────────────────────────────
   Los mandos están siempre en el HTML y solo se destapan aquí: si se
   inyectaran al pulsar «Personalizar», la página daría un salto y el
   orden de tabulación cambiaría bajo los pies de quien navega con
   teclado. */
.tablero-editando .wg-mando { display: flex; }
.tablero-editando .wg {
  outline: 1px dashed color-mix(in srgb, var(--ache-cyan) 45%, transparent);
  outline-offset: 3px;
  border-radius: var(--r-md);
}
.tablero-editando .wg-cuerpo > * { pointer-events: none; }
.wg-mando {
  display: none;
  align-items: center;
  gap: 6px;
  padding: 6px 8px;
  margin-bottom: 8px;
  border: 1px solid var(--borde);
  border-radius: var(--r-sm);
  background: var(--superficie-2);
  flex-wrap: wrap;
}
.wg-asa {
  cursor: grab;
  color: var(--texto-3);
  display: inline-flex;
  /* Un asa de 14 px es imposible de agarrar con el dedo en un iPad.
     El icono se queda pequeño; la zona que responde, no. */
  padding: 4px;
  margin: -4px;
  touch-action: none;      /* sin esto, arrastrar en táctil hace scroll */
}
.wg-asa:active { cursor: grabbing; }

/* ── Los mandos, rotulados ─────────────────────────────────────────
   Un icono suelto o un número suelto solo se entienden cuando ya sabes
   lo que hacen. Cada grupo lleva su palabra delante —«Mover», «Ancho»—
   y se dibuja como un bloque con su borde, para que se lea como un
   mando y no como tres cosas sueltas puestas en fila. */
.wg-grupo, .wg-anchos {
  display: inline-flex; align-items: center; gap: 3px;
  padding: 2px 5px;
  border: 1px solid var(--borde);
  border-radius: var(--r-full);
  background: var(--fondo);
}
.wg-etq {
  font-size: .6rem; font-weight: 800; letter-spacing: .05em;
  text-transform: uppercase;
  color: var(--texto-3);
  padding: 0 3px;
  white-space: nowrap;
}

/* Las flechas de mover: un SVG de verdad y una zona pulsable de 26 px.
   Antes eran los caracteres «↑» y «↓», que se dibujan con la fuente del
   texto —finos, pequeños y distintos en cada sistema— y en el iPad del
   cliente casi no se veían. */
.wg-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px;
  padding: 0;
  border: 0; border-radius: var(--r-sm);
  background: transparent;
  color: var(--texto-2);
  cursor: pointer;
  transition: background var(--transicion), color var(--transicion);
}
.wg-btn:hover { background: var(--superficie-2); color: var(--texto); }
.wg-btn svg { display: block; }

/* Los botones de ancho MIDEN lo que hacen. El de un tercio es estrecho,
   el de todo el ancho es largo: la forma del botón ya cuenta lo que va
   a pasar antes de pulsarlo. */
.wg-ancho {
  height: 24px;
  border: 1px solid var(--borde);
  border-radius: 5px;
  background: transparent;
  color: var(--texto-2);
  font: inherit; font-size: .68rem; font-weight: 800;
  cursor: pointer;
  padding: 0;
  transition: background var(--transicion), color var(--transicion), border-color var(--transicion);
}
.wg-ancho-1 { width: 16px; }
.wg-ancho-2 { width: 26px; }
.wg-ancho-3 { width: 36px; }
.wg-ancho:hover { background: var(--superficie); color: var(--texto); }
.wg-ancho.activo {
  background: var(--ache-magenta);
  border-color: var(--ache-magenta);
  color: #fff;
}

/* «1 · estirado a 3». El bloque que cierra una fila se ensancha solo
   para no dejar un hueco al lado, y sin esto el resultado era
   desconcertante: el botón marcado decía 1 y el bloque ocupaba tres.
   La regla es buena —fue lo que se pidió— pero tenía que verse. */
.wg-estirado {
  font-size: .6rem; font-weight: 800; letter-spacing: .03em;
  color: var(--ache-cyan);
  padding: 0 4px;
  white-space: nowrap;
}
.wg-estirado[hidden] { display: none; }

/* El bloque que se está arrastrando y el hueco donde va a caer. */
.wg-arrastrando { opacity: .45; }
.wg-destino::before {
  content: '';
  position: absolute; inset: -4px;
  border: 2px solid var(--ache-cyan);
  border-radius: var(--r-md);
  pointer-events: none;
}

.tablero-guardados[hidden] { display: none; }


/* ── 38. EL ENCARGO DENTRO DE UN COMPROMISO ──────────────────────────
   Un compromiso con encargo tiene que distinguirse de un compromiso
   suelto de un vistazo: no es «acuérdate de llamar a Postobón», es
   trabajo asignado con una cantidad y un avance. La banda de color a la
   izquierda lo dice sin necesidad de leer nada. */
.encargo {
  border: 1px solid var(--borde);
  border-left: 3px solid var(--ache-cyan);
  border-radius: var(--r-sm);
  background: var(--superficie-2);
  padding: 9px 11px;
}
.encargo .barra { height: 6px; }

/* «QUÉ HAY QUE GESTIONAR». El resumen del encargo salía suelto y en
   letra pequeña, y quien lo recibía lo leía como una etiqueta más:
   decía que solo le llegaba el comentario, teniéndolo delante. Un
   rótulo en mayúsculas y del color del encargo lo convierte en lo que
   es —la instrucción— en vez de en adorno. */
.encargo-rotulo {
  display: flex; align-items: center; gap: 5px;
  font-size: .62rem; font-weight: 800; letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--ache-cyan);
}

/* El encargo en los sitios estrechos —la agenda del día y el panel de
   «Lo que tienes encima»—: una sola línea que no puede empujar la
   tarjeta de ancho, pero que se lee y se distingue del resto del texto
   gris de alrededor. */
.alerta-encargo {
  display: flex; align-items: center; gap: 4px;
  margin-top: 3px;
  min-width: 0;
  color: var(--ache-cyan);
  font-weight: 600;
}
.alerta-encargo svg { flex: none; }
.alerta-encargo .truncar { min-width: 0; }

/* ── EL EDITOR DE LA FIRMA ───────────────────────────────────────────
   La previa a la izquierda y los datos a la derecha, para ver el efecto
   sin apartar la vista de lo que se escribe. En una pantalla estrecha se
   apila con la previa arriba: si quedara debajo de ocho campos habría
   que bajar para ver lo que se acaba de escribir, y entonces deja de
   ser una previa. */
/* Las pestañas de las firmas guardadas. Envuelven en pantalla estrecha:
   con cinco firmas y un iPad en vertical, no caben en una línea, y una
   fila de pestañas con desbordamiento lateral esconde justo la que hace
   falta. */
.firma-pestanas {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin: 4px 0 14px;
}
.firma-pes {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 7px 14px; border-radius: var(--r-full);
  border: 1px solid var(--borde); background: var(--superficie);
  color: var(--texto-2); font: inherit; font-size: .82rem; font-weight: 600;
  cursor: pointer; transition: .18s ease;
}
.firma-pes:hover { color: var(--texto); border-color: var(--borde-fuerte); }
.firma-pes.activa {
  color: var(--texto); border-color: var(--ache-magenta);
  background: rgba(230, 0, 126, .10);
}
.firma-pes-punto {
  width: 6px; height: 6px; border-radius: 50%; flex: none;
  background: var(--ache-cyan);
}
.firma-pes-mas { border-style: dashed; color: var(--texto-3); }

.firma-editor {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
  align-items: start;
}
@media (max-width: 900px) {
  .firma-editor { grid-template-columns: minmax(0, 1fr); }
}

/* Fondo blanco y tipografía de correo, siempre, también en modo oscuro:
   la firma se va a leer sobre el blanco de Gmail o de Outlook. Enseñarla
   sobre el fondo oscuro del CRM llevaría a elegir colores que después no
   se leen donde importa. */
.firma-previa {
  background: #ffffff;
  color: #111111;
  border: 1px solid var(--borde);
  border-radius: var(--r-md);
  padding: 18px;
  min-height: 120px;
  overflow-x: auto;
  font-family: Arial, Helvetica, sans-serif;
  /* Se queda pegada arriba mientras se recorren los campos. Son ocho, y
     sin esto los últimos —el teléfono, la web— se rellenan con la previa
     ya fuera de la pantalla, que es justo cuando hace falta verla. */
  position: sticky;
  top: calc(var(--header-h) + 16px);
}
@media (max-width: 900px) {
  /* Apilado, «pegada arriba» sería taparle el campo a quien escribe.
     Ahí vuelve a ser una caja normal. */
  .firma-previa { position: static; }
}

/* Dos columnas para los datos: ocho campos en una sola fila vertical
   obligan a bajar y bajar por lo que es media docena de palabras. Los
   que llevan texto largo —nombre, organización, correo— se quedan a lo
   ancho para no partir lo que se está escribiendo. */
.firma-campos { display: grid; grid-template-columns: 1fr 1fr; gap: 0 12px; }
/* Nombre, cargo, organización y correo, a lo ancho: son los que llevan
   texto largo. Teléfono, WhatsApp, web y color van de dos en dos, que es
   lo que ahorra la mitad del recorrido vertical. */
.firma-campos .campo:nth-child(-n+4) { grid-column: 1 / -1; }
@media (max-width: 620px) {
  .firma-campos { grid-template-columns: minmax(0, 1fr); }
}
.firma-previa:empty::after {
  content: 'Escribe los datos de la derecha y la firma aparecerá aquí.';
  color: #999999;
  font-size: .82rem;
}
.firma-previa table { width: auto; }

.aviso-firma {
  display: flex; align-items: flex-start; gap: 9px;
  padding: 11px 13px;
  border: 1px solid color-mix(in srgb, var(--alerta) 35%, var(--borde));
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--alerta) 8%, transparent);
  font-size: .82rem;
  line-height: 1.5;
}
.aviso-firma svg { flex: none; color: var(--alerta); margin-top: 1px; }

/* ── EL PANEL DE FRASES Y ATAJOS ─────────────────────────────────────
   Se abre sobre la Estación, así que tiene que caber sin empujar: cada
   frase es una línea de altura de dedo, y el texto largo se corta en vez
   de estirar el panel a lo ancho. */
.opr-bloque {
  border: 1px solid var(--borde);
  border-radius: var(--r-md);
  background: var(--superficie-2);
  padding: 12px 13px;
  margin-bottom: 12px;
}
.opr-lista { display: flex; flex-direction: column; gap: 5px; }
.opr-fila {
  display: flex; align-items: center; gap: 8px;
  min-height: 38px;
  padding: 4px 8px;
  border: 1px solid var(--borde);
  border-radius: var(--r-sm);
  background: var(--fondo);
}
.opr-punto { width: 9px; height: 9px; border-radius: 50%; flex: none; }
.opr-fila .opr-texto { font-size: .84rem; min-width: 0; }
/* Al editar en la propia fila, el campo ocupa el sitio del texto y no
   cambia el alto: si la fila diera un salto se perdería de vista cuál
   se estaba tocando. */
.opr-fila input[type="text"] { padding: 5px 8px; font-size: .84rem; min-width: 0; }
.opr-retirada { opacity: .55; }

/* El formulario de una fila: se usa igual para añadir abajo y para
   editar en el sitio, así que se dibuja igual en los dos casos. Que se
   vea distinto según dónde aparece haría dudar de si hace lo mismo. */
.opr-form {
  border: 1px solid var(--borde-fuerte);
  border-radius: var(--r-sm);
  background: var(--fondo);
  padding: 10px;
}
.opr-form input[type="text"] { padding: 7px 10px; font-size: .86rem; }
.opr-marca {
  display: flex; align-items: flex-start; gap: 8px;
  font-size: .8rem; line-height: 1.4;
  /* Altura de dedo: en el iPad una casilla de 17 px no se acierta. */
  min-height: 34px;
}
.opr-marca input { width: auto; flex: none; margin-top: 2px; }

/* Las pestañas del panel. Cinco listas seguidas obligan a recorrerlo
   entero para llegar a la última; en pestañas, cada una a un clic. */
.modal [role="tablist"] .chip svg { flex: none; }

/* La franja de la Estación cuando se entra desde un compromiso: hace
   falta que quede clarísimo que NO se está viendo la cola normal, sino
   un encargo. Sin esto es fácil creer que el CRM «perdió» contactos. */
.encargo-activo {
  border-color: color-mix(in srgb, var(--ache-cyan) 45%, var(--borde));
  background: linear-gradient(135deg,
              color-mix(in srgb, var(--ache-cyan) 10%, transparent),
              transparent 60%);
}

/* Las casillas del encargo. Un <input type=checkbox> nativo mide unos
   17 px: con el ratón se acierta, con el dedo en un iPad no. La etiqueta
   entera es la zona que responde —envuelve a la casilla—, así que se le
   da altura de dedo sin tocar cómo se dibuja la casilla, que es donde
   cada sistema tiene su propio aspecto y conviene no meterse. */
[data-encargo] label.pointer {
  min-height: 32px;
  padding-right: 4px;
}

/* El encargo en las vistas apretadas. En «compacta» y en «lista» lo que
   se busca es barrer muchas tarjetas de un vistazo, así que el encargo
   se reduce a su barra: el porcentaje es lo único que se mira al
   repasar, y el texto del criterio ya está en la vista detallada.
   Se encoge en vez de desaparecer porque un compromiso con encargo y
   uno sin él no pueden verse igual: son cosas distintas. */
.vista-compacta .encargo,
.vista-lista .encargo {
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  margin-top: 8px;
}
.vista-compacta .encargo > .flex,
.vista-lista .encargo > .flex,
.vista-compacta .encargo .t-xs.t-3,
.vista-lista .encargo .t-xs.t-3 {
  display: none;
}
.vista-compacta .encargo .barra,
.vista-lista .encargo .barra { margin-top: 0; height: 4px; }


/* ── 39. «AQUÍ ABAJO HAY MÁS» ────────────────────────────────────────
   Desde que los bloques del tablero tienen tope de alto, algunos se
   recorren por dentro. El problema es que no se notaba: el embudo
   enseñaba diez estados y parecía que esos eran todos, cuando había
   cuatro más debajo. Un corte limpio se lee como final.

   La señal es doble a propósito:
     · un DEGRADADO que difumina la última línea, porque un texto que
       se desvanece se lee como «sigue», mientras que uno cortado en
       seco se lee como «se acabó»;
     · y una flecha que sube y baja despacio, que es lo que hace que el
       ojo lo vea sin estar buscándolo.

   Se apaga sola al llegar abajo: una flecha que sigue ahí cuando ya no
   queda nada que ver enseña a no hacerle caso.

   Va sobre `.wg`, que NO se mueve, y no sobre la caja que se recorre:
   un pseudo-elemento dentro de un contenedor con scroll se va hacia
   arriba con el contenido y la señal desaparecería al primer empujón. */
.wg[data-hay-mas]::after {
  content: '⌄';
  position: absolute;
  left: 1px;
  right: 1px;
  bottom: 1px;
  height: 52px;
  display: grid;
  align-items: end;
  justify-items: center;
  padding-bottom: 4px;
  font-size: 1.15rem;
  line-height: 1;
  color: var(--texto-3);
  border-radius: 0 0 var(--r-lg) var(--r-lg);
  /* Hacia `--fondo` y no hacia `--superficie`: las tarjetas son
     translúcidas, así que un degradado hacia su propio color no taparía
     nada. El de la página sí. */
  background: linear-gradient(to top,
              var(--fondo) 10%,
              color-mix(in srgb, var(--fondo) 70%, transparent) 55%,
              transparent);
  pointer-events: none;   /* no puede robarle el clic a lo que tapa */
  animation: asomarse 2.6s ease-in-out infinite;
}

@keyframes asomarse {
  0%, 100% { transform: translateY(0); opacity: .85; }
  50%      { transform: translateY(4px); opacity: 1; }
}

/* Quien pidió menos movimiento —en Ajustes o en su sistema— conserva la
   señal, pero quieta. El degradado y la flecha siguen diciendo lo mismo;
   lo que sobra es el vaivén, no el aviso. */
html[data-animaciones="0"] .wg[data-hay-mas]::after { animation: none; }
@media (prefers-reduced-motion: reduce) {
  .wg[data-hay-mas]::after { animation: none; }
}

/* En modo edición estorbaría: ahí se está colocando el tablero, no
   leyéndolo, y el degradado tapa el borde del bloque que se arrastra. */
.tablero-editando .wg[data-hay-mas]::after { display: none; }

/* La fecha por la que se está filtrando, resaltada en la tarjeta del
   Directorio: sin ella no había forma de ver desde fuera que «fecha de
   alta» y «última gestión» son dos preguntas distintas. */
.fecha-filtrada {
  color: var(--ache-cyan);
  border-bottom: 1px dotted currentColor;
  cursor: help;
}

/* Una cifra que además se puede pulsar. Se marca con el subrayado
   punteado y no con color de enlace: en una fila de cuatro cifras
   pequeñas, cuatro azules gritan más que la propia cifra. */
.cifra-viva {
  color: inherit; text-decoration: none;
  border-bottom: 1px dotted var(--borde-fuerte);
  transition: color .14s ease, border-color .14s ease;
}
/* El color del hover NO se pone aquí a propósito: lo pone la regla
   general de los enlaces (magenta), que gana por especificidad —lleva
   cinco `:not()` y cada uno cuenta como una clase—. Repetirlo aquí con
   otro color habría sido escribir algo que nunca se aplica, que es peor
   que no escribir nada: se lee el CSS y se cree que hace algo. */
.cifra-viva:hover,
.cifra-viva:focus-visible { border-color: currentColor; }

/* =====================================================================
   LA BANDEJA DE WHATSAPP
   ─────────────────────────────────────────────────────────────────────
   Se copia de WhatsApp LA FORMA, no el color. La forma —dos paneles, la
   fila con su círculo a la izquierda, la burbuja con su pico, el fondo
   con dibujitos, el doble tic, la barra de escribir con el «+» y el
   micrófono a la derecha— es lo que la mano ya sabe: quien abra esto no
   tiene que aprender nada. El color es lo contrario: los verdes de
   WhatsApp dentro del CRM cantarían como un injerto.

   DOS COSAS QUE SE HICIERON MAL LA PRIMERA VEZ Y AQUÍ ESTÁN ARREGLADAS:

   1 · LAS BURBUJAS ERAN TRANSLÚCIDAS. Con un fondo de dibujos detrás,
       el dibujo se veía A TRAVÉS del texto y no se leía nada — sobre
       todo en modo oscuro. Ahora son OPACAS, con su color por tema. Una
       burbuja es papel, no cristal.

   2 · EL DIBUJO DEL FONDO IBA EN BLANCO PURO. Se escribió el trazo sin
       opacidad, así que en oscuro salía un enrejado blanco a toda
       potencia. El dibujo va en la capa de abajo y tiene que
       comportarse como tal: se ve si lo buscas y no si lees.

   Todo lo de aquí lleva el prefijo `wa-` y solo se usa en esa pantalla.
   ===================================================================== */
:root {
  /* ── Superficies de la bandeja ─────────────────────────────────────
     OPACAS a propósito: van encima del fondo con dibujos. Cualquier
     transparencia aquí deja pasar el garabato por debajo del texto. */
  --wa-lienzo:   #ece5dd;   /* el papel donde van las burbujas */
  --wa-suya:     #ffffff;   /* lo que escribe la otra persona */
  --wa-mia:      #d3eefb;   /* lo mío, en el cian de la fundación */
  --wa-panel:    #ffffff;   /* la lista y las cabeceras */
  --wa-panel-2:  #f5f6f8;
  --wa-borde:    rgba(11, 11, 20, .10);
  --wa-texto:    #14141c;
  --wa-texto-2:  #5b5b6b;
  --wa-doodle-color: #0b0b14;
  /* AQUÍ ESTABA EL FALLO DE «LOS FONDOS SALEN LISOS».
     Estaba en .05 y en la práctica es invisible: un gris al 5 % sobre
     un fondo claro no se distingue de nada. No estaba roto el dibujo,
     estaba apagado. Se sube hasta que se vea de verdad, y la prueba de
     navegador mide DOS cosas a la vez —que el dibujo se note y que el
     texto siga contrastando— porque subirlo sin mirar lo segundo es
     volver al problema del que se venía. */
  --wa-doodle-op: .11;
  --wa-cita:     rgba(11, 11, 20, .045);
  --wa-tic:      #00aeef;
}
/* El oscuro NO es el claro con los colores invertidos: el lienzo es casi
   negro para que la pantalla no queme de noche, y las burbujas suben lo
   justo para despegarse de él. */
html[data-tema="dark"], :root:not([data-tema="light"]) {
  --wa-lienzo:   #0b0b11;
  --wa-suya:     #1e2029;
  --wa-mia:      #0e3a4c;
  --wa-panel:    #121218;
  --wa-panel-2:  #17171f;
  --wa-borde:    rgba(255, 255, 255, .09);
  --wa-texto:    #ececf1;
  --wa-texto-2:  #a6a6b4;
  --wa-doodle-color: #ffffff;
  /* En oscuro un trazo claro rinde más, así que hace falta menos. */
  --wa-doodle-op: .085;
  --wa-cita:     rgba(255, 255, 255, .07);
  --wa-tic:      #4cc9f0;
}

/* ── EL MARCO ─────────────────────────────────────────────────────── */
.wa-marco {
  display: grid;
  grid-template-columns: 340px 1fr;
  height: min(78vh, 780px);
  overflow: hidden;
  background: var(--wa-panel);
  color: var(--wa-texto);
}

/* EL `min-height: 0` NO ES DECORACIÓN, ES EL SCROLL.
   Una caja de flex o de rejilla mide por defecto `min-height: auto`, o
   sea: «nunca me encojas por debajo de lo que llevo dentro». Con eso
   puesto, el `overflow-y: auto` de la lista de mensajes no sirve para
   nada —la caja crece con la conversación en vez de recortarla— y los
   mensajes se salen del marco, sin barra por ninguna parte. */
.wa-lista {
  border-right: 1px solid var(--wa-borde);
  display: flex; flex-direction: column; min-width: 0; min-height: 0;
  background: var(--wa-panel);
}
.wa-panel {
  display: flex; flex-direction: column;
  min-width: 0; min-height: 0; position: relative;
  background: var(--wa-lienzo);
}

/* En un teléfono no caben dos paneles, así que se enseña UNO: la lista,
   y al elegir una conversación, la conversación. Es lo que hace
   WhatsApp en el móvil. */
@media (max-width: 860px) {
  .wa-marco { grid-template-columns: 1fr; height: min(84vh, 780px); }
  .wa-marco[data-vista="charla"] .wa-lista { display: none; }
  .wa-marco[data-vista="lista"]  .wa-panel { display: none; }
  .wa-volver { display: inline-flex !important; }
}
.wa-volver { display: none; }

/* ── CABECERAS ────────────────────────────────────────────────────── */
.wa-cab {
  display: flex; align-items: center; gap: 10px;
  /* Más aire abajo: los botones y el buscador quedaban pegados a la
     línea que separa la cabecera de lo que hay debajo, y una fila de
     controles rozando un filo se lee como un error de maquetado. */
  padding: 11px 14px 12px; min-height: 60px;
  background: var(--wa-panel-2);
  border-bottom: 1px solid var(--wa-borde);
}

/* El buscador con su lupa dentro, como en la referencia. */
.wa-buscar {
  position: relative; flex: 1; min-width: 0;
}
.wa-buscar .ico {
  position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  color: var(--wa-texto-2); pointer-events: none;
}
.wa-buscar input {
  width: 100%; padding-left: 36px; border-radius: 999px;
  background: var(--wa-panel); border: 1px solid var(--wa-borde);
  color: var(--wa-texto);
}

/* ── LA LISTA DE CONVERSACIONES ───────────────────────────────────── */
/* LAS PESTAÑAS, TODAS DEL MISMO TAMAÑO. Antes «No leídos» salía el doble
   de alta —el contador era un bloque y la partía en dos renglones—, los
   botones usaban la letra del sistema en vez de la del CRM y se
   repartían en tres pisos. Ahora: una sola fila que se desliza de lado
   (como en WhatsApp), 32 px de alto para todas, la letra de la casa y el
   contador DENTRO de la pastilla. */
.wa-filtros {
  display: flex; gap: 6px; align-items: center;
  padding: 10px 14px; flex-wrap: nowrap;
  overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
  border-bottom: 1px solid var(--wa-borde);
}
.wa-filtros::-webkit-scrollbar { display: none; }
.wa-filtros.hay-mas-der { -webkit-mask-image: linear-gradient(to right, #000 82%, transparent);
                          mask-image: linear-gradient(to right, #000 82%, transparent); }
.wa-filtros.hay-mas-izq { -webkit-mask-image: linear-gradient(to left, #000 82%, transparent);
                          mask-image: linear-gradient(to left, #000 82%, transparent); }
.wa-filtros.hay-mas-izq.hay-mas-der {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 12%, #000 82%, transparent);
          mask-image: linear-gradient(to right, transparent, #000 12%, #000 82%, transparent);
}
.wa-chip {
  font: inherit; font-size: 12.5px; font-weight: 500; line-height: 1;
  display: inline-flex; align-items: center; gap: 6px; flex: none;
  height: 32px; padding: 0 13px; white-space: nowrap;
  border: 1px solid var(--wa-borde); background: var(--wa-panel);
  color: var(--wa-texto-2); border-radius: 999px; cursor: pointer;
  transition: background .14s ease, color .14s ease, border-color .14s ease;
}
.wa-chip:hover { color: var(--wa-texto); border-color: var(--wa-texto-2); }

/* EL BORDE TRANSPARENTE DEJABA VER EL DEGRADADO POR DEBAJO: el fondo se
   repetía bajo el borde y asomaba un filo de color. Con
   `background-origin: border-box` el degradado cubre también el borde
   sin repetirse, y el borde se queda —transparente— para que la
   pastilla encendida mida exactamente lo mismo que las apagadas. */
.wa-chip[aria-pressed="true"] {
  background: var(--grad-marca); background-origin: border-box;
  border-color: transparent; color: #fff; font-weight: 600;
}
.wa-chip-punto {
  width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--c);
}
.wa-chip[aria-pressed="true"] .wa-chip-punto { box-shadow: 0 0 0 1.5px #fff; }
.wa-chip-n {
  min-width: 20px; height: 18px; padding: 0 6px; border-radius: 999px;
  display: inline-grid; place-items: center;
  background: var(--ache-magenta); color: #fff; font-size: 10.5px; font-weight: 700;
}
.wa-chip[aria-pressed="true"] .wa-chip-n { background: #fff; color: var(--ache-magenta); }
/* El de gestionar etiquetas: redondo, solo el icono, al final. */
.wa-chip-ico { width: 32px; padding: 0; justify-content: center; }

/* Las etiquetas debajo de cada chat: tintadas con su color, pequeñas y
   todas de la misma altura. */
.wa-conv-etis { display: flex; gap: 4px; flex-wrap: wrap; margin-top: 5px; }
.wa-eti {
  display: inline-flex; align-items: center; height: 18px; padding: 0 8px;
  border-radius: 999px; font-size: 10.5px; font-weight: 600; line-height: 1;
  white-space: nowrap; color: var(--c);
  background: color-mix(in srgb, var(--c) 14%, transparent);
}

/* ELEGIR VARIOS: el círculo a la izquierda y la barra de arriba. */
.wa-marca {
  width: 22px; height: 22px; border-radius: 50%; flex: none;
  border: 2px solid var(--wa-texto-2); display: grid; place-items: center;
  color: #fff; transition: background .12s ease, border-color .12s ease;
}
.wa-conv[aria-pressed="true"] .wa-marca { background: var(--ache-magenta); border-color: var(--ache-magenta); }
.wa-conv[aria-pressed="true"] { background: color-mix(in srgb, var(--ache-magenta) 8%, transparent); }
.wa-lote {
  display: flex; align-items: center; gap: 4px; padding: 6px 8px;
  border-bottom: 1px solid var(--wa-borde); background: var(--wa-panel-2);
}
.wa-lote[hidden] { display: none; }
.wa-lote .wa-ico-btn { width: 34px; height: 34px; }
.wa-lote-n { font-size: 13px; font-weight: 600; color: var(--wa-texto); white-space: nowrap; }
.wa-lote-btn {
  font: inherit; font-size: 12px; border: 0; background: transparent; cursor: pointer;
  color: var(--ache-magenta); font-weight: 600; padding: 4px 6px;
}
.wa-lote-sep { flex: 1; }
#chat-elegir[aria-pressed="true"] { color: var(--ache-magenta); }

/* EL MENÚ DEL CLIC DERECHO. */
.wa-ctx {
  position: fixed; z-index: 9999; min-width: 210px; padding: 6px;
  background: var(--wa-panel); color: var(--wa-texto);
  border: 1px solid var(--wa-borde); border-radius: 12px;
  box-shadow: 0 12px 32px rgba(0, 0, 0, .22);
  animation: wa-ctx-entra .12s ease-out;
}
.wa-ctx button {
  font: inherit; font-size: 13.5px; width: 100%; display: flex; align-items: center; gap: 10px;
  border: 0; background: transparent; color: inherit; text-align: left;
  padding: 9px 10px; border-radius: 8px; cursor: pointer;
}
.wa-ctx button .ico { color: var(--wa-texto-2); flex: none; }
.wa-ctx button:hover, .wa-ctx button:focus-visible { background: var(--wa-panel-2); outline: none; }
@keyframes wa-ctx-entra { from { opacity: 0; transform: scale(.97); } to { opacity: 1; transform: none; } }

.wa-conv {
  width: 100%; text-align: left; border: 0; background: transparent;
  padding: 10px 12px; cursor: pointer; display: flex; gap: 12px;
  align-items: center; border-bottom: 1px solid var(--wa-borde);
  color: var(--wa-texto);
}
.wa-conv:hover { background: var(--wa-panel-2); }
.wa-conv[aria-current="true"] { background: var(--wa-panel-2); }
.wa-conv-txt { min-width: 0; flex: 1; }
.wa-conv-lin { display: flex; gap: 8px; align-items: center; justify-content: space-between; }
.wa-conv-nom, .wa-conv-ult {
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
.wa-conv-nom { font-weight: 600; font-size: 14px; }
.wa-conv-ult { font-size: 12.5px; color: var(--wa-texto-2); }
.wa-conv-hora { font-size: 11.5px; color: var(--wa-texto-2); flex: none; }
.wa-globo {
  min-width: 19px; height: 19px; padding: 0 6px; border-radius: 999px;
  background: var(--ache-magenta); color: #fff; font-size: 11px; font-weight: 700;
  display: grid; place-items: center; flex: none;
}

/* El círculo con las iniciales. Aquí NUNCA hay foto: la API de Meta no
   da la foto de perfil de quien escribe, así que en vez de un hueco
   gris igual para todos van sus iniciales sobre un color sacado del
   propio número. */
.wa-ficha {
  width: 46px; height: 46px; border-radius: 50%; flex: none;
  display: grid; place-items: center;
  font-weight: 700; font-size: 14px; color: #fff;
  letter-spacing: .02em; text-transform: uppercase;
}
.wa-ficha-sm { width: 38px; height: 38px; font-size: 12.5px; }

/* ── EL FONDO DE LA CONVERSACIÓN ──────────────────────────────────── */
/* EL FONDO VA EN UNA CAPA QUE NO SE MUEVE, y la conversación scrollea
   ENCIMA. Aquí estaba el fallo de «los patrones no se extienden por toda
   la conversación»: el dibujo era un `::before` con `inset: 0` DENTRO de
   la caja con scroll, y una capa absoluta dentro de un contenedor que
   scrollea mide lo que mide la parte visible y se va hacia arriba con el
   contenido. Resultado: el patrón cubría la primera pantalla y el resto
   del hilo quedaba liso.

   Separando las dos cosas —`.wa-lienzo` pinta y no scrollea,
   `.wa-mensajes` scrollea y es transparente— el dibujo cubre siempre el
   panel entero, que es además como se comporta WhatsApp. */
.wa-lienzo {
  position: relative;
  flex: 1 1 0; min-height: 0;
  display: flex; flex-direction: column;
  overflow: hidden;                 /* el dibujo no asoma por las esquinas */
  background-color: var(--wa-lienzo);
}
.wa-mensajes {
  flex: 1 1 0; min-height: 0; overflow-y: auto;
  padding: 14px clamp(12px, 5%, 60px);
  display: flex; flex-direction: column; gap: 2px;
  -webkit-overflow-scrolling: touch;
  position: relative; z-index: 1;   /* por encima del dibujo */
  background-color: transparent;
}

/* El dibujo va en una capa APARTE y no en el `background` de la caja.
   Así su opacidad se controla sola —sin teñir el texto, que es hijo— y
   la imagen que suba cada quien puede ir debajo sin pelearse con ella. */
/* EL DIBUJO SE PINTA CON MÁSCARA, NO CON `background-image`.
   Aquí estaba el fallo de «los fondos de formas no se ven, parece un
   color liso». El dibujo iba como imagen de fondo y su trazo estaba
   escrito a mano dentro del SVG —un gris fijo, `%23808080`—, aunque el
   comentario de al lado dijera que se heredaba del tema. No se hereda:
   una imagen de fondo es OTRO documento, y `currentColor` no llega ahí
   dentro. Resultado: un gris medio sobre un lienzo casi negro en oscuro
   y sobre uno casi blanco en claro; en los dos casos, invisible.

   Con máscara el SVG solo dice DÓNDE hay trazo, y el color lo pone
   `background-color`, que sí es del tema. Ahora el dibujo se ve en los
   dos temas con el mismo archivo, y subir o bajar la fuerza es cambiar
   un número en un sitio. */
.wa-lienzo::before {
  content: ""; position: absolute; inset: 0; z-index: 0;
  pointer-events: none;
  opacity: var(--wa-doodle-op);
  background-color: var(--wa-doodle-color);
  -webkit-mask-image: var(--wa-doodle, none);
          mask-image: var(--wa-doodle, none);
  -webkit-mask-repeat: repeat;      mask-repeat: repeat;
  -webkit-mask-size: 260px 260px;   mask-size: 260px 260px;
  -webkit-mask-position: 0 0;       mask-position: 0 0;
}
/* Sin dibujo no se pinta el velo de color: `mask-image: none` deja pasar
   TODO, así que el color taparía la conversación entera. */
.wa-lienzo:not([data-fondo])::before,
.wa-lienzo[data-fondo="liso"]::before,
.wa-lienzo[data-fondo="noche"]::before,
.wa-lienzo[data-fondo="degradado"]::before { background-color: transparent; }
.wa-mensajes > * { position: relative; z-index: 1; }

/* Los dibujitos. El color se hereda del tema con `currentColor`, así que
   el mismo garabato sirve en claro y en oscuro. */
.wa-lienzo[data-fondo="dibujos"], .wa-lienzo[data-fondo="ache"] {
  --wa-doodle: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='260' height='260' viewBox='0 0 260 260'%3E%3Cg fill='none' stroke='%23808080' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='30' cy='34' r='11'/%3E%3Cpath d='M92 22h22M103 11v22'/%3E%3Cpath d='M170 30c6-9 16-9 22 0'/%3E%3Cpath d='M222 18l14 14-14 14-14-14z'/%3E%3Cpath d='M20 96c8-11 19-11 27 0'/%3E%3Ccircle cx='108' cy='100' r='8'/%3E%3Cpath d='M160 88h26v26h-26z'/%3E%3Cpath d='M226 92v26M213 105h26'/%3E%3Cpath d='M28 168h26M41 155v26'/%3E%3Ccircle cx='104' cy='170' r='12'/%3E%3Cpath d='M158 160c8 9 8 15 0 24'/%3E%3Cpath d='M212 158l18 18-18 18'/%3E%3Cpath d='M24 232c9-10 21-10 30 0'/%3E%3Cpath d='M96 222h24v24H96z'/%3E%3Ccircle cx='172' cy='234' r='9'/%3E%3Cpath d='M216 224v22M205 235h22'/%3E%3C/g%3E%3C/svg%3E");
}
/* Los colores de la fundación, muy tenues, DEBAJO de los dibujos. */
.wa-lienzo[data-fondo="ache"] {
  background-image:
    radial-gradient(120% 90% at 12% 0%, rgba(230, 0, 126, .13), transparent 62%),
    radial-gradient(120% 90% at 88% 100%, rgba(116, 0, 184, .15), transparent 62%);
}
.wa-lienzo[data-fondo="noche"] {
  background-image:
    radial-gradient(140% 100% at 50% -20%, rgba(0, 174, 239, .16), transparent 60%);
  background-color: #05050a;
}
.wa-lienzo[data-fondo="papel"] {
  --wa-doodle: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='40' height='40'%3E%3Cg fill='none' stroke='%23808080' stroke-width='1'%3E%3Cpath d='M0 39.5h40M39.5 0v40'/%3E%3C/g%3E%3C/svg%3E");
}
.wa-lienzo[data-fondo="papel"]::before {
  -webkit-mask-size: 40px 40px; mask-size: 40px 40px;
}
.wa-lienzo[data-fondo="trama"] {
  --wa-doodle: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18'%3E%3Ccircle cx='2' cy='2' r='1.3' fill='%23808080'/%3E%3C/svg%3E");
}
.wa-lienzo[data-fondo="trama"]::before {
  -webkit-mask-size: 18px 18px; mask-size: 18px 18px;
  opacity: calc(var(--wa-doodle-op) * 2);
}
/* ── LOS PATRONES NUEVOS ──────────────────────────────────────────
   «Que los fondos sean principalmente de formas y patrones, y puede
    haber más opciones, pero la idea es que se vean.»
   Todos son máscaras: el color lo pone el tema, así que el mismo
   archivo se ve bien en claro y en oscuro. Y todos con trazo grueso a
   propósito — un patrón de un píxel se pierde igual que se perdían los
   de antes. */
.wa-lienzo[data-fondo="rombos"] {
  --wa-doodle: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='48' height='48'%3E%3Cpath d='M24 4 44 24 24 44 4 24z' fill='none' stroke='%23000' stroke-width='2'/%3E%3C/svg%3E");
}
.wa-lienzo[data-fondo="rombos"]::before {
  -webkit-mask-size: 48px 48px; mask-size: 48px 48px;
}
.wa-lienzo[data-fondo="ondas"] {
  --wa-doodle: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='60' height='30'%3E%3Cpath d='M0 22c8-14 22-14 30 0s22 14 30 0' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round'/%3E%3C/svg%3E");
}
.wa-lienzo[data-fondo="ondas"]::before {
  -webkit-mask-size: 60px 30px; mask-size: 60px 30px;
}
.wa-lienzo[data-fondo="panal"] {
  --wa-doodle: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='48'%3E%3Cg fill='none' stroke='%23000' stroke-width='2' stroke-linejoin='round'%3E%3Cpath d='M14 2 28 10v16L14 34 0 26V10z'/%3E%3Cpath d='M42 2 56 10v16L42 34 28 26V10z'/%3E%3Cpath d='M28 26 42 34v14'/%3E%3Cpath d='M14 34v14'/%3E%3C/g%3E%3C/svg%3E");
}
.wa-lienzo[data-fondo="panal"]::before {
  -webkit-mask-size: 56px 48px; mask-size: 56px 48px;
}
.wa-lienzo[data-fondo="diagonal"] {
  --wa-doodle: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24'%3E%3Cpath d='M-6 6 6 -6M0 24 24 0M18 30 30 18' fill='none' stroke='%23000' stroke-width='3'/%3E%3C/svg%3E");
}
.wa-lienzo[data-fondo="diagonal"]::before {
  -webkit-mask-size: 24px 24px; mask-size: 24px 24px;
}

.wa-lienzo[data-fondo="degradado"] {
  background-image: linear-gradient(160deg,
    rgba(230, 0, 126, .10), rgba(116, 0, 184, .10) 45%, rgba(0, 174, 239, .12));
}
/* «Liso» no lleva regla propia a propósito: el dibujo lo ponen las
   otras, así que no ponerlo ya es no tenerlo. */

/* La imagen que sube cada quien. Va como capa de fondo de la caja, con
   los dibujos apagados: dos fondos a la vez no es un fondo, es ruido. */
.wa-lienzo[data-fondo^="img"] {
  --wa-doodle: none;
  background-image: var(--wa-imagen, none);
  background-size: cover; background-position: center;
}
/* Y con un velo encima, porque una foto cualquiera detrás de un texto
   pequeño lo hace ilegible por muy bonita que sea. */
.wa-lienzo[data-fondo^="img"]::before {
  opacity: 1;
  /* SIN MÁSCARA: el velo tiene que cubrir la foto ENTERA. Con la del
     dibujo puesta se colaría la foto por los huecos del garabato y el
     texto volvería a quedar ilegible justo en esos trozos. */
  -webkit-mask-image: none; mask-image: none;
  background-image: none;
  background-color: color-mix(in srgb, var(--wa-lienzo) 62%, transparent);
}

/* ── LAS BURBUJAS ─────────────────────────────────────────────────── */
.wa-fila { display: flex; justify-content: flex-start; }
.wa-fila.mia { justify-content: flex-end; }
.wa-burbuja {
  position: relative;
  max-width: min(76%, 480px);
  background: var(--wa-suya);
  border-radius: 10px;
  padding: 6px 9px 5px;
  box-shadow: 0 1px 1px rgba(0, 0, 0, .16);
  font-size: 14px; line-height: 1.42;
  color: var(--wa-texto);
}
.wa-fila.mia .wa-burbuja { background: var(--wa-mia); }

/* El pico. Solo lo lleva el ÚLTIMO de una ráfaga seguida del mismo
   lado, que es como lo hace WhatsApp: un pico por mensaje convierte una
   ráfaga de seis en una sierra. */
.wa-fila.pico .wa-burbuja::after {
  content: ""; position: absolute; top: 0; width: 10px; height: 13px;
  background: inherit;
}
.wa-fila.pico:not(.mia) .wa-burbuja { border-top-left-radius: 0; }
.wa-fila.pico:not(.mia) .wa-burbuja::after {
  left: -8px; clip-path: polygon(100% 0, 100% 100%, 0 0);
}
.wa-fila.pico.mia .wa-burbuja { border-top-right-radius: 0; }
.wa-fila.pico.mia .wa-burbuja::after {
  right: -8px; clip-path: polygon(0 0, 100% 0, 0 100%);
}
.wa-fila + .wa-fila { margin-top: 2px; }
.wa-fila.pico { margin-top: 8px; }

.wa-texto { white-space: pre-wrap; word-break: break-word; }
.wa-texto a { color: var(--ache-cyan); }
.wa-pie {
  display: flex; gap: 4px; align-items: center; justify-content: flex-end;
  margin-top: 1px; white-space: nowrap;
  font-size: 11px; color: var(--wa-texto-2);
}
.wa-pie .ico { opacity: .9; }

/* La cita: el mensaje al que se contesta, encima y con su barra de
   color al lado, igual que en el teléfono. */
.wa-cita {
  border-left: 4px solid var(--ache-cyan);
  background: var(--wa-cita);
  border-radius: 6px; padding: 5px 8px; margin-bottom: 4px;
  max-height: 64px; overflow: hidden;
}
.wa-cita.suya { border-left-color: var(--ache-magenta); }

/* La reacción, colgando de la esquina de abajo de la burbuja. */
.wa-reaccion {
  position: absolute; bottom: -12px; font-size: 13px; line-height: 1;
  background: var(--wa-panel); border: 1px solid var(--wa-borde);
  border-radius: 999px; padding: 2px 6px;
}
.wa-fila.mia .wa-reaccion { right: 8px; }
.wa-fila:not(.mia) .wa-reaccion { left: 8px; }
.wa-fila:has(.wa-reaccion) { margin-bottom: 12px; }

/* La fecha que separa los días, flotando en el centro. */
.wa-dia {
  align-self: center; margin: 12px 0 6px;
  background: var(--wa-panel); border: 1px solid var(--wa-borde);
  border-radius: 999px; padding: 3px 12px;
  font-size: 11.5px; color: var(--wa-texto-2);
  box-shadow: 0 1px 1px rgba(0, 0, 0, .12);
}

/* Los botones que salen sobre la burbuja al pasar por encima.
   En pantalla táctil no hay «pasar por encima», así que ahí se dejan
   siempre puestos: un menú que solo aparece con el ratón no existe en
   un iPad. */
.wa-acciones {
  position: absolute; top: 2px; display: flex; gap: 3px;
  opacity: 0; transition: opacity .12s ease;
}
.wa-fila.mia .wa-acciones { left: -70px; }
.wa-fila:not(.mia) .wa-acciones { right: -70px; }
.wa-burbuja:hover .wa-acciones, .wa-acciones:focus-within { opacity: 1; }
@media (hover: none) { .wa-acciones { opacity: .5; } }
.wa-acc {
  border: 1px solid var(--wa-borde); background: var(--wa-panel);
  color: var(--wa-texto-2); border-radius: 7px; cursor: pointer;
  width: 26px; height: 26px; display: grid; place-items: center;
}
.wa-acc:hover { color: var(--wa-texto); }

/* El doble tic. Con icono, no con «✓✓» de texto: así el azul del leído
   es el azul de la fundación y no el que decida el sistema. */
.wa-tic { display: inline-flex; color: var(--wa-texto-2); }
.wa-tic.leido { color: var(--wa-tic); }

/* ── LA UBICACIÓN Y EL CONTACTO ───────────────────────────────────── */
.wa-mapa {
  display: block; width: 240px; border-radius: 8px; overflow: hidden;
  background: linear-gradient(135deg, rgba(0,174,239,.22), rgba(116,0,184,.22));
  border: 1px solid var(--wa-borde);
  padding: 22px 14px; text-align: center; color: inherit; text-decoration: none;
}
.wa-mapa:hover { filter: brightness(1.08); }
.wa-tarjeta {
  display: flex; gap: 10px; align-items: center;
  width: 240px; padding: 8px; border-radius: 8px;
  background: var(--wa-cita);
}

/* ── ESCRIBIR ─────────────────────────────────────────────────────── */
.wa-escribir {
  border-top: 1px solid var(--wa-borde);
  padding: 9px 12px;
  background: var(--wa-panel-2);
}
.wa-barra { display: flex; gap: 8px; align-items: flex-end; }

/* El cuadro de escribir, redondeado, con los iconos dentro como en la
   referencia. El micrófono queda FUERA y a la derecha, que es donde
   está en WhatsApp y donde lo busca el dedo. */
.wa-cuadro {
  flex: 1; display: flex; align-items: flex-end; gap: 4px;
  background: var(--wa-panel); border: 1px solid var(--wa-borde);
  border-radius: 20px; padding: 4px 6px 4px 4px; min-width: 0;
}
.wa-cuadro textarea {
  flex: 1; resize: none; border: 0; background: transparent; outline: none;
  color: var(--wa-texto); font: inherit; font-size: 14px;
  padding: 9px 4px; max-height: 130px; min-height: 38px; min-width: 0;
}
.wa-ico-btn {
  border: 0; background: transparent; color: var(--wa-texto-2);
  width: 38px; height: 38px; flex: none; border-radius: 50%;
  display: grid; place-items: center; cursor: pointer;
  transition: color .14s ease, background .14s ease;
}
.wa-ico-btn:hover { color: var(--wa-texto); background: var(--wa-cita); }
.wa-ico-btn:disabled { opacity: .45; cursor: not-allowed; }

/* El botón de mandar / grabar: uno solo que cambia de cara según haya
   texto escrito o no, igual que en WhatsApp. */
.wa-enviar {
  width: 44px; height: 44px; flex: none; border: 0; border-radius: 50%;
  background: var(--grad-marca); color: #fff;
  display: grid; place-items: center; cursor: pointer;
  box-shadow: 0 4px 14px rgba(230, 0, 126, .28);
}
.wa-enviar:hover { filter: brightness(1.08); }

/* ── EL MENÚ DEL «+» ──────────────────────────────────────────────── */
.wa-adjuntos {
  position: absolute; bottom: 70px; left: 14px; z-index: 8;
  background: var(--wa-panel); border: 1px solid var(--wa-borde);
  border-radius: 12px; padding: 6px; min-width: 216px;
  box-shadow: 0 16px 40px rgba(0, 0, 0, .34);
}
.wa-adj {
  display: flex; gap: 12px; align-items: center; width: 100%;
  border: 0; background: transparent; color: var(--wa-texto);
  padding: 9px 10px; border-radius: 9px; cursor: pointer; text-align: left;
  font-size: 13.5px;
}
.wa-adj:hover { background: var(--wa-cita); }
.wa-adj .wa-adj-ico {
  width: 32px; height: 32px; border-radius: 50%; flex: none;
  display: grid; place-items: center; color: #fff;
}

/* ── GRABANDO ─────────────────────────────────────────────────────── */
.wa-grabando {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 4px 6px;
}
.wa-punto-rec {
  width: 10px; height: 10px; border-radius: 50%; background: var(--peligro);
  flex: none; animation: waLatir 1.1s ease-in-out infinite;
}
@keyframes waLatir { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }

/* El espectro: barras que suben y bajan con la voz. Las alturas las
   pone el JavaScript leyendo el micrófono de verdad, no una animación
   de adorno — si el micrófono no está captando nada, se ve. */
.wa-espectro {
  flex: 1; display: flex; align-items: center; gap: 2px; height: 32px;
  min-width: 0; overflow: hidden;
}
.wa-espectro i {
  display: block; flex: 1; min-width: 2px; max-width: 4px;
  height: 3px; border-radius: 2px;
  background: var(--ache-cyan);
  transition: height .08s linear;
}
.wa-crono { font-variant-numeric: tabular-nums; font-size: 13px; flex: none; }

/* Se arrastra un archivo por encima: la conversación entera se marca.
   Sin esta señal, soltar un archivo es un acto de fe. */
.wa-panel.soltando::after {
  content: "Suelta el archivo para mandarlo";
  position: absolute; inset: 0; z-index: 9;
  display: grid; place-items: center; text-align: center;
  background: rgba(0, 174, 239, .14);
  border: 2px dashed var(--ache-cyan); border-radius: 12px;
  color: var(--wa-texto); font-weight: 600; pointer-events: none;
}

/* El botón de bajar al final, con lo que quedó sin leer. */
.wa-abajo {
  position: absolute; right: 20px; bottom: 96px; z-index: 6;
  width: 40px; height: 40px; border-radius: 50%;
  display: grid; place-items: center; cursor: pointer;
  background: var(--wa-panel); border: 1px solid var(--wa-borde);
  color: var(--wa-texto-2); box-shadow: 0 6px 18px rgba(0, 0, 0, .3);
}
.wa-abajo[data-nuevos]::after {
  content: attr(data-nuevos);
  position: absolute; top: -6px; right: -4px;
  background: var(--ache-magenta); color: #fff;
  border-radius: 999px; min-width: 18px; height: 18px; padding: 0 5px;
  font-size: 11px; font-weight: 700; display: grid; place-items: center;
}

/* El panel de la derecha con la ficha de la persona. Encima de la
   conversación y no en otra pantalla: se mira y se cierra. */
.wa-ficha-panel {
  position: absolute; inset: 0 0 0 auto; width: min(330px, 100%);
  background: var(--wa-panel); border-left: 1px solid var(--wa-borde);
  z-index: 10; display: flex; flex-direction: column; overflow-y: auto;
  color: var(--wa-texto);
}
.wa-galeria { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; }
.wa-galeria img { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: 6px; }

/* ── LOS EMOJIS ───────────────────────────────────────────────────
   Un PANEL anclado al botón, no una ventana modal. Estaba en una
   ventana con el fondo difuminado detrás, y para elegir una cara eso es
   demasiado: tapa la conversación —justo la que estás mirando para
   decidir qué contestar— y hay que cerrarla para volver.

   Y aquí es el ÚNICO sitio de la pantalla donde hay emojis: los iconos
   de la interfaz son todos SVG, porque un emoji se ve distinto en cada
   sistema y no hereda el color del tema. */
.wa-emojis-panel {
  position: absolute; bottom: 70px; left: 14px; z-index: 8;
  width: min(360px, calc(100% - 28px));
  background: var(--wa-panel); border: 1px solid var(--wa-borde);
  border-radius: 12px; overflow: hidden;
  box-shadow: 0 16px 40px rgba(0, 0, 0, .34);
  display: flex; flex-direction: column;
}
.wa-emoji-rejilla {
  display: grid; grid-template-columns: repeat(8, 1fr); gap: 2px;
  padding: 8px; max-height: 260px; overflow-y: auto;
}
.wa-emoji {
  border: 0; background: transparent; cursor: pointer;
  font-size: 21px; line-height: 1; padding: 5px; border-radius: 7px;
  font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", sans-serif;
}
.wa-emoji:hover { background: var(--wa-cita); }

/* La barra de categorías, abajo, como en el teclado del teléfono. */
.wa-emoji-tabs {
  display: flex; gap: 2px; padding: 5px 6px;
  border-top: 1px solid var(--wa-borde); background: var(--wa-panel-2);
  overflow-x: auto;
}
.wa-emoji-tab {
  border: 0; background: transparent; color: var(--wa-texto-2);
  cursor: pointer; border-radius: 7px; padding: 6px 9px; flex: none;
}
.wa-emoji-tab:hover { color: var(--wa-texto); background: var(--wa-cita); }
.wa-emoji-tab[aria-pressed="true"] {
  color: var(--ache-magenta);
  box-shadow: inset 0 -2px 0 var(--ache-magenta);
}

/* Las miniaturas para elegir fondo. */
.wa-fondos { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 10px; }
.wa-fondo-op {
  border: 2px solid var(--wa-borde); border-radius: 10px; cursor: pointer;
  padding: 0; overflow: hidden; background: var(--wa-lienzo);
  height: 74px; position: relative; color: var(--wa-texto);
}
.wa-fondo-op[aria-pressed="true"] { border-color: var(--ache-magenta); }
.wa-fondo-op span {
  position: absolute; left: 0; right: 0; bottom: 0;
  background: var(--wa-panel); font-size: 11px; padding: 3px 4px;
  border-top: 1px solid var(--wa-borde);
}

/* ── EL ASISTENTE POR PASOS ─────────────────────────────────────────
   La cinta de arriba con los pasos, las tres opciones grandes del
   «¿a quién?» y la lista de quiénes la reciben.

   Todo esto lo usan las DOS secciones —WhatsApp masivo y Email
   Marketing—, así que vive aquí y no en la hoja de ninguna de las dos:
   un asistente que se ve distinto según por dónde entres es dos
   asistentes. */

.asis-pasos {
  display: flex; gap: 6px; flex-wrap: wrap;
  padding: 0 0 14px; margin-bottom: 14px;
  border-bottom: 1px solid var(--borde);
}
.asis-paso {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: .74rem; color: var(--texto-3);
  padding: 4px 10px 4px 4px; border-radius: var(--r-full);
}
.asis-bola {
  width: 21px; height: 21px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 50%; font-size: .7rem; font-weight: 700;
  background: var(--superficie); border: 1px solid var(--borde);
  color: var(--texto-3);
}
.asis-paso.aqui { color: var(--texto); background: var(--superficie); font-weight: 600; }
.asis-paso.aqui .asis-bola {
  background: var(--grad-marca); border-color: transparent; color: #fff;
}
.asis-paso.hecho { color: var(--texto-2); }
.asis-paso.hecho .asis-bola { border-color: var(--exito); color: var(--exito); }
/* En el móvil el nombre de cada paso sobra: se queda la numeración,
   que es lo que dice dónde estás. El nombre entero está justo debajo,
   en el título del paso. */
@media (max-width: 640px) { .asis-nombre { display: none; } }

.asis-cabeza h3 { margin: 0; }

/* Las tres opciones grandes de «¿a quién?». Grandes a propósito: es la
   única decisión de esa pantalla, y de ella depende todo lo demás. */
.asis-opciones { display: grid; gap: 10px; }
.asis-opcion {
  display: flex; align-items: center; gap: 14px; text-align: left;
  width: 100%; padding: 15px 16px; cursor: pointer;
  background: var(--superficie); color: var(--texto);
  border: 1px solid var(--borde); border-radius: var(--r-md);
  transition: all var(--transicion);
}
.asis-opcion:hover { border-color: var(--borde-fuerte); transform: translateY(-1px); }
.asis-opcion.elegida {
  border-color: var(--ache-magenta);
  box-shadow: 0 0 0 1px var(--ache-magenta) inset;
}
.asis-icono {
  width: 42px; height: 42px; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 12px; color: var(--c, var(--ache-cyan));
  background: color-mix(in srgb, var(--c, var(--ache-cyan)) 14%, transparent);
}
.asis-op-txt { display: flex; flex-direction: column; gap: 3px; min-width: 0; }

/* ═══════════════════════════════════════════════════════════════════
   LA VISTA PREVIA DEL CERTIFICADO, SOBRE UNA HOJA CARTA DE VERDAD
   ═══════════════════════════════════════════════════════════════════
   Primer intento: hoja de 816 px con `transform: scale(.62)` y un
   margen negativo para tapar el hueco. Salió mal y se veía —«como si
   fuesen 2 hojas y el contenido se desfasa o se sale»—, porque
   `transform` cambia lo que se DIBUJA pero no lo que la hoja OCUPA:
   para la página la hoja seguía midiendo 816 × 1056, así que el marco
   negro se quedaba con el tamaño entero, la hoja reducida flotaba
   descentrada dentro de él y por debajo quedaba un tramo negro con
   forma de segunda página. El margen negativo, además, subía el
   contenido y le comía la cabecera.

   Ahora la reducción va en dos piezas: la hoja se dibuja reducida y la
   CAJA que la contiene toma el tamaño YA reducido, que el JS le pone al
   abrir el modal. Así la hoja ocupa exactamente lo que se ve, el marco
   se ajusta a ella y no sobra ni falta nada.

   La escala no está escrita aquí a propósito: depende de lo ancha que
   sea la ventana, y en el iPad no es la misma que en un portátil. */
.previa-marco {
  background: #0a0a0a; padding: 14px; border-radius: 14px;
  overflow: auto; display: flex; justify-content: center;
  /* ALTURA FIJA, Y LA HOJA SE DESPLAZA DENTRO.
     Antes el marco se encogía hasta la altura de la hoja, lo que
     obligaba a reducir la hoja hasta que cupiera ENTERA: a poco más de
     la mitad de su tamaño, ilegible —«se ve muy pequeño el
     certificado»—. Un documento se lee ajustado al ancho y
     desplazándose, como en cualquier lector. */
  max-height: 68vh;
}

/* Los mandos del aumento, encima de la hoja. */
.previa-mandos {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin: 0 0 8px;
}
.previa-zoom {
  min-width: 52px; text-align: center;
  font-size: .74rem; font-weight: 700; color: var(--texto-2);
}
.previa-caja { flex: 0 0 auto; }
.previa-hoja {
  width: 816px;          /* 8,5 pulgadas a 96 ppp: la carta, exacta */
  min-height: 1056px;    /* 11 pulgadas */
  padding: 45px;         /* los 12 mm de margen del PDF */
  background: #fff; color: #111;
  box-shadow: 0 6px 30px rgba(0, 0, 0, .5);
  transform-origin: top left;
}

/* ═══════════════════════════════════════════════════════════════════
   LA FICHA DEL CONTACTO, SIEMPRE A LA VISTA
   ═══════════════════════════════════════════════════════════════════
   «La información del contacto apenas abro telemercadeo sale muy
   arriba y debo estar haciendo scroll de arriba a abajo para hacer la
   gestión y buscar datos del contacto.»

   Se queda pegada bajo la cabecera mientras el formulario y el
   historial se desplazan por debajo. `top` sale de la altura real de la
   cabecera —que ya es `sticky`— y no de un número a ojo: cambiarla en
   un sitio no puede dejar la ficha metida debajo en el otro.

   Tres frenos, los tres necesarios:
     · un tope de altura, con desplazamiento propio, para el contacto
       que trae ocho teléfonos: una ficha que ocupa media pantalla
       estorba más de lo que ayuda;
     · en pantallas bajas (portátiles de 13") deja de pegarse: entre la
       cabecera y la ficha no quedaría sitio para escribir;
     · y en móvil tampoco, donde no hay dos columnas y pegarla se comería
       la pantalla entera.

   `z-index` bajo el de la cabecera (50) a propósito: al desplazar, la
   ficha tiene que pasar POR DEBAJO de la barra de arriba. */
.ficha-fija {
  position: sticky;
  top: calc(var(--header-h) + 16px);
  z-index: 3;
  /* El tope duro. Con un nombre de empresa largo, cuatro etiquetas y un
     proyecto, la fila de arriba se parte en dos y la ficha crece; ahí es
     donde tiene que haber un techo, porque es el caso que nadie prueba y
     el que se encuentra el cliente. 24vh son unos 200 px en la pantalla
     de 900 con la que se trabaja: pase lo que pase, la gestión se queda
     con las tres cuartas partes largas de la pantalla. */
  max-height: 30vh;
  overflow: auto;

  /* FONDO OPACO, Y ES LO QUE MÁS SE NOTA.
     `--superficie` es blanco al 3,5 %: sirve para una tarjeta apoyada en
     el fondo de la página, no para algo por DEBAJO de lo cual pasa
     contenido desplazándose. Desde que la ficha se quedó fija, el
     formulario se veía a través de ella —«en el modo oscuro es
     totalmente translúcido y se puede ver lo que está en la parte
     trasera»— y en claro también, aunque menos.

     Es la misma regla que ya tienen los menús flotantes de este CSS, por
     la misma razón: lo que se superpone lleva su propio color sólido.

     Y el color ya existía: `--fondo-fijo`, creada para este mismo
     problema en las cabeceras de tabla pegajosas, con su comentario
     explicándolo veinte líneas más arriba. Inventar aquí un color nuevo
     habría sido tener dos respuestas a la misma pregunta. */
  background: var(--fondo-fijo);
  box-shadow: 0 10px 22px -18px rgba(0, 0, 0, .9);
}

/* Y por dentro, compacta: es una barra de datos, no una tarjeta.

   COMPACTA, NO DIMINUTA. El primer intento se pasó de frenada: la ficha
   bajó de unos 330 píxeles a 83, y a 83 hay demasiada información
   metida en muy poca altura —«tampoco irse a los extremos… se ve mucha
   información para el tamaño que le colocaste»—. El teléfono y el
   correo son lo que se lee mientras se marca; si hay que acercarse a la
   pantalla para leerlos, la ficha ha dejado de servir aunque quepa.

   Así que sube a la mitad de camino: unos 115 px. Sigue dejando más de
   siete octavos de la pantalla para la gestión, que era el problema de
   verdad, y el texto vuelve a un tamaño que se lee de un vistazo. */
/* «Me dijeron que veían todos los datos muy comprimidos, así que hazla
   más grande para que los elementos no se vean tan pegados; no les
   molestaba como estaba inicialmente, solo que sea un poco más pequeña.»
   Ni lo de antes ni lo de después: a medio camino, con aire. */
.ficha-fija.card-p { padding: 18px 20px; }

/* ── ELEGIR LA HOJA DEL LIBRO ────────────────────────────────────────
   Filas pulsables enteras, no una casilla de trece píxeles: esto se usa
   también desde el iPad, donde acertarle a la casilla es imposible. */
.hoja-lista { display: flex; flex-direction: column; gap: 8px; }
.hoja-op {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 14px; cursor: pointer;
  border: 1px solid var(--borde); border-radius: var(--r-sm);
  background: var(--superficie);
  transition: border-color var(--transicion), background var(--transicion);
}
.hoja-op:hover { border-color: var(--ache-cyan); }
.hoja-op:has(input:checked) {
  border-color: var(--ache-magenta);
  background: var(--grad-suave);
}
/* Una hoja vacía se enseña igual, en gris y sin poder elegirse: saber
   que está y que no tiene nada es parte de reconocer el libro. */
.hoja-op.vacia { opacity: .5; cursor: not-allowed; }
.hoja-op input { flex: none; }

/* ── EL VELO DE ENCIMA DE LA FICHA ───────────────────────────────────
   «Quisiera que en la parte de arriba de la barra de contacto se viera
    como desvanecido, para que cuando haga scroll no sea posible ver lo
    que está atrás… pero sí todo lo que sale debajo de la barra.»

   Había DOS sitios por donde asomaba el formulario al subir:

     · el hueco de 16 px entre la cabecera de la aplicación y la ficha;
     · y la propia cabecera, que es de cristal —translúcida y con
       desenfoque— y deja ver en sombra lo que pasa por detrás.

   EL PRIMER INTENTO LO TAPÓ CON COLOR LISO, y se pasó de frenada:

     «Te pedí un efecto como desvanecido pero que se notaran los
      elementos de atrás, así sea borroso. Mejor cámbialo por otro efecto
      tipo glass, ya que como lo hiciste no se ve absolutamente nada.»

   Y tenía razón en las dos cosas: en que no se veía nada, y en que lo
   que hacía falta era otra cosa. Un tapón opaco a media pantalla se lee
   como un trozo de página que falta; un cristal esmerilado se lee como
   lo que es, algo que está POR DELANTE. Se intuye que hay contenido
   pasando por debajo —se ven las formas y los colores moverse— pero no
   se puede leer, que es exactamente lo que se quería: que lo principal
   de esa franja sea la barra de contacto y no lo que pasa detrás.

   CÓMO SE HACE: `backdrop-filter` desenfoca lo que hay por detrás del
   elemento, y el fondo translúcido por encima le quita contraste para
   que el desenfoque no se lea como texto borroso sino como niebla. Las
   dos cosas juntas; solo con una, el texto se sigue adivinando.

   Y UN RESPALDO PARA QUIEN NO LO TENGA. `backdrop-filter` no existe en
   navegadores viejos, y ahí un fondo al 55 % dejaría pasar el texto
   legible: lo que se quitó. Con `@supports`, quien puede desenfocar
   recibe el cristal y quien no, el color liso de antes — feo, pero
   nunca peor que lo que había.

   Va DEBAJO de la ficha (z-index 2 contra 3) y debajo de la cabecera
   (50), así que no tapa ninguna de las dos: lo único que se queda detrás
   es el formulario, que es justo lo que sobraba.

   `margin-bottom` negativo del mismo alto: el velo pinta pero no empuja.
   Sin eso, la ficha bajaría 90 px y aparecería un hueco en blanco.

   Y solo cubre la columna de la gestión: la lista de la izquierda se
   sigue viendo pasar bajo el cristal, como siempre. */
.ficha-velo {
  position: sticky;
  top: 0;
  z-index: 2;
  height: calc(var(--header-h) + 20px);
  margin-bottom: calc((var(--header-h) + 20px) * -1);
  /* Respaldo opaco: si el navegador no sabe desenfocar, tapa. */
  background: var(--fondo);
  pointer-events: none;
}

@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .ficha-velo {
    /* El desenfoque hace el trabajo; la saturación de más evita que el
       cristal apague los colores de la marca y lo deje todo gris. */
    -webkit-backdrop-filter: blur(22px) saturate(140%);
    backdrop-filter: blur(22px) saturate(140%);
    background: color-mix(in srgb, var(--fondo) 62%, transparent);
  }
}

@media (max-height: 720px), (max-width: 900px) {
  /* Donde la ficha deja de pegarse, el velo sobra: sin nada fijo arriba
     no hay nada que tapar, y taparía contenido normal. */
  .ficha-velo { display: none; }
}

/* La persona, el cargo y la ciudad, en su propia línea. Iban metidos en
   la misma tira que el teléfono y el correo, y ahí no se leían: son lo
   que se dice al saludar, no un dato que se copia. */
.ficha-quien { margin-top: 9px; font-size: .9rem; line-height: 1.45; }

.ficha-datos {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 10px 22px; margin-top: 10px;
  font-size: .92rem; line-height: 1.5;
}
.ficha-dato {
  display: inline-flex; align-items: center; gap: 7px;
  color: var(--texto); font-weight: 600;
  /* Un correo larguísimo parte por donde haga falta antes que desbordar
     la barra en horizontal, que es lo único que no se puede permitir:
     con scroll lateral el botón de Llamar se sale de la pantalla. */
  overflow-wrap: anywhere;
}
.ficha-dato.pointer:hover { color: var(--ache-cyan); }

@media (max-height: 720px), (max-width: 900px) {
  .ficha-fija { position: static; max-height: none; overflow: visible; box-shadow: none; }
}

/* ── EL FILTRO DE BASES DEL DASHBOARD ────────────────────────────────
   Una casilla por base, dentro del menú flotante de siempre. Las filas
   se pulsan enteras —la etiqueta envuelve la casilla— porque una
   casilla de 13 píxeles en un iPad es un objetivo imposible. */
.menu-bases > summary { height: 38px; }
.base-op {
  display: flex; align-items: center; gap: 10px;
  width: 100%; padding: 8px 12px;
  font-size: .82rem; color: var(--texto);
  border-radius: var(--r-sm);
}
.base-op:hover { background: var(--superficie-2); }
.base-op input { flex: none; margin: 0; }

/* ── LA VENTANA DE EXPORTAR INFORMES ─────────────────────────────────
   «Solo sale una cantidad de checkboxes y puede que un usuario ni sepa
    lo que se exportará si no conoce las opciones del CRM. Necesito que
    sea más visual, que muestre una pequeña previa de cada cosa que va en
    el informe.»

   Cada parte del informe pasa de ser un renglón con casilla a una
   tarjeta que enseña la FORMA que tiene en el papel, la pregunta que
   responde y en qué unidad cuenta. La casilla sigue ahí —es lo que se
   manda— pero escondida: lo que se pulsa es la tarjeta entera, que en un
   iPad es la diferencia entre acertar y no acertar. */
.pdf-tarjetas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 10px;
}

.pdf-tarjeta {
  position: relative;
  display: flex; align-items: flex-start; gap: 11px;
  padding: 12px 13px 12px 12px;
  border: 1px solid var(--borde);
  border-radius: 14px;
  background: var(--superficie);
  cursor: pointer;
  transition: border-color .16s, background .16s, transform .16s;
}
.pdf-tarjeta:hover { border-color: var(--borde-fuerte); }
.pdf-tarjeta:active { transform: scale(.995); }

/* La casilla de verdad, escondida pero NO quitada: sigue siendo la que
   se lee al generar y la que recorre el teclado. Un `display:none` la
   sacaría del tabulador y la tarjeta dejaría de poder usarse sin ratón. */
.pdf-tarjeta > input[type="checkbox"] {
  position: absolute; opacity: 0; width: 1px; height: 1px;
  margin: 0; pointer-events: none;
}
.pdf-tarjeta > input:focus-visible ~ .pdf-tarjeta-marca {
  outline: 2px solid var(--ache-cyan); outline-offset: 2px;
}

.pdf-tarjeta-marca {
  flex: 0 0 auto; width: 18px; height: 18px; margin-top: 1px;
  border: 2px solid var(--borde); border-radius: 6px;
  transition: background .16s, border-color .16s;
}
.pdf-tarjeta.activa { border-color: var(--ache-magenta); background: var(--grad-suave, transparent); }
.pdf-tarjeta.activa .pdf-tarjeta-marca {
  background: var(--ache-magenta); border-color: var(--ache-magenta);
  /* La palomita, dibujada con dos bordes girados: sin imagen y sin
     fuente de iconos, así no depende de que nada más haya cargado. */
  background-image: linear-gradient(45deg, transparent 46%, #fff 46%, #fff 56%, transparent 56%),
                    linear-gradient(-45deg, transparent 62%, #fff 62%, #fff 72%, transparent 72%);
  background-size: 60% 60%, 60% 60%;
  background-position: 62% 60%, 26% 52%;
  background-repeat: no-repeat;
}

.pdf-tarjeta-dibujo {
  flex: 0 0 auto; display: grid; place-items: center;
  width: 50px; height: 34px; border-radius: 8px;
  background: var(--superficie-2);
  color: var(--texto-3);
  transition: color .16s, background .16s;
}
.pdf-tarjeta.activa .pdf-tarjeta-dibujo {
  color: var(--ache-magenta);
  background: color-mix(in srgb, var(--ache-magenta) 14%, transparent);
}
.pdf-croquis { width: 38px; height: 21px; display: block; }

.pdf-tarjeta-texto { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.pdf-tarjeta-tit { font-weight: 700; font-size: .9rem; line-height: 1.25; overflow-wrap: anywhere; }
.pdf-tarjeta-sub { font-size: .78rem; color: var(--texto-2); line-height: 1.35; }
.pdf-tarjeta-pie { font-size: .72rem; color: var(--texto-3); line-height: 1.3; }

/* ── El aviso de los dos bloques que parecen gemelos ──────────────── */
.pdf-aviso {
  margin: 12px 0 4px; padding: 11px 13px;
  border: 1px solid rgba(245,165,36,.42); border-radius: 12px;
  background: rgba(245,165,36,.10);
}

/* ── Cada grupo del detalle, con su propio todas/ninguna ──────────── */
.pdf-grupo { margin: 0 0 14px; padding: 0 0 10px; border-bottom: 1px solid var(--borde); }
.pdf-grupo:last-child { border-bottom: 0; padding-bottom: 0; }
.pdf-grupo-cab { display: flex; align-items: center; gap: 8px; margin: 0 0 5px; }
/* Un grupo vacío no es un error, es una elección: «este bloque sin
   listas». Se marca en gris para que se vea que está a propósito. */
.pdf-grupo-vacio { opacity: .62; }

/* ── El resumen de abajo ──────────────────────────────────────────── */
.pdf-resumen {
  margin-top: 4px; padding: 11px 13px;
  border: 1px dashed var(--borde-fuerte); border-radius: 12px;
  background: var(--superficie);
}
.pdf-resumen-vacio {
  border-color: rgba(239,68,68,.5); background: rgba(239,68,68,.08);
  color: var(--peligro); font-size: .86rem;
}

@media (max-width: 560px) {
  .pdf-tarjetas { grid-template-columns: 1fr; }
  .pdf-tarjeta-dibujo { display: none; }
}

/* ── DIRECTORIO · VARIOS ESTADOS Y GRUPOS (parche 71) ─────────────── */
.dir-multi { position: relative; flex: 0 0 auto; }
.dir-multi > summary {
  list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 8px;
  min-height: 42px; padding: 0 14px; border-radius: var(--r-sm);
  border: 1px solid var(--borde-fuerte); background: var(--fondo-alto); color: var(--texto);
  font: inherit; white-space: nowrap;
  /* ANCHO FIJO. Con ancho automático el botón crecía o encogía según lo
     marcado («Sin gestionar + Llamar nueva…» frente a «3 estados»), la
     fila de filtros se reacomodaba y el desplegable saltaba de sitio
     mientras se elegía. */
  width: 250px; justify-content: space-between;
}
@media (max-width: 640px) { .dir-multi, .dir-multi > summary { width: 100%; } }
.dir-multi > summary::-webkit-details-marker { display: none; }
.dir-multi > summary span { overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.dir-multi[open] > summary { border-color: var(--ache-magenta); }
/* EL DESPLEGABLE SE QUEDABA DETRÁS DE LAS TARJETAS. Las tarjetas del
   directorio llevan transformaciones (el efecto 3D y la animación de
   entrada), y cada una de ellas forma su propia capa, que el navegador
   pinta ENCIMA de todo lo anterior. Un `z-index` dentro de la caja de
   filtros no sirve si la caja entera está en una capa más baja: hay que
   subir la caja de filtros completa mientras el desplegable está abierto. */
.filtros-encima { position: relative; z-index: 80; }
.dir-multi-caja {
  position: absolute; z-index: 60; top: calc(100% + 6px); left: 0; min-width: 260px;
  max-height: 360px; overflow-y: auto; padding: 8px;
  background: var(--fondo-fijo); border: 1px solid var(--borde-fuerte); border-radius: var(--r-md);
  box-shadow: var(--sombra);
}
.dir-multi-caja label {
  display: flex; align-items: center; gap: 9px; padding: 7px 8px; border-radius: 8px;
  cursor: pointer; font-size: 14px;
}
.dir-multi-caja label:hover { background: var(--superficie-2); }
.dir-multi-punto { width: 9px; height: 9px; border-radius: 50%; flex: none; display: inline-block; }
.dir-grupo {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  padding: 10px 4px 2px; border-bottom: 1px solid var(--borde); font-size: 15px;
}
