/* ==========================================================
   CRM - CAPA DE DISENO

   Se carga ULTIMA, despues de legibilidad.css y movil.css.
   legibilidad.css resuelve contraste a fuerza de !important y, de
   paso, aplana la jerarquia visual. Esta hoja le devuelve
   profundidad, ritmo y movimiento.

   Principios:
   - la profundidad se construye con capas de luz, no con sombras
     negras: borde superior claro + sombra difusa + brillo interno
   - una sola escala de espaciado, radios y duraciones
   - todo lo que aparece, aparece animado y en cascada
   - el color se gana: gris por defecto, verde solo donde hay accion
   ========================================================== */

:root {
    /* Espaciado */
    --sp-1: 4px;
    --sp-2: 8px;
    --sp-3: 12px;
    --sp-4: 16px;
    --sp-5: 24px;
    --sp-6: 32px;
    --sp-7: 48px;

    --control-h: 42px;
    --control-h-mobile: 46px;

    --r-sm: 10px;
    --r-md: 14px;
    --r-lg: 20px;
    --r-xl: 26px;

    /* Superficies: cada nivel se aclara y se despega del fondo */
    --surf-0: #0e1317;
    --surf-1: #141a20;
    --surf-2: #1a2229;
    --surf-3: #212b33;

    /* El borde no es una linea: es un degrade que simula luz cenital */
    --borde-luz: rgba(255, 255, 255, 0.09);
    --borde-sombra: rgba(0, 0, 0, 0.5);

    /* Sombras en capas: contacto + difusion + ambiente */
    --elev-1:
        0 1px 1px rgba(0, 0, 0, 0.28),
        0 2px 6px rgba(0, 0, 0, 0.22);
    --elev-2:
        0 1px 1px rgba(0, 0, 0, 0.3),
        0 4px 12px rgba(0, 0, 0, 0.3),
        0 12px 32px rgba(0, 0, 0, 0.22);
    --elev-3:
        0 2px 4px rgba(0, 0, 0, 0.35),
        0 12px 28px rgba(0, 0, 0, 0.38),
        0 32px 64px rgba(0, 0, 0, 0.3);

    /* Halo de marca para estados activos */
    --halo: 0 0 0 1px rgba(var(--acento-rgb), 0.35), 0 0 24px rgba(var(--acento-rgb), 0.16);

    /* Curvas y tiempos */
    --t-rapido: 140ms;
    --t-medio: 260ms;
    --t-lento: 420ms;
    --curva: cubic-bezier(0.22, 1, 0.36, 1);
    --curva-suave: cubic-bezier(0.4, 0, 0.2, 1);
}

/* ==========================================================
   0. FONDO

   Un plano grafito con dos focos frios muy tenues y una trama
   de puntos casi invisible. La trama es lo que separa un fondo
   plano de una superficie: se percibe sin llegar a verse.
   ========================================================== */

html {
    background:
        radial-gradient(60% 40% at 15% 0%, rgba(var(--acento-rgb), 0.055) 0%, transparent 62%),
        radial-gradient(50% 40% at 88% 8%, rgba(56, 189, 248, 0.035) 0%, transparent 58%),
        var(--surf-0) !important;
    background-attachment: fixed !important;
}

body::before {
    content: '';
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background-image: radial-gradient(rgba(255, 255, 255, 0.028) 1px, transparent 1px);
    background-size: 22px 22px;
}

/* ==========================================================
   1. PANELES

   El patron base: fondo translucido, borde de luz arriba que se
   apaga hacia abajo, y una linea interior clara en el borde
   superior. Es lo que hace que una caja se lea como material y
   no como un rectangulo de color.
   ========================================================== */

.glass-panel,
.top-navbar,
.main-tabs,
.barra-filtros,
.resumen-item,
.metric-card,
.chart-card,
.users-container,
.bitacora-panel {
    position: relative;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, 0.035) 0%, rgba(255, 255, 255, 0) 42%),
        var(--surf-1) !important;
    border: 1px solid var(--borde-luz) !important;
    border-radius: var(--r-lg) !important;
    box-shadow: var(--elev-2) !important;
    backdrop-filter: blur(14px) saturate(1.15);
    -webkit-backdrop-filter: blur(14px) saturate(1.15);
}

/* Filo superior: una linea de 1px mas clara que el borde, del ancho
   del panel y desvanecida en las puntas. Detalle barato, efecto caro. */
.glass-panel::after,
.resumen-item::after,
.metric-card::after {
    content: '';
    position: absolute;
    top: 0;
    left: 12%;
    right: 12%;
    height: 1px;
    pointer-events: none;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.22), transparent);
}

/* ==========================================================
   2. TIPOGRAFIA
   ========================================================== */

.section-head h2,
.users-header h2,
.historial-head h3 {
    font-size: clamp(1.05rem, 0.9rem + 0.6vw, 1.32rem) !important;
    font-weight: 800 !important;
    letter-spacing: -0.02em !important;
    line-height: 1.2 !important;
    color: var(--text-main) !important;
}

.section-head p,
.historial-head p {
    font-size: 0.8rem !important;
    line-height: 1.55 !important;
    color: var(--text-muted) !important;
    max-width: 66ch;
}

/* Todo dato numerico con ancho fijo: las cifras no bailan al cambiar */
.metric-value,
.resumen-item strong,
.count-badge,
.tab-badge,
.uso-totales strong,
.custom-table td {
    font-variant-numeric: tabular-nums;
    font-feature-settings: 'tnum' 1;
}

/* ==========================================================
   3. ENCABEZADO DE SECCION
   ========================================================== */

.section-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--sp-4);
    padding-bottom: var(--sp-4);
    margin-bottom: var(--sp-5);
    border-bottom: 1px solid var(--borde-luz);
}

.section-head__texto {
    min-width: 0;
    flex: 1 1 320px;
}

.section-head h2 {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    margin: 0;
}

/* El icono del titulo va en su propia pastilla: da peso al encabezado */
.section-head h2 i {
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    font-size: 0.82rem !important;
    border-radius: 9px;
    color: var(--primary) !important;
    background: rgba(var(--acento-rgb), 0.1);
    border: 1px solid rgba(var(--acento-rgb), 0.2);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
}

.section-head p {
    margin: var(--sp-2) 0 0;
}

.section-head__acciones {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    flex: 0 0 auto;
}

/* ==========================================================
   4. BOTONES

   El !important no es capricho: index.css declara .btn-primary-3d
   con !important en nueve propiedades. Para igualar la altura de
   ese boton con la del select de al lado hay que competir parejo.
   ========================================================== */

.section-head__acciones .btn,
.barra-filtros .btn,
.barra-filtros .select-field,
.barra-filtros input,
.historial-filtros .select-field,
.historial-filtros .btn {
    height: var(--control-h) !important;
    min-height: var(--control-h) !important;
    padding: 0 var(--sp-3) !important;
    margin: 0 !important;
    font-size: 0.82rem !important;
    font-weight: 700 !important;
    border-radius: var(--r-sm) !important;
    line-height: 1 !important;
    box-sizing: border-box !important;
    transition:
        transform var(--t-rapido) var(--curva),
        box-shadow var(--t-medio) var(--curva),
        border-color var(--t-medio) var(--curva),
        background var(--t-medio) var(--curva) !important;
}

/* Accion principal: la unica pieza rellena de la pantalla.
   Degrade vertical + filo claro arriba + halo verde debajo. */
.section-head__acciones .btn-primary-3d,
.section-head__acciones .btn-primary {
    background: linear-gradient(180deg, #4ff0a4 0%, var(--primary) 55%, #1fcf78 100%) !important;
    color: #06231a !important;
    border: none !important;
    padding: 0 var(--sp-5) !important;
    white-space: nowrap;
    letter-spacing: 0.01em;
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.45),
        0 1px 2px rgba(0, 0, 0, 0.3),
        0 6px 18px rgba(var(--acento-rgb), 0.28) !important;
}

.section-head__acciones .btn-primary-3d:hover,
.section-head__acciones .btn-primary:hover {
    transform: translateY(-2px) !important;
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.5),
        0 2px 4px rgba(0, 0, 0, 0.3),
        0 12px 30px rgba(var(--acento-rgb), 0.4) !important;
}

.section-head__acciones .btn-primary-3d:active,
.section-head__acciones .btn-primary:active {
    transform: translateY(0) !important;
    transition-duration: 60ms !important;
}

.section-head__acciones .btn-primary-3d i {
    font-size: 0.82rem !important;
    color: inherit !important;
}

/* Secundarios: solo icono, cuadrados, agrupados */
.btn-icono {
    width: var(--control-h) !important;
    padding: 0 !important;
    display: inline-flex !important;
    align-items: center;
    justify-content: center;
    background: var(--surf-2) !important;
    border: 1px solid var(--borde-luz) !important;
    color: var(--text-muted) !important;
    cursor: pointer;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05), var(--elev-1) !important;
}

.btn-icono:hover {
    border-color: rgba(var(--acento-rgb), 0.45) !important;
    color: var(--primary) !important;
    background: var(--surf-3) !important;
    transform: translateY(-1px) !important;
}

.btn-grupo {
    display: inline-flex;
    border-radius: var(--r-sm);
    box-shadow: var(--elev-1);
}

.btn-grupo .btn-icono {
    border-radius: 0 !important;
    margin-left: -1px !important;
    box-shadow: none !important;
}

.btn-grupo .btn-icono:first-child {
    border-radius: var(--r-sm) 0 0 var(--r-sm) !important;
    margin-left: 0 !important;
}

.btn-grupo .btn-icono:last-child {
    border-radius: 0 var(--r-sm) var(--r-sm) 0 !important;
}

.btn-grupo .btn-icono:hover {
    position: relative;
    z-index: 1;
    transform: none !important;
}

/* Foco visible y de marca en todo control accionable */
.btn:focus-visible,
.select-field:focus-visible,
.tab-btn:focus-visible,
input:focus-visible {
    outline: 2px solid var(--primary) !important;
    outline-offset: 2px !important;
}

/* ==========================================================
   5. BARRA DE FILTROS
   ========================================================== */

.barra-filtros {
    display: grid;
    grid-template-columns: minmax(200px, 1.4fr) repeat(auto-fit, minmax(150px, 1fr));
    align-items: center;
    gap: var(--sp-2);
    padding: var(--sp-2) !important;
    margin-bottom: var(--sp-5);
    border-radius: var(--r-md) !important;
}

.barra-filtros .buscador {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    height: var(--control-h);
    padding: 0 var(--sp-3);
    background: var(--surf-0);
    border: 1px solid var(--borde-luz);
    border-radius: var(--r-sm);
    transition: border-color var(--t-medio) var(--curva), box-shadow var(--t-medio) var(--curva);
}

.barra-filtros .buscador:focus-within {
    border-color: rgba(var(--acento-rgb), 0.5);
    box-shadow: var(--halo);
}

.barra-filtros .buscador i {
    color: var(--text-dim);
    font-size: 0.8rem;
    flex: 0 0 auto;
    transition: color var(--t-medio) var(--curva);
}

.barra-filtros .buscador:focus-within i {
    color: var(--primary);
}

.barra-filtros .buscador input {
    height: auto !important;
    min-height: 0 !important;
    padding: 0 !important;
    border: none !important;
    outline: none !important;
    background: transparent !important;
    width: 100%;
    min-width: 0;
    font-size: 0.84rem !important;
    font-weight: 600 !important;
    color: var(--text-main) !important;
}

.barra-filtros .select-field,
.historial-filtros .select-field {
    width: 100% !important;
    min-width: 0;
    background: var(--surf-0) !important;
    color: var(--text-main) !important;
    border: 1px solid var(--borde-luz) !important;
    cursor: pointer;
}

.barra-filtros .select-field:hover,
.historial-filtros .select-field:hover {
    border-color: rgba(255, 255, 255, 0.18) !important;
}

/* Un filtro puesto se tiene que notar sin abrirlo */
.barra-filtros .select-field.filtro-activo {
    border-color: rgba(var(--acento-rgb), 0.5) !important;
    background: rgba(var(--acento-rgb), 0.1) !important;
    color: var(--primary) !important;
    box-shadow: var(--halo) !important;
}

/* Un plazo pasado —o una consulta que nadie contesto dentro del SLA—
   es lo unico rojo de la fila. Si se pintaran tres cosas de rojo, el
   rojo dejaria de querer decir "esto se te esta escapando". */
.fila-sub.vencida {
    color: #ef4444;
    font-weight: 700;
}

/* PLANTILLAS DE MENSAJE (dentro de la ficha del lead)

   El bloque entero es un solo .form-group para heredar el ancho y el
   margen de los demas campos: asi no hay un ancho propio que se pueda
   desbordar en el telefono. */
.bloque-plantillas #plantilla-preview {
    margin-top: var(--sp-2, 8px);
    width: 100%;
    box-sizing: border-box;
    resize: vertical;
    min-height: 88px;
}

/* Los dos botones se reparten el ancho y bajan uno debajo del otro
   cuando no entran. Sin wrap, en 320px el segundo se salia de la
   tarjeta y el modal ganaba scroll horizontal. */
.plantilla-acciones {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2, 8px);
    margin-top: var(--sp-2, 8px);
}

.plantilla-acciones .btn {
    flex: 1 1 140px;
    min-width: 0;
    justify-content: center;
    white-space: nowrap;
}

.plantilla-acciones .btn.copiado {
    border-color: rgba(var(--acento-rgb), 0.5);
    color: var(--primary);
}

/* Un campo obligatorio que aparece solo tiene que avisar que aparecio:
   sin la entrada, el boton de guardar "no hace nada" y no se ve por que. */
#group-motivo-perdida:not([hidden]) {
    animation: ui-entrada 240ms var(--curva) both;
}

/* ==========================================================
   6. TARJETAS DE RESUMEN
   ========================================================== */

.consultas-resumen,
.clientes-resumen {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(162px, 1fr));
    gap: var(--sp-3);
    margin-bottom: var(--sp-5);
}

.resumen-item {
    padding: var(--sp-4) !important;
    border-radius: var(--r-md) !important;
    overflow: hidden;
    transition: transform var(--t-medio) var(--curva), box-shadow var(--t-medio) var(--curva);
}

/* La barra de color va abajo a lo ancho, no como borde izquierdo:
   ancla la tarjeta y deja el texto sin sangria rara. */
.resumen-item::before {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 2px;
    background: linear-gradient(90deg, var(--triage-color, var(--primary)), transparent 85%);
}

.resumen-item:hover {
    transform: translateY(-3px);
    box-shadow: var(--elev-3) !important;
}

.resumen-item strong {
    display: block;
    font-size: 1.6rem !important;
    font-weight: 800;
    line-height: 1.05;
    letter-spacing: -0.03em;
    color: var(--text-main);
}

.resumen-item span {
    display: block;
    margin-top: var(--sp-2);
    font-size: 0.76rem;
    font-weight: 700;
    color: var(--triage-color, var(--text-main));
}

.resumen-item small {
    display: block;
    margin-top: 3px;
    font-size: 0.68rem;
    color: var(--text-dim);
}

/* ==========================================================
   7. NAVEGACION

   La pastilla activa se desliza: el fondo es un pseudo-elemento
   que anima su opacidad y escala, no un cambio brusco de color.
   ========================================================== */

.main-tabs {
    gap: var(--sp-1) !important;
    padding: var(--sp-1) !important;
    border-radius: var(--r-md) !important;
}

.main-tabs .tab-btn {
    position: relative;
    display: inline-flex !important;
    align-items: center;
    gap: var(--sp-2);
    height: 42px;
    padding: 0 var(--sp-5) !important;
    border: none !important;
    border-radius: var(--r-sm) !important;
    background: transparent !important;
    font-size: 0.82rem !important;
    font-weight: 700 !important;
    color: var(--text-muted) !important;
    white-space: nowrap;
    box-shadow: none !important;
    transition:
        color var(--t-medio) var(--curva),
        background var(--t-medio) var(--curva),
        box-shadow var(--t-medio) var(--curva) !important;
}

/* El fondo va en el propio boton, no en un pseudo-elemento: index.css
   ya declara .tab-btn.active y competir por la opacidad de un ::before
   dejaba la pastilla invisible. Se anima el background directamente. */
.main-tabs .tab-btn:hover:not(.active) {
    color: var(--text-main) !important;
    background: rgba(255, 255, 255, 0.045) !important;
}

/* La pestaña de Estudio no usa un glifo de Font Awesome: es la marca
   de la casa (S/C) como texto, en un <i> sin clase fa-* para no
   heredar ningun icono ajeno. font-style normal para que no salga en
   cursiva, que es lo que el navegador le pone a <i> por defecto. */
.tab-ico-sc {
    font-style: normal;
    font-weight: 800;
    letter-spacing: -0.03em;
}

.main-tabs .tab-btn.active {
    color: var(--primary) !important;
    background: linear-gradient(180deg, rgba(var(--acento-rgb), 0.2), rgba(var(--acento-rgb), 0.07)) !important;
    box-shadow:
        inset 0 0 0 1px rgba(var(--acento-rgb), 0.32),
        inset 0 1px 0 rgba(255, 255, 255, 0.1),
        0 4px 18px rgba(var(--acento-rgb), 0.16) !important;
}

/* Subrayado de la pestana activa: crece desde el centro */
.main-tabs .tab-btn::after {
    content: '';
    position: absolute;
    left: 50%;
    right: 50%;
    bottom: 5px;
    height: 2px;
    border-radius: 2px;
    background: var(--primary);
    box-shadow: 0 0 10px rgba(var(--acento-rgb), 0.7);
    transition: left var(--t-medio) var(--curva), right var(--t-medio) var(--curva);
}

.main-tabs .tab-btn.active::after {
    left: 26%;
    right: 26%;
}

.main-tabs .tab-badge {
    padding: 2px 7px;
    border-radius: var(--radius-full);
    font-size: 0.66rem;
    font-weight: 800;
    background: rgba(255, 255, 255, 0.09);
    color: var(--text-main);
    transition: background var(--t-medio) var(--curva), color var(--t-medio) var(--curva);
}

.main-tabs .tab-btn.active .tab-badge {
    background: var(--primary);
    color: #06231a;
}

/* ==========================================================
   8. BARRA DE ETAPAS

   Reemplaza a las columnas del tablero. Cada pastilla filtra la
   grilla y muestra cuantas consultas hay en esa etapa.
   ========================================================== */

.barra-etapas {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
    margin-bottom: var(--sp-4);
}

.etapa-pill {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    height: 36px;
    padding: 0 var(--sp-3) 0 var(--sp-3);
    border-radius: var(--radius-full);
    border: 1px solid var(--borde-luz);
    background: var(--surf-1);
    color: var(--text-muted);
    font-size: 0.78rem;
    font-weight: 700;
    font-family: var(--font-family);
    cursor: pointer;
    white-space: nowrap;
    box-shadow: var(--elev-1);
    transition:
        border-color var(--t-medio) var(--curva),
        color var(--t-medio) var(--curva),
        background var(--t-medio) var(--curva),
        transform var(--t-rapido) var(--curva);
}

.etapa-punto {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--estado-color, var(--primary));
    box-shadow: 0 0 8px var(--estado-color, var(--primary));
}

.etapa-pill .count-badge {
    min-width: 22px;
    padding: 2px 7px;
    border-radius: var(--radius-full);
    font-size: 0.68rem;
    font-weight: 800;
    text-align: center;
    background: rgba(255, 255, 255, 0.07);
    color: var(--text-main);
}

.etapa-pill:hover {
    color: var(--text-main);
    border-color: rgba(255, 255, 255, 0.2);
    transform: translateY(-1px);
}

.etapa-pill.activa {
    color: var(--estado-color, var(--primary));
    border-color: color-mix(in srgb, var(--estado-color, var(--primary)) 45%, transparent);
    background:
        linear-gradient(180deg,
            color-mix(in srgb, var(--estado-color, var(--primary)) 16%, transparent),
            color-mix(in srgb, var(--estado-color, var(--primary)) 5%, transparent)),
        var(--surf-1);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.08),
        0 0 18px color-mix(in srgb, var(--estado-color, var(--primary)) 18%, transparent);
}

.etapa-pill.activa .count-badge {
    background: color-mix(in srgb, var(--estado-color, var(--primary)) 25%, transparent);
    color: var(--estado-color, var(--primary));
}

/* ==========================================================
   8b. GRILLA DE CONSULTAS

   Una fila por consulta. Es una tabla, pero construida con grid
   para que las columnas se alineen entre cabecera y cuerpo sin
   depender del ancho del contenido de cada celda.
   ========================================================== */

.grid-consultas {
    --col-cliente: minmax(210px, 1.7fr);
    --col-chip: minmax(130px, 1fr);
    --col-monto: minmax(110px, 0.8fr);
    --col-etapa: minmax(160px, 1.05fr);
    --col-resp: minmax(120px, 0.9fr);
    --col-fecha: 96px;
    --col-acc: 122px;

    overflow: hidden;
    border-radius: var(--r-lg);
    border: 1px solid var(--borde-luz);
    background: var(--surf-1);
    box-shadow: var(--elev-2);
}

.grid-head,
.grid-fila {
    display: grid;
    grid-template-columns:
        var(--col-cliente) var(--col-chip) var(--col-chip) var(--col-chip)
        var(--col-monto) var(--col-etapa) var(--col-resp) var(--col-fecha) var(--col-acc);
    align-items: center;
    gap: var(--sp-3);
    padding: 0 var(--sp-4);
}

/* Cabecera fija: al scrollear la lista larga, los rotulos quedan */
.grid-head {
    position: sticky;
    top: 0;
    z-index: 3;
    height: 44px;
    background: var(--surf-2);
    border-bottom: 1px solid var(--borde-luz);
    box-shadow: 0 1px 0 rgba(255, 255, 255, 0.04);
}

.grid-th {
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 0.68rem;
    font-weight: 800;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--text-dim);
    user-select: none;
    transition: color var(--t-rapido) var(--curva);
}

.grid-th.ordenable { cursor: pointer; }

.grid-th.ordenable:hover,
.grid-th.ordenando { color: var(--primary); }

.orden-icono {
    font-size: 0.62rem;
    opacity: 0.35;
    transition: opacity var(--t-rapido) var(--curva);
}

.orden-icono.activo { opacity: 1; }

.grid-th:hover .orden-icono { opacity: 0.8; }

/* La fila lleva el color de su etapa: barra a la izquierda y, al
   pasar por encima, un lavado del mismo color. Es lo que permite
   leer el estado de toda la cartera barriendo con la vista. */
.grid-fila {
    position: relative;
    min-height: 58px;
    cursor: pointer;
    border-bottom: 1px solid rgba(255, 255, 255, 0.045);
    background:
        linear-gradient(90deg,
            color-mix(in srgb, var(--estado-color, var(--primary)) 7%, transparent) 0%,
            transparent 22%);
    transition: background var(--t-rapido) var(--curva);
    animation: ui-entrada 300ms var(--curva) both;
}

.grid-fila::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: var(--estado-color, var(--primary));
    box-shadow: 0 0 12px color-mix(in srgb, var(--estado-color, var(--primary)) 55%, transparent);
}

.grid-fila:last-child { border-bottom: none; }

.grid-fila:hover {
    background:
        linear-gradient(90deg,
            color-mix(in srgb, var(--estado-color, var(--primary)) 14%, transparent) 0%,
            color-mix(in srgb, var(--estado-color, var(--primary)) 4%, transparent) 45%,
            transparent 75%);
}

/* Cascada de entrada de las primeras filas */
.grid-fila:nth-child(1) { animation-delay: 20ms; }
.grid-fila:nth-child(2) { animation-delay: 45ms; }
.grid-fila:nth-child(3) { animation-delay: 70ms; }
.grid-fila:nth-child(4) { animation-delay: 95ms; }
.grid-fila:nth-child(5) { animation-delay: 120ms; }
.grid-fila:nth-child(n+6) { animation-delay: 145ms; }

.grid-td {
    min-width: 0;
    font-size: 0.8rem;
    color: var(--text-muted);
    overflow: hidden;
}

.celda-cliente {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.fila-nombre {
    font-size: 0.86rem;
    font-weight: 800;
    letter-spacing: -0.01em;
    color: var(--text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.fila-sub {
    font-size: 0.7rem;
    color: var(--text-dim);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* El rubro de la empresa. Estilo base para el telefono, donde la
   bandeja sigue siendo una tabla; en escritorio la tarjeta lo
   reacomoda (ver escritorio.css). */
.fila-rubro {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    max-width: 100%;
    font-size: 0.7rem;
    font-weight: 600;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.fila-rubro i {
    flex: none;
    font-size: 0.62rem;
    opacity: 0.55;
}

.celda-monto {
    font-weight: 700;
    color: var(--text-main);
    font-variant-numeric: tabular-nums;
}

.celda-fecha {
    display: flex;
    flex-direction: column;
    gap: 1px;
    font-variant-numeric: tabular-nums;
}

.celda-responsable {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* El select de etapa se lee como texto hasta que se lo apunta */
.etapa-select {
    width: 100%;
    height: 32px;
    padding: 0 var(--sp-2);
    border-radius: var(--r-sm);
    border: 1px solid transparent;
    background: color-mix(in srgb, var(--estado-color, var(--primary)) 11%, transparent);
    color: var(--estado-color, var(--primary));
    font-family: var(--font-family);
    font-size: 0.73rem;
    font-weight: 700;
    cursor: pointer;
    transition: border-color var(--t-rapido) var(--curva), background var(--t-rapido) var(--curva);
}

.etapa-select:hover,
.etapa-select:focus {
    border-color: color-mix(in srgb, var(--estado-color, var(--primary)) 45%, transparent);
    background: color-mix(in srgb, var(--estado-color, var(--primary)) 18%, transparent);
    outline: none;
}

/* Por que canal se contactó al lead, al lado del select de etapa.
   Verde = WhatsApp, azul = email; son los dos únicos canales que
   sella marcarContactado() (ver canalContactoBadge en js/leads.js). */
.canal-contacto-ico {
    flex: none;
    font-size: 0.72rem;
    margin-left: 2px;
}

.canal-contacto-ico.canal-contacto-whatsapp {
    color: #25d366;
}

.canal-contacto-ico.canal-contacto-email {
    color: #2f8fef;
}

/* Quién mandó el mensaje (ver LeadsManager.quienContactoBadge) — solo
   el primer nombre, chico y mudo al lado del ícono de canal. No es un
   link ni repite el color del canal a propósito: es un dato secundario,
   no otra pastilla compitiendo por atención. */
.quien-contacto-ico {
    flex: none;
    font-size: 0.68rem;
    color: var(--text-muted);
    margin-left: 3px;
    white-space: nowrap;
}

.celda-acciones {
    display: flex;
    gap: 4px;
    justify-content: flex-end;
}

.btn-fila {
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    border-radius: 9px;
    border: 1px solid var(--borde-luz);
    background: var(--surf-2);
    color: var(--text-muted);
    font-size: 0.76rem;
    cursor: pointer;
    text-decoration: none;
    transition:
        color var(--t-rapido) var(--curva),
        border-color var(--t-rapido) var(--curva),
        transform var(--t-rapido) var(--curva);
}

.btn-fila:hover {
    color: var(--primary);
    border-color: rgba(var(--acento-rgb), 0.45);
    transform: translateY(-1px);
}

/* En reposo la fila informa; al apuntarla, ofrece acciones */
@media (hover: hover) and (pointer: fine) {
    .celda-acciones { opacity: 0.35; transition: opacity var(--t-medio) var(--curva); }
    .grid-fila:hover .celda-acciones { opacity: 1; }
}

.grid-vacia {
    padding: var(--sp-7) var(--sp-5);
    text-align: center;
    border-radius: var(--r-lg);
    border: 1px dashed rgba(255, 255, 255, 0.1);
    background: var(--surf-1);
}

.grid-vacia i {
    display: grid;
    place-items: center;
    width: 58px;
    height: 58px;
    margin: 0 auto var(--sp-3);
    font-size: 1.35rem;
    color: var(--primary);
    border-radius: 17px;
    background: rgba(var(--acento-rgb), 0.08);
    border: 1px solid rgba(var(--acento-rgb), 0.18);
}

.grid-vacia h4 {
    margin: 0 0 var(--sp-2);
    font-size: 1rem;
    color: var(--text-main);
}

.grid-vacia p {
    margin: 0;
    font-size: 0.83rem;
    color: var(--text-muted);
}

/* ==========================================================
   9. CHIPS DE TRIAGE

   Canal, tipo y prioridad dentro de cada fila de la grilla.
   ========================================================== */

.triage-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
}

.triage-chip {
    font-size: 0.66rem !important;
    font-weight: 700;
    line-height: 1;
    padding: 5px 9px;
    border-radius: var(--radius-full);
    white-space: nowrap;
    color: var(--triage-color, #8b9a95);
    background: color-mix(in srgb, var(--triage-color, #8b9a95) 13%, transparent);
    border: 1px solid color-mix(in srgb, var(--triage-color, #8b9a95) 30%, transparent);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
}

/* Barras de scroll finas y de marca */
.table-responsive::-webkit-scrollbar,
.grid-body::-webkit-scrollbar {
    width: 8px;
    height: 10px;
}

.table-responsive::-webkit-scrollbar-track,
.grid-body::-webkit-scrollbar-track {
    background: rgba(255, 255, 255, 0.03);
    border-radius: var(--radius-full);
}

.table-responsive::-webkit-scrollbar-thumb,
.grid-body::-webkit-scrollbar-thumb {
    background: rgba(255, 255, 255, 0.13);
    border-radius: var(--radius-full);
    transition: background var(--t-medio) var(--curva);
}

.table-responsive::-webkit-scrollbar-thumb:hover,
.grid-body::-webkit-scrollbar-thumb:hover {
    background: var(--primary-dim);
}


/* ==========================================================
   10. TABLAS
   ========================================================== */

.custom-table th {
    position: sticky;
    top: 0;
    z-index: 1;
    background: var(--surf-2) !important;
    font-size: 0.7rem !important;
    font-weight: 800 !important;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--text-dim) !important;
    white-space: nowrap;
    border-bottom: 1px solid var(--borde-luz) !important;
}

.custom-table td {
    font-size: 0.82rem !important;
    vertical-align: middle;
    border-bottom: 1px solid rgba(255, 255, 255, 0.045) !important;
}

.custom-table tbody tr {
    transition: background var(--t-rapido) var(--curva);
}

.custom-table tbody tr:hover {
    background: rgba(var(--acento-rgb), 0.045) !important;
}

/* ==========================================================
   11. CARTERA DE PROYECTOS
   ========================================================== */

.historial-head {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--sp-3);
    padding-bottom: var(--sp-3);
    margin-bottom: var(--sp-4);
    border-bottom: 1px solid var(--borde-luz);
}

.historial-head h3 i {
    color: var(--primary) !important;
    margin-right: var(--sp-2);
}

.historial-filtros {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2);
    align-items: center;
}

.historial-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: var(--sp-3);
}

/* ==========================================================
   11b. CARTERA DE CLIENTES

   Fichas en vez de tabla: siete columnas obligaban a scroll
   lateral y lo que se consulta de un cliente se lee mejor junto.
   ========================================================== */

.clientes-wrap {
    max-width: 1180px;
    margin: 0 auto;
}

.buscador-clientes { min-width: 240px; }

.clientes-lista {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: var(--sp-3);
}

.cliente-ficha {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--sp-3);
    padding: var(--sp-4);
    border-radius: var(--r-lg);
    border: 1px solid var(--borde-luz);
    background:
        linear-gradient(180deg, rgba(255, 255, 255, 0.035) 0%, rgba(255, 255, 255, 0) 42%),
        var(--surf-1);
    box-shadow: var(--elev-2);
    overflow: hidden;
    animation: ui-entrada 340ms var(--curva) both;
    transition: transform var(--t-medio) var(--curva), box-shadow var(--t-medio) var(--curva), border-color var(--t-medio) var(--curva);
}

.cliente-ficha::after {
    content: '';
    position: absolute;
    top: 0;
    left: 12%;
    right: 12%;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.22), transparent);
}

.cliente-ficha:hover {
    transform: translateY(-3px);
    border-color: rgba(var(--acento-rgb), 0.28);
    box-shadow: var(--elev-3);
}

.cliente-ficha:nth-child(1) { animation-delay: 30ms; }
.cliente-ficha:nth-child(2) { animation-delay: 65ms; }
.cliente-ficha:nth-child(3) { animation-delay: 100ms; }
.cliente-ficha:nth-child(4) { animation-delay: 135ms; }
.cliente-ficha:nth-child(n+5) { animation-delay: 170ms; }

.cliente-head {
    display: flex;
    align-items: center;
    gap: var(--sp-3);
}

.cliente-avatar {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    border-radius: 13px;
    font-size: 0.86rem;
    font-weight: 800;
    letter-spacing: 0.02em;
    color: var(--primary);
    background: linear-gradient(180deg, rgba(var(--acento-rgb), 0.18), rgba(var(--acento-rgb), 0.06));
    border: 1px solid rgba(var(--acento-rgb), 0.25);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
}

.cliente-id {
    min-width: 0;
    flex: 1;
}

.cliente-id h4 {
    margin: 0;
    font-size: 0.92rem;
    font-weight: 800;
    letter-spacing: -0.015em;
    color: var(--text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cliente-numero {
    display: inline-block;
    margin-top: 3px;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    color: var(--primary);
    font-variant-numeric: tabular-nums;
}

.cliente-tag {
    flex: 0 0 auto;
    padding: 4px 9px;
    border-radius: var(--radius-full);
    font-size: 0.64rem;
    font-weight: 700;
    color: var(--vivo-violeta);
    background: rgba(167, 139, 250, 0.12);
    border: 1px solid rgba(167, 139, 250, 0.3);
}

.cliente-datos {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: var(--sp-3);
    margin: 0;
    padding: var(--sp-3) 0;
    border-top: 1px solid rgba(255, 255, 255, 0.05);
    border-bottom: 1px solid rgba(255, 255, 255, 0.05);
}

.cliente-datos dt {
    font-size: 0.64rem;
    font-weight: 800;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--text-dim);
}

.cliente-datos dd {
    margin: 4px 0 0;
    font-size: 1.05rem;
    font-weight: 800;
    color: var(--text-main);
    font-variant-numeric: tabular-nums;
}

.cliente-datos .cliente-monto {
    font-size: 0.9rem;
    color: var(--primary);
}

.cliente-ultimo {
    margin: 0;
    font-size: 0.75rem;
    color: var(--text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.cliente-ultimo i {
    color: var(--text-dim);
    margin-right: 5px;
}

.cliente-acciones {
    display: flex;
    align-items: center;
    gap: var(--sp-2);
    margin-top: auto;
}

.cliente-tel {
    font-size: 0.74rem;
    color: var(--text-dim);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ==========================================================
   12. ESTADO VACIO
   ========================================================== */

.tabla-vacia {
    text-align: center;
    padding: var(--sp-7) var(--sp-5);
    max-width: 54ch;
    margin: 0 auto;
}

.tabla-vacia > i {
    display: grid;
    place-items: center;
    width: 62px;
    height: 62px;
    margin: 0 auto var(--sp-4);
    font-size: 1.5rem;
    color: var(--primary);
    border-radius: 18px;
    background: rgba(var(--acento-rgb), 0.08);
    border: 1px solid rgba(var(--acento-rgb), 0.18);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.07), 0 0 32px rgba(var(--acento-rgb), 0.1);
}

.tabla-vacia h4 {
    margin: 0 0 var(--sp-2);
    font-size: 1.02rem;
    font-weight: 800;
    letter-spacing: -0.02em;
    color: var(--text-main);
}

.tabla-vacia p {
    margin: 0 0 var(--sp-5);
    font-size: 0.84rem;
    line-height: 1.65;
    color: var(--text-muted);
}

.tabla-vacia strong {
    color: var(--primary);
}

.tabla-vacia .btn {
    display: inline-flex !important;
    width: auto !important;
    margin: 0 auto !important;
}

/* ==========================================================
   13. BITACORA Y HORAS DE USO
   ========================================================== */

.bitacora-panel {
    padding: var(--sp-5) !important;
}

.bitacora-resumen span,
.bitacora-resumen a {
    background: rgba(var(--acento-rgb), 0.09);
    border: 1px solid rgba(var(--acento-rgb), 0.2);
    border-radius: var(--r-sm);
    transition: background var(--t-medio) var(--curva), transform var(--t-medio) var(--curva);
}

.bitacora-resumen a:hover {
    background: rgba(var(--acento-rgb), 0.16);
    transform: translateY(-1px);
}

.bitacora-nota {
    border-radius: var(--r-sm);
    border: 1px solid var(--borde-luz);
    background: var(--surf-2);
    transition: border-color var(--t-medio) var(--curva);
}

.bitacora-nota:hover {
    border-color: rgba(var(--acento-rgb), 0.28);
}

.uso-totales > div {
    border-radius: var(--r-md);
    background: linear-gradient(180deg, rgba(var(--acento-rgb), 0.1), rgba(var(--acento-rgb), 0.03));
    border: 1px solid rgba(var(--acento-rgb), 0.18);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
}

.uso-barra-fill {
    background: linear-gradient(180deg, #4ff0a4, var(--primary) 60%, #17835a) !important;
    box-shadow: 0 0 14px rgba(var(--acento-rgb), 0.28);
    transition: height var(--t-lento) var(--curva) !important;
}

/* ==========================================================
   14. MOVIMIENTO

   Nada aparece de golpe. Las pestanas entran con un
   desplazamiento corto; las tarjetas, en cascada.
   ========================================================== */

@keyframes ui-entrada {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes ui-entrada-lateral {
    from { opacity: 0; transform: translateX(-14px); }
    to   { opacity: 1; transform: translateX(0); }
}

@keyframes ui-brillo {
    from { background-position: -180% 0; }
    to   { background-position: 180% 0; }
}

.tab-content.active {
    animation: ui-entrada var(--t-lento) var(--curva) both;
}

/* Cascada: cada bloque de la pantalla entra un poco despues que el
   anterior. Es lo que separa "aparecio la pagina" de "se armo". */
.tab-content.active > .section-head { animation: ui-entrada 380ms var(--curva) both; }
.tab-content.active > .consultas-resumen { animation: ui-entrada 380ms var(--curva) 60ms both; }
.tab-content.active > .barra-filtros { animation: ui-entrada 380ms var(--curva) 110ms both; }
.tab-content.active > .barra-etapas { animation: ui-entrada 380ms var(--curva) 160ms both; }
.tab-content.active > #consultas-grid { animation: ui-entrada 380ms var(--curva) 200ms both; }

/* Las pastillas de etapa entran de izquierda a derecha */
.etapa-pill {
    animation: ui-entrada-lateral 420ms var(--curva) both;
}

.etapa-pill:nth-child(1) { animation-delay: 40ms; }
.etapa-pill:nth-child(2) { animation-delay: 80ms; }
.etapa-pill:nth-child(3) { animation-delay: 120ms; }
.etapa-pill:nth-child(4) { animation-delay: 160ms; }
.etapa-pill:nth-child(5) { animation-delay: 200ms; }
.etapa-pill:nth-child(n+6) { animation-delay: 240ms; }

/* Tarjetas de resumen y filas de tabla */
.resumen-item { animation: ui-entrada 360ms var(--curva) both; }
.resumen-item:nth-child(1) { animation-delay: 30ms; }
.resumen-item:nth-child(2) { animation-delay: 70ms; }
.resumen-item:nth-child(3) { animation-delay: 110ms; }
.resumen-item:nth-child(4) { animation-delay: 150ms; }
.resumen-item:nth-child(n+5) { animation-delay: 190ms; }

.custom-table tbody tr { animation: ui-entrada 300ms var(--curva) both; }
.custom-table tbody tr:nth-child(1) { animation-delay: 20ms; }
.custom-table tbody tr:nth-child(2) { animation-delay: 50ms; }
.custom-table tbody tr:nth-child(3) { animation-delay: 80ms; }
.custom-table tbody tr:nth-child(4) { animation-delay: 110ms; }
.custom-table tbody tr:nth-child(n+5) { animation-delay: 140ms; }

/* Barrido para estados de carga */
.cargando {
    background: linear-gradient(90deg,
        var(--surf-2) 25%, var(--surf-3) 50%, var(--surf-2) 75%);
    background-size: 200% 100%;
    animation: ui-brillo 1.4s linear infinite;
    border-radius: var(--r-sm);
    color: transparent !important;
}

/* ==========================================================
   15. TELEFONO
   ========================================================== */

/* Tramo intermedio: entre 561 y 768px hay ancho de sobra para que la
   accion principal conserve su tamano natural. Estirarla a todo lo
   ancho recien tiene sentido cuando el pulgar no llega de una punta a
   la otra. */
@media (min-width: 561px) and (max-width: 768px) {
    .section-head__acciones { width: auto; }
    .section-head { align-items: flex-end; }
}

/* Debajo de 560px la accion principal si ocupa el ancho disponible */
@media (max-width: 560px) {
    .section-head__acciones .btn-primary-3d,
    .section-head__acciones .btn-primary {
        flex: 1;
    }
}

@media (max-width: 768px) {

    body::before { background-size: 18px 18px; }

    .section-head {
        align-items: stretch;
        gap: var(--sp-3);
        padding-bottom: var(--sp-3);
        margin-bottom: var(--sp-4);
    }

    .section-head__acciones { width: 100%; }

    .section-head__acciones .btn-primary-3d,
    .section-head__acciones .btn-primary {
        height: var(--control-h-mobile) !important;
        min-height: var(--control-h-mobile) !important;
    }

    .section-head__acciones .btn-icono {
        width: var(--control-h-mobile) !important;
        height: var(--control-h-mobile) !important;
        min-height: var(--control-h-mobile) !important;
    }

    /* Filtros plegados: en 375px, cinco selects abiertos empujaban
       el tablero fuera de la primera pantalla. */
    .filtros-toggle {
        display: flex !important;
        align-items: center;
        justify-content: space-between;
        gap: var(--sp-2);
        width: 100%;
        height: var(--control-h-mobile);
        padding: 0 var(--sp-4);
        margin-bottom: var(--sp-3);
        background: var(--surf-1);
        border: 1px solid var(--borde-luz);
        border-radius: var(--r-sm);
        box-shadow: var(--elev-1);
        color: var(--text-main);
        font-size: 0.84rem;
        font-weight: 700;
        cursor: pointer;
        transition: border-color var(--t-medio) var(--curva), color var(--t-medio) var(--curva);
    }

    .filtros-toggle[aria-expanded="true"] {
        border-color: rgba(var(--acento-rgb), 0.5);
        color: var(--primary);
        box-shadow: var(--halo);
    }

    .filtros-toggle .filtros-cuenta {
        padding: 2px 8px;
        border-radius: var(--radius-full);
        background: var(--primary);
        color: #06231a;
        font-size: 0.68rem;
        font-weight: 800;
    }

    /* El estado plegado lo fija el CSS, no el JS: asi no depende de
       cuando corra el script ni de que el telefono rote. */
    .barra-filtros {
        display: none !important;
        grid-template-columns: 1fr;
        gap: var(--sp-2);
    }

    .barra-filtros.filtros-abiertos {
        display: grid !important;
        animation: ui-entrada 300ms var(--curva) both;
    }

    .barra-filtros .buscador,
    .barra-filtros .select-field,
    .barra-filtros .btn {
        height: var(--control-h-mobile) !important;
        min-height: var(--control-h-mobile) !important;
        font-size: 0.86rem !important;
    }

    .consultas-resumen,
    .clientes-resumen {
        grid-template-columns: 1fr 1fr;
        gap: var(--sp-2);
    }

    .resumen-item { padding: var(--sp-3) !important; }
    .resumen-item strong { font-size: 1.28rem !important; }

    /* La barra de etapas se desliza de costado en vez de envolver.
       El degradado del borde derecho avisa que hay mas etapas: sin el,
       la ultima pastilla queda cortada al ras y parece un error. */
    .barra-etapas {
        position: relative;
        flex-wrap: nowrap;
        overflow-x: auto;
        margin: 0 calc(-1 * var(--sp-3)) var(--sp-3);
        padding: 0 var(--sp-3) var(--sp-2);
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
        scroll-snap-type: x proximity;
        mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 28px), transparent 100%);
        -webkit-mask-image: linear-gradient(90deg, #000 0, #000 calc(100% - 28px), transparent 100%);
    }

    .barra-etapas::-webkit-scrollbar { display: none; }

    .etapa-pill { scroll-snap-align: start; }

    /* La grilla deja de ser grilla: cada consulta pasa a ser una
       ficha. Nueve columnas en 375px serian ilegibles, y una tabla
       con scroll lateral obliga a ir y volver por cada fila. */
    .grid-head { display: none; }

    .grid-consultas {
        background: transparent;
        border: none;
        box-shadow: none;
        overflow: visible;
    }

    /* Cada celda tiene su propia area. Compartir area entre celdas y
       separarlas con justify-self no alcanza: los items se apilan en
       el mismo track y se superponen. */
    .grid-fila {
        display: grid;
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr);
        grid-template-areas:
            'cliente cliente etapa'
            'canal   tipo    prio'
            'monto   resp    fecha'
            'acc     acc     acc';
        gap: var(--sp-2);
        padding: var(--sp-3) var(--sp-3) var(--sp-3) var(--sp-4);
        margin-bottom: var(--sp-2);
        min-height: 0;
        border: 1px solid var(--borde-luz);
        border-radius: var(--r-md);
        background:
            linear-gradient(180deg, rgba(255, 255, 255, 0.03), transparent 45%),
            var(--surf-1);
        box-shadow: var(--elev-1);
    }

    .grid-fila::before { border-radius: var(--r-md) 0 0 var(--r-md); }

    .celda-cliente { grid-area: cliente; }
    .celda-etapa   { grid-area: etapa; justify-self: end; }

    .grid-fila > .grid-td:nth-child(2) { grid-area: canal; }
    .grid-fila > .grid-td:nth-child(3) { grid-area: tipo; }
    .grid-fila > .grid-td:nth-child(4) { grid-area: prio; }

    /* Los chips no pueden ensanchar su columna ni recortarse feo */
    .grid-fila > .grid-td:nth-child(2) .triage-chip,
    .grid-fila > .grid-td:nth-child(3) .triage-chip,
    .grid-fila > .grid-td:nth-child(4) .triage-chip {
        display: block;
        overflow: hidden;
        text-overflow: ellipsis;
        text-align: center;
    }

    .celda-monto       { grid-area: monto; font-size: 0.74rem; }
    .celda-responsable { grid-area: resp;  font-size: 0.74rem; text-align: center; }

    .celda-fecha {
        grid-area: fecha;
        flex-direction: row;
        justify-content: flex-end;
        gap: var(--sp-1);
        font-size: 0.74rem;
    }

    .celda-acciones {
        grid-area: acc;
        justify-content: stretch;
        opacity: 1;
        padding-top: var(--sp-1);
        border-top: 1px solid rgba(255, 255, 255, 0.05);
    }

    .celda-acciones .btn-fila { flex: 1; }

    .btn-fila {
        width: auto;
        height: var(--control-h-mobile);
    }

    .etapa-select { width: 100%; font-size: 0.7rem; }

    /* Una etapa por pantalla, se pasa deslizando */
    .historial-head { flex-direction: column; align-items: stretch; }

    .historial-filtros { display: grid; grid-template-columns: 1fr; }

    .historial-filtros .select-field,
    .historial-filtros .btn {
        height: var(--control-h-mobile) !important;
        min-height: var(--control-h-mobile) !important;
        width: 100%;
    }

    .historial-grid { grid-template-columns: 1fr; }

    .clientes-lista { grid-template-columns: 1fr; }

    /* Grid y no flex: movil.css declara `select { max-width: 100%
       !important }`, asi que el select ignora cualquier limite y en
       flex se lleva la fila entera aplastando al buscador. En grid el
       ancho lo fija el track, no el hijo. */
    #tab-clientes .section-head__acciones {
        display: grid;
        grid-template-columns: minmax(0, 1fr) minmax(0, 42%);
        gap: var(--sp-2);
        width: 100%;
    }

    .buscador-clientes,
    #clientes-orden {
        min-width: 0;
        width: 100%;
    }

    .bitacora-panel { padding: var(--sp-4) !important; }

    .tabla-vacia { padding: var(--sp-5) var(--sp-3); }
}

/* En desktop no hay plegado */
@media (min-width: 769px) {
    .filtros-toggle { display: none !important; }
    .barra-filtros { display: grid !important; }
}

/* ==========================================================
   16. ACCESIBILIDAD DE MOVIMIENTO

   Si el sistema pide menos movimiento, se apagan las animaciones
   pero NO las opacidades finales: nada puede quedar invisible.
   ========================================================== */

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-delay: 0ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }

}


/* ==========================================================
   BANDEJA ENTRANTE DE PROSPECCION

   El globito del boton de importar y la lista de empresas que
   trajeron los robots. Ver js/entrante.js.
   ========================================================== */

/* El boton es el ancla del globito, que le sale por la esquina.

   El z-index es lo que lo pone ADELANTE. El globito se sale del boton
   por arriba y por la derecha, justo encima del boton de al lado; sin
   nada declarado, el vecino se pinta despues —va despues en el HTML— y
   le tapaba la mitad al numero. */
#btn-abrir-csv {
    position: relative;
    overflow: visible !important;
    z-index: 3;
}

/* Rojo y no verde a proposito: el acento de la aplicacion es el
   color de "todo bien", y esto es una pila de trabajo sin hacer.
   Que se lea distinto de un boton contento. */
.entrante-globo {
    position: absolute;
    top: -6px;
    right: -6px;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    background: var(--danger);
    color: #fff;
    font-size: 11px;
    font-weight: 700;
    line-height: 1;
    /* El borde del color del fondo despega el globito del boton sin
       dibujar una sombra, que a este tamaño se ve sucia. */
    border: 2px solid var(--bg-surface);
    pointer-events: none;
    /* Arriba de todo lo que tenga alrededor: es un aviso, no un adorno. */
    z-index: 4;
}

.entrante-lista {
    max-height: 52vh;
    overflow-y: auto;
    margin: 16px 0;
    border: 1px solid var(--border-color);
    border-radius: 10px;
}

.entrante-fila {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 14px;
    border-bottom: 1px solid var(--border-color);
}

.entrante-fila:last-child { border-bottom: 0; }
.entrante-fila:hover { background: var(--bg-card); }

.entrante-fila__datos {
    flex: 1;
    min-width: 0;
    display: grid;
    /* La clasificacion tiene ancho minimo propio: "Certificado de
       seguridad roto" partido en tres lineas se lee como un error de
       maquetado y no como lo que es, la razon para llamar. */
    grid-template-columns: minmax(0, 1fr) auto auto minmax(150px, auto);
    align-items: baseline;
    gap: 4px 12px;
}

.entrante-fila__tel {
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.entrante-fila__email {
    color: var(--text-muted);
    font-size: 12px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.entrante-fila__interes {
    color: var(--primary);
    font-size: 13px;
    text-align: right;
}

/* El veredicto del calificador ocupa el ancho entero abajo: es el
   texto que se repite por telefono, tiene que leerse entero y no
   cortado con puntos suspensivos. */
.entrante-fila__notas {
    grid-column: 1 / -1;
    color: var(--text-dim);
    font-size: 12px;
}

.entrante-fila__acciones {
    display: flex;
    gap: 6px;
    flex-shrink: 0;
}

.entrante-fila__acciones [data-descartar]:hover {
    border-color: var(--danger) !important;
    color: var(--danger) !important;
}

.entrante-vacio {
    padding: 28px;
    text-align: center;
    color: var(--text-muted);
}


/* --- La lupa de prospeccion -------------------------------------
   Gira mientras el agente trabaja. Es el unico aviso de que la
   maquina esta ocupada, y con eso alcanza: el resultado llega al
   globito de al lado, que es donde hay que mirar. */

#btn-prospectar.esta-buscando {
    border-color: rgba(var(--acento-rgb), 0.45) !important;
    color: var(--primary) !important;
}

#btn-prospectar.esta-buscando i {
    animation: prospectar-gira 1.6s linear infinite;
}

@keyframes prospectar-gira {
    to { transform: rotate(360deg); }
}

.prospectar-estado {
    margin: 8px 0 0;
    color: var(--primary);
    font-size: 13px;
}

/* La animacion es decorativa: quien pidio no mirar animaciones no
   pierde nada, porque el texto de al lado dice lo mismo. */
@media (prefers-reduced-motion: reduce) {
    #btn-prospectar.esta-buscando i { animation: none; }
}

.prospectar-estimacion {
    margin: 6px 0 0;
    color: var(--text-muted);
    font-size: 12px;
}

/* El select de zona tiene que verse igual que los inputs de al lado:
   sin esto hereda el estilo del sistema operativo y desentona. */
#prospectar-zona {
    width: 100%;
}

/* Cuando el barrido se lleva media cuota mensual de GitHub, el numero
   deja de ser informativo y pasa a ser una advertencia. */
.prospectar-estimacion.es-mucho {
    color: var(--warning);
    font-weight: 600;
}

/* --- El buscador de prospectos ----------------------------------
   Es la pantalla donde se decide gastar horas de maquina y plata,
   asi que esta armada como un tablero: primero la liga, despues los
   rubros, despues donde, y al final los numeros pegados al boton.
   Nada de scroll para enterarse de lo que va a costar. */

/* Los !important no son pereza: legibilidad.css le pone a .modal-card
   un max-width de 650px con !important, y sin esto el buscador queda
   con el ancho de un dialogo de confirmacion. */
#prospectar-modal .prospectar-card {
    /* Ancho de escritorio, no de dialogo de confirmacion: son treinta
       rubros para leer. Apretarlos en 520px es lo que lo hacia ilegible. */
    width: min(1060px, 94vw) !important;
    max-width: none !important;
    max-height: 88vh !important;
    display: flex;
    flex-direction: column;
    padding: 26px 28px 22px !important;
    /* Scrollea la columna de rubros, no el modal entero: los numeros y
       el boton tienen que quedarse fijos donde el ojo los dejo. */
    overflow: hidden !important;
}

/* El cuerpo en dos columnas: a la izquierda que se elige, a la derecha
   donde y cuanto sale. Scrollea solo la izquierda, asi los numeros y el
   boton no se van nunca de la pantalla. */
.prosp-cuerpo {
    display: grid;
    grid-template-columns: 1.35fr 1fr;
    gap: 22px;
    min-height: 0;
    flex: 1;

    /* Ya no scrollea como un solo bloque: mas abajo cada columna se
       ocupa de si misma. Antes esto arrastraba tambien la lista de
       rubros —que ya tiene su propio scroll via .prosp-chips— cada
       vez que la columna de "Donde" no entraba, empujando la tarjeta
       "En esta PC" fuera de la vista por algo que no le pasaba a ella. */
    overflow: visible;
}

/* La columna derecha scrollea sola si no entra, sin arrastrar a la de
   rubros con ella: es la excepcion a "nunca dos scrolls anidados",
   puesta a conciencia (mismo arreglo que la version pagina, ver
   #prospectar-modal.es-pagina .prosp-col:last-child mas abajo). Si no
   entra nada se pierde, solo que ahora el scroll es mas corto: nunca
   hay que bajar mas de lo que la propia columna necesita. */
.prosp-col:last-child {
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-right: 4px;
}

/* El `min-width: 0` no es adorno: sin el, la columna de "Donde" no se
   veia.

   Un track de grid vale `min-width: auto`, o sea que no se achica mas
   que su contenido. Adentro esta la fila de categorias, que son chips
   `flex: none` con `nowrap` — no encogen ni se parten. Entre los dos
   inflaban la columna izquierda mas alla de su 1.35fr, empujaban la
   derecha fuera de la tarjeta, y como la tarjeta tiene
   `overflow: hidden` la zona y la cantidad quedaban invisibles: no
   habia forma de elegir donde buscar.

   Con esto la columna puede achicarse y el overflow-x de .prosp-cats
   hace lo suyo, que era la idea desde el principio. */
.prosp-col {
    min-height: 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 18px;
}

.prosp-buscar { width: 100%; margin-bottom: 10px; }

/* El aviso de "ningun rubro dice eso". Ocupa las dos columnas de la
   grilla para que el texto no salga cortado a la mitad del ancho. */
.prosp-nada {
    grid-column: 1 / -1;
    margin: 0;
    padding: 18px 4px;
    color: var(--text-muted);
    font-size: 13px;
    line-height: 1.5;
}

.prosp-bloque { display: flex; flex-direction: column; min-height: 0; }

.prosp-titulo {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: 10px;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--text-muted);
}

.prosp-contador {
    text-transform: none;
    letter-spacing: 0;
    font-weight: 600;
    color: var(--primary);
}

/* Los rubros en columnas de renglones enteros, no en pastillas que se
   acomodan solas: en pastillas el ojo no encuentra donde sigue la
   lista, y era el reclamo principal de la version anterior. */
.prosp-chips {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 2px 10px;
    align-content: start;
    overflow-y: auto;
    padding-right: 6px;
    /* Que la lista use el alto que sobre, en vez de un recorte fijo que
       en una pantalla grande deja medio modal vacio. */
    flex: 1;
    min-height: 190px;
}

.prosp-chip {
    display: flex;
    align-items: center;
    gap: 9px;
    width: 100%;
    padding: 7px 9px;
    background: transparent;
    border: 0;
    border-radius: 8px;
    color: var(--text-muted);
    font-size: 13px;
    text-align: left;
    cursor: pointer;
}

.prosp-chip::before {
    content: '';
    flex: none;
    width: 15px;
    height: 15px;
    border: 1.5px solid var(--border-color);
    border-radius: 4px;
}

/* El renglon que explica coma vs barra. Chico y apagado: es una ayuda
   que se lee una vez y despues estorba, asi que no puede competir con
   el campo que esta explicando. */
.prosp-ayuda {
    margin: 6px 0 0;
    font-size: 11.5px;
    line-height: 1.5;
    color: var(--text-muted);
}
.prosp-ayuda b { color: var(--text-main); font-weight: 600; }
.prosp-ayuda code {
    font-size: 11px;
    color: var(--primary);
    background: color-mix(in srgb, var(--primary) 10%, transparent);
    padding: 1px 5px;
    border-radius: 4px;
}

.prosp-chip:hover { background: var(--bg-card); color: var(--text-main); }

.prosp-chip.elegido { color: var(--text-main); font-weight: 500; }

.prosp-chip.elegido::before {
    background: var(--primary);
    border-color: var(--primary);
    /* El tilde dibujado con el borde: dos lados de un cuadrado girado.
       Evita meter un SVG por cada uno de los treinta rubros. */
    background-image: linear-gradient(45deg, transparent 42%, #0b0f0d 42%, #0b0f0d 48%, transparent 48%),
                      linear-gradient(-45deg, transparent 42%, #0b0f0d 42%, #0b0f0d 48%, transparent 48%);
    background-size: 100% 55%, 100% 55%;
    background-position: 0 60%, 0 60%;
    background-repeat: no-repeat;
}

.prosp-acciones {
    display: flex;
    gap: 18px;
    margin: 12px 0 10px;
    padding-top: 12px;
    border-top: 1px solid var(--border-color);
}

#prospectar-rubro { width: 100%; }

.prosp-campo { margin-bottom: 14px; }
.prosp-campo:last-child { margin-bottom: 0; }

.prosp-campo label {
    display: block;
    margin-bottom: 6px;
    font-size: 12px;
    color: var(--text-muted);
}

.prosp-campo input, .prosp-campo select { width: 100%; }

.prosp-o {
    margin: 0 0 14px;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--text-muted);
    opacity: .7;
}

.prosp-tablero {
    margin-top: auto;
    padding: 16px;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 12px;
}

.prosp-stats { display: grid; grid-template-columns: 1fr 1fr; gap: 14px 10px; }

.prosp-stat b {
    display: block;
    font-size: 24px;
    line-height: 1.1;
    color: var(--text-main);
}

.prosp-stat span { font-size: 11px; color: var(--text-muted); }

/* Los minutos de GitHub son el techo real del sistema. La barra
   muestra en gris lo ya gastado del mes y en color lo que se lleva
   este barrido: si el color se pasa del borde, no entra. */
.prosp-barra {
    display: flex;
    height: 6px;
    margin: 16px 0 10px;
    background: var(--border-color);
    border-radius: 999px;
    overflow: hidden;
}

.prosp-barra i { display: block; height: 100%; transition: width .2s; }
#prosp-barra-usado { background: var(--text-muted); opacity: .55; }
#prosp-barra-pedido { background: var(--primary); }
.prosp-barra.es-mucho #prosp-barra-pedido { background: var(--warning); }

/* En pantallas chicas las dos columnas se apilan y la lista de rubros
   vuelve a una sola columna: dos columnas de trece pixeles en un
   celular es exactamente lo que no queremos. */
@media (max-width: 860px) {
    .prospectar-card { padding: 20px; }
    .prosp-cuerpo { grid-template-columns: 1fr; gap: 18px; }
    .prosp-chips { grid-template-columns: 1fr; max-height: 240px; }
    .prosp-tablero { margin-top: 0; }
}

/* El "mostrar mas" de la bandeja. Ocupa el ancho entero y va al final
   de la lista, donde el ojo llega despues de recorrerla. */
.entrante-mas {
    display: block;
    width: 100%;
    padding: 12px;
    background: transparent;
    border: 0;
    border-top: 1px solid var(--border-color);
    color: var(--text-muted);
    cursor: pointer;
    font-size: 13px;
}

.entrante-mas:hover {
    color: var(--primary);
    background: var(--bg-card);
}


/* --- El matcher -------------------------------------------------
   La bandeja del cazador de a una tarjeta por vez. El mazo es una
   pila apilada con position:absolute: las dos de arriba ocupan el
   mismo lugar y la de atras se ve un poco mas chica, que es lo que
   hace leer "hay mas". */

#matcher-modal .matcher-card {
    /* Como en el buscador: legibilidad.css le clava 650px con
       !important a todo .modal-card. */
    width: min(560px, 94vw) !important;
    max-width: none !important;
    padding: 20px !important;
    overflow: hidden !important;
}

.matcher-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 14px;
}

.matcher-head h3 { margin: 0; }
.matcher-head > div { display: flex; align-items: center; gap: 12px; }

.matcher-mazo {
    position: relative;
    /* Alto fijo, y de los grandes: la pila esta en position absolute,
       asi que sin alto propio colapsa. 540 entra en una notebook de
       768 con el modal, los botones y el pie. */
    /* Mas alto que ancho, como una tarjeta de verdad. En el celular es
       lo que hace que la captura del sitio, la nota y los datos entren
       sin que haya que scrollear adentro de la tarjeta. */
    /* Alto atado a la pantalla, no fijo ni flexible. Fijo empujaba los
       botones fuera del celular; flex no servia porque la tarjeta se
       mide por su contenido y entonces nunca crecia. El clamp da una
       tarjeta alta —que es como se lee una ficha— sin pasarse del alto
       util en ninguna pantalla. */
    height: clamp(400px, 62vh, 660px);
}

.matcher-carta {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    padding: 18px;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: 18px;
    box-shadow: 0 18px 40px -18px rgba(0, 0, 0, .8);
    overflow: hidden;
    /* La de atras asoma apenas por abajo y mas chica. */
    transform: scale(.96) translateY(10px);
    touch-action: none;
    cursor: grab;
    user-select: none;
}

.matcher-carta.frente { transform: none; z-index: 2; }
.matcher-carta.agarrada { cursor: grabbing; transition: none; }

/* La vuelta al centro y el vuelo usan la misma transicion; mientras
   el dedo esta apoyado se saca, o la tarjeta iria siempre atrasada
   respecto del puntero. */
.matcher-carta:not(.agarrada) { transition: transform .22s ease-out, opacity .22s; }

.matcher-carta.vuela-izq    { transform: translate(-140%, 40px) rotate(-24deg); opacity: 0; }
.matcher-carta.vuela-der    { transform: translate(140%, 40px) rotate(24deg);   opacity: 0; }
.matcher-carta.vuela-arriba { transform: translateY(-140%) scale(.9);           opacity: 0; }

/* Los sellos. La opacidad la maneja el arrastre por variable, asi
   que aparecen de a poco y no de golpe al cruzar el umbral. */
.matcher-sello {
    position: absolute;
    top: 22px;
    z-index: 3;
    padding: 6px 12px;
    border: 2px solid;
    border-radius: 8px;
    font-size: 15px;
    font-weight: 800;
    letter-spacing: .06em;
    pointer-events: none;
}

.matcher-sello--si  { right: 18px; color: var(--primary); border-color: var(--primary); transform: rotate(12deg);  opacity: var(--sello-si, 0); }
.matcher-sello--no  { left: 18px;  color: var(--text-muted); border-color: var(--text-muted); transform: rotate(-12deg); opacity: var(--sello-no, 0); }
.matcher-sello--top { left: 50%; margin-left: -52px; color: #facc15; border-color: #facc15; opacity: var(--sello-top, 0); }

.matcher-carta__top { display: flex; align-items: center; gap: 14px; }
.matcher-carta__top h4 { margin: 0; font-size: 19px; line-height: 1.2; }
.matcher-carta__top p { margin: 4px 0 0; font-size: 13px; color: var(--text-muted); }

.matcher-logo {
    flex: none;
    width: 54px;
    height: 54px;
    object-fit: contain;
    border-radius: 12px;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
}

.matcher-logo--letra {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 24px;
    font-weight: 700;
    color: var(--text-muted);
}

/* La nota del calificador. Es lo primero que tiene que saltar: el
   pulgar decide sobre este numero. */
.matcher-nota {
    margin: 16px 0;
    padding: 12px 14px;
    border-radius: 12px;
    border: 1px solid var(--border-color);
    background: var(--bg-card);
}

.matcher-nota b { display: block; font-size: 26px; line-height: 1.1; }
.matcher-nota span { font-size: 12px; color: var(--text-muted); }

.matcher-nota.es-oro   b { color: var(--primary); }
.matcher-nota.es-tibio b { color: var(--warning); }
.matcher-nota.es-frio  b { color: var(--text-muted); }

.matcher-datos { flex: 1; margin: 0; overflow-y: auto; }
.matcher-datos > div { margin-bottom: 10px; }
.matcher-datos dt { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--text-muted); }
/* Las notas traen la url completa y en un celular no entra en el
   ancho: sin esto la tarjeta se hace mas ancha que la pantalla. */
.matcher-datos dd { margin: 2px 0 0; font-size: 13px; line-height: 1.45; overflow-wrap: anywhere; }

.matcher-carta__pie {
    display: flex;
    gap: 16px;
    padding-top: 12px;
    border-top: 1px solid var(--border-color);
}

.matcher-sinweb { font-size: 12px; color: var(--text-muted); }

.matcher-botones {
    display: flex;
    justify-content: center;
    gap: 18px;
    margin-top: 16px;
}

.matcher-btn {
    width: 54px;
    height: 54px;
    border-radius: 50%;
    background: transparent;
    border: 1.5px solid var(--border-color);
    color: var(--text-muted);
    font-size: 19px;
    cursor: pointer;
    transition: transform .12s, border-color .12s, color .12s;
}

.matcher-btn:hover { transform: translateY(-2px); }
.matcher-btn.es-si:hover  { border-color: var(--primary); color: var(--primary); }
.matcher-btn.es-top { width: 46px; height: 46px; align-self: center; }
.matcher-btn.es-top:hover { border-color: #facc15; color: #facc15; }

.matcher-pie {
    margin: 12px 0 0;
    text-align: center;
    font-size: 12px;
    color: var(--text-muted);
}

.matcher-vacio {
    display: flex;
    flex-direction: column;
    justify-content: center;
    height: 100%;
    padding: 20px;
    text-align: center;
    color: var(--text-muted);
    line-height: 1.6;
}

/* El top 20. Lista y no tarjetas: acá ya no se decide nada, se lee. */
.matcher-top { height: 100%; margin: 0; padding: 0 4px 0 0; overflow-y: auto; list-style: none; counter-reset: top; }

.matcher-top li {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 0;
    border-bottom: 1px solid var(--border-color);
}

.matcher-top li::before {
    counter-increment: top;
    content: counter(top);
    flex: none;
    width: 22px;
    text-align: right;
    font-size: 12px;
    color: var(--text-muted);
}

.matcher-top .matcher-logo { width: 34px; height: 34px; border-radius: 8px; font-size: 15px; }
.matcher-top li > div { flex: 1; min-width: 0; }
.matcher-top li b { display: block; font-size: 14px; }
.matcher-top li span { font-size: 12px; color: var(--text-muted); }
.matcher-top li em { font-style: normal; font-size: 13px; font-weight: 600; }
.matcher-top .es-oro { color: var(--primary); }
.matcher-top .es-tibio { color: var(--warning); }
.matcher-top .es-frio { color: var(--text-muted); }

/* El sitio embebido. Alto fijo y no automatico: un iframe sin alto
   colapsa a cero y parece que el sitio no cargo. */
#matcher-sitio-modal .matcher-sitio {
    width: min(1100px, 96vw) !important;
    max-width: none !important;
    padding: 16px !important;
}

#matcher-sitio-marco {
    width: 100%;
    height: 70vh;
    border: 1px solid var(--border-color);
    border-radius: 12px;
    background: #fff;
}

.matcher-sitio__nota { margin: 10px 0 0; font-size: 12px; color: var(--text-muted); }

@media (max-width: 560px) {
    .matcher-mazo { height: clamp(420px, 66vh, 600px); }
    .matcher-hero { height: 218px; }
    .matcher-carta__top h4 { font-size: 17px; }
}


/* El boton del matcher late. Es el unico de la barra que lo hace, y a
   proposito: los otros tres esperan a que los busques, este avisa que
   hay leads sin calificar. El resplandor va en box-shadow y no en
   filter para no forzar una capa de composicion nueva por el latido. */
/* Con el id y no con la clase: moderno.css le pone color y box-shadow
   a `.btn:not(.btn-primary)` con !important, y por especificidad le
   gana a cualquier clase suelta. */
#btn-matcher.btn-matcher {
    position: relative;
    color: var(--primary) !important;
    border-color: rgba(var(--acento-rgb), .45) !important;
    animation: matcher-late 2.4s ease-in-out infinite;
}

#btn-matcher.btn-matcher i { position: relative; z-index: 1; }

#btn-matcher.btn-matcher:hover {
    animation: none;
    box-shadow: 0 0 0 3px rgba(var(--acento-rgb), .18), 0 0 22px rgba(var(--acento-rgb), .55) !important;
    transform: translateY(-1px);
}

@keyframes matcher-late {
    0%, 100% { box-shadow: 0 0 0 0 rgba(var(--acento-rgb), .45), 0 0 10px rgba(var(--acento-rgb), .25); }
    50%      { box-shadow: 0 0 0 6px rgba(var(--acento-rgb), 0),  0 0 26px rgba(var(--acento-rgb), .65); }
}

/* Un boton que late sin parar es un problema real para quien tiene
   sensibilidad al movimiento. Sin animacion queda igual de visible:
   el color y el resplandor fijo alcanzan. */
@media (prefers-reduced-motion: reduce) {
    #btn-matcher.btn-matcher {
        animation: none;
        box-shadow: 0 0 0 2px rgba(var(--acento-rgb), .25), 0 0 16px rgba(var(--acento-rgb), .4) !important;
    }
}

/* --- La foto de la tarjeta ---------------------------------------
   El mapa real del lugar, embebido de Google. El iframe se apaga a
   los eventos: si tomara el puntero, arrastrar la tarjeta desde
   arriba movería el mapa en vez de calificar. */

.matcher-hero {
    position: relative;
    /* Casi la mitad de la tarjeta. La captura del sitio es lo que
       contesta la pregunta de esta pantalla; verla en una tirita de
       ciento noventa pixeles era tenerla y no usarla. */
    /* flex:none o la banda se comprime: la tarjeta es una columna flex
       y con los datos largos le come cuarenta pixeles a la imagen. */
    flex: none;
    height: 262px;
    margin: -18px -18px 0;
    background: var(--bg-card);
    overflow: hidden;
}

.matcher-foto {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    /* La imagen es un logo de 128 px estirado a toda la banda: sin el
       desenfoque se ven los pixeles. Con el, el logo deja de ser un
       logo y pasa a ser el color de la marca, que es lo que queremos. */
    /* Un logo de 128 px estirado a toda la banda se ve pixelado: para
       eso esta el desenfoque, que lo convierte en el color de la marca.
       La captura del sitio no lleva nada de eso: es la foto y se
       muestra como es. */
    filter: blur(26px) saturate(1.6) brightness(.72);
    transform: scale(1.4);
}

.matcher-foto--captura {
    filter: none;
    transform: none;
    object-position: top center;
}

/* Sin imagen, el color propio del nombre. El tono lo pone el JS. */
.matcher-foto--tono {
    background:
        radial-gradient(120% 90% at 30% 0%, hsl(var(--tono, 150) 55% 28%) 0%, transparent 70%),
        linear-gradient(160deg, hsl(var(--tono, 150) 45% 20%), var(--bg-card));
}

/* El degrade lleva el mapa al color de la tarjeta abajo, que es donde
   se apoya el nombre. */
.matcher-hero__velo {
    position: absolute;
    inset: 0;
    background: linear-gradient(to bottom,
        rgba(0, 0, 0, .15) 0%,
        rgba(0, 0, 0, .55) 55%,
        var(--bg-surface) 100%);
}

.matcher-hero .matcher-carta__top {
    position: absolute;
    left: 18px;
    right: 18px;
    bottom: 10px;
}

/* Sobre la captura el nombre no puede ser un parrafo: dos renglones y
   corta. El nombre completo esta en la ficha del lead. */
.matcher-hero .matcher-carta__top h4 {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.matcher-hero .matcher-carta__top h4 { text-shadow: 0 2px 8px rgba(0, 0, 0, .9); }
.matcher-hero .matcher-carta__top p { color: rgba(255, 255, 255, .82); text-shadow: 0 1px 6px rgba(0, 0, 0, .9); }

.matcher-hero .matcher-logo {
    background: rgba(255, 255, 255, .96);
    box-shadow: 0 4px 14px rgba(0, 0, 0, .5);
}

.matcher-hero .matcher-logo--letra { background: var(--bg-surface); }

/* Con el hero arriba, la nota y los datos empiezan mas abajo. */
.matcher-nota { margin-top: 14px; }

/* La inicial sin imagen usa el mismo tono que la banda, asi el cuadro
   del logo y el fondo se ven de la misma empresa y no de dos. */
.matcher-logo--letra {
    background: hsl(var(--tono, 150) 40% 22%) !important;
    color: hsl(var(--tono, 150) 60% 82%);
    border-color: hsl(var(--tono, 150) 40% 34%);
}

/* El logo va sobre el desenfoque: nitido, chico y con su fondo claro,
   que es como se lee un logo de verdad. */
.matcher-hero .matcher-logo { object-fit: contain; padding: 6px; }

/* Con una captura arriba, el velo solo tiene que oscurecer el pie de
   la banda: taparla entera seria esconder justo lo que se vino a ver. */
.matcher-hero:has(.matcher-foto--captura) .matcher-hero__velo {
    background: linear-gradient(to bottom,
        rgba(0, 0, 0, .05) 0%,
        rgba(0, 0, 0, .10) 45%,
        rgba(0, 0, 0, .75) 78%,
        var(--bg-surface) 100%);
}

/* El pie de la tarjeta ahora tiene tres accesos y en el celular no
   entran en una linea holgada: que bajen antes de salirse. */
.matcher-carta__pie { flex-wrap: wrap; gap: 14px 18px; }

/* La captura entra con un fundido, encima de lo que ya estaba. Sin
   esto el cambio de color es un parpadeo a mitad de lectura. */
.matcher-foto--captura { z-index: 1; animation: matcher-aparece .35s ease both; }

@keyframes matcher-aparece {
    from { opacity: 0; }
    to   { opacity: 1; }
}

/* Mientras la captura se genera —thum.io renderiza la pagina en el
   momento— una barra fina cruza la banda. Dice "esto todavia puede
   cambiar" sin tapar nada de lo que ya se puede leer. */
.matcher-hero.cargando::after {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    z-index: 2;
    width: 34%;
    height: 2px;
    background: linear-gradient(90deg, transparent, var(--primary), transparent);
    animation: matcher-cruza 1.5s ease-in-out infinite;
}

@keyframes matcher-cruza {
    from { transform: translateX(-100%); }
    to   { transform: translateX(330%); }
}

@media (prefers-reduced-motion: reduce) {
    .matcher-hero.cargando::after { animation: none; width: 100%; opacity: .5; }
    .matcher-foto--captura { animation: none; }
}

/* Orden de capas de la banda, de atras hacia adelante: la imagen, el
   velo, y arriba de todo el nombre. La captura entra despues en el
   DOM y sin esto se comia el nombre de la empresa, que es el dato mas
   importante de la tarjeta. */
.matcher-hero__velo { z-index: 2; }
.matcher-hero .matcher-carta__top { z-index: 3; }


/* --- Los fondos animados ----------------------------------------
   El estilo lo elige el usuario en Apariencia y viaja en un atributo
   de <html>. Solo "codigo" dibuja: es un canvas repintandose veinte
   veces por segundo. Los otros cuatro son CSS puro y tres de ellos
   no animan nada, o sea que despues del primer pintado no le cuestan
   un cuadro al navegador. */

/* Puntos es la trama de siempre, un poco mas presente. */
html[data-fondo="puntos"] body::before {
    background-image: radial-gradient(rgba(255, 255, 255, 0.055) 1px, transparent 1px);
    background-size: 20px 20px;
}

/* Malla: cuadricula fina. Dos degradados repetidos, sin animacion. */
html[data-fondo="malla"] body::before {
    background-image:
        linear-gradient(rgba(var(--acento-rgb), 0.045) 1px, transparent 1px),
        linear-gradient(90deg, rgba(var(--acento-rgb), 0.045) 1px, transparent 1px);
    background-size: 46px 46px;
}

/* Liso: ni la trama. Es el mas barato que hay. */
html[data-fondo="liso"] body::before { background-image: none; }

/* Hubo un fondo "aurora" —dos manchas de luz derivando— y se saco.
   Era una capa a pantalla completa con blur de 38 px animada: el
   navegador recalcula ese desenfoque en cada cuadro y se comia el
   presupuesto de tiempo entero. Si algun dia vuelve, tiene que ser sin
   blur sobre elemento en movimiento. */

/* La grilla de tarjetas de elección: fondo animado, modos de diseño
   y tema comparten esta misma clase — auto-fit, asi que da igual
   cuantas entren. */
.ap-estilos,
/* Los dos botones del tema reusan la pastilla de los estilos de
   fondo: es la misma clase de eleccion —una entre varias, con
   icono, titulo y aclaracion— y no habia por que inventar otra. */
.ap-temas {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(96px, 1fr));
    gap: 8px;
    margin-bottom: 14px;
}

.ap-estilo {
    padding: 10px 8px;
    background: transparent;
    border: 1px solid var(--border-color);
    border-radius: 10px;
    color: var(--text-muted);
    cursor: pointer;
    text-align: center;
    transition: border-color .15s, background .15s;
}

.ap-estilo:hover { border-color: rgba(var(--acento-rgb), .45); }

.ap-estilo.activo {
    border-color: var(--primary);
    background: rgba(var(--acento-rgb), .10);
    color: var(--primary);
}

.ap-estilo i { display: block; font-size: 15px; margin-bottom: 5px; }
.ap-estilo b { display: block; font-size: 12px; color: var(--text-main); }
.ap-estilo.activo b { color: var(--primary); }
.ap-estilo span { display: block; margin-top: 2px; font-size: 10px; line-height: 1.3; }

/* El "mostrar mas" de la grilla de consultas. Mismo trato que el de la
   bandeja: ancho completo, al final de la lista. */
.grid-mas {
    display: block;
    width: 100%;
    padding: 14px;
    margin-top: 2px;
    background: transparent;
    border: 1px dashed var(--border-color);
    border-radius: 12px;
    color: var(--text-muted);
    cursor: pointer;
    font-size: 13px;
}

.grid-mas:hover { color: var(--primary); border-color: rgba(var(--acento-rgb), .45); }


/* --- LA MARCA SIGUE EL COLOR DE ACENTO ---------------------------
   El logotipo era un PNG con el verde quemado adentro: elegias violeta
   en Apariencia y la marca seguia verde, que es justo lo que rompe la
   sensacion de que el CRM es tuyo.

   Se dibuja con dos capas apiladas del mismo tamaño, cada una usando
   una mitad del logo como recorte: una trae las letras que van en
   blanco y la otra las que llevan el acento. El color lo pone
   background, asi que cambia con la variable y sin tocar un archivo.

   Las mascaras se generaron separando los dos colores del PNG
   original, conservando el suavizado de los bordes. */

.marca-nombre,
.marca-iso {
    position: relative;
    display: block;
}

.marca-nombre > i,
.marca-iso > i {
    position: absolute;
    inset: 0;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    -webkit-mask-position: center;
    mask-position: center;
    -webkit-mask-size: contain;
    mask-size: contain;
}

/* El logotipo con el nombre, en la barra de arriba. */
.marca-nombre {
    /* La proporcion sale del PNG: 3384 x 371. */
    height: 24px;
    width: 219px;
}

/* --- La tinta de la marca ---------------------------------------
   La mitad "blanca" del logotipo ya no es blanca: es del color del
   texto, que cada tema define a su manera. En oscuro sigue siendo casi
   blanca; en claro pasa a grafito.

   Fijarla en #fff la hacia desaparecer en el tema claro —un logo
   blanco sobre una tarjeta blanca—, que es exactamente lo que pasaba
   en el aviso de "Estado guardado" y en el avatar del perfil.

   La otra mitad va con rgb(var(--acento-rgb)) y no con var(--primary):
   --primary es el verde de la marca y no se mueve, mientras que
   --acento-rgb es el color que la persona eligio en Apariencia. Con
   esto el isotipo acompana el acento como el resto de la aplicacion. */
.marca-nombre__blanco {
    background: var(--text-main);
    -webkit-mask-image: url('assets/nombre-blanco.png');
    mask-image: url('assets/nombre-blanco.png');
}

.marca-nombre__acento {
    background: rgb(var(--acento-rgb));
    -webkit-mask-image: url('assets/nombre-acento.png');
    mask-image: url('assets/nombre-acento.png');
}

/* El isotipo: la S y la barra con la C. */
.marca-iso {
    /* 513 x 300. */
    width: 154px;
    height: 90px;
    margin: 0 auto;
}

.marca-iso__blanco {
    background: var(--text-main);
    -webkit-mask-image: url('assets/logo-blanco.png');
    mask-image: url('assets/logo-blanco.png');
}

.marca-iso__acento {
    background: rgb(var(--acento-rgb));
    -webkit-mask-image: url('assets/logo-acento.png');
    mask-image: url('assets/logo-acento.png');
    /* Un resplandor del mismo color, apoyado en la forma y no en una
       caja: sin esto el isotipo queda plano al lado del original, que
       tenia el brillo pintado en el PNG. */
    filter: drop-shadow(0 0 14px rgba(var(--acento-rgb), .45));
}

/* El isotipo metido en un circulo: el avatar del perfil y el cartel de
   "Guardando cambios". Van con la medida del hueco, guardando la
   proporcion 513 x 300 del dibujo. */
.avatar-con-iso .marca-iso--avatar {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 66px;
    height: 39px;
    margin: 0;
    z-index: 1;
    /* Escondido salvo que el avatar siga siendo el logo. Un avatar de
       verdad —el trofeo, una foto— no lo tapa entero y el dibujo
       asomaba por los costados. */
    display: none;
}

.avatar-con-iso:has(> img[src*="assets/logo"]) .marca-iso--avatar { display: block; }

.avatar-con-iso > img { position: relative; z-index: 2; }

/* La version chica: el avatar de las tarjetas de usuarios. Trae su
   propio circulo porque ahi el estilo venia escrito en el atributo
   style de la imagen. */
.avatar-con-iso--chapa {
    position: relative;
    display: block;
    width: 42px;
    height: 42px;
    flex: 0 0 42px;
}

.avatar-con-iso--chapa > img {
    width: 42px;
    height: 42px;
    border-radius: 50%;
    object-fit: cover;
    border: 2px solid var(--primary);
    background: var(--bg-card);
    box-shadow: 0 2px 8px rgba(var(--acento-rgb), .2);
    display: block;
}

.avatar-con-iso--chapa .marca-iso--avatar { width: 30px; height: 18px; }

.avatar-con-iso--chapa:has(> img[src*="assets/logo"])::after {
    border-width: 2px;
    box-shadow: 0 2px 8px rgba(var(--acento-rgb), .2);
}

/* La miniatura de la grilla de avatares: el mismo circulo que traia
   la imagen, con el isotipo adentro. */
.marca-iso--muestra {
    width: 52px;
    height: 52px;
    margin: 0 auto 6px;
    border-radius: 50%;
    border: 1.5px solid var(--primary);
    background: var(--bg-card);
    /* El dibujo entra en la caja interna: las mascaras van con
       inset: 0, y el relleno las corre para adentro del circulo. */
    padding: 9px 8px;
    box-sizing: border-box;
    /* El resplandor del acento se queda dentro del circulo. */
    overflow: hidden;
}

/* Cuando el avatar es la foto de la persona, la imagen tapa el
   isotipo. Cuando sigue siendo el logo de la marca la dejamos
   transparente, para que se vea el dibujo coloreado de atras. El
   circulo, el borde y la sombra los toma el ::after, porque venian
   con la imagen que acabamos de esconder. */
.avatar-con-iso > img[src*="assets/logo"] { opacity: 0; }

.avatar-con-iso:has(> img[src*="assets/logo"])::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 3px solid var(--primary);
    box-shadow: 0 6px 20px rgba(var(--acento-rgb), 0.25);
    background: var(--bg-card);
    pointer-events: none;
    z-index: 0;
}

.guardando-marca .marca-iso {
    width: 62px;
    height: 36px;
    margin: 0;
    position: relative;
    z-index: 2;
}

/* En pantallas chicas la barra de arriba va apretada. */
@media (max-width: 720px) {
    .marca-nombre { height: 19px; width: 173px; }
}


/* --- La barra del barrido ----------------------------------------
   Un barrido de sesenta ciudades es mas de una hora de maquina. El
   cartel decia "buscando · quedan 59 ciudades" y nada mas: no habia
   contra que medir ese 59 —¿de 60 o de 600?— ni forma de saber si
   avanzaba. Es la diferencia entre esperar tranquilo y pensar que se
   colgo.

   Ahora dice en que anda, cuantas lleva de cuantas y cuanto falta, y
   la barra da la lectura de un vistazo. */

.prospectar-linea {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 4px 10px;
}

.prospectar-linea b { color: var(--text-main); font-weight: 600; }

.prospectar-resto {
    margin-left: auto;
    color: var(--text-muted);
    font-variant-numeric: tabular-nums;
}

.prospectar-barra {
    display: block;
    height: 3px;
    margin-top: 6px;
    background: var(--border-color);
    border-radius: 999px;
    overflow: hidden;
}

/* Solo se anima el ancho, y solo cuando el numero cambia de verdad
   —una vez por ciudad terminada, o sea cada varios minutos—. Nada de
   animaciones en bucle: la barra avanza cuando hay algo que avanzar. */
.prospectar-barra i {
    display: block;
    height: 100%;
    background: var(--primary);
    border-radius: 999px;
    transition: width 600ms cubic-bezier(.16, 1, .3, 1);
}

@media (max-width: 720px) {
    .prospectar-resto { margin-left: 0; width: 100%; }
}


/* --- Las categorias del catalogo ---------------------------------
   Trescientos rubros no se recorren con el ojo. Las categorias son
   un filtro mas —se combinan con el buscador, no encierran— y cada
   una dice cuantos rubros tiene: eso es lo que deja elegir por donde
   entrar sin tener que abrirlas todas.

   Van en una fila que scrollea al costado y no en una grilla: en
   grilla ocupaban media pantalla y empujaban la lista de rubros
   fuera de la vista, que es justo lo que se vino a mirar. */

.prosp-cats {
    display: flex;
    gap: 6px;
    overflow-x: auto;
    padding-bottom: 8px;
    margin-bottom: 10px;
    scrollbar-width: thin;
}

.prosp-cat {
    flex: none;
    padding: 5px 11px;
    background: transparent;
    border: 1px solid var(--border-color);
    border-radius: 999px;
    color: var(--text-muted);
    font-size: 12px;
    white-space: nowrap;
    cursor: pointer;
    transition: border-color .15s, color .15s, background .15s;
}

.prosp-cat:hover { border-color: rgba(var(--acento-rgb), .45); color: var(--text-main); }

.prosp-cat.activa {
    border-color: var(--primary);
    background: rgba(var(--acento-rgb), .10);
    color: var(--primary);
}

/* El numero de rubros, mas apagado que el nombre: informa, no
   compite con la etiqueta. */
.prosp-cat b {
    margin-left: 4px;
    font-weight: 600;
    opacity: .55;
    font-variant-numeric: tabular-nums;
}

.prosp-cat.activa b { opacity: .8; }



/* ==========================================================
   CAMPAÑA DE PRIMER CONTACTO

   Cuatro pasos en un modal. La regla del bloque: la lista de
   contactos es lo unico que crece, asi que es lo unico que
   scrollea; la guia de pasos y el pie quedan siempre a la vista
   para no perder de vista en que parte del proceso se esta.
   Ver js/campana.js.
   ========================================================== */

.campana-card {
    max-width: 800px;
    width: 100%;
}

/* Los cuatro pasos. El que corre va con el acento, los que ya
   pasaron quedan tildados: se lee cuanto falta sin contarlos. */
.campana-guia {
    display: flex;
    flex-wrap: wrap;
    gap: 6px 14px;
    margin: 4px 0 16px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--border-color);
}

.campana-paso {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--text-dim);
}

.campana-paso b {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: rgba(var(--acento-rgb), 0.12);
    color: var(--text-muted);
    font-size: 0.7rem;
}

.campana-paso.es-actual { color: var(--text-main); }
.campana-paso.es-actual b { background: rgb(var(--acento-rgb)); color: var(--bg-card); }
.campana-paso.es-hecho { color: var(--text-main); }
.campana-paso.es-hecho b { background: rgba(var(--acento-rgb), 0.28); color: var(--text-main); }

/* Las cuatro secciones, todas visibles a la vez y no detras de un
   "Continuar": se scrollea, no se navega (ver js/campana.js). Cada
   una es su propia tarjeta, no solo un divisor — asi se distinguen de
   un vistazo aunque se este mirando de lejos o en el celular. */
.campana-seccion {
    padding: 22px 24px;
    margin-bottom: 18px;
    border-radius: 16px;
    background: var(--surf-1);
    border: 1px solid var(--border-color);
}

.campana-seccion:last-child { margin-bottom: 0; }

.campana-seccion h4 {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0 0 12px;
    font-size: 0.98rem;
    color: var(--text-main);
}

.campana-historial-toggle {
    display: block;
    width: 100%;
    padding: 0;
    background: none;
    border: none;
    cursor: pointer;
    text-align: left;
}
.campana-historial-toggle h4 { margin-bottom: 0; }
.campana-historial-toggle h4 i { margin-left: auto; color: var(--text-dim); font-size: 0.8rem; }

.campana-historial-lista {
    list-style: none;
    margin: 12px 0 0;
    padding: 0;
    max-height: 280px;
    overflow-y: auto;
}

.campana-historial-lista li {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 0;
    font-size: 0.82rem;
    color: var(--text-main);
    border-top: 1px solid var(--border-color);
}
.campana-historial-lista li:first-child { border-top: none; }
.campana-historial-lista li i { color: var(--text-dim); width: 16px; text-align: center; }
.campana-historial-nombre { font-weight: 600; }
.campana-historial-cuando { margin-left: auto; color: var(--text-dim); font-size: 0.76rem; }

.campana-seccion-num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: rgb(var(--acento-rgb));
    color: var(--bg-card);
    font-size: 0.78rem;
    font-weight: 800;
}

/* Cuando la sección todavía no tiene con qué trabajar (sin filtro,
   sin elegidos): un aviso corto en vez del contenido entero, para no
   mostrar una lista o un editor vacíos que parecen rotos. La tarjeta
   se atenua para que se lea "todavia no" y no "esto esta roto". */
.campana-seccion-vacia { opacity: 0.6; }
.campana-seccion-vacia .campana-ayuda { margin: 0; }

.campana-previa-asunto { margin: 0 0 4px; font-size: 0.86rem; }

.campana-ayuda {
    margin: 0 0 14px;
    font-size: 0.82rem;
    line-height: 1.5;
    color: var(--text-muted);
}

/* Aviso del interruptor de emergencia (Campana.AUTOMATICO_WA_SUSPENDIDO,
   js/campana.js) — mismo tono que un error, pero no es rojo: no es
   que algo se rompió, es una pausa a propósito. */
.campana-auto-wa-suspendido {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 10px 12px;
    border-radius: 10px;
    background: color-mix(in srgb, #f59e0b 12%, transparent);
    border: 1px solid color-mix(in srgb, #f59e0b 35%, transparent);
    color: var(--text-main);
}
.campana-auto-wa-suspendido i { color: #f59e0b; margin-top: 2px; }

/* Toggle "Enviar automático (vía OpenWA)" — un checkbox simple, sin
   el estilo de píldora de .campana-canal-op: ahí eligen entre dos
   canales excluyentes, acá es una sola opción prendida/apagada. */
.campana-auto-wa {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 6px;
    font-size: 0.86rem;
    font-weight: 600;
    cursor: pointer;
}
.campana-auto-wa input { width: 16px; height: 16px; accent-color: var(--primary); cursor: pointer; }

/* Botón "Levantar OpenWA" — solo lo ve el dueño de esa PC (ver
   Campana.puedeLevantarOpenWA), así que va chico y separado, no
   compitiendo con el botón principal de mandar. */
.campana-btn-openwa { margin: 0 0 4px; }
.campana-ayuda-chica { margin: 0 0 14px; font-size: 0.76rem; }

/* Modal "Contactos en Negociación" (ver LeadsManager.openNegotiationsModal,
   js/leads.js). Reemplaza estilos inline que tenían colores fijos de
   modo claro (#f1f5f9, rgba(226,232,240,...)) — se veían bien en
   claro.css pero quedaban casi invisibles o desentonaban en el resto
   de los temas, porque no usaban las variables de tema. */
.negociacion-modal-card {
    max-width: 560px;
    width: 90%;
    max-height: 80vh;
    display: flex;
    flex-direction: column;
    border-top: 4px solid #a855f7;
    border-radius: 20px;
    box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.35), 0 0 30px rgba(168, 85, 247, 0.25);
}

.negociacion-modal-header {
    padding-bottom: 12px;
    border-bottom: 1px solid var(--border-color);
}
.negociacion-modal-titulo {
    color: var(--text-main);
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0;
    font-size: 1.2rem;
}
.negociacion-modal-titulo i { color: #a855f7; }

.negociacion-modal-ayuda {
    color: var(--text-muted);
    font-size: 0.88rem;
    margin: 10px 0 14px;
}

.negociacion-modal-lista {
    flex: 1;
    overflow-y: auto;
    padding-right: 4px;
    display: grid;
    gap: 10px;
    max-height: 60vh;
}

/* Chica a propósito: es una lista dentro de un modal angosto (ver
   .negociacion-modal-card, max-width 560px), no la ficha completa de
   un lead — el avatar y el borde de acento dan la misma "cara" que la
   tarjeta de leads sin repetir su tamaño ni su ancho completo. */
.negociacion-card {
    padding: 10px 12px;
    border-radius: 12px;
    border: 1px solid var(--border-color);
    border-left: 3px solid #a855f7;
    background: var(--bg-card);
    display: flex;
    flex-direction: column;
    gap: 6px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
}

.negociacion-card-cabecera {
    display: flex;
    align-items: center;
    gap: 10px;
}
.negociacion-card-avatar {
    flex: none;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: color-mix(in srgb, #a855f7 20%, transparent);
    color: #c98bfa;
    font-weight: 800;
    font-size: 0.9rem;
}
.negociacion-card-datos { flex: 1; min-width: 0; }
.negociacion-card-nombre {
    margin: 0;
    color: var(--text-main);
    font-size: 0.9rem;
    font-weight: 700;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.negociacion-card-interes { font-size: 0.74rem; color: var(--primary); font-weight: 600; }

.negociacion-badge {
    flex: none;
    font-size: 0.68rem;
    background: color-mix(in srgb, #a78bfa 18%, transparent);
    color: #c4a7fb;
    font-weight: 700;
    padding: 2px 8px;
    border-radius: 7px;
    border: 1px solid color-mix(in srgb, #a78bfa 45%, transparent);
    white-space: nowrap;
}

.negociacion-card-presupuesto { font-size: 0.76rem; color: var(--primary); font-weight: 600; }

.negociacion-card-nota {
    font-size: 0.74rem;
    color: var(--text-muted);
    background: color-mix(in srgb, var(--bg-main) 60%, transparent);
    padding: 5px 8px;
    border-radius: 6px;
    border: 1px solid var(--border-color);
}

.negociacion-card-pie {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-top: 2px;
    padding-top: 6px;
    border-top: 1px solid var(--border-color);
    gap: 8px;
    flex-wrap: wrap;
}
.negociacion-card-vendedor { font-size: 0.72rem; color: var(--text-muted); }
.negociacion-card-acciones { display: flex; gap: 4px; }

/* Solo ícono, redondos y chicos — la misma idea que .btn-fila de la
   grilla de leads, para no repetir tres botones de texto largos en
   una tarjeta que ya es angosta. */
.negociacion-ico-btn {
    flex: none;
    width: 28px;
    height: 28px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    border: 1px solid var(--border-color);
    background: var(--bg-main);
    color: var(--text-muted);
    font-size: 0.8rem;
    text-decoration: none;
    cursor: pointer;
}
.negociacion-ico-btn:hover { color: var(--text-main); border-color: var(--primary); }
.negociacion-ico-btn-wa { color: #25d366; }
.negociacion-ico-btn-wa:hover { color: #1fb355; border-color: #25d366; }

.campana-filtros {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
    gap: 10px;
    margin-bottom: 12px;
}

.campana-filtros label,
.campana-campo {
    display: flex;
    flex-direction: column;
    gap: 5px;
    font-size: 0.76rem;
    font-weight: 700;
    color: var(--text-muted);
}

.campana-filtros select,
.campana-campo select,
.campana-campo textarea,
.campana-campo input[type="text"] {
    width: 100%;
    padding: 9px 10px;
    border-radius: 10px;
    border: 1px solid var(--border-color);
    background: var(--surf-2);
    color: var(--text-main);
    font-size: 0.86rem;
    font-family: inherit;
}

/* Elegir WhatsApp o Email, arriba de todo del paso 1: cambia que
   dato hace falta en el lead y como se manda. */
.campana-canal {
    display: flex;
    gap: 10px;
    margin-bottom: 16px;
}

.campana-canal-op {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 12px 20px;
    border-radius: 14px;
    border: 1.5px solid var(--border-color);
    background: var(--surf-2);
    color: var(--text-muted);
    font-size: 0.9rem;
    font-weight: 700;
    cursor: pointer;
    transition: border-color .15s, transform .15s, box-shadow .15s;
}

.campana-canal-op:hover { transform: translateY(-1px); }

.campana-canal-op i { font-size: 1.05rem; }

.campana-canal-op input { position: absolute; opacity: 0; width: 0; height: 0; }

/* Cada canal con su propio color de marca cuando esta elegido: verde
   de WhatsApp, azul de mail. Un mismo acento para los dos se leia
   ambiguo — no quedaba claro cual de los dos estaba activo de un
   vistazo. */
.campana-canal-op:nth-child(1).es-elegido {
    border-color: #25d366;
    background: rgba(37, 211, 102, 0.12);
    color: var(--text-main);
    box-shadow: 0 0 0 1px rgba(37, 211, 102, 0.35) inset;
}
.campana-canal-op:nth-child(1).es-elegido i { color: #25d366; }

.campana-canal-op:nth-child(2).es-elegido {
    border-color: #3b82f6;
    background: rgba(59, 130, 246, 0.12);
    color: var(--text-main);
    box-shadow: 0 0 0 1px rgba(59, 130, 246, 0.35) inset;
}
.campana-canal-op:nth-child(2).es-elegido i { color: #3b82f6; }

.campana-campo { margin-bottom: 18px; }

/* EL TEXTO DEL MENSAJE SE LEE COMO UN TEXTO, NO COMO UN CAMPO.

   Aca adentro no va un dato corto: van los cinco parrafos que le
   van a llegar a una persona. Estaba saliendo en negrita, chico y
   apretado, y encima cortado —siete renglones de alto para un
   texto que mide el triple—, asi que para releer lo que uno esta
   por mandar habia que scrollear adentro de una cajita.

   El `!important` del peso no es capricho: index.css le pone
   `font-weight: 600 !important` a TODO textarea del CRM. Para un
   campo de una linea esta bien; para prosa larga es justo lo que
   la vuelve pesada de leer. Sin !important no hay forma de
   devolverla a peso normal.

   El alto minimo (y no `rows`) es lo que hace que se vea entero
   de una: sigue siendo redimensionable a mano por si alguien lo
   quiere mas chico. */
.campana-campo textarea {
    resize: vertical !important;
    font-weight: 400 !important;
    font-size: 0.92rem !important;
    line-height: 1.7 !important;
    /* `height: auto` ademas del min-height: ajustes.css fija
       `height: auto !important` y moderno.css `height: 36px
       !important`; sin ganar esa tambien, el alto lo termina
       decidiendo el `rows` del HTML y no esta regla. */
    height: auto !important;
    min-height: 320px !important;
    /* Techo: js/campana.js lo hace crecer con el texto, y sin esto
       una plantilla larguisima empujaria el boton de enviar fuera de
       la pantalla. Pasado el techo scrollea adentro, que para ese
       caso extremo es lo correcto. */
    max-height: 70vh !important;
    padding: 14px 16px !important;
}

.campana-check {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 0.82rem;
    color: var(--text-main);
    margin-bottom: 14px;
    cursor: pointer;
}

/* El conteo del filtro. Va grande porque es la respuesta a la
   unica pregunta del paso: a cuantos les vas a escribir. */
.campana-conteo {
    margin: 0;
    padding: 12px 14px;
    border-radius: 12px;
    background: rgba(var(--acento-rgb), 0.08);
    border: 1px solid rgba(var(--acento-rgb), 0.2);
    font-size: 0.86rem;
    color: var(--text-main);
}

.campana-conteo strong {
    font-size: 1.3rem;
    font-weight: 800;
    color: rgb(var(--acento-rgb));
    font-variant-numeric: tabular-nums;
}

.campana-conteo span {
    display: block;
    margin-top: 3px;
    font-size: 0.74rem;
    color: var(--text-dim);
}

.campana-acciones-lista {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
    flex-wrap: wrap;
}

.campana-buscar-lista {
    flex: 1 1 180px;
    min-width: 140px;
    padding: 6px 10px;
    border-radius: 8px;
    border: 1px solid var(--border-color);
    background: var(--surf-2);
    color: var(--text-main);
    font-size: 0.8rem;
}

.campana-elegidos {
    margin-left: auto;
    font-size: 0.78rem;
    color: var(--text-muted);
}

.campana-elegidos strong { color: var(--text-main); font-variant-numeric: tabular-nums; }

/* Lo unico que scrollea: alto fijo, la pagina no crece aunque el
   filtro traiga miles de contactos (pasa sobre todo en Email, que
   no depende de rubro/sector para armar la lista). */
.campana-lista {
    max-height: 320px;
    overflow-y: auto;
    border: 1px solid var(--border-color);
    border-radius: 12px;
}

.campana-fila {
    display: grid;
    grid-template-columns: 22px minmax(0, 1.4fr) minmax(0, 1fr) minmax(0, 0.8fr) auto;
    align-items: center;
    gap: 10px;
    padding: 8px 12px;
    border-bottom: 1px solid var(--border-color);
    font-size: 0.8rem;
    cursor: pointer;
}

.campana-fila:last-child { border-bottom: none; }
.campana-fila:hover { background: rgba(var(--acento-rgb), 0.05); }

.campana-fila-nombre {
    font-weight: 700;
    color: var(--text-main);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.campana-fila-dato {
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.campana-fila-chip {
    font-size: 0.7rem;
    font-weight: 700;
    color: var(--text-dim);
    text-transform: uppercase;
    letter-spacing: 0.02em;
    max-width: 160px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* La vista previa es el mensaje, no una caja de formulario: se
   muestra como se va a leer del otro lado. */
.campana-previa {
    padding: 16px 18px;
    border-radius: 14px;
    background: rgba(var(--acento-rgb), 0.08);
    border: 1px solid rgba(var(--acento-rgb), 0.2);
}

.campana-previa-cabecera {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 10px;
}

.campana-previa-rotulo {
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--text-dim);
}

.campana-previa-acciones {
    display: flex;
    align-items: center;
    gap: 12px;
}

.campana-previa-select {
    padding: 4px 8px;
    border-radius: 8px;
    border: 1px solid var(--border-color);
    background: var(--surf-2);
    color: var(--text-main);
    font-size: 0.76rem;
}

.campana-previa p {
    margin: 0;
    font-size: 0.86rem;
    line-height: 1.55;
    color: var(--text-main);
    white-space: pre-line;
}

.campana-previa-abrir {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    padding: 13px 16px;
    border-radius: 10px;
    border: 1px dashed rgba(var(--acento-rgb), 0.4);
    background: transparent;
    color: var(--text-main);
    font-size: 0.84rem;
    font-weight: 600;
    cursor: pointer;
    transition: background .15s, border-color .15s;
}

.campana-previa-abrir:hover {
    background: rgba(var(--acento-rgb), 0.1);
    border-color: rgba(var(--acento-rgb), 0.6);
}

/* --- Vista previa en su propia ventana -----------------------------
   Antes el mail entero iba embebido siempre abajo del texto: con un
   iframe de 280px siempre abierto, escribir el mensaje era pelear
   contra un bloque enorme que no se podía cerrar. Ahora es un modal
   aparte —mismo patrón que los demás overlays del CRM— que solo
   aparece cuando hace falta mirar cómo queda. */
.campana-previa-overlay {
    position: fixed;
    inset: 0;
    z-index: 200;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: rgba(0, 0, 0, 0.55);
    backdrop-filter: blur(2px);
}

.campana-previa-ventana {
    width: min(560px, 100%);
    max-height: min(680px, 90vh);
    display: flex;
    flex-direction: column;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: 16px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4);
    overflow: hidden;
}

.campana-previa-ventana-cab {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    border-bottom: 1px solid var(--border-color);
    font-size: 0.78rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--text-dim);
    flex: none;
}

.campana-previa-ventana-cuerpo {
    padding: 16px;
    overflow-y: auto;
}

/* Adentro del modal el mail tiene más aire para leerse: la misma
   caja fija de 280px se sentía chica cuando ya no compite por
   espacio con el resto del formulario. */
.campana-previa-ventana-cuerpo .campana-inbox-cuerpo {
    height: min(420px, 60vh);
}

/* --- El "inbox" de la vista previa --------------------------------
   Simula un cliente de correo/WhatsApp de verdad para que se lea de
   un vistazo, no como un bloque de texto suelto adentro de la
   tarjeta. El cuerpo del mail va en un <iframe srcdoc>: aislado del
   CSS del CRM, es EXACTAMENTE lo que llega, no una aproximacion. */
.campana-inbox {
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: 12px;
    padding: 14px;
}

.campana-inbox-cabecera {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin-bottom: 10px;
}

.campana-inbox-avatar {
    flex: none;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgb(var(--acento-rgb));
    color: var(--bg-card);
    font-size: 0.76rem;
    font-weight: 800;
}

.campana-inbox-datos {
    font-size: 0.8rem;
    color: var(--text-main);
    line-height: 1.4;
}

.campana-inbox-datos > span { color: var(--text-dim); font-weight: 400; }

.campana-inbox-para {
    font-size: 0.74rem;
    color: var(--text-muted);
}

.campana-inbox-asunto {
    margin: 0 0 10px;
    font-size: 0.95rem;
    font-weight: 700;
    color: var(--text-main);
}

.campana-inbox-cuerpo {
    width: 100%;
    height: 280px;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    background: #fff;
}

/* La burbuja de WhatsApp, sin el marco de mail. */
.campana-inbox-wa .campana-inbox-cabecera { margin-bottom: 6px; }

.campana-inbox-burbuja {
    display: inline-block;
    max-width: 90%;
    padding: 10px 12px;
    border-radius: 4px 14px 14px 14px;
    background: rgba(37, 211, 102, 0.14);
    border: 1px solid rgba(37, 211, 102, 0.3);
    font-size: 0.85rem;
    line-height: 1.5;
    color: var(--text-main);
    white-space: pre-line;
}

/* Las dos filas de chips para insertar variables ({nombre}, {dolor},
   etc) se sacaron: doce botones punteados repartidos en dos franjas,
   arriba del asunto y arriba del cuerpo, empujaban el mensaje fuera
   de la pantalla para insertar texto que las plantillas ya traen.
   Ver el comentario de seccionMensaje() en js/campana.js. */

.campana-contador {
    font-weight: 400;
    color: var(--text-dim);
    font-variant-numeric: tabular-nums;
}

.campana-contador.es-largo { color: var(--warning); }

/* --- Buscar emails automaticamente --- */
.campana-buscar-email {
    margin-top: 12px;
    padding: 14px 16px;
    border-radius: 12px;
    background: var(--surf-1);
    border: 1px solid var(--border-color);
}

.campana-buscar-email .campana-ayuda { margin: 0 0 10px; }
.campana-buscar-email .campana-envio-cuenta { margin-bottom: 10px; }

.campana-email-log {
    list-style: none;
    margin: 12px 0 0;
    padding: 0;
    max-height: 160px;
    overflow-y: auto;
    font-size: 0.78rem;
}

.campana-email-log li {
    padding: 4px 0;
    display: flex;
    align-items: center;
    gap: 8px;
    color: var(--text-muted);
    border-top: 1px solid var(--border-color);
}
.campana-email-log li:first-child { border-top: none; }
.campana-email-log li.es-ok { color: var(--text-main); }
.campana-email-log li.es-ok i { color: var(--success, #22c55e); }
.campana-email-log li.es-vacio i { color: var(--text-dim); }

/* --- El paso de envio --- */

/* LA COLA A LA IZQUIERDA, EL MENSAJE A LA DERECHA.

   Se mostraba un lead por vez y un "Vas 3 de 20": para ver la tanda
   entera habia que salir de la pantalla, y salir descarta la cola.

   No se puede meter WhatsApp aca adentro -web.whatsapp.com manda
   `frame-ancestors https://*.whatsapp.com`, asi que el navegador
   bloquea el iframe, y la app de escritorio no es una pagina-, pero si
   se puede dejar de tener media pantalla ciega. */
.campana-split {
    display: grid;
    grid-template-columns: minmax(180px, 240px) 1fr;
    gap: var(--e-4, 14px);
    align-items: start;
}

.campana-cola {
    border: 1px solid var(--border-color);
    border-radius: var(--rr-lg, 14px);
    background: var(--surf-1);
    overflow: hidden;
    /* La lista puede tener cincuenta: scrollea ella, no la pantalla. */
    display: flex;
    flex-direction: column;
    max-height: 420px;
}

.campana-cola__cab {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 10px 12px;
    border-bottom: 1px solid var(--border-color);
}
.campana-cola__cab strong { font-size: 0.82rem; color: var(--text-main); }
.campana-cola__cab span   { font-size: 0.72rem; color: var(--text-muted); font-variant-numeric: tabular-nums; }

.campana-cola__lista {
    list-style: none;
    margin: 0;
    padding: 4px;
    overflow-y: auto;
}

.campana-cola__item button {
    display: flex;
    align-items: center;
    gap: 8px;
    width: 100%;
    padding: 7px 8px;
    border: none;
    border-radius: 8px;
    background: transparent;
    color: var(--text-muted);
    font-size: 0.78rem;
    text-align: left;
    cursor: pointer;
}

.campana-cola__item button:hover { background: rgba(var(--acento-rgb), 0.10); }

.campana-cola__item i { font-size: 0.62rem; flex: none; width: 12px; text-align: center; }

.campana-cola__nombre {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Los tres estados se leen distinto a proposito: mandado es trabajo
   hecho, salteado es trabajo postergado, y no son lo mismo aunque los
   dos quedaron atras. */
.campana-cola__item.es-hecho button    { color: var(--text-dim); }
.campana-cola__item.es-hecho i         { color: var(--success, #22c55e); }
.campana-cola__item.es-hecho .campana-cola__nombre { text-decoration: line-through; }

.campana-cola__item.es-salteado i      { color: var(--warning, #f59e0b); }

.campana-cola__item.es-actual button {
    background: rgba(var(--acento-rgb), 0.14);
    color: var(--text-main);
    font-weight: 700;
}
.campana-cola__item.es-actual i { color: var(--primary); }

.campana-cola__tag {
    margin-left: auto;
    font-size: 0.62rem;
    font-style: normal;
    color: var(--warning, #f59e0b);
    flex: none;
}

/* En pantalla angosta la cola no puede comerse el mensaje: se apila,
   con la lista arriba y mas baja. */
@media (max-width: 720px) {
    .campana-split { grid-template-columns: 1fr; }
    .campana-cola  { max-height: 180px; }
}

.campana-envio-cuenta {
    font-size: 0.8rem;
    color: var(--text-muted);
    margin-bottom: 14px;
}

.campana-envio-cuenta strong {
    color: var(--text-main);
    font-variant-numeric: tabular-nums;
}

.campana-envio-cuenta .foco-barra { margin-top: 6px; }

.campana-envio-quien {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-bottom: 10px;
}

.campana-envio-quien strong { font-size: 1.05rem; color: var(--text-main); }
.campana-envio-quien span { font-size: 0.8rem; color: var(--text-muted); }

.campana-envio-texto {
    margin: 0 0 14px;
    padding: 12px 14px;
    border-radius: 14px 14px 14px 4px;
    background: var(--surf-2);
    border: 1px solid var(--border-color);
    font-size: 0.86rem;
    line-height: 1.55;
    color: var(--text-main);
    white-space: pre-line;
}

.campana-envio-botones {
    display: flex;
    gap: 10px;
}

.campana-envio-botones .btn { flex: 1; }

.campana-envio-sinfono {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.8rem;
    color: var(--text-dim);
    font-style: italic;
}

/* El detalle de mails que no salieron, con el motivo real de cada uno
   (ver motivoDeError en js/campana.js). Antes solo decía "revisá la
   consola" y la consola tampoco tenía el motivo real. */
.campana-envio-errores {
    width: 100%;
    margin-top: 10px;
    padding: 10px 12px;
    border-radius: 8px;
    background: rgba(239, 68, 68, 0.08);
    border: 1px solid rgba(239, 68, 68, 0.25);
    font-size: 0.8rem;
    text-align: left;
}

.campana-envio-errores > p {
    margin: 0 0 6px;
    font-weight: 600;
    color: var(--text-main);
}

.campana-envio-errores ul {
    margin: 0;
    padding-left: 18px;
    color: var(--text-dim);
}

.campana-envio-errores li + li {
    margin-top: 4px;
}

.campana-envio-nota {
    margin: 12px 0 0;
    font-size: 0.74rem;
    color: var(--text-dim);
    line-height: 1.5;
}

.campana-final {
    text-align: center;
    padding: 18px 8px 4px;
}

.campana-final i {
    font-size: 2.2rem;
    color: rgb(var(--acento-rgb));
}

.campana-final strong {
    display: block;
    margin: 10px 0 6px;
    font-size: 1.1rem;
    color: var(--text-main);
}

.campana-final p {
    margin: 0;
    font-size: 0.84rem;
    line-height: 1.55;
    color: var(--text-muted);
}

.campana-pie {
    display: flex;
    align-items: center;
    gap: 10px;
}

/* Por que el boton esta apagado. Sin esto, el paso uno parece
   roto: se elige nada y no se puede seguir. */
.campana-traba {
    font-size: 0.74rem;
    color: var(--text-dim);
    text-align: right;
    max-width: 220px;
    line-height: 1.4;
}

@media (max-width: 620px) {
    .campana-fila {
        grid-template-columns: 22px minmax(0, 1fr) auto;
    }

    .campana-fila-dato:nth-of-type(2),
    .campana-fila-chip { display: none; }
}

/* ==========================================================
   BUSCADOR: NUBE O ESTA PC
   20260814_2

   Dos tarjetas apretables abajo del tablero de cuota. Van
   despues de los numeros y no antes: primero se ve cuanto
   cuesta el barrido, despues se elige quien lo paga.
   ========================================================== */

.prosp-modos {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 10px;
    margin-top: 0.9rem;
}

.prosp-modo {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 2px;
    padding: 10px 12px;
    border-radius: 12px;
    border: 1.5px solid var(--border-glow);
    background: rgba(var(--acento-rgb), 0.04);
    color: var(--text-main);
    cursor: pointer;
    text-align: left;
    transition: border-color 0.15s, background 0.15s;
}

.prosp-modo:hover { background: rgba(var(--acento-rgb), 0.10); }

.prosp-modo i { font-size: 0.95rem; color: var(--text-dim); }
.prosp-modo b { font-size: 0.82rem; font-weight: 800; }

.prosp-modo small {
    font-size: 0.68rem;
    color: var(--text-dim);
    line-height: 1.3;
}

/* El elegido, con el acento. Es el unico borde encendido de la
   reja, asi que no hace falta ningun tilde ni radio button. */
.prosp-modo.elegido {
    border-color: var(--primary);
    background: rgba(var(--acento-rgb), 0.14);
}

.prosp-modo.elegido i { color: var(--primary); }

/* Apagado NO es deshabilitado, y la diferencia importa.

   Una PC apagada o un mes sin minutos siguen siendo elegibles a
   proposito: el pedido queda anotado y arranca cuando la maquina
   vuelva. Bloquear el boton obligaria a prender el agente ANTES
   de poder pedir nada, que es al reves de como se trabaja —se
   piden los barridos de la noche y despues se deja la PC
   prendida—. Se ve apagado, se puede apretar, y avisa. */
.prosp-modo.es-muerto { opacity: 0.72; }
.prosp-modo.es-muerto.elegido { opacity: 1; border-style: dashed; }

.prosp-modo small.es-bien { color: var(--primary); font-weight: 700; }
.prosp-modo small.es-mal  { color: #f59e0b; font-weight: 700; }

/* La fila del estado de la PC con su botón de refrescar. El latido
   se lee cada 20s solo, pero cerrar el agente y querer verlo al
   toque —sin esperar el próximo chequeo— es lo que este ícono
   resuelve. */
.prosp-local-estado {
    display: flex;
    align-items: center;
    gap: 6px;
}

.prosp-refrescar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    color: var(--text-dim);
    cursor: pointer;
    font-size: 0.62rem;
    transition: transform 0.2s, color 0.2s, background 0.2s;
}

.prosp-refrescar:hover {
    color: var(--primary);
    background: rgba(var(--acento-rgb), 0.14);
}

.prosp-refrescar i { transition: transform 0.3s; display: block; }

/* Gira mientras se espera la respuesta de la base: es la prueba de
   que el click se registró, aunque el estado termine siendo el mismo
   de antes (el caso más común). */
.prosp-refrescar.es-girando i {
    animation: prosp-girar 0.7s linear infinite;
}

@keyframes prosp-girar {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

@media (max-width: 560px) {
    .prosp-modos { grid-template-columns: 1fr; }
}

/* El boton de prender. Vive adentro de la tarjeta "En esta PC" y
   solo existe cuando la maquina esta apagada: con el agente vivo
   seria un boton que no hace nada visible, y esos son los que
   hacen que la gente deje de confiar en los botones. */
.prosp-prender {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    margin-top: 6px;
    padding: 3px 10px;
    border-radius: 999px;
    background: var(--primary);
    color: #06241a;
    font-size: 0.68rem;
    font-weight: 800;
    cursor: pointer;
    transition: filter 0.15s;
}

.prosp-prender:hover { filter: brightness(1.1); }
.prosp-prender i { font-size: 0.65rem; color: inherit; }

/* Sin privilegio: apagada y con candado, pero VISIBLE. Esconderla
   seria peor —el dia que alguien pregunte por que a uno le aparece
   y a otro no, la respuesta tiene que estar en la pantalla— y
   ademas dejaria un hueco raro al lado de la tarjeta de la nube. */
.prosp-modo.es-vedado {
    cursor: not-allowed;
    opacity: 0.55;
}

.prosp-modo.es-vedado:hover { background: rgba(var(--acento-rgb), 0.04); }

.prosp-modo.es-vedado b::after {
    content: "\f023";           /* fa-lock */
    font-family: "Font Awesome 6 Free";
    font-weight: 900;
    font-size: 0.6rem;
    margin-left: 6px;
    opacity: 0.8;
}

.prosp-modo.es-vedado small { color: var(--text-dim); font-weight: 600; }

/* --- Panel de avisos del sistema (Perfil) --- */
.avisos-estado {
    font-size: 0.82rem;
    line-height: 1.5;
    color: var(--text-dim);
    margin: 0 0 0.9rem;
}

.avisos-estado.es-bien { color: var(--primary); font-weight: 700; }
.avisos-estado.es-mal  { color: #f59e0b; }

.avisos-acciones { display: flex; gap: 10px; flex-wrap: wrap; }

.avisos-letra-chica {
    margin: 0.9rem 0 0;
    font-size: 0.7rem;
    line-height: 1.45;
    color: var(--text-dim);
    opacity: 0.85;
}

/* ==========================================================
   HERRAMIENTAS COMO PANTALLAS
   20260814_3

   Hunter, Mensajes y Matcher siguen siendo el mismo nodo
   .modal-overlay > .modal-card de siempre. `es-pagina` le
   apaga todo lo que lo hacia una ventana flotante: la
   posicion fija, el velo oscuro y el centrado.

   Se apaga en vez de reescribirse porque el modal tiene que
   poder volver a serlo: si la mudanza no ocurre —el nodo
   todavia no existe cuando corre herramientas.js— el
   comportamiento viejo sigue ahi, entero.
   ========================================================== */

.modal-overlay.es-pagina {
    position: static;
    inset: auto;
    display: block;
    background: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    padding: 0;
    z-index: auto;
    animation: none;
    overflow: visible;
}

.modal-overlay.es-pagina > .modal-card {
    /* Sin el tope de ancho del modal: en una pantalla completa la
       lista de leads del Matcher y la reja de rubros del Hunter
       tienen lugar de sobra, que es la mitad de la razon por la
       que esto dejo de ser una ventana. */
    max-width: none;
    width: 100%;
    max-height: none;
    /* El alto lo maneja el scroll de la pagina, no el de la
       tarjeta: dos barras de scroll anidadas es de las cosas
       que mas molestan y menos se saben explicar. */
    height: auto;
    overflow: visible;
    margin: 0;
    box-shadow: none;
    animation: none;
}

/* El boton de cerrar sigue existiendo y ahora significa "volver a
   la bandeja". No se esconde: es la salida que la gente busca. */
.modal-overlay.es-pagina .modal-actions { position: static; }

/* ESCRITORIO PRIMERO, como se pidio. En el telefono la barra
   izquierda no esta —hay una de seis botones abajo— asi que a
   estas tres se sigue entrando desde la bandeja, como siempre. */
@media (max-width: 900px) {
    .modal-overlay.es-pagina > .modal-card { padding: 1rem; }
}

/* ==========================================================
   LAS TRES, A PANTALLA COMPLETA
   20260814_4

   La regla generica de arriba le saca el tope de ancho a
   .modal-card, pero a estas tres no les llegaba: cada una
   tiene su propio `width: min(...) !important` puesto para
   ganarle al max-width que legibilidad.css le clava a todos
   los modales. Ese !important, que como ventana era lo
   correcto, como pantalla dejaba el Matcher en una columna de
   560px con dos tercios de monitor vacios al costado.

   Se sobreescribe con la misma arma y mas especificidad, en
   vez de sacar los !important de alla: como modal esos anchos
   siguen siendo los buenos, y esto tiene que poder volver a
   ser un modal.

   El tope de 1400 no es decorativo: en un monitor ancho una
   linea de texto de punta a punta no se lee, se recorre con
   la cabeza. ========================================================== */

.modal-overlay.es-pagina > .modal-card,
#prospectar-modal.es-pagina .prospectar-card,
#matcher-modal.es-pagina .matcher-card,
#campana-modal.es-pagina .campana-card {
    width: min(1400px, 100%) !important;
    max-width: min(1400px, 100%) !important;
    max-height: none !important;
    /* Centrada y no pegada a la izquierda: con el tope de 1400
       en un monitor de 2560 la diferencia es una pantalla que
       se ve armada y otra que se ve rota. */
    margin: 0 auto !important;
    overflow: visible !important;
}

/* ==========================================================
   EL HUNTER: LA LISTA VA DE COSTADO
   20260814_5

   Como modal, los 310 rubros entraban en dos columnas que
   scrolleaban hacia abajo adentro de un alto acotado (88vh).
   Al volverse pestaña ese alto desaparecio —el alto lo maneja
   la pagina— y `flex: 1` sobre .prosp-chips dejo de acotar
   nada: la lista se estiro a sus 155 renglones y la pantalla
   se volvio un rollo de scroll con el formulario a un
   kilometro del final. Eso es lo que se veia roto.

   La solucion no es volver a poner un alto y scrollear
   vertical. Con 310 rubros, scrollear hacia abajo adentro de
   una columna angosta es exactamente lo que se sentia mal
   antes. Se cambia el eje: `flex-flow: column wrap` con alto
   fijo hace que los rubros llenen una columna, sigan en la de
   al lado, y la lista crezca hacia la DERECHA. Se corre con
   las dos flechas, como una gondola.

   El ancho fijo de cada rubro no es decoracion: con `wrap` en
   columna, un item que se estira segun su texto hace que cada
   columna tenga un ancho distinto y la reja se ve chueca.
   ========================================================== */

/* EL CUERPO TIENE UN ALTO PROPIO, Y ES EL DE LA PANTALLA.

   Esto es lo que hace que las dos columnas se sostengan. Sin un alto
   que NO venga del contenido, `flex: 1` sobre la lista no resuelve
   contra nada: la lista se mide por sus 310 rubros, la fila de la
   grilla se estira a esos 10.000px y volvemos al rollo, ahora peor.
   Es circular —la lista quiere el alto que sobra, y el alto que sobra
   depende de la lista— y se corta acá, poniendo el alto a mano.

   EL `calc(100vh - 300px)` DE ABAJO ES SOLO EL PISO DE ARRANQUE.

   Es un numero fijo que asume cuanto ocupa todo lo que va ARRIBA del
   cuerpo —titulo, descripcion, el panel de salud, el aviso de
   cosecha—. El dia que ese panel de salud se agrego, el numero quedo
   viejo: la pantalla real ocupaba mas de 300px de arriba y el cuerpo
   se pasaba del viewport entero, empujando "En esta PC" y el boton
   Buscar fuera de la pantalla sin que ningun scroll interno lo
   avisara —`overflow: visible` en la tarjeta deja que eso se derrame
   a scroll de PAGINA, que es exactamente lo que se queria evitar.

   `ajustarAltoCuerpo()` en js/prospectar.js mide lo de arriba DE
   VERDAD, cada vez que se entra al Hunter y cuando cambia el
   tamaño de la ventana, y pisa este alto con un `style.height`
   inline. Este `clamp` es solo lo que se ve un instante antes de que
   ese calculo corra, o si por lo que sea no corriera. */
#prospectar-modal.es-pagina .prosp-cuerpo {
    grid-template-columns: minmax(0, 2fr) minmax(340px, 1fr);
    height: clamp(520px, calc(100vh - 300px), 820px);
    /* `flex: none` no es opcional: la tarjeta es un flex en columna y
       el `flex: 1` que .prosp-cuerpo trae de la version modal fija
       `flex-basis: 0`, que en el eje principal MANDA sobre `height`.
       Con el flex puesto, el alto de arriba se ignoraba en silencio y
       la lista se seguia midiendo por sus 310 rubros. */
    flex: none;
    overflow: visible;
    min-height: 0;
}

#prospectar-modal.es-pagina .prosp-col { min-height: 0; }

/* La columna de la derecha scrollea sola si no entra. Es la
   excepcion a "nunca dos scrolls anidados" y esta puesta a
   conciencia: la alternativa es recortar el Top 10 o el tablero, que
   son justo los numeros que hay que ver ANTES de apretar Buscar. */
#prospectar-modal.es-pagina .prosp-col:last-child {
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-right: 4px;
}

/* LAS DOS COLUMNAS TERMINAN JUNTAS.

   Con el alto fijo en 440 la lista dejaba 239px de vacio abajo a la
   izquierda mientras la columna derecha seguia bajando: la tarjeta se
   veia tirada para un lado, que era el reclamo.

   La grilla ya estira las dos columnas a la misma altura —es lo que
   hace `align-items: stretch`, el valor por defecto—; lo que faltaba
   era que ese alto de mas se lo quedara ALGUIEN. Ahora se lo queda la
   lista, que es lo unico que puede crecer sin quedar raro.

   Y de paso arregla lo otro: con `column wrap`, mas alto son menos
   columnas. La lista paso de 26 columnas a la mitad, o sea la mitad
   de veces que hay que apretar la flecha. */
/* SOLO LA COLUMNA DE LA IZQUIERDA.

   Esto decia `.prosp-col > .prosp-bloque:first-child`, o sea el primer
   bloque de CADA columna. El de la derecha es "Dónde" —zona, ciudad,
   cuántas— y con `flex: 1; min-height: 0` se lo dejaba encoger por
   debajo de su contenido: los tres campos se salian del bloque y
   caian encima del Top 10. Se veian las dos cosas escritas una arriba
   de la otra y no habia forma de elegir la ciudad.

   El `:first-child` sobre .prosp-col es lo que faltaba: crecer es un
   privilegio de la lista de rubros, que es la unica que tiene de
   donde sacar contenido para llenar el hueco. */
#prospectar-modal.es-pagina .prosp-col:first-child > .prosp-bloque:first-child {
    flex: 1;
    min-height: 0;
}

/* Y los de la derecha se quedan quietos, con el alto que pide su
   contenido. Explicito y no por herencia: es el bug de arriba, y
   dejarlo dependiendo de que nadie escriba otra regla que los estire
   es como se vuelve. */
#prospectar-modal.es-pagina .prosp-col:last-child > .prosp-bloque,
#prospectar-modal.es-pagina .prosp-col:last-child > .prosp-tablero,
#prospectar-modal.es-pagina .prosp-col:last-child > .prosp-modos {
    flex: none;
    min-height: auto;
}

#prospectar-modal.es-pagina .prosp-chips {
    display: flex;
    flex-flow: column wrap;
    align-content: flex-start;
    /* El `min-height` es la red: si por lo que sea el `flex: 1` no
       resuelve —una pantalla muy baja, un navegador raro—, `wrap`
       necesita SI o SI un alto contra el cual partir en columnas. Sin
       el, la lista se estira a lo largo y volvemos al rollo. */
    flex: 1;
    height: auto;
    min-height: 0;
    gap: 2px 20px;
    overflow-x: auto;
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    scroll-behavior: smooth;
    padding-bottom: 4px;

    /* La barra de scroll nativa se esconde: ya hay dos flechas y una
       barrita de posicion abajo, y tener las dos cosas era el segundo
       renglon de gris que se veia en la captura. Se esconde la barra,
       no el scroll: la rueda con shift y el trackpad siguen andando. */
    scrollbar-width: none;
    -ms-overflow-style: none;
}

#prospectar-modal.es-pagina .prosp-chips::-webkit-scrollbar { display: none; }

#prospectar-modal.es-pagina .prosp-chip {
    width: 250px;
    flex: none;
    /* Un renglon mas bajo entra mas veces por columna, y cada rubro
       que entra de mas es una columna menos que correr con la flecha:
       310 rubros a 12 por columna son 26 columnas; a 14, son 22. */
    padding: 5px 9px;
}

/* La columna derecha, mas compacta, para que entre sin scroll en una
   pantalla normal. Los cuatro numeros del tablero en fila —eran dos
   por dos— y los diez nichos con el renglon justo. Es la diferencia
   entre ver el tablero entero antes de apretar Buscar y tener que
   scrollear para encontrarlo. */
#prospectar-modal.es-pagina .prosp-stats {
    grid-template-columns: repeat(4, 1fr);
    gap: 10px;
}

#prospectar-modal.es-pagina .prosp-stat b { font-size: 19px; }
#prospectar-modal.es-pagina .prosp-top-fila { padding: 4px 8px; }

/* El aviso de "ningun rubro dice eso" es de la version en
   grilla; en modo columna el grid-column no aplica y sin ancho
   propio se parte en una tira vertical de una letra. */
#prospectar-modal.es-pagina .prosp-nada { width: 100%; }

/* Las flechas y la barrita de posicion. */
.prosp-mover {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-top: 10px;
}

.prosp-mover__btn {
    flex: none;
    width: 30px;
    height: 30px;
    display: grid;
    place-items: center;
    color: var(--text-muted);
    background: transparent;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    cursor: pointer;
    transition: color .15s, border-color .15s;
}

.prosp-mover__btn:hover { color: var(--primary); border-color: var(--primary); }

/* Cuanto de la lista se esta viendo y por donde va. Es la
   unica pista de que a la derecha hay mas: una barra de scroll
   horizontal en Windows es de tres pixeles y no la ve nadie. */
.prosp-mover__pista {
    position: relative;
    flex: 1;
    height: 4px;
    background: var(--border-color);
    border-radius: 999px;
    overflow: hidden;
}

.prosp-mover__pista > i {
    position: absolute;
    top: 0;
    bottom: 0;
    background: var(--primary);
    border-radius: 999px;
    transition: left .18s ease, width .18s ease;
}

/* ==========================================================
   TOP 10 DE NICHOS
   ========================================================== */

.prosp-top { flex: none; }

.prosp-top-lista {
    margin: 0;
    padding: 0;
    list-style: none;
    counter-reset: nicho;
    display: flex;
    flex-direction: column;
    gap: 2px;
    /* Con diez nichos la lista sola puede llenar media columna y
       empujar el tablero y las tarjetas de "En esta PC" mas abajo de
       lo necesario. Techo de cinco filas y scroll propio: los primeros
       —los que importan— se ven siempre sin tener que bajar nada. */
    max-height: 168px;
    overflow-y: auto;
}

.prosp-top-fila {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 6px 8px;
    font: inherit;
    font-size: 13px;
    color: var(--text-main);
    background: transparent;
    border: 0;
    border-radius: 8px;
    text-align: left;
    cursor: pointer;
}

.prosp-top-fila::before {
    counter-increment: nicho;
    content: counter(nicho);
    flex: none;
    width: 16px;
    text-align: right;
    font-size: 11px;
    color: var(--text-muted);
}

.prosp-top-fila:hover { background: var(--bg-hover, rgba(255, 255, 255, .05)); }
.prosp-top-fila.elegido { color: var(--primary); font-weight: 600; }

.prosp-top-nombre {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* La barra compara contra el primero. Diez numeros sueltos hay
   que compararlos de a pares; con la barra el reparto se ve de
   una, que es para lo que sirve un ranking. */
.prosp-top-barra {
    flex: none;
    width: 70px;
    height: 4px;
    background: var(--border-color);
    border-radius: 999px;
    overflow: hidden;
}

.prosp-top-barra > i { display: block; height: 100%; background: var(--primary); }

.prosp-top-n {
    flex: none;
    width: 30px;
    text-align: right;
    font-size: 12px;
    font-variant-numeric: tabular-nums;
    color: var(--text-muted);
}

.prosp-top-vacio {
    padding: 10px 4px;
    font-size: 12px;
    line-height: 1.5;
    color: var(--text-muted);
}

/* ==========================================================
   LA BUSQUEDA ACTIVA, ARRIBA DE TODO
   ========================================================== */

.prosp-vivo {
    margin-bottom: 18px;
    padding: 14px 16px;
    background: color-mix(in srgb, var(--primary) 7%, transparent);
    border: 1px solid color-mix(in srgb, var(--primary) 35%, transparent);
    border-radius: 14px;
}

.prosp-vivo__cabeza {
    display: flex;
    align-items: center;
    gap: 14px;
}

.prosp-vivo__que { flex: 1; min-width: 0; }
.prosp-vivo__que b { display: block; font-size: 14px; }
.prosp-vivo__que span { font-size: 12px; color: var(--text-muted); }

.prosp-vivo__cifras { flex: none; text-align: right; }
.prosp-vivo__cifras b { display: block; font-size: 13px; font-variant-numeric: tabular-nums; }
.prosp-vivo__cifras span { font-size: 11px; color: var(--text-muted); }

/* El punto que late. Es la diferencia entre "esto corrio
   alguna vez" y "esto esta pasando ahora", y se lee sin
   leer. */
.prosp-vivo__pulso {
    flex: none;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--primary);
    animation: prospLatir 1.6s ease-in-out infinite;
}

@keyframes prospLatir {
    0%, 100% { opacity: 1; box-shadow: 0 0 0 0 color-mix(in srgb, var(--primary) 60%, transparent); }
    50% { opacity: .55; box-shadow: 0 0 0 6px transparent; }
}

/* Sin animacion para quien la pidio apagada: un punto que late
   sin parar en el borde del ojo es de las cosas que mas
   molestan a quien es sensible al movimiento. */
@media (prefers-reduced-motion: reduce) {
    .prosp-vivo__pulso { animation: none; }
}

.prosp-vivo .prospectar-barra { margin-top: 12px; }

.prosp-vivo__fila {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 10px;
    margin: 10px 0 0;
    font-size: 12px;
    color: var(--text-muted);
}

.prosp-vivo__fila em {
    font-style: normal;
    padding: 2px 9px;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: 999px;
}

/* ==========================================================
   MATCHER COMO PANTALLA: MAZO + RANKING
   20260814_4

   Dos columnas. El mazo a la izquierda con el ancho de una
   tarjeta de verdad —mas ancho no la mejora, la estira— y el
   ranking a la derecha ocupando lo que sobra, que es el lugar
   que antes era margen gris.

   Como modal el ranking no se muestra: en 560px no entra, y
   ahi el boton "Top 50" sigue haciendo lo de siempre.
   ========================================================== */

.matcher-tablero { display: block; }

.modal-overlay:not(.es-pagina) .matcher-rank { display: none; }

.es-pagina .matcher-tablero {
    display: grid;
    grid-template-columns: minmax(320px, 520px) minmax(0, 1fr);
    gap: 26px;
    align-items: start;
}

.matcher-rank {
    display: flex;
    flex-direction: column;
    min-width: 0;
    /* El mismo alto que la pila de tarjetas mas los botones:
       las dos columnas terminan a la misma altura y no queda
       un escalon. */
    max-height: calc(clamp(400px, 62vh, 660px) + 90px);
    padding: 16px 18px;
    background: var(--bg-surface);
    border: 1px solid var(--border-color);
    border-radius: 16px;
}

.matcher-rank__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 12px;
}

.matcher-rank__head h4 {
    margin: 0;
    font-size: 15px;
    letter-spacing: .01em;
}

.matcher-rank__filtros {
    display: flex;
    gap: 6px;
    margin-bottom: 12px;
}

.matcher-rank__chip {
    padding: 5px 12px;
    font: inherit;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-muted);
    background: transparent;
    border: 1px solid var(--border-color);
    border-radius: 999px;
    cursor: pointer;
    transition: color .15s, border-color .15s, background .15s;
}

.matcher-rank__chip:hover { color: var(--text-main); }

.matcher-rank__chip.es-activo {
    color: var(--primary);
    border-color: var(--primary);
    background: color-mix(in srgb, var(--primary) 12%, transparent);
}

/* Scrollea la lista, no la pagina: los filtros y el titulo se
   quedan donde el ojo los dejo, que es la razon por la que el
   ranking esta al costado y no abajo. */
.matcher-rank__cuerpo {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
}

/* EL LOGO ES UN CUADRADO, NO UNA BANDERA.

   `.matcher-top li > div { flex: 1 }` estaba pensado para el bloque
   del nombre, que es el unico <div> que habia cuando se escribio. El
   logo de respaldo —la inicial sobre color, cuando no hay captura—
   TAMBIEN es un <div>, asi que se comia esa regla: `flex: 1` le gana
   por especificidad al `flex: none` de .matcher-logo y el cuadradito
   de 34px se estiraba a media fila. En pantalla eran barras de color
   gigantes con una letra en el medio.

   Se arregla por los dos lados: el bloque del nombre ahora tiene
   clase propia, y el logo repite su tamaño con mas especificidad para
   que ninguna regla futura vuelva a estirarlo. */
.matcher-top__quien { flex: 1; min-width: 0; }

.matcher-rank__cuerpo .matcher-top .matcher-logo {
    flex: none;
    width: 34px;
    height: 34px;
}

/* Toda la fila lleva a la ficha, así que toda la fila se siente
   apretable. */
.matcher-rank__cuerpo .matcher-top li { cursor: pointer; }
.matcher-rank__cuerpo .matcher-top li:hover b { color: var(--primary); }
.matcher-rank__cuerpo .matcher-top li:hover { background: var(--bg-hover, rgba(255, 255, 255, .04)); }
.matcher-rank__cuerpo .matcher-top .matcher-rank__wa { cursor: pointer; }

/* EL CHEVRON NO ES ADORNO.

   Toda la fila abre la ficha del lead desde el dia uno, y lo unico
   que lo anunciaba era el `title`: habia que parar el mouse encima y
   esperar para enterarse de que se podia hacer clic. Una funcion que
   nadie descubre es una funcion que no existe.

   La flecha se ve siempre, apagada, y se enciende al pasar por
   encima: dice "esto lleva a algun lado" sin gritarlo cincuenta
   veces en una lista de cincuenta. */
.matcher-rank__ir {
    flex: none;
    margin-left: 2px;
    font-size: 11px;
    color: var(--text-muted);
    opacity: .45;
    transition: opacity .15s, transform .15s, color .15s;
}
.matcher-rank__cuerpo .matcher-top li:hover .matcher-rank__ir {
    opacity: 1;
    color: var(--primary);
    transform: translateX(2px);
}

/* Ya llamado: sigue en la lista pero apagado. Sacarlo de una seria
   peor —desaparecen filas sin explicacion mientras se trabaja—; para
   sacarlos de verdad esta el tilde "sin llamar". */
.matcher-rank__cuerpo .matcher-top li.es-llamado { opacity: .5; }
.matcher-rank__hecho { color: var(--success, #22c55e); }

/* Rubro y "sin llamar" van en su propia fila y mas chicos que los
   chips: los chips son la pregunta principal —que pila miro— y esto
   es como la recorto. Del mismo tamaño competirian. */
.matcher-rank__filtros.es-fila2 { margin-top: 6px; align-items: center; }

.matcher-rank__select {
    flex: 1;
    min-width: 0;
    padding: 4px 8px;
    font: inherit;
    font-size: 12px;
    color: var(--text-muted);
    background: transparent;
    border: 1px solid var(--border-color);
    border-radius: 8px;
    cursor: pointer;
}
.matcher-rank__select:hover { color: var(--text-main); }

.matcher-rank__check {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 12px;
    color: var(--text-muted);
    cursor: pointer;
    white-space: nowrap;
}
.matcher-rank__check input { cursor: pointer; }

/* Deshacer vive debajo de los tres botones del pulgar, centrado y
   discreto: tiene que estar a mano en el momento exacto en que se
   necesita, sin pelearle la atencion a los que se usan siempre. */
.matcher-deshacer {
    display: block;
    margin: 6px auto 0;
    font-size: 12px;
}
.matcher-deshacer.hidden { display: none; }

/* ==========================================================
   EL CARTEL DEL APRENDIZAJE

   Discreto a proposito. Cuando todavia no sabe nada —que es el
   caso el primer mes— tiene que poder ignorarse sin estorbar
   la lista, que es para lo que se abrio la pantalla. Cuando ya
   aprendio algo, el titulo en color se gana la mirada solo.
   ========================================================== */
.aprende {
    margin: 8px 0 4px;
    padding: 8px 10px;
    border: 1px solid var(--border-color);
    border-radius: 10px;
    background: color-mix(in srgb, var(--primary) 4%, transparent);
}

.aprende__cabeza {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    width: 100%;
    padding: 0;
    font: inherit;
    text-align: left;
    background: none;
    border: none;
    cursor: pointer;
}
.aprende__cabeza b { font-size: 12.5px; line-height: 1.3; }
.aprende__cabeza i { flex: none; font-size: 10px; color: var(--text-muted); }

.aprende__detalle {
    margin: 4px 0 0;
    font-size: 11.5px;
    line-height: 1.4;
    color: var(--text-muted);
}

.aprende__tabla { width: 100%; margin-top: 8px; border-collapse: collapse; font-size: 11.5px; }
.aprende__tabla td { padding: 3px 0; border-top: 1px solid var(--border-color); }
.aprende__tabla td:first-child { width: 52px; font-weight: 700; }
.aprende__que { color: var(--text-muted); }
.aprende__cuanto { text-align: right; font-weight: 600; white-space: nowrap; }

/* Un tramo sin datos suficientes se ve, pero apagado: esconderlo
   seria peor —nadie se acuerda de juntar datos de algo que no ve—
   y darle el mismo peso que a uno medido seria mentir. */
.aprende__tabla tr.es-flojo td { opacity: .5; font-weight: 400; }
.aprende .es-oro { color: var(--primary); }
.aprende .es-tibio { color: var(--warning); }
.aprende .es-frio { color: var(--text-muted); }

/* Los chips ahora llevan el icono del boton que los produce. */
.matcher-rank__chip i { font-size: 10px; margin-right: 2px; }
.matcher-rank__chip[data-rank-filtro="top"] i { color: var(--warning); }
.matcher-rank__chip[data-rank-filtro="interesa"] i { color: var(--danger, #ef4444); }

/* Los tres primeros con el numero grande: un ranking de
   cincuenta se lee de arriba, y el podio tiene que verse sin
   contar. */
.matcher-rank__cuerpo .matcher-top li:nth-child(-n+3)::before {
    font-size: 15px;
    font-weight: 700;
    color: var(--primary);
}

.matcher-rank__estrella { color: var(--warning); font-size: 11px; }

.matcher-rank__wa {
    flex: none;
    width: 30px;
    height: 30px;
    display: grid;
    place-items: center;
    color: var(--text-muted);
    border-radius: 8px;
    text-decoration: none;
}

.matcher-rank__wa:hover { color: #25d366; background: var(--bg-hover, rgba(255,255,255,.06)); }

@media (max-width: 1100px) {
    .es-pagina .matcher-tablero { grid-template-columns: 1fr; }
    .matcher-rank { max-height: 420px; }
}

/* ==========================================================
   LA GALERIA DE TEXTOS DE MENSAJES
   20260814_4

   Las plantillas eran un <select>: para saber que decia cada
   una habia que elegirla, leerla abajo y probar la siguiente.
   Nadie compara tres mensajes a quince clics, asi que se
   mandaba siempre la primera de la lista.

   Como tarjetas se leen los textos enteros de un vistazo. El
   recorte a seis lineas es a proposito: la tarjeta sirve para
   comparar, y el texto completo esta abajo en el editor.
   ========================================================== */

.campana-galeria {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: 12px;
    margin-bottom: 18px;
}

.campana-texto {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 16px 18px;
    text-align: left;
    font: inherit;
    /* El color va explicito y no se da por heredado: `font: inherit`
       trae la tipografia pero NO el color, asi que un <button> sin
       esta linea se queda con el `buttontext` del navegador —negro—
       y cualquier hijo que no fije su propio color lo hereda. Es lo
       que hacia invisible al titulo de la plantilla sobre el fondo
       oscuro. */
    color: var(--text-main);
    /* Mas claro que el panel que las contiene (--surf-1), no mas
       oscuro: una tarjeta que se elige tiene que leerse levantada
       sobre la superficie, y con --bg-surface quedaba hundida, como
       un agujero en el panel. */
    background: var(--surf-2);
    border: 1px solid var(--border-color);
    border-radius: 14px;
    cursor: pointer;
    transition: border-color .15s, transform .15s, box-shadow .15s;
}

.campana-texto:hover { transform: translateY(-2px); border-color: var(--primary); }

.campana-texto.es-elegida {
    border-color: var(--primary);
    box-shadow: 0 0 0 1px var(--primary) inset;
}

.campana-texto__titulo {
    font-size: 13px;
    font-weight: 700;
    color: var(--text-main);
}

.campana-texto__cuerpo {
    font-size: 12.5px;
    line-height: 1.6;
    color: var(--text-muted);
    white-space: pre-wrap;
    /* Ocho lineas y puntos suspensivos. Ver el comentario de
       arriba: la tarjeta compara, el editor muestra todo. Eran
       seis y cortaban antes de que se entendiera de que va cada
       plantilla, que es lo unico que esta tarjeta tiene que
       resolver. */
    display: -webkit-box;
    -webkit-line-clamp: 8;
    line-clamp: 8;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Que el texto de abajo ya no es el de la plantilla. Sin esto
   se edita a mano, se cambia de tarjeta sin querer y no hay
   forma de saber que lo escrito se perdio. */
.campana-editado {
    margin-left: 8px;
    padding: 1px 7px;
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--warning);
    border: 1px solid var(--warning);
    border-radius: 999px;
}

.campana-previa-rotulo .copiado,
.btn-enlace.copiado { color: var(--success, #22c55e); }

/* Como pantalla la campaña usa el ancho: los filtros en cuatro
   columnas. El alto de la lista es el mismo fijo que en el
   dialogo —no el 52vh de antes—: en Email, sin rubro que la
   acote, esa lista podia empujar toda la pagina hacia abajo. */
#campana-modal.es-pagina .campana-lista { max-height: 320px; }

/* ==========================================================
   MENSAJES EN PC: DOS COLUMNAS, NO UN ROLLO VERTICAL
   Las cinco secciones (Filtrar, Elegir, Mensaje, Enviar, Historial)
   se apilaban una abajo de la otra a un solo ancho de columna —en un
   monitor ancho, media pantalla quedaba vacia a los costados y habia
   que scrollear para leer el paso 4. Mismo recurso que en
   Configuración: columnas CSS en vez de una lista vertical, asi cada
   tarjeta arranca apenas termina la de arriba EN SU COLUMNA, no
   espera a que termine toda la fila.

   Solo desde 1100px: mas angosto que eso las columnas no entrarian
   sin apretar el contenido, y el celular tiene que seguir siendo
   una lista simple de arriba a abajo. */
@media (min-width: 1100px) {
    #campana-modal.es-pagina .campana-cuerpo {
        column-width: 480px;
        column-gap: var(--e-4, 16px);
    }

    #campana-modal.es-pagina .campana-seccion {
        break-inside: avoid;
        display: inline-block;
        width: 100%;
        box-sizing: border-box;
    }
}

/* --- Lo cosechado, adentro del Hunter --- */
.prosp-cosecha {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 1rem;
    padding: 12px 16px;
    border-radius: 14px;
    border: 1.5px solid var(--border-glow);
    background: rgba(var(--acento-rgb), 0.10);
}

.prosp-cosecha.hidden { display: none; }

.prosp-cosecha__num {
    font-size: 1.6rem;
    font-weight: 800;
    color: var(--primary);
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

.prosp-cosecha__txt { flex: 1; min-width: 0; }
.prosp-cosecha__txt b { display: block; font-size: 0.85rem; color: var(--text-main); }
.prosp-cosecha__txt span { font-size: 0.7rem; color: var(--text-dim); }

@media (max-width: 560px) {
    .prosp-cosecha { flex-wrap: wrap; }
    .prosp-cosecha__txt { flex-basis: 100%; order: 3; }
}

/* ==========================================================
   SALUD DEL BUSCADOR
   20260814_4

   Cuatro luces arriba del Hunter. El color lo pone el estado,
   no la decoracion: verde es "anda", ambar es "anda pero mal",
   rojo es "esto es lo que te esta frenando".
   ========================================================== */

.salud-tablero {
    display: grid;
    grid-template-columns: repeat(4, 1fr) auto;
    gap: 8px;
    align-items: stretch;
    margin-bottom: 1rem;
}

.salud-tablero:empty { display: none; }

.salud-luz {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 9px 11px;
    border-radius: 11px;
    border: 1.5px solid var(--border-glow);
    background: rgba(var(--acento-rgb), 0.05);
    min-width: 0;
}

.salud-luz i { font-size: 0.9rem; margin-top: 2px; flex-shrink: 0; }

.salud-luz__txt { min-width: 0; display: flex; flex-direction: column; }
.salud-luz__txt b { font-size: 0.68rem; color: var(--text-dim); font-weight: 700; }

.salud-luz__valor {
    font-size: 0.86rem;
    font-weight: 800;
    color: var(--text-main);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.salud-luz__detalle {
    font-size: 0.64rem;
    color: var(--text-dim);
    line-height: 1.3;
}

.salud-luz.es-bien i    { color: var(--primary); }
.salud-luz.es-regular i { color: #f59e0b; }
.salud-luz.es-neutro i  { color: var(--text-dim); opacity: 0.6; }

/* El rojo tiñe la tarjeta entera y no solo el icono: es lo unico
   que hay que mirar cuando algo no anda, y un icono de doce
   pixeles no gana contra cuatro tarjetas iguales. */
.salud-luz.es-mal {
    border-color: rgba(220, 38, 38, 0.55);
    background: rgba(220, 38, 38, 0.10);
}
.salud-luz.es-mal i { color: #dc2626; }

.salud-cola {
    display: flex;
    align-items: center;
    padding: 0 12px;
    font-size: 0.7rem;
    color: var(--text-dim);
    white-space: nowrap;
}
.salud-cola b { color: var(--text-main); }

@media (max-width: 900px) {
    .salud-tablero { grid-template-columns: 1fr 1fr; }
    .salud-cola { grid-column: 1 / -1; justify-content: center; }
}
