:root{
  /* LA PALETA DE VALITECH (rama valitech, 2026-10-02): el azul de la marca
     sobre los fondos frios de siempre. Los NOMBRES vienen de la rama de
     origen (--oro-suave, --oro-texto...) y los VALORES son azules: asi un
     merge desde ella solo choca en estas lineas.
     --accent (#0b6b9a) ya se lee como letra: 5,86:1 sobre blanco y 5,21:1
     sobre --bg, con texto blanco encima de sus rellenos. --oro-texto es el
     mismo azul. --accent-2/-3 son el azul vivo de adorno, no de letra.
     --foco: el anillo de teclado, 5,21:1 sobre el fondo. */
  --bg:#eef2f6; --surface:#ffffff; --surface-2:#f6f8fb; --border:#d8e0e9;
  --ink:#0f1b2d; --ink-2:#4a5b70; --ink-3:#5f6f85;
  --accent:#0b6b9a; --accent-2:#12a3d6; --accent-3:#12a3d6;
  --accent-ink:#ffffff;
  --oro-suave:#e3f2fa; --oro-borde:#b5dcef;
  --navy:#0e1b33; --navy-2:#17263f; --navy-ink:#e8eef7;
  --oro-texto:#0b6b9a;
  --foco:var(--accent);
  --good:#15803d; --good-bg:#dcfce7; --warn:#b45309; --warn-bg:#fef3c7;
  --crit:#b91c1c; --crit-bg:#fee2e2; --neutral:#475569; --neutral-bg:#e2e8f0;
  --info:#1d4ed8; --info-bg:#dbeafe;
  --shadow:0 1px 2px rgba(15,27,45,.06),0 8px 24px rgba(15,27,45,.08);
  --radius:12px;
  --sans:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  --mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;
}
@media (prefers-color-scheme:dark){
  :root{
    /* Sobre oscuro el azul vivo se lee: --oro-texto es --accent, y el
       anillo de foco el --accent-2. */
    --bg:#0b111b; --surface:#141d2b; --surface-2:#0f1826; --border:#243244;
    --ink:#e7eef7; --ink-2:#a7b6c9; --ink-3:#75869a;
    --accent:#2aa5d8; --accent-2:#4cc4ef; --accent-3:#4cc4ef;
    --accent-ink:#04121c;
    --oro-texto:var(--accent);
    --oro-suave:#0b2433; --oro-borde:#16435c;
    --navy:#0f1826; --navy-2:#1a2740; --navy-ink:#e8eef7;
    --foco:var(--accent-2);
    --good:#4ade80; --good-bg:#0e2a1a; --warn:#fbbf24; --warn-bg:#2a1f07;
    --crit:#f87171; --crit-bg:#2a1212; --neutral:#94a3b8; --neutral-bg:#1e293b;
    --info:#60a5fa; --info-bg:#0f1e3a;
    --shadow:0 1px 2px rgba(0,0,0,.4),0 10px 30px rgba(0,0,0,.35);
  }
}
:root[data-theme="light"]{
  --bg:#eef2f6; --surface:#ffffff; --surface-2:#f6f8fb; --border:#d8e0e9;
  --ink:#0f1b2d; --ink-2:#4a5b70; --ink-3:#5f6f85; --accent:#0b6b9a; --accent-2:#12a3d6;
  --accent-3:#12a3d6; --accent-ink:#ffffff; --oro-suave:#e3f2fa; --oro-borde:#b5dcef;
  --oro-texto:#0b6b9a;
  --navy:#0e1b33; --navy-2:#17263f; --navy-ink:#e8eef7; --foco:var(--accent);
  --good:#15803d; --good-bg:#dcfce7; --warn:#b45309; --warn-bg:#fef3c7;
  --crit:#b91c1c; --crit-bg:#fee2e2; --neutral:#475569; --neutral-bg:#e2e8f0; --info:#1d4ed8; --info-bg:#dbeafe;
  --shadow:0 1px 2px rgba(15,27,45,.06),0 8px 24px rgba(15,27,45,.08);
}
:root[data-theme="dark"]{
  --bg:#0b111b; --surface:#141d2b; --surface-2:#0f1826; --border:#243244;
  --ink:#e7eef7; --ink-2:#a7b6c9; --ink-3:#75869a; --accent:#2aa5d8; --accent-2:#4cc4ef;
  --accent-3:#4cc4ef; --oro-suave:#0b2433; --oro-borde:#16435c;
  --oro-texto:var(--accent);
  --navy:#0f1826; --navy-2:#1a2740; --navy-ink:#e8eef7;
  --accent-ink:#04121c; --foco:var(--accent-2); --good:#4ade80; --good-bg:#0e2a1a; --warn:#fbbf24; --warn-bg:#2a1f07;
  --crit:#f87171; --crit-bg:#2a1212; --neutral:#94a3b8; --neutral-bg:#1e293b; --info:#60a5fa; --info-bg:#0f1e3a;
  --shadow:0 1px 2px rgba(0,0,0,.4),0 10px 30px rgba(0,0,0,.35);
}
*{box-sizing:border-box}
body{margin:0;background:var(--bg);color:var(--ink);font-family:var(--sans);
  font-size:14px;line-height:1.45;-webkit-font-smoothing:antialiased}
h1,h2,h3{margin:0;font-weight:650;letter-spacing:-.01em}
a{color:var(--accent);text-decoration:none}
a:hover{text-decoration:underline}
button{font-family:inherit;cursor:pointer}
.tnum{font-variant-numeric:tabular-nums}

/* ---- cabecera y menu lateral ----
   El ancho del menu es una variable en :root y no un numero repetido, porque
   `main` y el aviso de la IA se apartan con ella: al plegar el menu basta
   cambiar la variable en <body> y todo lo demas se recoloca solo. Sin esto
   habria que acordarse de tocar tres reglas a la vez, y la que se olvida deja
   una franja vacia que nadie sabe de donde sale. */
:root{
  --nav-w:236px;      /* desplegado: icono + etiqueta + contador */
  --nav-w-min:64px;   /* plegado: solo el icono, centrado */
  --head-h:56px;
  --ease:cubic-bezier(.4,0,.2,1);
}
body[data-nav="min"]{--nav-w:var(--nav-w-min)}

header{position:fixed;top:0;left:0;right:0;height:var(--head-h);z-index:40;
  background:var(--surface);border-bottom:1px solid var(--border);
  display:flex;align-items:center;gap:14px;padding:0 16px}
.brand{display:flex;align-items:center;gap:10px;font-weight:700;letter-spacing:-.02em}
.brand .mark{width:26px;height:26px;border-radius:7px;display:block;
  object-fit:contain;flex:none}
/* El logo del login. Centrado y con aire debajo; en pantallas cortas se
   encoge en vez de empujar el formulario fuera de la vista. */
.logo-login{display:block;margin:0 auto 14px;width:72px;height:72px;object-fit:contain}
@media (max-height:640px){.logo-login{width:52px;height:52px;margin-bottom:10px}}
.brand small{display:block;font-weight:500;color:var(--ink-3);font-size:11px;letter-spacing:.02em}
.spacer{flex:1}

/* Los iconos de la interfaz: un solo trazo, un solo tamaño, y el color lo
   heredan del texto de al lado. Asi un icono nunca se queda con el color del
   tema anterior al cambiar de claro a oscuro. */
svg{width:20px;height:20px;flex:none;fill:none;stroke:currentColor;
  stroke-width:1.75;stroke-linecap:round;stroke-linejoin:round}

.iconbtn,.navtoggle{border:1px solid var(--border);background:var(--surface-2);
  color:var(--ink-2);width:36px;height:36px;border-radius:9px;display:grid;
  place-items:center;transition:background .16s var(--ease),color .16s var(--ease),
  border-color .16s var(--ease)}
.iconbtn:hover,.navtoggle:hover{color:var(--ink);border-color:var(--accent)}

/* En pantalla tactil, 44x44. Los 36 de arriba son comodos con un raton y
   quedan por debajo del minimo de un dedo -- en el menu lateral ya se
   arreglo subiendo la fila a 44 bajo 900px, y la cabecera se habia quedado
   fuera. `pointer:coarse` y no un ancho: lo que manda aqui es con que se
   toca, no lo grande que es la pantalla (una tablet ancha se toca con el
   dedo igual). El icono no crece: crece el area que acepta el toque. */
@media (pointer:coarse){
  .iconbtn,.navtoggle{position:relative}
  /* El area, no la caja: subir el boton a 44px de alto lo sacaria de la
     barra (56px con su relleno, y 48 cuando la de la portada se condensa al
     bajar). El pseudoelemento centra 44x44 de zona sensible sobre un boton
     que se sigue viendo de 36 y no mueve nada de su alrededor. */
  .iconbtn::after,.navtoggle::after{content:"";position:absolute;top:50%;left:50%;
    transform:translate(-50%,-50%);width:44px;height:44px}
}
.navtoggle{border-color:transparent;background:transparent}

.sidenav{position:fixed;top:var(--head-h);left:0;bottom:0;z-index:35;
  width:var(--nav-w);background:var(--surface);border-right:1px solid var(--border);
  padding:12px 10px;display:flex;flex-direction:column;gap:2px;overflow-y:auto;
  transition:width .18s var(--ease)}
.sidenav .tab{display:flex;align-items:center;gap:12px;width:100%;
  border:1px solid transparent;background:transparent;color:var(--ink-2);
  padding:0 12px;height:40px;border-radius:9px;font-weight:600;font-size:13.5px;
  text-align:left;white-space:nowrap;overflow:hidden;
  transition:background .16s var(--ease),color .16s var(--ease)}
.sidenav .tab:hover{background:var(--surface-2);color:var(--ink)}
/* La seccion abierta se marca con fondo Y con una barra a la izquierda: el
   color solo no basta para quien no lo distingue, y es el unico sitio de la
   pantalla donde saber "donde estoy" no admite una segunda lectura. */
/* La entrada en la que estas. Antes era [aria-selected="true"], de cuando
   estos botones decian ser un `role="tab"` sin `tablist` que los contuviera
   ni `tabpanel` al otro lado -- ARIA a medias, que para un lector de
   pantalla no es una pestaña sino un boton suelto que dice estar
   seleccionado. Son navegacion entre vistas, y lo que marca la vista actual
   dentro de un <nav> es aria-current. */
.sidenav .tab[aria-current="page"]{background:var(--surface-2);color:var(--ink);
  box-shadow:inset 3px 0 0 var(--accent)}
.sidenav .tab .lbl{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}
.sidenav .tab .badge{background:var(--accent);color:var(--accent-ink);
  border-radius:20px;padding:1px 7px;font-size:11px;font-weight:700;flex:none}

/* Plegado: el icono se centra y la etiqueta desaparece. El contador no se
   esconde -- se reduce a un punto sobre el icono: si tienes alertas sin ver,
   plegar el menu no puede ser la forma de dejar de enterarte. */
body[data-nav="min"] .sidenav .tab{padding:0;justify-content:center}
/* Plegado, la etiqueta se oculta A LA VISTA pero NO se retira: `display:none`
   la saca tambien del arbol de accesibilidad y deja el boton sin nombre, con
   el `title` como unico apoyo -- que es justo el que los lectores de pantalla
   tratan de formas distintas. Asi el menu plegado sigue diciendo "Alertas" a
   quien lo escucha. */
body[data-nav="min"] .sidenav .tab .lbl{position:absolute;width:1px;height:1px;
  padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
body[data-nav="min"] .sidenav .tab .badge{position:absolute;margin-left:22px;
  margin-top:-16px;min-width:8px;padding:0;height:8px;width:8px;
  font-size:0;line-height:0}
body[data-nav="min"] .sidenav .tab{position:relative}

.navscrim{position:fixed;inset:0;z-index:34;background:rgba(2,8,20,.45)}

main{margin-left:var(--nav-w);padding:calc(var(--head-h) + 18px) 20px 60px;
  transition:margin-left .18s var(--ease)}
main > section{max-width:1500px;margin:0 auto}

/* ---- KPI tiles ---- */
/* LAS CIFRAS DE UNA PANTALLA: UNA TIRA, NO TARJETAS.
   Fueron tarjetas hasta el 2026-09-19, y el motivo del cambio es que un
   recuadro ocupa sitio POR SI MISMO: borde, sombra y relleno, cuatro o
   cinco veces, encima de la lista que es lo que se viene a mirar. En un
   portatil se comian la primera pantalla. Sin caja, con el icono, el numero
   y su palabra en la misma linea, lo mismo cabe en un renglon de ~22px
   donde habia un bloque de ~62. Se envuelven solas en un telefono.

   VA EN LA CLASE y no acotado a #kpis: la comparten el buscador, "Mis
   procesos" y la pantalla de Salud del panel, y las tres pintan ya la misma
   estructura (icono + numero + palabra). Estuvo un rato acotado porque una
   de ellas seguia con la estructura vieja, y eso es exactamente lo que no
   debe quedarse: dos aspectos para el mismo dato en la misma aplicacion. */
.kpis{display:flex;flex-wrap:wrap;align-items:center;gap:6px 18px;
  margin-bottom:12px}
.kpi{display:inline-flex;align-items:center;gap:6px;min-width:0}
/* El icono NO se encoge: sin `flex:none`, una cifra larga (los resultados
   pasan de 100.000) lo aplasta en vez de recortarse ella. */
.kpi .ico{width:15px;height:15px;flex:none;stroke:var(--ink-3);fill:none;
  stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
/* Sin versalitas ni espaciado de letras: en dos palabras y a este tamano se
   leen peor y ocupan mas ancho, que es justo lo que sobra aqui. */
.kpi .lbl{font-size:12px;color:var(--ink-3);font-weight:500;white-space:nowrap}
/* El numero sigue siendo lo grande de la tira -- es lo que se mira de reojo
   -- pero 15px al lado de su palabra pesa lo mismo que 26px dentro de una
   tarjeta, porque ya no compite con un recuadro. */
.kpi .val{font-size:15px;font-weight:700;line-height:1;letter-spacing:-.01em}
.kpi .val small{font-size:11px;color:var(--ink-2);font-weight:600}
/* Sin caja no hay borde donde poner una barra de acento: el acento es el
   color del numero y del icono, que es lo que se ve. */
.kpi.accent .val{color:var(--accent)}
.kpi.accent .ico{stroke:var(--accent)}

/* ---- filters ---- */
.panel{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
  box-shadow:var(--shadow)}
/* Cuatro columnas IGUALES, no 2fr/1.4fr/1fr/1fr/1fr. Con anchos distintos
   los cuatro campos con etiqueta salian de cuatro tamanos y la fila se veia
   desalineada; iguales, quedan en rejilla. La busqueda y los conmutadores
   ocupan el ancho entero y por eso no compiten por esas columnas. */
.filters{padding:14px 16px;margin-bottom:14px;display:grid;
  grid-template-columns:repeat(4,1fr);gap:10px 12px;align-items:end}
.filters .campoq{grid-column:1/-1}
.field{display:flex;flex-direction:column;gap:4px;min-width:0}
.field label{font-size:11px;font-weight:600;color:var(--ink-2);text-transform:uppercase;letter-spacing:.04em}
.field input,.field select{width:100%;padding:8px 10px;border:1px solid var(--border);
  border-radius:9px;background:var(--surface-2);color:var(--ink);font-size:13px;font-family:inherit}
.field input:focus,.field select:focus{outline:2px solid var(--foco);outline-offset:-1px;border-color:var(--accent)}
/* Los tres conmutadores, en su propia fila debajo de la busqueda (orden de
   la maqueta del socio humano, 2026-09-19). Sin filete arriba: van pegados a
   la caja de busqueda a proposito, porque acotan lo que se acaba de escribir
   -- el filete separa esto de los desplegables, no de la busqueda. */
.filters .conmutadores{grid-column:1/-1;display:flex;gap:14px;align-items:center;
  flex-wrap:wrap;padding-bottom:8px;border-bottom:1px solid var(--border)}
.filters .row2{grid-column:1/-1;display:flex;gap:14px;align-items:center;flex-wrap:wrap;
  padding-top:6px;border-top:1px solid var(--border);margin-top:2px}
.chk{display:flex;align-items:center;gap:7px;font-size:13px;color:var(--ink-2);font-weight:500}
.chk input{width:16px;height:16px;accent-color:var(--accent)}
.montos{display:flex;align-items:center;gap:6px}
.montos input{width:120px}
.kwrow{grid-column:1/-1;display:flex;flex-wrap:wrap;align-items:center;gap:8px;
  padding-top:10px;margin-top:4px;border-top:1px dashed var(--border)}
.kwlabel{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;color:var(--ink-2)}
.kwchips{display:flex;flex-wrap:wrap;gap:6px}
.kwchip{display:inline-flex;align-items:center;gap:6px;background:var(--info-bg);color:var(--info);
  border:1px solid transparent;border-radius:20px;padding:3px 6px 3px 11px;font-size:12px;font-weight:600}
.kwchip button{background:none;border:none;color:inherit;font-size:14px;line-height:1;cursor:pointer;opacity:.7}
.kwchip button:hover{opacity:1}
.kwadd{padding:6px 10px;border:1px solid var(--border);border-radius:20px;background:var(--surface-2);
  color:var(--ink);font-size:12.5px;width:190px;font-family:inherit}
.kwnote{font-size:11.5px;color:var(--ink-3);flex-basis:100%}
.kwrow.off{opacity:.45;pointer-events:none}
#exclChips .kwchip{background:var(--crit-bg);color:var(--crit)}
.savedbar{grid-column:1/-1;display:flex;flex-wrap:wrap;align-items:center;gap:8px;
  padding-top:10px;margin-top:4px;border-top:1px dashed var(--border)}
.savedbar select{padding:7px 10px;border:1px solid var(--border);border-radius:9px;
  background:var(--surface-2);color:var(--ink);font-size:13px;font-family:inherit;min-width:170px}
.foot{margin-top:18px;color:var(--ink-3);font-size:12px;display:flex;gap:16px;flex-wrap:wrap;
  border-top:1px solid var(--border);padding-top:12px}
.foot b{color:var(--ink-2);font-weight:600}
.btn{border:1px solid var(--border);background:var(--surface-2);color:var(--ink);
  padding:8px 14px;border-radius:9px;font-weight:600;font-size:13px}
.btn.primary{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
.btn:hover{border-color:var(--accent)}

/* ---- table ---- */
.count .pista{color:var(--ink-3)}
.count .pista::before{content:" · "}

.tablewrap{overflow-x:auto;border-radius:var(--radius)}
table.grid{width:100%;border-collapse:collapse;font-size:13px;min-width:900px}
table.grid thead th{position:sticky;top:0;background:var(--surface-2);text-align:left;
  padding:10px 12px;font-size:11px;text-transform:uppercase;letter-spacing:.04em;
  color:var(--ink-2);font-weight:650;border-bottom:1px solid var(--border);white-space:nowrap;cursor:pointer;user-select:none}
table.grid thead th .arrow{color:var(--accent);font-size:10px}
table.grid tbody td{padding:10px 12px;border-bottom:1px solid var(--border);vertical-align:top}
table.grid tbody tr{cursor:pointer}
table.grid tbody tr:hover{background:var(--surface-2)}

/* ---- la espera, con la forma de lo que va a llegar ----------------------
   Antes decia "Cargando…" en una linea debajo de una tabla vacia: la lista
   se encogia a nada, aparecia el texto y al llegar los datos todo volvia a
   dar un salto. Ahora la espera ocupa el sitio que van a ocupar las filas,
   asi que no hay salto -- y de paso dice cuanto viene, que un texto suelto
   no dice.

   El brillo que recorre la barra es lo unico que se mueve, y la regla de
   "reducir movimiento" de mas abajo lo para como todo lo demas. */
.skelrow td{pointer-events:none}
.skel{display:block;height:11px;border-radius:6px;background:var(--surface-2);
  background-image:linear-gradient(90deg,transparent,
    color-mix(in srgb,var(--ink) 7%,transparent),transparent);
  background-size:220% 100%;animation:brilla 1.2s ease-in-out infinite}
.skel.chica{height:9px;margin-top:7px;opacity:.65}
@keyframes brilla{from{background-position:220% 0}to{background-position:-220% 0}}
.nom{font-weight:600;color:var(--ink)}
.obj{color:var(--ink-2);font-size:12.5px;max-width:420px;display:-webkit-box;-webkit-line-clamp:2;
  -webkit-box-orient:vertical;overflow:hidden}
.ent{color:var(--ink-2);max-width:230px}
.val{text-align:right;font-weight:600;white-space:nowrap}
.val .prot{color:var(--ink-3);font-weight:500;font-style:italic;font-size:12px}
.star{background:none;border:none;font-size:17px;line-height:1;color:var(--ink-3);padding:2px 4px}
.star.on{color:#f5a623}
.score{display:inline-flex;align-items:center;gap:6px;font-weight:700;color:var(--ink)}
.score .bar{width:34px;height:6px;border-radius:4px;background:var(--neutral-bg);overflow:hidden}
.score .bar i{display:block;height:100%;background:linear-gradient(90deg,var(--accent),var(--accent-2))}
.pill{display:inline-block;padding:2px 9px;border-radius:20px;font-size:11px;font-weight:650;white-space:nowrap}
.pill.works{background:var(--warn-bg);color:var(--warn)}
.pill.goods{background:var(--info-bg);color:var(--info)}
.pill.services{background:var(--neutral-bg);color:var(--neutral)}
.chip{display:inline-block;background:var(--surface-2);border:1px solid var(--border);
  border-radius:20px;padding:2px 9px;font-size:11px;color:var(--ink-2);margin:2px 3px 0 0}
.empty{padding:60px 20px;text-align:center;color:var(--ink-3)}
.count{color:var(--ink-2);font-size:13px;margin:0 2px 8px}

/* ---- drawer ---- */
.scrim{position:fixed;inset:0;background:rgba(6,12,20,.5);opacity:0;pointer-events:none;
  transition:opacity .2s;z-index:40}
.scrim.open{opacity:1;pointer-events:auto}
.drawer{position:fixed;top:0;right:0;height:100%;width:min(560px,94vw);background:var(--surface);
  border-left:1px solid var(--border);box-shadow:var(--shadow);z-index:50;
  transform:translateX(100%);transition:transform .24s cubic-bezier(.4,0,.2,1);
  display:flex;flex-direction:column}
.drawer.open{transform:none}
.drawer .dhead{padding:18px 20px;border-bottom:1px solid var(--border);display:flex;gap:12px;align-items:flex-start}
.drawer .dhead h2{font-size:16px;line-height:1.3}
.drawer .dhead .sub{color:var(--ink-2);font-size:13px;margin-top:3px}
.drawer .dbody{overflow-y:auto;padding:6px 20px 30px}
.drawer .close{margin-left:auto;font-size:20px;background:none;border:none;color:var(--ink-3);line-height:1}
.sec{padding:16px 0;border-bottom:1px solid var(--border)}
.sec h3{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--ink-3);margin-bottom:10px}
.kv{display:grid;grid-template-columns:130px 1fr;gap:6px 12px;font-size:13px}
.kv dt{color:var(--ink-3)}
.kv dd{margin:0;color:var(--ink);font-weight:500}
.timeline{list-style:none;padding:0;margin:0;position:relative}
.timeline li{position:relative;padding:0 0 14px 22px;border-left:2px solid var(--border);margin-left:5px}
.timeline li:last-child{border-color:transparent}
.timeline li::before{content:"";position:absolute;left:-6px;top:2px;width:10px;height:10px;
  border-radius:50%;background:var(--accent);border:2px solid var(--surface)}
.timeline .etapa{font-weight:650;font-size:13px}
.timeline .fecha{color:var(--ink-2);font-size:12.5px}
.doc{display:flex;gap:10px;align-items:baseline;padding:7px 0;border-bottom:1px dashed var(--border)}
.doc:last-child{border:none}
.doc .dt{font-size:12px;color:var(--ink-3);white-space:nowrap;min-width:78px}
.docgroup{margin-bottom:8px}
.docgroup .gl{font-size:12px;font-weight:700;color:var(--ink-2);margin:8px 0 2px}
.reglist{columns:2;font-size:12.5px;color:var(--ink-2)}
.reglist div{break-inside:avoid;padding:2px 0}
.mini{width:100%;border-collapse:collapse;font-size:12.5px}
.mini td,.mini th{text-align:left;padding:5px 8px;border-bottom:1px solid var(--border)}
.mini th{color:var(--ink-3);font-weight:600;font-size:11px;text-transform:uppercase}
.dfoot{padding:14px 20px;border-top:1px solid var(--border);display:flex;gap:10px;background:var(--surface-2)}
.dfoot .btn{flex:1;text-align:center}

/* ---- CRM ---- */
.crmbar{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-bottom:14px}
.statcount{display:flex;gap:8px;flex-wrap:wrap}
.st-pill{padding:4px 12px;border-radius:20px;font-size:12px;font-weight:650;border:1px solid transparent}
.st-Por.evaluar{}
.est-porevaluar{background:var(--warn-bg);color:var(--warn)}
.est-vamos{background:var(--good-bg);color:var(--good)}
.est-preparacion{background:var(--info-bg);color:var(--info)}
.est-presentado{background:color-mix(in srgb,#8b5cf6 14%,var(--surface));color:var(--est-presentado-txt)}
.est-perdido{background:var(--crit-bg);color:var(--crit)}
.est-ganado{background:var(--good-bg);color:var(--good);border-color:var(--good)}
.est-descartado{background:var(--neutral-bg);color:var(--neutral)}
.crmcard{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
  box-shadow:var(--shadow);padding:14px 16px;margin-bottom:12px;display:grid;
  grid-template-columns:1fr 200px;gap:12px 18px}
.crmcard .main .nom{font-size:14px}
.crmcard .main .ent{max-width:none;margin-top:2px}
.crmcard .meta{display:flex;gap:8px;flex-wrap:wrap;margin-top:8px;align-items:center}
.crmcard .side{display:flex;flex-direction:column;gap:8px}
.crmcard select,.crmcard input,.crmcard textarea{padding:7px 9px;border:1px solid var(--border);
  border-radius:8px;background:var(--surface-2);color:var(--ink);font-family:inherit;font-size:12.5px;width:100%}
.crmcard textarea{grid-column:1/-1;resize:vertical;min-height:38px}
.crmcard .acts{display:flex;gap:8px;margin-top:2px}
.linklike{background:none;border:none;color:var(--accent);font-weight:600;font-size:12.5px;padding:0}
.danger{color:var(--crit)}
@media (max-width:720px){
  .filters{grid-template-columns:1fr 1fr}
  .crmcard{grid-template-columns:1fr}
  .brand small{display:none}
}

/* ================= añadidos del Monitor (no estaban en el prototipo) ===== */

/* El atributo hidden debe ganar SIEMPRE.
   La hoja del navegador trae [hidden]{display:none}, pero cualquier regla de
   autor que fije display la pisa: .loginwrap{display:grid} dejaba la pantalla
   de login visible aunque el JS pusiera hidden=true, y la app quedaba
   renderizada debajo del scroll. Sin este !important el login no se cierra. */
[hidden] { display: none !important; }

/* ---- login ---- */
.loginwrap{min-height:100vh;display:grid;place-items:center;padding:20px}
.logincard{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
  box-shadow:var(--shadow);padding:28px;width:min(380px,100%)}
.logincard h1{font-size:19px;margin-bottom:4px}
.logincard p.sub{color:var(--ink-3);font-size:13px;margin:0 0 18px}
.logincard .field{margin-bottom:12px}
.logincard .btn{width:100%;margin-top:6px}
.loginerr{background:var(--crit-bg);color:var(--crit);padding:9px 12px;border-radius:9px;
  font-size:12.5px;margin-bottom:12px}

/* ---- badge de frescura ---- */
/* `.fresh` (el estado de la ultima ingesta) se retiro el 2026-09-19 con el
   elemento que lo usaba: salia de GET /api/estado, que es del desarrollador,
   asi que para un cliente nunca decia nada. En su sitio va `.planchip`. */
.userchip{font-size:12.5px;color:var(--ink-2);display:flex;align-items:center;gap:8px}
/* EL PLAN, en la cabecera. Mismo lenguaje que los `chip` del resto de la
   pantalla: pastilla, borde y fondo tenue. */
.planchip{font-size:12px;font-weight:650;color:var(--ink-2);
  background:var(--surface-2);border:1px solid var(--border);border-radius:20px;
  padding:5px 12px;white-space:nowrap}
/* El color acompana al texto, no lo sustituye: quien no distingue el matiz
   lee "prueba" o "suspendida" igual, porque la palabra esta escrita. */
.planchip.tibio{background:var(--warn-bg);color:var(--warn);border-color:transparent}
.planchip.mal{background:var(--crit-bg);color:var(--crit);border-color:transparent}
/* Cerrar sesion, al pie del menu lateral. `margin-top:auto` lo empuja al
   fondo del <nav> (que es flex en columna) aunque manana haya mas secciones
   o menos. El color tenue lo separa de las secciones sin gritar: es una
   salida, no un destino. */
.tabsalir{margin-top:auto;color:var(--ink-3) !important}
.tabsalir:hover{color:var(--crit) !important;background:var(--crit-bg) !important}

/* ---- relevancia de la IA ---- */
.rel{display:inline-flex;align-items:center;gap:6px;font-weight:700;white-space:nowrap}
.rel .bar{width:40px;height:6px;border-radius:4px;background:var(--neutral-bg);overflow:hidden;flex:none}
.rel .bar i{display:block;height:100%;background:linear-gradient(90deg,var(--accent),var(--accent-2))}
.rel.no{color:var(--ink-3);font-weight:500}
.motivo{color:var(--ink-3);font-size:11.5px;font-style:italic;margin-top:2px;
  max-width:260px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}

/* ---- plazo de cotizacion ---- */
.plazo{white-space:nowrap;font-weight:600}
.plazo.hoy{color:var(--crit)}
.plazo.pronto{color:var(--warn)}
.plazo.vencido{color:var(--ink-3);font-weight:500;text-decoration:line-through}

.rubro-tag{display:inline-block;padding:2px 9px;border-radius:20px;font-size:11px;font-weight:650;
  background:var(--info-bg);color:var(--info);white-space:nowrap}

.loading{padding:50px;text-align:center;color:var(--ink-3)}
.pager{display:flex;gap:8px;align-items:center;justify-content:center;padding:14px}
.pager button[disabled]{opacity:.4;cursor:default}
.toast{position:fixed;bottom:22px;left:50%;transform:translateX(-50%);background:var(--ink);
  color:var(--bg);padding:10px 18px;border-radius:9px;font-size:13px;z-index:99;
  box-shadow:var(--shadow);opacity:0;transition:opacity .2s;pointer-events:none}
.toast.on{opacity:1}

/* ---- pestaña Horarios ---- */
.schedpanel{padding:16px 18px;margin-bottom:14px}
.schedpanel h3{font-size:14px;margin-bottom:6px;display:flex;align-items:center;gap:9px}
.schedpanel > .kwnote{margin:0 0 12px}
.schedpanel input[type="time"]{padding:8px 10px;border:1px solid var(--border);border-radius:9px;
  background:var(--surface-2);color:var(--ink);font-family:var(--mono);font-size:14px}
.schedpanel .chk{margin-right:14px}
.horalist{display:flex;flex-wrap:wrap;gap:10px;margin-bottom:14px}
.horaitem{display:flex;align-items:center;gap:8px;background:var(--surface-2);
  border:1px solid var(--border);border-radius:10px;padding:8px 10px}
.horaitem .num{font-size:11px;font-weight:700;color:var(--ink-3);text-transform:uppercase}
.horaitem button{background:none;border:none;color:var(--crit);font-size:16px;line-height:1;
  cursor:pointer;opacity:.65;padding:0 2px}
.horaitem button:hover{opacity:1}
.horaadd{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  border-top:1px dashed var(--border);padding-top:12px}
.savebar{display:flex;align-items:center;gap:12px;flex-wrap:wrap}
#manualPanel .acts{display:flex;gap:9px;flex-wrap:wrap}
.runout{background:var(--surface-2);border:1px solid var(--border);border-radius:9px;
  padding:11px 13px;font-family:var(--mono);font-size:12px;color:var(--ink-2);
  margin-top:12px;white-space:pre-wrap;max-height:220px;overflow:auto}

/* ---- pestaña Notificaciones (canales de aviso) ---- */
.canalfields{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));
  gap:10px 12px;margin-top:10px}
.canalacts{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:12px;
  padding-top:10px;border-top:1px dashed var(--border)}
.canalacts .kwnote{flex-basis:auto}
.timeline-dia{display:flex;align-items:center;gap:0;margin-top:4px;height:34px;position:relative;
  background:var(--surface-2);border:1px solid var(--border);border-radius:8px;overflow:hidden}
.timeline-dia .marca{position:absolute;top:0;bottom:0;width:2px;background:var(--accent)}
.timeline-dia .marca.barr{background:var(--ink-3)}
.timeline-dia .marca.res{background:var(--good)}
.timeline-dia .hora{position:absolute;top:2px;font-size:9px;color:var(--ink-3);transform:translateX(-50%)}
.fuente-tag{display:inline-block;margin-top:4px;font-size:10px;font-weight:700;letter-spacing:.03em;
  text-transform:uppercase;color:var(--ink-3);background:var(--surface-2);border:1px solid var(--border);
  border-radius:20px;padding:1px 8px}
.fuente-tag.mayor{color:var(--warn);background:var(--warn-bg);border-color:transparent}

/* ---- login: ver contraseña y recordar ---- */
.claveWrap{position:relative;display:flex;align-items:center}
.claveWrap input{padding-right:42px;width:100%}
.ojito{position:absolute;right:6px;background:none;border:none;font-size:16px;
  line-height:1;padding:6px;opacity:.55;border-radius:7px}
.ojito:hover{opacity:1;background:var(--surface-2)}
.ojito.on{opacity:1}
.ojito:focus-visible{outline:2px solid var(--foco);outline-offset:-1px}
.olvide{display:block;text-align:center;margin-top:14px;font-size:13px;color:var(--ink-2)}
.olvide:hover{color:var(--ink)}
.legal-login{text-align:center;margin:10px 0 0;font-size:12px;color:var(--ink-3)}
.legal-login a{color:var(--ink-3)}
#terminosDlg a{color:inherit;font-weight:650}
.recordar{margin:2px 0 4px;font-size:13px;color:var(--ink-2);cursor:pointer;user-select:none}

/* ---- pestaña Usuarios ---- */
.usrform{display:grid;grid-template-columns:1.4fr 1.4fr 1.2fr .8fr auto;gap:10px 12px;align-items:end}
.usrform .field label{font-size:11px}
.usrcard{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
  box-shadow:var(--shadow);padding:13px 16px;margin-bottom:10px;display:grid;
  grid-template-columns:1fr 150px 120px auto;gap:10px 16px;align-items:center}
.usrcard.inactivo{opacity:.55}
.usrcard .quien{min-width:0}
.usrcard .quien .nom{font-weight:650}
.usrcard .quien .mail{color:var(--ink-2);font-size:12.5px;overflow:hidden;text-overflow:ellipsis}
.usrcard .quien .meta{color:var(--ink-3);font-size:11.5px;margin-top:3px}
.usrcard select,.usrcard input{padding:7px 9px;border:1px solid var(--border);border-radius:8px;
  background:var(--surface-2);color:var(--ink);font-family:inherit;font-size:12.5px;width:100%}
.usrcard .acts{display:flex;gap:8px;align-items:center;white-space:nowrap}
/* Mis alertas: tres piezas (quien, chat_id, botones) y no las cuatro de
   Usuarios. Con la plantilla de cuatro los botones caian en la columna de
   120 px y "Guardando…" empujaba "Probar" fuera de la tarjeta. El ancho
   minimo del boton evita que la fila salte al cambiar el texto. */
#destinosList .usrcard{grid-template-columns:minmax(0,1fr) minmax(140px,220px) auto}
#destinosList [data-guardar-destino]{min-width:9em}
#destinosList [data-probar-destino],#destinosList [data-probar-correo]{min-width:8.4em}
#destinosList [data-probar-correo][disabled]{opacity:.5;cursor:not-allowed}
.rolpill{display:inline-block;padding:1px 9px;border-radius:20px;font-size:10.5px;font-weight:700;
  text-transform:uppercase;letter-spacing:.03em}
.rolpill.admin{background:var(--warn-bg);color:var(--warn)}
.rolpill.vendedor{background:var(--neutral-bg);color:var(--neutral)}
.yopill{background:var(--info-bg);color:var(--info);padding:1px 8px;border-radius:20px;
  font-size:10.5px;font-weight:700;margin-left:6px}
@media (max-width:900px){
  .usrform{grid-template-columns:1fr 1fr}
  .usrcard,#destinosList .usrcard{grid-template-columns:1fr}
}

/* ---- pestaña Alertas ---- */
.rango{display:flex;align-items:center;gap:6px}
.rango .rangolbl{font-size:11px;color:var(--ink-2);font-weight:600;
  text-transform:uppercase;letter-spacing:.04em}
.rango input{padding:7px 9px;border:1px solid var(--border);border-radius:8px;
  background:var(--surface-2);color:var(--ink);font-family:inherit;font-size:12.5px}

/* Las tarjetas de estado filtran al pulsarlas: son el atajo real a "y las
   omitidas?", que si no queda escondido dentro de un desplegable. */

.alpill{display:inline-block;padding:2px 9px;border-radius:20px;font-size:10.5px;
  font-weight:700;text-transform:uppercase;letter-spacing:.03em;white-space:nowrap}
.alpill.enviada{background:var(--good-bg);color:var(--good)}
.alpill.omitida{background:var(--crit-bg);color:var(--crit)}
.alpill.pendiente{background:var(--info-bg);color:var(--info)}
.alpill.telegram{background:var(--info-bg);color:var(--info)}
/* .rolpill.gerente: la plataforma nueva usa roles gerente/vendedor/
   desarrollador, no vendedor/admin como el producto viejo -- mismo color que
   tenia "admin" para no perder el contraste entre los dos roles de empresa. */
.rolpill.gerente{background:var(--warn-bg);color:var(--warn)}
.alwhen{color:var(--ink-2);font-size:12px;margin-top:4px;white-space:nowrap}
.alre{color:var(--warn);font-size:11px;font-weight:600;margin-top:2px;white-space:nowrap}

table.grid.alertas{min-width:1150px}

/* ---- las dos listas, en un telefono ------------------------------------
   Debajo de 720px la tabla deja de ser tabla y cada fila pasa a ser una
   tarjeta. El envoltorio tiene overflow-x:auto, asi que antes de esto la
   lista no rompia el diseño -- pero se leia a empujones: 900px de ancho
   minimo (1150 en alertas) en una pantalla de 360, con el objeto de la
   convocatoria, que es lo unico que se lee de verdad, partido en una
   columna de tres palabras.

   Se ordena con `order` y no se toca el HTML: la fila la pinta el
   JavaScript y el orden de sus celdas es el que tiene sentido en una tabla.
   Lo que cambia aqui es COMO SE APILAN, no lo que hay.

   Los `nth-child` van contados desde el <thead> de index.html, y por eso
   cada uno lleva escrito al lado de que columna es: renumerarlos a ciegas
   cuando alguien añada una columna es exactamente el fallo que este
   comentario existe para evitar. */
@media (max-width:720px){
  table.grid,table.grid tbody,table.grid tr,table.grid td{display:block}
  table.grid{min-width:0;font-size:13.5px}
  table.grid.alertas{min-width:0}
  table.grid thead{display:none}
  /* El borde inferior vivia en el <td> (regla base de mas arriba) y aqui se
     quita con `border:none` -- sin devolverselo a la fila, las "tarjetas" se
     leen como un unico bloque continuo de texto, que es justo lo que este
     bloque venia a arreglar. */
  table.grid tbody tr{position:relative;display:flex;flex-wrap:wrap;
    align-items:baseline;gap:5px 10px;padding:12px 46px 12px 13px;
    border-bottom:1px solid var(--border)}
  table.grid tbody tr:last-child{border-bottom:none}
  table.grid tbody td{padding:0;border:none}
  /* Lo importante, entero y arriba; lo demas, en una tira de chips. Son los
     chips que la fila ya trae (rubro, plazo, relevancia), no etiquetas con
     el nombre de la columna: esas NO existen aqui -- ver el comentario de
     los roles en index.html. */
  /* max-width:none a la fuerza: la regla base de .ent lo deja en 230px y
     el `flex:1 0 100%` se quedaba en un salto de linea sin ancho. */
  table.grid tbody td.ent{flex:1 0 100%;max-width:none;
    font-size:12px;color:var(--ink-3)}
  table.grid tbody td.val{text-align:left}

  /* Buscador: 1 estrella | 2 relevancia | 3 publicado | 4 entidad |
     5 nomenclatura+objeto | 6 rubro+fuente | 7 plazo | 8 valor */
  #tbl tbody td:nth-child(5){order:1;flex:1 0 100%}
  #tbl tbody td:nth-child(4){order:2}
  #tbl tbody td:nth-child(2){order:3}
  #tbl tbody td:nth-child(6){order:4}
  #tbl tbody td:nth-child(7){order:5}
  #tbl tbody td:nth-child(8){order:6;font-weight:650}
  #tbl tbody td:nth-child(3){order:7;font-size:11.5px;color:var(--ink-3)}
  #tbl tbody td:nth-child(1){position:absolute;top:9px;right:9px;order:0}

  /* Alertas: 1 estrella | 2 estado+fecha | 3 canal | 4 relevancia | 5 entidad |
     6 nomenclatura+objeto | 7 rubro+fuente | 8 plazo | 9 valor |
     10 acciones */
  #alTbl tbody td:nth-child(6){order:1;flex:1 0 100%}
  #alTbl tbody td:nth-child(5){order:2}
  #alTbl tbody td:nth-child(4){order:3}
  #alTbl tbody td:nth-child(7){order:4}
  #alTbl tbody td:nth-child(8){order:5}
  #alTbl tbody td:nth-child(9){order:6;font-weight:650}
  #alTbl tbody td:nth-child(3){order:7;font-size:11.5px;color:var(--ink-3)}
  #alTbl tbody td:nth-child(2){order:8;font-size:11.5px;color:var(--ink-3)}
  /* Las acciones, en su propia linea y al final: son lo ultimo que se hace
     con la tarjeta, y en la tira de etiquetas serian un boton entre datos. */
  #alTbl tbody td:nth-child(10){order:9;flex:1 0 100%;text-align:left;
    margin-top:4px}
  #alTbl tbody td:nth-child(1){position:absolute;top:9px;right:9px;order:0}
}
.alacts{display:flex;gap:6px;justify-content:flex-end;white-space:nowrap}
.alacts .btn{padding:5px 10px;font-size:12px}
.kpi.ojo{border-top:3px solid var(--warn)}
.rango select{padding:7px 9px;border:1px solid var(--border);border-radius:8px;
  background:var(--surface-2);color:var(--ink);font-family:inherit;font-size:12.5px}
.btn.linkbtn{padding:5px 9px;font-size:12px;line-height:1}

/* ---- pestaña Mensajes ---- */
/* Sin leer se distingue por TEXTO ("Sin leer") ademas de por color: quien no
   distingue el tono de fondo tiene que poder verlo igual. El color es solo
   refuerzo, nunca la unica pista. */
.msgcard{padding:14px 16px;margin-bottom:10px;display:flex;gap:14px;
  align-items:flex-start;justify-content:space-between}
.msgcard.noleido{border-left:3px solid var(--info)}
.msghead{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.msgasunto{font-weight:700;font-size:13.5px}
.msgcard.noleido .msgasunto{color:var(--ink)}
.msgnuevo{display:inline-block;background:var(--info-bg);color:var(--info);
  border-radius:20px;padding:1px 9px;font-size:10.5px;font-weight:700;
  text-transform:uppercase;letter-spacing:.03em}
.msgcuerpo{color:var(--ink-2);font-size:13px;margin-top:5px;white-space:pre-wrap}
.msgfecha{color:var(--ink-3);font-size:11.5px;margin-top:6px}
.msgcard .btn{flex:none;white-space:nowrap}

/* ---- pestaña Pagos ---- */
.pagocard{padding:13px 16px;margin-bottom:10px}
.pagonum{font-weight:700;font-size:13.5px}
.pagometa{display:flex;gap:10px;flex-wrap:wrap;align-items:center;
  margin-top:6px;color:var(--ink-2);font-size:12.5px}
/* La forma, compartida. Los dos son "un estado en una pildora" y sus seis
   declaraciones de geometria eran identicas byte a byte; lo que difiere son
   los VOCABULARIOS (declarado/aprobado/rechazado frente a
   activo/prueba/suspendido), y eso son clases modificadoras, no una base
   duplicada que hay que acordarse de cambiar dos veces. */
.pagopill,.estadopill{display:inline-block;padding:2px 9px;border-radius:20px;
  font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.03em}
.pagopill.declarado{background:var(--info-bg);color:var(--info)}
.pagopill.aprobado{background:var(--good-bg);color:var(--good)}
.pagopill.rechazado{background:var(--crit-bg);color:var(--crit)}
/* El estado de la suscripcion, en "Mi suscripcion". Mismo molde que
   .pagopill -- es la misma idea, un estado en una pildora -- pero con nombre
   propio: sus tres valores no son los de un pago (activo/prueba/suspendido
   frente a declarado/aprobado/rechazado) y compartir la clase obligaria a
   que las dos listas de estados crecieran juntas para siempre.
   La PALABRA lleva el significado; el color solo refuerza. */
.estadopill{background:var(--neutral-bg);color:var(--neutral)}
.estadopill.ok{background:var(--good-bg);color:var(--good)}
.estadopill.tibio{background:var(--warn-bg);color:var(--warn)}
.estadopill.malo{background:var(--crit-bg);color:var(--crit)}

/* El motivo del rechazo: lo unico que le dice al cliente que corregir. */
.pagomotivo{margin-top:8px;padding:8px 10px;background:var(--crit-bg);color:var(--crit);
  border-radius:9px;font-size:12.5px}

/* El comprobante del pago (2026-09-19). La miniatura es un enlace: en una
   captura de movil el numero de operacion no se lee a este tamano, asi que
   lo util es poder abrirla entera. */
.pagoshot{display:inline-flex;align-items:center;gap:10px;margin-top:10px;
  padding:6px 10px 6px 6px;border:1px solid var(--border);border-radius:10px;
  text-decoration:none;color:var(--ink-2);font-size:12.5px}
.pagoshot:hover{border-color:var(--accent);color:var(--accent)}
/* `object-fit:cover` y un alto fijo: las capturas llegan en cualquier
   proporcion y sin esto una alargada estira la tarjeta entera. */
/* `object-position:top` y no el centro: estas capturas son de MOVIL, muy
   altas y estrechas (1170x2532 es lo corriente), asi que recortarlas a una
   caja apaisada por el centro deja una banda del 15% del alto en la que no
   se distingue una transferencia de cualquier otra cosa. La cabecera -- el
   banco, el "operacion exitosa" -- es lo que la hace reconocible de un
   vistazo, y esta arriba. */
.pagoshot img{width:64px;height:56px;object-fit:cover;object-position:top;
  border-radius:7px;background:var(--bg);display:block}
.pagosincomp{margin-top:10px}
/* El <input type=file> lo dispara el <label>: el control nativo no se puede
   estilar y queda como un cuerpo extrano entre botones que si siguen el
   sistema. El label ES el disparador, asi que no hace falta JS para abrir el
   selector. */
/* El hueco lateral SOLO cuando va detras de la miniatura. `margin-left`
   fijo estaba pensado para eso, pero cuando NO hay captura el hermano
   anterior es un <div> de bloque y el boton caia a la linea siguiente
   desplazado 8px respecto a todo lo demas de la tarjeta. */
.pagoshot + .pagoadjuntar{margin-left:8px}
.pagoadjuntar{display:inline-block;margin-top:10px;cursor:pointer;
  border-radius:8px}
/* SE ESCONDE A LA VISTA, NO DEL TECLADO. Con `hidden` o `display:none` el
   input deja de ser enfocable y el control entero queda inalcanzable sin
   raton -- el mismo error que se arreglo en el aviso de la portada. Recortado
   a un pixel sigue en el orden de tabulacion. */
.pagoadjuntar input{position:absolute;width:1px;height:1px;padding:0;margin:-1px;
  overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}
/* Y como el input recortado no se ve, su anillo de foco tampoco: se pinta
   sobre el label, que es lo que si esta en pantalla. */
/* `:has(:focus-visible)` y no `:focus-within`, que es la convencion del
   resto del fichero: con `:focus-within` un clic de RATON deja el anillo
   pegado al label hasta que el foco se mueva, que es justo lo que
   `:focus-visible` existe para evitar. */
.pagoadjuntar:has(:focus-visible){outline:2px solid var(--foco);outline-offset:2px}
/* El <span> no intercepta el clic: asi el que lo recibe es el label, que es
   quien abre el selector. */
/* Como el <span> deja de ser blanco del puntero, su propio `:hover` no
   casa nunca: seria el unico .btn de la aplicacion que no responde al
   raton. Por eso el hover se cuelga del label. */
.pagoadjuntar .btn{pointer-events:none}
.pagoadjuntar:hover .btn{border-color:var(--accent)}

/* ---- pestaña Rubros ---- */
.rubrocard{padding:16px 18px;margin-bottom:14px}
.rubrocard.inactivo{opacity:.6}
.rubrohead{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-bottom:12px}
.rubrohead h3{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.rubrocard .field{margin-bottom:10px}
.rubrocard textarea,#rubroNuevo textarea{width:100%;padding:9px;border:1px solid var(--border);
  border-radius:9px;background:var(--surface-2);color:var(--ink);
  font-family:var(--mono);font-size:12.5px;resize:vertical}
.rubrocard input[type=text],#rubroNuevo input[type=text]{width:100%;padding:8px 10px;
  border:1px solid var(--border);border-radius:9px;background:var(--surface-2);
  color:var(--ink);font-size:13px;font-family:inherit}
.rubrocols{display:grid;grid-template-columns:1fr 1fr;gap:12px}
@media (max-width:800px){.rubrocols{grid-template-columns:1fr}}
.rubrobar{display:flex;margin-bottom:14px}

/* ================= accesibilidad y pantallas estrechas ================== */

/* ---- la cabecera cabe en un movil ----
   Era una fila unica sin flex-wrap: marca + 6 pestanas + estado + usuario +
   dos botones suman ~1350px de ancho minimo. Por debajo de eso desbordaba el
   body y arrastraba scroll horizontal a TODA la app, con la cabecera ademas
   sticky. Las pestanas bajan a su propia linea y se desplazan solas; lo demas
   se queda arriba, que es lo que cabe. El wrap es tambien la red de seguridad
   en anchos muy pequenos: envuelve en vez de desbordar. */
/* La cabecera NO se envuelve. Antes si lo hacia -- era sticky y crecia hacia
   abajo -- pero desde que tiene altura fija (--head-h, la misma que usan el
   menu lateral y el hueco superior de main) envolverse significa salirse del
   recuadro y montarse sobre el contenido. Aqui lo que sobra se encoge o se
   retira, que es lo que cabe en una barra de altura fija. */
@media (max-width:1100px){
  /* El plan se recorta antes que el nombre: "Pro · prueba" aguanta el
     recorte y sigue diciendo lo esencial. */
  .planchip{min-width:0;max-width:150px;overflow:hidden;
    text-overflow:ellipsis;white-space:nowrap}
  /* El nombre de quien entro puede ser un correo largo: se recorta antes de
     empujar a los botones fuera de la pantalla. */
  .userchip{min-width:0;max-width:200px;overflow:hidden;
    text-overflow:ellipsis;white-space:nowrap;display:block}
}
@media (max-width:820px){
  .planchip{max-width:110px}
  .userchip{max-width:120px}
}
@media (max-width:560px){
  /* A este ancho el nombre compite con los botones, y quien esta dentro ya
     sabe quien es. */
  .userchip{display:none}
}

/* AQUI YA NO SE TOCAN LAS COLUMNAS DE .filters, y conviene decir por que.
   Habia una regla para la banda 721-1100 que las repartia con
   `minmax(200px,1fr)`, heredada de cuando el panel tenia cinco columnas de
   anchos distintos. Con las cuatro iguales de ahora, esa regla solo cabia
   en TRES a 1024 y a 768 -- los dos anchos en los que mas se mira esto --,
   asi que "Ordenar por" se quedaba huerfano en su propio renglon y la fila
   alineada que justifica todo el reordenado no existia donde hace falta.
   Cuatro de ~160px son de sobra para un input y tres select, asi que
   `repeat(4,1fr)` llega hasta 720, y por debajo manda el display:flex. */

@media (max-width:520px){
  main{padding:calc(var(--head-h) + 14px) 14px 60px}
  .avisoia:not([hidden]) ~ main{padding-top:14px}
  header{padding:0 10px;gap:8px}
  /* El rango de fechas y el de montos los resuelve el bloque de 720px, mas
     abajo: alli dejan de ser filas que envuelven y pasan a ser rejillas.
     Envolver era justo lo que los desordenaba. */
  .brand div{font-size:13px}
  /* Dos columnas de campos a este ancho dejan cajas donde no cabe una fecha. */
  .usrform{grid-template-columns:1fr}
}

/* El aviso flotante crece con el texto del error que devuelva la API: sin
   techo, uno largo se sale por los dos lados en un movil. */
.toast{max-width:calc(100vw - 28px);box-sizing:border-box}

/* ---- foco visible en todo lo operable ----
   Solo lo tenian los inputs: pestanas, botones y tarjetas clicables se
   recorrian con el teclado a ciegas. :where() deja la especificidad en 0, asi
   que los anillos que ya existian siguen mandando donde estaban. */
:where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{
  outline:2px solid var(--foco);outline-offset:2px}

/* ---- la tarjeta de estado es un boton de verdad ----
   Era un <div> con onclick: filtraba con el raton y era inalcanzable con el
   teclado. Estas reglas le quitan al boton lo que trae de fabrica para que se
   vea exactamente igual que antes. */
button.kpi{font:inherit;color:inherit;text-align:left;width:100%;display:block}

/* ---- objetivos de puntero de 24x24 (WCAG 2.2 AA) ----
   La equis del chip medía ~8x14 y la del drawer ~11x20. Se agranda el area
   sensible con un pseudoelemento en vez de con padding: asi no se mueve
   nada de sitio. */
.kwchip button,.drawer .close{position:relative}
.kwchip button::after,.drawer .close::after{content:"";position:absolute;inset:-7px}
.linklike{min-height:24px}

/* ---- vinculacion de WhatsApp ---- */
.vincular{border-top:1px dashed var(--border);margin-top:14px;padding-top:12px}
.vincestado{font-size:13px;color:var(--ink-2);padding:8px 0;display:block}
.vincestado.ok{color:var(--good);font-weight:600}
/* El codigo es lo unico que importa de la pantalla mientras dura: caduca en
   menos de un minuto y hay que teclearlo en el telefono sin equivocarse. */
.paircode{margin-top:12px;padding:16px;border:2px solid var(--accent);
  border-radius:var(--radius);background:var(--surface-2);text-align:center}
.paircode .cod{font-family:var(--mono);font-size:30px;font-weight:700;
  letter-spacing:.12em;color:var(--accent);display:block;margin-bottom:6px}
.paircode .como{font-size:12.5px;color:var(--ink-2);line-height:1.5}

/* ---- guia paso a paso de WhatsApp ---- */
.guia{margin:14px 0;border:1px solid var(--border);border-radius:var(--radius);
  background:var(--surface-2);padding:4px 0;overflow:hidden}
.guia .paso{display:flex;gap:10px;align-items:flex-start;padding:9px 14px;
  border-bottom:1px solid var(--border);font-size:13px}
.guia .paso:last-child{border-bottom:none}
.guia .marca{flex:none;width:18px;text-align:center;font-weight:700;line-height:1.4}
.guia .paso.ok .marca{color:var(--good)}
.guia .paso.pendiente .marca{color:var(--warn)}
.guia .tit{font-weight:600}
.guia .paso.ok .tit{color:var(--ink-2);font-weight:500}
.guia .det{color:var(--ink-2);font-size:12.5px}
/* La instruccion del paso que toca: es lo unico accionable de la lista. */
.guia .acc{color:var(--ink);font-size:12.5px;margin-top:3px;line-height:1.5}
.guia .cuota{padding:9px 14px;font-size:12px;color:var(--ink-2);background:var(--surface)}
.guia .cuota a{margin-right:12px}

/* ---- aviso de que la IA no clasifica ---- */
/* Va bajo la cabecera y sobre todo lo demas: mientras dure, las cifras de
   relevancia de la pantalla estan congeladas y conviene saberlo antes de
   mirarlas. */
.avisoia{background:var(--crit-bg);color:var(--crit);border-bottom:1px solid var(--crit);
  padding:11px 20px;font-size:13.5px;display:flex;gap:10px;align-items:baseline;
  margin-left:var(--nav-w);margin-top:var(--head-h);transition:margin-left .18s var(--ease)}
/* Si el aviso esta puesto, main ya no tiene que dejar sitio a la cabecera: lo
   deja el aviso, que va justo debajo de ella. */
.avisoia:not([hidden]) ~ main{padding-top:18px}
.avisoia b{font-weight:700}
.avisoia .comorepararlo{color:var(--ink-2);font-size:12.5px}
.avisoia.tibio{background:var(--warn-bg);color:var(--warn);border-color:var(--warn)}

/* El aviso de la IA y el de vencimiento comparten sitio (Tarea 7, Fase C):
   los dos son .avisoia y pueden estar puestos a la vez, uno debajo del otro.
   Cada uno lleva margin-top:head-h para colocarse justo bajo la cabecera fija
   cuando es el PRIMERO visible -- si el de la IA ya esta puesto, el de
   vencimiento no necesita ese hueco otra vez, solo apilarse debajo de él. */
#avisoIa:not([hidden]) + #avisoVencimiento{margin-top:0}


/* ---- el menu lateral en pantalla estrecha ----
   Por debajo de 900px no caben menu y tabla a la vez, asi que el menu se sale
   de la pagina y vuelve por encima del contenido cuando se pide. Es el mismo
   boton de la cabecera: lo que cambia no es el control, es que aqui abre en
   vez de plegar. */
@media (max-width:900px){
  main,.avisoia{margin-left:0}
  .sidenav{transform:translateX(-100%);box-shadow:var(--shadow);width:var(--nav-w-open,236px)}
  body[data-nav="open"] .sidenav{transform:none}
  /* En movil el plegado a iconos no aplica: o esta o no esta. */
  body[data-nav="min"] .sidenav .tab{padding:0 12px;justify-content:flex-start}
  body[data-nav="min"] .sidenav .tab .lbl{position:static;width:auto;height:auto;
    margin:0;clip-path:none}
  body[data-nav="min"] .sidenav .tab .badge{position:static;margin:0;padding:1px 7px;
    height:auto;width:auto;min-width:0;font-size:11px;line-height:normal}
  /* Un destino tactil de 40px de alto se falla a menudo; 44 es el minimo que
     se acierta con el pulgar sin mirar. */
  .sidenav .tab{height:44px}
}
@media (min-width:901px){
  .navscrim{display:none}
}

/* ---- foco visible ----
   Un anillo propio, no el del navegador: el suyo es un contorno fino que sobre
   el azul de la marca casi no se ve. `:focus-visible` y no `:focus` para que no
   salte al hacer clic con el raton, que es lo que lleva a la gente a quitarlo
   -- y quitarlo deja sin navegacion a quien va por teclado. */
:focus-visible{outline:2px solid var(--foco);outline-offset:2px;border-radius:8px}
.sidenav .tab:focus-visible{outline-offset:-2px}

/* NO se fija la cabecera de la tabla, y conviene dejar escrito por que para
   que nadie lo intente otra vez de la forma facil: `.tablewrap` lleva
   `overflow-x:auto`, y en cuanto un eje deja de ser `visible` el otro pasa a
   `auto` tambien -- el envoltorio es contenedor de desplazamiento. Un
   `position:sticky` dentro se ancla a EL, no a la ventana, y como no tiene
   altura limitada nunca llega a desplazarse por dentro: la regla se escribe,
   no falla, y no hace nada. Fijarla de verdad exige darle al envoltorio una
   altura maxima y que la tabla se desplace por dentro, que es otro modelo de
   navegacion y otra decision. */

/* ---- movimiento ----
   Quien ha pedido menos movimiento en su sistema lo ha pedido por algo: hay
   quien se marea. Se queda el estado final, no el camino. */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms !important;animation-iteration-count:1 !important;
    transition-duration:.01ms !important;scroll-behavior:auto !important}
}

/* El veredicto de la IA, donde antes habia un emoji. El color lo da el mismo
   par semantico que usa el resto de la pantalla, y nunca va solo: la palabra
   esta al lado porque un verde y un rojo no se distinguen para todo el mundo. */
dd .ok{color:var(--good);font-weight:700}
dd .no{color:var(--crit);font-weight:700}

/* El ojo del login. El boton ya tiene su tamaño; el icono solo se centra. */
.ojito{display:grid;place-items:center}


/* ---- el buscador en un telefono ----------------------------------------
   Medido a 375px antes de esto: los cinco recuadros apilados ocupaban unos
   350px y el panel de filtros otros 600 -- casi mil pixeles de scroll antes
   de ver el primer resultado. Una pantalla cuyo contenido es una lista no
   puede empezar por la configuracion de la lista. */
/* El boton que pliega, a la derecha de los conmutadores. Plegado, de la
   linea hacia abajo no se ve nada, y la linea tampoco: sin nada debajo no
   separa nada. */
.filtrostoggle{margin-left:auto}
body[data-filtros="cerrado"] .filters > .field:not(.campoq),
body[data-filtros="cerrado"] .filters > .row2{display:none}
body[data-filtros="cerrado"] .filters .conmutadores{border-bottom:none;padding-bottom:0}

@media (max-width:720px){
  /* Las cifras ya son una tira en cualquier ancho (ver `.kpis` mas arriba):
     aqui solo se aprieta el hueco entre ellas para que quepan en dos
     renglones en vez de tres. En la clase, asi vale tambien para las de
     "Mis procesos". */
  .kpis{gap:5px 14px;margin-bottom:10px}

  /* ---- LOS FILTROS, ORDENADOS EN UN TELEFONO ----
     Plegado el panel, al abrirlo quedaban tres filas flex que envolvian por
     su cuenta: los tres conmutadores partidos 2+1, y sobre todo `.row2`,
     que mete en el MISMO renglon el rango de fechas (un select y dos
     fechas), los dos importes, un separador elastico y el boton de
     limpiar. A 375px nada de eso cabe, asi que cada trozo caia donde podia
     y el panel se leia como un monton de controles sueltos. Apilado y con
     los pares en rejilla, cada cosa ocupa su renglon y los dos extremos de
     un rango quedan uno al lado del otro, que es como se entiende que son
     un rango. */
  /* Los tres conmutadores tambien de dos en dos. Rejilla y no una fila que
     envuelve: envolviendo, el tercero se colocaba debajo del primero o del
     segundo segun lo que midiera cada etiqueta, asi que la misma pantalla
     se veia distinta en dos telefonos. */
  .filters .conmutadores{display:grid;grid-template-columns:1fr 1fr;
    gap:10px;align-items:center}
  .filters .row2{flex-direction:column;align-items:stretch;gap:12px}
  /* El separador elastico solo tiene sentido en una fila. Apilado, es un
     hueco vacio que empuja el boton fuera de la vista. */
  .filters .row2 .spacer{display:none}
  .filters .row2 > .btn{width:100%}

  /* `1fr auto 1fr`: los dos extremos iguales y el guion en medio. El guion
     SE QUEDA -- es lo unico que dice que son desde y hasta, porque estos
     campos no llevan etiqueta visible, solo `title`, que en tactil no
     existe. */
  .rango,.montos{display:grid;grid-template-columns:1fr auto 1fr;
    gap:8px;align-items:center}
  .rango input,.montos input{width:100%;min-width:0}
  /* Lo que manda sobre el rango va encima, a lo ancho: el select de "sobre
     que fecha" en uno, la palabra "Valor S/" en el otro. */
  .rango > select,.montos > span:first-child{grid-column:1/-1}
  /* Y la equis de quitar el rango, debajo y a la derecha, donde no se pulsa
     por error al escribir la segunda fecha. */
  .rango > .linkbtn{grid-column:1/-1;justify-self:end}

  /* Plegado, del panel solo queda la caja de busqueda y el boton que abre el
     resto. El selector nombra lo que SE QUEDA en vez de lo que se va: asi un
     filtro nuevo nace escondido en vez de nacer colandose. */
  /* DOS COLUMNAS, no una pila. Apilado cabia todo pero el panel abierto se
     iba a ~700px de alto: cuatro campos, tres conmutadores y dos rangos,
     cada uno en su renglon, en una pantalla que mide 660. De dos en dos,
     los cuatro campos ocupan dos renglones en vez de cuatro y los tres
     conmutadores dos en vez de tres -- el panel abierto cabe de una vez.
     Lo que NO se parte en dos es lo que no tiene sentido a medias: la caja
     de busqueda, el boton de mas filtros y la fila de rangos, que ya lleva
     sus propios pares dentro. */
  .filters{display:grid;grid-template-columns:1fr 1fr;gap:10px}
  .filtrostoggle{grid-column:1/-1;justify-self:start;margin-left:0}
  body[data-filtros="cerrado"] .filters > *:not(.campoq):not(.conmutadores){display:none}
  body[data-filtros="cerrado"] .filters .conmutadores > .chk{display:none}
  .filters .row2{border-top:none;padding-top:0}
  /* Mismo criterio que .row2 de aqui al lado: apilados, los renglones
     ya no existen y el filete separa de nada. */
  .filters .conmutadores{border-bottom:none;padding-bottom:0}
}

/* El contador de filtros puestos. Sin el, plegar el panel esconderia que hay
   un rango de fechas activo y la lista pareceria incompleta sin motivo. */
.filtrostoggle .cuenta{margin-left:7px;background:var(--accent);color:var(--accent-ink);
  border-radius:20px;padding:1px 7px;font-size:11px;font-weight:700}


/* ---- la guia de uso ----
   Un paso resuelto y uno pendiente tienen que distinguirse SIN depender del
   color: el pendiente lleva su numero y la palabra "Pendiente", el resuelto
   una marca y "Listo". El color solo refuerza. */
.paso{margin-bottom:12px}
.paso-cab{display:flex;align-items:center;gap:11px;margin-bottom:8px}
.paso-cab h3{flex:1;min-width:0;font-size:15px}
.paso-num{flex:none;width:26px;height:26px;border-radius:50%;display:grid;
  place-items:center;font-weight:750;font-size:13px;
  background:var(--neutral-bg);color:var(--neutral)}
.paso.pendiente .paso-num{background:var(--accent);color:var(--accent-ink)}
.paso.hecho .paso-num{background:var(--good-bg);color:var(--good)}
.paso-estado{flex:none;font-size:11px;font-weight:700;text-transform:uppercase;
  letter-spacing:.05em;border-radius:20px;padding:3px 10px}
.paso.pendiente .paso-estado{background:var(--warn-bg);color:var(--warn)}
.paso.hecho .paso-estado{background:var(--good-bg);color:var(--good)}
/* El resuelto se atenua un poco: lo que queda por hacer tiene que pesar mas
   en la pagina que lo que ya esta hecho. */
.paso.hecho{opacity:.82}
.paso.hecho:hover{opacity:1}


/* =========================================================================
   EL REDISEÑO DE LA APP DEL CLIENTE (2026-09-24)
   =========================================================================
   Va al final y en bloque propio, no repartido por el fichero de arriba: son
   reglas que GANAN a las de la maqueta anterior con la misma especificidad.
   Meterlas en su sitio natural obligaria a subir selectores o a borrar las
   viejas una por una, y lo segundo se lleva por delante los comentarios que
   explican por que cada pieza es como es. Mismo patron, y por el mismo
   motivo, que el bloque equivalente de static-admin/styles.css.
   ------------------------------------------------------------------------ */

:root{--head-h:72px; --nav-w:272px; --nav-w-open:272px}
body[data-nav="min"]{--nav-w:var(--nav-w-min)}

/* ---- la cabecera ---- */
header{gap:16px;padding:0 20px;background:var(--surface);
  border-bottom:1px solid var(--border)}
.brand{gap:11px;font-size:23px;font-weight:800;letter-spacing:-.03em;
  line-height:1.05}
.brand .mark{width:38px;height:38px;border-radius:9px}
/* "Pro" en oro, como el logotipo de al lado: T azul, P dorada, repetido en
   la palabra. Es adorno sobre un fondo blanco y no texto que haya que leer
   para entender nada -- la palabra de la marca se lee entera en --ink -- asi
   que aqui SI va el oro vivo. */
.brand .pro{color:var(--accent-3)}
.brand small{font-size:11.5px;font-weight:600;letter-spacing:0;
  color:var(--ink-3);margin-top:1px}

/* El boton de plegar: cuadrado con borde, no un icono suelto. Gira cuando el
   menu esta plegado, asi que el mismo dibujo dice "encoger" y "desplegar". */
.navtoggle{width:38px;height:38px;border-radius:11px;flex:none;
  border:1px solid var(--border);background:var(--surface-2);
  transition:transform .18s ease}
.navtoggle svg{width:18px;height:18px}
body[data-nav="min"] .navtoggle svg{transform:rotate(180deg)}

/* El boton del tema, con su palabra. Un sol o una luna solos obligan a
   pulsarlos para saber que hacen; la palabra dice a donde LLEVA, no donde
   estas. Debajo de 820px se queda el dibujo, que es donde el ancho manda. */
.temabtn{display:inline-flex;align-items:center;gap:8px;flex:none;height:38px;
  padding:0 14px;border-radius:20px;border:1px solid var(--border);
  background:var(--surface-2);color:var(--ink-2);font:inherit;font-size:13px;
  font-weight:650;cursor:pointer}
.temabtn:hover{color:var(--ink);border-color:var(--ink-3)}
.temabtn svg{width:16px;height:16px;fill:none;stroke:currentColor;
  stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
:root[data-theme="dark"] .ico-luna{display:none}
:root:not([data-theme="dark"]) .ico-sol{display:none}
/* Mientras nadie haya elegido tema NO hay atributo data-theme y manda el
   sistema. Las dos reglas de arriba solo miran el atributo, asi que en ese
   caso ensenaban siempre la luna: en un portatil puesto en oscuro el boton
   decia "Modo oscuro" estando ya oscuro, que es lo contrario de lo que un
   boton con palabra viene a resolver. Estas dos van DESPUES a proposito --
   tienen la misma especificidad y entre iguales gana la ultima. */
@media (prefers-color-scheme:dark){
  :root:not([data-theme]) .ico-luna{display:none}
  :root:not([data-theme]) .ico-sol{display:revert}
}
@media (max-width:820px){.temabtn .lbl{display:none}.temabtn{padding:0 11px}}
/* El area de toque del boton del tema. La cabecera ya tenia esta regla para
   .iconbtn y .navtoggle (busca `pointer:coarse` mas arriba, con el motivo
   entero); .temabtn es nuevo de hoy y se habria quedado fuera con sus 38px
   de alto. Crece el area, no la caja: subirlo a 44 lo sacaria de la barra.
   El ancho es 100% y no 44px porque este boton es mas ancho que alto. */
@media (pointer:coarse){
  .temabtn{position:relative}
  .temabtn::after{content:"";position:absolute;top:50%;left:50%;
    transform:translate(-50%,-50%);width:100%;height:44px}
}

header .sep{width:1px;height:26px;background:var(--border);flex:none}
/* Las iniciales de quien ha entrado. Va con aria-hidden en el HTML: el
   nombre completo esta escrito al lado y un lector de pantalla no tiene que
   oir las dos primeras letras otra vez. */
.avatar{width:34px;height:34px;border-radius:50%;flex:none;
  background:var(--oro-suave);border:1px solid var(--oro-borde);
  color:var(--oro-texto);display:grid;place-items:center;
  font-size:12px;font-weight:800}
/* .iconbtn ya no tiene ningun elemento en esta pantalla: era el boton del
   tema, que hoy es .temabtn, y el de cerrar sesion se fue al pie del menu
   lateral en 2026-09-19. Las reglas de mas arriba que lo nombran se quedan
   porque van emparejadas con .navtoggle, que si existe -- pero si alguien
   busca a quien pinta `.iconbtn` aqui, la respuesta es: a nadie. En /admin/
   sigue vivo (el boton de salir de su cabecera). */
/* El plan y el nombre son lo primero que sobra cuando la barra se queda sin
   ancho: el plan se mira una vez al mes y el nombre lo sabe quien lo ha
   escrito. El avatar se queda -- ocupa 34px y dice lo mismo. */
@media (max-width:640px){.userchip,header .sep{display:none}}
@media (max-width:520px){.planchip{display:none}}

/* En un telefono la barra se queda sin ancho antes que en /admin/: a esta
   pantalla se entra desde el movil, y con el logotipo a 38px, la marca a
   23px, su lema debajo, el boton de plegar, el del tema y el avatar no
   caben en 360px -- la marca se encoge y parte el nombre en dos lineas.
   Se recorta lo que no lleva informacion: el lema (lo dice la pagina
   entera) y unos puntos de la marca. El logotipo y el avatar se quedan. */
@media (max-width:480px){
  header{gap:10px;padding:0 12px}
  .brand{font-size:19px}
  .brand .mark{width:32px;height:32px}
  .brand small{display:none}
}

.planchip{border-radius:20px;font-size:11.5px;font-weight:700;
  background:var(--oro-suave);border-color:var(--oro-borde);color:var(--oro-texto)}

/* ---- el menu lateral ---- */
.sidenav{background:var(--surface);border-right:1px solid var(--border);
  padding:14px 14px 18px;display:flex;flex-direction:column;gap:2px}
/* 44px de alto, no los 40 de antes ni "lo que salga del relleno": 44 es el
   minimo que se acierta con el pulgar sin mirar, y la regla de mas arriba ya
   lo subia a 44 debajo de 900px. Escribirlo aqui lo deja igual en las dos,
   que es lo que un menu lateral tiene que ser. */
.sidenav .tab{gap:14px;padding:0 14px;height:44px;border-radius:12px;
  font-size:14.5px;font-weight:600;color:var(--ink-2)}
.sidenav .tab svg{width:20px;height:20px;flex:none}
.sidenav .tab:hover{background:var(--surface-2);color:var(--ink)}
/* El activo: fondo oro suave y una barra a la izquierda. La barra es lo que
   se lee en una columna -- un subrayado, que es lo que sirve en una fila,
   aqui queda debajo del texto y no separa nada. */
.sidenav .tab[aria-current="page"]{background:var(--oro-suave);
  color:var(--ink);font-weight:750;box-shadow:inset 3px 0 0 var(--accent-3);
  border:1px solid var(--oro-borde)}
.sidenav .tab[aria-current="page"] svg{color:var(--oro-texto)}
/* El contador, en gris y no en oro. Estos numeros son la razon de entrar a
   Alertas y a Mensajes, asi que tienen que LEERSE: relleno oro con texto
   oscuro encima competia con el fondo del boton activo, que es el mismo oro
   mas claro, y a 11px la diferencia no se veia. */
.sidenav .tab .badge{background:var(--surface-2);color:var(--ink-2);
  border:1px solid var(--border);font-weight:750}
/* Cerrar sesion sigue al pie y sigue tenue: es una salida, no un destino.
   Se repite aqui porque el bloque de arriba le cambia el color al resto de
   las filas y esta tiene que quedarse fuera. */
.tabsalir{color:var(--ink-3) !important}

/* Con el menu plegado a iconos, la fila deja de tener relleno lateral: si
   no, el icono se va a la izquierda en vez de quedarse centrado en los
   64px. La regla de arriba le puso 14px y esta se los quita.

   Va dentro de min-width:901px A PROPOSITO. Debajo de 900px el menu no se
   pliega a iconos -- se sale de la pagina entero y vuelve con sus etiquetas
   -- y hay una regla mas arriba que le devuelve el relleno para ese caso.
   Sin este envoltorio, esta linea, por estar al final del fichero, ganaria
   tambien alli y dejaria el menu movil con el texto pegado al borde. */
@media (min-width:901px){
  body[data-nav="min"] .sidenav .tab{padding:0}
}

main{background:var(--bg)}
/* El relleno, DENTRO de min-width:901px. Hay una regla mas arriba que lo
   baja a 14px por los lados debajo de 900px, y esta, por estar al final del
   fichero y tener la misma especificidad, se la llevaba por delante: el
   telefono se quedaba con los 20px de un escritorio y la tabla perdia
   ancho justo donde no sobra. */
@media (min-width:901px){
  main{padding:calc(var(--head-h) + 22px) 20px 60px}
}

/* ---- el oro que se lee --------------------------------------------------
   Todo lo que era AZUL y es TEXTO. Con la paleta azul estas reglas cumplian
   de sobra (--accent daba 5,86:1 sobre blanco); con la dorada, --accent cae
   a 2,1-2,3:1 y ninguna de estas llegaria al 4,5:1 de WCAG 1.4.3. Cambian
   al oro oscuro, que es el mismo color con la luz que hace falta.
   Lo que NO cambia: rellenos (.btn.primary, la barra del activo, las barras
   de relevancia) -- ahi el oro es fondo y quien tiene que leerse es el texto
   oscuro de encima, que da 8,3:1. */
a{color:var(--oro-texto)}
.linklike{color:var(--oro-texto)}
.kpi.accent .val{color:var(--oro-texto)}
.kpi.accent .ico{stroke:var(--oro-texto)}
table.grid thead th .arrow{color:var(--oro-texto)}
.pagoshot:hover{border-color:var(--accent);color:var(--oro-texto)}
.paircode{border-color:var(--oro-borde);background:var(--oro-suave)}
.paircode .cod{color:var(--oro-texto)}

/* ---- la puerta de entrada ----
   El login es la primera pantalla del producto para quien no ha entrado
   nunca, y hasta hoy era una caja gris con un logotipo encima. Ahora lleva
   la marca en dos tonos, como la barra y como la portada de la que viene. */
.logincard{border-radius:18px;padding:32px 30px;box-shadow:var(--shadow)}
.logincard h1{font-size:27px;font-weight:800;letter-spacing:-.035em}
.logincard h1 .pro{color:var(--accent-3)}
.logincard p.sub{font-size:13.5px;color:var(--ink-2);margin-bottom:22px}
.logincard .btn.primary{padding:11px 18px;font-size:14.5px;border-radius:11px}

/* ---- rubros plegables (2026-09-25) ----
   Plegados por defecto; la flecha gira al abrir. Plegada, la tarjeta pierde
   el hueco de debajo de la cabecera, que sin cuerpo no separa nada. */
.pliegue{width:30px;height:30px;flex:none;display:grid;place-items:center;
  border:1px solid var(--border);border-radius:8px;background:transparent;
  color:var(--ink-2);cursor:pointer}
.pliegue svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:2.4;
  stroke-linecap:round;stroke-linejoin:round;transition:transform .15s ease}
.pliegue[aria-expanded="true"] svg{transform:rotate(90deg)}
.pliegue:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
[data-cab]{cursor:pointer}
.rubrocard.plegado .rubrohead,.rubrocard.plegado .tarjeta-cab{margin-bottom:0}
@media (prefers-reduced-motion:reduce){.pliegue svg{transition:none}}

/* ---- Mis procesos como tablero (2026-09-25, rediseño 2026-09-26) ----
   Una columna por estado con su color (--c, ESTADO_COLOR en app.js). El
   tablero mide hasta el borde de la ventana (ajustarAltoTablero): la barra
   lateral queda abajo del todo y cada columna se desplaza por dentro. */
main:has(> #view-crm:not([hidden])){padding-bottom:14px}
.kanban{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(272px,1fr);
  gap:14px;overflow-x:auto;overflow-y:hidden;padding:2px 2px 12px;align-items:stretch;
  scrollbar-width:auto;scrollbar-color:var(--accent) var(--oro-suave)}
.kanban::-webkit-scrollbar{height:12px}
.kanban::-webkit-scrollbar-track{background:var(--oro-suave);border-radius:999px}
.kanban::-webkit-scrollbar-thumb{background:var(--accent);border-radius:999px;
  border:3px solid var(--oro-suave)}
.kanban::-webkit-scrollbar-thumb:hover{background:var(--accent-3)}

.kb-col{position:relative;display:flex;flex-direction:column;min-height:0;
  background:color-mix(in srgb,var(--c) 5%,var(--surface-2));
  border:1px solid color-mix(in srgb,var(--c) 18%,var(--border));border-radius:18px;
  overflow:hidden;transition:border-color .15s ease,box-shadow .15s ease,background .15s ease}
/* La franja de color de arriba: dice el estado sin tener que leerlo. */
.kb-col::before{content:"";position:absolute;inset:0 0 auto;height:4px;background:var(--c)}
.kb-col.sobre{border-color:var(--c);
  background:color-mix(in srgb,var(--c) 12%,var(--surface-2));
  box-shadow:0 0 0 3px color-mix(in srgb,var(--c) 22%,transparent)}
.kb-cab{display:flex;align-items:center;gap:9px;padding:16px 14px 10px}
.kb-dot{width:9px;height:9px;border-radius:50%;background:var(--c);flex:none;
  box-shadow:0 0 0 3px color-mix(in srgb,var(--c) 22%,transparent)}
.kb-nombre{font-size:13.5px;font-weight:750;color:var(--ink);letter-spacing:-.01em}
.kb-n{margin-left:auto;min-width:26px;padding:2px 9px;border-radius:999px;text-align:center;
  font-size:12px;font-weight:750;color:var(--ink);background:var(--surface);
  border:1px solid color-mix(in srgb,var(--c) 30%,var(--border))}
.kb-zona{flex:1;min-height:0;overflow-y:auto;display:flex;flex-direction:column;gap:10px;
  padding:4px 10px 12px;scrollbar-width:thin;scrollbar-color:var(--border) transparent}
.kb-vacio{display:flex;flex-direction:column;align-items:center;gap:6px;margin-top:4px;
  padding:22px 10px;border:1.5px dashed color-mix(in srgb,var(--c) 35%,var(--border));
  border-radius:14px;color:var(--ink-3);font-size:12px;text-align:center}
.kb-vacio svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:2;
  stroke-linecap:round}

.kb-card{position:relative;flex:none;display:flex;flex-direction:column;gap:8px;
  padding:12px 12px 10px 15px;border-radius:14px;background:var(--surface);
  border:1px solid var(--border);box-shadow:0 1px 2px rgba(15,27,45,.05);
  cursor:grab;font-size:12.5px;transition:transform .15s ease,box-shadow .15s ease,
  border-color .15s ease}
/* El filo de color a la izquierda: la tarjeta lleva el estado encima aunque
   se mire suelta. */
.kb-card::before{content:"";position:absolute;left:0;top:10px;bottom:10px;width:3px;
  border-radius:0 3px 3px 0;background:var(--c)}
.kb-card:hover{transform:translateY(-2px);border-color:color-mix(in srgb,var(--c) 40%,var(--border));
  box-shadow:0 10px 24px -12px rgba(15,27,45,.35)}
.kb-card:active{cursor:grabbing}
.kb-card.arrastrando{opacity:.4;transform:rotate(1.5deg)}
.kb-top{display:flex;align-items:flex-start;gap:6px}
.kb-cod{flex:1;min-width:0;font:700 11.5px/1.35 var(--mono);color:var(--ink);
  letter-spacing:-.01em;word-break:break-word}
.kb-grip{width:16px;height:16px;flex:none;fill:var(--ink-3);stroke:none;opacity:.5}
.kb-top{cursor:grab}
.kb-card{cursor:default}
.kb-card:hover .kb-grip{opacity:.9}
.kb-ent{margin:0;font-size:13px;font-weight:650;line-height:1.35;color:var(--ink-2)}
.kb-chips{display:flex;flex-wrap:wrap;gap:6px}
.kb-chip{display:inline-flex;align-items:center;padding:3px 9px;border-radius:999px;
  font-size:11.5px;font-weight:650;background:var(--surface-2);color:var(--ink-2);
  border:1px solid var(--border)}
.kb-cot{color:var(--ink-2)}
.kb-valor{background:var(--oro-suave);border-color:var(--oro-borde);color:var(--oro-texto)}
.kb-pie{display:flex;align-items:center;justify-content:space-between;gap:6px;
  padding-top:8px;border-top:1px solid var(--border)}
.kb-avatar{width:26px;height:26px;border-radius:50%;display:grid;place-items:center;
  flex:none;font-size:10.5px;font-weight:800;color:var(--accent-ink);
  background:linear-gradient(135deg,var(--accent),color-mix(in srgb,var(--accent) 88%,#000))}
.kb-acc{display:flex;align-items:center;gap:4px}
.kb-btn{height:28px;min-width:28px;padding:0 8px;display:inline-grid;place-items:center;
  border-radius:8px;border:1px solid var(--border);background:var(--surface);
  color:var(--ink-2);font:inherit;font-size:11.5px;font-weight:700;cursor:pointer;
  transition:background .12s ease,color .12s ease,border-color .12s ease}
.kb-btn svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:2.4;
  stroke-linecap:round;stroke-linejoin:round}
.kb-btn:hover:not(:disabled){border-color:var(--accent);color:var(--oro-texto);
  background:var(--oro-suave)}
.kb-btn:focus-visible{outline:2px solid var(--foco);outline-offset:2px}
.kb-btn:disabled{opacity:.35;cursor:default}
.kb-ver{padding:0 10px}
.kb-mas summary{cursor:pointer;color:var(--ink-3);font-size:11.5px;font-weight:650;
  display:flex;align-items:center;gap:6px;list-style:none}
.kb-mas summary::-webkit-details-marker{display:none}
.kb-mas summary::before{content:"";width:6px;height:6px;border-right:2px solid currentColor;
  border-bottom:2px solid currentColor;transform:rotate(-45deg);transition:transform .15s ease}
.kb-mas[open] summary::before{transform:rotate(45deg)}
.kb-mas[open]{display:flex;flex-direction:column;gap:8px}
.kb-punto{width:7px;height:7px;border-radius:50%;background:var(--accent);display:inline-block}
.kb-campo{display:flex;flex-direction:column;gap:3px;font-size:11px;font-weight:650;
  color:var(--ink-2)}
.kb-card textarea,.kb-card input,.kb-card select{padding:7px 9px;border:1px solid var(--border);
  border-radius:9px;background:var(--surface-2);color:var(--ink);font:inherit;
  font-size:12px;width:100%}
.kb-card textarea:focus,.kb-card input:focus,.kb-card select:focus{outline:2px solid var(--foco);
  outline-offset:-1px;border-color:var(--accent)}
.kb-card textarea{resize:vertical;min-height:56px}
@media (max-width:720px){
  .kanban{grid-auto-columns:84vw;scroll-snap-type:x mandatory}
  .kb-col{scroll-snap-align:start}
}
@media (prefers-reduced-motion:reduce){
  .kb-col,.kb-card,.kb-btn,.kb-mas summary::before{transition:none}
  .kb-card:hover,.kb-card.arrastrando{transform:none}
}

/* El contador de la Guia ("3/5"): mientras falte algo, con el color de los
   demas contadores; completa, en verde y sin reclamar atencion. */
.sidenav .tab .badge.guia.completa{background:var(--good-bg);color:var(--good)}

/* ---- resultados en la tarjeta (0039) ---- */
.kb-oferta{background:color-mix(in srgb,#8b5cf6 12%,var(--surface));
  border-color:color-mix(in srgb,#8b5cf6 30%,var(--border));color:var(--ink)}
.kb-falta{background:var(--warn-bg);border-color:transparent;color:var(--warn)}
.kb-perdida{margin:0;font-size:12px;color:var(--ink-2);line-height:1.4}

/* ---- el dialogo de datos (monto al presentar, datos al perder) ---- */
.dlg{border:0;padding:0;border-radius:18px;background:var(--surface);color:var(--ink);
  box-shadow:0 30px 60px -20px rgba(8,18,37,.5);width:min(420px,calc(100vw - 32px))}
.dlg::backdrop{background:rgba(8,18,37,.45);backdrop-filter:blur(2px)}
.dlg-form{display:flex;flex-direction:column;gap:12px;padding:22px}
.dlg-form h3{margin:0;font-size:17px;letter-spacing:-.01em}
.dlg-form .kwnote{margin:0}
.dlg-campo{display:flex;flex-direction:column;gap:5px;font-size:12px;font-weight:650;
  color:var(--ink-2)}
.dlg-campo input,.dlg-campo select{padding:10px 12px;border:1px solid var(--border);
  border-radius:10px;background:var(--surface-2);color:var(--ink);font:inherit;font-size:14px}
.dlg-campo input:focus,.dlg-campo select:focus{outline:2px solid var(--foco);outline-offset:-1px;
  border-color:var(--accent)}
.dlg-botones{display:flex;justify-content:flex-end;gap:8px;flex-wrap:wrap;margin-top:4px}

/* =========================================================================
   REPORTES (2026-09-26)
   Las tres series validadas con el validador del skill de visualizacion:
   claro sobre #fff, oscuro sobre #131c2e. El dorado oscuro baja de tono
   porque el de la marca se sale de la banda de luminosidad sobre el navy.
   ========================================================================= */
:root{--serie-ganado:#dea21e;--serie-espera:#8b5cf6;--serie-perdido:#dc2626}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){--serie-ganado:#bc8a12;--serie-espera:#8b5cf6;--serie-perdido:#ef4444}
}
:root[data-theme="dark"]{--serie-ganado:#bc8a12;--serie-espera:#8b5cf6;--serie-perdido:#ef4444}

.rep-barra{display:flex;align-items:center;justify-content:space-between;gap:12px;
  flex-wrap:wrap;margin-bottom:14px}
.rep-periodos{display:inline-flex;flex-wrap:wrap;padding:4px;gap:4px;border-radius:12px;
  background:var(--surface);border:1px solid var(--border)}
.rep-per{border:0;background:transparent;color:var(--ink-2);font:inherit;font-size:13px;
  font-weight:650;padding:7px 14px;border-radius:9px;cursor:pointer}
.rep-per[aria-pressed="true"]{background:var(--accent);color:var(--accent-ink)}
.rep-per:focus-visible{outline:2px solid var(--foco);outline-offset:2px}

.rep-cifras{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;
  margin-bottom:14px}
.rep-cifra{display:flex;flex-direction:column;gap:4px;padding:16px 18px;position:relative;
  overflow:hidden}
.rep-cifra::before{content:"";position:absolute;inset:0 auto 0 0;width:3px;background:var(--border)}
.rep-cifra.oro::before{background:var(--accent)}
.rep-cifra-t{font-size:12px;font-weight:650;color:var(--ink-2);text-transform:uppercase;
  letter-spacing:.04em}
.rep-cifra b{font-size:28px;font-weight:800;letter-spacing:-.03em;color:var(--ink);line-height:1.1}
.rep-cifra-p{font-size:12.5px;color:var(--ink-3)}

.rep-rejilla{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px}
.rep-ancho{grid-column:1/-1}
@media (max-width:900px){.rep-rejilla{grid-template-columns:1fr}}
.rep-bloque{padding:18px 20px}
.rep-bloque h3{margin:0 0 14px;font-size:15px;letter-spacing:-.01em}
.rep-vacio{margin:0;padding:22px 12px;text-align:center;color:var(--ink-3);font-size:13px;
  border:1.5px dashed var(--border);border-radius:12px}
.rep-sub{margin:16px 0 8px;font-size:12px;font-weight:700;color:var(--ink-2);
  text-transform:uppercase;letter-spacing:.04em}
.rep-sub:first-child{margin-top:0}
.rep-dato{margin:12px 0 0;font-size:13.5px;color:var(--ink-2)}
.rep-dato b{font-size:16px;color:var(--ink)}

/* Barras horizontales: embudo, tablero, motivos. Marca fina con el extremo
   redondeado y la cifra escrita al lado, no dentro. */
.rep-embudo,.rep-lista{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:10px}
.rep-embudo li,.rep-lista li{display:grid;grid-template-columns:130px 1fr 44px 48px;
  align-items:center;gap:10px;font-size:13px}
.rep-lista li{grid-template-columns:140px 1fr 40px}
.rep-embudo-n,.rep-etq{color:var(--ink-2);font-weight:600;display:flex;align-items:center;gap:7px;
  min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rep-embudo b,.rep-lista b{text-align:right;color:var(--ink)}
.rep-paso{font-size:11.5px;color:var(--ink-3);text-align:right}
.rep-barra-h{height:10px;border-radius:999px;background:var(--surface-2);overflow:hidden}
.rep-barra-h i{display:block;height:100%;border-radius:999px;background:var(--serie-espera)}
.rep-barra-h i.oro{background:var(--serie-ganado)}
.rep-barra-h i.perdido{background:var(--serie-perdido)}
.rep-barra-h i.color{background:var(--c)}
.rep-punto{width:9px;height:9px;border-radius:50%;background:var(--c);flex:none}

/* El grafico mensual: barras apiladas con un hueco de superficie entre
   segmentos (el trazo del mismo color que el fondo del panel). */
.rep-leyenda{display:flex;flex-wrap:wrap;gap:6px 16px;margin-bottom:8px;font-size:12.5px;color:var(--ink-2)}
.rep-leyenda span{display:inline-flex;align-items:center;gap:6px}
.rep-leyenda i{width:10px;height:10px;border-radius:3px}
.rep-leyenda .ganados,.rep-seg.ganados{background:var(--serie-ganado);fill:var(--serie-ganado)}
.rep-leyenda .perdidos,.rep-seg.perdidos{background:var(--serie-perdido);fill:var(--serie-perdido)}
.rep-leyenda .espera,.rep-seg.espera{background:var(--serie-espera);fill:var(--serie-espera)}
/* La regla global `svg{width:20px;stroke:currentColor}` es para iconos: aqui
   encogia el grafico a 20 px y le ponia contorno al texto. Se anula entera. */
.rep-svg{width:100%;height:auto;display:block;stroke:none;fill:none;flex:initial}
.rep-svg text{stroke:none}
.rep-seg{stroke:var(--surface);stroke-width:2}
.rep-seg:hover{opacity:.85}
.rep-rejilla-l{stroke:var(--border);stroke-width:1}
.rep-eje{font-size:11px;fill:var(--ink-3);text-anchor:middle}
.rep-val{font-size:12px;font-weight:700;fill:var(--ink);text-anchor:middle}
.rep-tabla{margin-top:10px}
.rep-tabla summary{cursor:pointer;font-size:12.5px;font-weight:650;color:var(--ink-2)}
.rep-tabla table{margin-top:8px}

.rep-ranking{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:6px;
  counter-reset:r}
.rep-ranking li{display:flex;justify-content:space-between;gap:10px;font-size:13px;
  padding:7px 10px;border-radius:9px;background:var(--surface-2);counter-increment:r}
.rep-ranking li span::before{content:counter(r) ". ";color:var(--ink-3);font-weight:700}
table.grid.rep-top,.rep-tabla table.grid{width:100%;min-width:0;table-layout:fixed}
table.grid.rep-top th,table.grid.rep-top td{padding:8px 6px;white-space:nowrap}
.rep-top th:not(:first-child),.rep-top td:not(:first-child){width:74px;text-align:right}
.rep-top th:nth-child(2),.rep-top td:nth-child(2){width:104px}
.rep-top td:first-child{overflow:hidden;text-overflow:ellipsis}
@media (max-width:560px){
  .rep-embudo li{grid-template-columns:96px 1fr 36px 40px}
  .rep-lista li{grid-template-columns:100px 1fr 32px}
}

/* ---- la torta de estados ---- */
.rep-dona{display:flex;align-items:center;gap:22px;flex-wrap:wrap}
.rep-dona-svg{width:200px;height:200px;flex:none}
.rep-porcion{stroke:var(--surface);stroke-width:2}
.rep-porcion:hover{opacity:.85}
.rep-dona-n{font-size:30px;font-weight:800;fill:var(--ink);text-anchor:middle;letter-spacing:-.03em}
.rep-dona-ley{list-style:none;margin:0;padding:0;flex:1;min-width:190px;display:flex;
  flex-direction:column;gap:7px}
.rep-dona-ley li{display:grid;grid-template-columns:auto 1fr auto 46px;align-items:center;
  gap:9px;font-size:13px;color:var(--ink-2)}
.rep-dona-ley li b{color:var(--ink)}
.rep-dona-ley li em{font-style:normal;color:var(--ink-3);text-align:right}
.rep-dona-ley li.cero{opacity:.5}

/* ---- los colores de cada estado (tablero y torta) ----
   Validados con el validador del skill de visualizacion, en claro sobre #fff
   y en oscuro sobre #131c2e, con el orden de porciones de DONA_ORDEN
   (app.js): ninguna pareja de vecinas se confunde con daltonismo. Antes
   "Por evaluar" era el ambar de aviso y en oscuro no se distinguia del
   dorado de "Ganado". */
:root{--est-evaluar:#0891b2;--est-vamos:#15803d;--est-prep:#1d4ed8;--est-presentado:#8b5cf6;
  --est-ganado:#dea21e;--est-perdido:#b91c1c;--est-descartado:#475569}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){--est-evaluar:#0e9ab8;--est-vamos:#22a456;--est-prep:#3b82f6;
    --est-presentado:#c04fd8;--est-ganado:#bc8a12;--est-perdido:#ef4444;--est-descartado:#94a3b8}
}
:root[data-theme="dark"]{--est-evaluar:#0e9ab8;--est-vamos:#22a456;--est-prep:#3b82f6;
  --est-presentado:#c04fd8;--est-ganado:#bc8a12;--est-perdido:#ef4444;--est-descartado:#94a3b8}

/* ---- el rango a medida de Reportes ---- */
.rep-barra .spacer{flex:1}
.rep-rango{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:4px 4px 4px 10px;
  border-radius:12px;background:var(--surface);border:1px solid var(--border)}
.rep-rango.activo{border-color:var(--accent);box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 20%,transparent)}
.rep-rango label{display:flex;align-items:center;gap:6px;font-size:12.5px;font-weight:650;color:var(--ink-2)}
.rep-rango input{padding:6px 8px;border:1px solid var(--border);border-radius:8px;
  background:var(--surface-2);color:var(--ink);font:inherit;font-size:13px}
.rep-rango input:focus{outline:2px solid var(--foco);outline-offset:-1px;border-color:var(--accent)}
.rep-rango .btn{padding:6px 12px}
.rep-rango.activo .btn{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}

/* ---- revision 2026-09-29 ---- */
/* "Presentado": el violeta fijo #7c4ddb daba 2,74:1 en oscuro y 4,48:1 en
   claro. Un tono por tema, los dos por encima de 4,5:1. */
:root{--est-presentado-txt:#6d3fd1}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){--est-presentado-txt:#c4a8ff}}
:root[data-theme="dark"]{--est-presentado-txt:#c4a8ff}
/* Texto solo para lectores de pantalla (el resumen de Reportes). */
.solo-lector{position:absolute;width:1px;height:1px;margin:-1px;padding:0;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* El logotipo oficial (2026-09-30): tinta azul en claro, blanca en oscuro.
   Mismas dos reglas que los tokens: el atributo manda, y sin atributo manda
   el sistema. */
img.logo{display:block;width:auto;border-radius:0;object-fit:contain}
img.logo-oscuro{display:none}
:root[data-theme="dark"] img.logo-claro{display:none}
:root[data-theme="dark"] img.logo-oscuro{display:block}
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]) img.logo-claro{display:none}
  :root:not([data-theme="light"]) img.logo-oscuro{display:block}
}
.brand img.logo{height:30px;width:auto}
.brand small{border-left:1px solid var(--border);padding-left:10px}
@media (max-width:640px){.brand img.logo{height:24px}}
h1.logo-login{display:flex;justify-content:center;width:auto;height:auto;margin:0 auto 10px}
h1.logo-login img.logo{height:52px}
@media (max-height:640px){h1.logo-login img.logo{height:40px}}

/* Telegram: el texto y, al lado, el QR del bot para abrirlo desde el
   telefono. El QR va siempre sobre blanco (con su margen) para que la camara
   lo lea tambien en el tema oscuro. En el telefono no hace falta: ahi se
   pulsa el enlace. */
.tg-conectar{display:flex;flex-direction:column;align-items:center;gap:14px;text-align:center}
.tg-texto{min-width:0;max-width:620px}
.tg-texto .kwnote{margin-left:auto;margin-right:auto}
.tg-qr{margin:0;flex:none;display:flex;flex-direction:column;align-items:center;gap:6px;max-width:170px}
.tg-qr #tgQrImg{background:#fff;border-radius:10px;padding:6px;border:1px solid var(--border);line-height:0}
.tg-qr svg{width:140px;height:140px;display:block;fill:none;
  stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;shape-rendering:crispEdges}
.tg-qr figcaption{font-size:11.5px;color:var(--ink-3);text-align:center;line-height:1.35}
@media (max-width:640px){.tg-qr{display:none}}
/* En pantalla ancha, en fila (2026-10-15): el QR a la izquierda y el texto a
   la derecha, alineado a la izquierda. Apilados y centrados dejaban media
   tarjeta en blanco. */
@media (min-width:641px){
  .tg-conectar{flex-direction:row;align-items:center;gap:28px;text-align:left}
  .tg-qr{order:-1}
  .tg-texto{flex:1;max-width:820px}
  .tg-texto .kwnote{margin-left:0;margin-right:0}
}

/* El interruptor de correo dentro de la tarjeta de cada persona. */
.usrcard .dest-correo{margin-top:8px;font-size:12.5px;color:var(--ink-2)}
.usrcard .dest-correo input{width:16px;height:16px;padding:0}

/* ---- Suscripcion: acciones y flujo de pago (2026-10-01) ---- */
.sub-acciones{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:14px 22px}
.sub-acc-texto{min-width:0;flex:1 1 320px}
.sub-acc-texto h3{margin:0 0 4px}
.sub-precio{font-weight:600;color:var(--ink-3);font-size:.9em}
.sub-acc-botones{display:flex;gap:10px;flex-wrap:wrap}
.sub-acc-botones .btn{padding:11px 20px}
.sub-pendiente{flex-basis:100%;margin:0;padding:10px 12px;border-radius:10px;font-size:13px;
  background:var(--warn-bg,#fff7e6);color:var(--ink-2)}
.sub-dlg{width:min(560px,calc(100vw - 32px))}
.sub-dlg-cuerpo{padding:22px 24px;display:flex;flex-direction:column;gap:14px}
.sub-dlg-cuerpo > div:not(.sub-dlg-cab){display:flex;flex-direction:column;gap:14px}
.sub-dlg-cuerpo > div[hidden]{display:none}
.sub-dlg-cab{display:flex;flex-direction:row;align-items:center;justify-content:space-between;gap:10px}
.sub-dlg-cab h3{text-align:left}
.sub-dlg-cab h3{margin:0;font-size:19px}
.sub-x{width:34px;height:34px;border-radius:10px;border:1px solid var(--border);background:var(--surface);
  color:var(--ink-2);font-size:20px;line-height:1;cursor:pointer}
.sub-planes,.sub-metodos{display:flex;flex-direction:column;gap:10px}
.sub-plan,.sub-metodo{display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:2px 12px;align-items:center;
  border:1px solid var(--border);border-radius:12px;padding:14px 16px;cursor:pointer;background:var(--surface)}
.sub-plan input,.sub-metodo input{width:18px;height:18px;accent-color:var(--accent);grid-row:1/span 2}
.sub-plan.marcado,.sub-metodo.marcado{border-color:var(--accent);background:var(--oro-suave,#e3f2fa);
  box-shadow:0 0 0 1px var(--accent)}
.sub-plan-nombre{font-weight:800}
.sub-plan-precio{font-weight:800;justify-self:end}
.sub-plan-precio small{font-weight:500;color:var(--ink-3)}
.sub-plan-det{grid-column:2/-1;font-size:12.5px;color:var(--ink-3)}
.sub-metodo{grid-template-columns:auto auto minmax(0,1fr)}
.sub-metodo-ico{grid-row:1/span 2;width:40px;height:40px;border-radius:10px;background:var(--surface-2);
  display:flex;align-items:center;justify-content:center}
.sub-metodo-ico svg{width:20px;height:20px;fill:none;stroke:var(--ink-2);stroke-width:2;stroke-linejoin:round}
.sub-metodo-txt{display:flex;flex-direction:column;gap:2px;grid-row:1/span 2}
.sub-metodo-txt small{font-size:12.5px;color:var(--ink-3);line-height:1.4}
.sub-metodo.off{opacity:.55;cursor:not-allowed}
/* El periodo de pago en la ventana de Suscripción (0057): pestañas en una
   pista suave, la elegida en blanco. */
.sub-periodos{display:flex;width:max-content;max-width:100%;margin:0 0 12px;padding:4px;gap:2px;
  border-radius:12px;background:var(--surface-2);border:1px solid var(--border);overflow-x:auto}
.sub-periodos[hidden]{display:none}
.sub-periodos button{border:0;background:transparent;font:inherit;font-size:13.5px;font-weight:600;
  color:var(--ink-3);padding:8px 14px;border-radius:9px;cursor:pointer;white-space:nowrap}
.sub-periodos button[aria-selected="true"]{background:var(--surface);color:var(--ink);
  box-shadow:0 1px 3px rgba(15,27,45,.12)}
.sub-periodos button:focus-visible{outline:2px solid var(--foco);outline-offset:2px}
/* El codigo promocional en la ventana de pago (0058): un enlace discreto que
   abre un campo corto, y un boton para quitarlo que se ve cuando ya se
   aplico. */
.sub-promo{margin:0 0 12px}
.sub-promo-abrir{border:0;background:none;padding:0;color:var(--accent);font:inherit;font-size:13.5px;
  font-weight:600;cursor:pointer;text-decoration:underline}
.sub-promo-campo{display:flex;gap:8px;margin-top:8px}
.sub-promo-campo input{flex:1;min-width:0;text-transform:uppercase}
.sub-resumen .kv{margin:0}
.sub-resumen{border:1px solid var(--border);border-radius:12px;padding:12px 16px;background:var(--surface-2)}
.sub-pregunta{margin:4px 0 0;font-weight:800}
.sub-banco{border:1px solid var(--border);border-radius:12px;padding:12px 16px;margin:0}
@media (max-width:640px){.sub-acc-botones,.sub-acc-botones .btn{width:100%}}

/* Empresa suspendida: aviso fijo arriba con el boton de pagar. */
.aviso-suspendida{display:flex;flex-wrap:wrap;align-items:center;gap:10px 14px;margin:0 0 14px;
  padding:14px 16px;border-radius:12px;background:var(--warn-bg,#fff7e6);
  border:1px solid var(--warn,#d97706);color:var(--ink)}
.aviso-suspendida .btn{margin-left:auto}

/* ---- catálogo de equipos (2026-10-13) ---- */
.cat-barra{flex-wrap:wrap;gap:8px}
.cat-barra input[type=search]{min-width:240px;flex:1 1 240px}
.cat-campos{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px 14px}
.cat-campos .cat-ancho{grid-column:1/-1}
.cat-sub{margin:16px 0 6px}
table.cat-ficha{width:100%;border-collapse:collapse;font-size:13px}
table.cat-ficha td{padding:4px}
table.cat-ficha input{width:100%}
tr.cat-no-usa input{color:var(--ink-3)}
ul.cat-errores{max-height:220px;overflow:auto;font-size:13px}
@media (max-width:640px){.cat-campos{grid-template-columns:1fr}}
/* El diálogo del producto del catálogo (2026-10-14): el doble de ancho que
   los demás diálogos y los campos en dos columnas. Va con #catDlg porque la
   regla general `.sub-dlg-cuerpo > div` apila en una columna todo lo que
   cuelga del cuerpo del diálogo y pisaba la rejilla de .cat-campos. */
#catDlg.sub-dlg{width:min(1120px,calc(100vw - 32px))}
#catDlg .cat-campos{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px 18px}
@media (max-width:640px){#catDlg .cat-campos{grid-template-columns:1fr}}
/* Los botones del pie en fila, como en los demás diálogos (la misma regla
   general los apilaba a todo lo ancho). */
#catDlg .dlg-botones{flex-direction:row;justify-content:flex-end}
#catDlg #catLinea{align-self:flex-start}

/* =========================================================================
   LA FRANJA DE ARRIBA CON LA FOTO Y EL CATALOGO NUEVO (2026-10-15)
   Maqueta del socio humano. La foto (cabecera.webp, una franja panoramica
   con el skyline, los arboles y el edificio) es UNA sola capa en lo alto del
   contenido (main::before), fundida por la izquierda y por abajo con una
   mascara: sin bordes duros. La cabecera, mientras no se ha bajado, es
   transparente a la derecha y deja verla; al bajar (clase .abajo, app.js)
   vuelve a ser blanca con su filete. Solo en pantalla ancha.
   ========================================================================= */
@media (min-width:900px){
  header{transition:background-color .2s ease,box-shadow .2s ease,border-color .2s ease}
  header:not(.abajo){border-bottom-color:transparent;
    background:linear-gradient(90deg,var(--surface) 0,var(--surface) 20%,rgba(255,255,255,.55) 38%,rgba(255,255,255,0) 56%)}
  header.abajo{background:var(--surface);box-shadow:0 8px 22px -16px rgba(2,8,20,.3)}
  main{position:relative;isolation:isolate}
  main::before{content:"";position:absolute;z-index:-1;top:0;right:0;width:min(1300px,80%);
    height:calc(var(--head-h) + 180px);pointer-events:none;
    background:linear-gradient(rgba(247,251,255,.3),rgba(247,251,255,.3)),
      url("cabecera.webp") right bottom/cover no-repeat;
    -webkit-mask-image:linear-gradient(90deg,transparent 0,rgba(0,0,0,.55) 22%,#000 48%),
                       linear-gradient(180deg,#000 50%,transparent 100%);
    -webkit-mask-composite:source-in;
    mask-image:linear-gradient(90deg,transparent 0,rgba(0,0,0,.55) 22%,#000 48%),
               linear-gradient(180deg,#000 50%,transparent 100%);
    mask-composite:intersect}
  /* El plan y el nombre, sobre la foto: en pastillas claras de vidrio. */
  .userchip,.planchip{-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
  .userchip{padding:6px 12px;border-radius:999px;background:rgba(255,255,255,.78)}
  header .sep{display:none}
}
.planchip{background:#e8f1fd;color:#1d6ff2;border-color:#cfe0fb}

/* -- la cabecera de cada pantalla (titulo, lema y acciones) -- */
.vt-cab{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:16px 24px;margin:8px 0 18px}
.vt-titulo{font-size:clamp(26px,2.4vw,36px);font-weight:850;letter-spacing:-.025em;color:#0b1f44}
.vt-titulo span{color:#1d6ff2}
/* La raya azul tras el titulo, solo en Catalogo (asi viene en su maqueta). */
#view-catalogo .vt-titulo::after{content:"";display:inline-block;width:50px;height:2px;margin-left:18px;vertical-align:middle;background:#1d6ff2}
.vt-lema{margin:8px 0 0;font-size:14.5px;color:var(--ink-2)}
.catv-acciones{display:flex;flex-wrap:wrap;gap:10px}
.catv-acciones .btn{display:inline-flex;align-items:center;gap:8px;min-height:42px;padding:0 16px;border-radius:8px;
  font-size:14px;line-height:1;
  background:var(--surface);font-weight:600;text-decoration:none;box-shadow:0 6px 16px -12px rgba(11,31,68,.35)}
.catv-acciones .btn.primary{background:#1d6ff2;border-color:#1d6ff2;color:#fff}
.catv-acciones .btn svg{width:18px;height:18px}

/* -- los filtros, en su tarjeta -- */
.catv-filtros{display:grid;gap:12px;padding:14px 16px;margin-bottom:14px;border-radius:14px}
.catv-buscar{display:flex;align-items:center;gap:10px;padding:0 14px;border:1px solid var(--border);
  border-radius:10px;background:var(--surface-2)}
.catv-buscar svg{color:#1d6ff2}
.catv-buscar input{flex:1;min-width:0;border:0;background:transparent;padding:11px 0;font-size:14px;outline:none}
.catv-buscar:focus-within{border-color:#1d6ff2;box-shadow:0 0 0 3px rgba(29,111,242,.15)}
.catv-fila{display:flex;flex-wrap:wrap;align-items:center;gap:10px}
.catv-sel{display:flex;align-items:center;gap:8px;min-width:min(210px,100%);padding:0 10px 0 12px;
  border:1px solid var(--border);border-radius:10px;background:var(--surface)}
.catv-sel svg{color:#1d6ff2}
.catv-sel select{flex:1;min-width:0;border:0;background:transparent;padding:10px 2px;font-size:13.5px;outline:none}
.catv-sel:focus-within{border-color:#1d6ff2}
.catv-fila .statcount{font-size:13.5px;color:var(--ink-2)}
#catLimpiar{display:inline-flex;align-items:center;gap:8px;border-radius:10px;background:var(--surface)}
#catLimpiar svg{width:18px;height:18px}
.catv-borrar{display:inline-flex;align-items:center;gap:8px;border-radius:10px;
  background:#fff5f5;border-color:#fca5a5;color:#dc2626}
.catv-borrar svg{width:18px;height:18px}
.catv-borrar[hidden]{display:none}

/* -- la tabla -- */
.catv-caja{border-radius:14px}
.catv-caja .tablewrap{border-radius:14px 14px 0 0}
#catTbl thead th{background:#f6f9fd;font-size:12px;letter-spacing:.04em;text-transform:uppercase;color:#334155;padding:14px 12px}
#catTbl tbody td{vertical-align:middle;padding:12px}
.catv-orden{display:inline-flex;align-items:center;gap:6px;padding:0;border:0;background:transparent;cursor:pointer;
  font:inherit;color:inherit;letter-spacing:inherit;text-transform:inherit}
.catv-orden svg{width:16px;height:16px;color:#1d6ff2}
.catv-prod{display:flex;align-items:center;gap:14px}
.catv-mini{width:52px;height:52px;flex:none;border-radius:10px;display:grid;place-items:center;
  background:#eef4fc;border:1px solid #e1e9f5}
.catv-mini svg{width:24px;height:24px;color:#1d55b5}
.catv-mini.material{background:#fff4e6;border-color:#fde7c7}
.catv-mini.material svg{color:#c2410c}
.catv-mini.servicio{background:#ecfdf5;border-color:#bbf7d0}
.catv-mini.servicio svg{color:#15803d}
.catv-acc{text-align:right;white-space:nowrap}
.catv-icono{width:38px;height:38px;display:inline-grid;place-items:center;vertical-align:middle;cursor:pointer;
  border:1px solid var(--border);border-radius:10px;background:var(--surface);color:#1d6ff2}
.catv-icono:hover{border-color:#1d6ff2}
.catv-icono svg{width:18px;height:18px}
.catv-menu{position:relative;display:inline-block;margin-left:6px;vertical-align:middle}
.catv-menu summary{list-style:none}
.catv-menu summary::-webkit-details-marker{display:none}
/* El menu se abre hacia la izquierda y centrado en la fila: hacia abajo, en
   la ultima fila lo cortaria el borde de la tabla. */
.catv-menu-lista{position:absolute;right:calc(100% + 8px);top:50%;transform:translateY(-50%);z-index:5;
  min-width:140px;display:grid;padding:6px;border-radius:10px;background:var(--surface);text-align:left;
  border:1px solid var(--border);box-shadow:0 18px 40px -18px rgba(11,31,68,.45)}
.catv-menu-lista button{padding:8px 10px;border:0;border-radius:6px;background:transparent;cursor:pointer;
  text-align:left;font:inherit;font-size:13.5px;color:var(--ink)}
.catv-menu-lista button:hover{background:var(--surface-2)}
.catv-menu-lista .peligro{color:#dc2626}
.catv-nada td{padding:28px;text-align:center;color:var(--ink-2)}
.catv-nada .btn{margin-left:10px}

/* -- el pie: cuantos se ven y las paginas -- */
.catv-pie{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;
  padding:12px 18px;border-top:1px solid var(--border)}
#catMostrando{font-size:13.5px;color:var(--ink-2)}
.catv-pie .pager{padding:0;gap:4px;justify-content:flex-end}
.catv-pag{min-width:38px;height:38px;padding:0 6px;display:inline-grid;place-items:center;cursor:pointer;
  border:1px solid transparent;border-radius:10px;background:transparent;font:inherit;font-weight:650;color:var(--ink-2)}
.catv-pag.actual{background:#e8f1fd;border-color:#cfe0fb;color:#1d6ff2}
.catv-pag:hover:not([disabled]){border-color:var(--border)}
.catv-pag svg{width:18px;height:18px}
.catv-hueco{padding:0 4px;color:var(--ink-3)}

/* =========================================================================
   EL BUSCADOR DE LA MAQUETA NUEVA (2026-10-15)
   ========================================================================= */
/* Las cifras, en dos tarjetas. La caja es del GRUPO: cada .kpi sigue siendo
   una tira sin caja (test_los_kpis_del_buscador_llevan_icono...). */
#view-buscador .kpis{gap:14px;margin-bottom:16px}
.kpi-grupo{display:inline-flex;flex-wrap:wrap;align-items:center;padding:12px 4px;border-radius:14px;
  background:var(--surface);border:1px solid #e3ebf6;box-shadow:0 14px 30px -24px rgba(11,31,68,.4)}
.kpi-grupo .kpi{gap:10px;padding:2px 20px}
.kpi-grupo .kpi + .kpi{border-left:1px solid #e3ebf6}
.kpi-grupo .kpi .ico{width:22px;height:22px;stroke:#1d6ff2}
.kpi-grupo .kpi .val{font-size:20px;font-weight:800;color:#0b1f44}
.kpi-grupo .kpi.accent .val{color:#1d6ff2}
.kpi-grupo .kpi.estrella .ico{stroke:#f5b301}
.kpi-grupo .kpi .lbl{font-size:13px;color:var(--ink-2)}

/* La busqueda: campo con lupa y el boton grande a su lado. */
#view-buscador .filters{border-radius:14px;padding:16px 18px}
.filters .campoq > label{font-size:11.5px;letter-spacing:.05em;text-transform:uppercase;color:#334155}
.busq-fila{display:flex;gap:12px;align-items:stretch}
.busq-campo{flex:1;min-width:0;display:flex;align-items:center;gap:10px;padding:0 14px;
  border:1px solid var(--border);border-radius:10px;background:var(--surface-2)}
.busq-campo svg{color:#1d6ff2}
.busq-campo input{flex:1;min-width:0;border:0;background:transparent;padding:12px 0;font-size:14.5px;outline:none}
.busq-campo:focus-within{border-color:#1d6ff2;box-shadow:0 0 0 3px rgba(29,111,242,.15)}
#buscarBtn{display:inline-flex;align-items:center;justify-content:center;gap:10px;min-width:150px;padding:0 24px;
  border:0;border-radius:10px;font-size:15px;font-weight:750;color:#fff;
  background:linear-gradient(180deg,#3b8cff,#1d6ff2);box-shadow:0 12px 24px -14px rgba(29,111,242,.85)}
#buscarBtn svg{width:18px;height:18px;stroke-width:2.2}
.filters .conmutadores input[type=checkbox]{accent-color:#1d6ff2;width:17px;height:17px}
.filtrostoggle{display:inline-flex;align-items:center;gap:8px;border-radius:10px;background:var(--surface);font-weight:650}
.filtrostoggle svg{width:18px;height:18px}
@media (min-width:721px){ .filters .campo-ent{grid-column:span 2} }

/* La barra de resultados: cuantos hay a la izquierda, el orden a la derecha. */
.resbar{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 16px;margin:0 2px 10px}
.resbar .count{margin:0}
.ordenar{display:inline-flex;align-items:center;gap:10px;font-size:13px;color:var(--ink-2)}
.ordenar select{padding:8px 10px;border:1px solid var(--border);border-radius:8px;background:var(--surface);
  font-size:13px;color:var(--ink);min-width:200px}

/* La tabla: cabecera en versalitas y la columna de acciones. */
#tbl thead th{background:#f6f9fd;font-size:12px;letter-spacing:.04em;text-transform:uppercase;color:#334155;padding:14px 12px}
#tbl .acc{text-align:right;white-space:nowrap}
.accbtn{width:36px;height:36px;display:inline-grid;place-items:center;vertical-align:middle;margin-left:6px;cursor:pointer;
  border:1px solid var(--border);border-radius:10px;background:var(--surface);color:#1d6ff2;text-decoration:none}
.accbtn:hover{border-color:#1d6ff2;text-decoration:none}
.accbtn svg{width:18px;height:18px}
/* La fuente al lado del rubro, no debajo, como en la maqueta. */
#tbl .fuente-tag{display:inline-block;margin:4px 0 0 4px}

@media (max-width:720px){
  .busq-fila{flex-wrap:wrap}
  .busq-fila .busq-campo{flex:1 1 100%}
  #buscarBtn{flex:1 1 100%;min-height:44px}
  .kpi-grupo{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:10px 0;width:100%}
  .kpi-grupo .kpi + .kpi{border-left:0}
  .kpi-grupo .kpi{padding:2px 14px}
}
/* En un portatil (hasta 1600px) la tabla, con su columna de acciones, se
   pasaba del ancho: el objeto y la entidad ceden un poco de sitio. */
@media (min-width:721px) and (max-width:1599px){
  #tbl .obj{max-width:330px}
  #tbl .ent{max-width:190px}
  #tbl .accbtn{width:32px;height:32px;margin-left:4px}
}
/* Para que la tabla quepa: las cabeceras pueden partirse en dos lineas, la
   fecha va con la hora debajo (como en la maqueta) y la etiqueta del rubro
   tambien parte si es larga. */
#tbl thead th{white-space:normal;vertical-align:bottom}
#tbl td.fecha{width:86px;min-width:86px}
#tbl .rubro-tag{white-space:normal}
#tbl .plazo{white-space:normal;display:inline-block;max-width:96px}
#tbl .rubro-tag{border-radius:8px}
@media (min-width:721px) and (max-width:1365px){
  #tbl .ent{max-width:160px}
  #tbl .obj{max-width:300px}
}

/* El aviso de que las alertas por correo pueden caer en spam (2026-10-15). */
.aviso-spam{color:#9a5b00}
.dest-correo + .aviso-spam{margin-top:4px;font-size:12px}

/* En que etapa va (2026-10-17): terminadas en gris con su visto, la(s) en
   curso resaltadas en azul, las proximas normales. */
.timeline li.tl-terminada .etapa,.timeline li.tl-terminada .fecha{color:var(--ink-3)}
.timeline li.tl-terminada::before{background:var(--ink-3);border-color:var(--ink-3)}
.timeline li.tl-terminada .etapa::before{content:"✓ ";color:var(--good)}
.timeline li.tl-en_curso::before{background:var(--accent);border-color:var(--accent);box-shadow:0 0 0 4px rgba(11,107,154,.2)}
.timeline li.tl-en_curso .etapa{color:var(--accent)}
.tl-ahora{display:inline-block;margin-left:6px;padding:1px 8px;border-radius:999px;font-size:10.5px;font-weight:800;
  letter-spacing:.04em;text-transform:uppercase;color:var(--accent-ink);background:var(--accent);vertical-align:middle}
/* La linea de la tarjeta de Mis procesos. */
.kb-etapa{margin:6px 0 0;font-size:12px;line-height:1.4;color:var(--ink-2)}
.kb-etapa b{color:var(--ink)}
.kb-etapa.ahora{color:var(--accent)}
.kb-etapa.ahora b{color:var(--accent)}
.kb-etapa.vacia{color:var(--ink-3);font-style:italic}

/* ---- Cotizaciones (2026-10-23): editor, estados y versiones ---- */
#view-cotizador .vt-titulo::after{content:"";display:inline-block;width:50px;height:2px;margin-left:18px;vertical-align:middle;background:#1d6ff2}
.cot-tabla{min-width:760px}
.cot-estado{font-weight:650;margin:0}
.cot-estado.borrador{background:var(--neutral-bg);color:var(--neutral)}
.cot-estado.enviada{background:var(--info-bg);color:var(--info)}
.cot-estado.aprobada{background:var(--good-bg);color:var(--good)}
.cot-estado.anulada{background:var(--crit-bg);color:var(--crit)}
.cot-barra{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px 16px;margin:8px 0 14px}
.cot-acciones{display:flex;flex-wrap:wrap;gap:8px}
.cot-acciones .btn{text-decoration:none}
.cot-acciones .btn.danger{border-color:var(--crit)}
.cot-aviso{margin:0 0 14px;padding:10px 14px;border-radius:10px;background:var(--warn-bg);color:var(--warn);font-weight:600}
.cot-aviso[hidden]{display:none}
.cot-bloque{padding:16px;margin-bottom:14px;border-radius:14px}
.cot-titulo{display:flex;align-items:center;flex-wrap:wrap;gap:10px;margin-bottom:12px;font-size:16px}
.cot-campos{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
.cot-ancho{grid-column:1/-1}
.field textarea{width:100%;padding:8px 10px;border:1px solid var(--border);border-radius:9px;
  background:var(--surface-2);color:var(--ink);font-size:13px;font-family:inherit;resize:vertical}
.field input:disabled,.field select:disabled,.field textarea:disabled{opacity:.7;cursor:not-allowed}
.cot-proceso{display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:10px 16px}
.cot-proceso .field{flex:1;min-width:min(260px,100%)}
#cotVersiones > summary{cursor:pointer;font-weight:650}
.cot-ver-nueva{display:flex;flex-wrap:wrap;align-items:flex-end;gap:10px;margin:12px 0}
.cot-ver-nueva .field{flex:1;min-width:min(240px,100%)}
.cot-ver{list-style:none;margin:0;padding:0}
.cot-ver li{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px 16px;
  padding:10px 0;border-top:1px solid var(--border)}
.cot-ver .kwnote{margin-left:8px}
.cot-ver-acc{display:flex;flex-wrap:wrap;gap:8px}
.cot-logo{max-width:160px;max-height:80px;margin-top:6px;object-fit:contain}
@media (max-width:900px){.cot-campos{grid-template-columns:repeat(2,1fr)}}
@media (max-width:640px){
  .cot-campos{grid-template-columns:1fr}
  .cot-acciones{width:100%}
  .cot-acciones .btn{flex:1 1 auto;text-align:center}
}

/* TABLA CON COLUMNAS REDIMENSIONABLES (copia de static-admin/styles.css).
   Lineas entre columnas y filas; el ancho de cada columna lo fija
   columnasRedimensionables() (cotizador.js) arrastrando el asa de la cabecera. */
.tabla-redim{border-collapse:collapse;table-layout:fixed;font-size:13px}
.tabla-redim th,.tabla-redim td{border:1px solid var(--border);padding:8px 10px;text-align:left;
  vertical-align:middle;overflow:hidden;overflow-wrap:anywhere}
.tabla-redim thead th{position:relative;background:var(--surface-2);font-weight:700;
  white-space:nowrap;text-overflow:ellipsis}
.tabla-redim tbody tr:hover{background:var(--surface-2)}
.tabla-redim .asa{position:absolute;top:0;right:0;width:7px;height:100%;cursor:col-resize;
  touch-action:none}
.tabla-redim .asa:hover,.tabla-redim .asa.activa{background:var(--accent);opacity:.35}

/* ---- Cotizaciones: el editor de secciones e ítems (2026-10-23) ----
   La tabla NO es .grid (en un teléfono .grid se vuelve tarjetas): tiene
   columnas de verdad y se desplaza de lado dentro de su caja, sin mover la
   página. */
.cot-editor-caja{min-width:0}
.cot-herr{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:10px 14px}
.cot-herr-acc{display:flex;flex-wrap:wrap;align-items:flex-end;gap:8px;flex:1 1 520px}
.cot-destino{min-width:min(220px,100%);flex:0 1 260px}
.cot-vista{display:inline-flex}
.cot-vista .btn{border-radius:0}
.cot-vista .btn:first-child{border-radius:9px 0 0 9px}
.cot-vista .btn:last-child{border-radius:0 9px 9px 0;margin-left:-1px}
.cot-vista .btn[aria-pressed="true"]{background:var(--accent);color:var(--accent-ink);border-color:var(--accent)}
.cot-tabla-caja{overflow-x:auto;max-width:100%;margin-top:14px;-webkit-overflow-scrolling:touch}
.cot-nota{margin:12px 0 0}
.cot-vacia{margin:14px 0 0;padding:24px 12px;text-align:center;color:var(--ink-3);
  border:1px dashed var(--border);border-radius:10px}
.cot-editor td{padding:3px 6px}
.cot-editor .cot-der{text-align:right}
.cot-editor .cot-num{white-space:nowrap;font-variant-numeric:tabular-nums;color:var(--ink-2)}
.cot-asa-fila{display:inline-flex;vertical-align:middle;margin-right:4px;cursor:grab;color:var(--ink-3)}
.cot-asa-fila svg{width:14px;height:14px;fill:currentColor}
.cot-celda{width:100%;padding:5px 6px;border:1px solid transparent;border-radius:6px;background:transparent;
  color:var(--ink);font:inherit;font-size:13px}
.cot-celda:hover{border-color:var(--border)}
.cot-celda:focus{outline:2px solid var(--foco);outline-offset:-1px;background:var(--surface)}
.cot-celda.num{text-align:right;font-variant-numeric:tabular-nums}
.cot-celda-txt{display:block;padding:5px 0;white-space:pre-wrap}
textarea.cot-desc{display:block;resize:none;overflow:hidden;min-height:30px;line-height:1.4;field-sizing:content}
.cot-fila-sec{background:var(--surface-2)}
.cot-fila-sec.nivel-0{background:var(--oro-suave)}
.cot-fila-sec td{font-weight:650}
.cot-sec-nombre{white-space:nowrap}
.cot-sec-input{width:calc(100% - 30px);font-weight:650;vertical-align:middle}
.cot-plegar{width:24px;height:24px;padding:0;border:0;border-radius:6px;background:transparent;color:var(--ink-2);
  vertical-align:middle;cursor:pointer}
.cot-plegar svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:2;transition:transform .15s}
.cot-plegar[aria-expanded="false"] svg{transform:rotate(-90deg)}
.cot-acc{white-space:nowrap}
.cot-ico{width:26px;height:26px;padding:0;margin-right:2px;border:1px solid transparent;border-radius:7px;
  background:transparent;color:var(--ink-2);cursor:pointer;vertical-align:middle}
.cot-ico:hover{border-color:var(--border);color:var(--accent)}
.cot-ico[data-accion="borrar"]:hover,.cot-ico[data-accion="quitar"]:hover{color:var(--crit)}
.cot-ico svg{width:15px;height:15px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.cot-pastilla{display:inline-block;min-width:34px;padding:2px 6px;border-radius:999px;font-size:10.5px;font-weight:800;
  letter-spacing:.03em;text-align:center;background:var(--neutral-bg);color:var(--neutral)}
.cot-pastilla.equipo{background:var(--info-bg);color:var(--info)}
.cot-pastilla.material{background:var(--warn-bg);color:var(--warn)}
.cot-pastilla.servicio{background:var(--good-bg);color:var(--good)}
.cot-pastilla.mano_obra{background:var(--oro-suave);color:var(--oro-texto)}
.cot-pastilla.gasto{background:var(--neutral-bg);color:var(--neutral)}
.cot-pastilla-caja{position:relative;display:inline-block;border-radius:999px}
.cot-pastilla-caja:focus-within{outline:2px solid var(--foco);outline-offset:1px}
.cot-tipo-sel{position:absolute;inset:0;width:100%;opacity:0;cursor:pointer}
.cot-soltar-antes td{box-shadow:inset 0 2px 0 var(--accent)}
.cot-soltar-despues td{box-shadow:inset 0 -2px 0 var(--accent)}
.cot-soltar-dentro td{background:var(--info-bg)}
.cot-arrastrando{opacity:.45}
.cot-totales{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:14px}
.cot-tot{display:flex;flex-direction:column;gap:2px;min-width:120px;padding:8px 12px;border:1px solid var(--border);
  border-radius:10px;background:var(--surface-2)}
.cot-tot span{font-size:11px;font-weight:600;color:var(--ink-2);text-transform:uppercase;letter-spacing:.04em}
.cot-tot b{font-size:14px}
.cot-tot.neg b{color:var(--crit)}
.cot-tot.total{background:var(--oro-suave);border-color:var(--oro-borde)}
.cot-tot.total b{color:var(--oro-texto);font-size:16px}
/* Pantalla completa: el bloque del editor tapa la ventana (bajo el aviso). */
body.cot-pantalla-completa{overflow:hidden}
/* `main` aísla su capa (isolation, por la imagen de cabecera): sin subirla
   entera, la cabecera y el menú lateral quedan encima del editor fijo y le
   tapan la barra de herramientas y la primera columna. */
body.cot-pantalla-completa main{position:relative;z-index:61}
body.cot-pantalla-completa #cotEditorTabla{position:fixed;inset:0;z-index:60;margin:0;border-radius:0;
  overflow:auto;padding:16px}
/* El buscador del catálogo. */
#cotDlgCatalogo.sub-dlg{width:min(860px,calc(100vw - 32px))}
#cotDlgCatalogo .cot-cat-filtros{display:grid;grid-template-columns:2fr 1fr 1.4fr;gap:10px}
#cotDlgCatalogo .cot-cat-lista{display:block;max-height:min(52vh,460px);overflow-y:auto;
  border:1px solid var(--border);border-radius:10px}
#cotDlgCatalogo .cot-cat-lista:empty{display:none}
.cot-cat-lista > .kwnote,.cot-cat-lista > .cot-vacia{margin:10px 12px}
.cot-cat-fila{display:flex;align-items:center;gap:10px;padding:8px 12px;border-top:1px solid var(--border)}
.cot-cat-fila:first-child{border-top:0}
.cot-cat-txt{flex:1;min-width:0;display:flex;align-items:flex-start;gap:8px;cursor:pointer;font-size:13px}
.cot-cat-sub{display:block;font-size:12px;color:var(--ink-3)}
.cot-cat-cant{width:80px;flex:none;padding:6px 8px;border:1px solid var(--border);border-radius:8px;
  background:var(--surface-2);color:var(--ink);font:inherit;text-align:right}
/* ---- Cotizaciones, fase 2: costos ocultos (2026-10-23) ----
   Un oculto se ve atenuado con su pastilla; debajo, su panel de reparto a
   todo lo ancho de la tabla. El panel se queda pegado al borde izquierdo de
   la caja y mide lo que se ve de ella (100cqw), así en un teléfono no hay que
   desplazar la tabla de lado para usarlo. */
.cot-tabla-caja{container-type:inline-size}
.cot-aviso-reparto{margin:14px 0 0}
.cot-acciones a[aria-disabled="true"]{opacity:.5;cursor:not-allowed}
.cot-oculto td,.cot-oculto .cot-celda,.cot-oculto .cot-celda-txt{color:var(--ink-3)}
.cot-oculto-marca{display:flex;flex-wrap:wrap;gap:4px;margin:3px 0 1px}
.cot-oculto-pas{display:inline-block;padding:1px 7px;border-radius:999px;font-size:10.5px;font-weight:700;
  background:var(--neutral-bg);color:var(--neutral)}
.cot-editor .cot-fila-reparto > td{padding:0;overflow:visible;background:var(--surface-2)}
.cot-reparto{position:sticky;left:0;width:min(900px,100cqw);padding:10px 12px}
.cot-rep-cab{display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px}
.cot-rep-total{color:var(--ink-2)}
.cot-rep-insignia{padding:2px 8px;border-radius:999px;font-size:11.5px;font-weight:700}
.cot-rep-insignia.ok{background:var(--good-bg);color:var(--good)}
.cot-rep-insignia.falta{background:var(--crit-bg);color:var(--crit)}
.cot-rep-sin{font-size:11.5px;font-weight:650;color:var(--warn)}
.cot-rep-cuerpo{display:flex;flex-direction:column;gap:8px;margin-top:8px}
.cot-rep-cuerpo[hidden]{display:none}
.cot-rep-fila,.cot-rep-grupo,.cot-rep-botones{display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px}
.cot-rep-grupo{font-size:12.5px;color:var(--ink-2)}
.cot-rep-miembro{display:inline-flex;align-items:center;gap:6px}
.cot-rep-destino,.cot-rep-porc{padding:6px 8px;border:1px solid var(--border);border-radius:8px;
  background:var(--surface);color:var(--ink);font:inherit;font-size:13px}
.cot-rep-destino{flex:1 1 260px;min-width:0;max-width:100%}
.cot-rep-porc{width:90px;text-align:right;font-variant-numeric:tabular-nums}
.cot-rep-destino:focus,.cot-rep-porc:focus{outline:2px solid var(--foco);outline-offset:-1px}
.cot-rep-pct{display:inline-flex;align-items:center;gap:4px}
.cot-rep-nombre{flex:1 1 260px;min-width:0}
.cot-rep-monto{min-width:110px;text-align:right}
.cot-rep-btn{padding:6px 10px;font-size:12.5px}
.cot-rep-btn:disabled{opacity:.5;cursor:not-allowed}
.cot-rep-vacio{margin:0;font-size:12.5px;color:var(--ink-3)}
#cotDlgReparto .cot-cat-lista{display:block;max-height:min(52vh,420px);overflow-y:auto;
  border:1px solid var(--border);border-radius:10px}
#cotDlgReparto .cot-cat-lista:empty{display:none}
/* ---- Cotizaciones, fase 3: la hoja de cálculo (2026-10-24) ----
   Columnas propias (las calculadas, atenuadas), filas calculadas al pie de
   la tabla, indicadores bajo los totales y el diálogo que los gestiona. */
.cot-editor th.cot-hoja-calc,.cot-editor td.cot-hoja-calc{color:var(--ink-3)}
.cot-editor td.cot-hoja-calc{background:var(--surface-2)}
.cot-error{color:var(--crit);font-weight:700;cursor:help}
input.cot-celda.cot-error{color:var(--crit);font-weight:700}
.cot-editor .cot-fila-calculada td{border-top:2px solid var(--border);background:var(--oro-suave);padding:7px 6px}
.cot-fila-calc-nombre{font-weight:650}
.cot-fila-calc-nombre b{margin-left:6px}
.cot-indicadores{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:8px}
.cot-indicadores[hidden]{display:none}
.cot-indicador{display:flex;flex-direction:column;gap:2px;min-width:120px;padding:8px 12px;border:1px dashed var(--border);
  border-radius:10px;background:var(--surface)}
.cot-indicador span{font-size:11px;font-weight:600;color:var(--ink-2);letter-spacing:.02em}
.cot-indicador b{font-size:14px}
.cot-indicador.destacado{border-style:solid;border-color:var(--oro-borde);background:var(--oro-suave)}
.cot-indicador.destacado b{color:var(--oro-texto);font-size:16px}
#cotDlgHoja.sub-dlg{width:min(720px,calc(100vw - 32px))}
#cotDlgHoja .cot-hoja-pestanas{display:inline-flex;flex-direction:row;gap:0;align-self:flex-start}
#cotDlgHoja .dlg-botones{flex-direction:row;justify-content:flex-end}
.cot-hoja-ayuda{margin:0;font-size:12.5px}
#cotDlgHoja .cot-hoja-lista{display:block;max-height:min(40vh,360px);overflow-y:auto;
  border:1px solid var(--border);border-radius:10px}
.cot-hoja-lista > .cot-vacia{margin:10px 12px;padding:14px 12px}
.cot-hoja-txt{flex:1;min-width:0;font-size:13px;overflow-wrap:anywhere}
.cot-hoja-fila.cot-soltar-antes{box-shadow:inset 0 2px 0 var(--accent)}
.cot-hoja-fila.cot-soltar-despues{box-shadow:inset 0 -2px 0 var(--accent)}
.cot-hoja-tit{margin:0;font-size:15px}
#cotHojaEditor{padding:14px;border:1px solid var(--border);border-radius:10px;background:var(--surface-2)}
#cotHojaEditor [hidden]{display:none}
#cotHojaEditor textarea{width:100%;padding:8px 10px;border:1px solid var(--border);border-radius:9px;
  background:var(--surface);color:var(--ink);font-family:var(--mono);font-size:13px;resize:vertical}
#cotHojaEditor textarea:focus{outline:2px solid var(--foco);outline-offset:-1px;border-color:var(--accent)}
#cotHojaEditor .field input,#cotHojaEditor .field select{background:var(--surface)}
@media (max-width:640px){
  .cot-herr-acc .btn{flex:1 1 auto}
  .cot-indicador{flex:1 1 calc(50% - 8px);min-width:0}
  .cot-hoja-fila{flex-wrap:wrap}
  .cot-destino{flex:1 1 100%}
  .cot-tot{flex:1 1 calc(50% - 8px);min-width:0}
  #cotDlgCatalogo .cot-cat-filtros{grid-template-columns:1fr}
  .cot-rep-monto{min-width:0}
}
