/* ===================================================================
 *  crm.css  ·  CRM Ingenieros AVI
 *
 *  Salio del archivo unico CRM_Vainova_prototipo.html el 03/09/2026.
 *  El contenido NO se toco: es el mismo, movido de sitio.
 *
 *  POR QUE SE SEPARO
 *    Todo el CRM vivia en un archivo de 1,26 MB. Cambiar un color
 *    obligaba a reescribirlo entero por la unidad de red, y esa
 *    unidad corta las escrituras grandes. Ahora cada cambio toca
 *    solo la parte que le corresponde.
 *
 *  EL ORDEN IMPORTA
 *    Se carga en el mismo punto del documento en el que estaba. No
 *    lo mueva de sitio ni le ponga «defer»: hay codigo que cuenta
 *    con que el marcado de arriba ya este pintado.
 * =================================================================== */

/* ---------- bloque 5 del archivo original ---------- */

/* ============================================================
   ZONA · BASE, VARIABLES Y TIPOGRAFIA
   9 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
/* ============================================================
   CONTRASTE DEL TEMA OSCURO   [01/09/2026]

   COMO SE ELIGIERON ESTOS COLORES
     Midiendo, no a ojo. Se calculo la relacion de contraste de cada
     color contra los tres fondos del tema (--bg, --panel y --panel2) y
     se subio hasta pasar el minimo. Elegir «un gris un poco mas claro»
     mirando la pantalla es como se llego al problema.

   QUE ESTABA MAL

     --line  era #2f363d: contraste 1,15 sobre las tarjetas internas.
       Por debajo de 1,5 una linea sencillamente NO SE VE. Los bordes de
       tarjetas, los separadores de tablas y las divisiones de los
       formularios estaban ahi, dibujados, invisibles. Sube a #525B65:
       2,04 sobre panel2 y 2,59 sobre el fondo. Se ve sin volverse un
       alambrado.

     --bad   era #ef4444: 3,74 sobre panel2, por debajo del 4,5 que pide
       un texto normal. Es el color de los errores y de lo que falta, o
       sea justo lo que hay que poder leer. Sube a #f87171: 5,09.

   EN CLARO NO SE TOCA NADA
     Ahi los contrastes ya cumplian, y el usuario dijo que funciona
     bien. Cambiarlo por simetria seria arreglar lo que no esta roto.

   LOS COLORES CON SIGNIFICADO, AHORA SON VARIABLES
     Compra, venta, alerta y aviso estaban escritos a mano en cada
     componente con el mismo valor para los dos temas. En oscuro, el
     ambar #b45309 daba 3,23 y el rojo 3,35: se leian mal. Ahora cada
     uno tiene su version por tema y se usan por nombre, de modo que
     arreglar uno los arregla en todas las pantallas a la vez.
   ============================================================ */
:root{
  --bg:#14181C; --panel:#1c2127; --panel2:#262c33; --line:#525B65;
  --txt:#e6e9ec; --muted:#98a1ab; --accent:#E8C86A; --accent2:#B8860B;
  --ok:#22c55e; --warn:#f59e0b; --bad:#f87171; --purple:#a78bfa;
  /* Colores con significado, legibles sobre fondo oscuro */
  --c-compra:#38bdf8; --c-venta:#4ade80; --c-rojo:#f87171; --c-ambar:#fbbf24;
  /* ============================================================
     TINTES SUAVES — ESCRITOS, NO CALCULADOS      [04/09/2026]

     Estos tres fondos se hacían con color-mix(). Se cambian a rgba
     literal por un motivo concreto y caro: html2canvas —el motor con
     el que este CRM genera TODOS sus PDF— no entiende color-mix() y
     aborta el dibujo entero al encontrarlo. El resultado no es un
     color mal puesto: es un PDF completamente EN BLANCO.

     Pasó el mismo día que se añadieron: la descarga de la
     programación salía vacía, y de rebote quedaba en riesgo el PDF
     del reporte SISO, que usa el mismo motor sobre esta misma hoja.

     La regla que queda para esta hoja: nada de color-mix(), oklch()
     ni colores relativos. Todo lo que se dibuje en un PDF tiene que
     estar escrito con colores que un motor de hace dos años entienda.
     ============================================================ */
  --acento-tenue:rgba(232,200,106,.09);
  --acento-suave:rgba(232,200,106,.15);
  --warn-suave:rgba(245,158,11,.13);
}
html[data-theme="light"]{
  --bg:#eef2f7; --panel:#ffffff; --panel2:#f1f5f9; --line:#d7dee7;
  --txt:#0f172a; --muted:#5c6b7a; --accent:#B8860B; --accent2:#8a6708;
  --ok:#16a34a; --warn:#d97706; --bad:#dc2626; --purple:#7c3aed;
  /* Los mismos significados, en su version oscura para papel claro */
  --c-compra:#0369a1; --c-venta:#15803d; --c-rojo:#dc2626; --c-ambar:#b45309;
  /* Los mismos tintes, sobre el acento del tema claro. */
  --acento-tenue:rgba(184,134,11,.09);
  --acento-suave:rgba(184,134,11,.15);
  --warn-suave:rgba(217,119,6,.13);
}
html[data-theme="light"] body{background:var(--bg);color:var(--txt)}
html[data-theme="light"] .side{box-shadow:0 0 0 1px #e2e8f0}
html[data-theme="light"] .card,html[data-theme="light"] .kpi{box-shadow:0 4px 14px rgba(15,23,42,.06)}
html[data-theme="light"] tr:hover td{background:#eef4fb}
/* Menú lateral: texto oscuro y selección resaltada en claro */
html[data-theme="light"] .nav a{color:#334155}
html[data-theme="light"] .nav a:hover{color:#0f172a;background:#e8eef6}
html[data-theme="light"] .nav a.active{background:#e0f2fe;color:#0c4a6e;font-weight:600;border-left-color:#0284c7;box-shadow:inset 0 0 0 1px #bae6fd}
.theme-sel{background:var(--panel2);border:1px solid var(--line);color:var(--txt);padding:6px 8px;border-radius:8px;font-size:12px;cursor:pointer}
/* Tiquetes · nivel de precio estilo Google Flights */
.nivel-bar{height:9px;border-radius:6px;background:linear-gradient(90deg,#22c55e 0%,#facc15 52%,#ef4444 100%);position:relative;margin:8px 0}
.nivel-mark{position:absolute;top:-4px;width:17px;height:17px;border-radius:50%;background:#fff;border:3px solid var(--accent2);transform:translateX(-50%);box-shadow:0 2px 6px rgba(0,0,0,.45)}
.nivel-scale{display:flex;justify-content:space-between;font-size:10px;color:var(--muted)}
.nivel-txt{font-size:13px;color:var(--txt)}
.vsm-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:12px}
.vsm-card{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:8px 10px;cursor:pointer;transition:border-color .15s,transform .12s}
.vsm-card:hover{border-color:var(--accent);transform:translateY(-2px)}
/* Tarjeta de la aerolínea más económica: latido suave y contorno verde
   tenue. Se destaca sin gritar, y sigue leyéndose como una tarjeta más. */
@keyframes vsmLatido{
  0%,100%{box-shadow:0 0 0 1px rgba(34,197,94,.45),0 0 0 0 rgba(34,197,94,0)}
  50%    {box-shadow:0 0 0 1px rgba(34,197,94,.75),0 0 14px 3px rgba(34,197,94,.22)}
}
.vsm-card{position:relative}
.vsm-mejor{border-color:rgba(34,197,94,.55);background:rgba(34,197,94,.06);animation:vsmLatido 2.4s ease-in-out infinite}
.vsm-mejor:hover{border-color:#22c55e}
.vsm-tag{position:absolute;top:-9px;right:10px;background:#14532d;color:#86efac;border:1px solid rgba(34,197,94,.5);
  font-size:9.5px;font-weight:700;padding:2px 8px;border-radius:20px;letter-spacing:.2px}
.vsm-ahorro{margin-top:4px;font-size:10.5px;color:#86efac;text-align:right}
@media(prefers-reduced-motion:reduce){ .vsm-mejor{animation:none} }
.vsm-ov{position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:130;display:flex;align-items:center;justify-content:center;padding:20px}
.vsm-ov-card{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:22px 24px;width:920px;max-width:95vw;position:relative;box-shadow:0 30px 80px rgba(0,0,0,.6)}
.vsm-ov-x{position:absolute;top:10px;right:12px;background:none;border:none;color:var(--muted);font-size:20px;cursor:pointer}
.vsm-title{font-size:12px;font-weight:700;margin-bottom:2px;color:var(--txt)}
.vsm-foot{display:flex;justify-content:space-between;align-items:center;font-size:11px;color:var(--muted);margin-top:3px;gap:6px;flex-wrap:wrap}
.clk-name{cursor:pointer}
.clk-name:hover{color:var(--accent);text-decoration:underline}
/* Cumpleaños */
.cumple-banner{background:linear-gradient(135deg,rgba(124,58,237,.18),rgba(236,72,153,.18));border:1px solid #a78bfa;color:var(--txt);border-radius:12px;padding:12px 16px;margin-bottom:14px;font-size:14px}
.confetti-wrap{position:fixed;inset:0;pointer-events:none;z-index:300;overflow:hidden}
.confetti{position:absolute;top:-20px;width:9px;height:14px;border-radius:2px;opacity:.92;animation:conffall linear forwards}
@keyframes conffall{0%{transform:translateY(-20px) rotate(0)}100%{transform:translateY(106vh) rotate(720deg)}}
.cumple-msg{position:absolute;top:20%;left:50%;transform:translateX(-50%);background:linear-gradient(135deg,#7c3aed,#ec4899);color:#fff;padding:20px 34px;border-radius:16px;font-size:22px;font-weight:800;text-align:center;box-shadow:0 20px 60px rgba(0,0,0,.5);transition:opacity 1.5s;max-width:90vw}
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:'Segoe UI',system-ui,sans-serif;background:var(--bg);color:var(--txt);font-size:14px;overflow-x:hidden}
.app{display:flex;min-height:calc(100vh/var(--z));--z:1;zoom:var(--z)}
/* Modales/overlays a pantalla completa: neutralizan el zoom para no desbordarse */
.app .overlay,.app .vsm-ov,.app .confetti-wrap{zoom:calc(1/var(--z,1))}
/* ==== Escalado de interfaz segun tamano de pantalla (mas grande = mas grandecito) ==== */
@media(min-width:1500px){.app{--z:1.10}}
@media(min-width:1750px){.app{--z:1.18}}
@media(min-width:2100px){.app{--z:1.28}}
@media(min-width:2560px){.app{--z:1.40}}
.side{width:var(--side-w,230px);background:var(--panel);border-right:1px solid var(--line);padding:18px 0;position:sticky;top:0;height:calc(100vh/var(--z));display:flex;flex-direction:column}
.nav{flex:1;overflow-y:auto;min-height:0}

/* ============================================================
   LA BARRA SE APARTA CUANDO NO SE LA NECESITA   [SEC-01]

   El menú se usa unos segundos y se mira el resto del tiempo, pero
   ocupa 230 px de ancho todo el rato. Al llevar el cursor al contenido
   la barra se recoge a los iconos y le devuelve ese espacio a lo que
   se está leyendo; al acercar el cursor al borde izquierdo vuelve
   entera. Nada se pierde: los iconos siguen ahí y siguen sirviendo.

   CÓMO SE ACTIVA EN CADA APARATO
     Con ratón, la cercanía del cursor la abre y la aleja. Con el dedo
     no existe «acercar»: se toca o no se toca. Así que en pantalla
     táctil ancha -un iPad en horizontal- la misma barra se recoge
     igual, pero se abre TOCÁNDOLA. El aspecto y la animación son los
     mismos; lo único que cambia es el gesto que la dispara.

     La primera versión metía todo dentro de (hover:hover), así que en
     el iPhone y en el iPad no ocurría nada. El error fue dejar que una
     regla de CSS decidiera algo que depende del aparato: ahora lo
     decide el código, que sí puede distinguir los casos, y el CSS solo
     se ocupa de cómo se ve.

     En el teléfono la barra no se recoge a iconos -60 px de rail en una
     pantalla de 390 se comen la sexta parte del ancho-: allí sigue
     siendo un cajón que entra y sale, pero ahora también con gestos.

   Se anima solo el ancho de la barra y la opacidad de los textos.
   `main` es flexible: sigue el cambio sin necesidad de animarse.
   ============================================================ */
/* ============================================================
   ZONA · BASE, VARIABLES Y TIPOGRAFIA
   36 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
:root{--side-w:230px; --side-min:60px}
@media (min-width:821px){
  body.sidefx .side{
    width:var(--side-min);
    overflow:hidden;
    transition:width .30s cubic-bezier(.4,0,.2,1);
    will-change:width;
  }
  body.sidefx.side-full .side{ width:var(--side-w); }

  /* ---- Los textos no solo se desvanecen: dejan de ocupar sitio ----
     Con opacidad 0 el texto seguía midiendo lo mismo. La fila del menú
     medía sus 150 px de siempre dentro de una franja de 60, y al
     centrarla lo que quedaba a la vista era la mitad de una palabra
     invisible: el icono se salía por la izquierda. Por eso la barra
     recogida se veía vacía.

     La solución es que el texto encoja a cero. Así el icono es lo único
     que queda y aparece centrado, que es lo que hay que ver. */
  body.sidefx .side .lb,
  body.sidefx .side .ubox-tx,
  body.sidefx .side .side-salir-tx,
  body.sidefx .side .brand span,
  /* El NIT se recoge con el nombre. Si se quedara, con la barra
     angosta saldría un número suelto debajo del logo, sin nada que
     diga de qué es. [08/09/2026] */
  body.sidefx .side .brand-nit{
    opacity:0; max-width:0; overflow:hidden; white-space:nowrap;
    transition:opacity .12s ease, max-width .30s cubic-bezier(.4,0,.2,1);
  }
  body.sidefx.side-full .side .lb,
  body.sidefx.side-full .side .ubox-tx,
  body.sidefx.side-full .side .side-salir-tx,
  body.sidefx.side-full .side .brand span,
  body.sidefx.side-full .side .brand-nit{
    opacity:1; max-width:200px;
    transition:opacity .2s ease .1s, max-width .30s cubic-bezier(.4,0,.2,1);
  }
/* fin [SEC-01] */

  /* ============================================================
     NADA CAMBIA DE ALTO AL RECOGERSE   [SEC-02]

     Esto se hizo mal la primera vez. Al recogerse la barra yo cambiaba
     el tamaño del logo, el de los iconos y el alto de los títulos de
     grupo. Cada uno de esos cambios movía verticalmente todo lo que
     venía debajo, y como cambiaban a la vez, el menú entero se
     reacomodaba: los iconos bailaban y algunos quedaban fuera de la
     zona visible del menú, que es por lo que parecían desaparecer.

     La regla ahora es una sola y no admite excepciones:
     RECOGER LA BARRA SOLO CAMBIA ANCHOS Y OPACIDADES. NINGÚN ALTO.

     Así cada icono conserva su posición vertical exacta y la foto del
     perfil no se mueve un píxel. Lo único que se desplaza es el borde
     derecho de la barra, que es de lo que se trata.
     ============================================================ */

  /* La fila mide siempre lo mismo: 42 px. El relleno lateral cambia;
     el vertical, jamás. */
  body.sidefx .side .nav a{
    height:42px; padding-top:0; padding-bottom:0; box-sizing:border-box;
    padding-left:0; padding-right:0; gap:0; justify-content:center;
    transition:padding .30s cubic-bezier(.4,0,.2,1), background .12s ease;
  }
  body.sidefx.side-full .side .nav a{
    padding-left:20px; padding-right:20px; gap:10px; justify-content:flex-start;
  }
  /* El icono vive en una caja de alto fijo. Puede crecer de tamaño de
     letra sin empujar nada, porque la caja no cambia. */
  body.sidefx .side .nav a .ic,
  body.sidefx .side .side-pin .ic{
    display:inline-flex; align-items:center; justify-content:center;
    height:20px; line-height:20px; flex:0 0 auto;
    font-size:17px; width:22px;
    transition:font-size .2s ease, width .30s cubic-bezier(.4,0,.2,1);
  }
  body.sidefx.side-full .side .nav a .ic,
  body.sidefx.side-full .side .side-pin .ic{ font-size:13px; width:18px; }

  /* Lo mismo para la fila de fijar el menú. */
  body.sidefx .side .side-pin{
    height:42px; padding-top:0; padding-bottom:0; box-sizing:border-box;
  }

  body.sidefx .side .brand{ padding-left:0; padding-right:0; text-align:center; }
  /* ------------------------------------------------------------------
     CENTRADO TAMBIÉN CON LA BARRA DESPLEGADA        [08/09/2026]

     Aquí decía `text-align:left`, y era la causa de que el nombre
     saliera descuadrado: el logo se centra solo —lleva `margin:0
     auto`— pero el texto se iba a la izquierda, así que el conjunto
     se veía torcido justo debajo de un logo que sí estaba centrado.

     Se arregló en su día el desajuste de DOS píxeles que provoca el
     `letter-spacing` (ver `.brand span`), pero seguía sin verse
     centrado porque el problema real estaba aquí y era de veinte.
     ------------------------------------------------------------------ */
  body.sidefx.side-full .side .brand{ padding-left:20px; padding-right:20px; text-align:center; }
  /* ---- El logo conserva su ALTO; lo que cambia es el ancho ----
     Antes pasaba de 160 px a 40 px de ancho y, al mantener la
     proporción, su alto caía con él: eso solo ya empujaba hacia arriba
     el menú completo. Con alto fijo y object-fit la imagen se encoge
     dentro de su caja sin deformarse y sin mover nada. */
  body.sidefx .side .brand-logo{
    width:44px; height:44px; object-fit:contain; object-position:center;
    margin:0 auto 12px;
    transition:width .30s cubic-bezier(.4,0,.2,1), margin .30s ease;
  }
  body.sidefx.side-full .side .brand-logo{
    width:auto; height:68px; object-fit:contain; object-position:center;
    margin:0 auto 12px;
  }
  /* Recogida: la foto arriba, la salida debajo, las dos centradas.
     El botón se encoge a un cuadrado del tamaño de la foto para que la
     columna quede alineada y no se salga de los 60 px. */
  /* ---- La foto del perfil no se mueve nunca ----
     La ficha va pegada al fondo con margen automático y con ALTO FIJO.
     El alto es lo que importa: si cambiara, la foto subiría o bajaría
     aunque la ficha siga anclada abajo.

       renglón 1  ·  foto 34 px   (con o sin el nombre al lado)
       separación ·  9 px
       renglón 2  ·  botón 36 px
       relleno    ·  10 arriba + 12 abajo
       ------------------------------------
       total          101 px, en los dos estados
  */
  body.sidefx .side .userbox{
    margin-top:auto; height:101px; box-sizing:border-box;
    padding-top:10px; padding-bottom:12px;
    padding-left:6px; padding-right:6px;
    transition:padding .30s cubic-bezier(.4,0,.2,1);
  }
  body.sidefx.side-full .side .userbox{ padding-left:20px; padding-right:20px; }
  body.sidefx .side .ubox{ justify-content:center; gap:0; }
  body.sidefx.side-full .side .ubox{ justify-content:flex-start; gap:10px; }
  /* El botón conserva su ALTO (36 px) y solo cambia de ancho. */
  body.sidefx .side .side-salir{
    gap:0; width:34px; min-width:34px; padding:0 0; height:36px;
    margin-left:auto; margin-right:auto;
    transition:width .30s cubic-bezier(.4,0,.2,1);
  }
  body.sidefx.side-full .side .side-salir{
    width:auto; min-width:0; padding:0 10px; gap:6px; height:36px;
  }

  /* ---- Los grupos siguen separándose sin su título ----
     El nombre del grupo no cabe en 60 px, pero la separación entre
     bloques sí importa: es lo que impide que veinte iconos se lean como
     una columna sola.

     La versión anterior aplastaba el título de 32 px a 1 px. Con dos
     grupos eso son 62 px que se esfumaban y arrastraban hacia arriba
     medio menú. Ahora el bloque MIDE LO MISMO en los dos estados: solo
     se apaga el texto y aparece una raya centrada en su lugar. */
  body.sidefx .side .navsec{
    position:relative; height:32px; box-sizing:border-box;
    padding:14px 0 5px; margin:0; font-size:10px; letter-spacing:1.5px;
    color:transparent; overflow:hidden;
    transition:color .12s ease;
  }
  body.sidefx .side .navsec::after{
    content:""; position:absolute; left:50%; top:50%;
    width:26px; height:1px; margin-left:-13px;
    background:var(--line);
    transition:opacity .2s ease; opacity:1;
  }
  body.sidefx.side-full .side .navsec{
    height:32px; padding:14px 20px 5px; color:var(--muted);
    transition:color .2s ease .1s;
  }
  body.sidefx.side-full .side .navsec::after{ opacity:0; }
  /* El grupo abierto se marca aunque no se lea su nombre. */
  body.sidefx .side .nav a.active{ background:var(--panel2); }

  /* ---- Fijar el menú: una fila más, al final de la lista ----
     Flotando sobre el logo lo tapaba y había que descubrirlo apuntando.
     Aquí abajo se lee, no estorba, y con la barra recogida deja solo su
     icono igual que las demás secciones. */
  body.sidefx .side-pin{ display:flex; }
  body.sidefx .side-pin{ justify-content:center; padding-left:0; padding-right:0; gap:0; }
  body.sidefx.side-full .side-pin{ justify-content:flex-start; padding-left:20px; padding-right:20px; gap:10px; }
  body.sidefx .side-pin .ic{ font-size:17px; width:22px; }
  body.sidefx.side-full .side-pin .ic{ font-size:13px; width:18px; }
  /* Fijado: se marca como una sección activa, con el mismo lenguaje. */
  body.sidefx.side-fijo .side-pin{ color:var(--txt); background:var(--panel2);
    border-left-color:var(--accent); }

  /* ---- El gesto en pantalla táctil ----
     La barra recogida entera es el botón: se toca en cualquier parte
     que no sea un enlace y se abre. Un blanco de 60 px de ancho por
     toda la altura no hay forma de fallarlo. */
  body.sidefx-tap .side{cursor:pointer}
  body.sidefx-tap .side .nav a{cursor:pointer}
  /* Pista visible de que la barra se puede abrir. */
  body.sidefx-tap .side .brand{position:relative}
  body.sidefx-tap:not(.side-full) .side .brand::after{
    content:"›"; position:absolute; right:6px; bottom:14px;
    color:var(--accent); font-size:18px; font-weight:700; line-height:1; opacity:.75}
}
/* Si el equipo pide menos movimiento, la barra se recoge igual pero sin
   deslizarse: el comportamiento es útil, la animación es adorno. */
@media (prefers-reduced-motion:reduce){
  body.sidefx .side, body.sidefx .side *{transition:none!important}
}
/* ============================================================
   ZONA · BARRA LATERAL Y MENU
   13 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
/* El bloque de marca va centrado sobre la barra lateral. Antes el logo
   se pegaba al borde izquierdo -margen automatico no habia- y con el
   nombre debajo tambien a la izquierda quedaba todo escorado dentro de
   una columna de 230 px. Se centra el bloque entero, no solo la
   imagen: centrar el logo y dejar el nombre a un lado se veria peor
   que como estaba. [03/09/2026] */
.brand{padding:0 20px 18px;border-bottom:1px solid var(--line);margin-bottom:12px;text-align:center}
.brand h1{font-size:20px;letter-spacing:1px;color:var(--txt)}
/* «CALEP S.A.S» centrado de verdad. El bloque ya iba centrado, pero
   letter-spacing anade su espacio TAMBIEN despues de la ultima letra,
   y ese sobrante empuja el texto 2 px a la izquierda. Se compensa con
   el mismo margen en negativo. Es un detalle de dos pixeles que se
   nota justo debajo de un logo que si esta centrado. [04/09/2026] */
.brand span{display:block;color:var(--accent);font-size:11px;letter-spacing:2px;
  text-transform:uppercase;margin-right:-1px}
/* ------------------------------------------------------------------
   ERAN −2 px Y SOBRABA UNO                          [08/09/2026]

   El comentario de arriba está bien en el diagnóstico y se pasó en la
   cuenta. El `letter-spacing` añade 2 px DESPUÉS de la última letra,
   así que la caja del texto mide 2 px más de lo que se ve. Al
   centrarla, ese sobrante se reparte entre los dos lados: los glifos
   quedan UN píxel a la izquierda, no dos. Compensar con −2 px los
   mandaba uno a la derecha.

   Medido en el navegador, con la barra en 230 px:
     centro de la caja ...... 115,0
     centro del logo ........ 115,0
     centro del NIT ......... 115,0
     centro del nombre ...... 116,0  con −2 px   ->   115,5 con −1 px

   NO SE PERSIGA EL MEDIO PÍXEL QUE QUEDA. Sale de que el ancho del
   propio texto es impar, y medio píxel no se ve en ninguna pantalla.
   Queda escrito aquí para que nadie lo «arregle» otra vez y vuelva a
   descuadrarlo, que es exactamente como llegó a estar en −2.
   ------------------------------------------------------------------ */
/* ===================================================================
   EL NIT, DEBAJO DEL NOMBRE                         [08/09/2026]

   Se pidió que salga en la barra lateral. Va en su propio elemento y
   no pegado al nombre porque son dos datos distintos: cuando el CRM
   se instale para otra empresa, los dos salen de la misma variable
   pero se editan por separado. Ver ANALISIS_Marca_Variable.md.

   MÁS PEQUEÑO Y EN GRIS, A PROPÓSITO
     Es un dato de identificación fiscal, no la marca. Con el mismo
     peso que el nombre competiría con él y la barra pasaría a tener
     dos títulos.

   `tabular-nums` para que los dígitos no bailen: en una fuente
   proporcional el 1 es más angosto y un número centrado se ve
   descuadrado respecto al nombre de arriba.
   =================================================================== */
.brand-nit{display:block;margin-top:3px;color:var(--muted);
  font-size:9.5px;letter-spacing:.6px;font-variant-numeric:tabular-nums}
.nav a{display:flex;align-items:center;gap:10px;padding:11px 20px;color:var(--muted);cursor:pointer;text-decoration:none;border-left:3px solid transparent}
.nav a:hover{background:var(--panel2);color:var(--txt)}
.nav a.active{background:var(--panel2);color:var(--txt);border-left-color:var(--accent)}
.nav a .ic{width:18px;text-align:center;flex:0 0 18px}
/* ===================================================================
   EL CONTADOR DE AVISOS DEL MENÚ                     [08/09/2026]

   Un número redondo sobre la entrada del módulo que espera algo. Hoy
   lo encienden Personal Técnico y Usuarios cuando hay alguien que
   entró por una solicitud y sigue inactivo; el mecanismo —navAvisos()
   en crm-main.js— sirve para cualquier módulo que lo necesite después.

   VA COLOCADO ENCIMA, NO EN LA FILA
     La barra lateral se estrecha hasta dejar solo los iconos. Si el
     número fuera un elemento más de la fila, al encogerse empujaría la
     etiqueta o se saldría. Puesto en posición absoluta no ocupa sitio:
     se ve igual con la barra ancha y con la barra angosta.

   EL BORDE DEL COLOR DEL PANEL
     Ese «box-shadow» de 2 px no es adorno: separa el número del icono
     cuando la barra está angosta y los dos quedan casi encima.

   SIN PARPADEO
     Es un estado, no un suceso. Algo que va a estar encendido hasta
     que alguien lo atienda no puede estar moviéndose todo el rato: se
     vuelve ruido y se deja de mirar.
   =================================================================== */
.nav a{position:relative}
.nav a .nav-avisa{position:absolute;right:12px;top:50%;transform:translateY(-50%);
  min-width:18px;padding:0 5px;border-radius:9px;
  background:var(--accent);color:#14181C;
  font-size:11px;font-weight:700;text-align:center;line-height:17px;
  box-shadow:0 0 0 2px var(--panel)}
/* ============================================================
   EL MENÚ NO CORTA SUS PROPIAS ETIQUETAS      [05/09/2026]

   QUÉ SE VEÍA
     «Reportes SISO / Líd», «Facturas de com». Cortadas a media
     palabra, sin puntos suspensivos, en claro y en oscuro. Una entrada
     de menú que no dice su nombre completo obliga a adivinar, y la
     adivinanza se repite cada día.

   POR QUÉ PASABA
     La barra mide 230 px fijos y el texto es un elemento flexible.
     Por regla del navegador, un elemento así NO se encoge por debajo
     de lo que mide su contenido: en vez de partirse, se desborda, y
     el borde de la barra se lo come.

   CÓMO SE ARREGLA
     Se le permite encogerse («min-width:0») y partir en dos renglones.
     La entrada crece de alto lo justo y no mueve nada más: el menú es
     una columna. Se prefiere partir a poner puntos suspensivos porque
     unos puntos esconden la palabra, y aquí la palabra es el nombre
     del módulo.

     El icono se deja fijo para que no se estruje al partirse el texto.
   ============================================================ */
.nav a .lb{min-width:0;white-space:normal;overflow-wrap:break-word;line-height:1.25}
/* Las sub-entradas: sangradas, en letra menor y con una guia vertical
   que las ata a su seccion. Sin la guia parecen entradas sueltas del
   menu principal y se pierde la relacion. */
/* ============================================================
   EL SUBMENU SE VE COMO SUBMENU   [01/09/2026]

   Se corre mas a la derecha -de 40 a 52 px- y la guia vertical se hace
   mas visible. Con la sangria justa parecian entradas sueltas del menu
   principal, y la relacion «esto vive dentro de Facturas de compra»
   solo se entendia leyendo los nombres.

   LA AMPLIACION AL PASAR EL RATON
     Se pidio que al pasar por encima se note en que seccion se esta.
     Se agranda un poco la entrada y se corre a la derecha: es un gesto
     breve, del tamano justo para que el ojo lo registre sin que la
     lista entera se mueva. Un salto grande obligaria a volver a buscar
     donde quedo el cursor.

     Se anima solo `transform`, que el navegador resuelve sin rehacer la
     distribucion de la pagina: animar `padding` o `font-size` obliga a
     recalcular todo el menu en cada cuadro y se siente pesado en un
     telefono.

     Quien tenga activado «reducir movimiento» no ve la ampliacion; el
     resalte de color se conserva, que es lo que informa.
   ============================================================ */
.nav a{transition:transform .13s ease, background .13s, color .13s;transform-origin:left center}
.nav a:hover{transform:scale(1.035) translateX(3px)}
/* El contenedor plegable. Se anima la altura máxima y no `display`,
   que no se puede animar: sin transición el submenú aparece de golpe y
   cuesta ver de dónde salió. */
.navsubs{max-height:0;overflow:hidden;transition:max-height .2s ease}
/* 240 px alcanzaban para cuatro opciones de escritorio. En el cajón del
   teléfono las opciones son más altas —el dedo necesita más blanco que
   el cursor— y la cuarta quedaba cortada por la mitad. Se sube el techo:
   como es un máximo, no estira nada, solo deja de recortar. Sigue siendo
   un número y no «ninguno» porque la animación de abrir necesita medir
   contra algo. [02/09/2026] */
.navsubs.abierto{max-height:420px}
/* La flecha, alineada a la derecha de su entrada. */
.nav-fl{margin-left:auto;background:none;border:none;color:inherit;cursor:pointer;
  font-size:11px;line-height:1;padding:4px 2px 4px 8px;opacity:.65;font-family:inherit}
.nav-fl:hover{opacity:1}
.nav a.navsub{padding:8px 20px 8px 52px;font-size:12.5px;position:relative}
.nav a.navsub::before{content:"";position:absolute;left:32px;top:0;bottom:0;
  width:2px;background:var(--line);border-radius:2px}
/* La primera y la ultima recortan la guia para que no sobresalga del
   grupo: asi el trazo abraza al submenu en vez de atravesarlo. */
.nav a.navsub:first-of-type::before{top:6px}
.nav a.navsub:last-of-type::before{bottom:6px}
.nav a.navsub .ic{width:15px;font-size:12px;opacity:.85}
/* La lupa al pasar por encima solo con ratón de verdad. En pantalla
   táctil el «hover» se queda pegado después de tocar, así que la opción
   del submenú se quedaba agrandada y torcida hasta que uno tocara otra
   cosa, como si estuviera seleccionada. [02/09/2026] */
@media(hover:hover) and (pointer:fine){
  .nav a.navsub:hover{transform:scale(1.03) translateX(4px)}
}
.nav a.navsub.active{background:var(--panel2);color:var(--txt);border-left-color:transparent}
.nav a.navsub.active::before{background:var(--accent);width:3px;left:31px}
/* La seccion madre se marca mientras se esta en cualquiera de sus
   hijas: sin esto parecia que uno habia salido de Facturas de compra. */
.nav a[data-v="facturacion"].madre-activa{color:var(--txt)}
.nav a[data-v="facturacion"].madre-activa .ic{color:var(--accent)}
@media (prefers-reduced-motion: reduce){
  .nav a,.nav a:hover,.nav a.navsub:hover{transform:none;transition:background .13s,color .13s}
}

/* Fila para fijar el menú. Se viste como un elemento del menú porque se
   usa igual: una fila que se toca. Va fuera de la lista de navegación a
   propósito, para que no se confunda con una sección del CRM ni la
   recorra el teclado junto con ellas. */
.side-pin{display:none;align-items:center;gap:10px;width:100%;padding:10px 20px;
  background:none;border:none;border-left:3px solid transparent;border-top:1px solid var(--line);
  color:var(--muted);font-size:12.5px;font-family:inherit;text-align:left;cursor:pointer;
  transition:background .12s ease,color .12s ease,padding .30s cubic-bezier(.4,0,.2,1)}
.side-pin:hover{background:var(--panel2);color:var(--txt)}
.side-pin .ic{width:18px;text-align:center;flex:0 0 auto}
.navsec{padding:14px 20px 5px;font-size:10px;letter-spacing:1.5px;text-transform:uppercase;color:var(--muted);opacity:.6;font-weight:700}
.navgrp+.navgrp{margin-top:2px;border-top:1px solid var(--line)}
.navparent{justify-content:space-between}
.caret{font-size:10px;transition:transform .2s;margin-left:auto}
.navgroup.open .caret{transform:rotate(180deg)}
.submenu{display:none;flex-direction:column}
.navgroup.open .submenu{display:flex}
.submenu a{padding-left:46px;font-size:13px}
/* .side-ver se retiró de la barra: su contenido vive ahora en el icono
   ⓘ de arriba. La regla queda por si alguna vista antigua lo emite. */
.side-ver{margin-top:auto;padding:12px 20px 4px;font-size:9.5px;line-height:1.5;color:var(--muted);opacity:.5;letter-spacing:.2px}
.side-ver b{color:var(--muted);font-weight:700}

/* ---- Icono de información, junto a la campana ----
   Mismo tamaño y forma que la campana: son dos controles hermanos de la
   barra superior y deben leerse como tales. */
/* ============================================================
   ZONA · BARRA SUPERIOR
   12 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
.infobtn{position:relative;display:flex;align-items:center;justify-content:center;
  width:38px;height:38px;background:var(--panel2);border:1px solid var(--line);
  border-radius:50%;cursor:pointer;user-select:none;font-size:18px;line-height:1;color:var(--muted)}
.infobtn:hover{border-color:var(--accent);color:var(--accent)}
.infomenu{display:none;position:absolute;right:0;top:120%;width:290px;max-width:86vw;
  background:var(--panel);border:1px solid var(--line);border-radius:12px;z-index:70;
  box-shadow:0 12px 30px rgba(0,0,0,.35);overflow:hidden;cursor:default}
.infomenu.open{display:block}
.info-head{padding:12px 14px;border-bottom:1px solid var(--line)}
.info-head b{display:block;font-size:14px;color:var(--txt)}
.info-head span{font-size:11.5px;color:var(--accent)}
.info-body{padding:8px 14px}
.info-fila{display:flex;justify-content:space-between;gap:12px;padding:5px 0;font-size:11.5px;color:var(--muted)}
.info-fila b{color:var(--txt);font-weight:600;text-align:right;overflow-wrap:anywhere}
.info-pie{padding:10px 14px;border-top:1px solid var(--line);background:var(--panel2);
  font-size:10px;line-height:1.5;color:var(--muted);text-align:center}
/* En pantalla angosta se ancla a la pantalla, igual que las
   notificaciones: colgado del icono se salía por la izquierda. */
.infomenu.fijo{position:fixed;left:8px;right:8px;width:auto;max-width:none;
  max-height:calc(100dvh - 96px);overflow-y:auto;-webkit-overflow-scrolling:touch}

/* ============================================================
   LA LUPA · BUSCAR EN EL CRM                  [08/09/2026]

   Va aquí, pegada a .infobtn, porque es su vecina en la barra y
   comparte con ella medidas y forma: el mismo círculo de 38 px,
   el mismo panel colgado a la derecha. Si mañana se cambia el
   aspecto de los botones de la barra, están juntos.

   EL BUSCADOR LLEVA SU FONDO Y SU LETRA ESCRITOS
     Un <input type="search"> sin color propio lo pinta el sistema
     operativo: fondo blanco y letra negra. En tema oscuro eso es
     una caja blanca en mitad del panel. Es el fallo (a) de la
     regla de color de la casa —el respaldo claro que solo se
     probó en tema claro— y aquí se evita de entrada.
   ============================================================ */
.lupabtn{position:relative;display:flex;align-items:center;justify-content:center;
  width:38px;height:38px;background:var(--panel2);border:1px solid var(--line);
  border-radius:50%;cursor:pointer;user-select:none;font-size:16px;line-height:1;color:var(--muted)}
.lupabtn:hover{border-color:var(--accent);color:var(--accent)}
.lupamenu{display:none;position:absolute;right:0;top:120%;width:380px;max-width:88vw;
  background:var(--panel);border:1px solid var(--line);border-radius:12px;z-index:70;
  box-shadow:0 12px 30px rgba(0,0,0,.35);overflow:hidden;cursor:default}
.lupamenu.open{display:block}
.lupa-head{padding:10px 12px;border-bottom:1px solid var(--line);background:var(--panel2)}
.lupa-head input{width:100%;box-sizing:border-box;padding:9px 11px;font-size:13px;
  background:var(--panel);color:var(--txt);border:1px solid var(--line);border-radius:8px;
  outline:none;font-family:inherit}
.lupa-head input:focus{border-color:var(--accent)}
.lupa-head input::placeholder{color:var(--muted)}
.lupa-list{max-height:min(56vh,420px);overflow-y:auto;-webkit-overflow-scrolling:touch}
.lupa-vacio{padding:18px 14px;font-size:12px;color:var(--muted);line-height:1.6;text-align:center}
.lupa-vacio b{color:var(--txt);font-weight:600}
.lupa-item{padding:9px 13px;border-bottom:1px solid var(--line);cursor:pointer}
.lupa-item:last-child{border-bottom:0}
.lupa-item:hover,.lupa-item:focus{background:var(--panel2);outline:none}
.lupa-item[data-ir]:hover .li-cab b{color:var(--accent)}
.li-cab{display:flex;justify-content:space-between;align-items:baseline;gap:10px}
.li-cab b{font-size:12.5px;color:var(--txt);font-weight:600}
.li-tipo{font-size:9.5px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);
  white-space:nowrap;flex:0 0 auto}
.li-txt{font-size:11.5px;color:var(--muted);line-height:1.5;margin-top:3px}
.li-cdo{font-size:11px;color:var(--accent);line-height:1.5;margin-top:3px}
.lupa-mas{padding:8px 13px;font-size:11px;color:var(--muted);text-align:center;
  border-top:1px solid var(--line)}
.lupa-pie{padding:9px 13px;border-top:1px solid var(--line);background:var(--panel2);
  font-size:10px;line-height:1.5;color:var(--muted);text-align:center}
/* En pantalla angosta se ancla a la pantalla, igual que el menú de
   información y el de notificaciones: colgado del icono se salía. */
.lupamenu.fijo{position:fixed;left:8px;right:8px;width:auto;max-width:none;
  max-height:calc(100dvh - 96px);overflow-y:auto;-webkit-overflow-scrolling:touch}

/* ============================================================
   AVISO DE SESIÓN CERRADA                   [08/09/2026]

   Tapa la pantalla entera y no se puede apartar. No es un aviso
   que se pueda posponer: detrás no hay nada con lo que seguir
   trabajando, solo la última foto de una sesión que ya no vale.

   El rojo va escrito, no sale de una variable del tema. Es una
   alarma, y tiene que verse igual de fuerte en claro y en oscuro
   aunque mañana se cambie la paleta.
   ============================================================ */
#sesion-caida{position:fixed;inset:0;z-index:9998;display:flex;
  align-items:center;justify-content:center;padding:20px;
  background:rgba(0,0,0,.62)}
#sesion-caida .sc-caja{width:100%;max-width:420px;background:var(--panel);
  border:1px solid var(--line);border-top:4px solid #b91c1c;border-radius:12px;
  padding:20px 22px;box-shadow:0 20px 60px rgba(0,0,0,.5)}
#sesion-caida b#sc-tit{display:block;font-size:16px;color:var(--txt);margin-bottom:9px}
#sesion-caida p{margin:0 0 10px;font-size:13px;color:var(--muted);line-height:1.6}
#sesion-caida .sc-ojo{color:var(--txt)}
#sesion-caida .sc-ojo b{color:#b91c1c}
#sesion-caida .btn{margin-top:6px;width:100%}
@media print{ #sesion-caida{display:none} }

/* ============================================================
   EL ASISTENTE DE ACTIVIDADES               [08/09/2026]

   Una pregunta a la vez, centrada y sin nada alrededor. La caja
   es estrecha a propósito: cuando solo hay un campo, un cuadro
   ancho hace que parezca que falta algo por rellenar.

   Los colores salen del tema, como todo lo demás, para que
   funcione igual en claro y en oscuro.
   ============================================================ */
.crono-asis{display:none;position:fixed;inset:0;z-index:220;
  background:rgba(0,0,0,.45);align-items:center;justify-content:center;padding:18px}
.crono-asis.open{display:flex}
.crono-asis .ca-caja{width:100%;max-width:520px;background:var(--panel);
  border:1px solid var(--line);border-radius:14px;overflow:hidden;
  box-shadow:0 18px 50px rgba(0,0,0,.4)}
.crono-asis .ca-cab{display:flex;align-items:center;gap:10px;padding:13px 16px;
  border-bottom:1px solid var(--line);background:var(--panel2)}
.crono-asis .ca-cab b{font-size:15px;color:var(--txt);flex:1 1 auto}
.crono-asis .ca-paso{font-size:10.5px;text-transform:uppercase;letter-spacing:.6px;
  color:var(--muted);white-space:nowrap;flex:0 0 auto}
.crono-asis .ca-x{background:none;border:0;color:var(--muted);font-size:15px;
  cursor:pointer;line-height:1;padding:4px 6px;border-radius:6px}
.crono-asis .ca-x:hover{color:var(--txt);background:var(--fx-hover)}
.crono-asis .ca-cuerpo{padding:18px 16px;min-height:118px}
.crono-asis .ca-campo{display:block;font-size:12px;color:var(--muted);margin-bottom:4px}
.crono-asis .ca-campo input,.crono-asis .ca-sel{width:100%;box-sizing:border-box;
  margin-top:5px;padding:10px 11px;font-size:14px;font-family:inherit;
  background:var(--panel2);color:var(--txt);border:1px solid var(--line);border-radius:8px}
.crono-asis .ca-campo input:focus,.crono-asis .ca-sel:focus{outline:none;border-color:var(--accent)}
.crono-asis .ca-corto{max-width:180px}
.crono-asis .ca-fechas{display:grid;grid-template-columns:1fr .7fr 1fr;gap:10px}
.crono-asis .ca-nota{margin:11px 0 0;font-size:11.5px;color:var(--muted);line-height:1.55}
.crono-asis .ca-nota b{color:var(--txt)}
.crono-asis .ca-solo{margin-top:0}
.crono-asis .ca-ops{display:flex;flex-direction:column;gap:8px}
.crono-asis .ca-op{display:flex;gap:10px;align-items:flex-start;padding:10px 12px;
  border:1px solid var(--line);border-radius:9px;cursor:pointer}
.crono-asis .ca-op:hover{border-color:var(--accent);background:var(--fx-hover)}
.crono-asis .ca-op input{margin-top:3px;flex:0 0 auto}
.crono-asis .ca-op b{display:block;font-size:13px;color:var(--txt);font-weight:600}
.crono-asis .ca-op small{display:block;font-size:11.5px;color:var(--muted);margin-top:2px}
.crono-asis .ca-sel{margin-top:9px}
.crono-asis .ca-sel:disabled{opacity:.45}
/* El aviso de lo que falta: rojo del tema, no a fuego. */
.crono-asis .ca-mal{margin-top:11px;padding:8px 11px;border-radius:8px;font-size:12.5px;
  background:var(--panel2);border:1px solid var(--mal,#b91c1c);color:var(--mal,#b91c1c)}
/* El resumen del cálculo del proyecto, copiado del formulario para que
   se vea la cuenta mientras se escribe el valor. [08/09/2026] */
.crono-asis .ca-calc{margin-top:11px}
.crono-asis .ca-calc:empty{display:none}
/* Los bloques de impuestos y estampillas se prestan del formulario:
   caben más anchos que un campo suelto y pueden crecer. */
.crono-asis #ca-cargos{max-height:min(46vh,340px);overflow-y:auto;
  -webkit-overflow-scrolling:touch}
.crono-asis .ca-ok{font-size:14px;color:var(--txt);line-height:1.6}
.crono-asis .ca-ok b{color:var(--accent)}
.crono-asis .ca-pie{display:flex;align-items:center;gap:8px;padding:12px 16px;
  border-top:1px solid var(--line);background:var(--panel2);flex-wrap:wrap}
.crono-asis .ca-sep{flex:1 1 auto}
/* El cuerpo se desplaza. Lo pide el paso de las autorizaciones de la
   solicitud de ingreso: el texto de la naturaleza de la cuenta son doce
   renglones y sin esto la ventana crecía hasta salirse de la pantalla,
   dejando los botones abajo, fuera de alcance. Es el mismo tropiezo que
   ya tuvo el formulario de registro en el teléfono. [08/09/2026] */
.crono-asis .ca-cuerpo{max-height:min(62vh,520px);overflow-y:auto;
  -webkit-overflow-scrolling:touch}
@media (max-width:520px){
  .crono-asis .ca-fechas{grid-template-columns:1fr}
  .crono-asis .ca-pie{flex-direction:column-reverse;align-items:stretch}
  .crono-asis .ca-pie .btn{width:100%}
}

/* ===================================================================
   EL ASISTENTE, VESTIDO DE PANTALLA DE INGRESO      [08/09/2026]

   POR QUÉ HACE FALTA UNA PIEL APARTE
     Este asistente —el de la solicitud de ingreso— es el único de los
     tres que NO sale dentro del CRM: sale sobre la pantalla de entrada.
     Y esa pantalla es, a propósito, una hoja clara sobre fondo oscuro
     que no sigue el tema, igual que el formulario de siempre. Un
     asistente oscuro encima de ella se vería como una ventana de otro
     programa.

     Hay además una razón práctica: presta los tres recuadros de foto
     del formulario, que traen sus colores claros escritos a fuego
     (.reg-slot). Sobre un panel oscuro quedaban tres cajas blancas
     flotando.

   REGLA DE LA CASA QUE SE CUMPLE AQUÍ
     Cada regla con fondo claro declara TAMBIÉN su color de texto. Sin
     eso, un <button> o un <input> toma el color del navegador, que en
     un sistema forzado a oscuro es claro: texto claro sobre blanco. Es
     lo que vigila _herramientas/auditar_tema.py, y ya pasó de verdad.

   POR ENCIMA DE LA PANTALLA DE INGRESO
     #login-overlay va en z-index 200 y .crono-asis en 220, así que ya
     quedaría encima. Se sube a 10001 —uno más que .reg-overlay— para
     que también quede por delante del formulario completo cuando este
     se abre desde «Prefiero el formulario completo» y se vuelve atrás.
   =================================================================== */
.crono-asis.ca-claro{z-index:10001;background:rgba(10,13,16,.72)}
.crono-asis.ca-claro .ca-caja{background:#fff;color:#14181C;border:1px solid #e6ebf1;
  box-shadow:0 30px 80px rgba(0,0,0,.5);
  font:14px/1.5 -apple-system,Segoe UI,system-ui,sans-serif}
.crono-asis.ca-claro .ca-cab{background:#fff;color:#14181C;border-bottom:1px solid #e6ebf1}
.crono-asis.ca-claro .ca-cab b{color:#14181C}
.crono-asis.ca-claro .ca-paso{background:#f0f3f7;color:#5c6b7a}
.crono-asis.ca-claro .ca-x{background:transparent;color:#98A2AB}
.crono-asis.ca-claro .ca-x:hover{background:#f0f3f7;color:#14181C}
.crono-asis.ca-claro .ca-cuerpo{background:#fff;color:#14181C}
.crono-asis.ca-claro .ca-campo{color:#5c6b7a}
.crono-asis.ca-claro .ca-campo small{color:#98A2AB;font-weight:400}
.crono-asis.ca-claro .ca-campo input,
.crono-asis.ca-claro .ca-sel{background:#f6f8fa;color:#14181C;border:1px solid #d7dee7}
.crono-asis.ca-claro .ca-campo input:focus,
.crono-asis.ca-claro .ca-sel:focus{background:#fff;color:#14181C;border-color:#B8860B}
.crono-asis.ca-claro .ca-nota{color:#5c6b7a}
.crono-asis.ca-claro .ca-nota b{color:#14181C}
.crono-asis.ca-claro .ca-ok{color:#14181C}
.crono-asis.ca-claro .ca-ok b{color:#8a6414}
.crono-asis.ca-claro .ca-op{background:#f6f8fa;color:#14181C;border:1px solid #d7dee7}
.crono-asis.ca-claro .ca-op:hover{background:#fdf7ea;color:#14181C;border-color:#B8860B}
.crono-asis.ca-claro .ca-op b{color:#14181C}
.crono-asis.ca-claro .ca-op small{color:#5c6b7a}
.crono-asis.ca-claro .ca-mal{background:#fdecec;color:#8c2f2f;border:1px solid #f3c9c9}
.crono-asis.ca-claro .ca-pie{background:#f6f8fa;color:#14181C;border-top:1px solid #e6ebf1}
/* El botón de contorno usa --line y --muted, que en el tema claro son
   grises muy suaves: sobre esta hoja blanca desaparecía. */
.crono-asis.ca-claro .ca-pie .btn.ghost{background:#fff;color:#5c6b7a;border:1px solid #d7dee7}
.crono-asis.ca-claro .ca-pie .btn.ghost:hover{background:#f0f3f7;color:#14181C;border-color:#98A2AB}
/* Los recuadros de foto prestados: sitio propio y con desplazamiento,
   que en un teléfono en horizontal tres recuadros no caben. */
.crono-asis #ca-regfotos{margin-top:12px}
.crono-asis #ca-regfotos .reg-fotos{margin-top:0;border-top:0;padding-top:0}

/* ============================================================
   LA BANDA DEL MODO DEMOSTRACIÓN            [08/09/2026]

   Tiene que MOLESTAR. Este modo enseña cifras falsas con cara de
   verdaderas, así que el peligro no es que se note demasiado: es
   que pase desapercibido y alguien decida algo de plata mirándolas.

   Por eso va arriba de todo, a lo ancho, sin botón de cerrar, y el
   cuerpo se baja para que nada la tape.

   EL ROJO VA ESCRITO AQUÍ Y NO SALE DE UNA VARIABLE DEL TEMA
     Es deliberado, y es la única excepción a la regla de la casa.
     Esto no es un color de la interfaz, es una alarma: tiene que
     verse igual de fuerte en claro y en oscuro, y no debe cambiar
     si mañana se cambia la paleta.

   No se imprime: en papel no hay forma de equivocarse, porque las
   capturas se toman a sabiendas.
   ============================================================ */
#demo-banda{position:fixed;top:0;left:0;right:0;z-index:9999;
  background:#b91c1c;color:#fff;text-align:center;
  padding:7px 14px;font-size:12.5px;line-height:1.4;
  letter-spacing:.3px;box-shadow:0 2px 10px rgba(0,0,0,.35)}
#demo-banda b{letter-spacing:1px}
#demo-banda span{opacity:.85}
body.demo-on{padding-top:34px}
@media print{ #demo-banda{display:none} body.demo-on{padding-top:0} }

/* ============================================================
   ZONA · BARRA LATERAL Y MENU
   6 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
.userbox{margin-top:0;padding:10px 20px 12px;border-top:1px solid var(--line);font-size:12px;color:var(--muted)}
.userbox b{color:var(--txt)}
.nav::-webkit-scrollbar{width:8px}
.nav::-webkit-scrollbar-thumb{background:var(--line);border-radius:8px}
.nav::-webkit-scrollbar-thumb:hover{background:#475569}
.nav::-webkit-scrollbar-track{background:transparent}
*::-webkit-scrollbar{width:10px;height:10px}
*::-webkit-scrollbar-thumb{background:var(--line);border-radius:8px}
*::-webkit-scrollbar-thumb:hover{background:#475569}
*::-webkit-scrollbar-track{background:transparent}
html{scrollbar-width:thin;scrollbar-color:#334155 transparent}
/* ---- Identidad y salida, uno debajo del otro ----
   Estaban en la misma fila. Con la barra recogida no caben los dos en
   60 px: el botón se salía y aparecía cortado contra el borde. Y aun
   con la barra abierta, apretaba el nombre contra el borde derecho.
   En columna cada cosa tiene su renglón y funciona igual de bien con
   la barra ancha que angosta. */
/* ============================================================
   ZONA · BARRA LATERAL Y MENU
   8 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
.ubox{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.ubox-tx{min-width:0;flex:1;overflow:hidden}
.ubox-tx b{display:block;white-space:normal;overflow-wrap:anywhere;line-height:1.2;font-size:11px}
/* ---- Salida rápida, debajo de la foto ----
   flex-basis 100% la empuja siempre a su propio renglón.
   Discreta mientras no se necesita; se tiñe de rojo al apuntarla o al
   recibir el foco, para que se note que es una acción de salida. */
.side-salir{display:inline-flex;align-items:center;justify-content:center;gap:6px;
  flex:0 0 100%;margin-top:9px;
  background:var(--panel2);border:1px solid var(--line);color:var(--muted);
  border-radius:9px;padding:7px 10px;min-height:36px;font-size:11.5px;font-weight:600;
  font-family:inherit;cursor:pointer;transition:color .15s,border-color .15s,background .15s}
.side-salir span[aria-hidden]{font-size:14px;line-height:1}
.side-salir:hover,.side-salir:focus-visible{color:var(--bad);border-color:var(--bad);background:var(--panel)}
.side-salir:focus-visible{outline:2px solid #ef4444;outline-offset:2px}
@media(max-width:820px){
  /* En el cajón del teléfono hay ancho de sobra: el botón se ve completo */
  .side-salir{padding:8px 12px;min-height:40px;font-size:12px}
}
.userchip{position:relative;display:flex;align-items:center;gap:8px;background:var(--panel2);border:1px solid var(--line);padding:5px 10px 5px 6px;border-radius:22px;cursor:pointer;user-select:none}
.userchip:hover{border-color:var(--accent)}
.uc-avatar{width:28px;height:28px;border-radius:50%;background:var(--accent2);color:#fff;font-weight:700;font-size:12px;display:flex;align-items:center;justify-content:center;flex:0 0 auto}
.ubox .uc-avatar{width:34px;height:34px;font-size:13px}
/* ============================================================
   ZONA · BARRA SUPERIOR
   6 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
.uc-name{font-size:13px;color:var(--txt);max-width:170px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.usermenu{display:none;position:absolute;right:0;top:112%;background:var(--panel);border:1px solid var(--line);border-radius:10px;min-width:190px;padding:6px;z-index:60;box-shadow:0 8px 24px rgba(0,0,0,.35)}
.usermenu.open{display:block}
.usermenu a{display:block;padding:9px 12px;border-radius:7px;color:var(--txt);font-size:13px;cursor:pointer;text-decoration:none}
.usermenu a:hover{background:var(--panel2);color:var(--accent)}
/* Punto de color del tipo, para leer la opción de un vistazo */
.usermenu a i.pt-aus{display:inline-block;width:8px;height:8px;border-radius:50%;background:#dc2626;vertical-align:middle;margin-right:4px}
/* ------------------------------------------------------------
   PERMISOS · LA AYUDA AL DEJAR EL CURSOR            [05/09/2026]

   Va pegada al <body> y colocada por JavaScript, no dentro de la
   tabla: la ventana de permisos tiene su propio desplazamiento y una
   caja dentro se cortaría en el borde.

   z-index alto porque flota sobre una ventana modal, que ya está por
   encima de todo lo demás.
   ------------------------------------------------------------ */
.perm-ayuda{position:fixed;z-index:300;background:var(--panel);
  border:1px solid var(--line);border-radius:9px;padding:11px 13px;
  box-shadow:0 10px 30px rgba(0,0,0,.35);pointer-events:none;
  animation:permAyudaEntra .12s ease-out}
@keyframes permAyudaEntra{from{opacity:0;transform:translateY(3px)}to{opacity:1;transform:none}}
.perm-ayuda .pa-tit{font-weight:600;color:var(--txt);font-size:13px;margin-bottom:4px}
.perm-ayuda .pa-txt{font-size:12.5px;color:var(--muted);line-height:1.5}
.perm-ayuda .pa-txt code{font-size:11.5px}
.perm-ayuda .pa-dep{margin-top:7px;padding-top:7px;border-top:1px solid var(--line);
  font-size:12px;color:var(--warn)}
.perm-ayuda .pa-dep b{color:var(--warn)}
/* Las celdas con ayuda avisan de que hay algo que mirar, sin ruido:
   solo cambia el cursor. */
td[data-mod]{cursor:help}
@media (prefers-reduced-motion: reduce){ .perm-ayuda{animation:none} }

/* ------------------------------------------------------------
   SUGERENCIAS · RECUENTO POR ESTADO                 [05/09/2026]

   Cuatro o cinco cifras pequeñas encima de la lista, para saber de un
   vistazo cuántas quedan por mirar sin contarlas a mano. Solo lo ve
   quien administra.

   Las nuevas se destacan con el color de acento: son las únicas que
   piden una acción. Las demás informan.
   ------------------------------------------------------------ */
.sug-resumen{display:flex;gap:7px;flex-wrap:wrap;margin-top:9px}
.sug-chip{font-size:11.5px;padding:3px 9px;border-radius:99px;
  background:var(--panel2);color:var(--muted);border:1px solid var(--line)}
.sug-chip.nueva{background:color-mix(in srgb,var(--accent) 14%,var(--panel2));
  color:var(--accent);border-color:var(--accent);font-weight:600}

/* ------------------------------------------------------------
   PERMISOS · MÓDULOS QUE DEPENDEN DE OTRO           [05/09/2026]

   Debajo del nombre del módulo, en pequeño. En gris cuando solo
   informa; en rojo cuando el permiso está concedido SIN su padre y por
   tanto no hace nada.

   El rojo sale de --bad y el gris de --muted: las dos existen en los
   dos temas. Un color fijo se habría perdido en uno de ellos.
   ------------------------------------------------------------ */
.perm-dep{font-size:11.5px;color:var(--muted);margin-top:2px;line-height:1.4;max-width:38ch}
.perm-dep.mal{color:var(--bad)}
.perm-dep b{color:inherit;font-weight:600}

/* ------------------------------------------------------------
   CRONOGRAMA · DESDE · DÍAS · HASTA                 [05/09/2026]

   El renglón de debajo dice en palabras lo que quedó («10 de sep →
   14 de sep · 5 días»), para no tener que restar dos fechas de
   cabeza. Va en tono apagado porque es una confirmación, no una
   instrucción: se lee de reojo.

   Los colores salen de --muted y --bad, que existen en los DOS temas.
   Un gris fijo se habría perdido sobre el panel oscuro.
   ------------------------------------------------------------ */
.crono-dias-pie{font-size:12.5px;color:var(--muted);margin:-4px 0 2px;min-height:16px}
.crono-dias-pie.mal{color:var(--bad);font-weight:600}
/* La casilla de días es corta a propósito: caben cuatro cifras y se
   lee de un vistazo junto a las fechas. Se quitan las flechitas del
   navegador, que en un campo de tres dígitos estorban más que ayudan. */
#crono-dias{text-align:center}
#crono-dias::-webkit-outer-spin-button,
#crono-dias::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
#crono-dias{-moz-appearance:textfield}

/* ------------------------------------------------------------
   CRONOGRAMA · CÓMO SE ENCADENA                     [05/09/2026]

   Dos opciones, cada una con su explicación debajo en letra pequeña.
   Se ven las dos a la vez -no en un desplegable- porque es una
   decisión que se toma una sola vez por actividad y conviene leerla
   entera antes de elegir.
   ------------------------------------------------------------ */
.crono-dep-modo{display:flex;flex-direction:column;gap:8px;margin:12px 0 4px}
.crono-dep-radio{display:flex;gap:9px;align-items:flex-start;cursor:pointer;
  border:1px solid var(--line);border-radius:8px;padding:9px 11px;
  background:var(--panel2);transition:border-color .15s}
.crono-dep-radio:hover{border-color:var(--accent)}
.crono-dep-radio input{margin-top:2px;flex:0 0 auto}
.crono-dep-radio b{font-weight:600;color:var(--txt);font-size:13.5px}
.crono-dep-radio small{color:var(--muted);font-size:12px;line-height:1.45}
/* La elegida se distingue sin depender solo del punto del radio, que
   en pantallas pequeñas cuesta ver. */
.crono-dep-radio:has(input:checked){border-color:var(--accent);
  background:color-mix(in srgb,var(--accent) 8%,var(--panel2))}

/* ------------------------------------------------------------
   LA OPCIÓN QUE ECHA A TODO EL MUNDO                [05/09/2026]

   «Cerrar sesión en todos los dispositivos» va en el mismo menú que
   «Editar perfil», pero no es de la misma familia: deja fuera del CRM
   a la empresa entera durante el minuto que tarda cada quien en volver
   a entrar. Se separa con una línea y se pinta en rojo para que nadie
   la pulse creyendo que es la salida normal, que está justo encima.

   El rojo sale de --bad, que está definida en los DOS temas
   (oscuro #f87171, claro #dc2626). Un rojo fijo se habría visto
   apagado sobre el panel oscuro. Ver la regla 3 de la casa.
   ------------------------------------------------------------ */
.usermenu a.um-peligro{border-top:1px solid var(--line);margin-top:5px;padding-top:11px;color:var(--bad)}
.usermenu a.um-peligro:hover{background:var(--panel2);color:var(--bad)}
/* .usermenu a lleva display:block, que le gana al display:none que el
   navegador da por el atributo hidden. Sin esta línea la opción se vería
   SIEMPRE, también a quien no es administrador. Va con [hidden] —más
   peso que la regla de arriba— en vez de !important. */
.usermenu a[hidden]{display:none}
#login-overlay{position:fixed;inset:0;background:linear-gradient(135deg,#0b0e12 0%,#14181C 55%,#0d1013 100%);z-index:200;display:flex;align-items:center;justify-content:center;--txt:#e2e8f0;--muted:#94a3b8;--line:#334155;--bad:#ef4444}
#login-overlay::before{content:"";position:absolute;inset:0;background:radial-gradient(circle at 82% 20%,var(--acento-suave,rgba(184,134,11,.18)),transparent 45%);pointer-events:none}
#login-overlay.hidden{display:none}
html[data-sesion="1"] #login-overlay{display:none}
/* ============================================================
   ZONA · PANTALLA DE INGRESO
   17 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
.login-card{position:relative;display:flex;background:#0f141a;border:1px solid rgba(255,255,255,.08);border-radius:20px;width:900px;max-width:95vw;min-height:540px;overflow:hidden;box-shadow:0 40px 100px rgba(0,0,0,.65)}
.login-left{flex:1 1 46%;background:#fff;padding:46px 44px;display:flex;flex-direction:column;justify-content:center}
/* ===================================================================
   LA PANTALLA DE ENTRADA                          [06/09/2026]

   Se retiraron el logo del panel claro y el renglón «Bienvenido a
   CALEP S.A.S»: había dos logos en la misma pantalla y dos saludos
   diciendo lo mismo. Las dos reglas se dejan escritas —sin uso— para
   que quien lea el CSS no crea que se perdieron; el marcado ya no las
   invoca.
   =================================================================== */
.login-logo{display:none}
.login-welcome-sub{display:none}
/* «Iniciar sesión» pasa a ser el título de verdad de la pantalla: es lo
   único que se hace aquí y ahora se lee primero. */
.login-title{margin:6px 0 26px;font-size:34px;font-weight:800;color:#14181C;
  letter-spacing:-.4px;line-height:1.1}
.login-l{display:block;font-size:11px;color:#6A737C;text-transform:uppercase;letter-spacing:.5px;margin-bottom:15px}
.login-l input{display:block;width:100%;margin-top:7px;background:#F2F4F6;border:1px solid #D7DEE7;color:#14181C;padding:12px;border-radius:10px;font-size:14px;transition:border-color .15s}
.login-l input:focus{outline:none;border-color:var(--accent,#B8860B);box-shadow:0 0 0 3px var(--acento-suave,rgba(184,134,11,.18))}
.login-err{color:#dc2626;font-size:12px;min-height:16px;margin-bottom:6px}
.login-btn{width:100%;margin-top:4px;background:linear-gradient(90deg,var(--accent2,#B8860B),var(--accent,#E8C86A));color:#14181C;border:none;padding:14px;border-radius:10px;font-size:14px;font-weight:800;letter-spacing:2px;cursor:pointer;transition:filter .15s}
.login-btn:hover{filter:brightness(1.07)}
.login-hint{color:#98A2AB;font-size:11px;text-align:center;margin-top:18px;letter-spacing:.5px}
.login-passwrap{position:relative;display:block}
.login-passwrap input{margin-top:7px;padding-right:44px}
.login-eye{position:absolute;right:8px;top:calc(50% + 4px);transform:translateY(-50%);background:none;border:none;color:#6A737C;cursor:pointer;font-size:17px;line-height:1;padding:4px}
.login-eye:hover{color:var(--accent,#B8860B)}
.login-check{display:flex;align-items:center;gap:8px;color:#6A737C;font-size:12px;margin:-4px 0 16px;text-transform:none;letter-spacing:0}
.login-check input{width:auto;margin:0}
.login-left a{color:var(--accent,#B8860B);font-weight:600}
.login-right{flex:1 1 54%;position:relative;overflow:hidden;background:radial-gradient(130% 120% at 78% 18%,#1b222b 0%,#12171C 55%,#0b0e12 100%);display:flex;align-items:center;justify-content:center}
.login-cordillera{position:absolute;left:0;right:0;bottom:0;width:100%;height:60%;opacity:.30}
/* Se sube el bloque entero: antes quedaba centrado y el logo caía
   demasiado abajo, pegado al «Bienvenido». [06/09/2026] */
.login-right-inner{position:relative;z-index:2;text-align:center;padding:24px;
  transform:translateY(-6%)}
/* El logo del panel oscuro sube y crece: es la marca de la casa y este
   es el único sitio de la pantalla donde tiene espacio para lucirse.
   [06/09/2026] */
.login-right-logo{width:196px;display:block;margin:0 auto 26px}
.login-welcome{font-size:46px;font-weight:800;color:#fff;letter-spacing:1px;line-height:1}
.login-welcome::after{content:"";display:block;width:64px;height:3px;background:linear-gradient(90deg,var(--accent2,#B8860B),var(--accent,#E8C86A));margin:16px auto 0;border-radius:2px}
.login-welcome-txt{color:#9aa4ae;font-size:13px;letter-spacing:1px;margin-top:16px}
/* En pantalla grande NO se ve: el logo grande del panel oscuro ya está
   ahí, y dos logos en la misma pantalla fue justo el problema que se
   quitó el 06/09. Solo aparece cuando el otro desaparece. */
.login-left-logo{display:none}
@media(max-width:820px){
  .login-card{flex-direction:column;width:430px;min-height:0}
  .login-right{display:none}
  .login-left{flex:1 1 auto;padding:34px 26px;position:relative}
  /* Arriba a la derecha, fuera del recorrido de lectura: identifica la
     pantalla sin competir con «Iniciar sesión», que es lo que hay que
     leer primero. Sin margen inferior propio para no empujar el título. */
  /* SE INVIERTE, Y NO ES UN CAPRICHO: assets/logo.png es la versión
     BLANCA —está hecha para el panel oscuro y para la barra lateral—.
     Medido: brillo medio 255 sobre sus 38.862 píxeles opacos, o sea
     blanco puro. Puesta tal cual sobre este panel blanco no se ve
     nada: el elemento está, ocupa su sitio y es invisible.

     Es el mismo invert(1) que ya usa «[data-theme=light] .brand-logo»
     unas líneas más arriba, por exactamente la misma razón.

     Se cayó en el error al añadirlo: el comentario del HTML llegó a
     decir que este era «el logo negro». No lo es. */
  .login-left-logo{display:block;position:absolute;top:16px;right:18px;
    width:76px;height:auto;opacity:.9;pointer-events:none;background:#12171C;border-radius:8px;padding:5px;box-sizing:border-box}
}
/* Teléfono estrecho: el logo se achica para no meterse con el título. */
@media(max-width:430px){
  .login-left-logo{width:60px;top:12px;right:12px}
}
/* Pantalla baja —el móvil en horizontal—: la tarjeta es corta y el logo
   estorbaría más de lo que identifica. */
@media(max-height:460px){
  .login-left-logo{display:none}
}
/* Ticker de divisas (dólar / euro) */
/* ============================================================
   ZONA · CINTA DE INDICADORES
   11 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
.ticker{overflow:hidden;white-space:nowrap;width:100%;transform:translateZ(0)}
/* width:max-content es obligatorio. Con inline-flex el ancho de la cinta
   quedaba sin resolver y Safari del iPhone y del iPad calculaba el -50%
   del recorrido contra cero: la animación corría, pero no desplazaba
   nada, así que la barra se veía completamente quieta. */
/* Los 70 s son el RESPALDO, para un navegador tan antiguo que no
   soporte la animación por código. Aquí no se puede medir el ancho de
   la cinta, así que el tiempo va fijo y se calculó para las cinco
   piezas de hoy. Lo normal es que mande la de JavaScript, que sí mide
   y mantiene la velocidad constante sin importar cuántas piezas haya
   —ver FX_VELOCIDAD en el bloque de código—. */
.ticker-track{display:flex;width:max-content;gap:48px;align-items:center;padding-left:48px;
  animation:tickermove 70s linear infinite;
  transform:translateZ(0);backface-visibility:hidden}
/* La pausa al pasar el cursor solo tiene sentido con un mouse de verdad.
   En pantalla táctil el «hover» se queda pegado después de tocar, así que
   con un solo toque la barra se congelaba y no volvía a arrancar. */
@media(hover:hover) and (pointer:fine){
  .ticker-card:hover .ticker-track{animation-play-state:paused}
}
@keyframes tickermove{from{transform:translate3d(0,0,0)}to{transform:translate3d(-50%,0,0)}}
.fx-item{display:inline-flex;align-items:center;gap:12px}
.fx-flag{width:40px;height:40px;border-radius:50%;flex:0 0 auto;box-shadow:0 0 0 1px rgba(255,255,255,.2)}
.fx-lbl{font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:.6px}
.fx-val{font-size:22px;font-weight:800;display:flex;align-items:center;gap:8px}
/* .fx-sub ya no se pinta: el origen del dato pasó al title de la cifra.
   La regla se conserva por si alguna vista antigua todavía lo emite. */
.fx-sub{font-size:10px;color:var(--muted)}
/* Sin el renglón de abajo la cinta queda más baja: se centra la cifra
   con la bandera para que no flote descolgada. */
.fx-item{cursor:help}
.fx-arrow{font-size:15px;font-weight:800}
.fx-up{color:#22c55e}.fx-down{color:var(--bad)}.fx-flat{color:var(--muted)}
/* Dashboard · asignaciones por personal técnico */
/* ============================================================
   ZONA · PERSONAL TÉCNICO
   14 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
.esp-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
.esp-tile{display:flex;flex-direction:column;align-items:center;gap:6px;background:var(--panel2);border:1px solid var(--line);border-radius:14px;padding:16px 10px;cursor:pointer;text-align:center;transition:border-color .15s,transform .12s,background .15s,box-shadow .15s}
.esp-tile:hover{border-color:var(--accent);background:var(--panel);transform:translateY(-2px);box-shadow:0 8px 24px rgba(0,0,0,.35)}
.esp-tile-nm{font-size:14px;font-weight:700;color:var(--txt);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.esp-tile-esp{font-size:10px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.esp-tile-ct{font-size:11px;color:var(--muted);margin-top:2px;background:var(--panel);border:1px solid var(--line);border-radius:20px;padding:3px 11px}
.chip-off{opacity:.5}
@media(max-width:900px){.esp-grid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:560px){.esp-grid{grid-template-columns:1fr}}

/* ============================================================
   IDONEIDAD DEL PERSONAL TÉCNICO   [02/09/2026]
   Los dos grupos, las etiquetas de alturas y la alarma de
   parafiscales. Los colores salen de las variables del tema, así que
   funcionan igual en claro y en oscuro.
   ============================================================ */
.ido-grupo{margin:0 0 18px}
.ido-grupo-cab{display:flex;flex-direction:column;gap:2px;margin:0 0 10px;
  padding:9px 12px;border-radius:10px;background:var(--panel2);
  border:1px solid var(--line);border-left-width:4px}
.ido-ok .ido-grupo-cab{border-left-color:var(--ok,#22c55e)}
.ido-aviso .ido-grupo-cab{border-left-color:#f59e0b}
.ido-grupo-cab b{font-size:13px;color:var(--txt);font-weight:700}
.ido-grupo-cab b span{display:inline-block;margin-left:6px;padding:1px 8px;border-radius:20px;
  background:var(--panel);border:1px solid var(--line);font-size:11px;color:var(--muted)}
.ido-grupo-cab em{font-style:normal;font-size:11px;color:var(--muted);line-height:1.35}

/* La ficha de quien no está en condiciones: un borde, no un fondo. Un
   fondo de color en una rejilla de fichas se lee como «seleccionado». */
.chip-falta{border-color:#f59e0b!important;box-shadow:0 0 0 1px rgba(245,158,11,.25) inset}

.cbadge.bad{background:rgba(239,68,68,.14);color:var(--bad,#f87171);
  border:1px solid rgba(239,68,68,.45)}
.cbadge.alt-ok{background:rgba(34,197,94,.13);color:var(--ok,#22c55e);
  border:1px solid rgba(34,197,94,.40)}
.cbadge.alt-mal{background:rgba(245,158,11,.14);color:#d97706;
  border:1px solid rgba(245,158,11,.45)}
.cbadge.alt-no{background:var(--panel);color:var(--muted);border:1px solid var(--line)}
html[data-theme="dark"] .cbadge.alt-mal{color:#fbbf24}

/* ---- La alarma ----
   Roja y con el borde grueso a la izquierda: es la única cosa de esta
   pantalla que impide que alguien trabaje hoy. */
.ido-alarma{display:flex;align-items:flex-start;gap:12px;padding:13px 15px;
  border-radius:12px;background:rgba(239,68,68,.10);
  border:1px solid rgba(239,68,68,.45);border-left:5px solid var(--bad,#ef4444)}
.ido-alarma-ic{font-size:22px;line-height:1;flex:0 0 auto;color:var(--bad,#ef4444);
  animation:idopulso 1.6s ease-in-out infinite}
@keyframes idopulso{0%,100%{opacity:1}50%{opacity:.35}}
/* Quien tenga puesto «reducir movimiento» no debe recibir un parpadeo:
   para algunas personas es molesto y para otras, peligroso. El aviso
   se sigue viendo igual, quieto. */
@media(prefers-reduced-motion:reduce){ .ido-alarma-ic{animation:none} }
.ido-alarma-tx{flex:1 1 auto;min-width:0}
.ido-alarma-tx b{display:block;font-size:13.5px;color:var(--txt);margin-bottom:2px}
.ido-alarma-tx>span{display:block;font-size:11.5px;color:var(--muted);line-height:1.4}
.ido-alarma-lista{display:flex;flex-wrap:wrap;gap:6px;margin-top:9px}
.ido-alarma-lista button{background:var(--panel);border:1px solid rgba(239,68,68,.45);
  color:var(--txt);border-radius:8px;padding:4px 10px;font-size:11.5px;font-weight:600;
  font-family:inherit;cursor:pointer;text-align:left;transition:border-color .15s,background .15s}
.ido-alarma-lista button:hover{border-color:var(--bad,#ef4444);background:var(--panel2)}
.ido-alarma-lista button em{font-style:normal;font-weight:400;color:var(--muted);font-size:10.5px}
.ido-alarma-x{flex:0 0 auto;background:var(--bad,#ef4444);border:none;color:#fff;
  border-radius:9px;padding:7px 13px;font-size:12px;font-weight:700;font-family:inherit;
  cursor:pointer;white-space:nowrap}
.ido-alarma-x:hover{filter:brightness(1.08)}
@media(max-width:640px){
  .ido-alarma{flex-wrap:wrap}
  .ido-alarma-x{width:100%;margin-top:4px}
}
.esp-assign{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:10px}
.esp-assign-h{display:flex;align-items:center;gap:11px;width:100%;margin-bottom:9px;cursor:pointer;background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:9px 12px;text-align:left;transition:border-color .15s,background .15s,transform .12s}
.esp-assign-h:hover{border-color:var(--accent);background:var(--panel2);transform:translateY(-1px)}
.esp-assign-nm{display:flex;flex-direction:column;line-height:1.2;min-width:0}
.esp-assign-nm b{font-size:15px;color:var(--txt);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.esp-assign-esp{font-size:10px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.esp-assign-ct{margin-left:auto;flex:0 0 auto;font-size:12px;background:var(--accent2);color:#fff}
/* ============================================================
   ZONA · CALENDARIO Y AGENDA
   6 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
.ea-list{display:flex;flex-direction:column;gap:5px;max-height:180px;overflow-y:auto}
.ea-row{display:flex;align-items:center;gap:8px;font-size:11px;background:var(--panel);border-radius:6px;padding:5px 8px;border-left:3px solid var(--accent)}
.ea-date{color:var(--accent);font-weight:700;white-space:nowrap}
.ea-cli{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ea-empty{font-size:11px;color:var(--muted);padding:4px 2px}
.ea-row .bdel{flex:0 0 auto;padding:2px 6px!important;font-size:11px!important}
.pros-bars{display:flex;flex-direction:column;gap:8px;margin-top:10px}
/* Dinamismo del dashboard */
.live-pill{display:inline-flex;align-items:center;gap:7px}
.live-dot{display:inline-block;width:9px;height:9px;border-radius:50%;background:#22c55e;animation:livepulse 1.3s infinite}
@keyframes livepulse{0%{box-shadow:0 0 0 0 rgba(34,197,94,.55)}70%{box-shadow:0 0 0 7px rgba(34,197,94,0)}100%{box-shadow:0 0 0 0 rgba(34,197,94,0)}}
#v-dash .card>h3{position:relative;padding-bottom:9px}
#v-dash .card>h3::after{content:"";position:absolute;left:0;bottom:0;height:2px;width:100%;background:linear-gradient(90deg,transparent,var(--accent),transparent);background-size:200% 100%;animation:sweep 3.2s linear infinite;opacity:.55}
@keyframes sweep{from{background-position:200% 0}to{background-position:-200% 0}}
.svc-track{animation-duration:75s;gap:40px;padding-left:40px}
.svc-item{display:inline-flex;align-items:center;gap:8px;font-size:12px;color:var(--txt);white-space:nowrap}
.svc-dot{width:8px;height:8px;border-radius:50%;flex:0 0 auto}
#v-dash .card .pfill{transition:width .8s cubic-bezier(.22,1,.36,1)}
.main{flex:1;padding:26px 34px;max-width:none;min-width:0}
.topbar{display:flex;justify-content:space-between;align-items:center;margin-bottom:22px}
.topbar h2{font-size:22px}
/* ============================================================
   EL TITULO «DASHBOARD», EN MORADO   [03/09/2026]

   QUE SE PIDIO
     Que el texto «Dashboard» de la barra de arriba deje de verse negro
     y pase a morado. Solo ese: al entrar a Facturas de compra, a
     Proyectos 2026 o a cualquier otra seccion, el titulo vuelve a su
     color de siempre.

   POR QUE SE HACE CON CSS Y NO TOCANDO EL CODIGO
     El <h2 id="title"> es UNO SOLO para todo el CRM: el codigo le
     cambia el texto al navegar. Para colorear solo un caso habria que
     meter mano en la navegacion —el sitio por donde pasa cada cambio
     de pantalla— y eso es riesgo a cambio de un color.

     Aqui se aprovecha algo que el CRM ya hace: la seccion visible
     lleva la clase «active» (.view{display:none} / .view.active
     {display:block}). Asi que basta preguntar «¿la seccion activa es
     el Dashboard?» y, si lo es, pintar el titulo. Cero JavaScript.

   :has() ES LO QUE PERMITE PREGUNTARLO
     El titulo esta ANTES que las secciones en el documento, y el CSS
     normal no puede mirar hacia adelante. :has() si. Lo soportan
     Chrome y Edge desde la 105, Safari desde la 15.4 y Firefox desde
     la 121. En un navegador mas viejo el titulo se queda del color de
     antes: no se rompe nada.

   YA NO ES MORADO
     Lo de arriba sigue siendo cierto -asi es como se pinta SOLO el
     titulo del Dashboard sin tocar la navegacion-, pero el color ya
     no es morado. Aquel morado fue una prueba del 03/09 y se pidio
     volver al negro el mismo dia.
   ============================================================ */
/* RETIRADO EL MORADO   [03/09/2026]
   El morado se puso el 03/09 como prueba y se pidio volver al negro.
   No se escribe «#000»: se deja el color normal del texto, var(--txt),
   que es #0f172a -practicamente negro- sobre el tema claro y #e6e9ec
   sobre el oscuro. Un negro literal seria invisible en el tema oscuro,
   que es justo con el que se trabaja aqui todo el dia. «Negro» quiere
   decir «como el resto de los titulos», y eso es lo que hace esto. */
.main:has(#v-dash.active) .topbar h2{color:var(--txt)}
.topbar .role{background:var(--panel2);padding:6px 12px;border-radius:8px;font-size:12px;color:var(--muted)}
/* ============================================================
   ZONA · ESTRUCTURA: TARJETAS Y REJILLAS
   11 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
.view{display:none}
.view.active{display:block}
.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:16px;margin-bottom:24px}
.card{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:18px}
.kpi .n{font-size:30px;font-weight:700}
.kpi{position:relative;overflow:hidden;transition:transform .18s ease,box-shadow .18s ease}
.kpi:hover{transform:translateY(-4px);box-shadow:0 14px 34px rgba(0,0,0,.4)}
.kpi::after{content:"";position:absolute;left:0;top:0;bottom:0;width:4px;background:var(--accent)}
.kpi.warn::after{background:var(--warn)}.kpi.ok::after{background:var(--ok)}.kpi.bad::after{background:var(--bad)}
.kpi .n{font-size:40px;line-height:1}
.kpi .l{margin-top:8px}
.pbar .pfill{border-radius:8px;box-shadow:0 1px 6px rgba(0,0,0,.25)}
/* ============================================================
   ZONA · ESTRUCTURA: TARJETAS Y REJILLAS
   9 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
.card{transition:border-color .15s,transform .15s}
.kpi .l{color:var(--muted);font-size:12px;margin-top:4px;text-transform:uppercase;letter-spacing:.5px}
.kpi.warn .n{color:var(--warn)} .kpi.ok .n{color:var(--ok)} .kpi.acc .n{color:var(--accent)} .kpi.pur .n{color:var(--purple)}
/* ---- KPIs compactos: cuatro botones en una sola fila ----
   Antes eran tarjetas altas (auto-fit 200px + número de 40px) que se
   partían en dos filas y empujaban el resto del dashboard hacia abajo. */
.kpis{grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:16px}
.kpi{padding:14px 16px;border-radius:12px;display:flex;align-items:center;gap:13px;min-width:0}
.kpi::after{width:4px}
.kpi .n{font-size:32px;line-height:1;margin:0;flex:0 0 auto}
.kpi .l{margin:0;font-size:11px;line-height:1.3;letter-spacing:.4px;min-width:0}
.kpi:hover{transform:translateY(-3px);box-shadow:0 10px 24px rgba(0,0,0,.32)}
/* Los KPI de vuelos llevan etiquetas largas: precio arriba y leyenda debajo.
   En horizontal el texto quedaba estrujado en una columna de 3 caracteres. */
#vuelos-kpis .kpi{flex-direction:column;align-items:flex-start;gap:5px;padding:13px 15px;justify-content:center;min-height:78px}
#vuelos-kpis .kpi .n{font-size:26px;white-space:nowrap}
#vuelos-kpis .kpi .l{font-size:10.5px;line-height:1.35;text-transform:none;letter-spacing:.2px;white-space:normal}
.grid2{display:grid;grid-template-columns:1.4fr 1fr;gap:16px}
.card h3{font-size:14px;margin-bottom:14px;color:var(--txt);display:flex;justify-content:space-between;align-items:center}
.card h3 small{color:var(--muted);font-weight:400}
table{width:100%;border-collapse:collapse}
th{text-align:left;color:var(--muted);font-size:11px;text-transform:uppercase;letter-spacing:.5px;padding:8px 10px;border-bottom:1px solid var(--line)}
td{padding:10px;border-bottom:1px solid var(--line);font-size:13px}
tr:hover td{background:var(--panel2)}
.badge{display:inline-block;padding:3px 9px;border-radius:20px;font-size:11px;font-weight:600}
.b-prog{background:#334155;color:#cbd5e1}
.b-ejec{background:#0c4a6e;color:#7dd3fc}
.b-firma{background:#78350f;color:#fcd34d}
.b-info{background:#14532d;color:#86efac}
.b-ok{background:#14532d;color:#86efac}
.b-warn{background:#78350f;color:#fcd34d}
.b-bad{background:#7f1d1d;color:#fca5a5}
/* ============================================================
   ZONA · BOTONES Y CAMPOS
   11 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
.pill{font-size:11px;padding:2px 8px;border-radius:6px;background:var(--panel2);color:var(--muted)}
.btn{background:var(--accent2);color:#fff;border:none;padding:8px 14px;border-radius:8px;cursor:pointer;font-size:13px}
.btn:hover{background:var(--accent)}
.btn.ghost{background:transparent;border:1px solid var(--line);color:var(--muted)}
/* ===================================================================
   UN BOTÓN APAGADO TIENE QUE VERSE APAGADO       [09/09/2026]

   EL FALLO, COMPROBADO EN LA PANTALLA
     .btn no decía nada sobre :disabled. Un botón deshabilitado se veía
     EXACTAMENTE igual que uno vivo: mismo dorado, mismo puntero de
     mano. Medido sobre «Aceptar y recibir»: opacity 1 y cursor pointer
     estando disabled=true.

   POR QUÉ IMPORTA MÁS DE LO QUE PARECE
     El CRM apaga botones en sitios donde apagarlos ES la protección:
     «Enviar» hasta que haya destino, «PDF de la remisión» hasta que
     haya algo que listar, «Aceptar y recibir» hasta que se firme el
     acuse. Si se ven encendidos, la gente los pulsa, no pasa nada, y
     concluye que el CRM está roto — cuando lo que pasa es que falta un
     paso que nadie le señaló.

   SI ESTAS DOS LÍNEAS DESAPARECEN: vuelven los botones que parecen
   funcionar y no funcionan, en todo el CRM.
   =================================================================== */
.btn:disabled,.btn[disabled]{opacity:.42;cursor:not-allowed}
.btn:disabled:hover,.btn[disabled]:hover{background:var(--accent2)}
.btn.ghost:disabled:hover,.btn.ghost[disabled]:hover{background:transparent}
/* ==== File inputs bonitos (Seleccionar archivo) ==== */
input[type=file]:not([style*="display:none"]){color:var(--muted);font-size:13px;background:var(--panel2);border:1px solid var(--line);border-radius:9px;padding:5px 10px 5px 5px;cursor:pointer;max-width:100%;transition:border-color .15s,background .15s}
input[type=file]:not([style*="display:none"]):hover{border-color:var(--accent)}
input[type=file]::file-selector-button{margin-right:10px;background:var(--accent2);color:#fff;border:none;padding:7px 15px;border-radius:7px;font-size:13px;font-weight:600;cursor:pointer;transition:background .15s,box-shadow .15s;box-shadow:0 1px 2px rgba(0,0,0,.2)}
input[type=file]:hover::file-selector-button{background:var(--accent)}
input[type=file]::-webkit-file-selector-button{margin-right:10px;background:var(--accent2);color:#fff;border:none;padding:7px 15px;border-radius:7px;font-size:13px;font-weight:600;cursor:pointer;transition:background .15s}
input[type=file]:hover::-webkit-file-selector-button{background:var(--accent)}
input[type=file]:focus-visible{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px rgba(56,189,248,.15)}

.link{color:var(--accent);cursor:pointer;text-decoration:underline}
.plane{color:var(--accent)}
.tl{display:flex;align-items:flex-start;margin:10px 0;width:100%}
.tl .step{flex:1 1 0;min-width:0;text-align:center;position:relative}
.tl .dot{width:26px;height:26px;border-radius:50%;background:var(--panel2);border:2px solid var(--line);margin:0 auto 6px;display:flex;align-items:center;justify-content:center;font-size:12px;color:var(--muted)}
.tl .step.done .dot{background:var(--ok);border-color:var(--ok);color:#052e16}
.tl .step.current .dot{background:var(--accent);border-color:var(--accent);color:#03293b;box-shadow:0 0 0 4px rgba(56,189,248,.2)}
.tl .step .lbl{font-size:10px;line-height:1.15;color:var(--muted);padding:0 2px;word-break:break-word}
.tl .step.done .lbl,.tl .step.current .lbl{color:var(--txt)}
.tl .bar{height:2px;background:var(--line);flex:1 1 0;min-width:6px;margin-top:12px}
.tl .bar.done{background:var(--ok)}
.overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:50;align-items:center;justify-content:center;overflow:auto;padding:16px;box-sizing:border-box}
.overlay.open{display:flex}
.modal{background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:24px;width:640px;max-width:92vw;max-height:92vh;overflow-y:auto;box-sizing:border-box}
/* ---- Vista preliminar del reporte (funciona sin lector de PDF) ----
   Pensada también para televisores: botones grandes, foco muy visible
   para el control remoto y ningún elemento que dependa del mouse. */
/* ============================================================
   ZONA · VISOR DE DOCUMENTOS
   13 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
.pdfv-modal{width:1100px;max-width:96vw;max-height:94vh;padding:0;display:flex;flex-direction:column;overflow:hidden}
.pdfv-bar{display:flex;align-items:center;gap:12px;flex-wrap:wrap;
  padding:12px 14px;border-bottom:1px solid var(--line);background:var(--panel2)}
.pdfv-tit{flex:1 1 200px;min-width:0;font-size:14px;font-weight:700;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pdfv-nav{display:flex;align-items:center;gap:6px;flex-wrap:wrap}
.pdfv-b{min-width:44px;min-height:40px;padding:6px 12px;font-size:16px;line-height:1}
.pdfv-b:focus-visible,.pdfv-b:focus{outline:3px solid var(--accent);outline-offset:2px}
.pdfv-pag{font-size:13px;color:var(--muted);min-width:92px;text-align:center;font-weight:600}
/* ---- POR QUE align-items NO PUEDE SER center ----
   Con `center`, una hoja mas ancha que la ventana se desborda por los
   DOS lados a la vez, y la mitad izquierda queda fuera del alcance del
   desplazamiento: no hay forma de llegar a ella. Es el comportamiento
   normal de una caja flexible centrada, y solo se nota al ampliar.

   Con `flex-start` mas los margenes automaticos de la hoja, se logran
   las dos cosas: se centra mientras quepa, y cuando no cabe arranca
   pegada al borde izquierdo y se recorre entera. */
.pdfv-lienzo{flex:1;overflow:auto;-webkit-overflow-scrolling:touch;background:#0b1220;
  padding:14px;display:flex;flex-direction:column;align-items:flex-start;gap:14px}
.pdfv-lienzo:focus{outline:none}
/* ---- Controles del visor ----
   La lista de hojas y el nivel de ampliación se visten como el resto de
   la barra para que no parezcan añadidos. */
.pdfv-sel{background:var(--panel2);border:1px solid var(--line);color:var(--txt);
  border-radius:8px;padding:4px 8px;font-size:12px;font-family:inherit;cursor:pointer;
  max-width:150px}
.pdfv-sel:hover{border-color:var(--accent)}
.pdfv-nivel{font-size:11.5px;color:var(--muted);min-width:44px;text-align:center;
  font-variant-numeric:tabular-nums}
/* Al ampliar, la hoja puede quedar más ancha que la ventana. Sin esto
   se recortaría por los lados sin forma de llegar al borde derecho:
   `center` deja de centrar cuando el contenido no cabe, y el
   desplazamiento horizontal se vuelve imprescindible. */
.pdfv-lienzo{overflow:auto}
.pdfv-lienzo canvas,.pdfv-lienzo img{margin-left:auto;margin-right:auto}
/* ---- POR QUE SE QUITO max-width:100% ----
   ESTE era el motivo de que el zoom no ampliara nada. La hoja se
   volvia a dibujar a mayor resolucion —el calculo estaba bien— pero
   esta regla le ponia un techo al ancho mostrado: el de la ventana.
   Resultado: al pulsar + la hoja ganaba nitidez y NO ganaba tamaño.
   Se veia exactamente igual, y solo cambiaba el numero del porcentaje.

   El ancho de cada hoja lo fija ahora el codigo al dibujarla, en
   proporcion al zoom elegido. Ver _pdfvPintar(). */
.pdfv-lienzo canvas{height:auto;background:#fff;border-radius:4px;
  box-shadow:0 8px 26px rgba(0,0,0,.5)}
/* ---- ARRASTRAR PARA RECORRER EL DOCUMENTO AMPLIADO ----
   QUE HACE
     Cambia el puntero a una mano cuando la hoja no cabe en la ventana,
     y a mano cerrada mientras se arrastra.

   POR QUE
     Al ampliar, la hoja se sale de la ventana por los lados y por abajo.
     Llegar a una esquina con las barras de desplazamiento obliga a
     soltar el documento, buscar la barra, arrastrarla, y repetir para el
     otro eje. Con el arrastre se recorre como un plano sobre la mesa: se
     agarra donde sea y se mueve. Es el gesto que ya se usa en los mapas.

   QUE CUIDAR
     La clase `pdfv-mano` la pone y la quita el codigo -_pdfvMano()-,
     segun si sobra documento o no. Si se pusiera fija, el puntero
     prometeria un arrastre que al 100 % no hace nada.

     Mientras se arrastra se apagan los eventos de la hoja y se corta la
     seleccion: sin eso el navegador entiende «estoy seleccionando» o
     «estoy arrastrando una imagen a otra ventana», y aparece el
     fantasma de la imagen pegado al puntero. */
.pdfv-lienzo.pdfv-mano{cursor:grab}
.pdfv-lienzo.pdfv-mano:active{cursor:grabbing}
.pdfv-lienzo.pdfv-arrastrando{cursor:grabbing;user-select:none;-webkit-user-select:none}
.pdfv-lienzo.pdfv-arrastrando canvas,
.pdfv-lienzo.pdfv-arrastrando img,
.pdfv-lienzo.pdfv-arrastrando iframe{pointer-events:none}
.pdfv-msg{color:var(--muted);font-size:13px;text-align:center;padding:40px 16px;line-height:1.6}
.pdfv-msg .btn{margin-top:12px}
.pdfv-pie{padding:9px 14px;border-top:1px solid var(--line);background:var(--panel2);
  font-size:11.5px;color:var(--muted);text-align:center}
[data-theme="light"] .pdfv-lienzo{background:#e2e8f0}
@media(max-width:640px){
/* ============================================================
   ZONA · VISOR DE DOCUMENTOS
   7 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
  .pdfv-modal{max-width:100%;max-height:calc(100vh - 16px)}
  .pdfv-bar{padding:10px}
  .pdfv-tit{flex:1 1 100%;font-size:13px;white-space:normal}
  .pdfv-nav{width:100%;justify-content:space-between}
  .pdfv-pag{min-width:0;flex:1 1 auto;font-size:12px}
  .pdfv-lienzo{padding:8px;gap:10px}
  .pdfv-pie{font-size:10.5px;padding:7px 10px}
}
@supports(height:100dvh){
  @media(max-width:640px){ .pdfv-modal{max-height:calc(100dvh - 16px)} }
}
.modal h3{font-size:18px;margin-bottom:4px}
.modal .sub{color:var(--muted);font-size:13px;margin-bottom:18px}
.kv{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:10px 24px;margin:16px 0}
.kv div span{color:var(--muted);font-size:11px;display:block;text-transform:uppercase}
.kv div b{font-size:14px;word-break:break-word;overflow-wrap:anywhere}
.spec-head{flex-wrap:wrap}
@media(max-width:520px){.modal{padding:16px}.kv{grid-template-columns:1fr;gap:10px}.modal h3{font-size:16px}}
.close{float:right;cursor:pointer;color:var(--muted);font-size:20px}
.filters{display:flex;gap:8px;margin-bottom:14px;flex-wrap:wrap}
/* ---- Filtros a la izquierda, acciones a la derecha ----
   Los botones de crear documento no filtran nada: son acciones. Puestos
   en la misma hilera se confundían con los desplegables. Ahora van
   aparte, pegados al costado derecho, uno sobre otro y del mismo ancho.
   Quedan siempre en el mismo lugar, se agranden o no los filtros. */
.filters-prog{align-items:center;justify-content:space-between;gap:10px}
.filtros-campos{display:flex;gap:8px;flex-wrap:wrap;align-items:center;flex:1 1 auto;min-width:0}
/* Los dos botones, uno al lado del otro, en el mismo renglón que los
   filtros y pegados al costado derecho. */
.filtros-acc{display:flex;flex-direction:row;gap:8px;flex:0 0 auto;align-items:center;flex-wrap:wrap}
.filtros-acc .btn{white-space:nowrap}
@media(max-width:820px){
  /* Si el renglón ya no da, los botones bajan juntos y ocupan el ancho */
  .filters-prog{align-items:stretch}
  .filtros-acc{width:100%}
  .filtros-acc .btn{flex:1 1 0;justify-content:center}
}
.filters select,.filters input{background:var(--panel2);border:1px solid var(--line);color:var(--txt);padding:7px 10px;border-radius:8px;font-size:13px}
.legend{display:flex;gap:14px;flex-wrap:wrap;font-size:12px;color:var(--muted);margin-top:10px}
.dotmini{display:inline-block;width:10px;height:10px;border-radius:50%;margin-right:5px;vertical-align:middle}
.ev.cumple{background:#ec4899!important}
.ev.imp{background:#f59e0b!important;color:#1a1a1a}
.evcard.imp{border-left-color:#f59e0b!important}
.imp-card{position:relative;overflow:hidden;border:1px solid var(--line);border-left:4px solid var(--line);background:var(--panel);box-shadow:0 6px 22px rgba(0,0,0,.06)}
.imp-card::before{content:"";position:absolute;top:0;left:0;right:0;height:3px;background:var(--line)}
.imp-card h3{display:flex;align-items:center;gap:8px}
.imp-badge{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;border-radius:8px;background:var(--panel2);color:var(--muted);font-size:14px;box-shadow:inset 0 0 0 1px var(--line)}
/* El marco completo adopta el tono del ítem más urgente (no queda fijo en ámbar) */
.imp-card.t-rojo{border-left-color:#ef4444;box-shadow:0 6px 22px rgba(239,68,68,.08)}
.imp-card.t-rojo::before{background:linear-gradient(90deg,#ef4444,#f87171,#ef4444)}
.imp-card.t-rojo .imp-badge{background:rgba(239,68,68,.16);color:#ef4444;box-shadow:inset 0 0 0 1px rgba(239,68,68,.35)}
.imp-card.t-amar{border-left-color:#f59e0b;box-shadow:0 6px 22px rgba(245,158,11,.08)}
.imp-card.t-amar::before{background:linear-gradient(90deg,#f59e0b,#fbbf24,#f59e0b)}
.imp-card.t-amar .imp-badge{background:rgba(245,158,11,.16);color:#f59e0b;box-shadow:inset 0 0 0 1px rgba(245,158,11,.35)}
.imp-card.t-verde{border-left-color:#22c55e;box-shadow:0 6px 22px rgba(34,197,94,.08)}
.imp-card.t-verde::before{background:linear-gradient(90deg,#22c55e,#4ade80,#22c55e)}
.imp-card.t-verde .imp-badge{background:rgba(34,197,94,.16);color:#22c55e;box-shadow:inset 0 0 0 1px rgba(34,197,94,.35)}
.imp-row{display:flex;align-items:center;gap:12px;padding:10px;margin:2px -6px;border-radius:10px;border-bottom:1px solid var(--line);font-size:13px;transition:background .15s,transform .12s}
.imp-row:last-child{border-bottom:none}
.imp-row:hover{background:rgba(245,158,11,.07);transform:translateX(2px)}
.imp-ico{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;flex:none;border-radius:8px;background:rgba(245,158,11,.14);color:#f59e0b;font-size:15px}
.imp-txt{flex:1;line-height:1.4}
.imp-txt small{display:block;color:var(--muted);font-size:11px;margin-top:1px}
.imp-meta{display:flex;flex-direction:column;align-items:flex-end;gap:4px;white-space:nowrap}
.imp-date{font-weight:700;color:var(--txt);font-size:12.5px}
.imp-days{font-size:10.5px;font-weight:700;letter-spacing:.3px;padding:2px 8px;border-radius:999px;background:rgba(245,158,11,.15);color:#f59e0b}
.imp-days.soon{background:rgba(239,68,68,.16);color:#f87171}
.imp-days.far{background:rgba(148,163,184,.16);color:var(--muted)}
/* ===== Importante · 3 tonos por proximidad de vencimiento ===== */
.imp-row.rojo{border-left:3px solid #ef4444;padding-left:8px}
.imp-row.amar{border-left:3px solid #f59e0b;padding-left:8px}
.imp-row.verde{border-left:3px solid #22c55e;padding-left:8px}
.imp-row.rojo:hover{background:rgba(239,68,68,.08)}
.imp-row.amar:hover{background:rgba(245,158,11,.08)}
.imp-row.verde:hover{background:rgba(34,197,94,.08)}
.imp-ico.rojo{background:rgba(239,68,68,.16);color:#ef4444}
.imp-ico.amar{background:rgba(245,158,11,.16);color:#f59e0b}
.imp-ico.verde{background:rgba(34,197,94,.16);color:#22c55e}
.imp-days.rojo{background:rgba(239,68,68,.16);color:#f87171}
.imp-days.amar{background:rgba(245,158,11,.16);color:#f59e0b}
.imp-days.verde{background:rgba(34,197,94,.16);color:#22c55e}
.imp-hide{margin-left:auto;background:transparent;border:1px solid var(--line);color:var(--muted);font-size:11px;padding:3px 9px;border-radius:999px;cursor:pointer}
.imp-hide:hover{background:var(--panel2);color:var(--txt)}
.imp-collapsed{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--muted);margin-bottom:16px;padding:8px 12px;border:1px dashed var(--line);border-radius:10px}
.imp-collapsed .btn{margin-left:auto}
/* ===== UptimeRobot · widget de estado en vivo ===== */
.ur-grid{display:grid;grid-template-columns:2fr 1fr;gap:16px;margin-bottom:16px}
.ur-mon-wrap{display:flex;flex-direction:column;gap:12px}
.ur-mon{background:linear-gradient(180deg,rgba(56,189,248,.10),rgba(56,189,248,0) 60%),var(--panel);border:1px solid var(--line);border-radius:14px;padding:14px 16px;display:flex;align-items:center;gap:12px}
.ur-mon .ur-name{flex:1;min-width:0}
.ur-mon .ur-name b{display:block;font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ur-mon .ur-name small{color:var(--muted);font-size:11px}
.ur-spark{display:flex;gap:2px;align-items:flex-end;height:22px}
.ur-spark i{width:4px;border-radius:1px;background:#22c55e;height:100%}
.ur-spark i.down{background:#ef4444}.ur-spark i.pause{background:#94a3b8}
.ur-pct{font-weight:700;font-size:13px;min-width:52px;text-align:right}
.ur-status{position:relative;background:var(--panel);border:1px solid var(--line);border-radius:14px;padding:16px;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center}
.ur-title{align-self:flex-start;font-size:12px;color:var(--muted);text-transform:uppercase;letter-spacing:.5px;margin-bottom:8px}
.ur-beacon{width:56px;height:56px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:24px;margin:6px 0 12px}
.ur-beacon.ok{background:rgba(34,197,94,.16);color:#22c55e;box-shadow:0 0 0 6px rgba(34,197,94,.08)}
.ur-beacon.bad{background:rgba(239,68,68,.16);color:#ef4444;box-shadow:0 0 0 6px rgba(239,68,68,.08)}
.ur-counts{display:flex;gap:18px;margin-bottom:8px}
.ur-counts div{text-align:center}.ur-counts .cn{font-size:22px;font-weight:700;line-height:1}
.ur-counts .cl{font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:.4px}
.ur-counts .up .cn{color:#22c55e}.ur-counts .down .cn{color:var(--bad)}.ur-counts .pause .cn{color:#94a3b8}
.ur-foot{font-size:11px;color:var(--muted)}
.ur-cfg{font-size:12px;color:var(--muted);text-align:center;padding:18px}
.ur-cfg input{background:var(--panel2);border:1px solid var(--line);color:var(--txt);padding:7px 10px;border-radius:8px;font-size:12px;width:min(320px,90%);margin:8px 0}
@media(max-width:820px){.ur-grid{grid-template-columns:1fr}}
/* Fila superior: Monitor página web (izq) + Importante (der), mismo estilo de cuadrito */
.dash-top-grid{display:flex;gap:16px;flex-wrap:wrap;align-items:flex-start;margin-bottom:16px}
.dash-top-grid>div{flex:1 1 340px;min-width:0}
/* Respaldo en CSS por si el ajuste de JavaScript no alcanzara a correr:
   una tarjeta sin contenido no debe reservar espacio ni separación. */
.dash-top-grid>div:empty{display:none}
.mon-foot{font-size:11px;color:var(--muted);margin-top:6px;padding-top:8px;border-top:1px solid var(--line);display:flex;gap:4px 12px;flex-wrap:wrap;align-items:center}
.mon-foot b{color:var(--txt)}
.cakemini{font-size:9px;margin-left:1px;vertical-align:middle}
.evcard.cumple .evmain b{color:#ec4899}
.leyop{flex-wrap:wrap;gap:6px 14px;margin-top:6px;border-top:1px solid var(--line);padding-top:8px}
.leyop-t{font-weight:700;color:var(--muted);font-size:11px;text-transform:uppercase;letter-spacing:.5px;margin-right:2px}
.leyop-i{display:inline-flex;align-items:center;font-size:12px;cursor:pointer;padding:2px 8px;border-radius:12px;border:1px solid transparent}
.leyop-i:hover{background:var(--panel2)}
.leyop-i.act{background:var(--panel2);border-color:var(--accent);font-weight:600}
.leyop-todos{font-weight:600}
.leyop-i.off{opacity:.45;text-decoration:line-through}
.swatch{display:inline-block;width:11px;height:11px;border-radius:3px;margin-right:5px;border:1px solid rgba(0,0,0,.25)}
.note{background:var(--panel2);border-left:3px solid var(--accent);padding:10px 14px;border-radius:8px;color:var(--muted);font-size:12px;margin-top:14px}
/* ---- Avatares: SIEMPRE circulares ----
   Dentro de un contenedor flex, el navegador encoge las imágenes a lo
   ancho pero no a lo alto: por eso al angostar la ventana las fotos
   salían ovaladas. Tres candados:
     flex:0 0 auto  -> no lo puede encoger el contenedor
     min-width:...  -> ni siquiera con min-width:auto de por medio
     aspect-ratio:1 -> si algo lo fuerza, se mantiene cuadrado
   object-fit:cover recorta la foto en vez de deformarla. */
.avatar{display:inline-flex;align-items:center;justify-content:center;border-radius:50%;color:#fff;font-weight:700;
  flex:0 0 auto;aspect-ratio:1/1;object-fit:cover;overflow:hidden}
img.avatar{display:block}
.avatar-w{display:inline-block;position:relative;line-height:0;flex:0 0 auto;aspect-ratio:1/1;border-radius:50%}
/* En cualquier fila con foto, el bloque de la imagen no cede espacio */
.chip-top .avatar,.chip-top .avatar-w,
.cg-nom .avatar,.cg-nom .avatar-w,
.cg-hnom .avatar,.cg-hnom .avatar-w,
.spec-head .avatar,.spec-head .avatar-w,
.ubox .avatar,.ubox .avatar-w{flex:0 0 auto!important}
.specrow{display:inline-flex;align-items:center;gap:10px;cursor:pointer}
.specrow:hover b{color:var(--accent);text-decoration:underline}
.spec-head{display:flex;align-items:center;gap:18px}
/* Calendario */
/* ============================================================
   ZONA · CALENDARIO Y AGENDA
   10 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
.calbar{display:block;margin-bottom:18px}
/* Fila única: selector de vista + los tres botones de agendar */
.calbar-top{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin-bottom:10px}
.calbar-nav{display:flex;flex-wrap:wrap;gap:12px;align-items:center;justify-content:space-between;
  padding-top:10px;border-top:1px solid var(--line)}
.calviews{display:flex;gap:4px;background:var(--panel2);padding:4px;border-radius:10px}
.calviews button{background:transparent;border:none;color:var(--muted);padding:7px 14px;border-radius:7px;cursor:pointer;font-size:13px}
.calviews button.on{background:var(--accent2);color:#fff}
.calnav{display:flex;align-items:center;gap:8px}
.callabel{font-size:15px;font-weight:600;margin-left:8px;text-transform:capitalize}
.calrange{display:flex;align-items:center;gap:8px;color:var(--muted);font-size:13px}
.calactions{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-left:auto}
/* Botones de agendamiento — mismo aspecto en la barra del calendario y en el
   pop-up del día. Color por tipo: cian mantenimiento, morado actividad,
   verde ausencia. Solo el signo +, sin emojis. */
.act-btn{display:inline-flex;align-items:center;gap:7px;padding:8px 14px;border:none;border-radius:9px;color:#fff;font-size:13px;font-weight:600;cursor:pointer;box-shadow:0 2px 6px rgba(0,0,0,.22);transition:transform .12s ease,filter .15s ease}
.act-btn span{font-size:16px;line-height:1;font-weight:700;opacity:.92}
.act-btn:hover{transform:translateY(-1px);filter:brightness(1.10)}
.act-btn:active{transform:translateY(0)}
.act-mant{background:#0ea5e9}
.act-act{background:#7c3aed}
.act-aus{background:#dc2626}
#prog-body tr.row-next{background:rgba(16,185,129,.10);box-shadow:inset 3px 0 0 #10b981}
#prog-body tr.row-past{opacity:.62}
/* ---- Listado general de programación (mantenimientos + actividades + ausencias) ---- */
.tbadge{font-size:10px;padding:2px 8px;border-radius:8px;font-weight:600;white-space:nowrap;display:inline-block}
.tbadge.t-mant{background:#0c4a6e;color:#bae6fd}
.tbadge.t-act{background:#4c1d95;color:#ddd6fe}
.tbadge.t-proy{background:#134e4a;color:#99f6e4}
.tbadge.t-aus{background:#7f1d1d;color:#fca5a5}
.ag-mes{margin-bottom:18px}
.ag-mes-h{display:flex;justify-content:space-between;align-items:baseline;gap:10px;flex-wrap:wrap;
  padding:7px 10px;margin-bottom:6px;background:var(--panel2);border:1px solid var(--line);border-radius:8px;
  position:sticky;top:0;z-index:2}
.ag-mes-h b{font-size:13px;text-transform:capitalize}
.ag-mes-h span{font-size:11px;color:var(--muted)}
.ag-row{display:grid;grid-template-columns:150px 128px 1fr 190px 132px 92px;gap:10px;align-items:center;
  padding:8px 10px;border-bottom:1px solid var(--line);font-size:12.5px}
.ag-row:hover{background:var(--panel2)}
/* ---- La columna de acciones no parte las palabras ----
   La ultima columna mide 92 px. Con un solo boton sobra; al meter un
   segundo, el texto se partia LETRA POR LETRA en vertical, porque una
   caja flexible estrecha rompe por donde puede. Se veia como una
   columna de caracteres sueltos.

   `nowrap` obliga al boton a mantenerse en una linea. Si algun dia no
   cabe, se sale o se encoge, pero nunca se deshace en letras. La
   solucion de fondo -y la que se aplico- fue dejar UN boton por fila y
   llevar el resto al detalle, igual que en mantenimientos. */
.ag-acc{display:flex;gap:6px;justify-content:flex-end;flex-wrap:nowrap}
.ag-acc .btn{white-space:nowrap;flex:0 0 auto;padding-left:9px;padding-right:9px}
.ag-row.ag-past{opacity:.55}
.ag-row.ag-hoy{background:rgba(16,185,129,.10)}
.ag-fecha{font-size:11.5px;color:var(--muted);line-height:1.5}
.ag-tit small{color:var(--muted);font-size:11px}
.ag-quien{font-size:11.5px;color:var(--muted);min-width:0}
/* Asignados en columna: un color + un nombre por línea */
.q-lista{display:flex;flex-direction:column;gap:3px}
.q-item{display:flex;align-items:center;gap:6px;line-height:1.25;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.q-item .swatch{flex:0 0 auto;width:9px;height:9px;border-radius:50%;display:inline-block}
.q-vacio{color:var(--muted);font-style:italic}
.q-det{display:block;margin-top:4px;color:var(--muted)}
.dd-item .q-lista{margin-top:3px}
/* ---- Vista Personalizado: un bloque por día ---- */
.cusdias{display:flex;flex-direction:column;gap:14px}
.cus-dia{border:1px solid var(--line);border-radius:10px;overflow:hidden;background:var(--panel)}
.cus-dia.hol{border-color:rgba(239,68,68,.45)}
.cus-dia.hoy{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent)}
.cus-h{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:9px 12px;cursor:pointer;
  background:var(--panel2);border-bottom:1px solid var(--line);font-size:13px}
.cus-h:hover{background:rgba(56,189,248,.10)}
.cus-h b{text-transform:capitalize}
.cus-n{margin-left:auto;font-size:11px;color:var(--muted)}
.cus-item{display:flex;gap:12px;align-items:flex-start;padding:9px 12px 9px 15px;
  border-bottom:1px solid var(--line);font-size:12.5px}
.cus-item:last-child{border-bottom:none}
.cus-item:hover{background:var(--panel2)}
.cus-hora{flex:0 0 96px;color:var(--muted);font-size:11.5px;line-height:1.45}
.cus-hora small{font-size:10px;opacity:.8}
.cus-b{flex:1;min-width:0;line-height:1.5}
.cus-b .q-lista{margin-top:5px}
@media(max-width:640px){
  .cus-item{flex-direction:column;gap:5px}
  .cus-hora{flex:0 0 auto}
}
.ag-acc{text-align:right;display:flex;gap:4px;justify-content:flex-end}
.ag-acc .btn{padding:3px 9px;font-size:11px}
/* Botón de borrado: discreto hasta que se apunta, para no invitar al clic */
.btn.bdel{color:var(--muted);padding:3px 7px;font-size:12px;line-height:1}
.btn.bdel:hover{color:#fca5a5;border-color:#7f1d1d;background:rgba(127,29,29,.25)}
.btn.danger{background:#7f1d1d;color:#fecaca;border-color:#991b1b}
.btn.danger:hover{background:#991b1b;color:#fff}
.dd-item .bdel{flex:0 0 auto;align-self:center}
@media(max-width:1100px){
  .ag-row{grid-template-columns:132px 112px 1fr 150px 86px;row-gap:4px}
  .ag-row .ag-est{display:none}
}
@media(max-width:760px){
  .ag-row{grid-template-columns:1fr auto;padding:10px}
  .ag-row>span{grid-column:1/2}
  .ag-row .ag-acc{grid-column:2/3;grid-row:1/3}
  .ag-row .ag-est{display:inline}
  .ag-mes-h{position:static}
}
/* ---- Detalle del día ---- */
.dd-sec{margin:14px 0 0}
.dd-sec h4{margin:0 0 7px;font-size:12px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted)}
.dd-item{display:flex;gap:10px;align-items:flex-start;padding:8px 10px;border-radius:8px;
  background:var(--panel2);border-left:4px solid var(--accent);margin-bottom:6px;font-size:12.5px}
.dd-item .dd-h{flex:0 0 74px;color:var(--muted);font-size:11px;padding-top:1px}
.dd-item .dd-b{flex:1;min-width:0}
.dd-item .dd-b small{display:block;color:var(--muted);font-size:11px;margin-top:2px}
.dd-libres{display:flex;flex-wrap:wrap;gap:6px;margin-top:4px}
.dd-libre{font-size:11px;padding:3px 9px;border-radius:20px;background:#14532d;color:#86efac;display:inline-flex;align-items:center;gap:5px}
.dd-ocup{background:#7c2d12;color:#fed7aa}
/* ============================================================
   ZONA · BOTONES Y CAMPOS
   20 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
/* contraste medido: era 2,54:1 con blanco encima, por debajo del minimo
   legible (4,5:1). Mismo verde, mas oscuro: 4,52:1. [03/09/2026] */
.pill-next{background:#0c875e;color:#fff;font-weight:600}
/* ===== Selector de personal técnico (Agendar actividad) ===== */
.colsel-bar{display:flex;align-items:center;gap:8px;margin:4px 0 8px;flex-wrap:wrap}
.colsel-bar .btn.ghost{padding:3px 10px}
.colsel-count{margin-left:auto;font-size:12px;color:var(--muted)}
.colsel-count b{color:var(--accent)}
.colsel-search{width:100%;background:var(--panel2);border:1px solid var(--line);color:var(--txt);padding:8px 10px;border-radius:8px;font-size:13px;margin-bottom:8px}
.colsel{max-height:250px;overflow-y:auto;padding:2px;display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:6px}
.colsel-item{display:flex;align-items:center;gap:8px;padding:5px 8px;border:1px solid var(--line);border-radius:9px;background:var(--panel2);cursor:pointer;font-weight:400;transition:border-color .12s,background .12s,transform .1s}
.colsel-item:hover{border-color:var(--accent);transform:translateY(-1px)}
.colsel-item input{position:absolute;opacity:0;width:0;height:0}
.colsel-item:has(input:checked){border-color:var(--accent2);background:rgba(14,165,233,.14)}
.colsel-ini{width:26px;height:26px;border-radius:50%;color:#fff;font-size:10px;font-weight:700;display:flex;align-items:center;justify-content:center;flex:0 0 auto}
.colsel-pic{flex:0 0 auto;line-height:0}
.colsel-pic .avatar{width:26px;height:26px}
.colsel-info{display:flex;flex-direction:column;min-width:0;line-height:1.15}
.colsel-name{font-size:12px;color:var(--txt);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.colsel-sub{font-size:10px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.colsel-tick{margin-left:auto;width:17px;height:17px;border-radius:50%;border:2px solid var(--line);flex:0 0 auto;display:flex;align-items:center;justify-content:center;color:#fff;font-size:11px}
.colsel-item:has(input:checked) .colsel-tick{background:var(--accent2);border-color:var(--accent2)}
.colsel-item:has(input:checked) .colsel-tick::after{content:"✓"}
@media(max-width:520px){.colsel{grid-template-columns:1fr}}
/* fin [SEC-02] */

.mgrid.big .mhead{display:grid;grid-template-columns:repeat(7,1fr);color:var(--muted);font-size:11px;text-transform:uppercase;margin-bottom:4px}
.mgrid.big .mhead span{padding:6px}
.mgrid.big .mdays{display:grid;grid-template-columns:repeat(7,1fr);gap:6px}
.mgrid.big .mc{min-height:94px;background:var(--panel2);border:1px solid var(--line);border-radius:8px;padding:6px;cursor:pointer;overflow:hidden;position:relative}
.mgrid.big .mc:hover{border-color:var(--accent)}
.mgrid.big .mc.empty{background:transparent;border:none;cursor:default}
.mgrid.big .mc b{font-size:13px;color:var(--txt)}
.mgrid.big .mc.today{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
.mgrid.big .mc.hol{background:#3b1113}
.mgrid.big .mc.hol b{color:#fca5a5}
.mc .hname{display:block;font-size:9px;color:#fca5a5;margin-top:2px;line-height:1.1;font-style:normal}
.mc .ev{display:block;font-size:9px;color:#03293b;border-radius:4px;padding:1px 4px;margin-top:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-style:normal}
/* Mantenimiento de varios días: la barra se ve continua entre celdas.
   Solo el primer día y el último llevan esquina redondeada. */
.mc .ev.ev-span{border-radius:0;margin-left:-4px;margin-right:-4px;padding-left:6px;padding-right:6px;opacity:.92}
.mc .ev.ev-span.ev-ini{border-radius:4px 0 0 4px;margin-left:0;padding-left:4px;opacity:1}
.mc .ev.ev-span.ev-fin{border-radius:0 4px 4px 0;margin-right:0;padding-right:4px}
.mc .ev.ev-span.ev-ini.ev-fin{border-radius:4px}
.mgrid .mtitle{display:none}
.yeargrid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px}
.mgrid.mini{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:10px}
.mgrid.mini .mtitle{display:block;font-size:13px;font-weight:600;margin-bottom:8px;text-align:center;cursor:pointer;text-transform:capitalize}
.mgrid.mini .mtitle:hover{color:var(--accent)}
.mgrid.mini .mhead{display:grid;grid-template-columns:repeat(7,1fr);font-size:9px;color:var(--muted);text-align:center}
.mgrid.mini .mdays{display:grid;grid-template-columns:repeat(7,1fr);gap:2px;margin-top:4px}
.mgrid.mini .mc{font-size:11px;text-align:center;padding:3px 0;border-radius:5px;cursor:pointer;position:relative}
.mgrid.mini .mc.empty{cursor:default}
.mgrid.mini .mc.hol{background:#7f1d1d;color:#fca5a5}
.mgrid.mini .mc.today{background:var(--accent);color:#03293b;font-weight:700}
.mgrid.mini .mc .evd{position:absolute;bottom:1px;left:50%;transform:translateX(-50%);width:4px;height:4px;border-radius:50%;background:var(--accent)}
.weekwrap{display:grid;grid-template-columns:repeat(7,1fr);gap:8px}
.wday{background:var(--panel2);border:1px solid var(--line);border-radius:8px;padding:8px;min-height:130px}
.wday.today{border-color:var(--accent)}
.wday.hol{background:#3b1113}
.wdh{font-size:12px;font-weight:600;margin-bottom:8px}
.wdh .holtag{display:block;font-size:9px;color:#fca5a5;font-weight:400}
.wday .empty{color:var(--muted);font-size:12px}
.evcard{display:flex;align-items:center;gap:8px;background:var(--panel);border:1px solid var(--line);border-radius:7px;padding:6px 8px;margin-bottom:6px;cursor:pointer}
.evcard:hover{border-color:var(--accent)}
.evtime{font-size:11px;color:var(--accent);font-weight:600}
.evmain{flex:1;display:flex;flex-direction:column}
.evmain small{color:var(--muted);font-size:10px}
.dayview h4{margin:10px 0;text-transform:capitalize}
.holbanner{background:#3b1113;color:#fca5a5;padding:10px 14px;border-radius:8px;margin-bottom:12px}
.empty{color:var(--muted)}
.customlist .crow{display:flex;gap:10px;align-items:center;padding:8px;border-bottom:1px solid var(--line);font-size:13px}
.customlist .crow.hol{background:#2a1113}
.customlist .cdate{width:170px;color:var(--muted);text-transform:capitalize}
/* Seguimiento de proyectos */
.minitl{display:inline-flex;gap:5px;align-items:center}
.pdot{width:11px;height:11px;border-radius:50%;background:var(--line);display:inline-block}
.pdot.done{background:var(--ok)}
.pdot.cur{background:var(--accent);box-shadow:0 0 0 3px rgba(56,189,248,.25)}
.pbars{display:flex;flex-direction:column;gap:10px;margin:6px 0 4px}
.pbar{display:grid;grid-template-columns:170px 1fr 160px;align-items:center;gap:12px}
.pbar .pname{font-size:13px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pbar .ptrack{background:var(--panel2);border:1px solid var(--line);border-radius:8px;height:22px;overflow:hidden}
.pbar .pfill{height:100%;display:flex;align-items:center;justify-content:flex-end;padding-right:8px;font-size:11px;font-weight:700;color:#04210f;min-width:34px;transition:width .5s}
.pbar .pphase{font-size:11px;color:var(--muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mininote{font-size:11px;color:var(--muted);margin:8px 0 4px}
.mh{margin:20px 0 12px;font-size:14px;color:var(--txt);border-top:1px solid var(--line);padding-top:16px}
.cform{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:12px}
.cform label{display:flex;flex-direction:column;font-size:11px;color:var(--muted);gap:4px;text-transform:uppercase;letter-spacing:.4px}
.cform input{background:var(--panel2);border:1px solid var(--line);color:var(--txt);padding:9px;border-radius:7px;font-size:13px}
.addnota{display:flex;gap:8px;margin-bottom:14px;flex-wrap:wrap}
.addnota input{background:var(--panel2);border:1px solid var(--line);color:var(--txt);padding:9px;border-radius:7px;font-size:13px}
.addnota input[type=text]{flex:1;min-width:180px}
.addnota textarea{flex:1;min-width:220px;background:var(--panel2);border:1px solid var(--line);color:var(--txt);padding:9px;border-radius:7px;font-size:13px;font-family:inherit;resize:vertical}
.bitlist .bitrow{display:flex;gap:14px;padding:9px 0;border-bottom:1px solid var(--line);font-size:13px}
.bitdate{color:var(--accent);font-weight:600;white-space:nowrap;font-size:12px;min-width:88px}
.bitautor{color:var(--muted);font-size:11px;font-style:italic}
.faselist{display:flex;flex-direction:column;gap:8px;margin-bottom:6px}
.faserow{display:flex;align-items:center;gap:12px;background:var(--panel2);border:1px solid var(--line);border-radius:8px;padding:8px 12px}
.faserow.current{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
.fcirc{width:28px;height:28px;border-radius:50%;border:2px solid var(--line);background:var(--panel);color:var(--muted);font-size:12px;font-weight:700;cursor:pointer;flex:0 0 auto}
.fcirc:hover{border-color:var(--accent)}
.fcirc.done{background:var(--ok);border-color:var(--ok);color:#052e16}
.fcirc.current{background:var(--accent);border-color:var(--accent);color:#03293b}
.faserow .fname{flex:1;font-size:13px}
.faserow input[type=date]{background:var(--panel);border:1px solid var(--line);color:var(--txt);padding:6px 8px;border-radius:6px;font-size:12px}
.fstat{font-size:11px;color:var(--muted);min-width:78px;text-align:right}
.fstat.done{color:var(--ok)} .fstat.current{color:var(--accent)}
.ejtl{margin:6px 0 4px}
.ejtl .mc{cursor:default}
.mgrid.mini .mc.dom{color:#f59e0b;font-weight:700}
.mgrid.mini .mc.out{opacity:.26}
.ejleg{display:flex;gap:14px;font-size:11px;color:var(--muted);margin:4px 0 2px;flex-wrap:wrap}
#ej-view,.ejsel{background:var(--panel2);border:1px solid var(--line);color:var(--txt);padding:6px 9px;border-radius:8px;font-size:12px}
.ejsel{width:100%}
.ejsel[multiple]{padding:2px}
.ejdet{margin-bottom:16px}
.ejdet-h{display:flex;gap:10px;align-items:center;margin-bottom:4px;font-size:13px;flex-wrap:wrap}
/* Gantt */
.gantt{margin:10px 0 4px;font-size:12px}
.grow{display:flex;align-items:center;margin-bottom:6px}
.grow.ghead{margin-bottom:4px}
.glabel{width:160px;flex:0 0 160px;padding-right:10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--txt)}
.gtrack{position:relative;flex:1;height:26px;background:var(--panel2);border-radius:6px;overflow:visible}
.gdays{position:absolute;top:5px;font-size:10px;font-weight:700;color:var(--muted);white-space:nowrap;pointer-events:none}
.gdays.urg{color:#fca5a5}
.gdays.fin{color:var(--muted);font-weight:400}
.ghtrack{height:16px;background:transparent;overflow:visible}
.gline{position:absolute;top:0;bottom:0;border-left:1px dashed var(--line)}
.glabm{position:absolute;top:0;font-size:9px;color:var(--muted);transform:translateX(3px);white-space:nowrap}
.gtoday{position:absolute;top:0;bottom:0;border-left:2px solid var(--accent);z-index:3}
.gbar{position:absolute;top:3px;height:20px;border:1px solid;border-radius:5px;overflow:hidden;cursor:pointer;min-width:16px;z-index:2}
.gbar:hover{filter:brightness(1.15)}
.gfill{position:absolute;top:0;left:0;height:100%;opacity:.5}
.gtxt{position:absolute;left:6px;top:4px;font-size:10px;color:#fff;white-space:nowrap;z-index:1;text-shadow:0 1px 2px rgba(0,0,0,.7)}
@keyframes blinkhoy{0%,100%{opacity:1}50%{opacity:.18}}
.gtoday{animation:blinkhoy 1s ease-in-out infinite;box-shadow:0 0 8px 1px var(--accent)}
.gtoday-lbl{position:absolute;top:0;transform:translateX(-50%);font-size:9px;font-weight:700;color:#fff;background:var(--accent2);padding:1px 5px;border-radius:8px;white-space:nowrap;z-index:4;animation:blinkhoy 1s ease-in-out infinite}
/* Disponibilidad y asignación */
.availleg{font-size:11px;color:var(--muted);display:flex;gap:12px;flex-wrap:wrap;margin:2px 0 10px;align-items:center}
.availdot{display:inline-block;width:9px;height:9px;border-radius:50%;vertical-align:middle;margin-right:3px}
.availdot.ok{background:#22c55e}.availdot.busy{background:#f59e0b}.availdot.off{background:#ef4444}
.ejcard{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:14px;margin-bottom:12px}
.ejcard-h{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-bottom:10px;font-size:14px}
.asigwrap{display:flex;gap:20px;flex-wrap:wrap}
.asigcol{display:flex;flex-direction:column;gap:6px;min-width:200px}
.asigcol.grow{flex:1}
.asiglbl{font-size:11px;text-transform:uppercase;letter-spacing:.4px;color:var(--muted)}
.asiglbl small{text-transform:none;letter-spacing:0}
/* ============================================================
   ZONA · PERSONAL TÉCNICO
   13 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
.chipgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
.chip{display:flex;flex-direction:column;gap:6px;background:var(--panel);border:1px solid var(--line);border-radius:10px;padding:10px;cursor:pointer;position:relative;transition:background .15s,box-shadow .15s;min-height:82px;box-sizing:border-box}
.chip-stat{min-height:36px}
.chip.islider{opacity:1;border-style:solid}
.chip:hover{border-color:var(--accent)}
.chip.on{background:rgba(56,189,248,.18);border-color:var(--accent);box-shadow:0 0 0 1px var(--accent)}
.chip.islider{opacity:.92;cursor:default;border-style:dashed}
.chip-top{display:flex;align-items:center;gap:8px;width:100%}
.chipname{font-size:12px;font-weight:500}
.chip.on .chipname{color:var(--txt);font-weight:600}
.chipmark{margin-left:auto;color:var(--accent);font-weight:700}
.chiptag{margin-left:auto;font-size:9px;background:var(--accent2);color:#fff;padding:2px 6px;border-radius:10px}
.chip-stat{display:flex;flex-wrap:wrap;gap:4px}
.cbadge{font-size:10px;padding:2px 7px;border-radius:8px;font-weight:600}
.cbadge.ok{background:#14532d;color:#86efac}
.cbadge.off{background:#7f1d1d;color:#fca5a5}
.cbadge.prog{background:#b45309;color:#fff;animation:pulseprog 1.4s ease-in-out infinite}
/* Programado a futuro: informa sin alarmar (el naranja pulsante queda
   reservado para quien está en servicio hoy). */
.cbadge.prox{background:#1e3a8a;color:#bfdbfe}
/* Convenciones de color de la sección Personal Técnico */
.conv{display:flex;flex-wrap:wrap;align-items:center;gap:7px 16px;margin:0 0 12px;padding:9px 12px;background:var(--panel2);border:1px solid var(--line);border-radius:10px;font-size:11px;color:var(--muted)}
.conv-t{font-weight:700;color:var(--txt);font-size:10px;letter-spacing:.6px;text-transform:uppercase}
.conv-i{display:inline-flex;align-items:center;gap:6px}
/* Detalle de programación dentro de la casilla del personal técnico */
/* ============================================================
   ZONA · PERSONAL TÉCNICO
   6 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
.chip-det{display:block;font-size:10px;line-height:1.5;margin-top:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.chip-det.det-cur{color:#fdba74;font-weight:600}
.chip-det.det-prox{color:#93c5fd}
.chip-det.det-aus{color:#fca5a5}
.chip-det.det-mas{color:var(--muted);font-style:italic}
/* Ya cumplido hoy: se informa, pero no marca a la persona como ocupada */
.chip-det.det-hecho{color:#86efac;opacity:.7;text-decoration:none}
/* ---- Carga de parafiscales desde la ficha ---- */
.paraf-sub{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:8px;padding:8px 10px;
  background:var(--panel2);border:1px solid var(--line);border-radius:8px;font-size:11.5px}
.paraf-sub b{color:var(--txt);font-size:11.5px}
.paraf-sub select{min-height:0;padding:5px 8px;font-size:11.5px;width:auto}
.paraf-sub input[type=file]{font-size:11px;max-width:210px;padding:4px;min-height:0}
.paraf-sub .btn{padding:5px 11px;font-size:11.5px}
.paraf-msg{font-size:11px;color:var(--muted);flex:1 1 100%}
/* Aviso de datos no reales en el módulo de tiquetes. Va en ámbar y arriba
   de todo: las cifras se ven autoritativas y alguien podría presupuestar
   con ellas. */
.fake-warn{display:flex;flex-direction:column;gap:5px;margin:6px 0 12px;padding:11px 14px;
  background:rgba(245,158,11,.10);border:1px solid rgba(245,158,11,.45);border-left:4px solid var(--warn);
  border-radius:8px;font-size:12px;line-height:1.55;color:var(--txt)}
.fake-warn b{color:var(--warn)}
.fake-warn span{color:var(--muted)}
.fake-warn code{background:var(--panel2);padding:1px 5px;border-radius:4px;font-size:11px;color:var(--txt)}
.fake-warn .fw-vieja{color:#fca5a5;font-weight:600}
/* ---- Consecutivos de cotización ---- */
/* ============================================================
   ZONA · TABLAS
   16 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
.cs-disp{display:flex;align-items:center;gap:20px;flex-wrap:wrap;padding:12px 14px;
  background:var(--panel2);border:1px solid var(--line);border-radius:10px}
.cs-next{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding-right:20px;border-right:1px solid var(--line)}
/* Dos renglones, en mayúsculas, justificado a la izquierda */
.cs-next-l{font-size:10px;text-transform:uppercase;letter-spacing:.6px;color:var(--muted);
  font-weight:700;line-height:1.3;text-align:left;flex:0 0 auto}
.cs-next-n{font-size:26px;font-weight:800;color:var(--accent);letter-spacing:.5px;font-family:'Segoe UI',monospace}
.cs-kpis{display:flex;gap:16px;flex-wrap:wrap}
.cs-k{display:flex;flex-direction:column;line-height:1.15}
.cs-k b{font-size:18px}
.cs-k small{color:var(--muted);font-size:9.5px;text-transform:uppercase;letter-spacing:.3px}
.cs-k-ok b{color:var(--ok)}
.cs-montos{display:flex;gap:16px;flex-wrap:wrap;font-size:11.5px;color:var(--muted);margin-left:auto;align-items:center}
.cs-montos b{color:var(--txt)}
.cs-ok{color:var(--ok)!important}
.cs-vence{color:var(--warn);font-weight:600}
.cs-cod{font-family:'Segoe UI',monospace;letter-spacing:.5px;color:var(--accent);white-space:nowrap}
.cs-cod-link{cursor:pointer}
.cs-cod-link:hover{text-decoration:underline;filter:brightness(1.15)}
.csv-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:4px 0 12px;padding-bottom:10px;border-bottom:1px solid var(--line)}
.csv-list{display:flex;flex-direction:column;gap:2px}
.csv-row{display:grid;grid-template-columns:160px 1fr;gap:12px;padding:7px 2px;border-bottom:1px dashed var(--line);align-items:start}
.csv-l{font-size:11px;text-transform:uppercase;letter-spacing:.4px;color:var(--muted);font-weight:700}
.csv-v{font-size:13px;word-break:break-word;white-space:pre-wrap}
@media(max-width:520px){.csv-row{grid-template-columns:1fr;gap:2px}}
/* ---- Insignias de estado ----
   Siguen el ciclo de vida de la propuesta y por eso van en ese orden en
   la leyenda, en el filtro y en el formulario. Ancho fijo para que la
   columna Estado quede alineada de arriba abajo.
     ámbar   apartado, aún no sale
     azul    ya salió al cliente
     verde   cerrada a favor
     rojo    cerrada en contra
     morado  fuera de juego: el número queda quemado */
/* ============================================================
   ZONA · TABLAS
   6 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
.cs-b{font-size:9.5px;padding:3px 0;border-radius:8px;font-weight:700;white-space:nowrap;
  display:inline-block;min-width:74px;text-align:center;letter-spacing:.2px}
.cs-res{background:#78350f;color:#fde68a}
.cs-env{background:#1e3a8a;color:#bfdbfe}
.cs-ace{background:#14532d;color:#86efac}
.cs-rec{background:#7f1d1d;color:#fca5a5}
.cs-anu{background:#4c1d95;color:#ddd6fe}
/* En la leyenda no se necesita el ancho fijo */
.conv .cs-b{min-width:0;padding:3px 9px}
/* Selector de estado dentro de la fila: se ve como una insignia más,
   pero se puede cambiar. La flecha nativa se deja visible para que se
   note que es editable. */
select.cs-sel{border:none;cursor:pointer;min-height:0;height:auto;width:auto;
  padding:3px 4px 3px 8px;font-size:9.5px;font-weight:700;letter-spacing:.2px;
  min-width:88px;-webkit-appearance:none;appearance:none;
  background-image:linear-gradient(45deg,transparent 50%,currentColor 50%),
                   linear-gradient(135deg,currentColor 50%,transparent 50%);
  background-position:calc(100% - 11px) 52%,calc(100% - 7px) 52%;
  background-size:4px 4px,4px 4px;background-repeat:no-repeat;padding-right:20px}
select.cs-sel:focus{outline:1px solid var(--accent);outline-offset:1px}
select.cs-sel:disabled{opacity:.6;cursor:wait}
select.cs-sel option{background:var(--panel);color:var(--txt);font-weight:600}
/* ---- Registro: filas de rejilla, no tabla ----
   Cliente y objeto suelen ser textos largos. En una tabla cada fila crecía
   distinto y la lista quedaba despareja. Aquí el texto se recorta a dos
   líneas —el contenido completo queda en el tooltip— para que todas las
   filas midan igual, y al angostar la ventana se apilan solas. */
/* ============================================================
   ZONA · TABLAS
   31 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
.cs-lista{display:flex;flex-direction:column}
.cs-row{display:grid;grid-template-columns:106px minmax(0,1.35fr) minmax(0,1.75fr) 104px 124px 148px 78px;
  gap:10px;align-items:center;padding:9px 6px;border-bottom:1px solid var(--line);font-size:12px}
.cs-row:last-child{border-bottom:none}
.cs-row:hover:not(.cs-head){background:var(--panel2)}
.cs-head{border-bottom:1px solid var(--accent);padding-bottom:7px;
  position:sticky;top:0;background:var(--panel);z-index:2}
/* Todos los títulos de columna con el mismo tamaño y peso: la celda de
   Reserva llevaba clase .cs-num y heredaba el tamaño de los datos (11,5 px),
   por lo que su encabezado se veía más grande que los demás. */
.cs-head>span{font-size:9.5px!important;text-transform:uppercase;letter-spacing:.4px;
  color:var(--muted);font-weight:700;line-height:1.3}
/* Recorte a dos líneas: la fila nunca crece más que eso */
.cs-c-txt{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
  line-height:1.35;min-width:0;word-break:break-word}
.cs-c-por{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--muted);font-size:11.5px}
.cs-c-cod{min-width:0}
.cs-row .cs-num{text-align:right;white-space:nowrap;font-size:11.5px}
.cs-c-est{display:flex;gap:5px;align-items:center;flex-wrap:wrap}
.cs-c-acc{text-align:right}
.cs-row .btn{padding:3px 9px;font-size:10.5px;white-space:nowrap}
/* Etiqueta del campo: oculta en escritorio, aparece al apilar */
.cs-lbl{display:none;font-style:normal;color:var(--muted);font-size:9px;text-transform:uppercase;
  letter-spacing:.4px;margin-right:5px}

@media(max-width:1180px){
  /* "Tomado por" es lo primero que sobra: el objeto de la propuesta manda */
  .cs-row{grid-template-columns:100px minmax(0,1.3fr) minmax(0,1.7fr) 100px 124px 74px;gap:9px}
  .cs-row>.cs-c-por,.cs-head>span:nth-child(6){display:none}
}
@media(max-width:960px){
  .cs-row{grid-template-columns:96px minmax(0,1.3fr) minmax(0,1.8fr) 122px 72px}
  .cs-row>.cs-num,.cs-head>span:nth-child(4){display:none}   /* fecha de reserva */
  .cs-montos{margin-left:0;width:100%}
  .cs-next{border-right:none;padding-right:0}
}
@media(max-width:860px){
  /* Cada consecutivo pasa a bloque: código y estado arriba, el resto debajo */
  .cs-head{display:none}
  .cs-row{grid-template-columns:minmax(0,1fr) auto;gap:5px 10px;padding:12px 6px;align-items:start}
  .cs-row>span{display:block!important}
  .cs-c-cod{grid-column:1/2}
  .cs-c-est{grid-column:2/3;grid-row:1/2;justify-content:flex-end}
  .cs-c-txt{grid-column:1/3;-webkit-line-clamp:3}
  .cs-row .cs-num{grid-column:1/3;text-align:left}
  .cs-c-por{grid-column:1/3;white-space:normal}
  .cs-c-acc{grid-column:1/3;text-align:left;margin-top:3px}
  .cs-lbl{display:inline}
  .cs-cod{font-size:14px}
}
/* ---- Interruptor del módulo de ayuda (Editar perfil) ---- */
.pf-sw{display:flex;align-items:flex-start;gap:10px;padding:11px 13px;cursor:pointer;
  background:var(--panel2);border:1px solid var(--line);border-radius:9px}
.pf-sw:hover{border-color:var(--accent)}
.pf-sw input{width:auto;min-height:0;margin:2px 0 0;flex:0 0 auto;cursor:pointer}
.pf-sw span{display:block;min-width:0}
.pf-sw b{display:block;font-size:12.5px;font-weight:600;margin-bottom:3px}
.pf-sw small{display:block;color:var(--muted);font-size:11px;line-height:1.5}
/* fin [SEC-03] */
/* ============================================================
   SELECTOR DE HORA EN 12 h (a.m./p.m.)   [SEC-04]

   POR QUÉ SE SALÍA DE LA CASILLA
     Las tres listas tenían ancho FIJO y prohibido encogerse:
     58 + 62 + 78 px, más las separaciones, son unos 215 px que no
     caben en la casilla de ENTRADA del reporte. Como no podían
     estrechar, se desbordaban por encima del borde de la tabla.

   CÓMO QUEDA
     Ancho proporcional en vez de fijo: las tres se reparten el sitio
     que haya, sea el que sea. En una casilla estrecha se estrechan; en
     un formulario ancho se ensanchan. Nunca se salen.

     La lista de a.m./p.m. recibe algo más de parte porque su texto es
     más largo que un número de dos cifras.
   ============================================================ */
/* ============================================================
   ZONA · BOTONES Y CAMPOS
   7 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
.h12{display:inline-flex;align-items:center;gap:4px;width:100%;max-width:100%;
  min-width:0;box-sizing:border-box}
.h12 select{padding:8px 2px;text-align:center;font-size:13px;
  min-width:0;width:auto;flex:1 1 0;box-sizing:border-box}
.h12 select.h12-h{flex-grow:1}
.h12 select.h12-m{flex-grow:1}
.h12 select.h12-p{flex-grow:1.45}
.h12 .h12-s{color:var(--muted);font-weight:700;flex:0 0 auto}
@media(max-width:640px){
  .h12 select{font-size:16px;padding:8px 1px}   /* evita el zoom de iOS al enfocar */
}

/* ---- Dentro de la hoja del reporte ----
   La casilla de ENTRADA y la de SALIDA son estrechas y comparten fila.
   Aquí el selector va compacto: menos relleno, letra algo menor y los
   dos puntos reducidos a lo justo. */
#rep-sheet .h12{gap:2px}
#rep-sheet .h12 select{padding:3px 0;font-size:11.5px;line-height:1.2}
#rep-sheet .h12 .h12-s{margin:0;font-size:11px}
/* En el teléfono la hoja se estrecha todavía más. */
@media(max-width:640px){
  #rep-sheet:not(.rep-pdf) .h12 select{font-size:16px;padding:5px 0}
}
/* ---- Contratos de mantenimiento activos ----
   Tabla ancha: se reduce la letra y se fijan anchos por columna para que
   cada fila quepa en UN solo renglón. Las fechas y los badges no se parten;
   si la pantalla es angosta, la tabla se desplaza en horizontal en vez de
   quebrar el texto. */
/* Sin barra de desplazamiento: la tabla ocupa el 100% del ancho disponible.
   Los tres campos de texto largo (N° contrato, Cliente y Detalle) se
   reparten en las líneas que necesiten; el resto —fechas, cifras, badges
   y botones— se mantiene en un solo renglón porque partirlos sí estorba. */
/* ============================================================
   ZONA · TABLAS
   23 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
.ca-wrap{width:100%}
.ca-tabla{font-size:11.5px;width:100%;table-layout:fixed;border-collapse:collapse}
.ca-tabla th,.ca-tabla td{padding:7px 6px;white-space:nowrap;vertical-align:middle}
.ca-tabla thead th{font-size:9.5px;letter-spacing:.2px;line-height:1.25;white-space:normal}
/* Anchos en porcentaje: se adaptan a cualquier monitor */
.ca-tabla col.c-num{width:3%}
.ca-tabla col.c-ctr{width:14%}
.ca-tabla col.c-cli{width:13%}
.ca-tabla col.c-det{width:12%}
.ca-tabla col.c-fec{width:7.5%}
.ca-tabla col.c-dur{width:7.5%}
.ca-tabla col.c-p{width:3.5%}
.ca-tabla col.c-per{width:9.5%}
.ca-tabla col.c-dem{width:5.5%}
.ca-tabla col.c-est{width:6%}
/* Columna de documentos: dos iconos, no necesita más. El ancho sale de
   «Detalle del servicio», que es la que mejor aguanta perder sitio. */
.ca-tabla col.c-doc{width:4%}
.ca-tabla col.c-acc{width:6.5%}
/* Las tres columnas de texto sí se envuelven, tantas líneas como haga falta */
.ca-tabla td:nth-child(2),.ca-tabla td:nth-child(3),.ca-tabla td:nth-child(4){
  white-space:normal;word-break:break-word;line-height:1.35}
.ca-tabla td:nth-child(3){font-weight:600}
/* Badges, cifras y botones nunca se parten */
.ca-tabla .badge,.ca-tabla .pill{white-space:nowrap;font-size:9px;padding:2px 5px;display:inline-block;line-height:1.4}
.ca-tabla td .btn{padding:3px 7px;font-size:10px;white-space:nowrap}
.ca-tabla td b{font-weight:600}
/* En pantallas pequeñas sí se permite desplazar: 13 columnas no caben */
@media(max-width:820px){
  .ca-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
  .ca-tabla{min-width:900px}
}

/* ---- Dona animada del dashboard ----
   El anillo gira; el número de cada porción contragira para no quedar
   de cabeza. Ambas animaciones duran lo mismo, así se cancelan. */
@keyframes dgira{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}
@keyframes dgiraInv{from{transform:rotate(0deg)}to{transform:rotate(-360deg)}}
@keyframes dlive{0%,100%{opacity:.25;transform:scale(.85)}50%{opacity:1;transform:scale(1)}}
/* La tarjeta completa es clicable y lleva a su sección */
.donut-card.donut-link{cursor:pointer;border-radius:12px;transition:background .15s}
.donut-ir{margin-top:10px;font-size:11.5px;color:var(--accent);font-weight:600;text-align:right}
/* En pantalla táctil el resaltado del cursor se queda pegado tras tocar.
   Se reserva para equipos con mouse. */
@media(hover:hover) and (pointer:fine){
  .donut-card.donut-link:hover{background:var(--panel2)}
  .donut-card.donut-link:hover .donut-ir{text-decoration:underline}
}
/* La sombra va en el contenedor QUIETO, no en el anillo que gira. Si va en
   el anillo, el teléfono tiene que volver a dibujarla en cada cuadro y el
   giro se ve a tirones o se detiene. Visualmente es idéntico. */
.donut{position:relative;width:170px;height:170px;flex:0 0 auto;border-radius:50%;box-shadow:0 10px 30px rgba(0,0,0,.4)}
.donut-ring{position:absolute;inset:0;border-radius:50%;will-change:transform;backface-visibility:hidden}
.donut-hole{position:absolute;inset:28px;background:var(--panel);border-radius:50%;
  display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:2}
.donut-n{font-size:38px;font-weight:800;line-height:1}
.donut-c{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.5px;margin-top:2px}
.donut-live{width:6px;height:6px;border-radius:50%;background:var(--ok);margin-top:5px;
  animation:dlive 2s ease-in-out infinite}
.donut-lbl{position:absolute;left:50%;top:50%;width:0;height:0}
/* Caja de 44×22 centrada exactamente sobre el punto que orbita:
   media caja hacia la izquierda y media hacia arriba. */
.donut-pct{position:absolute;left:-22px;top:-11px;width:44px;height:22px;
  display:flex;align-items:center;justify-content:center}
/* Sin will-change aquí: son hasta siete números por dona y tres donas en
   pantalla. Pedir una capa gráfica para cada uno agota la memoria de vídeo
   del teléfono y Safari termina dejando de animarlas todas. */
.donut-txt{display:inline-block;font-size:11.5px;font-weight:800;color:#fff;line-height:1;
  text-shadow:0 1px 3px rgba(0,0,0,.85),0 0 2px rgba(0,0,0,.7)}
/* Antes, si el equipo tenía activado «Reducir movimiento» (Ajustes →
   Accesibilidad, muy común de tener prendido en iPhone y iPad sin
   saberlo), la dona quedaba completamente quieta. El giro es lento
   —una vuelta cada veinte segundos— y no molesta a nadie, así que se
   deja andando siempre. Lo que sí se sigue respetando es el parpadeo
   del punto verde, que ese sí es un destello rápido. */
@media(prefers-reduced-motion:reduce){
  .donut-live{animation:none!important}
}
/* ---- Estadística de labores ejecutadas durante el mes ---- */
.cargatabs{display:flex;gap:4px;background:var(--panel2);padding:4px;border-radius:10px;margin:12px 0;width:fit-content}
.cargatabs button{background:none;border:none;color:var(--muted);padding:6px 14px;border-radius:7px;font-size:12px;cursor:pointer;font-weight:600}
.cargatabs button.on{background:var(--panel);color:var(--txt);box-shadow:0 1px 4px rgba(0,0,0,.25)}
/* ============================================================
   ZONA · PERSONAL TÉCNICO
   58 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
.cg-leg{display:flex;flex-wrap:wrap;gap:8px 18px;align-items:center;font-size:11px;color:var(--muted);margin-bottom:10px}
.cg-leg i{display:inline-block;width:9px;height:9px;border-radius:2px;margin-right:5px;vertical-align:middle}
.cg-prom{margin-left:auto;color:var(--txt)}
.cg-lista{display:flex;flex-direction:column}
/* Tres bloques: identidad · barra · cifras. Menos columnas rígidas = se
   reacomoda solo al angostar la ventana, sin cortar nombres. */
.cg-fila{display:grid;grid-template-columns:236px minmax(0,1fr) 268px;gap:12px;align-items:center;
  padding:8px 4px;border-bottom:1px solid var(--line);font-size:12px}
.cg-fila:last-child{border-bottom:none}
/* ---- Punto de presencia sobre la foto ----
   Verde: la persona esta usando el CRM ahora. Gris hueco: no.

   QUE CUIDAR
     El estado NO se transmite solo por el color. Cada punto lleva su
     `title` y un texto oculto para lector de pantalla que dice «En
     linea» o «Desconectado». Es el criterio 1.4.1 de WCAG, y ademas
     resuelve el caso de quien no distingue verde de gris.

     El anillo del color del panel separa el punto de la foto: sin el,
     sobre una foto clara el verde se pierde. */
.av-pres{position:relative;display:inline-flex;flex:0 0 auto;line-height:0}
.av-punto{position:absolute;right:-1px;bottom:-1px;width:11px;height:11px;border-radius:50%;
  background:transparent;border:2px solid var(--panel);box-shadow:inset 0 0 0 2px var(--muted);
  transition:box-shadow .2s ease}
.av-pres.on-linea .av-punto{background:#15803d;box-shadow:inset 0 0 0 2px #15803d}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}
/* La fila se puede pulsar para ver el detalle del mes. Se avisa con el
   puntero y con un realce al pasar por encima: una fila que reacciona
   al clic sin decirlo antes no la pulsa nadie. */
.cg-clic{cursor:pointer;border-radius:8px;transition:background .15s ease}
.cg-clic:hover{background:var(--panel2)}
.cg-clic:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.cg-datos{display:flex;align-items:center;gap:14px;justify-content:flex-end;min-width:0}
.cg-nom{display:flex;align-items:center;gap:8px;min-width:0}
.cg-nom .avatar{flex:0 0 auto}
/* Posición en el ranking de labores del mes. Sin color de énfasis: el azul
   en los tres primeros se leía como distinción, cuando lo que marca es
   mayor carga. El desbalance ya lo comunican la barra y la señal de
   "sobrecargado". */
.cg-pos{flex:0 0 auto;width:20px;text-align:center;font-size:11px;font-weight:700;color:var(--muted)}
.cg-nom-t{min-width:0;line-height:1.28}
/* El nombre puede ocupar dos líneas antes que cortarse: un "John Waldo
   Porr…" no identifica a nadie. */
.cg-nom b{display:block;font-size:12.5px;white-space:normal;word-break:break-word}
.cg-nom small{display:block;color:var(--muted);font-size:9.5px;text-transform:uppercase;letter-spacing:.3px;
  white-space:normal;word-break:break-word}
.cg-bar{display:flex;height:20px;border-radius:5px;overflow:hidden;background:var(--panel2);min-width:0}
.cg-s{display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:700;color:#04202e;
  font-style:normal;transition:width .3s ease;min-width:3px}
.cg-m{background:#0ea5e9}
.cg-a{background:#7c3aed;color:#f3e8ff;padding:0}
/* ---- Cómo salió cada actividad, DENTRO de la barra morada ----
   La barra de actividades deja de ser un bloque plano y se reparte
   según el resultado. El morado se conserva para lo que todavía no se
   ha reportado, así que:

     · una barra morada entera  = nadie ha calificado nada (lo de antes)
     · una barra verde entera   = todo cumplido
     · lo intermedio se ve como lo que es, sin leer un número

   Los segmentos llevan `title` con su cifra y el detalle va escrito al
   lado en cg-datos: la información no depende del color, que es el
   criterio 1.4.1 de WCAG. */
.cg-r{display:flex;align-items:center;justify-content:center;font-style:normal;
  font-size:10px;font-weight:700;min-width:0;transition:width .3s ease}
.cg-rc{background:#15803d;color:#dcfce7}   /* cumplida     */
.cg-rp{background:#b45309;color:#fef3c7}   /* parcial      */
.cg-rn{background:#b91c1c;color:#fee2e2}   /* no realizada */
.cg-rs{background:transparent;color:#f3e8ff} /* sin reportar: deja ver el morado */
/* Programado: aun no ha ocurrido. Mas claro que el morado de fondo,
   para distinguirlo de «ya paso y nadie dijo nada». */
.cg-rg{background:rgba(255,255,255,.18);color:#f3e8ff}
/* Felicitación cuando todo lo asignado quedó cumplido. */
.cg-100{display:inline-flex;align-items:center;gap:4px;font-size:10.5px;font-weight:700;
  color:#15803d;background:rgba(21,128,61,.14);border-radius:999px;padding:2px 8px;white-space:nowrap}
.cg-p{background:#f59e0b;color:#451a03}
/* el texto era casi negro sobre rojo: 3,34:1. En blanco da 4,83:1. */
.cg-u{background:#dc2626;color:#fff}
.cg-num{text-align:center;line-height:1.15}
.cg-num b{display:block;font-size:14px}
.cg-num small{color:var(--muted);font-size:9.5px;text-transform:uppercase;letter-spacing:.3px}
.cg-señal{font-size:10px;font-weight:600;padding:3px 9px;border-radius:8px;text-align:center;white-space:nowrap}
/* Los tres colores de la etiqueta que se retiro -naranja, azul y
   verde- se fueron con ella: el color tambien calificaba a la persona.
   Queda uno solo, neutro, para la cifra. Las tres clases se conservan
   vacias por si alguna quedara referenciada en otro sitio: asi no se
   rompe nada, pero tampoco pintan nada.
   Ver el bloque de _renderCargaMes() para el porque. */
.cg-alto{}
.cg-bajo{}
.cg-ok{}
.cg-neutro{background:var(--panel2);color:var(--muted);font-variant-numeric:tabular-nums}
.cg-libres{margin-top:12px;padding-top:10px;border-top:1px dashed var(--line);font-size:11.5px;color:var(--muted)}
.cg-libre{display:inline-flex;align-items:center;gap:5px;margin:3px 10px 0 0}
.cg-libre .swatch{width:8px;height:8px;border-radius:50%;display:inline-block}
/* Mapa de calor de tendencia */
.cg-heat{display:flex;flex-direction:column;gap:3px}
.cg-hrow{display:grid;grid-template-columns:210px repeat(6,1fr) 62px;gap:3px;align-items:center}
.cg-hhead span{font-size:10px;color:var(--muted);text-align:center;text-transform:uppercase;letter-spacing:.4px;padding-bottom:2px}
.cg-hhead small{display:block;font-size:9px;opacity:.7}
.cg-hnom{display:flex;align-items:center;gap:7px;font-size:12px;min-width:0}
.cg-hnom .avatar{flex:0 0 auto}
.cg-hnom>span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cg-cel{text-align:center;padding:7px 0;border-radius:5px;font-size:12px;font-weight:600;background:var(--panel2);color:var(--txt)}
.cg-tot{background:none;color:var(--accent);font-weight:700}
/* ---- Cómo se reacomoda al angostar la ventana ----
   Antes se mantenían las cinco columnas y el nombre se cortaba
   ("John Waldo Porr…"), mientras la barra se salía del recuadro.
   Ahora se van soltando columnas por orden de importancia y, cuando ya
   no caben, cada persona pasa a un bloque de dos filas: identidad
   arriba, barra completa y cifras abajo. El nombre nunca se trunca. */
@media(max-width:1180px){
  .cg-fila{grid-template-columns:210px minmax(0,1fr) 240px;gap:10px}
  .cg-datos{gap:11px}
}
@media(max-width:1000px){
  /* "Clientes" es lo primero que sobra: el nombre y la barra mandan */
  .cg-fila{grid-template-columns:196px minmax(0,1fr) 150px}
  .cg-datos .cg-cli{display:none}
  .cg-hrow{grid-template-columns:150px repeat(6,1fr) 48px}
}
@media(max-width:860px){
  /* Dos renglones por persona: identidad arriba; barra y cifras abajo.
     Aquí el nombre ya puede envolver en vez de cortarse. */
  .cg-fila{grid-template-columns:minmax(0,1fr);gap:7px;padding:11px 4px}
  .cg-datos{justify-content:flex-start;flex-wrap:wrap}
  .cg-datos .cg-cli{display:flex}
  .cg-nom b,.cg-nom small{white-space:normal}
  .cg-num{text-align:left}
  .cg-num b{display:inline;font-size:13px;margin-right:4px}
  .cg-num small{display:inline;font-size:9.5px}
  .cg-señal{margin-left:auto}
  .cg-leg{gap:6px 12px}
  .cg-prom{margin-left:0;width:100%}
}
@media(max-width:640px){
  .cg-heat{overflow-x:auto}
  .cg-hrow{grid-template-columns:130px repeat(6,44px) 44px;min-width:460px}
  .cg-fila .cg-nom .avatar,.cg-fila .cg-nom .avatar-w{width:22px!important;height:22px!important}
  .cg-libres{font-size:11px}
  .cg-señal{margin-left:0}
}
/* ---- Dona de labores del mes en la ficha del personal técnico ---- */
.fk-wrap{display:flex;gap:20px;align-items:center;flex-wrap:wrap;background:var(--panel2);
  border:1px solid var(--line);border-radius:10px;padding:14px 16px;margin-bottom:6px}
.fk-dona{flex:0 0 auto;line-height:0}
.fk-info{flex:1;min-width:230px}
.fk-mes{font-size:11px;text-transform:uppercase;letter-spacing:.6px;color:var(--muted);
  font-weight:700;margin-bottom:8px}
.fk-legs{display:flex;flex-direction:column;gap:5px;margin-bottom:11px}
.fk-leg{display:flex;align-items:center;gap:8px;font-size:12.5px}
.fk-leg i{flex:0 0 auto;width:10px;height:10px;border-radius:3px;display:inline-block}
.fk-leg .fk-l{flex:1;color:var(--muted)}
.fk-leg b{font-size:13px;min-width:20px;text-align:right}
.fk-leg .fk-p{color:var(--muted);font-size:11px;min-width:34px;text-align:right}
.fk-nums{display:flex;gap:16px;flex-wrap:wrap;padding-top:10px;border-top:1px solid var(--line)}
.fk-nums span{display:flex;flex-direction:column;line-height:1.2}
.fk-nums b{font-size:16px}
.fk-nums small{color:var(--muted);font-size:9.5px;text-transform:uppercase;letter-spacing:.3px}
@media(max-width:560px){
  .fk-wrap{justify-content:center;text-align:center}
  .fk-info{min-width:0}
  .fk-nums{justify-content:center}
}
/* Navegador de mes de las casillas de personal técnico */
.mesnav{display:inline-flex;align-items:center;gap:4px;vertical-align:middle;margin-left:4px}
.mesnav .btn{padding:2px 8px;font-size:11px;min-height:0;line-height:1.5}
.mesnav .btn[disabled]{opacity:.35;cursor:not-allowed}
.mesnav-lbl{font-size:11px;font-weight:600;color:var(--txt);text-transform:capitalize;min-width:104px;text-align:center}
/* ---- Tiquetes por gestionar: un bloque por viaje, un renglón por pasajero ---- */
.tiq-viaje{border:1px solid var(--line);border-radius:10px;margin-bottom:12px;overflow:hidden;background:var(--panel)}
.tiq-h{display:grid;grid-template-columns:1fr 1fr 132px 176px;gap:10px;align-items:center;
  padding:9px 12px;background:var(--panel2);border-bottom:1px solid var(--line);font-size:12.5px}
.tiq-ruta b,.tiq-cli{display:block;font-size:13px}
.tiq-h small{display:block;color:var(--muted);font-size:11px;font-weight:400;margin-top:1px}
.pax-row{display:grid;grid-template-columns:1.4fr .85fr 1.1fr .85fr 1.35fr;gap:10px;align-items:center;
  padding:9px 12px;border-bottom:1px solid var(--line);font-size:12.5px}
.pax-row:last-child{border-bottom:none}
.pax-n{display:flex;align-items:center;gap:7px;flex-wrap:wrap;min-width:0}
.pax-n .swatch{flex:0 0 auto;width:10px;height:10px;border-radius:50%;display:inline-block}
.pax-n small{color:var(--muted);font-size:10.5px;text-transform:uppercase;letter-spacing:.3px;width:100%;padding-left:17px}
.pax-d{font-size:12.5px;min-width:0}
.pax-d small{display:block;color:var(--muted);font-size:10px;text-transform:uppercase;letter-spacing:.4px}
.pax-mail{overflow:hidden}
.pax-mail a{color:var(--accent);text-decoration:none;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pax-mail a:hover{text-decoration:underline}
@media(max-width:900px){
  .tiq-h{grid-template-columns:1fr 1fr;row-gap:6px}
  .tiq-h>span:last-child{grid-column:1/-1;justify-content:flex-start!important}
  .pax-row{grid-template-columns:1fr 1fr}
}
@media(max-width:560px){
  .tiq-h,.pax-row{grid-template-columns:1fr}
}
@keyframes pulseprog{0%,100%{box-shadow:0 0 0 0 rgba(245,158,11,.65)}50%{box-shadow:0 0 0 5px rgba(245,158,11,0)}}
.chip.av-off{border-color:#7f1d1d}
@media(max-width:640px){.chipgrid{grid-template-columns:repeat(2,1fr)}}
/* ===== Responsive · multidispositivo (celular, tablet, TV) ===== */
.menu-btn{display:none;background:var(--panel2);border:1px solid var(--line);color:var(--txt);font-size:20px;border-radius:8px;padding:3px 11px;cursor:pointer;line-height:1.2}
#side-backdrop{display:none;position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:98}
#side-backdrop.show{display:block}
@media(max-width:820px){
  .side{position:fixed;left:0;top:0;z-index:99;transform:translateX(-100%);transition:transform .25s ease;box-shadow:0 0 40px rgba(0,0,0,.6)}
  .side.side-open{transform:translateX(0)}
  .menu-btn{display:inline-block}
  .main{padding:16px 16px 44px;max-width:100%}
  .topbar{flex-wrap:wrap;gap:10px}
  .kpis{grid-template-columns:repeat(4,1fr);gap:9px}   /* se mantiene en una fila */
  .kpi{padding:11px 11px;gap:9px}
  .kpi .n{font-size:25px}
  .kpi .l{font-size:10px;letter-spacing:.2px}
  .grid2{grid-template-columns:1fr}
  .cform{grid-template-columns:1fr}
  .yeargrid{grid-template-columns:repeat(2,1fr)}
  .asigwrap{flex-direction:column;gap:12px}
  .chipgrid{grid-template-columns:repeat(2,1fr)}
  .card table{display:block;overflow-x:auto;white-space:nowrap;-webkit-overflow-scrolling:touch}
  #cal-body,#ej-timeline{overflow-x:auto;-webkit-overflow-scrolling:touch}
  .weekwrap{min-width:640px}
  .mgrid.big .mdays{min-width:520px}
  .gantt{min-width:560px}
  .login-left{padding:34px 26px}
}
@media(max-width:460px){
  /* Único caso en que se parte: en un celular, cuatro botones en fila
     dejarían el texto ilegible. */
  .kpis{grid-template-columns:repeat(2,1fr)}
  .chipgrid{grid-template-columns:1fr}
  .yeargrid{grid-template-columns:1fr}
  .clock-time{font-size:14px}
  .vsearch,.spec-toolbar{flex-direction:column;align-items:stretch}
}
.warnmsg{font-size:11px;color:#fca5a5;margin-top:2px}
.warnmsg.amber{color:#fcd34d}
/* Alguien nuevo esperando. No es un fallo ni un vencimiento —los dos
   avisos de arriba sí lo son—, así que no se pinta de rojo ni de
   ámbar: va en el color de acento de la casa, con una barra a la
   izquierda para que se distinga de una línea de texto cualquiera. */
.warnmsg.nuevo{color:var(--accent);font-size:11.5px;font-weight:600;
  border-left:3px solid var(--accent);padding-left:9px;line-height:1.5}
.cbadge.nuevo{background:var(--accent);color:#14181C}
/* Dashboard tiquetes */
.vleg{display:flex;gap:16px;flex-wrap:wrap;font-size:12px;color:var(--muted);margin:8px 0 4px}
.buylinks{display:flex;gap:8px;flex-wrap:wrap}
.blink{display:inline-block;padding:7px 12px;border-radius:8px;background:var(--panel2);border:1px solid var(--line);color:var(--accent);font-size:12px;text-decoration:none}
.blink:hover{border-color:var(--accent);background:var(--panel)}
td .blink{padding:4px 9px;margin-right:5px;font-size:11px}
.vsearch{display:flex;gap:10px;flex-wrap:wrap;align-items:flex-end;margin:12px 0;background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:12px}
.vsearch label{display:flex;flex-direction:column;font-size:11px;color:var(--muted);gap:4px}
.vsearch select,.vsearch input{background:var(--panel);border:1px solid var(--line);color:var(--txt);padding:8px;border-radius:8px;font-size:13px}
/* ============================================================
   PESTAÑAS DE LA FICHA DE PERSONAL TÉCNICO
   La ficha pedía veintitantos datos en una sola columna larguísima:
   para llegar a los cursos había que pasar por la EPS, y quien solo
   venía a cargar un parafiscal tenía que recorrer todo el formulario.
   Tres pestañas, tres asuntos: quién es, su salud y sus documentos.
   La navegación no cambia lo que se guarda: los campos siguen siendo
   los mismos y «Guardar» guarda las tres pestañas a la vez, estén o no
   a la vista. Ocultar no es descartar.
   ============================================================ */
/* ============================================================
   CARNET VIRTUAL
   Medidas de credencial real (85,6 × 54 mm en horizontal, escaladas a
   pantalla) para que al imprimirlo salga del tamaño de una tarjeta y
   quepa en un portacarné. Los colores van FIJOS, no con las variables
   del tema: el carnet se imprime y se exporta a PDF, y en papel el
   fondo oscuro del CRM sale como una mancha de tinta.
   ============================================================ */
.carnet{width:420px;max-width:100%;margin:14px auto;background:#fff;color:#111827;
  border-radius:14px;overflow:hidden;box-shadow:0 10px 28px rgba(0,0,0,.35);font-family:inherit}
.carnet-top{background:#0f172a;color:#fff;padding:12px 16px;display:flex;align-items:center;gap:10px}
.carnet-top img{height:30px;width:auto}
.carnet-top .ct-tx{font-size:11px;letter-spacing:1.6px;text-transform:uppercase;opacity:.9;line-height:1.3}
.carnet-cuerpo{display:flex;gap:14px;padding:16px}
.carnet-foto{width:96px;height:96px;border-radius:10px;object-fit:cover;flex:0 0 auto;
  background:#e5e7eb;border:1px solid #d1d5db}
.carnet-id{min-width:0;flex:1}
.carnet-nom{font-size:17px;font-weight:800;line-height:1.2;color:#0f172a;word-break:break-word}
.carnet-cargo{font-size:12.5px;font-weight:600;color:#334155;margin-top:2px}
.carnet-ced{font-size:11.5px;color:#64748b;margin-top:5px}
.carnet-datos{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:#e5e7eb;border-top:1px solid #e5e7eb}
.carnet-d{background:#fff;padding:9px 14px}
.carnet-d span{display:block;font-size:9.5px;letter-spacing:.7px;text-transform:uppercase;color:#64748b;font-weight:700}
.carnet-d b{font-size:12.5px;color:#0f172a;font-weight:700;word-break:break-word}
.carnet-d.falta b{color:#b91c1c}
/* El RH ocupa toda la fila y va grande: es lo que se busca de afán. */
.carnet-rh{grid-column:1/-1;background:#fff;padding:9px 14px;display:flex;align-items:center;gap:12px}
.carnet-rh span{font-size:9.5px;letter-spacing:.7px;text-transform:uppercase;color:#64748b;font-weight:700}
.carnet-rh b{font-size:22px;font-weight:800;color:#b91c1c;line-height:1}
.carnet-rh.falta b{font-size:13px}
/* El QR va al pie, a la derecha, con su rotulo al lado: sin el rotulo
   nadie sabe que hacer con un cuadro negro. Fondo blanco siempre,
   tambien en tema oscuro, porque un QR sobre fondo oscuro no lo lee
   ningun telefono. */
.carnet-qr{display:flex;align-items:center;gap:10px;padding:10px 14px 0;background:#fff}
.carnet-qr svg{flex:0 0 auto;display:block;background:#fff}
/* El hueco reserva el sitio del código mientras se pide al servidor:
   sin altura fija, la tarjeta daba un salto al llegar la respuesta y
   se veía como un parpadeo. */
.carnet-qr-hueco{flex:0 0 auto;width:82px;min-height:82px;display:flex;
  align-items:center;justify-content:center;text-align:center;line-height:1.3}
.carnet-qr span{font-size:9px;color:#64748b;line-height:1.35;letter-spacing:.2px}
/* La dirección, en letra pequeña y monoespaciada para poder leerla
   carácter a carácter cuando algo no cuadra. Se parte en varias líneas
   antes que desbordar la tarjeta. */
#carnet-qr-url{display:block;font-style:normal;margin-top:5px;line-height:1.3}
.carnet-qr-probar{display:inline-block;font-size:9.5px;font-weight:700;color:#0369a1;
  text-decoration:none;border:1px solid #bae6fd;background:#f0f9ff;
  padding:3px 8px;border-radius:6px;margin-bottom:3px}
.carnet-qr-probar:hover{background:#e0f2fe}
.carnet-qr-dir{display:block;font-family:ui-monospace,Menlo,Consolas,monospace;
  font-size:8px;color:#94a3b8;word-break:break-all;line-height:1.3}
#carnet-qr-aviso{display:block;font-style:normal;font-size:8.5px;color:#b45309;
  margin-top:4px;line-height:1.35}
@media print{ #carnet-qr-url,#carnet-qr-aviso{display:none!important} }
.carnet-pie{background:#f8fafc;border-top:1px solid #e5e7eb;padding:9px 14px;font-size:9.5px;color:#64748b;line-height:1.45}
/* ============================================================
   EL CARNET IMPRESO SALE A TAMANO DE TARJETA   [01/09/2026]

   85,6 x 54 mm: la medida ISO 7810 ID-1, la de una tarjeta de credito
   y la de todos los porta-carnets que se consiguen. Antes se imprimia
   al ancho de la pantalla y habia que recortarlo a ojo.

   POR QUE EN MILIMETROS Y NO EN PIXELES
     Al imprimir, un pixel no mide nada fijo: depende del navegador y de
     la resolucion. Los milimetros son milimetros en cualquier impresora,
     que es justo lo que hace falta para que entre en el porta-carnet.

   POR QUE SE REESCALA TODO EN LUGAR DE REHACER EL DISENO
     La tarjeta esta disenada a 420 px de ancho. 85,6 mm son unos 323 px
     a 96 ppp, asi que se aplica un factor de 0,77 a la tarjeta entera:
     conserva las proporciones exactas que se ven en pantalla, sin tener
     que mantener dos disenos que se desincronizarian.

   LA GUIA DE CORTE
     Un borde punteado de 1 pt marca donde recortar. No se imprime en el
     PDF -ahi la hoja ya viene del tamano justo-, solo en papel, que es
     donde hay que cortar con tijeras.
   ============================================================ */
@media print{
  body *{visibility:hidden!important}
  #carnet-hoja,#carnet-hoja *{visibility:visible!important}
  #carnet-hoja{position:absolute;left:0;top:0;width:100%;margin:0;padding:0}
  @page{ size:auto; margin:8mm; }
  .carnet{
    box-shadow:none;
    border:1px dashed #94a3b8;          /* guia de corte */
    width:420px;                         /* el diseno original */
    transform:scale(0.7703);             /* 420px -> 85,60mm exactos (comprobado) */
    transform-origin:top left;
    margin:0;
  }
  /* El contenedor se encoge con la tarjeta para que no quede un hueco
     enorme debajo: sin esto, la hoja reserva los 420 px originales. */
  #carnet-hoja{height:54mm}
}
/* ============================================================
   AVISO DE VERSION NUEVA   [01/09/2026]

   POR QUE ES INSISTENTE PERO NO RECARGA SOLO
     Se pidio que «obligue» a actualizar, y lo hace: aparece arriba del
     todo, ocupa el ancho de la pantalla, empuja el contenido hacia
     abajo y NO se puede cerrar. Solo se va actualizando.

     Lo que NO hace es recargar por su cuenta. Si alguien esta a mitad
     de un reporte o escribiendo un proyecto, una recarga automatica le
     borra el trabajo sin preguntar. El aviso espera; el momento lo
     elige quien esta trabajando.

   POR QUE ARRIBA Y NO EN UNA ESQUINA
     Los avisos de esquina se aprenden a ignorar en dos dias. Este
     desplaza la pagina: no se puede mirar la pantalla sin verlo.
   ============================================================ */
/* El dorado de la casa (#B8860B -> #E8C86A), no el naranja de aviso:
   la barra es informacion del propio CRM, no una alarma. El texto va en
   la tinta oscura de la marca porque blanco sobre dorado da 1,9:1 y no
   se lee; #14181C sobre #E8C86A da 11,4:1. [03/09/2026] */
.crm-nueva-ver{
  position:fixed;left:0;right:0;top:0;z-index:9999;
  background:linear-gradient(90deg,#B8860B 0%,#E8C86A 55%,#B8860B 100%);color:#14181C;
  padding:10px 18px;display:flex;align-items:center;gap:14px;flex-wrap:wrap;
  box-shadow:0 6px 22px rgba(0,0,0,.28);font-size:13.5px;
  border-bottom:2px solid rgba(20,24,28,.18);
  animation:crmvernace .35s ease-out}
.crm-nueva-ver .cnv-ic{font-size:19px;line-height:1;flex:0 0 auto;
  animation:cnvgira 2.4s linear infinite}
@keyframes cnvgira{to{transform:rotate(360deg)}}
@media(prefers-reduced-motion:reduce){ .crm-nueva-ver .cnv-ic{animation:none} }
.crm-nueva-ver .cnv-tx{flex:1 1 auto;min-width:0;line-height:1.35}
.crm-nueva-ver .cnv-sub{display:block;font-size:11px;opacity:.75;font-weight:500}
.crm-nueva-ver .cnv-x{background:transparent;border:1px solid rgba(20,24,28,.3);
  color:#14181C;padding:7px 13px;border-radius:8px;font-weight:600;font-size:12.5px;
  cursor:pointer;font-family:inherit;white-space:nowrap}
.crm-nueva-ver .cnv-x:hover{background:rgba(20,24,28,.08)}
@keyframes crmvernace{from{transform:translateY(-100%)}to{transform:translateY(0)}}
.crm-nueva-ver b{font-weight:800;letter-spacing:.3px}
.crm-nueva-ver small{opacity:.9;font-size:11.5px}
.crm-nueva-ver .cnv-btn{margin-left:auto;background:#14181C;color:#E8C86A;border:none;
  padding:8px 18px;border-radius:8px;font-weight:800;font-size:13px;cursor:pointer;
  font-family:inherit;white-space:nowrap}
.crm-nueva-ver .cnv-btn:hover{background:#2a3038}
/* El contenido baja para no quedar tapado por el aviso. La medida la
   pone el propio aviso al dibujarse (--cnv-alto): en un telefono el
   texto ocupa dos renglones y un valor fijo tapaba el titulo. */
body.crm-con-aviso{padding-top:var(--cnv-alto,52px)}
@media(max-width:640px){
  .crm-nueva-ver{font-size:12.5px;padding:9px 12px;gap:9px}
  .crm-nueva-ver .cnv-btn{margin-left:0;width:100%}
  body.crm-con-aviso{padding-top:96px}
}
.ptabs{display:flex;gap:0;border-bottom:1px solid var(--line);margin:14px 0 6px;flex-wrap:wrap}
.ptabs button{background:none;border:none;color:var(--muted);padding:10px 16px;cursor:pointer;
  font-size:13px;font-family:inherit;border-bottom:2px solid transparent;white-space:nowrap}
.ptabs button:hover{color:var(--txt)}
.ptabs button.on{color:var(--accent);border-bottom-color:var(--accent);font-weight:600}
.ptabpane{padding-top:4px}
@media(max-width:560px){ .ptabs button{padding:9px 11px;font-size:12px} }
.vtabs{display:flex;gap:0;border-bottom:1px solid var(--line);margin:16px 0 4px}
.vtabs button{background:none;border:none;color:var(--muted);padding:8px 16px;cursor:pointer;font-size:13px;border-bottom:2px solid transparent}
.vtabs button.on{color:var(--accent);border-bottom-color:var(--accent);font-weight:600}
.fcard{background:var(--panel2);border:1px solid var(--line);border-radius:10px;margin-bottom:8px}
.fcard[open]{border-color:var(--accent)}
.fcard.best{border-color:#22c55e}
.fcard summary{list-style:none;cursor:pointer;display:flex;align-items:center;gap:12px;padding:12px}
.fcard summary::-webkit-details-marker{display:none}
.ftag{background:rgba(56,189,248,.2);color:var(--accent);border-radius:5px;padding:2px 8px;font-size:11px;font-weight:700;flex:0 0 auto}
.finfo{flex:1}
.finfo small{display:block;color:var(--muted);font-size:11px;margin-top:2px}
.fprice{text-align:right}
.fprice small{display:block;color:#86efac;font-size:11px;margin-top:1px}
.flinks{display:flex;gap:8px;flex-wrap:wrap;padding:0 12px 12px}
.mejor{background:#0d2818;border:1px solid #238636;color:#86efac;border-radius:8px;padding:10px 14px;font-weight:600;font-size:13px}
.abox{background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:14px;max-width:460px}
.abox input{background:var(--panel);border:1px solid var(--line);color:var(--txt);padding:8px;border-radius:6px;width:100%;box-sizing:border-box;margin-bottom:10px}
.proxlist{display:flex;flex-wrap:wrap;gap:7px;margin-top:8px}
.proxchip{background:var(--panel2);border:1px solid var(--line);border-radius:6px;padding:5px 9px;font-size:10px;color:var(--muted);text-align:center}
#vuelos-chart svg{cursor:crosshair}
.vtip{position:absolute;pointer-events:none;background:#0f172a;border:1px solid var(--accent);border-radius:8px;padding:8px 10px;font-size:11px;z-index:6;box-shadow:0 4px 14px rgba(0,0,0,.55);min-width:150px}
.vtip-d{font-weight:700;margin-bottom:4px;text-transform:capitalize;color:#e2e8f0}
.vtip-r{color:#cbd5e1;margin:1px 0}
.aerosel{display:flex;flex-wrap:wrap;gap:8px;margin:2px 0 4px}
.aerochip{display:inline-flex;align-items:center;gap:6px;background:var(--panel2);border:1px solid var(--line);color:var(--muted);border-radius:20px;padding:5px 12px;font-size:12px;cursor:pointer}
.aerochip.on{color:var(--txt);font-weight:600}
.aerochip:hover{border-color:var(--accent)}
/* Aerolínea que no opera la ruta seleccionada: no es un filtro apagado,
   es que ahí no hay servicio. Se deja visible pero inerte. */
.aerochip.sinruta{opacity:.32;cursor:not-allowed;text-decoration:line-through;border-style:dashed}
.aerochip.sinruta:hover{border-color:var(--line)}
.ruta-nota{width:100%;margin-top:8px;font-size:11.5px;color:var(--muted);line-height:1.5;
  background:var(--panel2);border:1px solid var(--line);border-radius:8px;padding:7px 11px}
/* Chips de días (proyectos en ejecución) */
.daychip{font-size:10px;padding:2px 8px;border-radius:8px;background:var(--panel);border:1px solid var(--line);color:var(--muted)}
.daychip.dur{color:#7dd3fc;border-color:#0c4a6e}
.daychip.wait{color:#fcd34d;border-color:#78350f}
.daychip.go{color:#86efac;border-color:#14532d}
.daychip.done{color:var(--muted)}
/* Reloj en vivo */
.clock{display:flex;flex-direction:column;align-items:flex-end;line-height:1.1}
.clock-time{font-size:16px;font-weight:700;color:var(--ok);font-variant-numeric:tabular-nums;letter-spacing:.5px}
.clock-date{font-size:10px;color:var(--muted);text-transform:capitalize}
/* Personal Técnico: toolbar, estado y formulario */
.spec-toolbar{display:flex;gap:8px;margin-bottom:14px;flex-wrap:wrap;align-items:center}
.spec-toolbar select,.spec-toolbar input{background:var(--panel2);border:1px solid var(--line);color:var(--txt);padding:7px 10px;border-radius:8px;font-size:13px}
tr.inactivo td{opacity:.45}
tr.inactivo td .badge{opacity:1}
.b-off{background:#3f2937;color:#f9a8c4}
/* ============================================================
   PROYECTOS 2026 · FORMULARIO Y FICHAS
   El formulario es ANCHO a propósito: son ocho campos que se llenan
   seguido, y en 640 px quedaban dos por fila tan estrechos que el
   nombre del proyecto no se veía entero mientras se escribía. A 900 px
   caben dos columnas de verdad, con el rótulo encima de cada casilla en
   vez de al lado, que es lo que apretaba la casilla contra el borde.
   ============================================================ */
.p26-modal{width:900px;padding:28px 30px}
.p26-grid{gap:16px 20px;margin:12px 0 20px}
.p26-grid label{font-size:11px}
.p26-grid input,.p26-grid select,.p26-grid textarea{
  background:var(--panel2);border:1px solid var(--line);color:var(--txt);
  padding:11px 12px;border-radius:8px;font-size:13.5px;font-family:inherit;width:100%;box-sizing:border-box}
.p26-grid textarea{resize:vertical;line-height:1.5}
/* ---- Impuestos y estampillas ---- */
.p26-cargos-h{display:flex;justify-content:space-between;align-items:center;gap:10px;
  margin:16px 0 7px;font-size:11px;font-weight:700;letter-spacing:.5px;
  text-transform:uppercase;color:var(--muted)}
.p26-cargos-h small{font-weight:400;text-transform:none;letter-spacing:0}
.p26-cargos-h .btn{padding:4px 10px;font-size:11.5px;text-transform:none;letter-spacing:0}
.p26-cargos{display:flex;flex-direction:column;gap:7px}
.p26-cargo{display:grid;grid-template-columns:1fr 88px 118px 34px;gap:8px;align-items:center}
.p26-cargo input,.p26-cargo select{background:var(--panel2);border:1px solid var(--line);color:var(--txt);
  padding:8px 10px;border-radius:7px;font-size:12.5px;font-family:inherit;width:100%;box-sizing:border-box}
.p26-cargo .pct{text-align:right;font-variant-numeric:tabular-nums}
.p26-cargo .quitar{background:none;border:1px solid var(--line);color:var(--muted);
  border-radius:7px;padding:7px 0;cursor:pointer;font-size:13px;line-height:1}
.p26-cargo .quitar:hover{border-color:var(--bad);color:var(--bad)}
.p26-cargos-vacio{color:var(--muted);font-size:12px;padding:4px 0}
/* El rótulo de la base es TEXTO, no un control: la regla contable no se
   elige, se cumple. Verlo escrito permite comprobarla de un vistazo. */
.p26-base{font-size:11px;color:var(--muted);text-align:center;line-height:1.25}
.p26-base.iva{color:var(--c-compra);font-weight:600}
.p26-desc-tot{color:var(--c-ambar)}
@media(max-width:640px){ .p26-cargo{grid-template-columns:1fr 70px 34px} .p26-base{grid-column:1/-1;text-align:left} }

/* ---- El resumen: la cuenta armada mientras se escribe ---- */
.p26-resumen{margin:16px 0 6px;background:var(--panel2);border:1px solid var(--line);
  border-radius:10px;padding:11px 14px;display:flex;flex-direction:column;gap:3px}
.p26-r{display:flex;justify-content:space-between;align-items:baseline;gap:12px;font-size:12.5px}
.p26-r span{color:var(--muted)}
.p26-r b{font-variant-numeric:tabular-nums;white-space:nowrap;color:var(--txt);font-weight:600}
.p26-r.suma b{color:var(--c-venta)}
.p26-r.resta b{color:var(--c-ambar)}
.p26-r.sep{border-top:1px solid var(--line);margin-top:5px;padding-top:6px}
.p26-r.grande span{color:var(--txt);font-weight:700}
.p26-r.grande b{font-size:15px;font-weight:800}
.p26-modal .mh{margin:18px 0 0}
.p26-modal .mh:first-of-type{margin-top:6px}
@media(max-width:760px){ .p26-grid{grid-template-columns:1fr} }

/* Fichas: una por proyecto, en rejilla que se acomoda al ancho. */
/* ============================================================
   RUEDA DE LAS SIETE FASES   [01/09/2026]

   Las siete SIEMPRE se ven. Una barra de progreso diría «vamos por el
   57 %» sin decir de qué; el círculo completo enseña el camino entero y
   dónde se está dentro de él, que es la pregunta real.

   Tres estados con contraste suficiente para leerse de un vistazo:
     · cumplida  -> color lleno
     · actual    -> color lleno + anillo exterior + latido suave
     · pendiente -> trazo tenue
   Se usan los colores del CRM (--accent, --ok, --line) para que la
   pieza no parezca traída de otro programa.
   ============================================================ */
/* ---- Encabezado de la ficha: rueda + nombre ---- */
.p26-cab2{display:flex;align-items:center;gap:13px;margin-bottom:11px}
.p26-rueda-wrap{flex:0 0 auto;cursor:pointer;line-height:0;border-radius:50%;
  transition:transform .15s}
.p26-rueda-wrap:hover{transform:scale(1.06)}
.p26-tit{min-width:0;flex:1}
.p26-fasetx{font-size:11.5px;color:var(--muted);margin-top:3px;cursor:pointer}
.p26-fasetx b{color:var(--accent)}
.p26-fasetx:hover{color:var(--txt)}

/* ---- Intermitencia de la fase actual ----
   Late el ARCO y su halo, no toda la rueda: si parpadeara entera, las
   fases cumplidas y las pendientes también desaparecerían y se perdería
   justo lo que la rueda enseña.

   Se anima `opacity`, que el navegador resuelve por hardware y no
   obliga a recalcular el trazado en cada cuadro. Y como los colores
   salen de las variables del tema (--accent, --ok, --line), el latido
   se ve igual de bien en claro y en oscuro sin escribir dos versiones.

   Quien tenga activado «reducir movimiento» en su sistema no ve el
   parpadeo: para esas personas puede provocar molestia real, y el dato
   se sigue leyendo por color y por el número del centro. */
@keyframes p26pulso{
  0%,100%{opacity:1}
  50%{opacity:.45}
}
@keyframes p26halo{
  0%,100%{opacity:.30;transform:scale(1)}
  50%{opacity:0;transform:scale(1.13)}
}
.p26-rueda .actual{animation:p26pulso 1.6s ease-in-out infinite;transform-origin:center}
.p26-rueda .halo{animation:p26halo 1.6s ease-in-out infinite;transform-origin:center}
@media (prefers-reduced-motion: reduce){
  .p26-rueda .actual,.p26-rueda .halo{animation:none}
  .p26-rueda .halo{opacity:.22}
}
.p26-fases{display:flex;align-items:center;gap:12px;cursor:pointer;
  border-top:1px dashed var(--line);padding-top:11px;margin-top:2px}
.p26-fases:hover .p26-rueda-tx{color:var(--accent)}
.p26-rueda{flex:0 0 auto;display:block}
.p26-rueda .seg{transition:opacity .18s}
.p26-rueda-info{min-width:0}
.p26-rueda-tx{font-size:12.5px;font-weight:700;color:var(--txt);line-height:1.25}
.p26-rueda-sub{font-size:11px;color:var(--muted);margin-top:2px}
@keyframes p26lat{0%,100%{opacity:1}50%{opacity:.55}}
.p26-rueda .actual{animation:p26lat 1.8s ease-in-out infinite}

/* Lista de fases del pop-up */
.p26-flist{display:flex;flex-direction:column;gap:8px;margin:6px 0 4px}
.p26-fila{display:grid;grid-template-columns:30px 1fr 150px;gap:10px;align-items:center;
  background:var(--panel2);border:1px solid var(--line);border-radius:9px;padding:9px 11px}
.p26-fila.es-actual{border-color:var(--accent);background:rgba(56,189,248,.09)}
.p26-fila .num{width:26px;height:26px;border-radius:50%;display:flex;align-items:center;
  justify-content:center;font-size:11px;font-weight:800;background:var(--line);color:var(--muted)}
.p26-fila.hecha .num{background:var(--ok);color:#04121d}
.p26-fila.es-actual .num{background:var(--accent);color:#04121d}
.p26-fila .nom{font-size:13px;color:var(--txt);font-weight:600;min-width:0}
.p26-fila .nom small{display:block;font-weight:400;font-size:11px;color:var(--muted)}
.p26-fila input[type=date]{background:var(--panel);border:1px solid var(--line);color:var(--txt);
  padding:7px 9px;border-radius:7px;font-size:12.5px;font-family:inherit;width:100%;box-sizing:border-box}
.p26-fmarca{display:flex;align-items:center;gap:7px;font-size:11.5px;color:var(--muted);cursor:pointer}
@media(max-width:560px){ .p26-fila{grid-template-columns:30px 1fr} .p26-fila input[type=date]{grid-column:2/3} }

/* ---- Acumulados de la cartera, bajo el encabezado ---- */
.p26-kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:12px;margin-top:14px}
.p26-kpi{background:var(--panel2);border:1px solid var(--line);border-radius:11px;padding:11px 14px}
.p26-kpi .r{font-size:10px;font-weight:700;letter-spacing:.6px;text-transform:uppercase;color:var(--muted)}
.p26-kpi .v{font-size:17px;font-weight:800;color:var(--txt);margin-top:3px;
  font-variant-numeric:tabular-nums;white-space:nowrap;letter-spacing:-.3px}
.p26-kpi .d{font-size:10.5px;color:var(--muted);margin-top:2px}
.p26-kpi.iva{border-color:rgba(34,197,94,.4)}
.p26-kpi.iva .v{color:var(--c-venta)}
.p26-kpi.tot{border-color:var(--accent)}

/* ============================================================
   COMPRAS CONTRA VENTAS EN EL DASHBOARD   [01/09/2026]
   ============================================================ */
/* El costado izquierdo mide 4 px SIEMPRE, tenga alarma o no. Si solo
   se engordara al saltar la alarma, la tarjeta se correria 3 px hacia
   la derecha justo en el momento en que uno la esta mirando. */
.iva-card{cursor:pointer;border-left-width:4px;transition:border-color .14s,transform .14s}
.iva-card:hover{border-color:var(--accent);transform:translateY(-1px)}
/* Cuando la compra se acerca a la venta la tarjeta se marca: el color
   avisa antes de que nadie lea la cifra. */
/* ============================================================
   LA ALARMA DEL IVA, EN EL COSTADO   [03/09/2026]

   Antes esto pintaba de ambar el BORDE ENTERO. Cumplia su funcion
   -avisar de lejos, sin leer cifras- pero chocaba con la regla nueva
   de la casa: en modo oscuro todos los bordes de tarjeta son grises y
   apenas se ven.

   Se traslada la senal al costado izquierdo, que es como ya avisan
   otras tarjetas del CRM (.imp-card, .evcard, .ido-grupo-cab). El
   borde de la tarjeta queda gris como los demas y el aviso se sigue
   viendo desde el otro lado del escritorio.

   NO se quita la alarma. Se enciende cuando el IVA de ventas llega al
   85 % del de compra, que es antes de que haya un problema; apagarla
   por una cuestion de color habria sido cambiar una advertencia de
   dinero por un detalle estetico.
   ============================================================ */
/* Los tres niveles usan las variables del tema y no colores escritos a
   mano: asi el verde y el rojo se aclaran o se oscurecen solos al pasar
   de tema oscuro a claro, sin dejar un tono que deslumbre o que se
   pierda contra el fondo. */
.iva-card.iva-ok    {border-left-color:var(--ok)}     /* por debajo del 80 %  */
.iva-card.iva-cerca {border-left-color:var(--warn)}   /* entre el 80 y el 90 %*/
.iva-card.iva-alerta{border-left-color:var(--bad)}    /* por encima del 90 %  */

/* ---- El sello de «en vivo» ----
   Un punto que late y el tiempo desde la última lectura. Distingue una
   cifra quieta de una cifra congelada: sin esto nadie sabe si el tablero
   está mirando o se quedó pegado. */
.iva-vivo{display:flex;align-items:center;gap:7px;flex-wrap:wrap;
  font-size:10.5px;color:var(--muted);margin:2px 0 6px}
.iva-vivo b{font-weight:700;color:var(--ok);letter-spacing:.4px;text-transform:uppercase}
.iva-vivo #iva-desde{font-variant-numeric:tabular-nums}
.iva-pulso{width:7px;height:7px;border-radius:50%;background:var(--ok);flex:0 0 auto;
  animation:ivalate 2s ease-in-out infinite}
@keyframes ivalate{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.35;transform:scale(.75)}}

/* ---- El destello de lo que cambió ----
   Solo sobre las cifras que se movieron. Un número que cambia sin avisar
   pasa desapercibido, y el sentido de tenerlo en vivo es enterarse. Dura
   poco: si se quedara encendido dejaría de señalar. */
.iva-cambio{animation:ivacambio 1.5s ease-out 1}
@keyframes ivacambio{
  0%  {background:rgba(245,158,11,.38);box-shadow:0 0 0 5px rgba(245,158,11,.18);border-radius:5px}
  70% {background:rgba(245,158,11,.14);box-shadow:0 0 0 5px rgba(245,158,11,.06);border-radius:5px}
  100%{background:transparent;box-shadow:none;border-radius:5px}
}
@media(prefers-reduced-motion:reduce){ .iva-pulso,.iva-cambio{animation:none} }

/* ---- La barra: dos filas, las mismas tres columnas ----
   La comparación la hace el ojo bajando por la columna. Columnas de 1fr
   para que midan igual aunque las cifras midan distinto: si el ancho lo
   pusiera el contenido, bailarían al crecer un dígito, y ese movimiento
   es justo lo que impide comparar. */
/* ============================================================
   EL MEDIDOR DE IVA
   Un riel con una raya. El riel vale el mayor de los dos IVA; la raya
   marca el techo (el IVA de compra). Verde por debajo de la raya, rojo
   lo que la pase. Se dibuja con dos <i> posicionados en porcentaje: no
   hace falta ninguna librería para una barra, y así funciona igual en
   red local sin internet.
   ============================================================ */
.med{margin:10px 0 4px}
.med-cab b{display:block;font-size:23px;font-weight:800;line-height:1.1;
  font-variant-numeric:tabular-nums;white-space:nowrap}
.med-cab em{display:block;font-style:normal;font-size:11px;color:var(--muted);margin-top:3px}
.med-riel{position:relative;height:26px;margin:16px 0 30px;border-radius:8px;
  background:var(--panel2);border:1px solid var(--line);overflow:visible}
.med-b{position:absolute;top:0;bottom:0;display:block;border-radius:7px;
  transition:left .5s ease,width .5s ease}
.med-b.ok{background:linear-gradient(90deg,var(--c-venta),#4ade80)}
.med-b.mal{background:linear-gradient(90deg,var(--c-rojo),#fca5a5);border-radius:0 7px 7px 0}
/* La raya sobresale arriba y abajo para que se lea POR ENCIMA de la
   barra aunque la barra la tape: si quedara al mismo nivel, justo
   cuando el valor la alcanza -que es el momento que importa- dejaría
   de verse. */
.med-raya{position:absolute;top:-6px;bottom:-6px;width:3px;margin-left:-1px;
  background:var(--txt);border-radius:2px;box-shadow:0 0 0 2px var(--panel);z-index:3}
.med-raya-tx{position:absolute;top:100%;margin-top:9px;transform:translateX(-50%);
  font-style:normal;font-size:10px;font-weight:700;color:var(--muted);white-space:nowrap;z-index:3;
  /* Tope de seguridad: aunque el calculo fallara, el rotulo nunca puede
     ser mas ancho que su caja. Con «clip» en vez de puntos suspensivos
     porque unos puntos en una etiqueta de 10 px no se entienden. */
  max-width:100%;overflow:hidden;text-overflow:clip}
/* Anclado por el final: la etiqueta crece hacia la izquierda y su borde
   derecho queda sobre la raya, dentro de la caja. */
.med-raya-tx.rtx-fin{transform:translateX(-100%)}
/* Anclado por el principio: crece hacia la derecha. */
.med-raya-tx.rtx-ini{transform:translateX(0)}
.med-pies{display:flex;gap:26px;flex-wrap:wrap;margin-top:4px}
.med-pie{font-size:11.5px;color:var(--muted);line-height:1.35}
.med-pie i{display:inline-block;width:10px;height:10px;border-radius:3px;margin-right:6px;vertical-align:-1px}
.med-pie.compra i{background:var(--txt)}
.med-pie.venta i{background:var(--c-venta)}
.med-pie b{display:block;font-size:15px;font-weight:800;color:var(--txt);
  font-variant-numeric:tabular-nums;margin-top:2px}
.med-pie em{display:block;font-style:normal;font-size:10.5px;margin-top:1px;opacity:.8}
.med-uso{margin-top:11px;font-size:12px;color:var(--muted)}
.med-vacio{padding:24px 10px;text-align:center;color:var(--muted);font-size:12.5px}
/* En pantalla angosta la etiqueta de la raya se sale por el borde
   cuando el límite queda muy a la izquierda o muy a la derecha; se
   deja de posicionar y se ancla al principio del riel. */
@media(max-width:560px){
  /* En pantalla estrecha no hay sitio para colocarlo bajo la raya sin
     que estorbe: se manda al principio de la linea y se queda quieto.
     El !important tambien vence al anclado de arriba, que aqui sobra. */
  .med-raya-tx,
  .med-raya-tx.rtx-fin,
  .med-raya-tx.rtx-ini{left:0 !important;transform:none !important}
  .med-cab b{font-size:19px}
  .med-pies{gap:14px}
}
.cmp{display:flex;flex-direction:column;gap:9px;margin-top:8px}
.cmp-fila{display:grid;grid-template-columns:minmax(150px,1.15fr) 1fr 1fr 1fr;gap:10px;
  align-items:center;background:var(--panel2);border:1px solid var(--line);
  border-radius:11px;padding:10px 14px}
.cmp-fila.compra{border-left:3px solid var(--c-compra)}
.cmp-fila.venta{border-left:3px solid var(--c-venta)}
.cmp-rot{font-size:12.5px;font-weight:700;color:var(--txt);line-height:1.25;min-width:0}
.cmp-rot em{display:block;font-style:normal;font-size:10.5px;font-weight:400;color:var(--muted);margin-top:2px}
.cmp-c{min-width:0;text-align:right}
.cmp-c span{display:block;font-size:9.5px;font-weight:700;letter-spacing:.5px;
  text-transform:uppercase;color:var(--muted)}
.cmp-c b{display:block;font-size:15px;font-weight:800;margin-top:2px;
  font-variant-numeric:tabular-nums;white-space:nowrap;color:var(--txt)}
/* El IVA se resalta porque es la única columna que se resta contra la
   otra fila: es la que se mira. */
.cmp-fila.compra .cmp-c.iva b{color:var(--c-compra)}
.cmp-fila.venta .cmp-c.iva b{color:var(--c-venta)}
.cmp-c.tot b{font-size:16px}
.cmp-saldo{display:flex;justify-content:space-between;align-items:center;gap:14px;
  flex-wrap:wrap;margin-top:11px;padding-top:11px;border-top:2px solid var(--line)}
.cmp-saldo span{font-size:12.5px;font-weight:700;color:var(--txt)}
.cmp-saldo em{display:block;font-style:normal;font-size:10.5px;font-weight:400;color:var(--muted);margin-top:2px}
.cmp-saldo b{font-size:19px;font-weight:800;font-variant-numeric:tabular-nums;white-space:nowrap}
.cmp-saldo b i{display:block;font-style:normal;font-size:10.5px;font-weight:400;
  color:var(--muted);text-align:right;margin-top:1px}
/* En 375 px seis cifras de nueve dígitos no caben, y media cifra no
   sirve para nada: el rótulo se va a su propio renglón. */
@media(max-width:720px){
  .cmp-fila{grid-template-columns:1fr 1fr 1fr}
  .cmp-rot{grid-column:1/-1;text-align:left}
  .cmp-c{text-align:left}
  .cmp-c b{font-size:14px}
}
/* ============================================================
   EN EL TELÉFONO, UNA CIFRA POR RENGLÓN   [02/09/2026]

   QUÉ SE VEÍA
     Tres columnas de 103 px en una pantalla de 390. «$ 43.528.492,13»
     necesita 118 px y lleva `white-space:nowrap` —una cifra partida en
     dos renglones no se puede leer—, así que se salía de su casilla y
     se montaba sobre la de al lado: «$ 43.528.492,1‡8.238.165,87‡$
     51.766.658,00». Las tres cifras ilegibles.

   POR QUÉ NO BASTA CON ACHICAR LA LETRA
     Para que quepan tres cifras de nueve dígitos en 390 px habría que
     bajar a 9 px. Eso no es leerlas, es adivinarlas — y son las cifras
     que se le declaran a la DIAN.

   LO QUE SE HACE
     Cada cifra pasa a su propio renglón, con el rótulo a la izquierda
     y el número a la derecha, que es como se lee un extracto. Ocupa
     tres renglones en vez de uno, y los tres se entienden.

   POR QUÉ 560 Y NO 430
     A 560 px —un teléfono grande acostado, o una ventana angosta en el
     computador— la cuenta ya no da: 3 x 160 px menos los espacios deja
     147 px por columna y la cifra más larga pide 118 px más el rótulo
     «SUBTOTAL» encima, que pide 62. Se parte antes de que falle.
   ============================================================ */
@media(max-width:560px){
  .cmp-fila{grid-template-columns:1fr;gap:0;padding:11px 13px}
  .cmp-rot{margin-bottom:7px}
  .cmp-c{display:flex;align-items:baseline;justify-content:space-between;gap:12px;
    padding:6px 0;border-top:1px solid var(--line)}
  .cmp-c span{margin:0;flex:0 0 auto}
  .cmp-c b{margin:0;font-size:15px;text-align:right;flex:1 1 auto;min-width:0;
    overflow:hidden;text-overflow:ellipsis}
  .cmp-c.tot b{font-size:16px}
}
/* El saldo, igual: en 390 px el rótulo y la cifra no caben lado a lado
   y flex-wrap los ponía a distinta altura, con la cifra flotando. */
@media(max-width:560px){
  .cmp-saldo{flex-direction:column;align-items:flex-start;gap:6px}
  .cmp-saldo b{font-size:22px}
  .cmp-saldo b i{text-align:left}
}
@media(max-width:520px){ .p26-kpi .v{font-size:15px} }
.p26-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(330px,1fr));gap:16px}
/* position:relative para que los tres puntos se coloquen respecto a la
   tarjeta. El padding derecho crece para que el titulo no se meta
   debajo del boton. [04/09/2026] */
.p26-card{position:relative;background:var(--panel2);border:1px solid var(--line);border-radius:13px;
  padding:16px 17px;padding-right:44px;display:flex;flex-direction:column;gap:11px}
.p26-card.venc{border-color:rgba(239,68,68,.55)}
.p26-cab{display:flex;justify-content:space-between;align-items:flex-start;gap:10px}
.p26-nom{font-size:15px;font-weight:700;line-height:1.3;color:var(--txt);word-break:break-word}
.p26-datos{display:flex;flex-direction:column;gap:7px;font-size:12.5px;color:var(--muted)}
.p26-dato{display:flex;gap:8px;align-items:flex-start;line-height:1.4;min-width:0}
.p26-dato>span:last-child,.p26-dato>div{min-width:0}
.p26-dato b{color:var(--txt);font-weight:600}
/* ---- La cuenta del proyecto ----
   Rótulo a la izquierda, importe a la derecha, en su propia celda. Con
   `tabular-nums` todas las cifras ocupan lo mismo, así que los puntos
   de millar quedan alineados en vertical de un renglón a otro y la
   columna se lee como una suma, no como tres frases sueltas.
   `white-space:nowrap` en el importe es lo que impide que una cifra de
   miles de millones se parta a mitad. */
.p26-cuenta{flex:1;min-width:0;display:flex;flex-direction:column;gap:2px;
  background:var(--panel);border:1px solid var(--line);border-radius:8px;padding:7px 10px}
.p26-l{display:flex;justify-content:space-between;align-items:baseline;gap:10px;font-size:11.5px}
.p26-l span{color:var(--muted);flex:0 0 auto}
.p26-l b{font-weight:600;color:var(--txt);font-variant-numeric:tabular-nums;
  white-space:nowrap;text-align:right;letter-spacing:-.2px}
.p26-l.iva span,.p26-l.iva b{color:#22c55e}
.p26-l.tot{border-top:1px solid var(--line);margin-top:3px;padding-top:4px}
.p26-l.tot span{color:var(--txt);font-weight:600}
.p26-l.tot b{font-size:14px;font-weight:800}
.p26-clic{cursor:pointer;transition:border-color .12s,background .12s}
.p26-clic:hover{border-color:var(--accent);background:var(--panel2)}
.p26-vermas{margin-top:5px;padding-top:5px;border-top:1px dashed var(--line);
  font-size:10.5px;color:var(--accent);text-align:right}
/* Tabla del detalle: rótulo, tarifa, base e importe, cada uno en su
   columna. En una sola línea corrida las cifras largas se parten. */
.p26-det{width:100%;border-collapse:collapse;font-size:12.5px}
.p26-det th{text-align:left;font-size:10px;letter-spacing:.5px;text-transform:uppercase;
  color:var(--muted);border-bottom:1px solid var(--line);padding:7px 8px;font-weight:700}
.p26-det td{padding:7px 8px;border-bottom:1px solid var(--line);color:var(--txt)}
.p26-det td.n{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
.p26-det td.sub{color:var(--muted);font-size:11.5px}
.p26-det tr.grupo td{background:var(--panel2);font-size:10px;letter-spacing:.5px;
  text-transform:uppercase;color:var(--muted);font-weight:700}
.p26-det tr.res td{font-weight:700}
.p26-det tr.res.fin td{font-size:14px;font-weight:800;border-top:2px solid var(--line)}
/* ROJO para todo lo que descuenta: tarifas e importes. El ámbar se
   confundía con un aviso; el rojo dice «esto se resta» sin leer. */
.p26-det .rojo{color:var(--c-rojo);font-weight:600}
.p26-det .desc{color:var(--c-rojo)}
.p26-det .iva{color:#22c55e}
/* Cierre de cada sección: se destaca sin llegar a competir con el neto. */
.p26-det tr.sub-tot td{background:rgba(220,38,38,.06);font-weight:700;
  border-top:1px solid rgba(220,38,38,.25);border-bottom:1px solid rgba(220,38,38,.25)}
.p26-det tr.tot-desc td{background:rgba(220,38,38,.10);font-weight:800;
  border-top:2px solid rgba(220,38,38,.35)}
@media(max-width:400px){ .p26-l{font-size:11px} .p26-l.tot b{font-size:13px} }
.p26-ico{flex:0 0 17px;text-align:center;opacity:.85}
.p26-plazo{font-weight:700}
/* Documentos del proyecto dentro de la ficha: lista compacta, cada uno
   con ver, descargar y quitar. Se ve todo sin abrir nada. */
/* ============================================================
   GALERIA DE FOTOS DEL PROYECTO   [02/09/2026]

   Rejilla que se acomoda sola al ancho: en el teléfono caben dos por
   fila, en el computador cinco o seis. No se fija un número de
   columnas porque el mismo proyecto se consulta desde la obra y desde
   la oficina.

   Las miniaturas son cuadradas y recortan la foto (object-fit:cover).
   Respetar la proporción de cada una dejaría la rejilla desigual y
   costaría más recorrerla con la vista; al abrirla se ve completa.
   ============================================================ */
.p26-fotos{border-top:1px dashed var(--line);padding-top:11px;margin-top:11px;font-size:12px}
/* La galería dentro de la ficha se retiró el 02/09/2026: hacía crecer
   la tarjeta del proyecto con cada foto. Las miniaturas viven ahora
   en la carpeta (.pc-grid). El botón de quitar sí se conserva:
   la carpeta lo reutiliza sobre sus propias miniaturas. */
/* El botón «×» de cada foto se retiró el 02/09/2026: lo reemplazó el
   menú de tres puntos (.pc-mas), que separa renombrar de eliminar.
   Dos iconos juntos sobre una miniatura hacían que el dedo
   acertara el que no era. */

/* ---- La carpeta: todas las miniaturas en una ventana ---- */
.p26-carpeta{position:fixed;inset:0;z-index:9997;background:rgba(2,6,23,.72);
  display:none;align-items:center;justify-content:center;padding:18px}
.p26-carpeta.open{display:flex}
.pc-caja{background:var(--panel);border:1px solid var(--line);border-radius:14px;
  width:min(1000px,96vw);max-height:88vh;display:flex;flex-direction:column;overflow:hidden;
  box-shadow:0 24px 60px rgba(0,0,0,.5)}
.pc-top{display:flex;align-items:center;gap:10px;padding:13px 16px;
  border-bottom:1px solid var(--line);flex-wrap:wrap}
.pc-top b{font-size:14px;color:var(--txt)}
.pc-top span{font-size:11.5px;color:var(--muted)}
.pc-x{margin-left:auto;background:none;border:none;color:var(--muted);font-size:24px;
  line-height:1;cursor:pointer;padding:0 4px;font-family:inherit}
.pc-x:hover{color:var(--txt)}
/* La rejilla se desplaza dentro de la ventana, no la página de atrás. */
.pc-grid{overflow:auto;padding:14px 16px 18px;display:grid;
  grid-template-columns:repeat(auto-fill,minmax(128px,1fr));gap:10px}
.pc-item{position:relative;margin:0;border-radius:9px;overflow:hidden;cursor:pointer;
  background:var(--panel2);border:1px solid var(--line);transition:transform .13s,border-color .13s}
.pc-item:hover{transform:translateY(-2px);border-color:var(--accent)}
.pc-item img{width:100%;aspect-ratio:1/1;object-fit:cover;display:block;background:var(--panel2)}
.pc-item figcaption{padding:5px 7px;font-size:10px;line-height:1.3;color:var(--muted)}
/* El nombre del archivo, en letra de ancho fijo para que los guiones y
   la fecha se lean como lo que son. Se corta con puntos suspensivos: el
   nombre completo queda en el «title» y en la descarga. */
.pc-arch{display:block;margin-top:3px;font-family:ui-monospace,Menlo,Consolas,monospace;
  font-size:8.5px;line-height:1.25;color:var(--muted);opacity:.85;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* El botón de ordenar nombres, en la cabecera de la carpeta. Se empuja
   contra la «×» sin taparla. */
.pc-orden{margin-left:auto;background:var(--panel2);border:1px solid var(--line);
  color:var(--txt);border-radius:8px;padding:5px 10px;font-size:11px;font-weight:600;
  font-family:inherit;cursor:pointer;white-space:nowrap;transition:border-color .15s,color .15s}
.pc-orden:hover{border-color:var(--accent);color:var(--accent)}
.pc-item figcaption b{display:block;color:var(--txt);font-size:10.5px;font-weight:600;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* ---- Los tres puntos de cada foto ----
   Sobre un fondo oscuro semitransparente para que se vean tanto en una
   foto clara como en una oscura: un icono blanco sobre una pared blanca
   no existe. */
.pc-mas{position:absolute;top:5px;right:5px;width:26px;height:26px;border-radius:7px;
  border:none;background:rgba(15,23,42,.62);color:#fff;font-size:15px;line-height:1;
  cursor:pointer;opacity:0;transition:opacity .13s,background .13s;font-family:inherit;
  display:flex;align-items:center;justify-content:center;padding:0}
.pc-item:hover .pc-mas{opacity:1}
.pc-mas:hover{background:rgba(15,23,42,.85)}
/* En pantalla táctil no existe «pasar por encima»: si dependiera del
   hover, en un teléfono no habría manera de abrir el menú. */
@media (hover:none){ .pc-mas{opacity:.9} }

/* ---- El menú ---- */
.pc-menu{position:fixed;z-index:10000;display:none;min-width:190px;
  background:var(--panel);border:1px solid var(--line);border-radius:10px;
  box-shadow:0 12px 34px rgba(0,0,0,.42);overflow:hidden;padding:4px}
.pc-menu button{display:flex;align-items:center;gap:9px;width:100%;background:none;
  border:none;color:var(--txt);font-family:inherit;font-size:13px;text-align:left;
  padding:9px 11px;cursor:pointer;border-radius:7px}
.pc-menu button:hover{background:var(--panel2)}
.pc-menu button span{font-size:14px;line-height:1}
.pc-menu .pc-menu-del:hover{background:rgba(248,113,113,.14);color:var(--bad)}
.pc-menu-no{padding:9px 11px;font-size:11.5px;color:var(--muted);line-height:1.35}

.pc-vacio{grid-column:1/-1;text-align:center;color:var(--muted);font-size:12.5px;
  padding:38px 12px;line-height:1.6}
@media(max-width:520px){
  .pc-grid{grid-template-columns:repeat(auto-fill,minmax(104px,1fr));padding:10px 11px 14px}
  .pc-caja{max-height:92vh}
}

/* ---- El visor ---- */
.p26-visor{position:fixed;inset:0;z-index:9998;background:rgba(2,6,23,.94);
  display:none;align-items:center;justify-content:center;padding:20px}
.p26-visor.open{display:flex}
.p26-visor figure{margin:0;max-width:min(1100px,94vw);text-align:center}
.p26-visor img{max-width:100%;max-height:78vh;border-radius:10px;display:block;margin:0 auto;
  background:#0f172a}
.p26-visor figcaption{color:#cbd5e1;font-size:12px;margin-top:12px;line-height:1.5}
.p26-visor button{position:absolute;background:rgba(255,255,255,.10);color:#fff;border:none;
  cursor:pointer;font-family:inherit}
.p26-visor .pv-x{top:14px;right:16px;width:40px;height:40px;border-radius:50%;font-size:24px;line-height:1}
.p26-visor .pv-a,.p26-visor .pv-s{top:50%;transform:translateY(-50%);width:46px;height:74px;
  border-radius:10px;font-size:32px;line-height:1}
.p26-visor .pv-a{left:12px} .p26-visor .pv-s{right:12px}
.p26-visor button:hover{background:rgba(255,255,255,.22)}
@media(max-width:640px){
  .p26-visor .pv-a,.p26-visor .pv-s{width:38px;height:60px;font-size:26px}
  .p26-visor img{max-height:68vh}
}

.p26-docs{border-top:1px dashed var(--line);padding-top:11px;font-size:12px}
.p26-docs-t{display:flex;align-items:center;gap:7px;font-weight:600;color:var(--txt);margin-bottom:7px}
.p26-n{background:var(--accent);color:#04121d;border-radius:999px;font-size:10px;font-weight:800;padding:1px 7px}
.p26-doclist{list-style:none;margin:0 0 8px;padding:0;display:flex;flex-direction:column;gap:5px}
.p26-doclist li{display:flex;justify-content:space-between;align-items:center;gap:8px;
  background:var(--panel);border:1px solid var(--line);border-radius:8px;padding:6px 9px}
.p26-doc-n{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--txt)}
.p26-doc-n small{color:var(--muted);font-weight:400}
.p26-doc-a{display:flex;gap:5px;flex:0 0 auto}
.p26-doc-a .btn{padding:3px 9px;font-size:11px;text-decoration:none}
.p26-doc-vacio{color:var(--muted);margin-bottom:8px}
.p26-alc{border-top:1px dashed var(--line);padding-top:11px;display:flex;gap:8px;
  flex-wrap:wrap;align-items:center;font-size:12px}
.p26-alc .btn{padding:4px 11px;font-size:11.5px}
.p26-acc{display:flex;gap:7px;flex-wrap:wrap;margin-top:auto;padding-top:4px}
.p26-acc .btn{padding:4px 11px;font-size:11.5px}
/* ============================================================
   ALINEACIÓN DE LOS CAMPOS   [01/09/2026]

   QUÉ SE VEÍA MAL
     «Valor total del contrato» lleva una aclaración debajo («· IVA
     incluido») y «Tarifa de IVA» no. Al ser los rótulos de distinta
     altura, sus casillas arrancaban a alturas distintas y la fila
     quedaba escalonada.

   POR QUÉ NO SE ARREGLA QUITANDO LA ACLARACIÓN
     Porque hace falta: sin ella nadie sabe si la cifra que escribe
     lleva IVA o no, y ese malentendido cuesta plata. El problema no era
     el texto, era la rejilla.

   LA SOLUCIÓN
     El control se empuja al fondo de su celda (margin-top:auto) y las
     celdas se estiran a la misma altura. Las casillas quedan a ras sin
     importar si el rótulo ocupa uno o dos renglones, y sirve para
     cualquier campo que se agregue después: no hay que medir nada a
     mano ni acordarse de esta regla.
   ============================================================ */
.formgrid{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin:10px 0 14px;align-items:stretch}
.formgrid label{display:flex;flex-direction:column;font-size:11px;color:var(--muted);gap:4px;text-transform:uppercase;letter-spacing:.4px}
.formgrid label>input,.formgrid label>select,.formgrid label>textarea{margin-top:auto}
/* La aclaración del rótulo es una nota, no un título: sin mayúsculas
   forzadas ni el espaciado entre letras del rótulo. */
.formgrid label small{text-transform:none;letter-spacing:0;font-size:10.5px;opacity:.8;line-height:1.25}
.formgrid input,.formgrid select{background:var(--panel2);border:1px solid var(--line);color:var(--txt);padding:9px;border-radius:7px;font-size:13px}
.fotoprev{width:64px;height:64px;border-radius:50%;object-fit:cover;border:1px solid var(--line)}
/* Reporte de servicio CALEP */
/* ============================================================
   ZONA · HOJA DEL REPORTE
   25 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
#rep-overlay .modal{width:840px;max-width:96vw;max-height:94vh;overflow:auto;padding:0;background:#fff;color:#111}
#rep-sheet{background:#fff;color:#111;padding:26px 30px;font-size:12px}
#rep-sheet .rhead{display:flex;justify-content:space-between;align-items:flex-start;border-bottom:2px solid #B8860B;padding-bottom:10px;margin-bottom:10px;gap:18px}
#rep-sheet .rhead-left{max-width:44%}
#rep-sheet .rhead-right{flex:1;display:flex;flex-direction:column;align-items:flex-end;gap:7px}
#rep-sheet .rtitle{color:#B8860B;font-weight:800;font-size:26px;letter-spacing:1px;line-height:1}
#rep-sheet .rlogo{height:46px;margin-bottom:6px;display:block}
#rep-sheet .rfechatb{border-collapse:collapse;font-size:10px;color:#B8860B;font-weight:700}
#rep-sheet .rfechatb td{border:1px solid #B8860B;padding:2px 6px;text-align:center}
#rep-sheet .rfechatb td.lbl{background:#eef2f7;font-weight:800;letter-spacing:.3px}
#rep-sheet .rfechatb input{border:none;padding:1px;font-size:11px;font-weight:400;color:#111;text-align:center;width:96px;font-family:inherit}
/* ---- Casillas de ENTRADA y SALIDA ----
   Se les fija el ancho para que la tabla no dependa de lo que mida su
   contenido. Sin esto, el selector de hora empujaba la casilla y se
   desbordaba por encima del borde azul. Con el ancho fijo, el selector
   se acomoda dentro y la tabla mantiene siempre la misma forma, que es
   además lo que conviene en un documento que se imprime. */
#rep-sheet .rfechatb td.hcell{width:116px;max-width:116px;padding:2px 3px;overflow:hidden}
#rep-sheet .rfechatb td.hcell .h12{width:100%;max-width:100%}
/* ---- Alto de la tabla de FECHA y HORA ----
   Se veía estirada porque cada casilla crecía con lo que llevara
   dentro: el campo de fecha pedía 34 px de alto y las listas de la hora
   otro tanto, y la tabla acababa midiendo el triple de lo necesario en
   un encabezado que debe ser discreto.

   Ahora el alto lo manda la tabla, no su contenido. Las filas miden lo
   mismo y el bloque queda proporcionado tanto en pantalla como en el
   documento impreso. */
#rep-sheet .rfechatb td{height:19px;line-height:1.15}
#rep-sheet .rfechatb td.lbl{white-space:nowrap}
#rep-sheet .rfechatb input,
#rep-sheet .rfechatb select{min-height:0;height:17px;line-height:1.1}
#rep-sheet .rfechatb .h12 select{padding:0 1px;font-size:11px}
#rep-sheet .rfechatb .h12{gap:2px}
#rep-sheet .rfechatb .h12 .h12-s{font-size:10px}
#rep-sheet .rtipos{display:flex;gap:22px;align-items:center;margin:2px 0;font-size:11px;color:#B8860B;font-weight:800}
#rep-sheet .rtipos label{display:inline-flex;align-items:center;gap:7px;cursor:pointer}
#rep-sheet .rtipos input[type=radio]{-webkit-appearance:none;appearance:none;width:14px;height:14px;border:1.5px solid #B8860B;border-radius:2px;position:relative;margin:0;cursor:pointer}
#rep-sheet .rtipos input[type=radio]:checked::after{content:"\2715";position:absolute;left:1px;top:-3px;font-size:13px;font-weight:800;color:#B8860B;line-height:1}
#rep-sheet .rfill{display:flex;align-items:baseline;gap:8px;margin:6px 0;font-size:11px;color:#B8860B;font-weight:800}
#rep-sheet .rfill input{flex:1;border:none;border-bottom:1px solid #B8860B;border-radius:0;padding:2px 4px;font-size:12px;font-weight:400;color:#111;font-family:inherit;background:transparent}
/* Alto del logo: 104 px. La imagen mide 511×359 (razón 1,42), así que a
   ese alto ocupa ~148 px de ancho y sigue cabiendo en los 190 px libres
   de la barra (230 px menos 20 de padding a cada lado) e incluso en el
   breakpoint de 200 px. max-width:100% lo protege si se cambia la barra. */
.brand-logo{display:block;width:auto;max-width:100%;height:104px;margin:0 auto 12px}
/* ============================================================
   ZONA · HOJA DEL REPORTE
   10 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
#rep-sheet .rco{font-size:9px;color:#333;text-align:left;line-height:1.45;margin-top:6px}
#rep-sheet .rco b{color:#B8860B}
#rep-sheet .rrow{display:flex;gap:12px;flex-wrap:wrap;margin:8px 0}
#rep-sheet .rf{display:flex;flex-direction:column;gap:3px;font-size:9.5px;color:#B8860B;font-weight:700;letter-spacing:.4px}
#rep-sheet .rf input,#rep-sheet .rf textarea,#rep-sheet .rbox textarea{border:1px solid #cbd5e1;border-radius:5px;padding:6px 8px;font-size:12px;color:#111;font-weight:400;font-family:inherit}
#rep-sheet .rbox{border:1px solid #B8860B;border-radius:6px;padding:10px 12px;margin:10px 0}
#rep-sheet .rlabel{color:#B8860B;font-weight:800;font-size:11px;margin-bottom:6px;letter-spacing:.5px;
  display:flex;align-items:center;gap:10px;flex-wrap:wrap}
/* ---- Botón de dictado ----
   Discreto mientras no se usa; en rojo y con un latido mientras escucha,
   para que no quede el micrófono abierto sin darse cuenta. */
#rep-sheet .dictar{background:#e2e8f0;border:1px solid #cbd5e1;color:#334155;
  border-radius:20px;padding:3px 11px;font-size:10.5px;font-weight:700;cursor:pointer;
  font-family:inherit;letter-spacing:0;display:inline-flex;align-items:center;gap:5px;
  min-height:26px;transition:background .15s,border-color .15s,color .15s}
#rep-sheet .dictar:hover{border-color:#0ea5e9;color:#0c4a6e}
#rep-sheet .dictar.grabando{background:#fee2e2;border-color:#ef4444;color:#991b1b;
  animation:dicLatido 1.4s ease-in-out infinite}
@keyframes dicLatido{0%,100%{box-shadow:0 0 0 0 rgba(239,68,68,.5)}
  60%{box-shadow:0 0 0 7px rgba(239,68,68,0)}}
/* ============================================================
   ZONA · HOJA DEL REPORTE
   32 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
#rep-sheet .dic-est{font-weight:600;font-size:10px;letter-spacing:0;color:#64748b;
  text-transform:none;flex:1 1 160px;min-width:0}
@media(max-width:640px){
  #rep-sheet .dictar{min-height:32px;padding:5px 13px;font-size:11px}
}
#rep-sheet textarea{width:100%;min-height:96px;resize:vertical}
/* Descripción y observaciones con renglones (papel rayado), como el reporte de ejemplo */
#rep-sheet .rbox textarea{line-height:26px;padding-top:5px;background-image:repeating-linear-gradient(transparent,transparent 25px,#c7d2e0 25px,#c7d2e0 26px);background-attachment:local;background-position:0 4px}
/* Las filas se arman por acomodo justificado: el ancho de cada foto lo
   pone _repAcomodarFotos() según su propia proporción. */
#rep-sheet .rimgs{display:flex;flex-wrap:wrap;gap:10px;align-items:flex-start}
/* ---- El recuadro de la foto ----
   Tiene alto propio y la imagen lo LLENA, recortando lo que sobra por
   los lados. Antes la imagen se encogía hasta caber entera y una foto
   vertical dejaba dos franjas blancas enormes a los costados —y una
   horizontal, arriba y abajo—. Ahora todas las fotos ocupan el mismo
   espacio, sin blancos, y el reporte queda parejo y más corto. */
#rep-sheet .rimg{flex:1;border:1px solid #64748b;border-radius:4px;
  height:230px;display:block;overflow:hidden;background:#f1f5f9}
#rep-sheet .rimg img{width:100%;height:100%;object-fit:cover;object-position:center;
  display:block;max-width:none;max-height:none}
#rep-sheet .rsign{display:flex;gap:40px;margin-top:22px}
#rep-sheet .rsign .col{flex:1;display:flex;flex-direction:column;align-items:center}
#rep-sheet .rsign .signame{border:none;width:100%;text-align:center;font-size:12px;color:#111;padding:2px 4px;font-family:inherit;background:transparent}
#rep-sheet .rsign .sigbox{border:none;height:70px;width:100%;display:flex;align-items:flex-end;justify-content:center;overflow:hidden;margin-bottom:0}
#rep-sheet .rsign img{max-height:68px;max-width:100%}
#rep-sheet .rsign .cap{color:#B8860B;font-weight:800;font-size:10px;line-height:1.3;width:100%;text-align:center;border-top:1px solid #333;padding-top:6px;margin-top:2px}
#rep-sheet .rsign .upl{margin-top:4px}
#rep-sheet .ringresp{font-size:10px;color:#B8860B;font-weight:700;text-align:center;margin-top:3px}
#rep-sheet .ringresp input{border:none;border-bottom:1px solid #cbd5e1;font-size:11px;font-weight:400;color:#111;font-family:inherit;padding:1px 3px;width:60%;background:transparent}
#rep-sheet .upl{display:inline-block;background:#0ea5e9;color:#fff;padding:5px 10px;border-radius:6px;font-size:11px;cursor:pointer;font-weight:400}
.rep-actions{display:flex;gap:8px;justify-content:flex-end;padding:12px 16px;border-top:1px solid #e2e8f0}
/* Módulo Reportes de servicio: tarjetas por cliente */
.rep-cli-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:12px;margin-top:6px}
.rep-cli-card{display:flex;flex-direction:column;gap:6px;text-align:left;background:var(--panel2);border:1px solid var(--line);border-radius:10px;padding:14px;cursor:pointer;color:var(--txt);transition:border-color .15s,transform .05s}
.rep-cli-card:hover{border-color:var(--accent)}
.rep-cli-card:active{transform:scale(.99)}
.rep-cli-card .rc-nom{font-weight:700;font-size:14px}
.rep-cli-card .rc-meta{display:flex;justify-content:space-between;align-items:center;color:var(--muted);font-size:12px}
.rep-cli-card .rc-badge{background:var(--accent);color:#fff;border-radius:20px;padding:2px 9px;font-size:11px;font-weight:700}
/* Botones de acción de un reporte (ver / descargar) */
.rep-ver,.rep-dl{display:inline-flex;align-items:center;gap:6px;border-radius:8px;padding:6px 12px;font-size:12px;font-weight:600;cursor:pointer;transition:background .15s,color .15s,box-shadow .15s,transform .05s;line-height:1}
.rep-ver svg,.rep-dl svg{width:14px;height:14px}
.rep-ver{background:transparent;color:var(--accent);border:1px solid var(--accent)}
.rep-ver:hover{background:var(--accent);color:#fff}
.rep-dl{background:linear-gradient(180deg,#10b981,#059669);color:#fff;border:1px solid #059669;box-shadow:0 1px 2px rgba(5,150,105,.3)}
.rep-dl:hover{background:linear-gradient(180deg,#059669,#047857);box-shadow:0 2px 8px rgba(5,150,105,.45)}
.rep-ver:active,.rep-dl:active{transform:scale(.96)}
/* fin [SEC-04] */

/* ============================================================
 *  ADAPTACIÓN A TABLETA Y CELULAR   [SEC-05]
 *  Va al final de la hoja para ganarle en cascada a las reglas
 *  de escritorio sin tener que reescribirlas.
 *
 *  Cortes:
 *    ≤1180px  iPad Pro horizontal · barra lateral más angosta
 *    ≤1024px  iPad horizontal
 *    ≤820px   iPad vertical → menú hamburguesa (ya existía)
 *    ≤640px   celular grande
 *    ≤430px   celular estándar
 * ============================================================ */

/* --- Base táctil: aplica en cualquier pantalla --- */
html{-webkit-text-size-adjust:100%;text-size-adjust:100%}
*{-webkit-tap-highlight-color:rgba(56,189,248,.18)}
img,canvas,svg,video{max-width:100%;height:auto}
/* Nada puede desbordar horizontalmente y romper el scroll de la página */
.card,.modal,.chip,.evcard{min-width:0}
.card{overflow-wrap:anywhere}

@media(max-width:1180px){
  .main{padding:22px 24px}
  :root{--side-w:200px}
  .esp-grid{grid-template-columns:repeat(3,1fr)}
}

@media(max-width:1024px){          /* iPad horizontal */
  .main{padding:20px 20px 40px}
  .grid2{grid-template-columns:1fr 1fr}
  .ur-grid{grid-template-columns:1fr}
  .kpi .n{font-size:28px}
  .kpi .l{font-size:10.5px}
}

@media(max-width:820px){           /* iPad vertical y abajo */
  /* La barra lateral pasa a cajón; el contenido usa todo el ancho */
  .side{width:270px;padding-top:calc(18px + env(safe-area-inset-top))}
  /* ---- El dedo necesita 44 px ----
     Con el ratón, una opción de 33 px de alto se acierta siempre. Con
     el dedo no: 44 px es la medida que recomiendan Apple y Google, y
     por debajo de ahí se toca la opción de al lado. Vale para las
     opciones del menú y para las del submenú de Facturas de compra,
     que son las más angostas de las dos. [02/09/2026] */
  .nav a{min-height:44px;display:flex;align-items:center}
  .nav a.navsub{min-height:42px;padding-top:6px;padding-bottom:6px}
  /* El cajón se puede recorrer con el dedo aunque el menú sea largo, y
     el último renglón no queda debajo de la barra del iPhone. */
  .nav{-webkit-overflow-scrolling:touch;padding-bottom:env(safe-area-inset-bottom)}
  .main{padding-left:max(16px,env(safe-area-inset-left));padding-right:max(16px,env(safe-area-inset-right))}
  .topbar{align-items:flex-start}
  .topbar h2{font-size:17px}
  .grid2{grid-template-columns:1fr}
  .dash-top-grid{flex-direction:column}
  .dash-top-grid>div{width:100%}
  /* Si las dos tarjetas están plegadas son apenas dos franjas delgadas:
     no tiene sentido gastar dos renglones del teléfono en ellas. */
  .dash-top-grid.dash-top-plegado{flex-direction:row;flex-wrap:wrap;gap:10px}
  .dash-top-grid.dash-top-plegado>div{width:auto;flex:1 1 240px}
  .esp-grid{grid-template-columns:repeat(2,1fr)}
  .formgrid{grid-template-columns:1fr 1fr}
  .colsel{grid-template-columns:repeat(auto-fill,minmax(160px,1fr));max-height:230px}
  /* Los modales dejan de tener ancho fijo. max-width en % (no en vw) porque
     el overlay ya tiene padding propio: con 96vw el modal se salía y obligaba
     a desplazar la ventana en horizontal. */
  .overlay{padding:12px}
  .modal{width:100%!important;max-width:100%;padding:18px}
  #rep-overlay .modal{max-width:100%}
  /* Blancos táctiles cómodos sin agrandar la interfaz de escritorio */
  .btn{min-height:38px;padding:8px 14px}
  select,input,textarea{min-height:38px}
  .calbar{gap:10px}
  .calviews{width:100%;display:flex;flex-wrap:wrap}
  .calviews button{flex:1 1 auto}
}

@media(max-width:640px){           /* celular grande */
  .main{padding:14px 14px calc(40px + env(safe-area-inset-bottom))}
  .topbar{margin-bottom:14px;gap:8px}
  .topbar h2{font-size:16px}
  .clock{display:none}                    /* la hora ya la da el sistema */
  .kpis{grid-template-columns:repeat(2,1fr);gap:8px}
  .kpi{padding:12px}
  .kpi .n{font-size:26px}
  .kpi .l{font-size:10px}
  .esp-grid{grid-template-columns:1fr}
  .formgrid{grid-template-columns:1fr}
  .formgrid>label[style*="grid-column"]{grid-column:1/2!important}
  .kv{grid-template-columns:1fr}
  .card{padding:14px}
  .card h3{font-size:15px;flex-wrap:wrap}
  .card h3 small{display:block;width:100%;margin:2px 0 0}
  .spec-toolbar>*,.vsearch>*{flex:1 1 100%}
  .conv{gap:6px 10px;padding:8px 10px}
  .conv-i{flex:1 1 100%}
  /* iOS hace zoom automático si el campo enfocado mide menos de 16px */
  input,select,textarea{font-size:16px}
  .overlay{padding:8px;align-items:flex-start}
  .modal{max-height:calc(100vh - 16px);padding:16px}
/* ============================================================
   ZONA · HOJA DEL REPORTE
   26 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
  .rep-actions{flex-wrap:wrap;justify-content:stretch}
  .rep-actions .btn{flex:1 1 100%}
  #rep-estado{flex:1 1 100%;text-align:center;order:-1;margin-bottom:6px}
  /* ---- El reporte de servicio en el celular ----
     Antes la hoja se dejaba en 660 px y tocaba desplazarla de lado.
     Ahora se acomoda al ancho del teléfono y se ve completa. El PDF no
     se afecta: se arma aparte, en una hoja A4 de 840 px, así que sale
     igual de bien aunque en pantalla se vea en una sola columna. */
  /* OJO con el :not(.rep-pdf): la copia que se usa para armar el PDF es
     una clonación de esta misma hoja y conserva el id. Sin esa exclusión,
     un reporte generado desde el celular saldría en una sola columna en
     vez del formato A4 de siempre. Con ella, el PDF sale idéntico se
     genere desde donde se genere. */
  #rep-overlay .modal{overflow-x:hidden}
  #rep-sheet:not(.rep-pdf){min-width:0;padding:16px 14px}
  #rep-sheet:not(.rep-pdf) .rhead{flex-direction:column;align-items:stretch;gap:12px}
  #rep-sheet:not(.rep-pdf) .rhead-left{max-width:100%}
  #rep-sheet:not(.rep-pdf) .rhead-right{align-items:stretch}
  #rep-sheet:not(.rep-pdf) .rtitle{font-size:20px;letter-spacing:.5px}
  #rep-sheet:not(.rep-pdf) .rlogo{height:40px}
  /* Fecha, entrada y salida: deben caber completas, sin recortarse */
  #rep-sheet:not(.rep-pdf) .rfechatb{width:100%;table-layout:fixed;font-size:9.5px}
  #rep-sheet:not(.rep-pdf) .rfechatb td{padding:3px 2px}
  #rep-sheet:not(.rep-pdf) .rfechatb td.lbl:first-child{width:56px}
  /* En el teléfono los campos necesitan algo más de alto para poder
     tocarlos, pero 34 px por casilla estiraban el encabezado entero.
     26 px sigue siendo un blanco cómodo y deja la tabla proporcionada. */
  #rep-sheet:not(.rep-pdf) .rfechatb input{width:100%;min-width:0;padding:2px 1px;height:26px;min-height:0}
  #rep-sheet:not(.rep-pdf) .rfechatb td{height:28px}
  #rep-sheet:not(.rep-pdf) .rfechatb select{height:26px;min-height:0}
  #rep-sheet:not(.rep-pdf) .rtipos{flex-wrap:wrap;gap:8px 16px}
  /* Etiqueta arriba y campo debajo: en una línea no cabían */
  #rep-sheet:not(.rep-pdf) .rfill{flex-direction:column;align-items:stretch;gap:2px}
  #rep-sheet:not(.rep-pdf) .rfill input{width:100%;flex:0 0 auto}
  #rep-sheet:not(.rep-pdf) .rrow{gap:10px}
  #rep-sheet:not(.rep-pdf) .rrow .rf{flex:1 1 100%!important;min-width:0!important}
  #rep-sheet:not(.rep-pdf) .rf input,#rep-sheet:not(.rep-pdf) .rf textarea{width:100%}
  #rep-sheet:not(.rep-pdf) .rbox{padding:9px 10px}
  #rep-sheet:not(.rep-pdf) .rimgs{flex-wrap:wrap}
  #rep-sheet:not(.rep-pdf) .rimgs>[data-foto]{flex:1 1 100%!important}
  #rep-sheet:not(.rep-pdf) .rsign{flex-direction:column;gap:22px;margin-top:16px}
  /* ---- Tablas en el teléfono ----
     Una tabla de siete columnas no cabe en una pantalla angosta, y
     obligaba a desplazar la página de lado para alcanzar los botones.
     Con la clase .tblr cada fila pasa a ser una ficha: el nombre de la
     columna a la izquierda y su valor a la derecha, uno debajo de otro.
     No hay que desplazar nada. En computador y tableta la tabla se
     sigue viendo igual que siempre: esto solo aplica aquí. */
/* ============================================================
   ZONA · TABLAS
   16 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
  table.tblr,table.tblr tbody,table.tblr tr,table.tblr td{display:block;width:100%}
  table.tblr thead{display:none}
  table.tblr tr{background:var(--panel2);border:1px solid var(--line);
    border-radius:10px;padding:2px 12px;margin-bottom:10px}
  table.tblr tr:hover td{background:transparent}
  table.tblr td{border:none;border-bottom:1px dashed var(--line);padding:9px 0;
    display:flex;gap:10px;align-items:flex-start;justify-content:space-between;
    font-size:12.5px;text-align:right;min-width:0;word-break:break-word}
  table.tblr td:last-child{border-bottom:none}
  table.tblr td::before{content:attr(data-lbl);flex:0 0 40%;text-align:left;
    color:var(--muted);font-size:10.5px;text-transform:uppercase;
    letter-spacing:.4px;font-weight:700;line-height:1.6}
  table.tblr td:not([data-lbl])::before{display:none}
  /* La celda de botones ocupa el ancho completo y se puede tocar cómodo */
  table.tblr td[data-acc]{display:block;text-align:left;white-space:normal!important;padding-top:11px}
  table.tblr td[data-acc]::before{display:none}
  table.tblr td[data-acc]>div{display:flex!important;width:100%;margin:0 0 6px!important}
  table.tblr td[data-acc]>div>*{flex:1 1 0;min-width:0}
  table.tblr td[data-acc] button,table.tblr td[data-acc] .btn{min-height:40px;width:100%}
  /* Fila sin datos: no debe verse como una ficha vacía */
  table.tblr tr.sinfilas{background:none;border:none;padding:0}
  /* Matrices de permisos: se desplazan dentro de su propio recuadro,
     nunca arrastrando la página entera. */
  .tbl-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch}
  .tbl-scroll table{min-width:420px}
  /* ---- Barras de acciones de cada sección ----
     Los botones del encabezado quedaban empujados a la derecha y había
     que desplazar de lado para alcanzarlos. Ahora bajan a su propio
     renglón y ocupan el ancho, que además es más fácil de tocar. */
  .card h3{flex-wrap:wrap;gap:6px}
  .card h3>span[style*="margin-left:auto"],
  .card h3>span[style*="margin-left: auto"]{margin-left:0!important;width:100%;flex-wrap:wrap;gap:6px!important}
  .card h3>span[style*="margin-left:auto"]>.btn,
  .card h3>span[style*="margin-left: auto"]>.btn{flex:1 1 auto}
  .card h3>.btn{flex:1 1 100%;margin-left:0!important}
  .rep-cli-grid{grid-template-columns:1fr!important}
  .vsearch,.spec-toolbar{gap:8px}
  /* Red de seguridad: nada puede arrastrar la página de lado. Lo que
     necesite más ancho se desplaza dentro de su propio recuadro. */
  body{overflow-x:hidden}
  .view,.card{max-width:100%}
  /* Tablas: scroll horizontal con la primera columna siempre visible */
  .card table{font-size:12px}
  .tl{overflow-x:auto;padding-bottom:4px;-webkit-overflow-scrolling:touch}
  .tl .lbl{font-size:9px}
  .mgrid.big .mdays{min-width:460px}
  .weekwrap{min-width:560px}
  .usermenu{right:0;left:auto;min-width:190px}
}

@media(max-width:430px){           /* celular estándar */
  .main{padding:12px 12px calc(36px + env(safe-area-inset-bottom))}
  .side{width:86vw}
  .kpis{grid-template-columns:repeat(2,1fr);gap:7px}
  .kpi{padding:10px;gap:9px}
  .kpi .n{font-size:22px}
  .kpi .l{font-size:9.5px}
  .card{padding:12px;border-radius:10px}
  .yeargrid{grid-template-columns:1fr}
  .chipgrid{grid-template-columns:1fr}
  .colsel{grid-template-columns:1fr}
  .uc-name{display:none}                  /* solo el avatar en la barra */
  .chip-det{font-size:9.5px}
  .btn{font-size:12px;padding:8px 11px}
  .modal{padding:14px;border-radius:12px}
  .login-left{padding:28px 20px}
  #rep-sheet:not(.rep-pdf){padding:14px 11px}
  #rep-sheet:not(.rep-pdf) .rtitle{font-size:17px}
  #rep-sheet:not(.rep-pdf) .rfechatb td.lbl:first-child{width:50px}
}

/* Pantalla baja en horizontal (celular acostado): el menú no debe
   quedar más alto que la ventana. */
@media(max-height:520px) and (orientation:landscape){
  .side{height:100vh;overflow-y:auto}
  .modal{max-height:96vh}
}

/* ---- Alto real de la ventana en el celular y en el iPad ----
   En Safari de iPhone y de iPad, 100vh cuenta también la franja del
   navegador, así que el menú y los cuadros quedaban cortados por abajo
   y no se alcanzaba a ver el final. La unidad dvh mide el alto que de
   verdad se ve. Los navegadores que no la conocen se quedan con 100vh,
   de modo que nada se rompe en ningún lado. */
@supports(height:100dvh){
  .app{min-height:calc(100dvh/var(--z))}
  .side{height:calc(100dvh/var(--z))}
  @media(max-width:820px){ .modal{max-height:calc(100dvh - 24px)} }
  @media(max-width:640px){ .modal{max-height:calc(100dvh - 16px)} }
  @media(max-height:520px) and (orientation:landscape){
    .side{height:100dvh}
    .modal{max-height:96dvh}
  }
}

@media print{
  @page{size:A4;margin:12mm}
  body *{visibility:hidden}
/* ============================================================
   ZONA · HOJA DEL REPORTE
   15 reglas seguidas. Las reglas NO se movieron de sitio: en
   estilos el orden manda -una regla posterior pisa a la anterior-,
   asi que reordenarlas cambiaria como se ve el CRM. Esto solo
   marca donde empieza cada zona.
   ============================================================ */
  #rep-sheet,#rep-sheet *{visibility:visible}
  #rep-overlay{position:static;display:block;background:#fff}
  #rep-overlay .modal{box-shadow:none;max-height:none;width:100%}
  #rep-sheet{position:absolute;left:0;top:0;width:100%;padding:0;font-size:11px}
  .rep-actions,.upl,.noprint{display:none !important}
  #rep-sheet .rf input,#rep-sheet .rfill input,#rep-sheet .signame,#rep-sheet textarea{border:none}
  #rep-sheet .rfill input{border-bottom:1px solid #B8860B}
  #rep-sheet .signame{border-bottom:1px solid #333}
  #rep-sheet .rbox{margin:7px 0;padding:8px 10px;page-break-inside:avoid}
  #rep-sheet #r-desc{min-height:auto}
  #rep-sheet #r-obs{min-height:40px}
  #rep-sheet .rsign{margin-top:16px;page-break-inside:avoid}
  #rep-sheet .rsign .sigbox{height:64px}
  #rep-sheet .rimg{border:1px solid #ccc}
  #rep-sheet .rfechatb input{border:none}
}


/* ---------- bloque 7 del archivo original ---------- */

/* fin [SEC-05] */
/* ============================================================
   ICONO DE DESCARGA — UNO SOLO PARA TODO EL CRM   [SEC-06]

   Antes se usaba el carácter de flecha hacia abajo de la tipografía.
   Cada sistema lo dibuja
   a su manera: en Windows sale fino, en Mac grueso, en Android es otro
   glifo, y en algún televisor no existe y aparece un recuadro vacío. En
   la sección de reportes, además, ya había un icono dibujado distinto:
   dos formas para la misma acción.

   Ahora es un dibujo propio en SVG, el mismo en los doce sitios donde
   se descarga algo.

   TAMAÑO PROPORCIONAL
     Se mide en `em`, no en píxeles. El icono toma su tamaño de la letra
     del botón que lo contiene: crece en un botón grande y se encoge en
     uno pequeño, sin escribir una medida para cada caso.

   COLOR
     `currentColor` en el trazo: hereda el color del texto de al lado.
     Así se tiñe solo al apuntar el botón, al desactivarlo o al cambiar
     entre tema claro y oscuro, sin reglas aparte.
   ============================================================ */
.ico-dl{width:1.08em;height:1.08em;vertical-align:-0.19em;flex:0 0 auto;
  display:inline-block;overflow:visible}
/* En un botón sin texto el icono es el botón: se le da algo más de
   presencia para que siga siendo un blanco cómodo. */
.pdfv-b .ico-dl{width:1.25em;height:1.25em;vertical-align:-0.25em}
/* La franja de acciones de los reportes usa botones muy pequeños. */
.rep-dl .ico-dl,.rep-ver .ico-dl{width:1.15em;height:1.15em}

/* ---- Ficha del contrato en solo lectura ---- */
.cv-estado{display:flex;gap:8px;flex-wrap:wrap;margin:10px 0 2px}
.cv-datos{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:9px 18px;margin-top:6px}
.cv-d{display:flex;flex-direction:column;gap:2px;min-width:0}
.cv-d span{font-size:10px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted)}
.cv-d b{font-size:13px;color:var(--txt);font-weight:600;overflow-wrap:anywhere}
.cv-d.ancho{grid-column:1/3}
.cv-docs{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin-top:6px}
.cv-doc{border:1px solid var(--line);border-radius:12px;background:var(--panel2);padding:12px}
.cv-doc-t{font-size:13px;font-weight:700;color:var(--txt);margin-bottom:4px}
.cv-doc-e{font-size:11px;color:var(--muted);line-height:1.5;min-height:32px}
.cv-doc-b{display:flex;gap:6px;flex-wrap:wrap;margin-top:9px}
.cv-doc-b .btn{padding:5px 10px;font-size:11.5px}
.cv-doc.falta{border-color:#f59e0b55}
.cv-doc.falta .cv-doc-e{color:#f59e0b}
@media(max-width:620px){
  .cv-datos,.cv-docs{grid-template-columns:1fr}
  .cv-d.ancho{grid-column:1}
}

/* Filtro por marca comercial en Clientes */
.cl-grupos{display:flex;gap:7px;flex-wrap:wrap;margin:10px 0 2px}
.cl-gchip{padding:5px 12px;border:1px solid var(--line);border-radius:999px;background:var(--panel2);
  font-size:11.5px;cursor:pointer;color:var(--txt);white-space:nowrap;
  transition:border-color .12s,background .12s}
.cl-gchip:hover{border-color:var(--accent)}
.cl-gchip.on{background:var(--accent2);border-color:var(--accent2);color:#fff;font-weight:600}
.cl-gchip i{font-style:normal;opacity:.7;margin-left:5px;font-size:10.5px}
.cl-gchip.on i{opacity:.9}
/* fin [SEC-06] */

/* ============================================================
   FICHA TÉCNICA DEL SITIO   [SEC-07]
   Foto a la izquierda y datos a la derecha en pantalla ancha; una
   debajo de la otra en el teléfono. Los equipos son tarjetas y no una
   tabla: una tabla de siete columnas no se puede llenar con el pulgar
   parado frente a un tablero, que es donde de verdad se usa esto.
   ============================================================ */
.fic-top{display:flex;gap:16px;flex-wrap:wrap;margin-top:12px}
.fic-foto{flex:0 0 240px;min-width:0}
.fic-datos{flex:1 1 320px;min-width:0}
.fic-marco{width:100%;aspect-ratio:4/3;border:1px solid var(--line);border-radius:10px;
  background:var(--panel2);display:flex;align-items:center;justify-content:center;overflow:hidden}
.fic-marco img{width:100%;height:100%;object-fit:cover;display:block}
.fic-vacio{font-size:11.5px;color:var(--muted);text-align:center;padding:10px}
.fic-eqs{display:flex;flex-direction:column;gap:9px;margin-top:6px}
.fic-eq{border:1px solid var(--line);border-radius:11px;background:var(--panel2);padding:10px 11px}
.fic-eq-top{display:flex;align-items:center;gap:8px;margin-bottom:8px}
.fic-eq-n{font-size:11px;font-weight:700;color:var(--muted);flex:0 0 auto}
.fic-eq-g{display:grid;grid-template-columns:repeat(4,1fr);gap:8px}
.fic-eq-g label{display:flex;flex-direction:column;gap:3px;font-size:10px;
  text-transform:uppercase;letter-spacing:.4px;color:var(--muted)}
.fic-eq-g input{width:100%;font-size:12.5px;padding:6px 8px}
.fic-eq-g .col2{grid-column:span 2}
@media(max-width:700px){
  .fic-foto{flex:1 1 100%}
  .fic-eq-g{grid-template-columns:repeat(2,1fr)}
  .fic-eq-g .col2{grid-column:span 2}
}
@media(max-width:400px){ .fic-eq-g{grid-template-columns:1fr} .fic-eq-g .col2{grid-column:span 1} }

/* Campana de notificaciones */
.notifbell{position:relative;display:flex;align-items:center;justify-content:center;width:38px;height:38px;background:var(--panel2);border:1px solid var(--line);border-radius:50%;cursor:pointer;user-select:none;font-size:17px;line-height:1}
.notifbell:hover{border-color:var(--accent)}
/* el contador de avisos: 3,76:1 era flojo para un numero de 11 px.
   Con el rojo del resto del CRM sube a 4,83:1. */
.notif-badge{position:absolute;top:-4px;right:-4px;min-width:18px;height:18px;padding:0 4px;background:#dc2626;color:#fff;font-size:11px;font-weight:700;border-radius:10px;display:flex;align-items:center;justify-content:center;box-shadow:0 0 0 2px var(--panel)}
.notifmenu{display:none;position:absolute;right:0;top:120%;width:340px;max-width:86vw;background:var(--panel);border:1px solid var(--line);border-radius:12px;z-index:70;box-shadow:0 12px 30px rgba(0,0,0,.35);overflow:hidden}
.notifmenu.open{display:block}
/* ---- Pantalla angosta: el panel se ancla a la pantalla, no a la campana ----
   El panel cuelga de la campana con right:0, así que crece 340 px hacia la
   IZQUIERDA. En un computador sobra sitio; en un teléfono la campana está
   cerca del borde izquierdo y el panel se salía de la pantalla y aparecía
   cortado. Anclado a la pantalla, con un margen a cada lado, siempre cabe,
   sin importar dónde quede la campana ni cuánto mida el teléfono. */
.notifmenu.fijo{position:fixed;left:8px;right:8px;width:auto;max-width:none;
  max-height:calc(100dvh - 96px);overflow-y:auto;-webkit-overflow-scrolling:touch}
.notifmenu.fijo .notif-list{max-height:none}
.notif-head{display:flex;align-items:center;justify-content:space-between;padding:11px 14px;border-bottom:1px solid var(--line)}
.notif-head b{font-size:13px;color:var(--txt)}
.notif-head a{font-size:11.5px;color:var(--accent);cursor:pointer;text-decoration:none}
.notif-list{max-height:400px;overflow-y:auto}
.notif-pie{padding:9px 14px;border-top:1px solid var(--line);text-align:center;background:var(--panel2)}
.notif-pie a{font-size:11.5px;color:var(--accent);cursor:pointer;font-weight:600}
/* ---- Historial completo de notificaciones ---- */
.hist-modal{width:960px;max-width:96vw;max-height:92vh;display:flex;flex-direction:column;padding:0;overflow:hidden}
.hist-bar{display:flex;gap:8px;flex-wrap:wrap;align-items:center;padding:14px;border-bottom:1px solid var(--line);background:var(--panel2)}
.hist-bar h3{font-size:16px;margin:0;flex:1 1 180px}
.hist-bar input,.hist-bar select{min-height:36px;font-size:13px}
.hist-bar .hb-q{flex:1 1 190px;min-width:0}
.hist-lista{flex:1;overflow-y:auto;padding:6px 14px 14px}
.hist-dia{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.6px;
  font-weight:700;margin:14px 0 6px;position:sticky;top:0;background:var(--panel);padding:6px 0;z-index:1}
.hist-fila{display:flex;gap:11px;align-items:flex-start;padding:9px 0;border-bottom:1px solid var(--line)}
.hist-ico{flex:0 0 26px;width:26px;height:26px;border-radius:7px;display:flex;align-items:center;
  justify-content:center;font-size:13px;background:var(--panel2)}
.hist-tx{flex:1;min-width:0}
.hist-tx b{display:block;font-size:12.5px;font-weight:600;line-height:1.35}
.hist-tx small{display:block;color:var(--muted);font-size:11px;margin-top:2px;line-height:1.45}
.hist-hora{flex:0 0 auto;color:var(--muted);font-size:11px;white-space:nowrap;padding-top:2px}
.hist-pie{display:flex;gap:10px;align-items:center;justify-content:center;flex-wrap:wrap;
  padding:11px 14px;border-top:1px solid var(--line);background:var(--panel2);font-size:12px;color:var(--muted)}
@media(max-width:640px){
  .hist-modal{max-width:100%;max-height:calc(100vh - 16px)}
  .hist-bar{padding:11px}
  .hist-bar>*{flex:1 1 100%}
  .hist-lista{padding:4px 11px 11px}
  .hist-hora{flex:1 1 100%;padding-top:4px}
  .hist-fila{flex-wrap:wrap}
}
.notif-item{position:relative;display:flex;gap:10px;padding:11px 30px 11px 14px;border-bottom:1px solid var(--line);cursor:pointer}
.notif-del{position:absolute;top:7px;right:7px;border:none;background:transparent;color:var(--muted);font-size:15px;line-height:1;cursor:pointer;padding:1px 6px;border-radius:6px}
.notif-del:hover{background:var(--line);color:var(--bad)}
.notif-item:last-child{border-bottom:none}
.notif-item:hover{background:var(--panel2)}
.notif-item.no-leida{background:var(--panel2);border-left:3px solid var(--accent);padding-left:11px}
.notif-ic{flex:0 0 auto;font-size:16px;margin-top:1px}
.notif-tx{min-width:0}
.notif-tx .t{font-size:12.5px;font-weight:600;color:var(--txt);margin-bottom:2px}
.notif-tx .m{font-size:12px;color:var(--muted);line-height:1.35}
.notif-tx .d{font-size:10.5px;color:var(--muted);margin-top:3px}
.notif-empty{padding:22px 14px;text-align:center;color:var(--muted);font-size:12.5px}
/* fin [SEC-07] */
/* ---- Movimiento de la campana ----
   Un balanceo corto: se inclina a un lado y al otro y vuelve al centro.
   Solo se anima transform, que es lo que resuelven por hardware tanto un
   iPhone como un televisor; se ve igual de fluido en todos. */
@keyframes campanazo{
  0%,100%{transform:rotate(0)}
  8%{transform:rotate(-16deg)} 20%{transform:rotate(13deg)}
  32%{transform:rotate(-9deg)} 44%{transform:rotate(6deg)}
  56%{transform:rotate(-3deg)} 68%{transform:rotate(0)}
}
.notifbell span[aria-hidden]{display:inline-block;transform-origin:50% 15%;
  will-change:transform;backface-visibility:hidden}
.notifbell span[aria-hidden].campanea{animation:campanazo 1s ease-in-out}
/* NO se apaga con «Reducir movimiento». Ese ajuste está encendido en
   muchos iPhone y iPad sin que su dueño lo recuerde, y era la razón de
   que allá no se viera moverse la campana. El balanceo dura un segundo
   y es suave: no es la clase de movimiento que incomoda a nadie, y aquí
   cumple una función —avisar de algo pendiente— que no conviene perder. */
/* Aviso de cuántas hojas ocupará el reporte, junto a «+ Agregar foto» */
.rep-hojas{font-size:11px;color:#64748b;line-height:1.45;flex:1 1 220px;min-width:0}
.rep-hojas.avisa{color:#b45309;font-weight:600}
.rep-hojas.alerta{color:#b91c1c;font-weight:700}
.rep-hojas:empty{display:none}
/* ---- Estado del equipo, dentro de la tarjeta de personal técnico ----
   Mismo lenguaje que el pie de las donas: cifras grandes centradas con
   su rótulo debajo, separadas por una línea sutil. */
.esp-res{display:flex;flex-wrap:wrap;gap:4px 0;align-items:stretch;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  margin:2px 0 14px;padding:12px 0}
.esp-res>span{flex:1 1 88px;min-width:0;text-align:center;padding:0 8px;
  display:flex;flex-direction:column;align-items:center;gap:3px;
  border-right:1px solid var(--line)}
.esp-res>span:last-child{border-right:none}
.esp-res b{font-size:23px;font-weight:800;line-height:1}
.esp-res small{font-size:9.5px;color:var(--muted);text-transform:uppercase;
  letter-spacing:.5px;line-height:1.3}
/* El detalle («1 permiso») aparece y desaparece según el día. Si no se
   le reserva su renglón, la franja entera crece y encoge y arrastra
   hacia abajo todo lo que viene después: otro salto, más disimulado.
   Con el alto reservado, aparecer o irse no mueve nada. */
.esp-res i{font-style:normal;font-size:10px;color:var(--muted);line-height:1.35;
  min-height:14px;display:block}
.esp-res i[hidden]{display:block;visibility:hidden}
.esp-res .er-ok b{color:var(--ok)}
.esp-res .er-cur b{color:var(--warn)}
.esp-res .er-vac b{color:#2dd4bf}
.esp-res .er-aus b{color:var(--purple)}
.esp-res .er-off b{color:var(--muted)}
/* ---- Movimiento de la franja de estado ----
   Dos gestos, los dos cortos y sin sobresaltos:
     · las celdas entran subiendo apenas, una tras otra;
     · la cifra que cambió da un latido, para que se note qué se movió.
   Se anima solo transform y opacity, que es lo que el teléfono resuelve
   por hardware: se ve igual de fluido en un iPhone viejo que en un PC. */
@keyframes erIn{from{opacity:0;transform:translateY(7px)}to{opacity:1;transform:none}}
@keyframes erPulso{0%{transform:scale(1)}32%{transform:scale(1.16)}100%{transform:scale(1)}}
@keyframes erBrillo{0%{box-shadow:inset 0 0 0 0 rgba(56,189,248,0)}
  30%{box-shadow:inset 0 0 22px -6px rgba(56,189,248,.35)}
  100%{box-shadow:inset 0 0 0 0 rgba(56,189,248,0)}}
.esp-res>span{will-change:transform,opacity}
.esp-res>span.er-in{animation:erIn .42s cubic-bezier(.2,.8,.3,1) both}
.esp-res>span.er-cambio b{display:inline-block;animation:erPulso .7s ease-out}
.esp-res>span.er-cambio{border-radius:9px;animation:erBrillo .9s ease-out}
.esp-res b{transition:color .25s ease}
/* En pantalla táctil el resaltado se queda pegado: solo con mouse */
@media(hover:hover) and (pointer:fine){
  .esp-res>span{transition:transform .18s ease}
  .esp-res>span:hover{transform:translateY(-2px)}
}
/* Si el equipo pide menos movimiento, entran sin desplazarse */
@media(prefers-reduced-motion:reduce){
  .esp-res>span.er-in{animation:none}
  .esp-res>span.er-cambio,.esp-res>span.er-cambio b{animation:none}
}
/* Las fichas de cada persona: respuesta suave al tocarlas o apuntarlas */
.esp-grid .chip{transition:transform .16s ease,border-color .16s ease,box-shadow .16s ease}
.esp-grid .chip:active{transform:scale(.985)}
@media(hover:hover) and (pointer:fine){
  .esp-grid .chip:hover{transform:translateY(-2px);box-shadow:0 8px 20px rgba(0,0,0,.28)}
}
/* Quiénes son, debajo de las cifras. Solo aparece si hay algo que decir. */
.esp-det{display:flex;flex-direction:column;gap:6px;margin:-6px 0 14px}
.esp-det:empty{display:none;margin:0}
.esp-det>span{font-size:11.5px;color:var(--muted);line-height:1.6}
.esp-det b{color:var(--txt);font-weight:600;margin-right:4px}
.esp-det .ed-vac b{color:#2dd4bf}
.esp-det .ed-aus b{color:var(--purple)}
.esp-det .ed-prox b{color:var(--muted)}
.esp-det .swatch{width:8px;height:8px;border-radius:2px;display:inline-block;
  margin-right:5px;vertical-align:baseline}
@media(max-width:640px){
  .esp-res{padding:10px 0;margin-bottom:12px}
  .esp-res>span{flex:1 1 33%;padding:6px 4px;border-right:none}
  .esp-res b{font-size:20px}
  .esp-res small{font-size:9px}
}


/* ---------- bloque 21 del archivo original ---------- */

#sa-ov{position:fixed;inset:0;z-index:99999;display:none;align-items:center;justify-content:center;background:rgba(1,4,9,.72);padding:16px;font:14px/1.45 system-ui,"Segoe UI",Roboto,Arial,sans-serif;-webkit-tap-highlight-color:transparent}
#sa-ov.on{display:flex}
#sa-ov .sa-card{width:100%;max-width:560px;max-height:88vh;display:flex;flex-direction:column;background:#161b22;color:#e6edf3;border:1px solid #30363d;border-radius:14px;box-shadow:0 18px 60px rgba(0,0,0,.6);overflow:hidden}
#sa-ov .sa-hd{display:flex;align-items:center;gap:10px;padding:14px 16px;border-bottom:1px solid #30363d;background:#1c2128}
#sa-ov .sa-hd h2{margin:0;font-size:16px;font-weight:600;flex:1}
#sa-ov .sa-x{background:transparent;border:0;color:#8b949e;font-size:18px;cursor:pointer;line-height:1;padding:4px 9px;border-radius:8px}
#sa-ov .sa-x:hover{background:#30363d;color:#e6edf3}
#sa-ov .sa-bd{padding:14px 16px;overflow:auto}
#sa-ov .sa-ft{display:flex;justify-content:flex-end;gap:10px;padding:12px 16px;border-top:1px solid #30363d;background:#1c2128}
#sa-ov .sa-note{margin:0 0 12px;color:#8b949e;font-size:12.5px}
#sa-ov .sa-tabs{display:flex;gap:6px;margin-bottom:14px;border-bottom:1px solid #30363d}
#sa-ov .sa-tab{background:transparent;border:0;border-bottom:2px solid transparent;color:#8b949e;padding:8px 12px;cursor:pointer;font-size:13px;font-weight:600}
#sa-ov .sa-tab.on{color:#e6edf3;border-bottom-color:#2ea043}
#sa-ov .sa-sec{display:none}
#sa-ov .sa-sec.on{display:block}
#sa-ov .sa-grp{margin:14px 0 6px;font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:#6e7681;font-weight:700}
#sa-ov .sa-row{display:flex;align-items:center;gap:10px;padding:9px 10px;border:1px solid #30363d;border-radius:10px;margin-bottom:8px;background:#0d1117}
#sa-ov .sa-ic{width:22px;text-align:center;color:#8b949e}
#sa-ov .sa-nm{flex:1;font-size:13.5px}
#sa-ov .sa-tg{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;color:#adbac7;cursor:pointer;user-select:none;white-space:nowrap}
#sa-ov .sa-tg input{width:16px;height:16px;accent-color:#2ea043;cursor:pointer;margin:0}
#sa-ov .sa-btn{background:#21262d;border:1px solid #30363d;color:#e6edf3;padding:8px 14px;border-radius:9px;cursor:pointer;font-size:13px;font-weight:600}
#sa-ov .sa-btn:hover{background:#30363d}
#sa-ov .sa-btn.pri{background:#238636;border-color:#2ea043;color:#fff}
#sa-ov .sa-btn.pri:hover{background:#2ea043}
#sa-ov .sa-btn:disabled{opacity:.6;cursor:default}
/* Los campos de la pestaña «Marca» se visten igual que los que ya
   había en este panel: mismo fondo, mismo borde, mismo tamaño. Se
   añaden a esta regla en vez de escribir otra para que el día que se
   cambie el aspecto del panel no queden dos estilos distintos dentro
   de la misma ventana. [14/09/2026] */
#sa-ov .sa-gate input,#sa-ov .sa-add select,
#sa-ov .sa-sec input[type=text],#sa-ov .sa-sec input[type=file]{width:100%;box-sizing:border-box;background:#0d1117;border:1px solid #30363d;color:#e6edf3;padding:10px 12px;border-radius:9px;font-size:14px;margin-top:6px}
#sa-ov .sa-sec input[type=file]{padding:8px 12px;font-size:12.5px}
#sa-ov .sa-l{display:block;margin:10px 0 0}
#sa-ov .sa-add{display:flex;gap:8px;align-items:center;margin-top:10px}
#sa-ov .sa-add select{flex:1;margin-top:0}
#sa-ov .sa-msg{margin-top:8px;font-size:12.5px;min-height:16px}
@media(max-width:600px){
  #sa-ov{padding:0;align-items:stretch}
  #sa-ov .sa-card{max-width:none;max-height:100vh;border-radius:0}
  #sa-ov .sa-row{flex-wrap:wrap}
  #sa-ov .sa-tg{flex:1;justify-content:flex-start;padding:6px 0}
}

/* ===================================================================
   COMPOSICIÓN DEL GASTO, DIBUJADA POR EL CRM        [11/09/2026]

   POR QUÉ EXISTE ESTA TARJETA SI YA HABÍA UNA
     La de antes era la pantalla de Facturación metida entera dentro
     de un <iframe>. En el iPad ese marco PARPADEA, y se descartó todo
     lo demás a base de pruebas: parpadeaba con la gráfica girando,
     parpadeaba con la gráfica completamente quieta, y parpadeaba
     igual en Chrome y en Safari. Un dibujo que no se repinta no puede
     parpadear solo: el culpable era el marco. iOS le da a cada
     <iframe> una capa aparte y la recompone cuando le conviene.

     Las tarjetas propias del CRM nunca han parpadeado en ese mismo
     iPad, y el otro CRM de la casa —que no tiene ni un iframe—
     tampoco. Así que esta se dibuja aquí, en el documento del CRM,
     como las demás.

   NI UN LIENZO, NI UNA LIBRERÍA
     El anillo es un `conic-gradient`: dos porciones, que es justo lo
     que hay que enseñar —subtotal e IVA—. No hay <canvas> que
     rasterizar ni Chart.js que descargar. Menos cosas que puedan
     fallar, y en un iPad se nota además en lo que tarda.

   NADA DE color-mix() NI oklch(), como en toda esta hoja: html2canvas
   —el motor de los PDF del CRM— no los entiende y deja la hoja en
   blanco. `conic-gradient` sí se entiende, y de todos modos esta
   tarjeta no entra en ningún PDF.

   LOS COLORES SALEN DEL TEMA
     Verde de venta para el subtotal y azul de compra para el IVA, los
     mismos significados que usa el resto del CRM. El agujero del
     centro es `--panel`, la superficie real de la tarjeta en cada
     tema: escribirlo en blanco dejaría un disco blanco en oscuro.
   =================================================================== */
.dt-cuerpo{display:grid;grid-template-columns:minmax(200px,.8fr) minmax(260px,1.2fr);
  gap:20px;align-items:center}
.dt-izq{display:flex;align-items:center;justify-content:center;min-width:0}
.dt-anillo{position:relative;width:200px;height:200px;border-radius:50%;
  background:conic-gradient(var(--c-venta) 0 var(--corte),var(--c-compra) var(--corte) 100%);
  display:grid;place-items:center;flex:0 0 auto}
/* El hueco del centro. `inset` en porcentaje para que el grosor del
   anillo no dependa del tamaño en píxeles. */
.dt-anillo::after{content:"";position:absolute;inset:19%;border-radius:50%;
  background:var(--panel)}
.dt-centro{position:relative;z-index:1;text-align:center;line-height:1.35}
.dt-centro .dtc-rot{display:block;font-size:11px;font-weight:600;color:var(--muted);
  letter-spacing:.3px}
.dt-centro .dtc-tot{display:block;font-size:17px;font-weight:800;color:var(--txt)}
.dt-centro .dtc-doc{display:block;font-size:11px;color:var(--muted)}
.dt-der{min-width:0}
.dt-fila{display:grid;grid-template-columns:1fr auto auto;gap:8px;align-items:baseline;
  padding:6px 0;font-size:13px;border-bottom:1px solid var(--line)}
.dt-fila:last-child{border-bottom:0}
.dt-fila.tot{font-weight:800;border-top:1px solid var(--line);border-bottom:0;margin-top:2px}
.dt-fila .dtf-nom{color:var(--txt);display:flex;align-items:center;gap:7px;min-width:0}
.dt-fila .dtf-val{font-weight:700;color:var(--txt);white-space:nowrap}
.dt-fila .dtf-pct{color:var(--muted);font-size:12px;white-space:nowrap;min-width:52px;
  text-align:right}
.dt-punto{width:9px;height:9px;border-radius:50%;flex:0 0 auto}
.dt-punto.base{background:var(--c-venta)}
.dt-punto.iva{background:var(--c-compra)}
.dt-provs{margin-top:12px;border-top:1px solid var(--line);padding-top:10px}
.dt-provs .dtp-cab{display:flex;justify-content:space-between;align-items:baseline;gap:8px;
  font-size:11px;text-transform:uppercase;letter-spacing:.5px;color:var(--muted);
  font-weight:700;margin-bottom:6px}
.dt-provs .dtp-sub{text-transform:none;letter-spacing:0;font-weight:400}
.dt-prov{display:grid;grid-template-columns:1fr auto auto;
  grid-template-areas:'nom val pct' 'bar bar bar';gap:2px 8px;align-items:center;
  padding:5px 0;font-size:12.5px}
.dt-prov .dtp-nom{grid-area:nom;color:var(--txt);min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.dt-prov .dtp-val{grid-area:val;font-weight:700;color:var(--txt);white-space:nowrap}
.dt-prov .dtp-pct{grid-area:pct;color:var(--muted);white-space:nowrap;min-width:48px;
  text-align:right}
.dt-prov .dtp-bar{grid-area:bar;height:4px;border-radius:3px;background:var(--panel2);
  overflow:hidden}
/* El proveedor pequeño se ve como punto y no como suciedad de render:
   con uno al 93 % y otro al 2 %, dos píxeles no parecen un dato. */
.dt-prov .dtp-bar i{display:block;height:100%;min-width:5px;border-radius:3px;
  background:var(--c-venta)}
.dt-sello{margin-top:10px;font-size:11px;color:var(--muted)}
.dt-cargando,.dt-fallo{padding:26px 14px;text-align:center;color:var(--muted);font-size:13px}
.dt-fallo b{display:block;color:var(--txt);margin-bottom:4px}
@media(max-width:820px){
  .dt-cuerpo{grid-template-columns:1fr;gap:14px}
  .dt-anillo{width:170px;height:170px}
}

/* ===================================================================
   EL BORDE DE LAS TARJETAS                        [03/09/2026]

   LO QUE SE PIDIO
     En oscuro, gris, que apenas se vea. En claro, naranja. En todos
     los modulos del menu de la izquierda, y en los que se hagan
     manana sin tener que acordarse de nada.

   POR QUE NO SE CAMBIO --line, QUE ERA LO OBVIO
     --line se usa en 136 reglas de esta hoja, y la gran mayoria NO son
     tarjetas: son los campos de texto, las lineas que separan las
     filas de las tablas, los menus desplegables, las pildoras y los
     botones fantasma. Pintar --line de naranja habria dejado el CRM
     entero rayado de naranja en modo claro. Por eso se creo una
     variable APARTE, que solo tocan las tarjetas.

   COMO SE ELIGIERON LAS TARJETAS
     No a dedo. Se recorrio la hoja buscando la firma de una tarjeta:
     fondo de panel, borde COMPLETO (no un border-top suelto, que eso
     es un separador) y esquinas de 10 a 16 px. Lo de las esquinas es
     lo que distingue una tarjeta de una pildora: las pildoras usan 20,
     22 o 999. Ademas se dejaron fuera por nombre los menus, los
     botones y las campanas. Salieron 30, y ahi esta .card, que es la
     que usan casi todas las pantallas.

   POR QUE EMPIEZAN TODAS POR «html»
     crm.css se carga ANTES que crm-carnet-tabs.css y
     crm-carnet-vivo.css. Con el mismo peso, gana la ultima hoja que se
     carga, asi que un simple «.cv-strip» de aqui perderia contra el
     «.cv-strip» de alla y el borde no cambiaria. Anteponer «html» pesa
     un poquito mas y gana siempre, venga de la hoja que venga. Asi no
     hubo que entrar a editar los archivos del companero.

   LOS DOS COLORES, MEDIDOS
     Oscuro  #333a42 sobre la tarjeta #1c2127 -> 1,41:1. Se intuye el
             contorno y no se impone. Antes era #525B65, 2,35:1, que
             marcaba demasiado.
     Claro   #e0821a sobre la tarjeta blanca  -> 2,85:1, y 2,53:1
             contra el fondo de la pagina. Naranja claro, firme, sin
             gritar.

   PARA UNA TARJETA NUEVA
     Si se construye con class="card", ya hereda el borde y no hay
     nada que hacer. Si lleva una clase propia, se agrega a la lista
     de abajo. Es el unico sitio donde tocar.
   =================================================================== */
:root{ --borde-tarjeta:#333a42; }
html[data-theme="light"]{ --borde-tarjeta:#e0821a; }
html .vsm-card,
html .vsm-ov-card,
html .esp-tile,
html .ido-grupo-cab,
html .esp-assign,
html .esp-assign-h,
html .card,
html .ur-mon,
html .ur-status,
html .cus-dia,
html .mgrid.mini,
html .ejcard,
html .conv,
html .cs-disp,
html .fk-wrap,
html .tiq-viaje,
html .vsearch,
html .fcard,
html .abox,
html .p26-resumen,
html .p26-kpi,
html .cmp-fila,
html .p26-card,
html .pc-caja,
html .rep-cli-card,
html .cv-doc,
html .fic-marco,
html .fic-eq,
html #spec-overlay .spec-card,
html .ident-caja,
html .cv-strip{ border-color:var(--borde-tarjeta); }

/* ===================================================================
   LAS TRES FOTOS DE IDENTIDAD EN EL PERFIL          [08/09/2026]

   Se ven en dos sitios: la pestaña «Documentos personales» de la ficha
   de Personal Técnico, y una ventana propia desde la tabla de Usuarios.
   El guion está en crm-identidad.js.

   ESTO SÍ VIVE DENTRO DEL CRM
     Al revés que el formulario de solicitud —que es una hoja clara
     sobre la pantalla de ingreso y no sigue el tema—, esto se mira
     dentro del CRM. Así que TODO sale de las variables del tema y se
     comporta igual en claro y en oscuro. Regla de la casa.

   EL RECUADRO VACÍO SE VE DISTINTO, NO IGUAL
     Que falte una imagen es información: quiere decir que la persona
     no la entregó, y las fotos son opcionales. Un hueco en blanco
     parecería un fallo de carga; un recuadro a trazos que dice «Sin
     registrar» dice lo que pasa.
   =================================================================== */
.ident-caja{margin:14px 0 16px;padding:13px 14px;border:1px solid var(--line);
  border-radius:12px;background:var(--panel2)}
.ident-tit{font-size:11px;font-weight:700;letter-spacing:1px;text-transform:uppercase;
  color:var(--muted);display:flex;align-items:center;gap:9px;flex-wrap:wrap}
.ident-ced{font-size:11px;font-weight:600;letter-spacing:.4px;text-transform:none;
  padding:1px 8px;border-radius:99px;background:var(--panel);color:var(--txt);
  border:1px solid var(--line)}
.ident-fila{display:grid;gap:10px;grid-template-columns:repeat(3,1fr);margin-top:11px}
.ident-uno{display:block;text-decoration:none;color:var(--txt)}
.ident-marco{display:block;position:relative;border:1px solid var(--line);
  border-radius:9px;overflow:hidden;background:var(--panel)}
.ident-uno img{display:block;width:100%;height:104px;object-fit:cover}
/* El rótulo de «no hay» nace ESCONDIDO y solo sale cuando la imagen
   falla de verdad.

   La primera versión lo dejaba puesto detrás de la imagen, contando con
   que esta lo tapara al cargar. El retrato pesa más de un mega: durante
   el segundo que tarda en llegar, los tres recuadros anunciaban «Sin
   registrar» con los tres archivos sanos en el servidor. Se llegó a dar
   por rota una función que funcionaba. [08/09/2026] */
.ident-falta{position:absolute;inset:0;display:none;align-items:center;
  justify-content:center;font-size:11px;color:var(--muted);text-align:center;padding:6px}
.ident-uno.vacio .ident-falta{display:flex}
.ident-uno.vacio .ident-marco{border-style:dashed;background:var(--panel2)}
/* Mientras la imagen viaja, el recuadro está vacío y en silencio: no
   dice nada que pueda ser mentira. */
.ident-marco{min-height:104px}
.ident-uno.vacio{cursor:default}
.ident-uno b{display:block;font-size:12px;font-weight:600;color:var(--txt);margin-top:6px}
.ident-uno small{display:block;font-size:10.5px;color:var(--muted);line-height:1.35;margin-top:2px}
.ident-uno:hover .ident-marco{border-color:var(--accent)}
.ident-uno.vacio:hover .ident-marco{border-color:var(--line)}
.ident-pie{margin-top:11px;font-size:11px;color:var(--muted);line-height:1.5}
.ident-pie b{color:var(--txt)}
.ident-btn{padding:4px 10px;font-size:12px}

/* La ventana desde la tabla de Usuarios. */
.ident-ov{display:none;position:fixed;inset:0;z-index:9600;background:rgba(10,13,16,.66);
  align-items:flex-start;justify-content:center;padding:40px 20px;overflow:auto}
.ident-ov.open{display:flex}
.ident-card{position:relative;width:100%;max-width:560px;background:var(--panel);
  color:var(--txt);border:1px solid var(--borde-tarjeta);border-radius:14px;
  padding:20px 22px;box-shadow:0 24px 60px rgba(0,0,0,.45)}
.ident-x{position:absolute;right:12px;top:10px;background:none;border:0;
  color:var(--muted);font-size:15px;line-height:1;cursor:pointer;padding:5px 7px;
  border-radius:7px}
.ident-x:hover{color:var(--txt);background:var(--fx-hover)}
/* Dentro de su propia ventana la caja ya no necesita marco: la ventana
   es el marco. */
.ident-card .ident-caja{margin:0;border:0;padding:0;background:transparent}
@media (max-width:560px){
  .ident-fila{grid-template-columns:1fr}
  .ident-uno img{height:150px}
}

/* ===================================================================
   EL PALPITO DE LA CIFRA A PAGAR                     [03/09/2026]

   La franja ambar del costado avisa de lejos. Esto avisa de cerca: la
   cifra que hay que girarle a la DIAN respira despacio, para que el ojo
   vuelva a ella aunque uno haya entrado al tablero a mirar otra cosa.

   COMO SE EVITO QUE MOLESTE
     · 2,6 segundos por ciclo. Son 0,38 destellos por segundo. Lo que
       cansa la vista -y lo que puede provocar una crisis a una persona
       fotosensible- esta por encima de 3 por segundo: esto va ocho
       veces por debajo. Un parpadeo rapido habria sido llamativo el
       primer minuto e insoportable el segundo.
     · La opacidad baja hasta 0,70 y no mas. Una cifra que casi
       desaparece se lee como un fallo de la pantalla, no como un
       aviso, y ademas obliga a esperar a que vuelva para leerla.
     · NO se mueve ni cambia de tamano. Un numero que crece y encoge
       empuja al texto de al lado y se vuelve dificil de leer. Solo
       respira la luz; el numero se queda quieto y legible todo el rato.
     · El halo usa currentColor, que es el rojo que ya tiene la cifra.
       Asi vale igual en tema oscuro y en claro, sin escribir dos
       colores que luego alguien tendria que acordarse de mantener.

   SI EL EQUIPO PIDE NO ANIMAR
     Con «reducir movimiento» activado el palpito se detiene, pero la
     cifra CONSERVA el halo fijo. El aviso no puede depender de un
     ajuste del sistema operativo: se cambia el modo de llamar la
     atencion, no se renuncia a llamarla.
   =================================================================== */
/* CORREGIDO EL MISMO DIA: SIN HALO
   La primera version acompanaba el latido con un «text-shadow». Sobre
   una cifra grande y en negrita eso no se lee como un resplandor: se
   lee como si el numero estuviera DESENFOCADO, y da la sensacion de
   que la pantalla esta fallando. Un aviso no puede parecer una averia.
   Queda solo la opacidad, que respira sin tocar un solo pixel del
   contorno: el numero se mantiene nitido de principio a fin. */
.iva-palpita{ animation:ivaPalpito 2.6s ease-in-out infinite; will-change:opacity }
@keyframes ivaPalpito{
  0%,100%{ opacity:1 }
  50%    { opacity:.62 }
}
@media (prefers-reduced-motion:reduce){ .iva-palpita{ animation:none } }

/* ===================================================================
   LA «X» DE CERRAR                                   [03/09/2026]
   Se coloca sola en los pop-up que no tenian ninguna forma visible de
   cerrarse (crm-popups.js). Va pegada arriba a la derecha del propio
   recuadro, no de la pantalla: asi cae en su sitio tanto en una
   ventana pequena como en el visor de PDF, que ocupa casi todo.
   Es un <button> de verdad, no un <span>: se alcanza con el tabulador
   y el lector de pantalla lo anuncia como «Cerrar».
   Y lleva «noprint» porque el reporte de servicio se imprime desde su
   propia ventana, y un boton impreso en la hoja seria un error.
   =================================================================== */
.x-cerrar{position:absolute;top:10px;right:12px;z-index:6;
  width:30px;height:30px;padding:0;display:flex;align-items:center;justify-content:center;
  background:var(--panel2);border:1px solid var(--line);border-radius:8px;
  color:var(--muted);font-size:15px;line-height:1;cursor:pointer;
  transition:color .12s,border-color .12s,background .12s}
.x-cerrar:hover{color:var(--txt);border-color:var(--accent);background:var(--panel)}
.x-cerrar:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
@media print{ .x-cerrar{display:none!important} }

/* Las tres fechas del proyecto, en una sola fila. Con auto-fit se
   parten solas en un telefono: tres campos de fecha en 360 px no caben
   y quedarian ilegibles. El minimo de 150 px es el ancho que necesita
   un selector de fecha para no cortar el «dd/mm/aaaa». [04/09/2026] */
.p26-fechas{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px}

/* ===================================================================
   LA PESTANA «LABORES DEL MES», OCULTA        [04/09/2026]
   Se pidio quitarla del perfil. Se hace desde AQUI y no borrando el
   codigo, porque esa pestana la dibuja crm-carnet-tabs.js, que es
   archivo de otro desarrollador: entrar a modificarlo por un cambio de
   visual es la forma de pisarse el trabajo entre dos personas.
   Ocultarla desde la hoja de estilos consigue lo mismo, no rompe su
   codigo, y el dia que quiera volver a verse se borran estas dos
   lineas.
   =================================================================== */
#spec-overlay .spectabs button[data-st="mes"],
#spec-overlay .spectab-panel[data-st="mes"]{ display:none !important }

/* La insignia del proyecto en la tarjeta de cada persona. Sin proyecto
   se pone ambar: no es un error -hay gente que legitimamente no esta en
   ninguna obra- pero si algo que hay que mirar. */
.chip-proy{display:inline-flex;align-items:center;gap:4px;max-width:100%;
  padding:2px 8px;border-radius:20px;font-size:10.5px;font-weight:700;
  background:var(--panel);border:1px solid var(--line);color:var(--muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.chip-proy.sinproy{border-color:var(--warn);color:var(--warn)}

/* ===================================================================
   EL CRONOGRAMA DE UN PROYECTO                     [04/09/2026]
   Se apoya en las clases del Gantt que ya existian (.gantt, .grow,
   .gtrack, .gbar...). Aqui van SOLO las piezas propias: los hitos de
   fase, las iniciales del personal sobre la barra y el formulario.
   =================================================================== */

/* Los hitos de las siete fases: un circulito con el numero, sobre la
   linea. Con el numero dentro no hace falta leyenda ni pasar el raton
   para saber cual es cual. */
.crono-hito{position:absolute;top:3px;width:20px;height:20px;margin-left:-10px;
  border-radius:50%;background:var(--panel);border:2px solid var(--accent);
  color:var(--accent);font-size:10px;font-weight:800;line-height:16px;
  text-align:center;z-index:4;cursor:default}

/* Las iniciales de quien va. A la derecha de la pista y no encima de la
   barra: una actividad corta deja una barra de pocos pixeles, y ahi no
   cabe ni una inicial. */
/* Las iniciales se corren para dejar sitio a los dias y al menu. */
.crono-gente{position:absolute;right:104px;top:4px;display:flex;gap:3px;
  pointer-events:none;z-index:3}
.crono-ini{display:inline-block;min-width:19px;height:18px;line-height:16px;
  padding:0 3px;border-radius:9px;background:var(--panel);border:1px solid var(--line);
  color:var(--muted);font-size:9.5px;font-weight:800;text-align:center;
  pointer-events:auto;cursor:default}

/* ===================================================================
   LA FILA DE UNA ACTIVIDAD                        [04/09/2026]
   De derecha a izquierda: los tres puntos, los dias que quedan y las
   iniciales de quien va. En ese orden porque asi se leen de fuera
   hacia dentro sin que ninguno tape a la barra.
   =================================================================== */

/* Tres puntos, iguales a los de la tarjeta de proyecto para que se
   reconozcan sin aprender nada nuevo. Dibujados con spans y no con el
   caracter «⋮», que cada sistema pinta a su manera. */
.crono-mas{position:absolute;right:3px;top:3px;z-index:6;
  width:20px;height:20px;padding:0;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:2px;
  background:transparent;border:1px solid transparent;border-radius:6px;cursor:pointer;
  transition:background .12s,border-color .12s}
.crono-mas span{display:block;width:3px;height:3px;border-radius:50%;background:var(--muted)}
.crono-mas:hover{background:var(--panel);border-color:var(--line)}
.crono-mas:hover span{background:var(--txt)}
.crono-mas:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* Los dias que quedan. Ambar cuando quedan dos o menos -es cuando hay
   que hacer algo- y apagado cuando ya termino, porque una actividad
   cerrada no pide atencion. */
.crono-dias{position:absolute;right:27px;top:5px;z-index:4;
  font-size:10px;font-weight:700;color:var(--muted);white-space:nowrap;pointer-events:none}
.crono-dias.urg{color:var(--warn)}
.crono-dias.fin{color:var(--muted);font-weight:400;opacity:.7}

.crono-menu button.peligro{color:var(--bad)}
.crono-menu button.peligro:hover{background:rgba(220,38,38,.12)}

.crono-sep{margin:14px 0 8px;padding-top:10px;border-top:1px solid var(--line);
  font-size:11px;font-weight:700;letter-spacing:1px;text-transform:uppercase;color:var(--muted)}

/* El formulario aparece bajo el cronograma, no encima: al programar se
   mira la linea mientras se escribe la fecha. */
.crono-form{display:none;margin-top:16px;padding-top:14px;border-top:1px solid var(--line)}
.crono-form.open{display:block}

.crono-personal{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));
  gap:4px 10px;max-height:190px;overflow-y:auto;padding:8px;border-radius:10px;
  background:var(--panel2);border:1px solid var(--line)}
.crono-p{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--txt);cursor:pointer}
.crono-p input{width:15px;height:15px;flex:none;margin:0}

/* En pantalla estrecha la etiqueta de cada fila come demasiado ancho y
   las barras quedan en nada. Se encoge, que el nombre completo ya esta
   en el title. */
@media (max-width:760px){
  .gantt .glabel{width:100px;flex:0 0 100px;font-size:11px}
  /* En pantalla estrecha no caben las tres cosas: se quitan las
     iniciales, que son el dato que tambien esta al pasar el raton, y se
     conservan los dias y el menu, que son acciones. */
  .crono-gente{display:none}
  .crono-dias{right:25px;font-size:9.5px}
}

/* El icono del cronograma, alineado con su texto. vertical-align por
   la mitad de la equis minuscula y no por la linea base: un dibujo
   cuadrado apoyado en la linea base parece hundido al lado de la
   palabra. [04/09/2026] */
.btn-crono{display:inline-flex;align-items:center;gap:6px}
.ico-crono{flex:none;vertical-align:-.15em}

/* ===================================================================
   LOS TRES PUNTOS DE LA TARJETA DE PROYECTO      [04/09/2026]
   Tres puntos dibujados con spans y no con el caracter «⋮»: ese signo
   lo dibuja cada sistema a su manera y en algunos ni siquiera existe
   en la tipografia, con lo que sale un cuadradito. Tres puntos hechos
   a mano se ven iguales en todas partes.
   El area pulsable es de 30x30 aunque los puntos ocupen menos: por
   debajo de eso falla el dedo en una tableta.
   =================================================================== */
.p26-mas{position:absolute;top:11px;right:11px;z-index:4;
  width:30px;height:30px;padding:0;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:3px;
  background:transparent;border:1px solid transparent;border-radius:8px;
  cursor:pointer;transition:background .12s,border-color .12s}
.p26-mas span{display:block;width:3.5px;height:3.5px;border-radius:50%;background:var(--muted)}
.p26-mas:hover{background:var(--panel);border-color:var(--line)}
.p26-mas:hover span{background:var(--txt)}
.p26-mas:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* «Eliminar» en rojo dentro del menu: es la unica que no se puede
   deshacer, y tiene que distinguirse de la de al lado ANTES de
   pulsarla. */
.p26-menu button.peligro{color:var(--bad)}
.p26-menu button.peligro:hover{background:rgba(220,38,38,.12)}

/* El boton del cronograma, mas visible: color lleno, mas alto y a todo
   el ancho de la tarjeta. Ahora es la unica accion de abajo, asi que no
   hay nada con lo que competir por el sitio. */
.btn-crono.grande{width:100%;justify-content:center;padding:9px 14px;
  font-size:13.5px;font-weight:600}
.btn-crono.grande .ico-crono{stroke-width:1.9}

/* ===================================================================
   LAS TRES FECHAS DEL PROYECTO                    [04/09/2026]
   =================================================================== */

/* En la tarjeta: tres columnas iguales, en el orden en que ocurren.
   auto-fit para que en un telefono se apilen en vez de encogerse hasta
   que la fecha no se lea. */
.p26-3f{display:grid;grid-template-columns:repeat(auto-fit,minmax(96px,1fr));
  gap:6px 10px;padding:9px 11px;border-radius:10px;
  background:var(--panel);border:1px solid var(--line)}
.p26-3f>div{min-width:0;display:flex;flex-direction:column;gap:1px}
.p26-3f span{font-size:9.5px;font-weight:700;letter-spacing:.6px;
  text-transform:uppercase;color:var(--muted)}
.p26-3f b{font-size:12.5px;color:var(--txt);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.p26-3f i{font-style:normal;font-size:10.5px;font-weight:700}

/* En el cronograma: las tres, el boton y el aviso, en una fila. */
/* Cuatro columnas escritas a mano y no «auto-fit». Con auto-fit
   seguido de una columna «auto» el navegador no sabe cuantas repetir y
   acababa poniendo una por renglon: las tres fechas salian apiladas.
   Escritas asi, van en una fila. [04/09/2026] */
.crono-fechas{display:grid;
  grid-template-columns:1fr 1fr 1fr auto;
  gap:10px 12px;align-items:end;margin:14px 0 4px;padding:12px 13px;
  border-radius:12px;background:var(--panel2);border:1px solid var(--line)}
.crono-fechas label{display:flex;flex-direction:column;gap:4px;font-size:11.5px;color:var(--muted)}
.crono-fechas input{min-width:0}
.crono-f-aviso{grid-column:1/-1;font-size:11.5px;min-height:0;color:var(--muted)}
.crono-f-aviso.mal{color:var(--bad);font-weight:600}
.crono-f-aviso.bien{color:var(--ok)}
/* Por debajo de 780 px tres fechas y un boton no caben en una fila sin
   que el selector de fecha corte el «dd/mm/aaaa»: se pasa a dos
   columnas, y en telefono a una. */
/* El botón «Guardar fechas» se alinea con los de fecha, que ahora
   llevan un rótulo encima. [04/09/2026] */
.crono-fechas>#crono-f-guardar{align-self:end;margin-bottom:1px;white-space:nowrap}
@media (max-width:780px){
  .crono-fechas{grid-template-columns:1fr 1fr}
  .crono-fechas>button{grid-column:1/-1}
}
@media (max-width:480px){
  .crono-fechas{grid-template-columns:1fr}
}

/* La barra provisional de la actividad que se esta escribiendo: a
   rayas y sin relleno, para que se distinga de las de verdad. */
.gbar.crono-previa{border-style:dashed;border-width:2px;opacity:.95}
.gbar.crono-previa .gfill{opacity:.22}
.grow.crono-fila-previa .glabel{font-style:italic;color:var(--accent)}

/* El módulo, dentro del aviso de versión nueva: en el color de acento
   para que se lea de un vistazo sin ir palabra por palabra.
   [04/09/2026] */
.cnv-mod{color:var(--accent);font-weight:700}

/* ===================================================================
   LAS TRES FECHAS DEL PROYECTO, COMO BOTONES        [04/09/2026]

   Se leen cien veces por cada vez que se cambian, así que se muestran
   grandes y legibles y el modo de edición se pide con los tres
   puntos. Los tres puntos aparecen al pasar por encima o al llegar
   con el tabulador: presentes cuando se buscan, callados mientras se
   consulta.

   La fecha vacía se marca en otro color y con «—»: un hueco en blanco
   se lee como «se me olvidó pintarlo», no como «falta el dato».
   =================================================================== */
.fbtn{position:relative;display:flex;flex-direction:column;gap:3px;min-width:0}
.fbtn-rot{font-size:11px;font-weight:700;letter-spacing:.4px;
  text-transform:uppercase;color:var(--muted)}
.fbtn-val{
  display:block;width:100%;text-align:left;
  font-size:16px;font-weight:700;font-variant-numeric:tabular-nums;
  color:var(--txt);background:var(--panel);border:1px solid var(--borde-tarjeta,var(--line));
  border-radius:10px;padding:9px 34px 9px 12px;cursor:pointer;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  transition:border-color .12s, background .12s}
.fbtn-val:hover{border-color:var(--accent);background:var(--panel2)}
.fbtn-val.vacia{color:var(--muted);font-weight:600}

/* Los tres puntos, en la esquina del propio botón. */
.fbtn-mas{
  position:absolute;right:6px;bottom:9px;width:24px;height:26px;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;
  background:transparent;border:0;border-radius:7px;cursor:pointer;
  opacity:0;transition:opacity .12s, background .12s}
.fbtn-mas span{width:3px;height:3px;border-radius:50%;background:var(--muted);display:block}
.fbtn:hover .fbtn-mas,
.fbtn-mas:focus-visible,
.fbtn-val:focus-visible + .fbtn-mas{opacity:1}
.fbtn-mas:hover{background:var(--fx-hover,var(--panel2))}
.fbtn-mas:hover span{background:var(--accent)}
/* En pantalla táctil no hay «pasar por encima»: se dejan siempre. */
@media (hover:none){ .fbtn-mas{opacity:.85} }

/* La casilla real: escondida hasta que se pide editar, y entonces
   ocupa el sitio del botón para que nada se mueva. */
.fbtn-input{display:none;font-size:15px;padding:9px 10px;border-radius:10px;
  background:var(--panel);color:var(--txt);border:1px solid var(--accent);width:100%}
.fbtn.editando .fbtn-val,
.fbtn.editando .fbtn-mas{display:none}
.fbtn.editando .fbtn-input{display:block}

/* Botones con icono: el dibujo y el texto alineados por su centro, no
   por la linea base. Un icono cuadrado apoyado en la linea base parece
   hundido al lado de la palabra. [04/09/2026] */
.btn-ico{display:inline-flex;align-items:center;gap:6px}
.ico-avi{flex:none;vertical-align:-.15em}

/* ===================================================================
   CRONOGRAMA GENERAL                              [04/09/2026]
   =================================================================== */
.crogen-leyenda{display:flex;gap:16px;flex-wrap:wrap;align-items:center;
  margin:12px 0 6px;font-size:11.5px;color:var(--muted)}
.crogen-leyenda span{display:inline-flex;align-items:center;gap:6px}
.crogen-leyenda i{width:11px;height:11px;border-radius:3px;flex:none}
.crogen-ayuda{margin-left:auto;font-style:italic}

/* Toda la pista es pulsable, no solo la barra: una obra de tres dias
   deja una barra de pocos pixeles y acertarle con el dedo en una
   tableta seria cuestion de suerte. */
.crogen-pista{cursor:pointer;transition:background .12s}
.crogen-pista:hover{background:var(--panel)}
@media (max-width:640px){
  .crogen-ayuda{margin-left:0;width:100%}
}

/* ===================================================================
   LA ESCALA DIARIA DEL CRONOGRAMA          [04/09/2026]
   =================================================================== */

/* La cabecera crece para que quepan las fechas de pie. 46 px es lo que
   ocupa «04/09» en vertical a 9,5 px mas su respiro. */
.crono-ghead .gtrack{height:52px;background:transparent}
.crono-gantt .gline{border-left-color:var(--line);opacity:.45}

/* Las fechas, escritas de arriba abajo. writing-mode y no rotate():
   un texto rotado con transform conserva su ancho original en el
   diseño y empuja lo de al lado; con writing-mode ocupa de verdad lo
   que se ve. */
/* ===================================================================
   LAS FECHAS SE LEEN DE ABAJO HACIA ARRIBA   [04/09/2026 · corregido]

   Estaban escritas de arriba abajo y costaba leerlas. No es
   costumbre: es que al girar la cabeza -o el papel- a la derecha, que
   es el gesto natural, un texto de arriba abajo queda BOCA ABAJO. De
   abajo hacia arriba queda derecho. Es la misma razón por la que los
   lomos de los libros y los ejes de las gráficas se escriben así.

   Se consigue con writing-mode más un giro de media vuelta. La
   propiedad que lo haría de una (sideways-lr) todavía la entiende un
   solo navegador, y estos reportes se abren en Chrome, en Edge y en
   el teléfono.

   Y se sube el tamaño y el peso: en gris claro a 9,5 px eran
   ilegibles de verdad. Ahora van a 11 px, en seminegrita y con el
   color del texto normal, no el apagado.
   =================================================================== */
.crono-fecha{position:absolute;bottom:2px;top:auto;display:flex;
  align-items:flex-start;justify-content:center;
  writing-mode:vertical-rl;text-orientation:mixed;transform:rotate(180deg);
  font-size:11px;font-weight:600;font-variant-numeric:tabular-nums;
  color:var(--txt);opacity:.78;
  letter-spacing:.2px;pointer-events:none;user-select:none}
.crono-fecha.finde{color:var(--warn);opacity:1;font-weight:700}
/* Las cuatro fechas del proyecto —inicio, entrega y los dos extremos
   del desmonte— se rotulan siempre, aunque el muestreo no las toque, y
   se resaltan: son las que se buscan al abrir un cronograma. La raya
   de su día también, para que la vista las enlace con el arranque de
   la barra sin tener que contar columnas. [08/09/2026] */
.crono-fecha.clave{color:var(--accent);opacity:1;font-weight:800}
.crono-gantt .gline.clave{border-left-style:solid;border-left-color:var(--accent);opacity:.55}

/* Sabados y domingos, sombreados. En obra no se trabaja igual, y verlo
   evita programar tres dias de trabajo sobre un puente. */
.crono-finde{position:absolute;top:0;bottom:0;background:var(--panel);opacity:.55;z-index:0}

/* La fila del proyecto: la de referencia, algo mas marcada que las
   actividades que van debajo. */
/* ===================================================================
   EL TÍTULO DE LA COLUMNA DE ACTIVIDADES            [08/09/2026]

   Separa la barra del proyecto de las actividades que cuelgan de
   ella. Sin él las dos cosas se leían como una sola lista y el nombre
   del proyecto parecía la primera actividad.

   La fila no lleva barra: es un rótulo, no un tramo de tiempo. Por
   eso su pista queda con el fondo de días y nada más.
   =================================================================== */
/* ===================================================================
   EL NÚMERO Y LAS FLECHAS DE CADA ACTIVIDAD         [08/09/2026]

   El número es la POSICIÓN en la lista —1, 2, 3…—, no el id de la
   base: una lista que salta del 3 al 7 se lee como si faltara algo.

   Las flechas van pegadas al número y no al final de la fila, porque
   es donde está el orden: se mira el número, se decide que va más
   arriba, y la flecha está justo ahí.

   Ancho fijo en las dos cosas para que los títulos empiecen todos en
   la misma columna. Sin eso, pasar del 9 al 10 corre el nombre de
   todas las filas de abajo un par de píxeles y la lista se ve torcida.
   =================================================================== */
/* El aviso que ocupa el sitio de una gráfica del Dashboard que no
   cargó. Antes ese sitio quedaba en blanco y no decía nada.
   [08/09/2026] */
.dash-pieza-mal{padding:26px 20px;text-align:center;color:var(--txt);
  display:flex;flex-direction:column;gap:8px;align-items:center;justify-content:center;
  min-height:140px}
.dash-pieza-mal .sub{font-size:12px;color:var(--muted);max-width:420px;line-height:1.45}

.crono-num{display:inline-block;min-width:20px;margin-right:5px;
  color:var(--muted);font-size:10.5px;font-weight:700;
  font-variant-numeric:tabular-nums;text-align:right;vertical-align:middle}
.crono-mover{display:inline-flex;flex-direction:column;gap:1px;
  margin-right:6px;vertical-align:middle}
/* «crono-mv» y no «crono-fl»: esta última ya es la clase de las FLECHAS
   DE DEPENDENCIA, que son trazos de un SVG y viven más abajo en esta
   misma hoja. Al reutilizar el nombre, estas reglas de botón —con su
   fondo y su borde— caían también sobre los trazos, y de paso el CRM
   contaba como flechas los botones de mover. [08/09/2026] */
.crono-mv{width:16px;height:11px;padding:0;line-height:9px;
  border:1px solid var(--line);border-radius:3px;
  background:var(--panel2);color:var(--muted);
  font-size:7px;cursor:pointer;display:block}
.crono-mv:hover:not(:disabled){border-color:var(--accent);color:var(--accent)}
/* Apagada, no escondida: esconderla movería el resto de la fila y la
   lista bailaría al reordenar. */
.crono-mv:disabled{opacity:.28;cursor:default}

.grow.crono-fila-tit{margin-top:6px}
.crono-tit-col{font-size:10.5px;font-weight:700;letter-spacing:.7px;
  color:var(--muted);text-transform:uppercase}
.crono-tit-n{display:inline-block;min-width:16px;padding:0 5px;margin-left:5px;
  border-radius:8px;background:var(--panel2);border:1px solid var(--line);
  color:var(--txt);font-size:10px;font-weight:700;letter-spacing:0}

/* La franja del desmonte en la fila del proyecto: mismo alto que la
   del proyecto para que se lean como una sola línea de tiempo, pero
   en ámbar, porque entregar y desmontar no son lo mismo. */
.gbar.crono-barra-desm{top:1px;height:24px;border-width:2px}

.crono-fila-proy{margin-bottom:10px;padding-bottom:8px;border-bottom:1px dashed var(--line)}
.crono-fila-proy .glabel b{font-weight:700;color:var(--txt)}
.gbar.crono-barra-proy{top:1px;height:24px;border-width:2px}

/* El contador de dias, dentro de la etiqueta y no flotando sobre la
   barra: es lo que se lee recorriendo la lista de arriba abajo al
   hacer seguimiento. */
/* ===================================================================
   LA ETIQUETA DE CADA ACTIVIDAD          [04/09/2026 · rehecho]

   QUE PASABA
     El nombre iba en un solo renglon con puntos suspensivos, asi que
     «Montaje de andamios en el tramo norte» se leia «Montaje de anda…».
     Y el contador iba debajo, en letra de nueve puntos y medio, dentro
     de una pildora del ancho de su texto. Resultado: de la unica
     columna que dice QUE hay que hacer, no se leia ni lo uno ni lo
     otro.

   COMO QUEDA
     Dos columnas dentro de la etiqueta: el TEXTO a la izquierda, que
     ya puede ocupar hasta tres renglones, y una CASILLA fija a la
     derecha con el numero grande y, debajo, a que se refiere -«para
     iniciar» o «restantes»-.

   POR QUE TRES RENGLONES Y NO LOS QUE HAGAN FALTA
     Con nombres largos, una actividad podria ocupar seis renglones y
     empujar su barra tan abajo que dejaria de alinearse con la vecina.
     Tres caben casi todos los nombres reales; los que no, siguen
     completos en el globo al posar el raton.

   POR QUE LA CASILLA ES DE ANCHO FIJO
     Porque asi todas las casillas quedan alineadas en columna y se
     pueden comparar de un vistazo bajando la vista. Con el ancho del
     texto, cada una empezaba en un sitio y habia que leerlas una a
     una.
   =================================================================== */
.gantt .glabel{white-space:normal;line-height:1.3;padding-right:8px;
  display:flex;align-items:center;gap:8px}
.crono-tit{flex:1 1 auto;min-width:0;
  display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;
  overflow:hidden;word-break:break-word;hyphens:auto}

/* ------------------------------------------------------------------
   EL NOMBRE ABRE LA EDICIÓN, Y TIENE QUE NOTARSE   [08/09/2026]

   Se puede pulsar el nombre de una actividad para editarla. Un texto
   que hace algo al pulsarlo y no lo aparenta no lo pulsa nadie: la
   función existiría sin que nadie la encontrara.

   Se marca con lo mínimo que se entiende sin explicación —la mano del
   cursor y un subrayado al pasar por encima— y no con un color de
   enlace permanente: en una lista de cuarenta actividades, cuarenta
   textos de color cansan y le quitan importancia a los avisos que sí
   deben destacar.

   Solo dentro de una fila con `data-act`: el título del PROYECTO usa
   esta misma clase y ese no se edita desde aquí.
   ------------------------------------------------------------------ */
[data-act] .crono-tit{cursor:pointer}
[data-act] .crono-tit:hover{text-decoration:underline;text-underline-offset:2px}
/* En pantalla táctil no hay «pasar por encima»: el subrayado no
   llegaría nunca, así que la pista es el propio tamaño de la zona. */
@media (hover:none){ [data-act] .crono-tit:hover{text-decoration:none} }

/* La casilla del contador. */
.crono-cont{flex:0 0 58px;display:flex;flex-direction:column;align-items:center;
  justify-content:center;gap:1px;padding:4px 2px;border-radius:9px;
  background:var(--panel);border:1px solid var(--line);color:var(--muted);
  text-align:center;line-height:1.05}
.crono-cont b{font-size:15px;font-weight:800;color:var(--txt);
  font-variant-numeric:tabular-nums;letter-spacing:-.3px}
.crono-cont b small{font-size:9.5px;font-weight:700;margin-left:1px;opacity:.75}
.crono-cont i{font-style:normal;font-size:8.5px;font-weight:700;
  letter-spacing:.3px;text-transform:uppercase;opacity:.8}

/* Los tres estados se distinguen por color, no solo por el texto: al
   recorrer la lista se ve donde hay que mirar antes de leer nada. */
.crono-cont.pre{border-color:var(--line)}
.crono-cont.pre b{color:var(--muted)}
.crono-cont.urg{border-color:var(--warn);background:var(--warn-suave)}
.crono-cont.urg b,.crono-cont.urg i{color:var(--warn)}
.crono-cont.fin{opacity:.55}
.crono-cont.fin b{color:var(--ok)}

/* Ya no hace falta ningún respaldo: rgba() lo entiende todo lo que
   sepa dibujar una página. Este bloque se queda vacío a propósito
   —quitarlo entero obligaría a recontar llaves— y no aplica nada. */
@supports (background:rgba(0,0,0,.1)){
  .crono-cont.urg{background:var(--warn-suave)}
}

.crono-vacio{padding:16px 4px;font-size:12.5px;color:var(--muted);font-style:italic}

/* La etiqueta necesita mas sitio ahora que lleva DOS COLUMNAS: el
   nombre a varios renglones y la casilla del contador. 190 px se
   repartian entre las dos y el nombre volvia a quedarse sin espacio.
   [04/09/2026] */
.crono-gantt .glabel{width:250px;flex:0 0 250px}
@media (max-width:760px){
  .crono-gantt .glabel{width:170px;flex:0 0 170px;font-size:11px;gap:5px}
  .crono-cont{flex:0 0 48px;padding:3px 1px}
  .crono-cont b{font-size:13px}
  .crono-tit{-webkit-line-clamp:2}
  .crono-ghead .gtrack{height:46px}
  .crono-fecha{font-size:8.5px}
}

/* ===================================================================
   LAS GUIAS QUE SIGUEN AL RATON                    [04/09/2026]

   En cuarenta columnas, ir con la vista de una barra hasta su fecha es
   justo donde uno se equivoca de columna. La raya vertical dice QUE
   DIA, la horizontal dice QUE ACTIVIDAD, y la etiqueta canta la fecha
   exacta para no tener que leerla de pie.

   pointer-events:none en todo el bloque: si las guias recibieran el
   raton se lo quitarian a las barras y a los tres puntos de cada
   actividad, y nada de eso se podria pulsar.
   =================================================================== */
.crono-gantt{position:relative}
.crono-cruz{position:absolute;inset:0;pointer-events:none;z-index:6;
  opacity:0;transition:opacity .12s ease}
.crono-cruz.on{opacity:1}
.crono-cruz .cx-v{position:absolute;top:0;bottom:0;width:0;
  border-left:1px dashed var(--accent);opacity:.85}
.crono-cruz .cx-h{position:absolute;left:0;right:0;height:0;
  border-top:1px dashed var(--accent);opacity:.55}
.crono-cruz .cx-fecha{position:absolute;top:-2px;transform:translateX(-50%);
  font-size:10px;font-weight:700;font-variant-numeric:tabular-nums;
  color:#fff;background:var(--accent2);padding:1px 6px;border-radius:8px;
  white-space:nowrap;box-shadow:0 2px 6px rgba(0,0,0,.35)}
/* Pegada al borde derecho se ancla al otro lado para no salirse. */
.crono-cruz .cx-fecha.der{transform:translateX(50%)}

/* ===================================================================
   LA FILA POR LA QUE SE PASA, RESALTADA DE VERDAD
   [04/09/2026 · reforzado]

   Estaba puesto pero se notaba tan poco -un borde de un pixel y la
   letra un punto mas gruesa- que no cumplia su unica funcion: decir
   QUE actividad corresponde a la fecha que se esta mirando.

   Ahora se resaltan las dos mitades a la vez y con el mismo color: la
   ETIQUETA de la izquierda -que es lo que se pidio ver marcado- y la
   PISTA de la derecha. Al pasar por una fecha, el ojo tiene los dos
   extremos de la fila encendidos y no hay que seguir nada con el dedo.

   Se usa un fondo y una barra lateral, no solo un borde: un borde de
   un pixel a lo ancho de 1200 px es invisible en la practica.
   =================================================================== */
.crono-gantt .grow.crono-hover .gtrack{
  box-shadow:inset 0 0 0 1.5px var(--accent);
  background:var(--acento-tenue)}
.crono-gantt .grow.crono-hover .glabel{
  color:var(--txt);font-weight:700;
  background:var(--acento-suave);
  border-left:3px solid var(--accent);
  border-radius:6px 0 0 6px;
  margin-left:-3px;padding-left:8px}
.crono-gantt .grow.crono-hover .crono-cont{
  border-color:var(--accent);color:var(--txt)}

/* El botón de descarga se va al extremo derecho de su fila: crear una
   actividad y descargar la programación son cosas distintas y pegadas
   se pulsa una por otra. [04/09/2026] */
.crono-pdf-btn{margin-left:auto;font-weight:700;letter-spacing:.3px}
.crono-pdf-btn svg{flex:none}
.crono-pdf-btn:disabled{opacity:.6}

/* El aviso de que a la base le falta una migración. En ámbar y no en
   rojo: no hay nada roto, hay algo que todavía no está instalado, y el
   resto del cronograma funciona. [04/09/2026] */
.crono-falta{
  margin:10px 0 2px;padding:10px 13px;border-radius:10px;
  background:var(--warn-suave);border:1px solid var(--warn);
  color:var(--txt);font-size:12.5px;line-height:1.45}

/* ===================================================================
   EL AVANCE DE CADA ACTIVIDAD                      [04/09/2026]

   La barra entera es la duración; lo relleno, a plena intensidad, es
   lo avanzado. El mismo tono en dos fuerzas y no dos colores: en el
   diagrama ya hay color para el proyecto, para las actividades y para
   las flechas, y un cuarto obligaría a poner una leyenda.

   El relleno se anima al cambiar: al mover la barra deslizante de la
   ventana se ve crecer en el diagrama, que es lo que confirma que se
   está tocando la actividad correcta.
   =================================================================== */
.gbar.con-avance .gfill{transition:width .18s ease}
/* La parte no avanzada se ve pálida a través del fondo de la barra,
   que ya venía con el color al 13 %. No hace falta pintarla aparte. */

/* El porcentaje, escrito sobre la barra. Va a la derecha para no
   taparse con las iniciales del personal, que van a la izquierda. */
.gav{
  position:absolute;right:5px;top:50%;transform:translateY(-50%);
  font-size:9.5px;font-weight:800;font-variant-numeric:tabular-nums;
  color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.75);
  pointer-events:none;z-index:2;letter-spacing:.2px}
/* En barras muy cortas el número no cabe y estorba más que ayuda; el
   globo al posar el ratón lo sigue diciendo. */
.gbar{container-type:inline-size}
@container (max-width: 44px){ .gav{display:none} }

/* Una barra que se puede tocar tiene que parecerlo. */
.gbar-editable{cursor:pointer}
.gbar-editable:hover{filter:brightness(1.18)}
.gbar-editable:hover .gav{text-shadow:0 1px 3px rgba(0,0,0,.9)}

/* ===================================================================
   LA VENTANA DEL AVANCE                            [04/09/2026]
   Tres formas de poner el número —saltos, barra deslizante y casilla—
   porque se usa con el ratón en la oficina y con el dedo en obra.
   =================================================================== */
.crono-av-num{display:flex;align-items:baseline;justify-content:center;
  gap:3px;margin:18px 0 6px}
.crono-av-num b{font-size:52px;font-weight:800;line-height:1;
  color:var(--accent);font-variant-numeric:tabular-nums}
.crono-av-num i{font-style:normal;font-size:22px;font-weight:700;color:var(--muted)}

.crono-av-rango{width:100%;margin:6px 0 14px;accent-color:var(--accent)}

.crono-av-saltos{display:grid;grid-template-columns:repeat(5,1fr);gap:6px}
.crono-av-saltos .btn{padding:7px 0;font-size:12px;font-weight:600}

.crono-av-exacto{display:flex;align-items:center;gap:10px;margin-top:14px;
  font-size:12.5px;color:var(--muted)}
.crono-av-exacto input{width:92px;font-size:15px;font-weight:700;padding:7px 10px;
  border-radius:9px;background:var(--panel);color:var(--txt);
  border:1px solid var(--line);text-align:center}

.crono-av-aviso{min-height:16px;margin-top:8px;font-size:12px;font-weight:600;color:transparent}
.crono-av-aviso.mal{color:var(--bad)}

/* ===================================================================
   LAS FLECHAS DE DEPENDENCIA                       [04/09/2026]

   Van en un lienzo SVG por encima del diagrama pero por debajo de la
   línea de HOY y de las guías del ratón: son estructura, no lo que se
   está mirando en este momento.

   pointer-events:none en todo el lienzo. Si recibiera el ratón se lo
   quitaría a las barras y a los tres puntos de cada actividad, y nada
   de eso se podría pulsar. Es el mismo cuidado que con las guías.

   En escuadra y del color de acento, más finas que las barras: tienen
   que leerse como una relación entre dos cosas, no competir con las
   cosas mismas.
   =================================================================== */
.crono-flechas{position:absolute;left:0;top:0;z-index:4;pointer-events:none;
  overflow:visible}
.crono-fl{fill:none;stroke:var(--accent);stroke-width:1.6;opacity:.85;
  stroke-linecap:round;stroke-linejoin:round}
.crono-fl-punta{fill:var(--accent);opacity:.95}
/* El eslabón delante del nombre: avisa de que esta actividad espera a
   otra aunque su flecha quede lejos en un diagrama largo. */
.crono-eslabon{font-size:10px;opacity:.75;color:var(--accent)}
/* ===================================================================
   CUÁNTAS PERSONAS NECESITA LA ACTIVIDAD          [06/09/2026]

   Va discreto: al lado del título, en el mismo tono apagado que el
   resto de las marcas de la fila. No compite con el nombre de la
   actividad, que es lo que se lee primero, ni con el contador de días.

   Los colores salen de las variables del tema, así que se comporta
   igual en claro y en oscuro. Regla de la casa: nada de colores
   escritos a mano en un chip.
   =================================================================== */
.crono-cuadrilla{
  font-size:10.5px;opacity:.85;color:var(--muted);
  background:var(--panel-2,var(--panel));border:1px solid var(--line);
  border-radius:9px;padding:1px 6px;margin-left:6px;white-space:nowrap;
  display:inline-block;vertical-align:middle
}

/* ===================================================================
   ¿DEPENDE DE OTRA? — dentro del formulario     [04/09/2026]
   La casilla siempre a la vista y la lista solo cuando se marca: la
   mayoría de actividades no dependen de ninguna, y un desplegable
   desplegado en cada alta invita a elegir algo por inercia.
   =================================================================== */
/* El resumen dentro del formulario: dice qué se decidió y deja
   cambiarlo, sin ocupar el sitio que ocupaba la casilla. */
.crono-dep-resumen{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  margin-top:12px;padding:9px 12px;border-radius:10px;
  background:var(--panel);border:1px solid var(--line);
  font-size:12.5px;color:var(--muted)}
.crono-dep-resumen #crono-dep-txt{flex:1;min-width:0}
.crono-dep-resumen #crono-dep-txt.ok{color:var(--ok);font-weight:600}
.crono-dep-resumen .btn{padding:3px 10px;font-size:11.5px;flex:none}

/* Las dos respuestas de la ventana: «No» primero y destacada, porque
   es la de la mayoría de actividades. */
.crono-dep-opc{display:flex;gap:10px;flex-wrap:wrap;margin:16px 0 4px}
.crono-dep-opc .btn{flex:1 1 200px;padding:12px 14px;font-size:14px;font-weight:600}

.crono-dep-caja{margin-top:10px}
.crono-dep-caja label{display:flex;flex-direction:column;gap:4px;
  font-size:11.5px;color:var(--muted)}
.crono-dep-caja select{font-size:13.5px;padding:8px 10px;border-radius:9px;
  background:var(--panel2);color:var(--txt);border:1px solid var(--line);width:100%}
.crono-dep-caja select:disabled{opacity:.6}
.crono-dep-nota{margin-top:6px;font-size:11.5px;color:var(--muted);line-height:1.35}
.crono-dep-nota.ok{color:var(--ok);font-weight:600}
.crono-dep-nota.mal{color:var(--bad);font-weight:600}

/* ===================================================================
   OBSERVACIONES DE LA ACTIVIDAD                    [04/09/2026]
   =================================================================== */
.crono-obs{display:block;margin-top:12px;font-size:12.5px;color:var(--muted)}
.crono-obs textarea{display:block;width:100%;margin-top:4px;resize:vertical;
  font-size:13.5px;line-height:1.4;padding:9px 11px;border-radius:10px;
  background:var(--panel);color:var(--txt);border:1px solid var(--line)}
.crono-obs small{display:block;margin-top:4px;font-size:11px;opacity:.85}

/* ===================================================================
   LA LINEA DE HOY, ENTERA                          [04/09/2026]
   Una sola raya sobre todo el diagrama, colocada por medida desde el
   guion. Antes se dibujaba dentro de cada pista y entre fila y fila
   quedaban seis pixeles de aire: salian trocitos, no una linea.
   =================================================================== */
.crono-hoy{position:absolute;top:0;bottom:0;width:0;z-index:5;
  border-left:2px solid var(--accent);pointer-events:none;
  box-shadow:0 0 8px 1px var(--accent);animation:blinkhoy 1.8s ease-in-out infinite}
.crono-hoy b{position:absolute;top:-1px;left:0;transform:translateX(-50%);
  font-size:9px;font-weight:800;letter-spacing:.7px;color:#fff;
  background:var(--accent2);padding:1px 6px;border-radius:8px}
/* Dentro de las pistas ya no hace falta la marca por fila. */
.crono-gantt .gtoday,.crono-gantt .gtoday-lbl{display:none}

/* ===================================================================
   EL LATIDO DEL BOTON DE CRONOGRAMA                 [04/09/2026]

   Late en su propio amarillo cuando esa obra tiene actividades en
   curso, algo que vence o la entrega encima. Es una invitacion a
   entrar a mirar, no un aviso que haya que leer.

   POR QUE LATE ASI Y NO PARPADEANDO
     Un parpadeo -aparecer y desaparecer- es lo que hace un error y
     cansa la vista en un panel que se tiene abierto toda la jornada.
     Un latido es un halo que crece y se va: se ve por el rabillo del
     ojo, el texto del boton nunca deja de leerse y no marea.
     Dos pulsos seguidos y una pausa, como un corazon de verdad.

   RESPETA A QUIEN PIDE QUIETO
     Con «reducir movimiento» activado en el sistema, no se mueve: se
     queda el halo fijo. La alarma sigue estando, sin animacion.
   =================================================================== */
@keyframes cronoLatido{
  0%   {box-shadow:0 0 0 0 rgba(232,200,106,.55)}
  14%  {box-shadow:0 0 0 6px rgba(232,200,106,0)}
  24%  {box-shadow:0 0 0 0 rgba(232,200,106,.45)}
  38%  {box-shadow:0 0 0 7px rgba(232,200,106,0)}
  39%,100%{box-shadow:0 0 0 0 rgba(232,200,106,0)}
}
.btn-crono.late{animation:cronoLatido 2.2s ease-out infinite}
@media (prefers-reduced-motion:reduce){
  .btn-crono.late{animation:none;box-shadow:0 0 0 3px rgba(232,200,106,.35)}
  .crono-hoy{animation:none}
}

/* ===================================================================
   EL AVISO DE «GUARDADA» DENTRO DEL PANEL          [04/09/2026]
   El panel ya no se cierra al guardar, asi que hace falta algo que
   diga que si se guardo. Se borra solo a los pocos segundos: un aviso
   que se queda deja de leerse como respuesta a lo ultimo que se hizo.
   =================================================================== */
/* ===================================================================
   QUÉ PROYECTOS VE CADA USUARIO                    [04/09/2026]

   Va dentro de la ventana de permisos, debajo de la tabla de módulos:
   es la misma decisión -qué alcanza a ver esta persona- y separarla en
   otra pantalla obligaría a acordarse de pasar por las dos.

   Se separa con una línea arriba para que se lea como un bloque
   propio y no como una fila más de la tabla de permisos.
   =================================================================== */
.permu-proy{border-top:1px dashed var(--line);margin-top:14px;padding-top:4px}
.permu-proy-acc{display:flex;gap:8px;margin:8px 0}
.permu-proy-acc .btn{padding:3px 10px;font-size:11.5px}
/* Dos columnas cuando caben: con quince obras, una sola columna
   obligaba a desplazar la ventana entera para ver el final. */
.permu-proy-lista{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));
  gap:4px 12px;max-height:230px;overflow:auto;padding:2px}
.permu-proy-item{display:flex;align-items:center;gap:7px;min-width:0;
  padding:4px 6px;border-radius:7px;font-size:12.5px;color:var(--txt)}
.permu-proy-item:hover{background:var(--panel2)}
.permu-proy-item span{flex:1;min-width:0;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap}
.permu-proy-item small{flex:0 0 auto;font-size:10px;color:var(--muted)}
/* Cuando hay restricción, el subtítulo se marca: es un estado que hay
   que notar sin leerlo entero. */
.permu-proy-limitado{color:var(--warn) !important;font-weight:600}

/* ===================================================================
   ROLES Y PERMISOS: LOS BOTONES EN COLUMNA         [04/09/2026]

   Cada renglon es una rejilla de cuatro columnas: el nombre del rol,
   que se estira, y tres columnas fijas -una por boton-. Asi los
   botones caen siempre en la misma vertical, mida lo que mida el
   nombre del rol, y los roles que no se pueden eliminar dejan su
   tercera columna vacia en vez de correr las otras dos.

   Se resuelve con rejilla y no con margenes calculados porque una
   rejilla no hay que volver a ajustarla cuando manana se agregue un
   rol con un nombre mas largo.
   =================================================================== */
.rol-fila{display:grid;grid-template-columns:1fr auto auto auto;
  align-items:center;gap:8px;margin-bottom:6px}
.rol-nom{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rol-nom small{color:var(--muted)}
/* Ancho minimo comun: «Permisos» y «Renombrar» no miden lo mismo, y sin
   esto cada columna se ajustaria a su propio texto. */
.rol-b{padding:3px 8px;min-width:92px;text-align:center;justify-content:center}
.rol-b.peligro{border-color:#ef4444;color:#ef4444}
.rol-hueco{display:block;min-width:92px;height:1px}
@media (max-width:560px){
  .rol-fila{grid-template-columns:1fr;gap:6px}
  .rol-b,.rol-hueco{min-width:0;width:100%}
  .rol-hueco{display:none}
}

/* ===================================================================
   EL SELECTOR DE CALIDAD DE LAS FOTOS              [04/09/2026]
   Va junto a «+ Agregar foto» porque es ahi donde se decide: se ven
   las fotos que hay, el peso y las hojas, y se ajusta en el sitio.
   =================================================================== */
.rep-cal{display:inline-flex;align-items:center;gap:6px;
  font-size:11.5px;font-weight:600;color:var(--muted)}
.rep-cal select{font-size:11.5px;padding:4px 8px;border-radius:8px;
  background:var(--panel);color:var(--txt);border:1px solid var(--line)}
.rep-cal select:disabled{opacity:.55}

.crono-aviso{min-height:16px;font-size:12.5px;font-weight:600;color:transparent}
.crono-aviso.ok{color:var(--ok)}
.crono-aviso.mal{color:var(--bad)}

/* ===================================================================
   LETRA MAS GRANDE EN EL CRONOGRAMA                [04/09/2026]

   Se pidio subir el tamaño para poder leer. Se sube donde de verdad
   cuesta -nombres de actividad, contadores, fechas de la escala y los
   campos del formulario- y no de forma global: agrandar todo a la vez
   descuadra la rejilla de las tres fechas y devuelve el problema de
   que la escala no cabe.

   Las fechas de pie suben de 9,5 a 11 px. Caben porque la ventana
   paso de 1040 a 1280 px: hay un 23 % mas de sitio por dia.
   =================================================================== */
.crono-modal .gantt{font-size:13px}
.crono-modal .crono-gantt .glabel{font-size:13px;line-height:1.3}
.crono-modal .crono-tit{font-size:13px;font-weight:600}
.crono-modal .crono-cont b{font-size:17px}
.crono-modal .crono-cont i{font-size:9px}
.crono-modal .crono-fecha{font-size:11px;letter-spacing:.2px}
.crono-modal .crono-ghead .gtrack{height:58px}
.crono-modal .gtxt{font-size:11px}
.crono-modal .crono-fechas label{font-size:12.5px}
.crono-modal .crono-fechas input,
.crono-modal .crono-form input,
.crono-modal .crono-form select{font-size:14px;padding:8px 10px}
.crono-modal .crono-form label{font-size:12.5px}
.crono-modal .crono-form .mh{font-size:14px}
.crono-modal .crono-personal label{font-size:12.5px}
.crono-modal .crono-vacio{font-size:13.5px}
.crono-modal .crono-f-aviso{font-size:12.5px}
/* La etiqueta crece con la letra: si no, los nombres de dos renglones
   empiezan a cortarse justo despues de agrandarlos. */
.crono-modal .crono-gantt .glabel{width:300px;flex:0 0 300px}
@media (max-width:900px){
  .crono-modal .crono-gantt .glabel{width:185px;flex:0 0 185px;font-size:12px}
  .crono-modal .crono-fecha{font-size:9.5px}
  .crono-modal .crono-ghead .gtrack{height:50px}
}

/* ===================================================================
   MEJORAS DE LECTURA                              [05/09/2026]
   Cuatro cosas que se notan a diario y que no cambian ningún dato:
   la leyenda del cronograma, la marca de terminado, el foco del
   teclado y la alineación de las cifras de dinero.
   =================================================================== */

/* --- 1. La leyenda del cronograma ---------------------------------
   Explica los contadores de la izquierda, que mezclan días, horas, un
   visto y un marco naranja sin decir qué significa cada cosa. Va
   debajo del diagrama y en letra pequeña: quien ya lo sabe no la lee.
   Los colores son los MISMOS que usan los contadores, así que la
   leyenda y lo que explica no pueden separarse por descuido. */
.crono-leyenda{
  display:flex; flex-wrap:wrap; gap:6px 16px; align-items:center;
  margin:10px 2px 0; padding-top:9px;
  border-top:1px dashed var(--line);
  font-size:11.5px; color:var(--muted); line-height:1.5;
}
.crono-leyenda b{color:var(--txt); font-weight:700}
.crono-leyenda span{display:inline-flex; align-items:center; gap:5px}
/* El cuadradito de color delante de cada caso: es lo que ata la
   palabra al contador que se ve en la fila. */
.crono-leyenda .cl-pre::before,
.crono-leyenda .cl-urg::before,
.crono-leyenda .cl-fin::before{
  content:""; width:9px; height:9px; border-radius:2px;
  border:1.5px solid currentColor; flex:0 0 9px;
}
.crono-leyenda .cl-pre{color:var(--muted)}
.crono-leyenda .cl-urg{color:var(--warn)}
.crono-leyenda .cl-fin{color:var(--ok)}
.crono-leyenda .cl-fin::before{background:currentColor}

/* --- 2. Lo terminado se distingue de lo casi terminado -------------
   Al 100 % la barra era idéntica a la del 90 %: solo cambiaba la
   cifra escrita dentro. Ahora lleva un visto delante y un borde
   entero, para que se lea de un vistazo recorriendo la columna. */
.gbar.gbar-lleno{border-style:solid; border-width:1.5px}
.gbar.gbar-lleno .gav{font-weight:700; letter-spacing:.2px}

/* --- 3. Las barras muy cortas siguen siendo pulsables --------------
   Una actividad de tres horas dentro de un mes ocupaba unos pocos
   píxeles: imposible de acertar con el ratón para editarle el avance.
   El mínimo sube lo justo para que quepa el dedo, sin llegar a
   mentir sobre la duración. */
.gbar{min-width:22px}

/* --- 4. El foco del teclado, visible ------------------------------
   Hasta hoy, recorrer el CRM con el tabulador era ir a ciegas: no se
   veía dónde estaba uno. Eso deja fuera a quien no puede usar el
   ratón, y estorba a todos los demás cuando se les cae el ratón o
   trabajan con las manos ocupadas.

   Se usa «:focus-visible» y no «:focus» a propósito: así el marco
   aparece al navegar con teclado y NO al hacer clic, que es cuando
   molestaría sin aportar nada. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible,
.btn:focus-visible,
.nav a:focus-visible{
  outline:2px solid var(--accent);
  outline-offset:2px;
  border-radius:6px;
}
/* Dentro del menú lateral el marco se mete hacia adentro: en el borde
   quedaría cortado por el filo de la barra. */
.nav a:focus-visible{outline-offset:-3px}

/* --- 5. Las cifras de dinero, en columna ---------------------------
   Los montos se escribían con la letra normal, donde el «1» es más
   estrecho que el «8». En una columna de valores eso desalinea las
   comas y obliga a leer cifra por cifra en vez de comparar de un
   vistazo. «tabular-nums» hace que todos los dígitos midan igual.
   No cambia la fuente ni el tamaño: solo el ancho de los números. */
.p26-r b, .p26-money, .iva-fila b, .cmp b,
td.num, .kpi b, .kpi .val,
.crono-cont b{
  font-variant-numeric:tabular-nums;
  font-feature-settings:"tnum" 1;
}

/* --- 6. Modo claro: el botón principal al pasar el ratón -----------
   El botón usa «--accent2» de fondo con letra blanca, que en claro da
   buen contraste. Pero al pasar el ratón cambiaba a «--accent», un
   dorado más claro, y ahí la letra blanca se quedaba en 3,4:1: por
   debajo del mínimo legible. El estado de reposo se leía bien y el de
   paso del ratón no, que es justo cuando se está a punto de pulsar.

   En claro se oscurece al pasar el ratón en vez de aclararse. En
   oscuro se deja como está, que ahí sí funciona. */
html[data-theme="light"] .btn:hover{background:#6f5206}
html[data-theme="light"] .btn:active{background:#5a4205}

/* ===================================================================
   EL DASHBOARD QUE CADA PERSONA SE ARMA            [06/09/2026]

   Reglas de la casa que se respetan aquí:
     · ningún color escrito a mano: todo sale de las variables del
       tema, así que funciona igual en claro y en oscuro;
     · los bordes de tarjeta con var(--line), como el resto;
     · el texto secundario con var(--muted).
   =================================================================== */

/* ---- La barra de arriba: aviso a la izquierda, botón a la derecha ---- */
.dash-barra{display:flex;align-items:center;justify-content:space-between;
  gap:12px;margin-bottom:14px;flex-wrap:wrap}
.dash-aviso{font-size:12.5px;color:var(--muted);background:var(--panel2);
  border:1px solid var(--line);border-radius:8px;padding:6px 11px}
.dash-aviso.malo{color:var(--txt);border-color:var(--accent2)}

/* ---- El panel de «qué puedo agregar» ---- */
.dash-panel{background:var(--panel);border:1px solid var(--line);
  border-radius:12px;padding:16px 18px;margin-bottom:16px}
.dash-panel-tit{font-weight:600;font-size:14px;margin-bottom:4px;color:var(--txt)}
.dash-cat-tit{font-size:11px;text-transform:uppercase;letter-spacing:.6px;
  color:var(--muted);margin:12px 0 8px}
.dash-cat-grid{display:grid;gap:8px;
  grid-template-columns:repeat(auto-fill,minmax(210px,1fr))}
.dash-cat-item{display:flex;align-items:center;gap:9px;width:100%;text-align:left;
  background:var(--panel2);border:1px solid var(--line);border-radius:9px;
  padding:9px 11px;color:var(--txt);font-size:13px;cursor:pointer;
  transition:border-color .15s,transform .12s}
.dash-cat-item:hover:not(:disabled){border-color:var(--accent);transform:translateY(-1px)}
.dash-cat-item:disabled{opacity:.55;cursor:default}
.dash-cat-item .ic{width:20px;text-align:center;color:var(--accent)}
.dash-cat-item .lb{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dash-cat-item .mas{color:var(--muted);font-weight:600}

/* ---- El lienzo donde caen las piezas ---- */
.dash-lienzo{display:block;min-height:120px;border-radius:12px;
  transition:background .15s,box-shadow .15s}
/* Mientras se arrastra un módulo por encima, se marca dónde soltar.
   Sin esta señal nadie sabe que el sitio admite lo que trae. */
.dash-lienzo.encima{box-shadow:inset 0 0 0 2px var(--accent);
  background:color-mix(in srgb, var(--accent) 8%, transparent)}
body.dash-arrastrando .dash-lienzo{box-shadow:inset 0 0 0 1px var(--line)}

.dash-pieza{position:relative;margin-bottom:16px}

/* ---- Cuando está vacío, se dice qué hacer ---- */
.dash-vacio{border:1px dashed var(--line);border-radius:12px;
  padding:38px 24px;text-align:center;color:var(--muted)}
.dash-vacio-ic{font-size:30px;opacity:.5;margin-bottom:8px;color:var(--accent)}
.dash-vacio h3{margin:0 0 8px;font-size:16px;color:var(--txt)}
.dash-vacio p{margin:0 auto 6px;max-width:52ch;font-size:13px;line-height:1.5}
.dash-vacio p.sub{font-size:12px;opacity:.85}

/* ---- Las herramientas de cada pieza, solo en modo personalizar ---- */
.dash-tools{display:flex;align-items:center;gap:6px;margin-bottom:6px;
  background:var(--panel2);border:1px solid var(--line);
  border-radius:8px 8px 0 0;padding:5px 9px}
.dash-tools-tit{flex:1;font-size:12px;color:var(--muted);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dash-tools button{background:transparent;border:1px solid var(--line);
  color:var(--txt);border-radius:6px;width:26px;height:24px;font-size:11px;
  cursor:pointer;line-height:1}
.dash-tools button:hover{border-color:var(--accent)}
.dash-tools button.quitar:hover{border-color:var(--accent2);color:var(--accent2)}

/* ---- Los accesos directos ---- */
.dash-acceso-btn{display:flex;align-items:center;gap:12px;width:100%;
  background:var(--panel);border:1px solid var(--line);border-radius:12px;
  padding:16px 18px;color:var(--txt);font-size:15px;cursor:pointer;text-align:left;
  transition:border-color .15s,transform .12s}
.dash-acceso-btn:hover{border-color:var(--accent);transform:translateY(-1px)}
.dash-acceso-ic{font-size:20px;color:var(--accent);width:26px;text-align:center}
.dash-acceso-lb{font-weight:600}

/* ---- El «+» de cada módulo del menú ----
   Aparece al pasar el ratón. En pantalla táctil no hay «pasar el
   ratón», así que allí se deja siempre visible: es el único camino
   para agregar sin arrastrar. */
#nav a[data-v]{position:relative}
.nav-mas{position:absolute;right:6px;top:50%;transform:translateY(-50%);
  width:22px;height:22px;line-height:1;border-radius:6px;
  background:var(--panel2);border:1px solid var(--line);color:var(--muted);
  font-size:14px;cursor:pointer;display:none;padding:0}
#nav a[data-v]:hover .nav-mas{display:block}
.nav-mas:hover{border-color:var(--accent);color:var(--accent)}
#nav a[data-v].en-dash .nav-mas{color:var(--accent);border-color:var(--accent)}
@media (hover:none){ .nav-mas{display:block} }

/* Una tarjeta que hoy no tiene qué mostrar lo dice, en vez de dejar un
   hueco blanco que se lee como una gráfica rota. [06/09/2026] */
.dash-sin-datos{border:1px dashed var(--line);border-radius:10px;
  padding:14px 16px;margin-bottom:16px;color:var(--muted);font-size:12.5px}

/* Las gráficas que vienen de Facturación se incrustan en su propio
   marco: son de otra aplicación y traen su hoja de estilos. El fondo se
   deja transparente para que no corte con el tema del CRM. [06/09/2026] */
.dash-iframe{display:block;background:transparent}
.dash-marco{overflow:hidden}

/* ===================================================================
   LOS DOS CAMINOS DEL PIE DE LA ENTRADA           [06/09/2026]

   «¿Olvidó su contraseña?» es para quien YA tiene cuenta.
   «Solicite su ingreso» es para quien no la tiene.

   Son cosas distintas y por eso no se ven igual: la primera es un
   enlace discreto; la segunda, un botón de contorno. Puestos con el
   mismo peso, quien llega nuevo prueba primero el de recuperar clave
   —que no le va a servir— y se va pensando que el sistema falla.
   =================================================================== */
.login-pies{display:flex;flex-direction:column;align-items:center;gap:12px;margin-top:14px}
.login-enlace{font-size:12px;cursor:pointer;color:var(--accent,#B8860B);font-weight:600}
.login-enlace:hover{text-decoration:underline}
.login-registro{
  background:transparent;border:1px solid #d7dee7;border-radius:9px;
  padding:9px 16px;font-size:12.5px;font-weight:600;color:#5c6b7a;
  cursor:pointer;transition:border-color .15s,color .15s
}
.login-registro:hover{border-color:var(--accent,#B8860B);color:var(--accent,#B8860B)}

/* ===================================================================
   SOLICITAR INGRESO                               [06/09/2026]

   Esta ventana la ve alguien que TODAVÍA NO ha entrado, así que no
   puede depender del tema claro/oscuro que se guarda por usuario: se
   deja siempre en claro, igual que el panel de entrada al que
   pertenece. Es la única pantalla del CRM con esa excepción, y es a
   propósito.
   =================================================================== */
/* ===================================================================
   LA VENTANA DE REGISTRO CABE EN CUALQUIER PANTALLA  [07/09/2026]

   POR QUÉ «flex-start» Y NO «center»
     Con «align-items:center», una tarjeta más alta que la pantalla se
     recorta por ARRIBA y a esa parte NO se puede llegar desplazando:
     el navegador no deja desplazarse hacia el desbordamiento de un
     elemento centrado con flex. El formulario quedaba inservible en
     el teléfono, y peor en horizontal, donde la pantalla es más baja.

     Se centra con «margin:auto» sobre la tarjeta, que hace lo mismo
     visualmente cuando cabe y no rompe nada cuando no cabe.

   POR QUÉ «100dvh» Y NO «100vh»
     En el móvil, «vh» cuenta la pantalla SIN la barra del navegador,
     que aparece y desaparece al desplazarse. Con vh, el pie de la
     ventana queda debajo de esa barra justo cuando se necesita pulsar
     ENVIAR. «dvh» sigue el alto real. Se deja vh de respaldo para los
     navegadores viejos, que lo entienden.
   =================================================================== */
.reg-overlay{position:fixed;inset:0;z-index:10000;display:flex;align-items:flex-start;
  justify-content:center;padding:16px;background:rgba(10,13,16,.72);
  overflow-y:auto;-webkit-overflow-scrolling:touch}
/* «display:flex» le gana a «hidden», así que la ventana salía abierta
   nada más cargar. Hay que decirlo explícitamente. Es el tropiezo
   clásico de cualquier caja que se muestre con flex o grid.
   [06/09/2026] */
.reg-overlay[hidden]{display:none}
.reg-card{position:relative;background:#fff;color:#14181C;border-radius:16px;
  padding:24px 26px 20px;width:560px;max-width:100%;margin:auto;
  display:flex;flex-direction:column;
  max-height:calc(100vh - 32px);max-height:calc(100dvh - 32px);
  box-shadow:0 30px 80px rgba(0,0,0,.5);font:14px/1.5 -apple-system,Segoe UI,system-ui,sans-serif}
/* El cuerpo es lo único que se desplaza. El título queda arriba y los
   botones abajo, siempre a la vista: en un formulario largo, tener que
   bajar hasta el final para encontrar ENVIAR es la mitad del problema.
   El «padding-right» deja sitio a la barra de desplazamiento para que
   no se monte sobre los campos. */
.reg-cuerpo{flex:1 1 auto;overflow-y:auto;-webkit-overflow-scrolling:touch;
  padding-right:4px;margin-right:-4px;min-height:0}
.reg-x{position:absolute;right:14px;top:12px;background:transparent;border:0;
  font-size:17px;color:#98A2AB;cursor:pointer;line-height:1;padding:4px 6px}
.reg-x:hover{color:#14181C}
.reg-tit{margin:0 0 6px;font-size:26px;font-weight:800;letter-spacing:-.3px}
.reg-sub{margin:0 0 18px;font-size:13px;color:#5c6b7a}
.reg-campos{display:grid;gap:12px;grid-template-columns:1fr 1fr}
.reg-l{display:block;font-size:11px;font-weight:700;letter-spacing:1px;
  text-transform:uppercase;color:#5c6b7a}
.reg-l:first-child,.reg-campos>.reg-l:nth-child(1){grid-column:1/-1}
.reg-op{font-weight:500;text-transform:none;letter-spacing:0;color:#98A2AB}
/* El asterisco de lo indispensable. Rojo firme sobre la tarjeta clara
   del ingreso —4,8:1 sobre blanco—, y en negrita para que se vea a
   simple vista sin tener que leer el rótulo entero. */
.reg-ob{color:#b91c1c;font-weight:800}
.reg-l input{display:block;width:100%;margin-top:5px;padding:11px 13px;
  border:1px solid #d7dee7;border-radius:9px;background:#f6f8fa;color:#14181C;
  font-size:14px;font-family:inherit}
/* El color del texto se repite en :focus a propósito. Un fondo claro
   sin color propio hereda el del navegador, y en un sistema forzado a
   oscuro ese heredado es claro: texto claro sobre fondo blanco. Es el
   aviso que da _herramientas/auditar_tema.py, y tiene razón. */
.reg-l input:focus{outline:none;border-color:#B8860B;background:#fff;color:#14181C}
.reg-check{display:flex;gap:10px;align-items:flex-start;margin:16px 0 4px;
  font-size:12px;color:#5c6b7a;line-height:1.45}
.reg-check input{margin-top:2px;flex:0 0 auto}
.reg-msg{margin-top:12px;padding:10px 12px;border-radius:9px;font-size:13px}
.reg-msg.bien{background:#e8f5ee;color:#1c6b41;border:1px solid #bfe3ce}
.reg-msg.malo{background:#fdecec;color:#8c2f2f;border:1px solid #f3c9c9}
.reg-pies{display:flex;gap:10px;justify-content:flex-end;margin-top:18px;flex-wrap:wrap}
.reg-enviar{width:auto;padding-left:26px;padding-right:26px;margin:0}

/* ===================================================================
   LAS TRES FOTOGRAFÍAS DEL ENROLAMIENTO           [06/09/2026]

   Colores fijos y claros, como todo el bloque .reg-* de arriba: esta
   ventana vive en la pantalla de ingreso, que es una hoja clara sobre
   un fondo oscuro y no cambia con el tema. El auditor de tema ya
   perdona los blancos de la pantalla de ingreso por ese motivo.

   TRES ESTADOS DE RECUADRO, Y CADA UNO DICE ALGO
     vacío    borde a trazos: falta por hacer.
     lleno    borde continuo verde: la foto se midió y sirve.
     dudosa   borde continuo ámbar: se aceptó, pero algo no está bien
              —oscura, movida, pequeña—. NO se rechaza: se avisa. Una
              foto que el CRM rechaza solo es una persona que no puede
              terminar su solicitud.
   =================================================================== */
.reg-fotos{margin-top:18px;border-top:1px solid #e6ebf1;padding-top:16px}
.reg-fotos-tit{font-size:11px;font-weight:700;letter-spacing:1px;
  text-transform:uppercase;color:#5c6b7a}
.reg-fotos-ay{font-size:12px;color:#5c6b7a;margin:6px 0 12px;line-height:1.45}
.reg-slots{display:grid;gap:10px;grid-template-columns:repeat(3,1fr)}
/* Cada regla con fondo claro declara TAMBIÉN su color de texto. Son
   botones, y un <button> no hereda el color de su tarjeta: usa el del
   navegador, que en un sistema forzado a oscuro es claro. Sin esto, el
   rótulo del recuadro puede desaparecer sobre su propio fondo. */
.reg-slot{border:1px dashed #d7dee7;border-radius:10px;background:#f6f8fa;
  color:#14181C;padding:8px;text-align:center;cursor:pointer;font-family:inherit}
.reg-slot:hover{border-color:#B8860B}
.reg-slot:focus-visible{outline:2px solid #B8860B;outline-offset:2px}
.reg-slot.lleno{border-style:solid;border-color:#7fbf9b;background:#f2f9f5;color:#14181C}
.reg-slot.dudosa{border-style:solid;border-color:#d9a441;background:#fdf7ea;color:#14181C}
/* Sin fondo propio: mientras carga se ve el del recuadro, y una imagen
   no lleva texto encima que pueda quedar ilegible. */
.reg-slot img{width:100%;height:84px;object-fit:cover;border-radius:7px;display:block}
.reg-slot-vacio{height:84px;display:flex;align-items:center;justify-content:center;
  font-size:24px;color:#98A2AB}
/* El dibujo del recuadro vacío (ver REG_ICONOS). Se mide en porcentaje
   del alto del recuadro y no en píxeles: los dos tamaños reducidos de
   más abajo —60 px y 48 px— lo encogen solos, sin repetir la regla. */
.reg-slot-vacio svg{height:62%;width:auto;display:block;fill:currentColor}
.reg-slot-tx{font-size:11px;font-weight:700;color:#14181C;margin-top:6px;line-height:1.3}
.reg-slot-nota{font-size:10.5px;color:#5c6b7a;margin-top:3px;line-height:1.35;min-height:28px}
.reg-slot.dudosa .reg-slot-nota{color:#8a6414}
.reg-slot.lleno  .reg-slot-nota{color:#1c6b41}
/* ===================================================================
   LOS TRES TAMAÑOS QUE HAY QUE ATENDER              [07/09/2026]

   1. TELÉFONO EN VERTICAL (ancho < 560)
      Una sola columna. Dos columnas de 130 px no son dos columnas:
      son dos campos ilegibles. Los recuadros de foto también se
      apilan, porque a un tercio de pantalla no se ve qué hay dentro.

   2. PANTALLA BAJA (alto < 560) — teléfono EN HORIZONTAL
      Es el caso que peor estaba y el que se pidió arreglar. Aquí no
      sobra ni un píxel de alto: se recortan los márgenes, el título
      baja de 26 a 19 px y el texto de ayuda se esconde. Las tres
      casillas largas se quedan —son obligatorias y hay que leerlas—
      pero el cuerpo se desplaza, que es lo que las hace alcanzables.

      El ancho sí sobra en horizontal, así que los campos se quedan en
      dos columnas: se ve más formulario de una vez.

   3. TABLETA Y ESCRITORIO
      Lo de arriba, sin tocar: 560 px de tarjeta y dos columnas.

   Todo con «max-height», no con «orientation:landscape». Lo que
   estorba no es la orientación, es la altura: un iPad en horizontal
   tiene 768 px de alto y no necesita nada de esto.
   =================================================================== */
@media (max-width:560px){ .reg-campos{grid-template-columns:1fr}
                          .reg-slots{grid-template-columns:1fr}
                          .reg-card{padding:20px 18px 16px;border-radius:14px}
                          .reg-tit{font-size:22px} }

@media (max-height:560px){
  .reg-overlay{padding:8px}
  .reg-card{padding:14px 18px 12px;max-height:calc(100vh - 16px);max-height:calc(100dvh - 16px)}
  .reg-tit{font-size:19px;margin-bottom:2px}
  .reg-sub{display:none}                 /* lo explica el título */
  .reg-campos{gap:8px}
  .reg-l input{padding:8px 11px}
  .reg-check{margin:10px 0 2px;font-size:11.5px}
  .reg-fotos{margin-top:12px;padding-top:11px}
  .reg-slot img,.reg-slot-vacio{height:60px}
  .reg-pies{margin-top:10px}
}
/* Pantalla MUY baja (móvil horizontal con el teclado abierto): la
   tarjeta ocupa todo y solo se conserva lo imprescindible. */
@media (max-height:420px){
  .reg-fotos-ay{display:none}
  .reg-slot-nota{display:none}
  .reg-slot img,.reg-slot-vacio{height:48px}
}

/* ===================================================================
   BANDEJA DE SOLICITUDES DE INGRESO               [06/09/2026]
   Esta sí vive dentro del CRM, así que usa las variables del tema y se
   comporta igual en claro y en oscuro. Regla de la casa.
   =================================================================== */
.sol-badge{display:inline-block;min-width:18px;padding:0 5px;margin-left:6px;
  border-radius:9px;background:var(--accent);color:#14181C;
  font-size:11px;font-weight:700;text-align:center;line-height:17px}
.sol-overlay{position:fixed;inset:0;z-index:9500;display:flex;align-items:flex-start;
  justify-content:center;padding:40px 20px;background:rgba(10,13,16,.66);overflow:auto}

/* ===================================================================
   INVENTARIO · LAS BODEGAS EN EL MENÚ Y LA PANTALLA DE UNA BODEGA
   [09/09/2026]

   Todo sale de las variables del tema: esto vive DENTRO del CRM y
   tiene que comportarse igual en claro y en oscuro. Regla de la casa.

   Va en crm.css y no en los estilos que el módulo se inyecta solo,
   por un motivo concreto: lo que se inyecta desde JavaScript NO lo
   revisa _herramientas/auditar_tema.py. Aquí sí, y aquí se queda.
   =================================================================== */

/* ---- El submenú de bodegas, debajo de «Inventario» --------------- */
.inv-submenu{display:flex;flex-direction:column;margin:2px 0 6px}
/* ===================================================================
   LA CAUSA DE «NO SE DESPLIEGAN LAS BODEGAS»       [10/09/2026]

   Esto es lo que estaba mal, y explica por qué el fallo era, en sus
   palabras, «reiterativo».

   El programa plegaba el submenú poniéndole el atributo `hidden`. El
   navegador esconde lo que lleva `hidden` con una regla suya
   —display:none— pero CUALQUIER regla escrita a mano le gana, y la
   línea de arriba dice display:flex sin condiciones.

   Resultado medido en pantalla: el atributo SÍ estaba puesto
   (hasAttribute('hidden') = true) y el bloque seguía viéndose
   (display calculado: flex, alto > 0). Las bodegas no se ocultaron
   nunca. Se pulsaba, el programa hacía su trabajo, y no pasaba nada
   visible.

   Es la misma trampa de siempre con `hidden`: en cuanto un elemento
   tiene su propio display, hay que apagarlo a mano.

   SI ESTA LÍNEA DESAPARECE: el submenú de bodegas deja de plegarse
   otra vez, y sin ningún error que lo delate.
   =================================================================== */
.inv-submenu[hidden]{display:none}
/* ===================================================================
   EL NÚMERO DE ENVÍOS SIN ACEPTAR, EN EL MENÚ      [10/09/2026]

   Se pidió «un número con la cantidad de notificaciones que tengo
   cuando envío un pedido», al lado del nombre de la bodega.

   Ámbar y no rojo: no es un error, es algo que espera a que alguien lo
   atienda. Y con `margin-left:auto` se va al borde derecho del
   renglón, donde el ojo ya busca los contadores del resto del menú.
   =================================================================== */
.inv-sub-n{
  margin-left:auto;min-width:18px;height:18px;padding:0 5px;border-radius:9px;
  background:var(--warn);color:#1b1206;font-size:11px;font-weight:700;
  display:inline-flex;align-items:center;justify-content:center;line-height:1;
}
/* .inv-sub es flex, así que el atributo `hidden` por sí solo no lo
   esconde: hay que apagarlo a mano. Es el mismo fallo que tuvo el
   submenú entero esta mañana, y no se repite. */
.inv-sub-n[hidden]{display:none}

/* ===================================================================
   EL ORDEN DE LAS CAPAS, EN UN SOLO SITIO          [10/09/2026]

   El cuadro de preguntar y avisar del CRM tiene que estar POR ENCIMA
   de cualquier ventana, porque siempre se abre DESDE una de ellas:
   se pulsa «Aceptar y recibir» dentro de la ventana del envío y la
   pregunta sale encima.

   Traía z-index:300 escrito en el propio elemento y las ventanas del
   inventario usan 9999: la pregunta se dibujaba detrás. No se veía,
   no se podía pulsar, y la ventana se quedaba abierta para siempre.

   Las capas del CRM, de abajo arriba:
       9400  el menú de tres puntos
       9700  el cuadro que pide un texto
       9999  las ventanas del inventario
      10500  ESTE, que pregunta y avisa
   =================================================================== */
#ui-dialog-ov{z-index:10500}
.inv-submenu .inv-sub{
  display:flex;align-items:center;gap:10px;cursor:pointer;
  padding:6px 10px 6px 30px;color:var(--muted);font-size:13px;
  border-left:2px solid transparent;text-decoration:none;
}
.inv-submenu .inv-sub .ic{font-size:11px;opacity:.75;width:12px;text-align:center}
.inv-submenu .inv-sub:hover{color:var(--txt);background:var(--fx-hover)}
.inv-submenu .inv-sub:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.inv-submenu .inv-sub.activa{color:var(--txt);border-left-color:var(--accent);background:var(--fx-hover)}
/* La principal se distingue: es la única que no se puede crear ni
   borrar, y de ella sale casi todo el material. */
.inv-submenu .inv-sub.principal{font-weight:600;color:var(--txt)}
/* Con la barra recogida solo quedan los iconos; los nombres de las
   bodegas no caben y sobra el sangrado. */
.side.mini .inv-submenu .inv-sub{padding-left:0;justify-content:center}
.side.mini .inv-submenu .inv-sub .lb{display:none}

/* ---- Elegir tocando: categorías, unidades y bodegas -------------- */
.inv-campo{display:block;margin:12px 0 4px}
.inv-campo-t{display:block;font-size:12px;color:var(--muted);margin-bottom:6px}
.inv-campo-t small{color:var(--muted);opacity:.85;font-weight:400}
.inv-campo input{width:100%;box-sizing:border-box;background:var(--panel2);color:var(--txt);
  border:1px solid var(--line);border-radius:8px;padding:8px 10px;font:inherit;font-size:13px}
.inv-campo input:focus{outline:none;border-color:var(--accent)}
/* El código no se escribe: lo arma el sistema al elegir la categoría.
   Se ve que es un dato, no un campo — fondo del panel, en monoespaciada
   y sin cursor de escritura. Un consecutivo que alguien puede
   sobrescribir deja de ser un consecutivo. [09/09/2026] */
.inv-cod{
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  letter-spacing:.5px;font-weight:600;color:var(--txt);
  background:var(--panel)!important;cursor:default;
}
.inv-cod::placeholder{font-family:inherit;font-weight:400;letter-spacing:0;color:var(--muted)}
.inv-chips{display:flex;flex-wrap:wrap;gap:7px}
.inv-chip{
  background:var(--panel2);color:var(--muted);border:1px solid var(--line);
  border-radius:99px;padding:6px 13px;font:inherit;font-size:12.5px;cursor:pointer;
  transition:border-color .12s,color .12s;
}
.inv-chip:hover{color:var(--txt);border-color:var(--accent)}
.inv-chip:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* El elegido se distingue por borde y peso, no solo por color: en una
   pantalla de obra, a contraluz, el color solo no alcanza. */
.inv-chip.on{background:var(--panel);color:var(--txt);border-color:var(--accent);
  border-width:2px;padding:5px 12px;font-weight:600}

/* ---- La pantalla de una bodega: dos tablas iguales ---------------- */
.inv-bod-tit{font-size:16px;color:var(--muted);margin:2px 0 14px}
.inv-bod-tit b{color:var(--txt);font-weight:600}
.inv-bod-tit small{color:var(--muted);font-weight:400}
.inv-bod-col{min-width:0;display:flex;flex-direction:column;gap:8px}
.inv-bod-h{display:flex;align-items:center;gap:9px;font-size:11px;font-weight:700;
  letter-spacing:1px;text-transform:uppercase;color:var(--muted)}
.inv-cant2{width:96px}
/* Marcado y sin cantidad: no se puede mandar, y tiene que verse. */
.inv-tabla-bod tr.inv-sin td{color:var(--warn,#d9a441)}
.inv-tabla-bod tr.inv-sin .inv-cant{border-color:var(--warn,#d9a441)}

/* ---- La franja de abajo: qué se hace, y a dónde va ----------------
   El destino va A LA DERECHA, como se pidió el 09/09/2026, y con él el
   botón Enviar: elegir bodega y enviar son dos gestos seguidos y ahora
   caen en el mismo sitio. A la izquierda quedan los botones que no
   dependen del destino (los PDF y el descuento en sitio).
   La columna de acciones es «auto» —lo que ocupen sus botones— y la del
   destino se lleva el resto, porque es la que crece cuando hay muchas
   bodegas creadas. */
.inv-bod-pie{
  display:grid;grid-template-columns:auto minmax(0,1fr);gap:16px;align-items:end;
  margin-top:16px;padding-top:14px;border-top:1px solid var(--line);
}
/* En pantalla estrecha se apilan, y entonces el destino va PRIMERO:
   apilado ya no hay izquierda ni derecha, y lo que manda es el orden de
   lectura — a dónde va, y después enviar. */
@media (max-width:900px){
  .inv-bod-pie{grid-template-columns:minmax(0,1fr)}
  .inv-pie-dest{order:-1}
}
.inv-pie-t{font-size:11px;font-weight:700;letter-spacing:1px;text-transform:uppercase;
  color:var(--muted);margin-bottom:8px}
.inv-bod-bs{display:flex;flex-wrap:wrap;gap:8px}
.inv-bod-b{
  background:var(--panel2);color:var(--muted);border:1px solid var(--line);
  border-radius:9px;padding:8px 15px;font:inherit;font-size:13px;cursor:pointer;
}
.inv-bod-b:hover{color:var(--txt);border-color:var(--accent)}
.inv-bod-b:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.inv-bod-b.pri{font-weight:600;color:var(--txt)}
.inv-bod-b.on{background:var(--panel);color:var(--txt);border-color:var(--accent);
  border-width:2px;padding:7px 14px;font-weight:600}
/* Los botones que NO dependen del destino, a la izquierda. */
.inv-pie-acc{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-start;align-items:flex-end}
/* El bloque del destino, a la derecha, con su rótulo, sus bodegas, el
   responsable y el botón Enviar debajo — todo alineado a la derecha
   para que el ojo no tenga que cruzar la pantalla dos veces. */
.inv-pie-dest{display:flex;flex-direction:column;align-items:flex-end;text-align:right}
/* ------------------------------------------------------------------
   LOS DESTINOS, EN DOS FILAS DE TRES              [10/09/2026]

     «Necesito que esos seis botones los ubique en dos filas, con el
      fin de que se mantengan en la zona en donde voy a trasladar y no
      me invadan el lado izquierdo de la pantalla.»

   QUÉ PASABA
     Eran flex con `wrap`: se repartían según el ancho que hubiera. Con
     sitio de sobra, los seis se ponían en una sola fila larga que
     cruzaba hacia la izquierda y se metía debajo de la tabla. La zona
     de traslado dejaba de tener un límite visible.

   POR QUÉ REJILLA Y NO SEGUIR CON FLEX
     `flex-wrap` decide dónde cortar según quepa; una rejilla de tres
     columnas corta SIEMPRE a los tres. Seis botones dan dos filas
     exactas, siempre las mismas, y el bloque ocupa un rectángulo
     estable que no invade nada.

   `1fr` Y NO `auto`: las tres columnas miden igual, así los botones no
   bailan de ancho según lo largo que sea el nombre de cada bodega.

   EL DÍA QUE HAYA SIETE BODEGAS DESTINO
     Serán tres filas —tres, tres y una—, no una fila larga. Que es lo
     que se quería.
   ------------------------------------------------------------------ */
.inv-pie-dest .inv-bod-bs{
  display:grid;grid-template-columns:repeat(3,1fr);gap:8px;
  justify-content:end;width:max-content;max-width:100%;
}
.inv-pie-dest .inv-bod-b{width:100%;text-align:center;white-space:nowrap}
/* En pantalla angosta, dos columnas: con tres, los nombres largos se
   parten en dos renglones y la franja crece el doble de alto. */
@media (max-width:820px){
  .inv-pie-dest .inv-bod-bs{grid-template-columns:repeat(2,1fr)}
}
/* Los dos botones del envío, juntos y a la derecha: primero el papel
   que firma quien recibe, después el material. [10/09/2026] */
.inv-pie-enviar{margin-top:10px;display:flex;gap:10px;justify-content:flex-end;flex-wrap:wrap}
/* El nombre viejo sigue definido: si alguna pantalla que no se ha
   tocado todavía lo usa, no se queda sin estilo. [09/09/2026] */
.inv-pie-der{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}

/* ===================================================================
   EL MENÚ DE TRES PUNTOS, COMÚN A TODO EL CRM       [09/09/2026]
   Lo dibuja crm-menu3p.js. Lo usan la lista de reportes y, en su
   momento, todo lo que hoy tiene botones sueltos en la fila.
   =================================================================== */
.rep-3p{
  background:none;border:0;color:var(--muted);cursor:pointer;
  font-size:17px;line-height:1;padding:3px 8px;border-radius:7px;
}
.rep-3p:hover{color:var(--txt);background:var(--fx-hover)}
.rep-3p:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
.crm-m3p{
  position:fixed;z-index:9400;min-width:220px;
  background:var(--panel);border:1px solid var(--borde-tarjeta);border-radius:10px;
  box-shadow:0 12px 34px rgba(0,0,0,.4);padding:5px;
}
.crm-m3p-t{font-size:11px;color:var(--muted);padding:6px 10px 7px;
  border-bottom:1px solid var(--line);margin-bottom:4px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:280px}
.crm-m3p button{
  display:block;width:100%;text-align:left;background:none;border:0;
  color:var(--txt);font:inherit;font-size:13px;cursor:pointer;
  padding:8px 10px;border-radius:7px;
}
.crm-m3p button:hover:not(:disabled){background:var(--fx-hover)}
.crm-m3p button:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
/* La opción que destruye se ve distinta ANTES de pulsarla. */
.crm-m3p button.mal{color:var(--bad,#ef4444)}
.crm-m3p button.mal:hover:not(:disabled){background:var(--bad-suave,rgba(239,68,68,.12))}
/* Apagada, no escondida: quien no puede usarla ve que existe y por qué
   no, en vez de buscar algo que en su pantalla no está. */
.crm-m3p button:disabled{color:var(--faint,#6E7C88);cursor:default;opacity:.7}

/* ---- Los tres puntos de cada artículo ----------------------------- */
.inv-acc{width:1%;white-space:nowrap;text-align:right}
.inv-3p{
  background:none;border:0;color:var(--muted);cursor:pointer;
  font-size:17px;line-height:1;padding:3px 8px;border-radius:7px;
}
.inv-3p:hover{color:var(--txt);background:var(--fx-hover)}
.inv-3p:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
/* El menú va en position:fixed sobre todo lo demás. Por debajo de los
   cuadros de diálogo (9600+) para que nunca les gane. */
.inv-menu{
  position:fixed;z-index:9400;min-width:210px;
  background:var(--panel);border:1px solid var(--borde-tarjeta);border-radius:10px;
  box-shadow:0 12px 34px rgba(0,0,0,.4);padding:5px;
}
.inv-menu-t{font-size:11px;color:var(--muted);padding:6px 10px 7px;
  border-bottom:1px solid var(--line);margin-bottom:4px;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:260px}
.inv-menu button{
  display:block;width:100%;text-align:left;background:none;border:0;
  color:var(--txt);font:inherit;font-size:13px;cursor:pointer;
  padding:8px 10px;border-radius:7px;
}
.inv-menu button:hover{background:var(--fx-hover)}
.inv-menu button:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
/* La opción que destruye se ve distinta ANTES de pulsarla. */
.inv-menu button.mal{color:var(--bad,#ef4444)}
.inv-menu button.mal:hover{background:var(--bad-suave,rgba(239,68,68,.12))}

/* ---- El cuadro de borrado definitivo ------------------------------ */
.inv-borrar-ov{position:fixed;inset:0;z-index:9650;display:none;align-items:center;
  justify-content:center;padding:20px;background:rgba(10,13,16,.7)}
.inv-borrar-ov.open{display:flex}
.inv-br-card{
  width:100%;max-width:560px;background:var(--panel);color:var(--txt);
  border:1px solid var(--bad,#ef4444);border-radius:14px;padding:18px 20px;
  box-shadow:0 24px 60px rgba(0,0,0,.5);
}
.inv-br-card > b{display:block;font-size:15px;color:var(--txt);margin-bottom:7px}
.inv-br-card p{margin:0 0 14px;font-size:12.5px;color:var(--muted);line-height:1.6}
.inv-br-card p b{color:var(--bad,#ef4444)}
.inv-br-lista{display:flex;flex-direction:column;gap:6px;
  max-height:min(44vh,340px);overflow-y:auto;-webkit-overflow-scrolling:touch}
.inv-br-fila{
  display:grid;grid-template-columns:auto minmax(0,1fr);gap:4px 11px;align-items:start;
  background:var(--panel2);border:1px solid var(--line);border-radius:9px;
  padding:9px 11px;cursor:pointer;
}
.inv-br-fila:hover{border-color:var(--accent)}
.inv-br-fila.marcada{border-color:var(--bad,#ef4444)}
.inv-br-fila input{margin-top:2px}
.inv-br-n{font-size:13px;color:var(--txt);overflow:hidden;text-overflow:ellipsis}
.inv-br-d{grid-column:2;font-size:11px;color:var(--muted);line-height:1.45}
.inv-br-fila.marcada .inv-br-d{color:var(--bad,#ef4444)}
.inv-br-pie{display:flex;gap:9px;align-items:center;justify-content:flex-end;
  margin-top:15px;flex-wrap:wrap}
.inv-br-cuenta{flex:1 1 auto;font-size:12px;color:var(--muted)}
.inv-br-pie .btn.danger{background:var(--bad,#ef4444);color:#fff}
.inv-br-pie .btn.danger:disabled{opacity:.45;cursor:default}

/* ---- Las tres pestañas de dentro de una bodega -------------------- */
.inv-subtabs{display:flex;gap:4px;flex-wrap:wrap;margin:0 0 14px;
  border-bottom:1px solid var(--line);padding-bottom:0}
.inv-subtab{
  background:none;border:0;border-bottom:2px solid transparent;
  color:var(--muted);font:inherit;font-size:13px;cursor:pointer;
  padding:7px 13px;margin-bottom:-1px;
}
.inv-subtab:hover{color:var(--txt)}
.inv-subtab:focus-visible{outline:2px solid var(--accent);outline-offset:-2px;border-radius:6px}
.inv-subtab.activa{color:var(--txt);border-bottom-color:var(--accent);font-weight:600}

/* ---- El histórico y el reconteo ---------------------------------- */
.inv-nota{font-size:12px;color:var(--muted);line-height:1.55;margin:0 0 12px;max-width:78ch}
.inv-nota b{color:var(--txt)}
.inv-fecha{white-space:nowrap;font-variant-numeric:tabular-nums;font-size:12px}
.inv-motivo{font-size:12px;color:var(--muted)}
/* La etiqueta del tipo de movimiento. El color no es decoración: dice
   de un vistazo si el material entró o salió. */
.inv-mv{display:inline-block;font-size:11px;font-weight:600;padding:1px 8px;
  border-radius:99px;background:var(--panel2);border:1px solid var(--line);color:var(--muted)}
.inv-mv.entrada,.inv-mv.recepcion{color:var(--ok,#22c55e);border-color:var(--ok,#22c55e)}
.inv-mv.salida,.inv-mv.despacho{color:var(--warn,#d9a441);border-color:var(--warn,#d9a441)}
.inv-mv.ajuste{color:var(--bad,#ef4444);border-color:var(--bad,#ef4444)}
.inv-sube{color:var(--ok,#22c55e)}
.inv-baja{color:var(--bad,#ef4444)}
.inv-ok{color:var(--ok,#22c55e);font-size:12px}
.inv-cont{width:104px}
/* La fila que no cuadra se marca entera: en una tabla larga, un número
   distinto en una columna se pasa por alto. */
.inv-table tr.inv-dif{background:var(--fx-hover)}
.inv-table tr.inv-dif .inv-cont{border-color:var(--warn,#d9a441)}

/* ---- Las bodegas como tarjetas ----------------------------------- */
.inv-tarjetas{display:grid;gap:12px;grid-template-columns:repeat(auto-fill,minmax(230px,1fr))}
.inv-tj{
  text-align:left;background:var(--panel);color:var(--txt);
  border:1px solid var(--borde-tarjeta);border-radius:12px;padding:14px 15px;
  cursor:pointer;font:inherit;display:flex;flex-direction:column;gap:5px;
}
.inv-tj:hover{border-color:var(--accent)}
.inv-tj:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.inv-tj.pri{border-left-width:3px;border-left-color:var(--accent)}
.inv-tj-cab{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.inv-tj-cab b{font-size:14px;color:var(--txt)}
.inv-tj-n{font-size:26px;font-weight:700;line-height:1.1;color:var(--txt);
  font-variant-numeric:tabular-nums;display:flex;align-items:baseline;gap:7px}
.inv-tj-n small{font-size:11px;font-weight:400;color:var(--muted)}
.inv-tj-u{font-size:12px;color:var(--muted);font-variant-numeric:tabular-nums}
.inv-tj-e{
  display:inline-block;align-self:flex-start;margin-top:3px;
  font-size:11px;font-weight:600;padding:2px 9px;border-radius:99px;
  background:var(--panel2);border:1px solid var(--line);color:var(--muted);
}
.inv-tj-e.bien{color:var(--ok,#22c55e);border-color:var(--ok,#22c55e)}
.inv-tj-e.bajo{color:var(--warn,#d9a441);border-color:var(--warn,#d9a441)}
.inv-tj-e.vacia{color:var(--bad,#ef4444);border-color:var(--bad,#ef4444)}
.inv-tj-r{font-size:11px;color:var(--muted);margin-top:4px;line-height:1.45}

.inv-bod{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:16px;align-items:start}
/* ------------------------------------------------------------------
   EL CORTE VA EN 1280, NO EN 1180              [10/09/2026]

   Medido en pantalla: con la ventana en 1047 px el panel se lleva 320
   y a la tabla le quedan menos de 700. Las seis columnas no caben y la
   última —«Bodega»— aparece partida en dos renglones detrás del panel.
   La tabla sigue pudiéndose desplazar, así que no se pierde nada, pero
   una columna cortada se lee como un fallo.

   Por debajo del corte el panel baja y se pone a lo ancho: se ve la
   tabla entera y el panel entero, uno encima del otro.

   POR QUÉ SUBIÓ DE 1180 A 1280
     El 1180 se midió cuando la tabla tenía SEIS columnas. Después se
     añadieron dos: «A usar en sitio» y el ⋮ de cada artículo. Con
     siete, la tabla pide 609 px; en una ventana de 1186 —la de la
     oficina— el reparto a mitades le daba 435, y las dos columnas
     nuevas quedaban cortadas por la derecha. Cortadas EN SILENCIO:
     no hay ninguna señal de que la tabla siga más allá del borde, así
     que quien mira ve una pantalla a la que le faltan cosas.

     Con el corte en 1280 esa misma ventana pone el panel debajo y la
     tabla ocupa los 887 px enteros. Medido, no calculado.

     SI SE AÑADE OTRA COLUMNA, ESTE NÚMERO VUELVE A QUEDARSE VIEJO.
     La comprobación es de una línea, en la consola del navegador:
       const s=document.querySelector('.inv-scroll');
       s.scrollWidth <= s.clientWidth       // tiene que dar true
   ------------------------------------------------------------------ */
@media (max-width:1280px){
  .inv-bod{grid-template-columns:minmax(0,1fr)}
}
/* Del panel lateral solo queda el hueco: ahora «Por enviar» es una
   tabla igual a la otra, no una barra pegada al borde. Se conserva la
   regla vacía a propósito, para que quien busque .inv-bod-lado en la
   hoja encuentre esta nota y no crea que se perdió. */
.inv-bod-lado{min-width:0}
.inv-bod .inv-pe-vacio{
  display:block;color:var(--muted);font-size:12.5px;line-height:1.55;
  background:transparent;border:1px dashed var(--line);border-radius:10px;
  padding:22px 16px;text-align:center;
}
.inv-bod-tabla{min-width:0}
.inv-tabla-bod th.inv-chk,.inv-tabla-bod td.inv-chk{width:34px;text-align:center;padding-left:6px;padding-right:0}
.inv-tabla-bod .inv-cant{
  width:104px;text-align:right;background:var(--panel2);color:var(--txt);
  border:1px solid var(--line);border-radius:7px;padding:5px 8px;font:inherit;font-size:13px;
}
.inv-tabla-bod .inv-cant:focus{outline:none;border-color:var(--accent)}
.inv-tabla-bod .inv-cant:disabled{opacity:.4}
.inv-tabla-bod tr.inv-marcada{background:var(--fx-hover)}

/* ---- El panel «Por enviar» --------------------------------------- */
.inv-bod-lado{
  background:var(--panel2);color:var(--txt);
  border:1px solid var(--borde-tarjeta);border-radius:12px;padding:14px 15px;
  position:sticky;top:12px;
}
.inv-pe-cab{display:flex;align-items:center;gap:9px;font-size:15px;color:var(--txt)}
.inv-pe-n{
  min-width:22px;padding:0 7px;border-radius:99px;background:var(--accent);color:#14181C;
  font-size:12px;font-weight:700;text-align:center;line-height:19px;
}
.inv-pe-ay{margin:7px 0 12px;font-size:11.5px;color:var(--muted);line-height:1.5}
.inv-pe-ay b{color:var(--txt)}
.inv-pe-lista{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:7px;
  max-height:min(38vh,320px);overflow-y:auto}
.inv-pe-lista li{
  display:grid;grid-template-columns:minmax(0,1fr) auto auto;gap:8px;align-items:center;
  background:var(--panel);border:1px solid var(--line);border-radius:9px;padding:7px 9px;
}
.inv-pe-a{font-size:12.5px;color:var(--txt);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.inv-pe-c{font-size:12px;color:var(--muted);white-space:nowrap;font-variant-numeric:tabular-nums}
/* Marcado pero sin cantidad: no se puede mandar y hay que verlo. */
.inv-pe-lista li.inv-sin{border-color:var(--warn,#d9a441)}
.inv-pe-lista li.inv-sin .inv-pe-c{color:var(--warn,#d9a441)}
.inv-pe-vacio{display:block;color:var(--muted);font-size:12px;line-height:1.5;
  background:transparent;border:1px dashed var(--line);text-align:center}
.inv-pe-x{background:none;border:0;color:var(--muted);cursor:pointer;font-size:12px;
  padding:2px 5px;border-radius:6px;line-height:1}
.inv-pe-x:hover{color:var(--txt);background:var(--fx-hover)}
.inv-pe-pie{margin-top:13px;border-top:1px solid var(--line);padding-top:12px}
.inv-pe-l{display:block;font-size:11px;text-transform:uppercase;letter-spacing:.7px;color:var(--muted)}
.inv-pe-l select{
  width:100%;box-sizing:border-box;margin-top:5px;background:var(--panel);color:var(--txt);
  border:1px solid var(--line);border-radius:8px;padding:7px 9px;font:inherit;font-size:13px;
}
.inv-pe-l select:focus{outline:none;border-color:var(--accent)}
.inv-pe-resp{margin-top:9px;font-size:12px;color:var(--muted);line-height:1.5}
.inv-pe-resp b{color:var(--txt)}
.inv-pe-resp.sin{color:var(--warn,#d9a441)}
.inv-pe-resp.sin b{color:var(--warn,#d9a441)}
.inv-pe-btns{display:flex;gap:8px;justify-content:flex-end;margin-top:13px;flex-wrap:wrap}
.inv-crumb-tit{margin-left:10px;color:var(--txt);font-size:14px}

/* ===================================================================
   EL CUADRO QUE PIDE EL MOTIVO DEL RECHAZO          [09/09/2026]

   POR QUÉ EXISTE
     Antes se pedía con `prompt()`, el cuadro del navegador. Ese
     congela la página entera mientras espera, y Chrome lo puede
     apagar del todo con la casilla «no permitir más diálogos» — y
     entonces el botón deja de hacer nada, sin decirlo. El CRM tenía
     su propio cuadro de aviso y de confirmación, pero ninguno con
     campo de texto; este lo completa.

   VA POR ENCIMA DE LA BANDEJA
     La bandeja de solicitudes está en 9500 y esto sale sobre ella.
     Se queda por debajo del aviso de sesión caída (9998), que tiene
     que ganarle a todo.
   =================================================================== */
.solp-ov{position:fixed;inset:0;z-index:9700;display:none;align-items:center;
  justify-content:center;padding:20px;background:rgba(10,13,16,.66)}
.solp-ov.open{display:flex}
.solp-card{width:100%;max-width:440px;background:var(--panel);color:var(--txt);
  border:1px solid var(--borde-tarjeta);border-radius:14px;padding:18px 20px;
  box-shadow:0 24px 60px rgba(0,0,0,.45)}
.solp-card b{display:block;font-size:15px;color:var(--txt);margin-bottom:6px}
.solp-card p{margin:0 0 12px;font-size:12.5px;color:var(--muted);line-height:1.55}
.solp-card textarea{width:100%;box-sizing:border-box;background:var(--panel2);
  color:var(--txt);border:1px solid var(--line);border-radius:9px;
  padding:9px 11px;font:13px/1.5 inherit;resize:vertical}
.solp-card textarea:focus{outline:none;border-color:var(--accent)}
.solp-pie{display:flex;gap:8px;justify-content:flex-end;margin-top:14px;flex-wrap:wrap}
.sol-overlay[hidden]{display:none}
.sol-card{position:relative;background:var(--panel);color:var(--txt);
  border:1px solid var(--line);border-radius:14px;padding:24px 26px;
  width:760px;max-width:100%;box-shadow:0 30px 80px rgba(0,0,0,.5)}
.sol-fila{display:flex;gap:14px;align-items:center;flex-wrap:wrap;
  border:1px solid var(--line);border-radius:10px;padding:12px 14px;margin-bottom:10px;
  background:var(--panel2)}
.sol-datos{flex:1 1 320px;min-width:0}
.sol-nombre{font-weight:600;font-size:14.5px}
.sol-sub{font-size:12px;color:var(--muted);margin-top:2px}
.sol-ok{color:var(--ok,#2F6B45)}
.sol-no{color:var(--accent2)}
.sol-acciones{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.sol-rol{background:var(--panel);border:1px solid var(--line);color:var(--txt);
  border-radius:8px;padding:7px 9px;font-size:12.5px}
.sol-aprobar:disabled{opacity:.5;cursor:not-allowed}
.sol-estado{font-size:12px;color:var(--muted)}
.sol-vacia{border:1px dashed var(--line);border-radius:10px;padding:26px;
  text-align:center;color:var(--muted);font-size:13.5px}

/* -------------------------------------------------------------------
   LAS FOTOS Y EL CRUCE, EN LA BANDEJA             [06/09/2026]

   Aquí sí manda el tema: esto vive dentro del CRM. Los tres distintivos
   toman su color de --ok, --warn y --muted, que están definidos en las
   dos hojas —claro y oscuro— con valores propios de cada una. El fondo
   es siempre var(--panel) y lo que cambia es el texto y el borde: así
   ninguno se queda ilegible al cambiar de tema, que es lo que pasa
   cuando se le pinta un fondo de color a fuego.
   ------------------------------------------------------------------- */
.sol-fotos{display:flex;gap:8px;margin-top:9px;flex-wrap:wrap}
.sol-foto{width:64px;height:64px;border-radius:8px;object-fit:cover;
  border:1px solid var(--line);background:var(--panel);cursor:zoom-in}
.sol-foto:hover{border-color:var(--accent)}
.sol-foto-no{width:64px;height:64px;border-radius:8px;border:1px dashed var(--line);
  display:flex;align-items:center;justify-content:center;text-align:center;
  font-size:10px;line-height:1.25;color:var(--muted);padding:4px}
.sol-chip{display:inline-block;padding:2px 9px;border-radius:99px;
  font-size:11px;font-weight:600;background:var(--panel);
  border:1px solid var(--line);color:var(--muted)}
.sol-chip.si{color:var(--ok);border-color:var(--ok)}
.sol-chip.no{color:var(--warn);border-color:var(--warn)}

/* ===================================================================
   EN EL TELÉFONO, UNA TARJETA DE CIFRA POR FILA     [07/09/2026]

   QUÉ PASABA
     Las tarjetas de indicadores iban de dos en dos en el móvil. Con
     importes colombianos —«$955.557.865,13», catorce caracteres— no
     caben en media pantalla: el número se partía y el «13» quedaba
     colgando en el renglón de abajo. Un importe cortado no es un
     importe; es dos números que no significan nada.

   POR QUÉ AL FINAL DEL ARCHIVO Y NO EDITANDO LAS REGLAS DE ARRIBA
     Hay SEIS media queries repartidas por la hoja que tocan «.kpis»
     —640, 820, 460, 430…— puestas en distintos momentos y por motivos
     distintos. Cambiarlas una a una es tocar seis sitios y arriesgarse
     a romper alguno. Aquí abajo, con el mismo peso y de últimas, esta
     gana sin discutir con ninguna.

   POR QUÉ 600 px Y NO 430
     Porque el problema no es el teléfono: es el ANCHO DE COLUMNA. A
     600 px repartidos en dos, cada tarjeta tiene 290 px y el importe
     ya no cabe. Se corta donde se rompe el dato, no donde cambia el
     aparato.

   EL NÚMERO TAMPOCO SE PARTE
     «white-space:nowrap» sobre la cifra. Antes que partirla, que se
     salga o se achique; un importe siempre en una sola línea.
   =================================================================== */
@media(max-width:600px){
  .kpis,
  .p26-kpis,
  #vuelos-kpis{grid-template-columns:1fr !important;gap:10px}
  .cs-kpis{flex-direction:column}
  .cs-kpis > *{width:100%}
  /* La cifra, entera y en una línea. Si aun así no cupiera, se
     encoge sola en vez de romperse. */
  .kpi .n,
  .p26-kpi .n,
  .kpi-num{white-space:nowrap;font-size:clamp(20px,7.2vw,32px)}
}

/* ============================================================
   MARCA POR EMPRESA — decoración del login sigue el color
   La cordillera y la estrella del panel de ingreso venían en dorado
   fijo (#E8C86A). Ahora usan --accent, así cada empresa las ve en su
   propio color (rojo para Ingenieros AVI, etc.). [25/09/2026]
   ============================================================ */
.login-cordillera g[stroke="#E8C86A"]{stroke:var(--accent,#E8C86A)}
.login-cordillera g[fill="#E8C86A"]{fill:var(--accent,#E8C86A)}

/* ============================================================
   LOGO DE LA BARRA EN TEMA CLARO  [25/09/2026]
   La barra es clara en tema claro; un logo pensado para fondo oscuro
   (trazo claro) se pierde. En vez de ponerlo sobre un recuadro oscuro
   (se veía como un parche) o de invertirlo (rompe los logos a color),
   se le da un contorno oscuro fino con drop-shadow: el mismo logo a
   color de siempre, pero visible sobre fondo claro. Sirve para
   cualquier empresa sin tener que subir otro archivo.
   ============================================================ */
[data-theme="light"] .brand-logo{
  filter:
    drop-shadow(1px 0 0 rgba(0,0,0,.55))
    drop-shadow(-1px 0 0 rgba(0,0,0,.55))
    drop-shadow(0 1px 0 rgba(0,0,0,.55))
    drop-shadow(0 -1px 0 rgba(0,0,0,.55))
    drop-shadow(0 1px 2px rgba(0,0,0,.35));
}
