
:root{
  /* LOS CONTROLES QUE DIBUJA EL SISTEMA OPERATIVO, EN EL TEMA QUE CORRESPONDE. Sin esto el navegador
     los pinta siempre en claro: en Stock, con tema oscuro, las casillas de tildar salían como
     CUADRADOS BLANCOS —26 px en el teléfono— y la esquina donde se cruzan las dos barras de scroll
     quedaba de un blanco que saltaba a la vista en cada tabla. Con `color-scheme` los pinta el
     sistema en oscuro y no hay que maquillar cada control uno por uno. */
  color-scheme:dark;
  /* GRISES NEUTROS. El azulado de antes (#151922) daba el aire de aplicación nueva; el clásico usa
     gris parejo. Y los escalones entre superficies son chicos a propósito: acá lo que separa una
     zona de otra es la línea, no el salto de color. */
  --bg:#1b1e21;
  --bg-2:#1e2124;
  /* EL MENU LATERAL, medio escalon mas CLARO que el fondo. Estaba pintado con `--bg`, el mismo
     valor exacto que el cuerpo —1.00:1— y se camuflaba: lo unico que lo separaba era la linea. */
  --rail:#212427;
  --surface:#232629;
  --surface-2:#282c30;
  --surface-3:#2e3237;
  --border:#34383e;
  --border-strong:#454b52;
  /* En oscuro, la letra en peso normal necesita más contraste que la misma letra en negrita, y el
     clásico usa menos negrita. Por eso estos grises son más claros que los de antes. */
  --text:#e9ecef;
  --text-dim:#c2c8cf;      /* medido: 9,1 de contraste sobre --surface */
  --text-faint:#a2aab3;    /* medido: 6,4 — sigue leyéndose como secundario */
  --signal:#2f6091;       /* el acento de la maqueta: azul apagado, para RELLENOS */
  --signal-dim:#274f77;
  --on-signal:#ffffff;    /* texto/íconos sobre el relleno de acento */
  --accent-ink:#7fb3e0;   /* el acento como TEXTO o línea fina sobre fondo oscuro */
  --link:#7fb3e0;
  --amber:#d4a24a;
  /* Medido: con #e8837f las etiquetas chicas de 11 px (atacando, sin senal) quedaban en 4,4 : 1,
     apenas por debajo del minimo. A #ef918c pasan a 4,9 y el tono sigue siendo el de la maqueta. */
  --red:#ef918c;
  --red-fill:#a83a37;      /* para fondos con texto blanco */
  --accent-fill:#2f6091;
  --green:#5fbe84;
  --violet:#9a93cf;
  --amb-oficina:#4f8b96; --amb-gesron:#6a8bb5; --amb-baja:#c07a76;   /* ámbitos de Stock */
  /* Casi sin sombra: en clásico el relieve lo dan los bordes, no el desenfoque. */
  --shadow:0 1px 3px rgba(0,0,0,.38);
  /* El fondo de lo ELEGIDO: un filtro puesto, un período elegido, una fila seleccionada. Tenue a
     propósito: marca sin gritar, que es lo que hace un sistema clásico. */
  --selected:#2a3644;
  /* La franja de las filas pares. Va como capa translúcida y no como color fijo, así funciona
     sobre cualquiera de las superficies sin tener que definir una variante por cada una. */
  --zebra:rgba(255,255,255,.035);
  --radius:2px;   /* clásico: esquinas casi rectas */
  /* ESCALA DE PESO Y DE RADIO. Los valores son los de hoy: esta capa no cambia nada de cómo se ve.
     Existe para que el estilo clásico se pueda probar cambiando estos números en un solo lugar, en
     vez de tocar mil cuatrocientas declaraciones repartidas por toda la hoja. */
  /* PESOS. En la maqueta clásica lo más pesado era 600: la jerarquía la dan el tamaño y el espacio,
     no el grosor. Los nombres se mantienen para no tocar mil cuatrocientas declaraciones. */
  --fw-normal:400; --fw-medium:500; --fw-semi:600; --fw-bold:600; --fw-black:700; --fw-max:700;
  /* RADIOS. Casi rectos. El círculo NO se toca: son las fotos de perfil y los puntos de estado, que
     redondos son redondos en cualquier estilo. */
  --radius-xs:0; --radius-sm:2px; --radius-lg:3px; --radius-xl:3px;
  --radius-circ:50%; --radius-pill:2px;
}

/* ====================== TEMA CLARO (empresarial) ====================== */
html[data-theme="light"]{
  color-scheme:light;
  /* Papel blanco y grises neutros: la planilla de siempre. */
  --bg:#eceef0;
  --bg-2:#f2f3f5;
  /* Y ACA MEDIO ESCALON MAS OSCURO, no mas claro. En claro el cuerpo trae las tarjetas en blanco,
     asi que el menu tiene que irse hacia abajo para leerse como el marco y no como contenido. */
  --rail:#e4e8ec;
  --surface:#ffffff;
  --surface-2:#f7f8f9;
  /* MÁS OSCURO QUE EL FONDO. Era #eceef0, el MISMO valor que `--bg`: la cabecera de las 89 tablas
     del sistema estaba pintada del color del papel y no se veía —medido, 1.00:1—. */
  --surface-3:#dde2e7;
  /* Las líneas de todas las tablas y rejillas. A #dfe2e6 daban 1.12:1 contra el fondo, que es no
     verse. En oscuro no se tocan: ahí se ven bien. */
  --border:#c9ced5;
  --border-strong:#a8afb8;
  --text:#1a1d21;
  --text-dim:#494f57;
  /* Medido: con #6b727b el texto secundario quedaba en 4,38 : 1, apenas por debajo del mínimo.
     A #616870 pasa a 5,1 y sigue leyéndose como secundario. */
  --text-faint:#616870;
  /* COLORES DE ESTADO PROPIOS DEL TEMA CLARO. Los de arriba se eligieron para fondo oscuro: sobre
     el papel blanco de este tema son ilegibles. Están acá adentro a propósito, así tocarlos no
     puede afectar al tema oscuro. */
  --amb-oficina:#0a7168; --amb-gesron:#12559f; --amb-baja:#a32020;   /* ámbitos de Stock */
  --red:#a32020;
  --amber:#8a5a00;
  --green:#1b6b39;
  --violet:#4b3fa8;
  --red-fill:var(--red);
  --accent-fill:var(--accent-ink);
  --signal:#144a80;
  --signal-dim:#103a64;
  --on-signal:#ffffff;
  --accent-ink:#144a80;
  --link:#144a80;
  --selected:#dfe8f2;
  --zebra:rgba(0,0,0,.028);
  --shadow:0 1px 3px rgba(23,37,64,.16);
}
html[data-theme="light"] body::before{
  background:transparent;
}
html[data-theme="light"] .app-header{background:rgba(244,246,249,.9)}
/* Tema claro: que las tarjetas se despeguen del fondo de la columna (blancas + sombrita) */
html[data-theme="light"] .card{background:var(--card-bg,var(--surface));box-shadow:0 1px 3px rgba(23,37,64,.07)}
html[data-theme="light"] .card:hover{box-shadow:0 8px 18px -10px rgba(23,37,64,.26)}
html[data-theme="light"] .login-aside{
  background:var(--surface-2);
}
html[data-theme="light"] .scrim{background:rgba(28,38,58,.42)}
html[data-theme="light"] #leaflet,
html[data-theme="light"] .leaflet-container{background:#e6eaf1}
html[data-theme="light"] .leaflet-tile{filter:none}
html[data-theme="light"] .map-legend{background:rgba(255,255,255,.95)}
html[data-theme="light"] .leaflet-control-attribution{background:rgba(255,255,255,.86)!important}
html[data-theme="light"] ::selection{background:var(--signal);color:#fff}
/* tema claro: chips con acento cian → tinte teal del tema (no neón) */
html[data-theme="light"] .role-tec,
html[data-theme="light"] .lg-blue{background:rgba(47,95,208,.12)}
/* tema claro: bajar la saturación de los acentos brillantes (menos "neón") */
html[data-theme="light"] .grupo-chip,
html[data-theme="light"] .grupo-dot,
html[data-theme="light"] .prio-badge,
html[data-theme="light"] .pd,
html[data-theme="light"] .col-dot,
html[data-theme="light"] .card-prio,
html[data-theme="light"] .role-tag,
html[data-theme="light"] .chk-fill,
html[data-theme="light"] .km-bar > div,
html[data-theme="light"] .card-sector,
html[data-theme="light"] .clbl,
html[data-theme="light"] .stat .ico,
html[data-theme="light"] .kpi.accent,
html[data-theme="light"] .map-legend .ld,
html[data-theme="light"] .map-legend .ll{ filter: saturate(.68); }
/* tema claro: subir el contraste de textos de color (chips/estados) que quedaban casi invisibles */
html[data-theme="light"] .ic-chip.clientes{color:#1f7a70}
html[data-theme="light"] .ic-chip.cierreop,
html[data-theme="light"] .lane-tk,
html[data-theme="light"] .ic-chip.recoord{color:#9a6b12}
html[data-theme="light"] .ic-chip.depok,
html[data-theme="light"] .ic-chip.avisado{color:#157a4e}
html[data-theme="light"] .ic-chip.origen,
html[data-theme="light"] .role-stock,
html[data-theme="light"] .card-motivo.prep{color:#2f6dbf}
html[data-theme="light"] .ic-chip.derivada{color:#6a4fc0}
html[data-theme="light"] .ic-chip.blocked,
html[data-theme="light"] .card-motivo,
html[data-theme="light"] .role-admin{color:#c0303f}
html[data-theme="light"] .motivo-note.blk{color:#c0455a}
html[data-theme="light"] .flt-recoord,
html[data-theme="light"] .role-tag.coord{color:#b0501f}
html[data-theme="light"] .tv-col.infra .tv-col-ic,
html[data-theme="light"] .tv-col.infra .tv-tile.good .tv-n{color:#7b3fb5}
html[data-theme="light"] .role-tag.admin,
html[data-theme="light"] .role-coord,
html[data-theme="light"] .stat.alert .num,
html[data-theme="light"] .stat.alert .ico,
html[data-theme="light"] .sc.sc-alert b{color:#9a6b12}
html[data-theme="light"] .umenu-item.on .um-state{color:#157a4e}
html[data-theme="light"] .card-dates .due-bad,
html[data-theme="light"] .card-meta .row.due-bad,
html[data-theme="light"] .login-err,
html[data-theme="light"] .ui-err{color:#8e1a22}   /* iba en #c0303f, que sobre la tarjeta teñida daba 3,19 */
/* Los estados de zona llevan el color del estado (--ec), que es configurable y puede ser cualquiera:
   el verde de «Finalizado» daba 2,52 sobre fondo claro. Misma solución que los chips de tipo. */
html[data-theme="light"]        .zn-work .zn-est{color:color-mix(in srgb, var(--ec, var(--text-dim)) 44%, #000)}
:root:not([data-theme="light"]) .zn-work .zn-est{color:color-mix(in srgb, var(--ec, var(--text-dim)) 47%, #fff)}
html[data-theme="light"] .role-admin{color:#96140f}   /* sobre su propio tinte rojo quedaba en 4,44 */
/* Niveles de vencimiento: el color del nivel entra por --vc y cada tema lo lleva hacia donde le falta. */
html[data-theme="light"]        .venc-lvl{color:color-mix(in srgb, var(--vc) 78%, #000)}
:root:not([data-theme="light"]) .venc-lvl{color:color-mix(in srgb, var(--vc) 78%, #fff)}
/* pills de proyecto: texto blanco sobre color elegido por el usuario → sombra sutil para que siempre se lea */
.proj-chip,.mt-proj,.proj-ic,.flt-proj,.fl-mini-proj,.hist-grp-ic,.clbl{text-shadow:0 1px 1.5px rgba(0,0,0,.28)}

*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
/* El doble toque ya no agranda; el pellizco sí sigue andando. Sin esto, dos toques seguidos sobre
   una fila de tabla dejaban la pantalla con zoom, y como el `body` no scrollea (abajo) no había
   manera de volver salvo pellizcando a mano. */
html{touch-action:manipulation}
/* `small` sin tamaño propio vale 0.8333em = 13,3333 px, y hay 437 en la página: con densidad 1 eso
   es medio píxel repartido en cada letra. Se le fija el entero más cercano. */
small{font-size:12.5px}
/* Estos tres heredaban el 0.8333em del navegador y quedaban en 13,3333: un span del menu y las
   flechitas del mes en Caja. */
#sideNav .sn-toggle span,.cja-mes .icon-btn{font-size:12.5px}
body{
  font-family:'IBM Plex Sans',sans-serif;
  background:var(--bg);
  color:var(--text);
  /* NO poner `antialiased`: apaga el subpixel de Windows y el texto se ve fino y lavado en
     pantallas de densidad 1, que son las que se usan acá. */
  -webkit-font-smoothing:auto;
  overflow:hidden;
}
/* fondo atmosférico tipo panel NOC */
body::before{
  content:"";position:fixed;inset:0;z-index:0;pointer-events:none;
  background:transparent;
}
button{font-family:inherit;cursor:pointer;border:none;background:none;color:inherit}
/* NO HABÍA NINGUNA REGLA DE LINKS EN TODO EL SISTEMA. Los <a> sin clase salían con el azul que trae
   el navegador de fábrica (#0000EE): sobre fondo oscuro eso da 1,68 de contraste, o sea invisible.
   Se notaba en «Caídas de clientes», donde el número de caídas y la señal son links. Va en el
   arranque y con especificidad mínima, así que cualquier link que ya tenga su color lo conserva. */
a{color:var(--link);text-decoration:none}
a:hover{text-decoration:underline}
input,select,textarea{font-family:inherit}
.mono{font-family:'IBM Plex Mono',monospace}
::selection{background:var(--signal);color:var(--on-signal)}

/* scrollbars */
::-webkit-scrollbar{height:10px;width:10px}
::-webkit-scrollbar-track{background:transparent}
/* Donde se cruzan la barra de abajo y la de la derecha queda un cuadradito. Al pintar las otras
   partes a mano, ésa se quedó con el blanco de fábrica y saltaba en cada tabla del tema oscuro. */
::-webkit-scrollbar-corner{background:transparent}
::-webkit-scrollbar-thumb{background:var(--border-strong);border-radius:var(--radius);border:3px solid transparent;background-clip:padding-box}
::-webkit-scrollbar-thumb:hover{background:var(--text-faint);background-clip:padding-box}

/* Datos de conexión en UNA fila: antes eran cinco cajones grandes con un ejemplo adentro, ocupando
   media pantalla para no decir nada. Vacío se ve como «—» y no como un hueco enorme. */
.zn-conn2{display:flex;gap:10px;flex-wrap:wrap}
.zn-c2{display:flex;flex-direction:column;gap:3px;flex:1 1 150px;min-width:0}
.zn-c2>span{font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint);font-weight:var(--fw-bold)}
.zn-c2>input{width:100%;box-sizing:border-box}
@media(max-width:760px){ .zn-c2{flex:1 1 45%} }

/* ====================== LOGIN ====================== */
/* Con sesión guardada, la pantalla de entrada no se dibuja nunca: en su lugar va la marca con el
   girito hasta que el programa está listo. Si la sesión resultó vencida, `showLogin()` pone el
   display en el elemento y eso le gana a esta regla — se ve el login, que es lo correcto. */
html.con-sesion #login{display:none}
#arranque{position:fixed;inset:0;z-index:60;display:none;align-items:center;justify-content:center;
  flex-direction:column;gap:16px;background:var(--bg,#151922)}
html.con-sesion #arranque{display:flex}
html.listo #arranque{display:none}
#arranque .ar-marca{font-family:'Archivo',system-ui,sans-serif;font-weight:var(--fw-black);font-size:19px;
  letter-spacing:-.3px;color:var(--text,#e7ecf5)}
#arranque .ar-marca span{color:var(--accent-ink,#e0457b)}
#arranque .ar-spin{width:26px;height:26px;border:3px solid rgba(255,255,255,.14);
  border-top-color:var(--accent-ink,#e0457b);border-radius:var(--radius-circ);animation:ar-gira .8s linear infinite}
@keyframes ar-gira{to{transform:rotate(360deg)}}
#login{
  position:fixed;inset:0;z-index:50;display:flex;align-items:center;justify-content:center;
  padding:24px;
}
.login-card{
  position:relative;z-index:1;width:min(960px,100%);
  background:var(--surface);
  border:1px solid var(--border);border-radius:var(--radius);box-shadow:var(--shadow);
  display:grid;grid-template-columns:1.05fr 1fr;overflow:hidden;
  animation:rise .6s cubic-bezier(.2,.8,.2,1) both;
}
.login-aside{
  padding:48px 44px;border-right:1px solid var(--border);
  background:var(--bg-2);
  display:flex;flex-direction:column;justify-content:space-between;
}
.brand{display:flex;align-items:center;gap:12px}
.brand .glyph{
  width:40px;height:40px;border-radius:var(--radius);display:grid;place-items:center;
  background:var(--signal);
  color:var(--on-signal);
}
.brand .glyph svg{width:23px;height:23px}
.brand h1{font-family:'Archivo';font-weight:var(--fw-max);font-size:21px;letter-spacing:-.4px}
.brand-txt{display:flex;flex-direction:column;justify-content:center}
.brand-ver{font-family:'IBM Plex Mono';font-size:10px;font-weight:var(--fw-bold);color:var(--accent-ink);letter-spacing:.14em;line-height:1;margin-top:2px;align-self:flex-end}
.brand h1 span{color:var(--accent-ink)}
.login-aside .tagline{
  font-family:'Archivo';font-weight:var(--fw-black);font-size:30px;line-height:1.08;letter-spacing:-1px;
  margin-top:auto;margin-bottom:14px;
}
.login-aside .tagline em{color:var(--accent-ink);font-style:normal}
.login-aside p{color:var(--text-dim);font-size:14px;line-height:1.6;max-width:38ch}
.login-meta{display:flex;gap:22px;margin-top:28px;color:var(--text-faint);font-size:12px;letter-spacing:.12em;text-transform:uppercase}
.login-meta b{color:var(--accent-ink);font-weight:var(--fw-semi)}

.login-main{padding:44px 42px;display:flex;flex-direction:column}
.login-main h2{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:17px;letter-spacing:-.2px}
.login-main .sub{color:var(--text-dim);font-size:13.5px;margin:6px 0 22px}
.li-remember{display:flex;align-items:center;gap:8px;margin:2px 0 2px;font-size:12.5px;color:var(--text-dim);cursor:pointer;user-select:none;font-weight:var(--fw-medium)}
.li-remember input{width:16px;height:16px;margin:0;cursor:pointer;accent-color:var(--accent, #3b82f6)}
.li-remember span{line-height:1.3}
.login-form{display:flex;flex-direction:column;gap:6px}
.login-form label{font-size:11px;letter-spacing:.13em;text-transform:uppercase;color:var(--text-faint);font-weight:var(--fw-semi);margin-top:10px}
.login-form .inp{padding:12px 14px;font-size:13.5px}
.login-form .btn-primary{margin-top:18px;width:100%;justify-content:center;padding:12px}
.btn-install{margin-top:14px;width:100%;justify-content:center;gap:9px;padding:12px;background:transparent;border:1.5px solid var(--signal);color:var(--accent-ink);font-weight:var(--fw-bold)}
.btn-install:hover{background:rgba(147,37,90,.1)}
.btn-install svg{width:18px;height:18px}
.install-hint{margin-top:14px;font-size:12.5px;color:var(--text-dim);line-height:1.5;text-align:center}
.login-err{color:var(--red);font-size:12.5px;min-height:18px;margin-top:8px}
.user-list{display:flex;flex-direction:column;gap:10px;overflow:auto;max-height:330px;padding-right:6px}
.user-row{
  display:flex;align-items:center;gap:14px;padding:13px 15px;border-radius:var(--radius);
  background:var(--surface-2);border:1px solid var(--border);
  transition:.18s;text-align:left;width:100%;
}
.user-row:hover{border-color:var(--accent-ink);background:var(--surface-3);transform:translateX(3px)}
.avatar{
  width:42px;height:42px;border-radius:var(--radius);display:grid;place-items:center;flex:0 0 auto;
  font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:14px;color:#06121a;letter-spacing:.5px;
}
.user-row .who{flex:1;min-width:0}
.user-row .who .nm{font-weight:var(--fw-semi);font-size:14px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.user-row .who .rl{font-size:12px;color:var(--text-faint);letter-spacing:.1em;text-transform:uppercase;margin-top:2px}
.role-tag{
  font-size:11px;letter-spacing:.14em;text-transform:uppercase;padding:5px 9px;border-radius:var(--radius-sm);font-weight:var(--fw-semi);
}
.role-tag.admin{background:rgba(255,176,46,.14);color:var(--amber);border:1px solid rgba(255,176,46,.3)}
.role-tag.tec{background:rgba(147,37,90,.12);color:var(--accent-ink);border:1px solid rgba(147,37,90,.28)}
.role-tag.coord{background:rgba(255,138,91,.14);color:#ff8a5b;border:1px solid rgba(255,138,91,.3)}

/* ====================== APP SHELL ====================== */
#app{position:relative;z-index:1;height:100%;display:none;flex-direction:column}
.app-header{flex:0 0 auto;background:#191d27;border-bottom:1px solid var(--border)}
.topbar{
  display:flex;align-items:center;flex-wrap:wrap;gap:14px;row-gap:10px;padding:14px 22px 8px;
  flex:0 0 auto;background:transparent;
}
.topbar .brand h1{font-size:17px}
.topbar .brand .glyph{width:34px;height:34px;border-radius:var(--radius)}
.topbar .brand .glyph svg{width:20px;height:20px}
.board-switch{display:flex;align-items:center;gap:8px;color:var(--text-dim);font-size:12.5px}
.divider{width:1px;height:26px;background:var(--border)}
.topbar-spacer{flex:1}
/* Solapas de la ficha del cliente. Al ras del contenido, sin recuadro: son dos vistas de lo mismo,
   no dos lugares distintos. */
.ocl-tabs{display:flex;gap:2px;margin:0 0 14px;border-bottom:1px solid var(--border)}
.ocl-tab{background:none;border:none;border-bottom:2px solid transparent;color:var(--text-dim);
  font:inherit;font-size:13.5px;padding:8px 14px;cursor:pointer;margin-bottom:-1px}
.ocl-tab:hover{color:var(--text)}
.ocl-tab.on{color:var(--text);font-weight:var(--fw-semi);border-bottom-color:var(--signal)}
/* Buscador de pantalla. Va al final de la barra del panel, discreto: es una herramienta, no el
   contenido. Se ensancha al escribir para que entre lo que se esta buscando. */
.pf-wrap{display:flex;align-items:center;gap:8px;margin-left:auto;flex:0 0 auto}
.pf-find{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);color:var(--text);
  font:inherit;font-size:12.5px;padding:6px 10px;width:190px;transition:width .16s ease,border-color .16s}
.pf-find::placeholder{color:var(--text-faint)}
.pf-find:focus{outline:none;border-color:var(--text-faint);width:250px}
.pf-cont{font-size:12px;color:var(--text-faint);font-variant-numeric:tabular-nums;white-space:nowrap}
.pf-cont:empty{display:none}
@media (max-width:900px){ .pf-find{width:130px} .pf-find:focus{width:160px} }
/* Salud del Pi en la barra. Discreto a proposito: gris, letra chica, sin recuadro ni icono. Solo
   se enciende cuando algo cruza un umbral — un indicador que grita siempre deja de leerse. */
.pi-sal{display:flex;align-items:center;gap:10px;font-size:11px;color:var(--text-faint);
  font-variant-numeric:tabular-nums;letter-spacing:.02em;white-space:nowrap;cursor:default;user-select:none}
.pi-sal:empty{display:none}
.pi-sal .pi-p{display:inline-flex;align-items:baseline;gap:3px}
/* El rotulito iba en opacity .62 y daba 3,03 de contraste a 9,5 px — por debajo del minimo de 4,5.
   Un texto decorativo igual hay que poder leerlo. Sube a .88 y a 10 px: sigue siendo mas tenue que
   el numero, que es lo que se buscaba, pero se lee. */
.pi-sal .pi-p i{font-style:normal;opacity:.88;font-size:10px;text-transform:uppercase;letter-spacing:.07em}
.pi-sal.pi-ojo{color:var(--amber)}
.pi-sal.pi-mal{color:var(--red);font-weight:var(--fw-semi)}
/* En el celular la barra ya viene apretada y esto es informacion de fondo: se va. */
@media (max-width:900px){ .pi-sal{display:none} }
.toolbar{display:flex;align-items:center;flex-wrap:wrap;gap:8px;padding:2px 22px 10px;background:transparent;flex:0 0 auto}
/* Mantenimiento + Proyectos de red + ficha de tarea: UNA sola tipografía en todo el texto (Matías) */
#toolbar, #toolbar *, #boardWrap, #boardWrap *, #flowView, #flowView *,
.modal.modal-task, .modal.modal-task *{ font-family:'IBM Plex Sans', sans-serif !important; }
.tb-spacer{flex:1;min-width:8px}
.area-tools{display:flex;align-items:center;gap:8px}
.area-tools:not(:empty){margin-left:auto}
#areaTools .tv-period{padding:3px;border-radius:var(--radius)}
#areaTools .tv-period button{padding:6px 13px;font-size:12.5px;border-radius:var(--radius-sm)}
#areaTools .tv-btn{padding:0 12px;height:34px;font-size:12.5px;border-radius:var(--radius)}
#areaTools .tv-btn-ic{padding:0 10px}
.tb-counts{display:flex;flex-wrap:wrap;align-items:center;gap:6px;padding-left:8px;margin-left:4px;border-left:1px solid var(--border)}
.sc{display:inline-flex;align-items:center;gap:5px;font-size:12px;color:var(--text-dim);background:var(--surface-2);border:1px solid var(--border);padding:5px 9px;border-radius:var(--radius);white-space:nowrap}
.sc-ico{display:inline-flex}
.sc-ico svg{width:13px;height:13px}
.sc b{font-family:'IBM Plex Mono';font-weight:var(--fw-black);color:var(--text);font-size:12.5px}
.sc-lbl{color:var(--text-faint)}
.sc.sc-alert{border-color:rgba(255,91,110,.45);background:rgba(255,91,110,.08)}
.sc.sc-alert b{color:var(--red)}
.sc{cursor:pointer}
.sc:hover{border-color:var(--border-strong)}
.sc.on{border-color:var(--accent-ink);background:rgba(147,37,90,.12)}
.sc.on b{color:var(--text)}
.filt-wrap{position:relative}
.filt-panel{position:absolute;top:calc(100% + 8px);right:0;z-index:70;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:13px;display:none;flex-direction:column;gap:10px;min-width:240px;box-shadow:var(--shadow)}
.filt-panel.open{display:flex}
.filt-row{display:flex;flex-direction:column;gap:5px}
.filt-row > span{font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--text-faint);font-weight:var(--fw-semi)}
.filt-sep{height:1px;background:var(--border);margin:1px 0}
.filt-panel .fl{width:100%}
.filt-badge{display:none;align-items:center;justify-content:center;min-width:17px;height:17px;padding:0 4px;border-radius:var(--radius);background:var(--signal);color:var(--on-signal);font-size:11px;font-weight:var(--fw-black);margin-left:1px}
.fl-btn.on{border-color:var(--accent-ink);color:var(--text)}
.fl-btn{display:inline-flex;align-items:center;gap:6px;background:var(--surface-2);border:1px solid var(--border);color:var(--text);padding:8px 13px;border-radius:var(--radius);font-size:12.5px;font-weight:var(--fw-semi);cursor:pointer;transition:.15s}
.fl-btn:hover{border-color:var(--border-strong);color:var(--text)}
.fl-btn svg{width:15px;height:15px}

.filters{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.fl{
  appearance:none;background:var(--surface-2);border:1px solid var(--border);color:var(--text);
  padding:8px 30px 8px 12px;border-radius:var(--radius);font-size:12.5px;font-weight:var(--fw-medium);cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%2394a0b8' stroke-width='2'%3E%3Cpath d='M3 5l3 3 3-3'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 10px center;transition:.15s;
}
.fl:hover{border-color:var(--border-strong)}
.fl:focus{outline:none;border-color:var(--accent-ink)}
.tb-f{max-width:160px}
.tb-cancel{display:inline-flex;align-items:center;gap:7px;font-size:12.5px;font-weight:var(--fw-medium);color:var(--text-dim);cursor:pointer;white-space:nowrap;flex:0 0 auto}
.tb-cancel input{width:15px;height:15px;accent-color:var(--accent-ink);cursor:pointer;flex:0 0 auto}
/* el buscador es un input, no un select: sin flechita ni padding extra a la derecha */
#searchBox{background-image:none;padding-right:12px}

.btn{
  display:inline-flex;align-items:center;gap:8px;padding:9px 15px;border-radius:var(--radius);font-weight:var(--fw-semi);font-size:12.5px;
  transition:.16s;white-space:nowrap;
}
.btn-primary{background:var(--signal);color:var(--on-signal);box-shadow:none}
.btn-primary:hover{background:var(--signal-dim)}
.btn-ghost{background:var(--surface-2);border:1px solid var(--border);color:var(--text-dim)}
.btn-ghost:hover{border-color:var(--border-strong);color:var(--text)}

/* menú de usuario (avatar) — oculto salvo en móvil admin/coord */
.umscrim{display:none;position:fixed;inset:0;z-index:670;background:transparent}
.umenu{display:none;position:fixed;top:calc(54px + env(safe-area-inset-top));right:10px;z-index:680;
  flex-direction:column;gap:2px;min-width:212px;padding:6px;background:var(--bg-2);
  border:1px solid var(--border);border-radius:var(--radius);box-shadow:0 18px 44px -12px rgba(0,0,0,.7)}
.umenu-item{display:flex;align-items:center;gap:11px;width:100%;padding:12px 13px;border-radius:var(--radius);
  background:none;border:none;color:var(--text);font-size:14px;font-weight:var(--fw-semi);text-align:left;cursor:pointer}
.umenu-item:active,.umenu-item:hover{background:var(--surface-2)}
.umenu-item svg{width:18px;height:18px;color:var(--text-dim);flex:0 0 auto}
.umenu-sep{height:1px;background:var(--border);margin:4px 2px}
.umenu.open{display:flex}
.umscrim.open{display:block}
/* el avatar es el menú de usuario: ocultamos los botones sueltos de la barra */
#bellBtn,#logoutBtn{display:none!important}
#meBox{cursor:pointer}
#meBox::after{content:"";margin-left:1px;border-left:4px solid transparent;border-right:4px solid transparent;border-top:5px solid var(--text-dim);flex:0 0 auto}
.umenu-item .um-state{margin-left:auto;font-size:11px;font-weight:var(--fw-bold);color:var(--text-faint)}
.umenu-item.on .um-state{color:var(--green)}
@keyframes updpulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.55;transform:scale(1.2)}}
@keyframes updglow{0%{box-shadow:0 0 0 0 color-mix(in srgb,var(--accent-ink) 70%,transparent)}70%{box-shadow:0 0 0 9px transparent}100%{box-shadow:0 0 0 0 transparent}}
@keyframes upddot{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(1.55);opacity:.55}}
.icon-btn.has-update{color:var(--accent-ink);border-color:var(--accent-ink);position:relative;animation:updglow 1s ease-out infinite}
.icon-btn.has-update svg{animation:updpulse .8s ease-in-out infinite;transform-origin:center}
.icon-btn.has-update::after{content:"";position:absolute;top:4px;right:4px;width:7px;height:7px;border-radius:var(--radius-circ);background:var(--accent-ink);box-shadow:0 0 0 2px var(--surface-2);animation:upddot .8s ease-in-out infinite}
/* botón flotante desplegable (speed-dial) */
/* Anotador: croquis (canvas) y herramientas */
.an-tools{display:flex;align-items:center;gap:6px;flex-wrap:wrap;margin-bottom:6px}
.an-col{width:22px;height:22px;border-radius:var(--radius-circ);border:2px solid transparent;cursor:pointer;padding:0}
.an-col.on{border-color:var(--text)}
.an-tool{padding:5px 9px;font-size:12px}
.an-tool.on{background:var(--surface-3);color:var(--text);border-color:var(--border-strong)}
#an_canvas{width:100%;border:1px solid var(--border);border-radius:var(--radius);background:#1e232d;touch-action:none;cursor:crosshair;display:block}
.natt-thumb{max-width:130px;max-height:96px;border-radius:var(--radius-sm);border:1px solid var(--border);display:block}
/* Vista simplificada del técnico (finalizar tarea desde el celular) */
.tf-body{display:flex;flex-direction:column;gap:14px}
.tf-blk{background:color-mix(in srgb,var(--red) 12%,transparent);border:1px solid color-mix(in srgb,var(--red) 35%,var(--border));color:var(--text);border-radius:var(--radius);padding:10px 12px;font-size:13.5px}
.tf-card{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:12px 14px;display:flex;flex-direction:column;gap:9px}
.tf-proj{align-self:flex-start;background:var(--pc,#5e6a82);color:#fff;font-weight:var(--fw-black);font-size:12px;letter-spacing:.04em;padding:3px 10px;border-radius:var(--radius-sm);margin-bottom:2px}
.tf-row{display:flex;gap:10px;align-items:baseline;font-size:14px}
.tf-l{flex:0 0 130px;color:var(--text-dim);font-size:12.5px;text-transform:uppercase;letter-spacing:.05em;font-weight:var(--fw-semi)}
.tf-v{flex:1;color:var(--text);font-weight:var(--fw-semi)}
.tf-maps,.tf-plano{display:flex}
.tf-maps .btn-open,.tf-plano .btn-open{flex:1;justify-content:center;padding:14px;font-size:15px;font-weight:var(--fw-bold);border-radius:var(--radius);background:var(--surface-3);border:1px solid var(--border-strong)}
.tf-plano:empty{display:none}
.tf-imgs{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:9px}
.tf-img{display:block;width:90px;height:90px;border-radius:var(--radius);overflow:hidden;border:1px solid var(--border)}
.tf-img img{width:100%;height:100%;object-fit:cover;display:block}
.tf-noimg{color:var(--text-faint);font-size:13.5px;margin-bottom:9px}
.tf-addimg{align-self:flex-start;display:inline-flex;align-items:center;gap:7px;padding:11px 14px;font-size:14px;background:var(--surface-3);border:1px solid var(--border-strong);color:var(--text)}
.tf-addimg svg{width:16px;height:16px}
.tf-sec{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:11px 14px}
.tf-sec-t{font-size:12px;text-transform:uppercase;letter-spacing:.06em;font-weight:var(--fw-bold);color:var(--text-dim);margin-bottom:6px}
.tf-sec-b{font-size:14px;line-height:1.5;color:var(--text);white-space:pre-line}
.tf-sec-b.tf-strong{font-weight:var(--fw-bold)}
.tf-fin-box{background:var(--surface-2);border:1px solid var(--border-strong);border-radius:var(--radius);padding:13px 14px;display:flex;flex-direction:column;gap:10px}
.tf-seg{display:flex;gap:6px}
.tf-seg-b{flex:1;padding:11px 6px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-3);color:var(--text-dim);font-size:12.5px;font-weight:var(--fw-bold);cursor:pointer;text-align:center;line-height:1.2}
.tf-seg-b.on[data-est="completo"]{border-color:var(--green);color:var(--green);background:color-mix(in srgb,var(--green) 12%,var(--surface-3))}
.tf-seg-b.on[data-est="parcial"]{border-color:#c08a34;color:#c08a34;background:color-mix(in srgb,#c08a34 12%,var(--surface-3))}
.tf-seg-b.on[data-est="nopudo"]{border-color:var(--red);color:var(--red);background:color-mix(in srgb,var(--red) 12%,var(--surface-3))}
.tf-finbtn.tf-warn{background:#c08a34;border-color:#c08a34}
.tf-desc{font-size:15px;padding:12px 13px;min-height:80px}
.tf-ubicbtn{align-self:flex-start;display:inline-flex;align-items:center;gap:7px;padding:11px 14px;font-size:14px;background:var(--surface-3);border:1px solid var(--border-strong);color:var(--text)}
.tf-ubicbtn svg{width:16px;height:16px}
.tf-ubicshow{display:flex;align-items:center;gap:10px;flex-wrap:wrap;font-size:13.5px}
.tf-ubic-ok{color:var(--green);font-weight:var(--fw-bold)}
.tf-donemsg{background:color-mix(in srgb,var(--green) 12%,transparent);border:1px solid color-mix(in srgb,var(--green) 35%,var(--border));color:var(--text);border-radius:var(--radius);padding:13px 15px;font-size:14px;font-weight:var(--fw-semi)}
.tf-foot{display:flex;gap:10px}
.tf-finbtn{flex:1;padding:15px;font-size:16px;font-weight:var(--fw-black)}
.tf-foot .btn-ghost{flex:0 0 auto;padding:15px 18px;font-size:15px}
.note.pinned{border-top:2px solid var(--accent-ink)}
.note .note-act[data-pin].on{color:var(--accent-ink)}
/* Anotador: botón flotante de captura rápida (módulo Proyectos de red) */
.anot-fab{border-radius:var(--radius-pill);display:none;position:fixed;right:18px;bottom:calc(18px + env(safe-area-inset-bottom));z-index:580;align-items:center;gap:7px;padding:11px 16px;border:1px solid var(--border-strong);border-radius:var(--radius-sm);background:var(--surface-3);color:var(--text);font-weight:var(--fw-bold);font-size:12.5px;cursor:pointer;box-shadow:0 8px 22px -8px rgba(0,0,0,.55)}
.anot-fab:hover{background:var(--surface-2);border-color:var(--accent-ink)}
.anot-fab svg{width:16px;height:16px}
.anot-fab.show{display:flex}
@media (max-width:720px){ .anot-fab{bottom:calc(92px + env(safe-area-inset-bottom))} }
.fabscrim{display:none;position:fixed;inset:0;z-index:599;background:transparent}
.fabscrim.open{display:block}
.fab-wrap{display:none;position:fixed;right:16px;bottom:calc(18px + env(safe-area-inset-bottom));z-index:600;
  flex-direction:column;align-items:flex-end;gap:13px}
.fab{width:56px;height:56px;border-radius:var(--radius-circ);border:none;cursor:pointer;align-self:flex-end;
  display:flex;align-items:center;justify-content:center;color:var(--on-signal);
  background:var(--signal);
  box-shadow:0 6px 18px -8px rgba(0,0,0,.55)}
.fab:active{transform:scale(.96)}
.fab svg{width:26px;height:26px;transition:transform .2s}
.fab-wrap.open .fab svg{transform:rotate(45deg)}   /* + → × */
.fab-actions{display:flex;flex-direction:column;align-items:flex-end;gap:11px;
  opacity:0;transform:translateY(8px) scale(.96);pointer-events:none;transition:.16s ease}
.fab-wrap.open .fab-actions{opacity:1;transform:none;pointer-events:auto}
.fab-act{display:flex;align-items:center;gap:10px;background:none;border:none;cursor:pointer;padding:0}
.fab-act-lbl{background:var(--bg-2);border:1px solid var(--border);color:var(--text);
  font-size:13.5px;font-weight:var(--fw-semi);padding:7px 11px;border-radius:var(--radius);box-shadow:var(--shadow);white-space:nowrap}
.fab-act-ic{width:46px;height:46px;border-radius:var(--radius-circ);display:flex;align-items:center;justify-content:center;
  background:var(--surface-2);border:1px solid var(--border);color:var(--text);box-shadow:var(--shadow)}
.fab-act-ic svg{width:21px;height:21px}
.btn svg{width:16px;height:16px}

.me{display:flex;align-items:center;gap:10px;cursor:pointer;padding:4px 6px;border-radius:var(--radius);transition:.15s}
.me:hover{background:var(--surface-2)}
.me .avatar{width:34px;height:34px;border-radius:var(--radius);font-size:12.5px}
.me .who .nm{font-size:12.5px;font-weight:var(--fw-semi);line-height:1.1}
.me .who .rl{font-size:11px;color:var(--text-faint);letter-spacing:.1em;text-transform:uppercase}

/* stats strip */
.stats{display:flex;gap:10px;padding:13px 22px 0}
.stat{
  display:flex;align-items:center;gap:11px;padding:11px 15px;border-radius:var(--radius);
  background:var(--surface);border:1px solid var(--border);min-width:140px;
}
.stat .ico{width:34px;height:34px;border-radius:var(--radius);display:grid;place-items:center;flex:0 0 auto}
.stat .num{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:19px;line-height:1}
.stat .lbl{font-size:11px;color:var(--text-faint);letter-spacing:.1em;text-transform:uppercase;margin-top:3px}
.stat.alert .ico{background:rgba(255,91,110,.14);color:var(--red)}
.stat.alert .num{color:var(--red)}

/* ====================== BOARD ====================== */
.board-wrap{position:relative;flex:1;display:flex;min-height:0}
.board{
  flex:1;display:flex;gap:14px;padding:16px 22px 22px;overflow-x:hidden;overflow-y:hidden;align-items:flex-start;
}
.board-wm{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;pointer-events:none;z-index:3;opacity:.045}
.wm-title{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:clamp(26px,4.6vw,64px);letter-spacing:.22em;color:var(--text);white-space:nowrap}
.wm-ver{font-family:'IBM Plex Mono';font-size:clamp(11px,1.1vw,15px);letter-spacing:.18em;color:var(--text)}
.board.panning{cursor:grabbing;user-select:none}
.board.panning .card{cursor:grabbing}
.col{
  flex:1 1 0;min-width:0;display:flex;flex-direction:column;max-height:100%;
  background:var(--surface);
  border:1px solid var(--border);border-radius:var(--radius);
}
.col.drag-over{border-color:var(--accent-ink);box-shadow:0 0 0 1px var(--signal)}
/* Vista en CARRILES por cuadrilla */
.board.lanes{display:block;overflow:auto;padding:0 16px 22px}
.lanes{min-width:780px}
/* ===== LA TARJETA EN LA VISTA CARRILES =====
   Medido el 31/08/2026: se veian 24 tareas de 141. La tarjeta gastaba 38 px en repetir el tipo que
   ya dice el carril y hasta 3 renglones en el titulo. Sacando el chip y cortando el titulo en dos,
   la tarjeta baja de ~113 a ~70 px y entran alrededor de 38 tareas. */
.lane .tipo-chip{display:none}
/* Sin el chip, la fila de arriba queda solo con el ID: no necesita el alto de dos renglones. */
.lane .card-top{min-height:0}
.lane .card-title{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
  margin-bottom:5px}
/* ===== «TARJETAS COMPACTAS» EN CARRILES = MODO PLANILLA =====
   Matias: «quiero ver un paneo general de la mayor cantidad de tareas». MEDIDO: con la tarjeta
   normal se ven 26 de 141, y NO es culpa del alto de la tarjeta — se probo en vivo sacarle el techo
   de 300 px a la celda y las visibles BAJARON a 12, porque el primer carril pasa a medir 6.111 px y
   tapa a los otros dos. Lo unico que sube el numero de verdad es que la tarjeta ocupe menos.
   Con esto la tarjeta pasa de 106 a 68 px y se ven 39. Sin los chips llegaria a 53, pero se
   perderian el ticket y el «avisado», que es justo lo que se mira en el paneo.
   Se engancha en «Tarjetas compactas», que ya existia: es opt-in y no agrega otro control. */
body.board-compact .lane .card{padding:4px 8px 4px 10px}
/* EL NUMERO DE TAREA VUELVE, Y NO CUESTA NADA: va FUERA DEL FLUJO, flotando en la esquina de
   arriba a la derecha. Medidas las tres formas: en su propia linea la tarjeta pasa de 56 a 74 px y
   se pierden 8 tareas de la vista (43 -> 35); flotando, la tarjeta sigue en 56 px y las visibles en
   43. Lo unico que paga es ancho del titulo, que ya venia truncado. */
body.board-compact .lane .card{position:relative}
body.board-compact .lane .card .card-top{display:block;position:absolute;top:3px;right:7px;z-index:1;margin:0}
/* Del encabezado sobrevive SOLO el numero: el chip del tipo lo dice el carril. */
body.board-compact .lane .card .card-top .ct-chips{display:none}
body.board-compact .lane .card .card-id{font-size:10px;opacity:.5}
/* Para que el titulo no se meta debajo del numero. */
body.board-compact .lane .card .card-title{padding-right:52px}
body.board-compact .lane .card .card-title{font-size:12.5px;line-height:1.3;-webkit-line-clamp:1;margin:0 0 2px}
body.board-compact .lane .card .card-icons{gap:4px;margin:0}
body.board-compact .lane .card .card-icons .ic-chip{font-size:10px;padding:0 4px}
body.board-compact .lane .card .card-foot{font-size:11px;margin:0}
body.board-compact .lane-cell{gap:3px}
.lanes-head{display:grid;grid-template-columns:var(--lane-tipo,156px) repeat(var(--lane-cols,5),minmax(0,1fr));gap:8px;position:sticky;top:0;z-index:5;background:var(--bg);padding:9px 0 7px;border-bottom:1px solid var(--border);box-shadow:0 5px 7px -5px rgba(0,0,0,.30)}
.lane-corner{display:flex;align-items:flex-end;padding:0 6px 5px;font-size:11px;font-weight:var(--fw-black);text-transform:uppercase;letter-spacing:.06em;color:var(--text-faint)}
.lane-colh{display:flex;align-items:center;gap:7px;font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:12.5px;text-transform:uppercase;letter-spacing:.02em;padding:6px 6px;border-radius:var(--radius-sm);cursor:grab}
.lane-colh:active{cursor:grabbing}
.lane-colh.col-dragging{opacity:.4}
.lane-colh.colh-over{background:color-mix(in srgb,var(--signal) 18%,transparent);box-shadow:inset 0 0 0 1px var(--signal)}
.lane-grip{color:var(--text-faint);font-size:11px;letter-spacing:-2px;cursor:grab;flex:0 0 auto;opacity:.6}
.lane-name:active{cursor:grabbing}
.lane.lane-dragging{opacity:.45}
.lane-name.lanerow-over{box-shadow:inset 0 0 0 1px var(--signal);background:color-mix(in srgb,var(--signal) 16%,transparent)}
.lane{display:grid;grid-template-columns:var(--lane-tipo,156px) repeat(var(--lane-cols,5),minmax(0,1fr));gap:8px;border-top:1px solid var(--border);padding:8px 0}
/* El envoltorio de las tablas scrollea en TODOS los anchos, no sólo en pantalla grande:
   la regla de arriba vive dentro de un @media(min-width:1000px) y dejaba sin scroll al celular,
   a la tablet y a cualquier ventana angosta. */
.sup-tk-wrap{overflow-x:auto;max-width:100%}
@media(max-width:760px){
}
@media(max-width:680px){
  #board.board{flex-direction:column;overflow-x:hidden;align-items:stretch}
  #board.board>.col{flex:0 0 auto;width:100%;max-width:100%;max-height:none}
  #board.board>.col>.col-body{max-height:none;overflow:visible}
}
@media(max-width:999px){
  #oltWrap,#oltWrap .so-wrap,#oltWrap .so-main,#oltWrap .so-panel,
  #oltWrap .so-panel-body,#oltWrap .so-panel-body>div,#oltWrap .sup-card,
  #oltWrap .so-panel-body>div>div{max-width:100%;min-width:0}
  /* PERO LOS INDICADORES NO. El selector de arriba termina en `>div>div`, que agarra a cualquier
     nieto del cuerpo del panel — y ahí caen las tarjetas de la tira de indicadores. Al anularles el
     ancho mínimo se encogían a 69 px: el número entra, pero la etiqueta se queda con 0 px y
     desaparece. En «Caídas de clientes» eso dejaba cuatro números sueltos —1510, 133, 1116, 164—
     sin nada que dijera qué eran. Medido en un teléfono de 360 px: «Caídas del período» pedía 55 px
     y recibía 0; «Sin alimentación» pedía 92 y recibía 0.
     No le pasaba a todas las pantallas del módulo: depende de a qué profundidad quede la tira, así
     que en «Clientes baja señal» —donde cuelga más adentro— las tarjetas sí medían sus 118 px. Por
     eso pasó desapercibido.
     La tira ya sabe deslizarse de costado (`overflow-x:auto`), así que devolverles el ancho mínimo
     no corta nada: se ven dos tarjetas y media y se llega al resto con el dedo, que es como está
     pensado en el resto del sistema. */
  /* Va por `.tt-kpis > .tt-kpi` y no por `.tt-kpi` a secas POR LA ESPECIFICIDAD: la regla de arriba
     es `#oltWrap .so-panel-body>div>div`, que suma un id, una clase y DOS selectores de tipo, así
     que le gana a `#oltWrap .tt-kpi` —un id y una clase— y el arreglo no aplicaba. Con dos clases
     empata en el id y gana por clases. Comprobado midiendo la tarjeta en un teléfono emulado. */
  #oltWrap .tt-kpis > .tt-kpi{min-width:118px}
}

@media(max-width:760px){
  .board.lanes{padding:0 10px 18px}
  .lanes{min-width:0}
  .lanes-head,.lane{grid-template-columns:116px repeat(var(--lane-cols,5),minmax(150px,72vw));gap:6px}
  .lane-name{padding:6px 6px}
  /* El nombre se queda con la fila entera de su columna; el triángulo y el punto bajan a la línea de
     las chapas. Sin esto le quedaban 52 px de 96 y el corte partía las palabras al medio. */
  .lane-name{flex-wrap:wrap;align-content:flex-start;align-items:flex-start}
  .lane-name .lane-nt{flex:1 0 100%;order:-1}
  .lane-name b{font-size:11px}
  .lane-colh{font-size:12px;padding:5px}
}
.lane-name{display:flex;align-items:center;gap:6px;padding:8px 6px;position:sticky;left:0;background:var(--bg);z-index:2;border-radius:var(--radius);cursor:pointer;user-select:none}
.lane-name:hover{background:var(--surface-2)}
.lane-name b{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:12px;text-transform:uppercase;letter-spacing:.01em;white-space:normal;overflow-wrap:anywhere;line-height:1.15}
.lane-caret{font-size:10px;color:var(--text-faint);flex:0 0 auto;width:10px}
.lane.collapsed{grid-template-columns:1fr;padding:4px 0}
.lane.collapsed .lane-name{position:static;width:100%;flex-wrap:wrap}
.lane-minis{display:flex;gap:6px;flex-wrap:wrap;margin-left:6px}
.lane-mini{font-size:11px;font-family:'IBM Plex Mono';color:var(--text-faint);border:1px solid var(--border);border-left:3px solid var(--cc,var(--border));border-radius:var(--radius-sm);padding:1px 6px}
.lane-dot{width:10px;height:10px;border-radius:var(--radius-circ);flex:0 0 auto}
.lane-nt{display:flex;flex-direction:column;align-items:flex-start;gap:5px;min-width:0}
.lane-meta{display:flex;flex-direction:column;align-items:flex-start;gap:5px}
.lane-count{display:inline-flex;align-items:center;flex:0 0 auto;font-size:11px;font-weight:var(--fw-bold);color:var(--text-faint);background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:1px 9px;letter-spacing:.01em}
.lane-tk{display:inline-flex;align-items:center;gap:4px;flex:0 0 auto;font-size:11px;font-weight:var(--fw-bold);color:#c08a34;background:#c08a341a;border:1px solid #c08a3455;border-radius:var(--radius);padding:1px 8px}
.lane-tk svg{width:12px;height:12px}
.lane-cell{display:flex;flex-direction:column;gap:7px;min-height:46px;max-height:300px;overflow-y:auto;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:7px}
.lane-cell.drag-over{border-color:var(--accent-ink);box-shadow:inset 0 0 0 1px var(--signal)}
.col-head{display:flex;align-items:center;gap:10px;padding:13px 15px 11px}
.col:not(.collapsed) .col-head{border-bottom:1px solid var(--border)}
.col-dot{width:9px;height:9px;border-radius:var(--radius-circ);flex:0 0 auto}
.col-head .ttl{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:13.5px;letter-spacing:.02em;text-transform:uppercase}
.col-count{
  font-family:'IBM Plex Mono';font-size:12px;font-weight:var(--fw-semi);color:var(--text-faint);
  background:var(--surface-2);padding:2px 9px;border-radius:var(--radius);
}
.col-body{
  flex:1;overflow-y:auto;padding:4px 11px 14px;display:flex;flex-direction:column;gap:8px;min-height:60px;
}
.col-collapse{margin-left:auto;width:24px;height:24px;display:flex;align-items:center;justify-content:center;border:none;background:none;border-radius:var(--radius-sm);color:var(--text-faint);cursor:pointer;flex:0 0 auto}
.col-collapse:hover{background:var(--surface-3);color:var(--text)}
.col-collapse svg{width:15px;height:15px;transition:transform .2s}
.col.collapsed{flex:0 0 auto}
.col.collapsed .col-body{display:none}
.col.collapsed .col-head{flex-direction:column;align-items:center;gap:12px;padding:12px 8px;height:100%;cursor:pointer}
.col.collapsed .col-collapse{order:-1;margin-left:0;transform:rotate(180deg)}
.col.collapsed .ttl{writing-mode:vertical-rl;transform:rotate(180deg);white-space:nowrap;flex:0 0 auto}
.col.collapsed .col-count{flex:0 0 auto}
.col-head[draggable="true"]{cursor:grab}
.col-head[draggable="true"]:active{cursor:grabbing}
.col.col-dragging{opacity:.45}
/* ---- Pantalla de PRUEBA: cola de trabajo + ficha, en vez de columnas ---- */
#pruebaWrap,#pruebaView .so-wrap,#pruebaView .so-main,#pruebaView .so-panel,
#pruebaView .so-panel-bar,#pruebaView .so-panel-body,#pruebaView .pb-view{min-width:0;max-width:100%}
.pb-view{padding:14px 16px calc(20px + env(safe-area-inset-bottom));max-width:100%}
.pb-aviso{font-size:11px;color:var(--text-faint);font-style:italic}
.pb-busca{width:170px;height:32px;font-size:12px}
/* Cola a la izquierda, ficha a la derecha: se elige de una lista y se lee al lado, sin perder el
   lugar. Con el tablero hay que abrir una ventana encima y cerrarla para volver. */
.pb-split{display:grid;grid-template-columns:minmax(300px,380px) minmax(0,1fr);gap:14px;align-items:start}
.pb-cola{display:flex;flex-direction:column;gap:6px;max-height:calc(100vh - 330px);overflow:auto;padding-right:2px}
.pb-fila{display:flex;flex-direction:column;gap:3px;text-align:left;width:100%;cursor:pointer;
  background:var(--surface-2);border:1px solid var(--border);border-left:3px solid var(--border);
  border-radius:var(--radius);padding:9px 11px;color:inherit;font:inherit}
.pb-fila:hover{background:var(--surface-3)}
.pb-fila.on{border-color:var(--link);border-left-color:var(--link);background:var(--surface-3)}
/* Lo vencido se ve de lejos: es lo unico que de verdad ordena la urgencia. */
.pb-fila.venc{border-left-color:var(--red)}
.pb-f1{display:flex;align-items:center;gap:7px;flex-wrap:wrap}
.pb-tipo{font-size:10px;font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:.04em;
  color:var(--cc,var(--text-dim));border:1px solid color-mix(in srgb,var(--cc,var(--border)) 55%,transparent);
  background:color-mix(in srgb,var(--cc,var(--border)) 14%,transparent);border-radius:var(--radius-sm);padding:1px 6px}
.pb-id{font-size:11px;color:var(--text-faint)}
.pb-venc{font-size:10px;font-weight:var(--fw-bold);color:var(--red);background:color-mix(in srgb,var(--red) 15%,transparent);
  border-radius:var(--radius);padding:0 7px}
.pb-fecha{font-size:11px;color:var(--text-faint);margin-left:auto}
.pb-tit{font-size:12.5px;font-weight:var(--fw-semi);line-height:1.3;overflow-wrap:anywhere}
.pb-sub,.pb-tk{font-size:11px;color:var(--text-faint);overflow-wrap:anywhere}
/* La ficha al lado, no encima. */
.pb-detalle{position:sticky;top:0;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);
  padding:16px 18px;min-height:220px}
.pb-fhead{display:flex;align-items:center;gap:9px;flex-wrap:wrap;margin-bottom:8px}
.pb-estado{font-size:11px;font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:.04em;color:var(--text-dim);
  border:1px solid var(--border);border-radius:var(--radius);padding:1px 9px}
.pb-ftit{margin:0 0 14px;font-family:'IBM Plex Sans';font-size:18px;font-weight:var(--fw-bold);line-height:1.25;overflow-wrap:anywhere}
/* Una sola accion grande: es a lo que se viene. El resto queda de costado. */
.pb-acciones{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:14px}
.pb-avanzar{min-width:150px}
.pb-desc{font-size:12.5px;line-height:1.5;color:var(--text-dim);white-space:pre-wrap;
  background:var(--surface-3);border-radius:var(--radius);padding:10px 12px;margin-bottom:14px;overflow-wrap:anywhere}
.pb-datos{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px 18px;margin-bottom:16px}
.pb-dato{display:flex;flex-direction:column;gap:2px;min-width:0}
.pb-dato span{font-size:10px;text-transform:uppercase;letter-spacing:.05em;color:var(--text-faint);font-weight:var(--fw-bold)}
.pb-dato b{font-size:12.5px;font-weight:var(--fw-semi);overflow-wrap:anywhere}
.pb-dato i{color:var(--text-faint);font-weight:var(--fw-normal)}
.pb-seccion{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--text-faint);
  font-weight:var(--fw-bold);border-top:1px solid var(--border);padding-top:11px;margin-bottom:8px}
.pb-log{font-size:12px;color:var(--text-dim);padding:4px 0;line-height:1.45}
.pb-log b{color:var(--text);font-weight:var(--fw-semi)}
.pb-log i{color:var(--text-faint);font-size:11px;font-style:normal;margin-left:6px}
.pb-log.vacio{color:var(--text-faint);font-style:italic}
.pb-vacio{color:var(--text-faint);font-size:12.5px;padding:26px 10px;text-align:center;
  border:1.5px dashed var(--border);border-radius:var(--radius)}
/* --- Diseño 2: la planilla --- */
/* Los filtros arriba de la tabla, en una fila que se parte sola si no entran. */
/* Todo en una fila: botones y desplegables juntos, para no apilar franjas antes de la tabla. */
.pb-controles{align-items:center;gap:10px;margin:0 0 10px}
.pb-fil{width:auto;min-width:96px;max-width:150px;font-size:12px;
  padding:6px 24px 6px 9px;background-position:right 8px center}
/* El que esta puesto se distingue del que no: si no, hay que abrirlos para saber cual filtra. */
.pb-fil.on{border-color:var(--link);color:var(--text)}
.pb-controles .sup-tk-card{margin:0}
.pb-limpiar{height:29px}
/* El de vencidos se ve distinto: es el unico que marca un problema. */
.sup-seg-b.peligro{color:var(--red)}
.sup-seg-b.peligro.on{color:#fff}
.pb-tabla td{vertical-align:top}
.pb-c-id a{color:var(--link);text-decoration:none;font-weight:var(--fw-semi)}
.pb-c-id a:hover{text-decoration:underline}
.pb-c-edo{white-space:nowrap}
.pb-esp{display:block;margin-top:3px;font-size:10px;font-weight:var(--fw-bold);text-transform:uppercase;
  letter-spacing:.04em;color:var(--amber)}
.pb-c-tit{min-width:210px;max-width:340px}
.pb-c-tit small{display:block;color:var(--text-faint);font-size:11px;line-height:1.35;margin-top:2px;overflow-wrap:anywhere}
.pb-c-tk a{color:var(--link);text-decoration:none;font-family:'IBM Plex Mono';font-size:12px}
.pb-c-fecha,.pb-c-edad,.pb-c-acc{white-space:nowrap}
.pb-venc-txt{color:var(--red)}
.pb-falta{color:var(--text-faint)}
/* La fila vencida se marca de canto, igual que en la cola: mismo codigo visual en los dos diseños. */
.pb-tabla tbody tr.pb-r-venc td{box-shadow:inset 3px 0 0 -1px var(--red)}
.pb-mini{padding:2px 9px;font-size:12px}
/* En pantalla angosta la ficha va debajo de la cola, no al lado. */
@media(max-width:900px){
  .pb-split{grid-template-columns:minmax(0,1fr)}
  .pb-cola{max-height:none}
  .pb-detalle{position:static}
  .pb-view{padding:10px 10px 18px}
}
/* ---- Vista «Tickets»: los frenados en Re coordinar cruzados contra las tareas ---- */
/* La cadena tiene que poder achicarse: sin esto el ancho minimo de las tablas la estira y el
   `overflow:hidden` del panel se come la ultima columna. Ver el comentario del parche p36. */
#recoordWrap,#recoordView .so-wrap,#recoordView .so-main,#recoordView .so-panel,
#recoordView .so-panel-bar,#recoordView .so-panel-body,#recoordView .rc-view,
#recoordView .sup-card,#recoordView .sup-tk-wrap{min-width:0;max-width:100%}
/* ===== «LA RED AHORA»: la pantalla de vistazo, pensada para el teléfono =====
   Renglones altos y de una sola columna. Nada se desliza de costado: en un teléfono, una tabla de
   doce columnas es la forma más rápida de que la pantalla no se use. Los tamaños están puestos para
   leerse de un vistazo y tocarse con el pulgar, no para meter la mayor cantidad de datos. */
/* Las cajas de la ficha del diagnóstico, separadas entre sí y sin el margen suelto que traen por
   omisión: acá el espacio lo pone el contenedor, que es como se arma en el resto del sistema. */
.dg-fichas{display:flex;flex-direction:column;gap:12px}
/* La tabla del resumen por áreas: pocas filas, para leer de un vistazo. */
.dg-areas td{vertical-align:middle;padding:9px 10px}
.dg-ar-n{font-weight:var(--fw-semi);white-space:nowrap}
.dg-ar-d{color:var(--text-dim);font-size:12px}
/* La barrita del costado dice el estado del área sin depender de leer la palabra. */
.dg-areas tbody tr.dg-ar-mal  > td:first-child{box-shadow:inset 3px 0 0 var(--red)}
.dg-areas tbody tr.dg-ar-ojo  > td:first-child{box-shadow:inset 3px 0 0 var(--amber)}
.dg-areas tbody tr.dg-ar-bien > td:first-child{box-shadow:inset 3px 0 0 var(--green)}
.dg-areas tbody tr.dg-ar-sindato > td:first-child{box-shadow:inset 3px 0 0 var(--text-faint)}
/* La chapita de estado en el título de cada bloque, corrida a la derecha. */
.dg-ar-chapa{margin-left:auto;flex:0 0 auto}
@media(max-width:760px){
  /* En el teléfono la pregunta del área sobra: ocupa dos renglones y el título ya la contesta. */
  .dg-caja .sup-tk-head h4 small{display:none}
  .dg-ar-n{white-space:normal}
  /* Y tres columnas no entran: la del diagnóstico —justo la que importa— quedaba cortada contra el
     borde derecho, y para leerla había que arrastrar la tabla de costado. Cada fila pasa a ser un
     bloque: el área y su estado arriba, el porqué abajo con todo el ancho. */
  .dg-areas thead{display:none}
  .dg-areas tbody tr{display:flex;flex-wrap:wrap;align-items:center;gap:4px 9px;padding:9px 11px}
  .dg-areas tbody tr + tr{border-top:1px solid var(--border)}
  /* Sin bordes por casillero: el renglón de abajo es el mismo dato, no una fila nueva, y la línea
     lo partía al medio. La separación entre áreas la pone el borde de la fila. */
  .sup-tk.tk-grid.dg-areas td{display:block;padding:0;border:none;background:none}
  .dg-areas td.dg-ar-d{flex:1 0 100%}
  /* La barrita de estado se muda del primer casillero al borde de la fila entera. El selector lleva
     el estado adentro a propósito: el que la pinta también lo lleva y, si no, le gana y quedan dos. */
  .dg-areas tbody tr.dg-ar-mal > td:first-child,
  .dg-areas tbody tr.dg-ar-ojo > td:first-child,
  .dg-areas tbody tr.dg-ar-bien > td:first-child,
  .dg-areas tbody tr.dg-ar-sindato > td:first-child{box-shadow:none}
  .dg-areas tbody tr{border-left:3px solid var(--text-faint)}
  .dg-areas tbody tr.dg-ar-mal{border-left-color:var(--red)}
  .dg-areas tbody tr.dg-ar-ojo{border-left-color:var(--amber)}
  .dg-areas tbody tr.dg-ar-bien{border-left-color:var(--green)}
  /* El rayado va en la fila, no en el casillero: los casilleros ahora son bloques que se achican al
     texto, y el gris quedaba como un recuadro suelto a media línea. */
  .sup-tk.tk-grid.dg-areas tbody tr:nth-child(even) td,
  .sup-tk.tk-grid.dg-areas tbody tr:hover td{background:none}
  .dg-areas tbody tr:nth-child(even){background:var(--zebra)}
}
.dg-fichas .dg-caja{margin-top:0}
/* La cabecera del cliente y el veredicto ya no necesitan su margen de arriba: están adentro de la
   caja, debajo de su título. */
.dg-caja .dg-cab{margin-top:0}
.dg-caja .dg-ver{margin-bottom:0}

.vz-cuerpo{display:flex;flex-direction:column;gap:12px}
.vz-cuerpo .vz-caja{margin-top:0}
/* ===== LA MISMA PANTALLA EN LA COMPUTADORA =====
   Es la MISMA pantalla, no una versión de escritorio aparte: los mismos datos, las mismas cajas y el
   mismo código. Lo único que cambia es cómo se acomodan. En el teléfono van una abajo de la otra,
   que es como se diseñó; de 1.000 px para arriba se reparten en columnas, porque una sola columna
   flaca en el medio de una pantalla ancha es una captura de celular estirada y se lee peor que en el
   propio celular.
   `minmax(420px,1fr)`: más angosto que eso, los renglones de «Equipos principales» —nombre del
   equipo y su estado— empiezan a partirse en dos líneas. Da dos columnas en una pantalla normal y
   tres en una grande, sin fijar el número a mano. */
@media(min-width:1000px){
  /* `width:100%` y `min-width:0` no son de adorno: el cuerpo cuelga de un contenedor flex y, como
     item de flex, toma el ancho de su CONTENIDO y no el del padre. Medido: el padre daba 1.216 px y
     la grilla se quedaba en 886 —dos columnas de 420 pegadas a la izquierda con un tercio de
     pantalla vacío al lado— porque las columnas en `1fr` no tenían de qué repartirse. Es la misma
     cadena flex que ya obligó a poner esto en otros cinco lugares del sistema. */
  /* ===== ÍNDICE A LA IZQUIERDA, DETALLE A LA DERECHA =====
     La grilla de tarjetas que había antes quedaba vacía: una de tres renglones al lado de una de
     quince deja media pantalla en blanco. Acá no hay huecos posibles porque no hay que encajar
     tarjetas de distinto alto: el índice es una columna fija de 232 px y el detalle usa todo lo que
     queda, sea lo que sea que tenga adentro. */
  .vz-cuerpo{display:flex;flex-direction:column;gap:14px;width:100%;min-width:0;max-width:100%}
  /* ===== LAS COLUMNAS LAS REPARTIMOS NOSOTROS =====
     Se probó con `columns` del CSS y no alcanza. En el monitor de 1.920 de Matías armaba cuatro
     columnas de 446 px y metía las cuatro tarjetas en las dos primeras, dejando un tercio de la
     pantalla en blanco a la derecha. Fijándole la cantidad en tres, tampoco: usaba dos y dejaba la
     tercera vacía. El repartidor del navegador no garantiza usar todas las columnas cuando los
     bloques son altos y no se pueden partir, que es exactamente nuestro caso, y no hay forma de
     obligarlo desde el CSS.
     Así que las columnas son cajas de verdad y el reparto lo hace `vzColumnas()` midiendo el alto
     de cada tarjeta. Es la única manera de garantizar que ninguna quede vacía. */
  /* `stretch` y no `start`: con `start` cada columna medía lo que medía su contenido, así que la
     línea que la separa de la de al lado se cortaba a media altura y el bloque quedaba abierto
     abajo. Estirándolas, todas llegan al piso y la celda cierra. */
  .vz-cols{display:grid;grid-template-columns:repeat(var(--vz-n,2),minmax(0,1fr));
    gap:14px;align-items:stretch}
  .vz-col{display:flex;flex-direction:column;gap:14px;min-width:0}
  .vz-col > .vz-caja{margin:0}
  /* ===== LAS BALDOSAS DE EQUIPOS =====
     Una por categoría, el número grande y el rótulo abajo. Es el bloque que contesta «¿está entera
     la infraestructura?» sin leer nada, y por eso el número va primero y en grande — igual que en
     la fila de KPI del resto del sistema, que es de donde sale el tamaño. */
  /* Cinco columnas fijas, no auto-fit: con auto-fit la quinta baldosa —«Núcleo y switches»— se caía
     sola a un segundo renglón porque el rótulo «SUPERROUTERS» es más ancho que el mínimo y empujaba.
     Son siempre cinco categorías; el ancho lo reparten entre las cinco y los rótulos envuelven. */
  .vz-tiles{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:8px;padding:0 14px 12px}
  .vz-tile{display:flex;flex-direction:column;gap:2px;align-items:flex-start;cursor:pointer;
    padding:9px 12px;border-radius:var(--radius-lg);border:1px solid var(--border);background:var(--surface-2);
    text-align:left;transition:.12s}
  .vz-tile:hover{border-color:var(--border-strong)}
  .vz-tile.on{background:var(--surface);border-color:var(--border-strong)}
  /* 15 y no 21: veintiuno es la medida de un contador que ENCABEZA una pantalla, y estos cinco están
     dentro de una tarjeta, compitiendo con el título de la tarjeta que los contiene. */
  .vz-tile-n{font-family:'IBM Plex Sans';font-weight:var(--fw-semi);font-size:14px;line-height:1.15;
    font-variant-numeric:tabular-nums}
  .vz-tile-n i{font-style:normal;font-weight:var(--fw-normal);font-size:12px;color:var(--text-faint)}
  /* Sin mayúsculas forzadas: eran las que hacían que los rótulos se cortaran —«SUPERROUTER» sin la
     S, «NODOS INALÁMBRICO» sin la S—, porque en versales el mismo texto es bastante más ancho. */
  .vz-tile-r{font-size:11.5px;text-transform:none;letter-spacing:0;font-weight:var(--fw-normal);
    color:var(--text-dim);line-height:1.25}
  .vz-tile-bien .vz-tile-n{color:var(--green)}
  .vz-tile-mal .vz-tile-n{color:var(--red)}
  .vz-tile-mal{border-left:3px solid var(--red)}
  /* Ámbar: todos contestan ahora, pero alguno falló hace poco. Es el estado que la foto no muestra. */
  .vz-tile-ojo .vz-tile-n{color:var(--amber)}
  .vz-tile-ojo{border-left:3px solid var(--amber)}
  .vz-tile-p{display:block;font-style:normal;text-transform:none;letter-spacing:0;font-weight:var(--fw-semi);
    color:var(--amber);margin-top:1px}
  .vz-eq-ojo{border-left-color:var(--amber);background:color-mix(in srgb,var(--amber) 8%,transparent)}
  .vz-eq-ojo b{color:var(--amber)}
  /* Lo que no responde va debajo de las baldosas, siempre, con el motivo al lado. */
  .vz-caidos{padding:0 14px 6px}
  .vz-verif{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:8px 0 2px}
  .vz-verif span{font-size:11.5px;color:var(--text-faint);flex:1 1 220px;min-width:0}
  .vz-fila.vz-f-ok{border-left:3px solid var(--green)}
  .vz-todook{padding:0 14px 14px;font-size:12px;color:var(--green)}
  /* Rótulo de sub-lista adentro de una tarjeta: dice de qué es la lista que sigue. Usa el mismo
     `hoy-sec-h` del resto del sistema, más chico porque acá va adentro de una caja y no encabezando
     una pantalla. */
  /* Sin versales: era uno de los dos únicos elementos en mayúsculas forzadas que quedaban en la
     pantalla, y las cabeceras de las tablas del sistema ya las perdieron. */
  .vz-sub{margin:2px 14px 4px;font-size:11.5px;text-transform:none;letter-spacing:0;
    font-weight:var(--fw-bold);color:var(--text-faint)}
  /* LAS TABLAS DE ACÁ TIENEN QUE VERSE COMO LAS DEL RESTO. `.sup-tk td` no fija color y lo hereda,
     y la cadena de esta pantalla le llegaba con `--text` mientras en «IP pública compartida» o en
     «Clientes baja señal» llega con `--text-dim`: medido, rgb(236,238,241) contra rgb(178,185,196).
     En el texto en negrita no se nota, pero el texto común —la OLT, la IP, los destinos— salía más
     brillante que en cualquier otra tabla del sistema. Se fija al valor de la casa en vez de seguir
     buscando quién lo hereda. */
  .vz-caja .sup-tk td{color:var(--text-dim)}

  /* El rótulo de sub-lista, dentro de esta pantalla, sin versales y a la medida de los demás. */
  .vz-pc .hoy-sec-h{font-size:11.5px;text-transform:none;letter-spacing:0;font-weight:var(--fw-semi);
    background:transparent;border-bottom:1px solid var(--border);padding:6px 10px}

  /* LA ACLARACIÓN DE CADA CONTADOR SE QUEDA. La regla del sistema la esconde a partir de cinco
     contadores para que entren; acá entran, porque el contador ya no lleva caja ni ancho mínimo, y
     sin ella los rótulos dicen la mitad: «Cortes en curso» sin «ninguno ahora». */
  .vz-pc > .vz-kpis .tt-kpis:has(.tt-kpi:nth-child(5)) .k-sub{display:inline}

  /* Los dos párrafos que explican qué se está midiendo: el texto hace falta, el tamaño no. Pasan a
     la medida de una aclaración en vez de competir con los datos de al lado. */
  .vz-pc .vz-todook,.vz-pc .vz-verif span,.vz-pc .vz-caidos p,.vz-pc .vz-caidos > div > span{font-size:11.5px;color:var(--text-faint)}

  /* ===== EL DIBUJO DE LA MAQUETA CLÁSICA =====
     Columnas separadas por una línea, no tarjetas flotando. Todo acotado a `.vz-pc`: en el teléfono
     las tarjetas siguen siendo tarjetas, que es lo que corresponde cuando van una abajo de la otra. */
  /* EL ENCUADRE. Las tres columnas son un solo bloque con borde, y entre una y otra va una línea.
     No se puede usar `column-rule` porque el reparto lo hace vzColumnas() en JavaScript y no
     `columns` del CSS: las columnas son cajas de verdad, así que la línea es su borde. */
  /* ===== EL MOSAICO: nueve celdas parejas =====
     `auto-fit` con un mínimo de 190 px: en una pantalla ancha entran las nueve en dos filas y en una
     angosta se reacomodan solas. La grilla lleva el borde y las celdas la línea, como el resto. */
  /* ===== LA TABLA DE ESTADO =====
     Es la tabla común del sistema, así que acá sólo van los anchos, la fila abierta y el detalle.
     `table-layout:fixed` para que las columnas no se muevan al abrir una fila: sin eso, el detalle
     desplegado —que es ancho— reacomoda las cinco columnas de arriba y la tabla salta. */
  .vz-tabla{table-layout:fixed}
  .vz-tabla .vz-th-e{width:30px} .vz-tabla .vz-th-a{width:150px}
  .vz-tabla .vz-th-v{width:86px} .vz-tabla .vz-th-d{width:110px}
  /* EL CUADRADITO: su regla vive acotada a la tabla de Capacidad, asi que aca hay que darle forma.
     Es el mismo dibujo —8 px, cuadrado, sin radio— para que sea el mismo lenguaje. */
  .vz-tabla .vz-td-e{text-align:center;padding-left:0;padding-right:0}
  .vz-tabla .cuad{display:inline-block;width:8px;height:8px;background:var(--text-faint)}
  .vz-tabla .cuad.ok{background:var(--green)}
  .vz-tabla .cuad.warn{background:var(--amber)}
  .vz-tabla .cuad.err{background:var(--red)}
  .vz-tabla .vz-td-a{font-weight:var(--fw-medium)}
  .vz-tabla .vz-td-v{font-family:'IBM Plex Mono',ui-monospace,monospace;font-weight:var(--fw-semi)}
  .vz-tabla .vz-td-v i{font-style:normal;font-weight:var(--fw-normal);color:var(--text-faint)}
  .vz-tabla .vz-td-s,.vz-tabla .vz-td-d{color:var(--text-dim)}
  .vz-tabla .vz-td-d{font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:12px}
  /* El color va en el valor, que es lo que se mira. El nombre del área se queda neutro: pintarlo
     también haría que la fila entera grite. */
  .vz-tabla .vz-fi-mal .vz-td-v{color:var(--red)}
  .vz-tabla .vz-fi-ojo .vz-td-v{color:var(--amber)}
  .vz-tabla .vz-fi-bien .vz-td-v{color:var(--green)}
  .vz-tabla tbody tr.vz-fi{cursor:pointer}
  .vz-tabla tbody tr.vz-fi.on td{background:var(--surface-2)}
  /* El detalle ocupa la fila entera y sin relleno de celda: adentro va una tarjeta que ya trae el
     suyo. */
  .vz-tabla tbody tr.vz-fi-det > td{padding:0;background:var(--bg)}
  .vz-tabla tbody tr.vz-fi-det .vz-caja{background:transparent;border:0;border-radius:0;margin:0}
  .vz-tabla tbody tr.vz-fi-det .sup-tk-head{background:var(--surface-3);padding:5px 12px;margin:0;
    border-bottom:1px solid var(--border-strong)}
  /* Cuando el área no tiene nada que mostrar —cero cortes, cero cajas— la fila igual contesta algo:
     una que al tocarla no hace nada parece rota. */
  /* ===== LA GRILLA DE ESTADO DE LAS OLT =====
     Celdas chiquitas y parejas, tantas por renglón como entren. El color ES el dato: por eso el
     relleno tiene peso —no es un adorno detrás del texto— pero se queda en un tercio para que el
     nombre siga siendo lo primero que se lee. */
  /* La baldosa fija no se toca: sin cursor de mano y sin el realce de las que sí se abren. Se ve
     igual que las otras porque dice lo mismo —cuántos de cuántos— pero no promete un clic. */
  .vz-tile-fija{cursor:default}
  .vz-tile-fija:hover{background:inherit}
  .vz-ogrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(66px,1fr));gap:2px;
    padding:8px 12px}
  /* El nombre se corta con puntos suspensivos: los Mikrotik no tienen separador y algunos miden
     treinta caracteres. El entero está en el globito y en el detalle. */
  .vz-og{padding:3px 4px;border:1px solid var(--border);border-radius:var(--radius-sm);
    font:inherit;font-size:11px;font-weight:var(--fw-semi);line-height:1.25;color:var(--text);
    background:var(--surface-2);cursor:pointer;text-align:center;min-width:0;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  /* AL 55%. Medido componiendo el píxel de verdad: al 26% el relleno daba 1,65:1 contra el fondo en
     oscuro y 1,46 en claro — o sea que el color no decía nada. Al 55% da alrededor de 2,7 y 2,4, que
     es donde el estado se ve sin mirar dos veces. AJUSTADO DESPUES A 46%: al 55 el NOMBRE encima
     caia a 4,30:1, por debajo del minimo legible, y un color de estado que tapa el nombre del equipo
     no sirve. A 46 las dos cosas dan.
     LOS TRES SUBEN IGUAL: si sube uno solo dejan de compararse entre sí, que es para lo que están. */
  .vz-og-bien{background:color-mix(in srgb,var(--green) 46%,transparent);
    border-color:color-mix(in srgb,var(--green) 70%,var(--border))}
  .vz-og-ojo{background:color-mix(in srgb,var(--amber) 46%,transparent);
    border-color:color-mix(in srgb,var(--amber) 70%,var(--border))}
  .vz-og-mal{background:color-mix(in srgb,var(--red) 46%,transparent);
    border-color:color-mix(in srgb,var(--red) 70%,var(--border))}
  .vz-og:hover{border-color:var(--text-faint)}
  /* La abierta se marca con el borde de acento, no cambiándole el color: el color dice el estado y
     no puede querer decir dos cosas. */
  .vz-og.on{box-shadow:inset 0 0 0 2px var(--accent-ink)}
  /* El detalle de la que se tocó, debajo de la grilla y a todo el ancho. */
  .vz-odet{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 10px;
    padding:8px 12px;border-top:1px solid var(--border);font-size:12.5px}
  .vz-odet b{font-weight:var(--fw-semi)}
  .vz-odet span{color:var(--text-dim)}
  .vz-nada{padding:10px 12px;font-size:12.5px;color:var(--text-faint)}
  /* La IP en monoespaciada, como cada numero del sistema que se compara de arriba a abajo: en una
     lista de diecisiete direcciones, alineadas se leen y en proporcional no. */
  .vz-ip{font-style:normal;font-family:'IBM Plex Mono',monospace;color:var(--text-dim)}
  /* El cuerpo del detalle de equipos, con el mismo margen que el de las otras secciones. */
  .vz-tabla tbody tr.vz-fi-det .vz-det-eq{padding:10px 12px}
  .vz-tabla tbody tr.vz-fi-det .vz-caja{background:transparent;border:0;border-radius:0;padding:0;margin:0}
  /* La fila de las tres caídas: tres columnas fijas —son tres, no «las que entren»— y separada de lo
     de abajo por el mismo ritmo de 12 px que usa el resto del sistema entre tarjetas. */
  /* ===== LOS TRES BLOQUES, PEGADOS =====
     Medido: 14 px entre la fila de contadores y ésta, y 26 más hasta la de abajo. No eran márgenes
     —los tres tenían 0— sino el `gap:14px` del cuerpo, que es un flex en columna. En el estilo
     clásico lo que separa un bloque de otro es la LÍNEA, no el aire.
     Cada bloque se apoya en el siguiente y la línea que los divide es una sola: la de arriba del de
     abajo. Por eso éste va sin borde arriba ni abajo. */
  /* ===== EXCEPCIÓN, Y SÓLO PARA ESTA PANTALLA =====
     Pedida. En el resto del sistema lo que separa un bloque de otro es la LÍNEA, no el aire; acá son
     siete cajas de contenido muy distinto —una lista de nombres, una grilla de estado, una tabla de
     temperaturas— y pegadas se leen como una sola.
     Ocho píxeles, no catorce: «un poquito». */
  /* OCHO A CADA LADO, los mismos que separan una tarjeta de la otra. El cuerpo de las pantallas no
     lleva relleno horizontal —por eso las tablas corren hasta el borde—, pero desde que estas
     tarjetas tienen borde propio, la de los extremos tocaba el vidrio mientras las del medio
     respiraban: asimétrico, y se leía como si estuviera cortada.
     VA CON TRES CLASES A PROPÓSITO. Con dos —`.vz-pc.vz-cuerpo`— empata con `.so-panel-body.so-pad`,
     que pone el relleno de TODAS las pantallas y está mil seiscientas líneas más abajo: a igual
     especificidad gana la última y esto no llegaba nunca. Se sube con una clase que el elemento ya
     tiene, que es preferible a un `!important` que después nadie sabe por qué está. */
  .vz-pc.vz-cuerpo{gap:8px}
  .so-pad.vz-cuerpo.vz-pc{padding-left:8px;padding-right:8px;padding-top:8px}
  /* FILA FIJA: la que NO reparte el sistema por altura. Se llamaba `vz-tres` y quedó mintiendo el
     día que la fila de arriba pasó a tener cuatro bloques; el número de columnas lo pone quien la
     arma, con `--vz-n`. */
  .vz-pc .vz-fija{grid-template-columns:repeat(var(--vz-n,3),minmax(0,1fr));margin:0;border:0}
  .vz-pc .vz-cols:not(.vz-fija){margin:0;border:0}
  /* Cuatro bloques abajo de 1.300 px son cuatro recortes; uno solo arriba de 950 es una tira. */
  @media(max-width:1300px){ .vz-pc .vz-fija{grid-template-columns:repeat(2,minmax(0,1fr))} }
  @media(max-width:950px){ .vz-pc .vz-fija{grid-template-columns:1fr} }
  .vz-tabla-w{overflow-x:auto}

  /* CINCO COLUMNAS, no `auto-fit`. Con auto-fit el navegador mete todas las que entran —ocho en
     1.500 px— y la novena cae sola en un renglón. Cinco reparte 5 + 4. */
  .vz-mos{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));
    border:1px solid var(--border);border-bottom:0;background:var(--surface)}
  @media(max-width:1100px){ .vz-mos{grid-template-columns:repeat(3,minmax(0,1fr))} }
  .vz-cel{display:flex;flex-direction:column;align-items:flex-start;gap:2px;text-align:left;
    padding:9px 12px 10px;border:0;border-bottom:1px solid var(--border);border-left:1px solid var(--border);
    background:transparent;cursor:pointer;min-width:0;width:100%}
  .vz-cel:hover{background:var(--surface-2)}
  .vz-cel.on{background:var(--surface-2);box-shadow:inset 0 -2px 0 var(--accent-ink)}
  .vz-cel-r{font-size:11.5px;color:var(--text-dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
  .vz-cel-n{font-family:'IBM Plex Sans';font-weight:var(--fw-semi);font-size:19px;line-height:1.15;
    font-variant-numeric:tabular-nums}
  .vz-cel-n i{font-style:normal;font-weight:var(--fw-normal);font-size:12px;color:var(--text-faint)}
  .vz-cel-s{font-size:11px;color:var(--text-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
  /* El color va en el número, que es lo que se mira; el rótulo se queda neutro. */
  .vz-cel-bien .vz-cel-n{color:var(--green)}
  .vz-cel-ojo .vz-cel-n{color:var(--amber)}
  .vz-cel-mal .vz-cel-n{color:var(--red)}
  /* El detalle de la celda abierta va debajo, a todo el ancho, sin tarjeta propia. */
  .vz-mosaico > .vz-caja{background:transparent;border:0;border-radius:0;padding:0;margin:0}
  .vz-mosaico > .vz-caja > .sup-tk-head{background:var(--surface-3);border-bottom:1px solid var(--border-strong);
    border-top:1px solid var(--border);padding:5px 12px;margin:0}
  /* EL MARCO PASA DE LA GRILLA A CADA CAJA. Con las cajas separadas y el marco afuera, las líneas
     internas quedaban flotando en el aire sin nada que cerrar. Ahora cada caja se cierra sola. */
  /* ===== LOS DOS GRUPOS DE LA PANTALLA =====
     Arriba lo que hay que ATENDER —lo que está roto ahora— y abajo lo que se MONITOREA. El rótulo
     no es decoración: sin él, los tres bloques de abajo se leen como tres problemas más. */
  .vz-pc .vz-grupo{font-family:'IBM Plex Sans';font-size:11px;font-weight:var(--fw-bold);
    letter-spacing:.14em;text-transform:uppercase;color:var(--text-dim);margin:0;padding:6px 2px 0}
  /* EL PRIMERO NO ES LA EXCEPCION. Tenia `padding-top:0` para que no se despegara de mas, y sumado
     a que el cuerpo tampoco lleva relleno arriba quedaba a 4 px de la barra del titulo, al borde de
     tocarla. Los dos rotulos llevan el mismo aire: es lo que hace que se lean como dos rotulos del
     mismo tipo y no como dos cosas distintas. */
  /* EL PULSO PASA DE LA FILA DE NÚMEROS A LA TARJETA, porque la fila se fue. Era el aviso de que hay
     un corte en curso, que es lo primero que se quiere ver de toda la pantalla. Se mezcla con
     `--surface` y no con transparente: ahora late algo que tiene fondo propio. */
  @keyframes vz-late-caja{ 0%,100%{ background:color-mix(in srgb,var(--red) 7%,var(--surface)) }
                           50%{ background:color-mix(in srgb,var(--red) 22%,var(--surface)) } }
  .vz-pc .vz-col.vz-hay-corte > .vz-caja{animation:vz-late-caja 2s ease-in-out infinite;
    border-color:color-mix(in srgb,var(--red) 45%,var(--border))}
  @media(prefers-reduced-motion:reduce){
    .vz-pc .vz-col.vz-hay-corte > .vz-caja{animation:none;
      background:color-mix(in srgb,var(--red) 14%,var(--surface))}
  }
  .vz-pc .vz-cols{gap:8px;border:0}
  .vz-pc .vz-col{gap:8px;border-left:0;min-width:0}
  /* LA TARJETA LLENA SU COLUMNA. La columna se estira al alto de la fila —es una grilla— y la
     tarjeta no: quedaba un hueco transparente abajo que se ve como un agujero en la fila. Medido
     antes de tocar nada: 85 px de diferencia arriba y 236 abajo entre la mas alta y la mas baja.
     El precio es aire adentro de la tarjeta corta, y molesta menos que el borde de abajo bailando:
     con los bordes desparejos el ojo no encuentra la linea horizontal y la fila no se lee como fila. */
  .vz-pc .vz-fija > .vz-col > .vz-caja{flex:1 1 auto}
  /* Sin aire entre secciones: con el borde alrededor, los catorce píxeles ya no separan nada —eso
     lo hace la línea— y sí impiden que se lea como una tabla de tres columnas. */
  /* Dos cajas apiladas ya no necesitan una línea que las separe: las separa el aire. */
  .vz-pc .vz-caja{background:var(--surface);border:1px solid var(--border);border-radius:0;
    box-shadow:none;padding:0;overflow:hidden}
  /* La cabecera de cada columna es la misma que la de las 89 tablas del sistema. */
  .vz-pc .vz-caja > .sup-tk-head{background:var(--surface-3);border-bottom:1px solid var(--border-strong);
    padding:5px 10px;margin:0;border-radius:0;min-height:0}
  .vz-pc .vz-caja > .sup-tk-head h4{font-size:12.5px;font-weight:var(--fw-semi);margin:0;line-height:1.5}
  .vz-pc .vz-caja > .sup-tk-head h4 small{font-size:11.5px;font-weight:var(--fw-normal);color:var(--text-faint)}

  /* LA BARRA LATERAL PASA A SER UN CUADRADITO, el mismo de la tabla de Capacidad. Una barra de 3 px
     pegada al borde sólo se lee como estado si ya sabés que lo es; el cuadradito va junto al dato,
     que es donde mira el ojo. */
  .vz-pc .vz-fila{border-left:0;border-top:0;border-bottom:1px solid var(--border);
    padding:4px 10px;gap:8px}
  .vz-pc .vz-fila::before{content:'';flex:0 0 auto;width:8px;height:8px;background:var(--text-faint)}
  .vz-pc .vz-f-bien::before{background:var(--green)}
  .vz-pc .vz-f-ojo::before{background:var(--amber)}
  .vz-pc .vz-f-mal::before{background:var(--red)}
  .vz-pc .vz-f-ok::before{background:var(--green)}
  .vz-pc .vz-fila.vz-f-ok{border-left:0}
  /* Los renglones que no dicen estado no llevan cuadradito: un cuadrado gris en cada fila sería
     ruido con forma de dato. */
  .vz-pc [data-vzsec="gpon"] .vz-fila::before{display:none}

  /* Las baldosas de «Equipos principales» pasan a ser filas, como en la maqueta: nombre a la
     izquierda, cuadradito y cuenta a la derecha. En columna angosta cinco baldosas no entran, y
     partidas en dos filas de dos y media se ven peor que una lista. */
  .vz-pc .vz-tiles{display:block;padding:0}
  .vz-pc .vz-tile{flex-direction:row;align-items:center;gap:8px;padding:4px 10px;
    border:0;border-bottom:1px solid var(--border);border-radius:0;background:transparent;width:100%}
  .vz-pc .vz-tile:hover{background:var(--surface-2)}
  .vz-pc .vz-tile.on{background:var(--surface-2)}
  .vz-pc .vz-tile-r{order:0;flex:1 1 auto;font-size:12.5px;color:var(--text)}
  .vz-pc .vz-tile-n{order:2;flex:0 0 auto;font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:12.5px}
  .vz-pc .vz-tile-mal,.vz-pc .vz-tile-ojo{border-left:0}
  /* ===== EL CONTENIDO DE UNA CATEGORÍA, PLANO =====
     Traía una barra vertical de 2 px a la izquierda y un sangrado: las filas arrancaban en x=73 y la
     grilla en x=104. Una barra al costado es el dibujo de «esto cuelga de aquello», así que la fila
     de superrouters —que viene justo después de la grilla de OLT— se leía como si estuviera adentro.
     Y no cerraba con nada: la fila lleva su línea ABAJO, así que después de la grilla no había
     ninguna y la grilla se tocaba con la fila siguiente. De ahí el «doble recuadro».
     Ahora separa la línea y nada más, como en el resto del sistema: fila · línea · contenido · línea.
     El sangrado se queda en el teléfono, donde las categorías se abren de a una y no hay ancho para
     alinear nada. */
  .vz-pc .vz-det{border-left:0;margin-left:0;padding:0 10px 10px;
    border-bottom:1px solid var(--border)}
  /* La grilla ya no pone su propio margen a los costados: lo pone el contenido, y así las celdas
     arrancan donde arranca el texto de su fila en vez de treinta píxeles más adentro. */
  .vz-pc .vz-det .vz-ogrid{padding:8px 0 0}
  /* A LA DERECHA, PEGADO AL NÚMERO. El estado de «OLT» ES el número —17 de 18—: el color tiene que
     estar donde está el dato que califica, no al principio del renglón. */
  .vz-pc .vz-tile::before{content:'';order:1;flex:0 0 auto;width:8px;height:8px;background:var(--green)}
  .vz-pc .vz-tile-mal::before{background:var(--red)}
  .vz-pc .vz-tile-ojo::before{background:var(--amber)}

  /* LOS SUPERROUTERS SE QUEDAN EN DOS RENGLONES. En la maqueta iban en uno solo y los nombres
     salían cortados —«SRout…», «SuperRouter14v2 — OLT 0…»—: el nombre dice de qué OLT es cada uno,
     y cortado no sirve. Se quedan como están, con el nombre entero arriba y el detalle debajo; lo
     único que cambia es el dibujo: pierden la cajita con borde de color y ganan el cuadradito y la
     línea de abajo, como el resto de la pantalla. */
  .vz-pc .vz-eqs{gap:0}
  .vz-pc .vz-eq{display:grid;grid-template-columns:8px 1fr;column-gap:8px;row-gap:1px;align-items:baseline;
    padding:4px 10px;border:0;border-bottom:1px solid var(--border);border-radius:0;background:transparent}
  .vz-pc .vz-eq::before{content:'';grid-row:1;width:8px;height:8px;background:var(--green);align-self:center}
  .vz-pc .vz-eq-mal::before{background:var(--red)}
  .vz-pc .vz-eq-ojo::before{background:var(--amber)}
  .vz-pc .vz-eq-sindato::before{background:var(--text-faint)}
  .vz-pc .vz-eq b{grid-column:2}
  .vz-pc .vz-eq span{grid-column:2}
  .vz-pc .vz-eq-ojo,.vz-pc .vz-eq-mal{background:transparent}

  /* Los contadores de arriba pierden la caja: número arriba, y debajo el rótulo con su aclaración
     en la misma línea. Los separa una línea vertical, no un recuadro cada uno. */
  .vz-pc > .vz-kpis .tt-kpi{background:transparent;border:0;border-left:1px solid var(--border);
    border-radius:0;padding:7px 14px;flex-wrap:wrap;gap:0}
/* 12 px y no 0: sin la linea vertical de los otros, el `padding-left:0` dejaba el primer numero
     pegado al borde del menu lateral —medido, a 1 px, contra los 11 de las bandas de las tarjetas—.
     12 es el valor de la casa: `.sup-tk-head`, la franja de aviso y los indicadores de «Que hacer
     hoy» usan el mismo. */
  .vz-pc > .vz-kpis .tt-kpi:first-child{border-left:0;padding-left:10px}
  /* ===== LA FILA DE CONTADORES CIERRA =====
     No tenía borde propio: quedaba flotando entre la franja y los bloques de abajo, con aire de los
     dos lados. Ahora lleva el mismo marco que el resto y se apoya sobre el bloque de abajo — la
     línea que los separa es una sola, la de abajo de ésta. */
  .vz-pc > .vz-kpis{border:1px solid var(--border);border-bottom:0;background:var(--surface);
    margin-bottom:0}
  /* EL QUE TIENE ALGO MAL SE PINTA. Un número rojo entre cuatro números se encuentra leyendo; una
     caja con su color se encuentra mirando. El tinte es del 6%: tiene que distinguirse, no gritar. */
  .vz-pc > .vz-kpis .tt-kpi.k-mal{background:color-mix(in srgb,var(--red) 6%,transparent);
    box-shadow:inset 3px 0 0 var(--red)}
  .vz-pc > .vz-kpis .tt-kpi.k-mal .k-lbl{color:var(--text)}
  /* ===== EL CORTE EN CURSO PULSA =====
     Es lo primero que se quiere ver de la pantalla. Dos segundos por vuelta: lo bastante lento para
     no molestar mientras se trabaja, lo bastante para que el ojo lo agarre al entrar. Y SÓLO cuando
     hay corte — un pulso permanente deja de avisar a los diez minutos. */
  @keyframes vz-late{ 0%,100%{ background:color-mix(in srgb,var(--red) 6%,transparent) }
                      50%{ background:color-mix(in srgb,var(--red) 20%,transparent) } }
  .vz-pc > .vz-kpis .tt-kpi.k-late{animation:vz-late 2s ease-in-out infinite}
  /* Con el movimiento reducido no se anima: se deja el tinte más fuerte, fijo. */
  @media(prefers-reduced-motion:reduce){
    .vz-pc > .vz-kpis .tt-kpi.k-late{animation:none;
      background:color-mix(in srgb,var(--red) 16%,transparent)}
  }
  .vz-pc > .vz-kpis .tt-kpi .k-num{flex:0 0 100%;font-size:20px;margin-bottom:1px}
  .vz-pc > .vz-kpis .tt-kpi .k-lbl{flex:0 0 auto;font-size:12px;color:var(--text-dim)}
  .vz-pc > .vz-kpis .tt-kpi .k-sub{flex:0 1 auto;font-size:12px;color:var(--text-faint)}
  /* El punto medio se separa con margen y no con espacios dentro del `content`: el rotulo y la
     aclaracion son dos items flex, y ahi los espacios de los extremos se colapsan —quedaba
     «Cortes en curso· ninguno ahora»—. */
  .vz-pc > .vz-kpis .tt-kpi .k-sub{margin-left:5px}
  .vz-pc > .vz-kpis .tt-kpi .k-sub::before{content:'·';margin-right:5px}
  /* La banda de contadores, encerrada igual que las columnas: es la misma rejilla, un renglón más
     arriba. */
  .vz-pc > .vz-kpis .tt-kpis{border:1px solid var(--border);border-bottom:0;margin-bottom:0;padding:0;gap:0}
  /* La banda y las columnas son UNA rejilla, no dos bloques apilados: comparten el borde. Con aire
     entre medio se leen como dos cosas, y son la misma —cada numero de arriba es el indice de una
     columna de abajo—. */
  .vz-pc > .vz-kpis{margin-bottom:0}
  .vz-pc > .vz-kpis + .vz-cols{border-top:0}

  /* El aviso, en un renglón: una línea de color a la izquierda y el texto seguido.
     CENTRADO Y NO POR BASELINE: la barra de color ocupa todo el alto y el texto apoyado en la línea
     de base quedaba corrido respecto de ella.
     Y CON UN TINTE DEL COLOR DEL ESTADO —7%, apenas una veladura— para que se lea como una banda y
     no como un renglón más: es el único aviso de la pantalla. El tinte sale del color del estado y
     no de un gris fijo, así el color dice la severidad también en el fondo. */
  .vz-pc > .vz-tit.vz-franja{display:flex;align-items:center;gap:10px;padding:7px 12px 7px 11px;
    background:color-mix(in srgb,var(--red) 7%,transparent);
    border:0;border-left:3px solid var(--red);border-radius:0;margin-bottom:8px}
  .vz-pc > .vz-tit.vz-franja.vz-ojo{border-left-color:var(--amber);
    background:color-mix(in srgb,var(--amber) 7%,transparent)}
  .vz-pc > .vz-tit.vz-franja .vz-tit-ic{display:none}
  .vz-pc > .vz-tit.vz-franja .vz-tit-tx{flex-direction:row;align-items:center;gap:10px}
  .vz-pc > .vz-tit.vz-franja .vz-tit-tx b{font-family:inherit;font-size:12.5px;font-weight:var(--fw-semi);
    letter-spacing:0;color:var(--red)}
  .vz-pc > .vz-tit.vz-franja.vz-ojo .vz-tit-tx b{color:var(--amber)}
  .vz-pc > .vz-tit.vz-franja .vz-tit-tx span{font-size:12.5px;font-weight:var(--fw-semi);color:var(--red)}
  .vz-pc > .vz-tit.vz-franja.vz-ojo .vz-tit-tx span{color:var(--amber)}
  /* EN LA FRANJA MANDA LA ENUMERACIÓN. El resumen de arriba dice lo mismo con otras palabras y, con
     un solo problema, exactamente las mismas: se muestra sólo cuando no hubo lista que enumerar. */
  .vz-pc > .vz-tit.vz-franja .vz-tit-tx b{display:none}
  .vz-pc > .vz-tit.vz-franja .vz-tit-tx:has(.vz-sinlista) b{display:inline}
  .vz-pc > .vz-tit.vz-franja .vz-tit-tx:has(.vz-sinlista) span{font-weight:var(--fw-normal);color:var(--text-dim)}

  /* Y las zonas degradándose, a la misma escala que el resto. Sin esto heredaban los 16 px del
     cuerpo, que era el único tamaño suelto que quedaba en la pantalla. */
  .vz-pc .vz-zd{padding:4px 10px;font-size:12.5px}
  .vz-pc .vz-zd-n,.vz-pc .vz-zd-c{font-size:12px}
  .vz-pc .vz-zd-q b{font-weight:var(--fw-medium)}
}
/* Zonas degradándose: tres columnas —qué zona, cuánto bajó y desde cuándo—. Grilla y no tabla
   porque la tarjeta vive en una columna angosta, donde una tabla se desborda. */
.vz-zd{display:grid;grid-template-columns:1fr auto auto;gap:10px;align-items:baseline;
  padding:8px 10px;border-bottom:1px solid var(--border)}
.vz-zd:last-child{border-bottom:0}
.vz-zd small{display:block;font-size:11px;color:var(--text-faint);font-family:'IBM Plex Sans',sans-serif}
.vz-zd-n{text-align:right;white-space:nowrap} .vz-zd-n b{color:var(--red)}
.vz-zd-c{text-align:right;white-space:nowrap;color:var(--text-dim);font-size:12px}
@media(max-width:520px){ .vz-zd{grid-template-columns:1fr auto} .vz-zd-c{grid-column:1/-1;text-align:left} }
@media(min-width:1000px){
  /* (sigue el bloque de escritorio) */
  /* La fila de números cruza el ancho, como en todas las pantallas que la tienen. */
  .vz-cuerpo > .vz-kpis .tt-kpis{margin:0}
  /* LOS RENGLONES SE ACHICAN. Los 48 px de alto son para el dedo; con mouse sobran, y en un monitor
     esa altura convierte cinco equipos en media pantalla. La tipografía y los colores no se tocan:
     lo único que cambia es cuánto aire lleva cada renglón. */
  .vz-cuerpo .vz-fila{min-height:28px;padding:4px 2px}
  /* GPON MÁS CALIENTES, UNA LÍNEA POR GPON. «OLT 09» y «GPON 3» ocupaban un renglón cada uno: ocho
     GPON eran 533 px, más que cualquier otra tarjeta de la pantalla. Puestos en la misma línea la
     misma información entra en la mitad, y no hace falta tocar cómo se arma la fila. */
  .vz-cuerpo [data-vzsec="gpon"] .vz-f-main{flex-direction:row;align-items:baseline;gap:7px}
  .vz-cuerpo [data-vzsec="gpon"] .vz-f-main span{color:var(--text-dim)}
  .vz-cuerpo [data-vzsec="gpon"] .vz-fila{min-height:26px}
  /* Y el titular no necesita el tamaño de teléfono cuando tiene 1.200 px para él solo. */
  .vz-cuerpo > .vz-tit{padding:14px 18px}
  /* El titular es la conclusión de todo lo de abajo: va cruzado arriba y no compitiendo por una
     columna con una caja cualquiera. */
  .vz-cuerpo > .vz-tit{grid-column:1/-1}
  /* Y las dos cajas donde se escribe ocupan el ancho: un campo de búsqueda en una columna de 420 px,
     con los resultados abajo, queda apretado justo cuando lo estás usando. */
}
/* El titular: lo primero y lo más grande. El color hace la mitad del trabajo — se entiende antes de
   leer— pero NUNCA va solo: lleva su símbolo y su frase, para el que no distingue los colores. */
.vz-tit{display:flex;align-items:center;gap:14px;padding:16px 18px;border-radius:var(--radius-xl);border:1px solid var(--border)}
.vz-tit-ic{flex:0 0 auto;width:46px;height:46px;border-radius:var(--radius-circ);display:flex;align-items:center;
  justify-content:center;font-size:24px;font-weight:var(--fw-black);line-height:1}
.vz-tit-tx{display:flex;flex-direction:column;gap:3px;min-width:0}
.vz-tit-tx b{font-family:'Archivo',system-ui,sans-serif;font-weight:var(--fw-black);font-size:20px;line-height:1.15;letter-spacing:-.3px}
.vz-tit-tx span{font-size:12.5px;color:var(--text-dim)}
.vz-tit.vz-bien{background:color-mix(in srgb,var(--green) 10%,transparent);border-color:color-mix(in srgb,var(--green) 40%,var(--border))}
.vz-tit.vz-bien .vz-tit-ic{background:color-mix(in srgb,var(--green) 22%,transparent);color:var(--green)}
.vz-tit.vz-ojo{background:color-mix(in srgb,var(--amber) 10%,transparent);border-color:color-mix(in srgb,var(--amber) 40%,var(--border))}
.vz-tit.vz-ojo .vz-tit-ic{background:color-mix(in srgb,var(--amber) 22%,transparent);color:var(--amber)}
.vz-tit.vz-mal{background:color-mix(in srgb,var(--red) 10%,transparent);border-color:color-mix(in srgb,var(--red) 40%,var(--border))}
.vz-tit.vz-mal .vz-tit-ic{background:color-mix(in srgb,var(--red) 22%,transparent);color:var(--red)}

/* Cada renglón: 48 px de alto mínimo, que es lo que se recomienda para tocar con el dedo. */
.vz-lista{display:flex;flex-direction:column}
.vz-fila{display:flex;align-items:center;gap:10px;min-height:48px;padding:9px 2px;
  border-top:1px solid var(--border);border-left:3px solid transparent}
.vz-fila:first-child{border-top:none}
.vz-f-main{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:2px}
/* 13 y 11: la escala de los datos de Capacidad. Catorce y doce eran medio escalón más, suficiente
   para que la misma información se viera de otro sistema. */
.vz-f-main b{font-size:12.5px;font-weight:var(--fw-medium)}
.vz-f-main span{font-size:11px;color:var(--text-faint);overflow-wrap:anywhere}
.vz-cajas{font-family:'IBM Plex Mono',monospace;font-size:11.5px!important;color:var(--text-faint)!important}
.vz-f-lado{flex:0 0 auto;font-size:12px;color:var(--text-dim);text-align:right;white-space:nowrap}
/* La cuenta «18/18»: el número que importa grande y el total chico al lado. */
/* La cuenta «2/2» es el dato de la fila, con la misma medida que los demás. */
.vz-cuenta{font-family:'IBM Plex Mono',ui-monospace,monospace;font-weight:var(--fw-semi);font-size:12.5px;color:var(--text)}
.vz-cuenta i{font-style:normal;font-weight:var(--fw-normal);font-size:11px;color:var(--text-faint)}
/* La temperatura es un DATO de la fila, no un titular: a la escala de los datos y monoespaciada,
   como todos los números del sistema. En 17 px con peso 700 era más grande que el título de su
   propia tarjeta, y ocho de ésas hacían que la tarjeta se viera gigante. */
.vz-temp{font-family:'IBM Plex Mono',ui-monospace,monospace;font-weight:var(--fw-semi);font-size:12.5px}
/* La barrita de la izquierda dice el estado sin depender de leer el número. */
.vz-f-bien{border-left-color:var(--green)}
.vz-f-ojo {border-left-color:var(--amber)}
.vz-f-ojo  .vz-temp{color:var(--amber)}
.vz-f-mal {border-left-color:var(--red)}
.vz-f-mal  .vz-temp{color:var(--red)}
.vz-f-bien .vz-temp{color:var(--text-dim)}

/* ---- Los renglones que se abren ---- */
.vz-tap{cursor:pointer;-webkit-tap-highlight-color:transparent}
.vz-tap:hover{background:color-mix(in srgb,var(--accent-ink) 5%,transparent)}
.vz-tap:focus-visible{outline:2px solid var(--accent-ink);outline-offset:-2px}
.vz-ch{font-style:normal;margin-left:9px;color:var(--text-faint);font-size:12px}
.vz-on{background:color-mix(in srgb,var(--accent-ink) 4%,transparent)}
/* El detalle va SANGRADO y con el borde a la izquierda: se ve que cuelga del renglón de arriba y no
   que es otro renglón más de la lista. */
.vz-det{padding:4px 0 12px 14px;margin-left:3px;border-left:2px solid var(--border);
  display:flex;flex-direction:column;gap:7px}
.vz-det-l{display:flex;gap:8px;font-size:12px;line-height:1.45}
.vz-det-l b{flex:0 0 78px;color:var(--text-dim);font-weight:var(--fw-semi)}
.vz-det-l span{flex:1 1 auto;min-width:0;color:var(--text);overflow-wrap:anywhere}
.vz-det-mas{font-size:12px;color:var(--text-faint);padding:4px 0}
/* Los clientes del detalle son botones: se tocan y abren su diagnóstico. */
.vz-det-cli{display:flex;flex-direction:column;gap:4px}
.vz-cli{display:flex;flex-direction:column;gap:1px;align-items:flex-start;text-align:left;width:100%;
  min-height:44px;padding:6px 9px;border:1px solid var(--border);border-radius:var(--radius);
  background:var(--surface-2);font-family:inherit;cursor:pointer}
.vz-cli:hover{border-color:var(--border-strong)}
.vz-cli b{font-size:12.5px;font-weight:var(--fw-semi);color:var(--text)}
.vz-cli span{font-size:11.5px;color:var(--text-dim)}
/* Los equipos de una categoría: en columnas, que entran muchos y se barren con la vista. */
.vz-eqs{display:grid;grid-template-columns:1fr 1fr;gap:5px}
@media(max-width:420px){ .vz-eqs{grid-template-columns:1fr} }
.vz-eq{display:flex;flex-direction:column;gap:1px;padding:5px 8px;border-radius:5px;
  border-left:3px solid var(--border);background:var(--surface-2);min-width:0}
/* Mismo par que los renglones: 13 para el nombre, 11 apagado para el detalle. */
.vz-eq b{font-size:12.5px;font-weight:var(--fw-medium);overflow-wrap:anywhere}
.vz-eq span{font-size:11px;color:var(--text-faint);overflow-wrap:anywhere}
.vz-eq-bien{border-left-color:var(--green)}
.vz-eq-mal{border-left-color:var(--red);background:color-mix(in srgb,var(--red) 8%,transparent)}
.vz-eq-mal b{color:var(--red)}
.vz-eq-sindato{border-left-color:var(--text-faint)}
/* Los resultados del buscador de cliente cuelgan del campo, sin caja propia. */
.vz-res{margin-top:8px}

.vz-busca{width:100%;margin:0 0 8px;min-height:40px}
.vz-mas{width:100%;margin-top:8px;min-height:40px}
.vz-diag{display:flex;flex-direction:column;gap:8px}
.vz-diag .vz-busca{margin:0}
/* Centrado explícito: siendo de ancho completo, el texto pegado a la izquierda hace que no parezca
   un botón sino un renglón más. */
.vz-diag-go{min-height:44px;display:flex;align-items:center;justify-content:center}
/* En pantalla ancha la pantalla sigue sirviendo, pero no se estira a lo bestia: es una columna de
   lectura, y a 1.400 px de ancho un renglón de 48 px con dos datos queda ridículo. */
@media(min-width:900px){
  .vz-cuerpo{max-width:720px;margin:0 auto}
  .vz-diag{flex-direction:row}
  .vz-diag .vz-busca{flex:1 1 auto}
  .vz-diag-go{flex:0 0 auto;min-width:130px}
}
/* ---- LAS CUATRO PANTALLAS QUE COMPARTEN ESTE ARMADO: QUE LA CADENA SE PUEDA ACHICAR ----
   Empezó por «Mis soportes» —Matías: «no me entra en la pantalla la tabla, se corta a la derecha»—
   y al revisarlo en un teléfono de verdad resultó que a «Registro de soporte» le pasaba lo mismo y
   PEOR: de sus doce columnas se veían tres. Las otras nueve —NODO, Estado, Fecha, Duración,
   Observación, Seguimiento, Ticket, Ficha y los botones— quedaban recortadas y sin forma de llegar
   a ellas, porque el que desbordaba era el panel y no la caja de la tabla, así que no aparecía
   ninguna barra para deslizar. Nadie lo había reportado: se ve sólo en pantalla angosta.

   LA CAUSA. En un elemento de flex el tamaño mínimo por omisión es `auto`, o sea el del contenido,
   no cero. Los encabezados de estas tablas van en una sola línea, así que su ancho mínimo es grande,
   estira toda la cadena de contenedores y el `overflow:hidden` del panel corta lo que sobra.
   Dejando que cada eslabón se pueda achicar, el sobrante vuelve a caer en `.sup-tk-wrap`, que sí
   tiene `overflow-x:auto`, y la tabla se desliza de costado.

   Las cuatro van juntas porque tienen EXACTAMENTE el mismo armado —vista, contenedor, `.so-wrap`,
   `.so-main`, panel— y así la próxima que se agregue con esta forma entra sola. No se suman acá las
   de Monitor OLT, Prueba y Tickets: ésas tienen su propia lista, con elementos distintos, y la de
   Monitor OLT además vive adentro de una consulta de ancho. Juntarlas cambiaría pantallas que hoy
   andan bien. */
#respWrap,#respView .so-wrap,#respView .so-main,#respView .so-panel,
#respView .so-panel-bar,#respView .so-panel-body,#respView .sup-card,#respView .sup-tk-wrap,
#sopregWrap,#sopregView .so-wrap,#sopregView .so-main,#sopregView .so-panel,
#sopregView .so-panel-bar,#sopregView .so-panel-body,#sopregView .sup-card,#sopregView .sup-tk-wrap,
#lupaWrap,#lupaView .so-wrap,#lupaView .so-main,#lupaView .so-panel,
#lupaView .so-panel-bar,#lupaView .so-panel-body,#lupaView .sup-card,#lupaView .sup-tk-wrap,
#vistazoWrap,#vistazoView .so-wrap,#vistazoView .so-main,#vistazoView .so-panel,
#vistazoView .so-panel-bar,#vistazoView .so-panel-body,#vistazoView .sup-card,
#missopWrap,#missopView .so-wrap,#missopView .so-main,#missopView .so-panel,
#missopView .so-panel-bar,#missopView .so-panel-body,#missopView .sup-card,#missopView .sup-tk-wrap{
  min-width:0;max-width:100%}
/* LA COLUMNA DEL CLIENTE QUEDA FIJA AL DESLIZAR. Con 23 columnas, correrse a la derecha para ver el
   nodo o la IP dejaba las filas sin identificar: números sueltos sin saber de quién eran. El
   encabezado ya se queda pegado arriba; esto es lo mismo para el costado.
   EL FONDO VA OPACO Y CON `!important` A PROPÓSITO: el tinte de antigüedad de la fila y el rayado de
   las pares son translúcidos —un 7% y un 6%—, así que una celda fija con ese fondo dejaría ver pasar
   el resto de la tabla por debajo. La barrita de color del borde izquierdo, que es la que marca
   cuánto hace que el ticket espera, se conserva porque va como sombra interior y no como fondo. */
#missopView .sup-tk th:first-child{position:sticky;left:0;z-index:3;background:var(--surface-2)}
#missopView .sup-tk tbody td:first-child{position:sticky;left:0;z-index:2;background:var(--surface)!important}
.rc-view{max-width:100%;padding:14px 16px calc(20px + env(safe-area-inset-bottom))}
/* Las pestañas van en la barra del titulo: son navegacion, no contenido. */
.so-panel-bar .sup-tabseg{margin:0}
.rc-bar-estado{font-size:12px;color:var(--text-faint);white-space:nowrap}
/* El selector de motivo, en la misma fila que el resto de los controles. */
.rc-motfil{display:inline-flex;align-items:center;gap:7px;font-size:12px;color:var(--text-dim);padding-left:14px;border-left:1px solid var(--border)}
.rc-motfil .sel{width:auto;min-width:150px;max-width:230px;font-size:12px;height:30px;padding:0 8px}
/* No envuelve: si no entra se desplaza de costado, igual que los KPI y que la franja de Caidas. */
.rc-tools{display:flex;align-items:center;gap:10px;flex-wrap:nowrap;overflow-x:auto;
  scrollbar-width:thin;margin:10px 0 12px;padding-bottom:2px}
.rc-tools>*{flex:0 0 auto}
.rc-fresco{font-size:12px;color:var(--text-faint)}
.rc-refrescar{background:none;border:none;color:var(--link);font-size:12px;text-decoration:underline;cursor:pointer;padding:0}
.rc-pill{display:inline-flex;align-items:center;font-size:11px;font-weight:var(--fw-bold);border-radius:var(--radius);padding:1px 8px;
  border:1px solid var(--border);color:var(--text-dim);background:var(--surface-3);white-space:nowrap}
/* El sin-tarea es el motivo de la pantalla: se ve de lejos y la fila entera se marca. */
.rc-pill.sin{color:#c0503f;background:#c0503f1f;border-color:#c0503f66}
.rc-pill.desc{color:var(--text-faint)}
.rc-pill.frenado{color:#d08a2c;background:#d08a2c1f;border-color:#d08a2c66}
.rc-pill.baja{color:var(--text-faint);font-weight:var(--fw-semi)}
.rc-pill.venta{margin-left:6px;color:#8f7ad8;background:#8f7ad81f;border-color:#8f7ad866}
.rc-pill.mot{color:var(--text);background:var(--surface-3);white-space:normal}
.rc-td-mot{min-width:120px}
/* Contacto y direccion: texto largo que tiene que poder cortarse, no estirar la tabla. */
.rc-td-cont{min-width:104px;max-width:150px;font-size:12px;overflow-wrap:anywhere}
.rc-td-dir{min-width:140px;max-width:210px;font-size:12px;overflow-wrap:anywhere}
.rc-geo{color:var(--link);font-size:11px;text-decoration:underline}
/* El numerito de la pestaña: cuantos siguen frenados y sin tarea en esa seccion. */
/* Las solapas de adentro: separadas de las de arriba para que no se confundan los dos niveles. */
/* Van en la misma fila que los filtros, separadas por una linea vertical. */
.rc-orig{margin:0;padding:0 14px 0 0;border-right:1px solid var(--border)}
.rc-tabtot{margin-left:6px;color:var(--text-faint);font-family:'IBM Plex Mono';font-size:11px;font-weight:var(--fw-semi)}
.sup-tab.on .rc-tabtot{color:inherit;opacity:.75}
.rc-tabn{margin-left:6px;background:#c0503f;color:#fff;border-radius:var(--radius);font-family:'IBM Plex Mono';font-size:10px;font-weight:var(--fw-bold);line-height:15px;padding:0 5px;min-width:17px;display:inline-block;text-align:center}
.rc-td-edo{white-space:nowrap}
/* El numero rojo al lado del nombre del area: es el aviso de que hay algo sin procesar. */
.area-switch button .area-badge{margin-left:6px;background:#c0503f;color:#fff;border-radius:var(--radius);font-family:'IBM Plex Mono';font-size:11px;font-weight:var(--fw-bold);line-height:16px;padding:0 6px;min-width:18px;text-align:center}
.sup-tk tbody tr.rc-desc td{opacity:.6}
.sup-tk tbody tr.rc-huerfano td{box-shadow:inset 3px 0 0 -1px #c0503f}
.rc-tarea{font-family:'IBM Plex Mono';font-weight:var(--fw-bold);color:var(--link);text-decoration:none}
.rc-tarea:hover{text-decoration:underline}
.rc-td-tarea{white-space:nowrap;min-width:166px}
.rc-td-tarea>.rc-pill,.rc-td-tarea>.rc-tarea{margin-right:5px}
.rc-td-dias{white-space:nowrap}
/* La observacion es el dato que decide si esto es infraestructura: entera, respetando los renglones. */
.rc-td-obs{white-space:pre-wrap;overflow-wrap:anywhere;min-width:200px;max-width:360px;font-size:12px;line-height:1.4;color:var(--text-dim)}
/* Los botones van debajo del estado de la tarea, en la misma celda. */
.rc-acts{display:flex;gap:5px;flex-wrap:wrap;margin-top:5px}
.rc-mini{padding:2px 9px;font-size:12px}
@media(max-width:760px){ .rc-view{padding:10px 10px 18px} .rc-td-obs{max-width:260px} }
.col-empty{
  border:1.5px dashed var(--border);border-radius:var(--radius);padding:22px 12px;text-align:center;
  color:var(--text-faint);font-size:12.5px;
}

/* card */
.card{
  position:relative;background:var(--card-bg,var(--surface-2));border:1px solid var(--border);border-radius:var(--radius);
  padding:9px 11px;cursor:grab;transition:.14s;overflow:hidden;
  flex:0 0 auto;
  content-visibility:auto;contain-intrinsic-size:auto 86px;   /* virtualización: no pinta tarjetas fuera de pantalla */
}
.card:hover{border-color:var(--border-strong);transform:translateY(-2px);box-shadow:0 12px 28px -14px rgba(0,0,0,.7)}
.card:active{cursor:grabbing}
.card.dragging{opacity:.45;transform:rotate(1.5deg) scale(.98)}
.card.blocked{border-color:var(--amber);background:color-mix(in srgb,var(--amber) 9%,var(--card-bg,var(--surface-2)))}
/* Vencidas: efecto sutil (sin recuadro lleno) — borde tenue + resplandor que late despacio */
@keyframes overdueGlow{
  0%,100%{ box-shadow:0 0 0 1px color-mix(in srgb,var(--red) 28%,transparent), 0 6px 20px -14px color-mix(in srgb,var(--red) 60%,transparent); }
  50%    { box-shadow:0 0 0 1px color-mix(in srgb,var(--red) 50%,transparent), 0 10px 30px -10px color-mix(in srgb,var(--red) 80%,transparent); }
}
/* Vencidas: la PRIORIDAD alta parpadea; media y baja quedan sólo con el borde. El aro tenue que
   distinguía a la media se sacó por pedido de Matías (01/09/2026), para que la tarjeta quede más
   limpia: se gana calma visual y se pierde poder distinguir media de baja de un vistazo. */
.card.overdue{background:var(--card-bg,var(--surface-2))}
.card.overdue.prio-alta{animation:overdueGlow 2.6s ease-in-out infinite}
.card.overdue.prio-alta:hover{animation:none}
@media (prefers-reduced-motion: reduce){ .card.overdue.prio-alta{animation:none;box-shadow:0 0 0 1px color-mix(in srgb,var(--red) 45%,transparent)} }
/* Alerta progresiva de vencimiento (5 niveles): la tinta la lleva LA FECHA (ver `.venc-lvl`), no el
   borde de la tarjeta — se sacó el 01/09/2026 porque repetía el mismo dato rodeando toda la tarjeta
   y llenaba la pantalla de marcos de color. */
.proj-obj.venc-warn{color:#c08a34}
.proj-obj.venc-over{color:#c07a52;font-weight:var(--fw-semi)}
.proj-obj.venc-late,.proj-obj.venc-crit{color:var(--red);font-weight:var(--fw-bold)}
/* Modo compacto: tarjetas más chicas para ver más en pantalla */
body.board-compact .card{padding:6px 9px;border-radius:var(--radius);contain-intrinsic-size:auto 58px}
body.board-compact .card-top{margin-bottom:4px}
body.board-compact .card-title{font-size:12px;line-height:1.25;margin-bottom:5px}
body.board-compact .tipo-chip{font-size:10px;padding:2px 6px;letter-spacing:.05em}
body.board-compact .card-icons{gap:4px}
body.board-compact .ic-chip{font-size:10px;padding:1px 5px}
body.board-compact .ic-chip svg{width:11px;height:11px}
body.board-compact .card-cover{height:64px;margin-bottom:7px}
.card-prio{position:absolute;left:0;top:0;bottom:0;width:3px}
.card-top{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:6px}
.tipo-chip{
  font-size:11px;font-weight:var(--fw-semi);letter-spacing:.08em;text-transform:uppercase;
  padding:4px 8px;border-radius:var(--radius-sm);background:var(--surface-3);color:var(--text-dim);
}
/* CHIPS DE TIPO CON COLOR PROPIO.
   El color lo elige cada uno en Configuración, así que puede ser cualquiera: hay violetas y verdes
   que sobre fondo claro quedaban en 2,7 de contraste (ilegibles) y rojos que sobre fondo oscuro
   quedaban en 3,0. Antes se corregía con `filter`, que aclaraba todo por igual sin mirar el color de
   partida —y encima los filtros no se pueden medir con getComputedStyle, así que las auditorías de
   contraste no los veían—. Ahora el color entra por --cc y cada tema lo lleva hacia donde le falta:
   hacia el blanco sobre fondo oscuro, hacia el negro sobre fondo claro. Las proporciones están
   calibradas contra los peores casos posibles (negro y blanco puros): ninguna baja de 4,5.
   Si el navegador no soporta color-mix, la regla se descarta y queda el color tal cual: se ve
   como antes, nunca en blanco. */
.tipo-chip[data-cc]{
  color:var(--cc);
  background:color-mix(in srgb, var(--cc) 13%, transparent);
  border:1px solid color-mix(in srgb, var(--cc) 25%, transparent);
}
:root:not([data-theme="light"]) .tipo-chip[data-cc]{ color:color-mix(in srgb, var(--cc) 47%, #fff); }
html[data-theme="light"]        .tipo-chip[data-cc]{ color:color-mix(in srgb, var(--cc) 44%, #000); }
.proj-chip{
  display:inline-flex;align-items:center;font-size:11px;font-weight:var(--fw-bold);
  letter-spacing:.04em;color:#fff;background:var(--pc,#5e6a82);padding:3px 7px;border-radius:var(--radius-sm);
  cursor:pointer;border:none;white-space:nowrap;
}
.proj-chip:hover{filter:brightness(1.18)}
.proxima-badge{display:inline-flex;align-items:center;font-size:10px;font-weight:var(--fw-black);letter-spacing:.07em;color:var(--on-signal);background:var(--signal);padding:3px 7px;border-radius:var(--radius-sm);text-transform:uppercase}
.card-id{font-size:11px;font-weight:var(--fw-bold);color:var(--card-num,var(--text));background:var(--surface-3);padding:1px 6px;border-radius:var(--radius-sm);flex:0 0 auto}
.ct-chips{display:flex;gap:6px;align-items:center;min-width:0;flex-wrap:wrap}
.card-title{font-size:13.5px;font-weight:var(--fw-semi);line-height:1.3;margin-bottom:7px;color:var(--card-title,inherit)}
/* Los títulos iban forzados a mayúscula. Servía cuando eran cortos («Z240P», «AMPLIAR CAJA»), pero
   hoy el 40% pasa de 40 caracteres y en el celular son tres renglones que se leen de a una palabra:
   la mayúscula borra la forma de cada palabra, que es de lo que se agarra el ojo para leer de un
   saque. Se muestran como los escribieron — el que los escribió en mayúscula los sigue viendo así.
   La mayúscula queda donde sí funciona: etiquetas cortas, chips de tipo y encabezados. */
.card-title,.mt-ttl,.flt-ttl,.fl-mini-ttl,.tre-ttl,.proj-nm{text-transform:none}
.card-icons{display:flex;flex-wrap:wrap;gap:5px;margin-bottom:0}
.ic-chip{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:var(--fw-semi);color:var(--text-dim);background:var(--surface-3);padding:2px 6px;border-radius:var(--radius-sm);line-height:1}
.ic-chip svg{width:12px;height:12px;flex:0 0 auto}
.ic-chip b{font-weight:var(--fw-black);font-size:11px}
.ic-chip.blocked{color:#c2555f;background:#c2555f1a}
.ic-chip.bloq-dep,.ic-chip.bloq-mat{background:var(--red-fill);color:#fff;border:1px solid var(--red-fill);font-weight:var(--fw-black);padding:2px 8px}
.ic-chip.bloq-prep{background:#5b7aa8;color:#06121a;border:1px solid #5b7aa8;font-weight:var(--fw-black);padding:2px 8px}
/* La espera no es un error: es ambar, no rojo. Y la que ya se libero va en verde porque es la
   unica de las cuatro que pide una accion inmediata. */
.ic-chip.bloq-esp{background:#c08a34;color:#1a1206;border:1px solid #c08a34;font-weight:var(--fw-black);padding:2px 8px}
.ic-chip.bloq-libre{background:#4f9e78;color:#04140d;border:1px solid #4f9e78;font-weight:var(--fw-black);padding:2px 8px}
.flt-bloq.bloq-esp{background:#c08a34;color:#1a1206}
.flt-bloq.bloq-libre{background:#4f9e78;color:#04140d}
.espera-vivo{font-size:12px;color:var(--text-dim);line-height:1.55;padding:2px 0}
.espera-vivo:empty{display:none}
.ic-chip.cierreop{color:#c08a34;background:#c08a341a;border:1px solid #c08a3455;font-weight:var(--fw-bold)}
.ic-chip.devpend{color:#c08a34;background:#c08a341a;border:1px solid #c08a3466;font-weight:var(--fw-black)}
.ic-chip.devno{color:#c2555f;background:#c2555f1a;border:1px solid #c2555f66;font-weight:var(--fw-black)}
.card-motivo.dev-parcial{color:#c08a34;background:#c08a3412}
.card-motivo.dev-nopudo{color:#ff7683;background:#c2555f12}
.card-motivo .dev-by{opacity:.7;font-weight:var(--fw-semi)}
.ic-chip.clientes{color:#3f8a9c;background:#3f8a9c1a;border:1px solid #3f8a9c55;font-weight:var(--fw-bold)}
.cierre-hint{font-size:12px;color:var(--text-faint);line-height:1.4;margin:2px 0 4px}
.ic-chip.bloq-dep svg,.ic-chip.bloq-mat svg,.ic-chip.bloq-prep svg,.ic-chip.bloq-esp svg,.ic-chip.bloq-libre svg{opacity:.95}
.ic-chip.depok{color:#4f9e78;background:#4f9e781a}
.deps-pick{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:8px}
.dep-chip{display:inline-flex;align-items:center;gap:7px;font-size:12px;background:var(--surface-3);border:1px solid var(--border);padding:4px 9px;border-radius:var(--radius-sm);max-width:100%}
.dep-chip.missing{opacity:.6}
.dep-chip .dep-state{width:7px;height:7px;border-radius:var(--radius-circ);flex:0 0 auto}
.dep-chip .dep-tx{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:240px}
.dep-x{margin-left:1px;color:var(--text-faint);font-size:12.5px;line-height:1;cursor:pointer;border:none;background:none;padding:0 2px}
.dep-x:hover{color:var(--red)}
.card-dates{font-size:12px;color:var(--text-faint);flex:1;min-width:0;line-height:1.3}
.card-dates .due-bad{color:var(--red);font-weight:var(--fw-semi)}
.card-nodate{opacity:.7}
/* Antigüedad de la tarea. El escalón de color es la información: sin él, «hace 456 días» se lee
   igual que «hace 3 días». Los colores salen del tema para que funcionen en claro y en oscuro. */
.card-edad{color:var(--text-faint)}
.card-edad.edad-vieja{color:var(--amber)}
.card-edad.edad-anio{color:var(--red);font-weight:var(--fw-semi)}
.card-motivo{font-size:12px;color:#c2555f;background:#c2555f12;border-radius:var(--radius-sm);padding:4px 8px;margin-bottom:9px;line-height:1.3;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.card-motivo.cancel{color:var(--text-faint);background:var(--surface-3)}
.card-motivo.prep{color:#5b7aa8;background:#5b7aa812}
.motivo-note{font-size:12.5px;color:var(--text-dim);background:var(--surface-3);border-radius:var(--radius);padding:8px 11px;line-height:1.35}
.motivo-note.blk{color:#ff8a8f;background:#c2555f14;border:1px solid #c2555f33}
.card-meta{display:flex;flex-direction:column;gap:6px;font-size:12.5px;color:var(--text-dim)}
.card-meta .row{display:flex;align-items:center;gap:7px}
.card-meta svg{width:13px;height:13px;flex:0 0 auto;color:var(--text-faint)}
.card-meta .row.due-bad{color:var(--red)}
.card-meta .row.due-bad svg{color:var(--red)}
.card-foot{display:flex;align-items:center;justify-content:space-between;margin-top:7px;gap:10px;color:var(--text-dim)}
.prio-badge{display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:var(--fw-semi);letter-spacing:.04em}
.prio-badge .pd{width:7px;height:7px;border-radius:var(--radius-circ)}
.chk-bar{flex:1;display:flex;align-items:center;gap:7px;font-size:11px;color:var(--text-faint)}
.chk-track{flex:1;height:5px;border-radius:var(--radius-sm);background:var(--surface-3);overflow:hidden}
.chk-fill{height:100%;background:linear-gradient(90deg,var(--signal-dim),var(--signal));border-radius:var(--radius-sm);transition:width .3s}
.assignee{display:flex;align-items:center;gap:6px;flex:0 0 auto}
.assignee .avatar{width:20px;height:20px;border-radius:var(--radius-sm);font-size:10px}
.asg-nm{font-size:12px;color:var(--text-dim);font-weight:var(--fw-semi);white-space:nowrap}
.assignee .nm{font-size:12px;color:var(--text-dim);font-weight:var(--fw-medium)}
.unassigned{font-size:12px;color:var(--text-faint);font-style:italic}
.assignee .avatar + .avatar{margin-left:-9px;box-shadow:0 0 0 2px var(--surface-2)}
.assignee .nm{margin-left:4px;font-size:11px;color:var(--text-dim);font-weight:var(--fw-semi)}
.tecs-pick{display:flex;flex-wrap:wrap;gap:6px;max-height:122px;overflow:auto;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:8px}
.tecs-opt{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--text-dim);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:5px 9px 5px 7px;cursor:pointer;transition:.12s}
.tecs-opt:hover{border-color:var(--border-strong)}
.tecs-opt input{accent-color:var(--accent-ink);width:14px;height:14px;cursor:pointer;margin:0}
.tecs-opt .avatar{width:22px;height:22px;border-radius:var(--radius-sm);font-size:9px}
.lbl-pick{display:flex;flex-wrap:wrap;gap:7px}
.lbl-opt{font-size:12px;font-weight:var(--fw-semi);padding:6px 11px;border-radius:var(--radius-sm);border:1.5px solid var(--lc);color:var(--lc);background:transparent;cursor:pointer;transition:.12s;opacity:.65}
.lbl-opt:hover{opacity:.9}
.lbl-opt.on{background:var(--lc);color:#fff;opacity:1}
.card-labels{display:flex;flex-wrap:wrap;gap:5px;margin:1px 0 9px}
.clbl{display:inline-block;font-size:10px;font-weight:var(--fw-bold);color:#fff;padding:2px 7px;border-radius:var(--radius-sm);white-space:nowrap}

/* ====================== MODAL ====================== */
.scrim{
  position:fixed;inset:0;z-index:60;background:rgba(5,8,14,.86);
  display:none;align-items:flex-start;justify-content:center;padding:40px 20px;overflow:auto;
}
.scrim.open{display:flex}
.ui-scrim{z-index:90;align-items:center}
.ui-err{color:var(--red);font-size:12px;min-height:15px;margin-top:1px}
.modal{
  width:min(680px,100%);background:linear-gradient(180deg,var(--surface),var(--bg-2));
  border:1px solid var(--border-strong);border-radius:var(--radius);box-shadow:var(--shadow);
  animation:rise .35s cubic-bezier(.2,.8,.2,1) both;overflow:hidden;
}
.modal-head{
  display:flex;align-items:flex-start;gap:14px;padding:20px 22px;border-bottom:1px solid var(--border);
  background:linear-gradient(180deg,rgba(147,37,90,.05),transparent);
}
.modal-head .mh-prio{width:4px;align-self:stretch;border-radius:var(--radius-sm);min-height:38px}
.modal-head .grow{flex:1;min-width:0}
.modal-head .mh-id{font-family:'IBM Plex Mono';font-size:12px;color:var(--accent-ink);letter-spacing:.05em}
.modal-head h3{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:17px;letter-spacing:-.3px;margin-top:3px;line-height:1.25}
.icon-btn{width:34px;height:34px;border-radius:var(--radius);display:grid;place-items:center;background:var(--surface-2);border:1px solid var(--border);color:var(--text-dim);flex:0 0 auto;transition:.15s}
.icon-btn:hover{color:var(--text);border-color:var(--border-strong)}
.icon-btn svg{width:17px;height:17px}
.icon-btn.on{background:var(--selected);color:var(--text);border-color:var(--accent-ink)}

.modal-body{padding:20px 22px;display:flex;flex-direction:column;gap:18px;max-height:62vh;overflow:auto}
.mpanel{display:none;flex-direction:column;gap:18px}
.mpanel.on{display:flex}
.set-tabs .set-tab{cursor:pointer}
.field{display:flex;flex-direction:column;gap:7px}
.field > label{font-size:11px;letter-spacing:.13em;text-transform:uppercase;color:var(--text-faint);font-weight:var(--fw-semi)}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:14px}
/* ===== Formulario de tarea: MODAL centrado, estilo FICHA (etiqueta a la izquierda) ===== */
.modal.modal-task{width:min(1040px,100%);display:flex;flex-direction:column;background:var(--bg);--form-w:1040px}
@media(min-width:681px){ .modal.modal-task{max-height:calc(100vh - 96px)} }
/* Encabezado: ID · título · estado — unido con las pestañas en un solo bloque */
.modal.modal-task .mt-top{flex:0 0 auto;display:flex;align-items:center;gap:13px;padding:13px max(clamp(16px,3vw,48px), (100% - var(--form-w))/2) 9px;border-bottom:0;background:var(--surface)}
.mt-top .mt-prio{width:4px;align-self:stretch;border-radius:var(--radius-sm);min-height:34px;flex:0 0 auto}
.mt-top .mt-top-h{flex:1;min-width:0}
.mt-top .mt-top-id{display:flex;align-items:center;gap:12px}
.mt-top .mt-top-id .flt-id{font-family:'IBM Plex Mono';font-size:12px;color:var(--accent-ink);letter-spacing:.04em}
.mt-top .mt-top-date{font-size:11px;color:var(--text-faint)}
.mt-top .mt-top-title{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:17px;letter-spacing:-.2px;margin-top:2px;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mt-top .mt-est{flex:0 0 auto;font-size:11px;font-weight:var(--fw-bold);color:var(--ec);border:1px solid var(--ec);border-radius:var(--radius);padding:3px 12px;background:color-mix(in srgb,var(--ec) 12%,transparent)}
/* Pestañas sobrias con subrayado */
.modal.modal-task .mt-tabs{flex:0 0 auto;display:flex;gap:2px;padding:0 max(clamp(16px,3vw,48px), (100% - var(--form-w))/2);background:var(--surface);border:0;border-bottom:1px solid var(--border);border-radius:0;overflow-x:auto}
.modal.modal-task .mt-tabs .set-tab{padding:12px 15px;border:0;border-bottom:2px solid transparent;border-radius:0;background:none;color:var(--text-dim);font-size:12.5px;font-weight:var(--fw-semi);white-space:nowrap;transition:.15s}
.modal.modal-task .mt-tabs .set-tab:hover{color:var(--text)}
.modal.modal-task .mt-tabs .set-tab.on{color:var(--accent-ink);border-bottom-color:var(--accent-ink)}
/* Cuerpo */
.modal.modal-task .modal-body{flex:1 1 auto;min-height:0;max-height:none;overflow:auto;padding:16px clamp(16px,3vw,48px) 34px}
/* Footer (Eliminar · Imprimir · Cerrar · Guardar) alineado al mismo ancho centrado */
.modal.modal-task .modal-foot{flex:0 0 auto;padding:14px max(clamp(16px,3vw,48px), (100% - var(--form-w))/2)}
/* Estilo COHERENTE de etiquetas y secciones en TODOS los paneles (Datos, Ficha, Devolución, etc.) */
.modal.modal-task .field>label{font-size:12px;text-transform:none;letter-spacing:0;color:var(--text-dim);font-weight:var(--fw-semi)}
.modal.modal-task .f-sec{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);text-transform:uppercase;color:var(--text);font-size:11px;letter-spacing:.14em;margin:6px 0 2px;padding:0 0 6px;border-top:0;border-bottom:1.5px solid var(--border-strong)}
/* Panel DATOS: secciones a lo ancho; campos en filas tipo ficha repartidas en columnas */
.modal.modal-task .mpanel.on[data-panel="datos"]{display:grid;grid-template-columns:1fr 1fr;gap:0 48px;align-content:start;max-width:var(--form-w);margin:0 auto;width:100%}
.modal.modal-task .mpanel[data-panel="datos"] .grid2{display:contents}
.modal.modal-task .mpanel[data-panel="datos"] .modal-idline{display:none}
.modal.modal-task .mpanel[data-panel="datos"] .field{display:grid;grid-template-columns:128px minmax(0,1fr);align-items:center;column-gap:14px;row-gap:2px;margin:0;padding:7px 0;border-bottom:1px solid var(--border);min-width:0}
.modal.modal-task .mpanel[data-panel="datos"] .field>label{font-size:12px;text-transform:none;letter-spacing:0;color:var(--text-dim);font-weight:var(--fw-semi);margin:0}
.modal.modal-task .mpanel[data-panel="datos"] .field .inp,
.modal.modal-task .mpanel[data-panel="datos"] .field .sel{padding:7px 10px;border-radius:var(--radius);font-size:12.5px}
.modal.modal-task .mpanel[data-panel="datos"] .ro-val{font-size:12.5px}
/* Estado en vivo de la caja elegida, debajo del campo. Vacío no ocupa lugar: sólo aparece cuando
   lo escrito corresponde a una caja de verdad. En el panel «datos» los campos son una grilla de
   dos columnas, así que hay que mandarlo a la segunda o se mete abajo de la etiqueta. */
.caja-vivo{font-size:12px;color:var(--text-dim);line-height:1.55}
.caja-vivo:empty{display:none}
.modal.modal-task .mpanel[data-panel="datos"] .field > .caja-vivo{grid-column:2}
/* secciones y avisos a lo ancho */
.modal.modal-task .mpanel[data-panel="datos"] .f-sec,
.modal.modal-task .mpanel[data-panel="datos"] .tec-hint,
.modal.modal-task .mpanel[data-panel="datos"] .motivo-note,
.modal.modal-task .mpanel[data-panel="datos"] #f_clienteWrap{grid-column:1 / -1}
.modal.modal-task .mpanel[data-panel="datos"] .f-sec{margin:15px 0 2px;padding:0 0 6px;border-top:0;border-bottom:1.5px solid var(--border-strong);color:var(--text);font-size:11px;letter-spacing:.14em}
/* Título: fila ficha a lo ancho */
.modal.modal-task .mpanel[data-panel="datos"] .mt-span{grid-column:1 / -1;display:grid;grid-template-columns:128px minmax(0,1fr);align-items:center;column-gap:14px;padding:8px 0;border-bottom:1px solid var(--border)}
.modal.modal-task .mpanel[data-panel="datos"] .mt-span>label{font-size:12px;text-transform:none;letter-spacing:0;color:var(--text-dim);font-weight:var(--fw-semi);margin:0}
/* campos "bloque" (a todo el ancho, etiqueta arriba): cuadrillas, dependencias, mapa, ticket pendiente */
.modal.modal-task .mpanel[data-panel="datos"] .field:has(.map-actions),
.modal.modal-task .mpanel[data-panel="datos"] .field:has(.chk-recoord),
.modal.modal-task .mpanel[data-panel="datos"] .field:has(.tecs-pick),
.modal.modal-task .mpanel[data-panel="datos"] .field:has(#f_deps),
.modal.modal-task .mpanel[data-panel="datos"] .field:has(#f_tickets),
.modal.modal-task .mpanel[data-panel="datos"] .field:has(#f_mtec),
.modal.modal-task .mpanel[data-panel="datos"] .field:has(#f_grupos){grid-column:1 / -1;display:block;border-bottom:0;padding:9px 0}
.modal.modal-task .mpanel[data-panel="datos"] .field:has(#f_deps)>label,
.modal.modal-task .mpanel[data-panel="datos"] .field:has(#f_mtec)>label,
.modal.modal-task .mpanel[data-panel="datos"] .field:has(#f_grupos)>label,
.modal.modal-task .mpanel[data-panel="datos"] .field:has(.chk-recoord)>label{margin-bottom:6px}
/* otras pestañas (Ficha técnica, Devolución, Imágenes, Bitácora): mismo look, columna centrada y prolija */
.modal.modal-task .mpanel:not([data-panel="datos"]){max-width:var(--form-w);margin:0 auto;width:100%;gap:14px}
.modal.modal-task .mpanel:not([data-panel="datos"]) .field>label{margin-bottom:5px}
.modal.modal-task .mpanel:not([data-panel="datos"]) .ta{min-height:96px}
@media(max-width:620px){
  .modal.modal-task .mpanel.on[data-panel="datos"]{grid-template-columns:1fr;gap:0}
  .modal.modal-task .mpanel[data-panel="datos"] .field,
  .modal.modal-task .mpanel[data-panel="datos"] .mt-span{grid-template-columns:104px minmax(0,1fr)}
  .mt-top .mt-top-title{white-space:normal}
}
/* Botón compacto "Abrir ..." (ticket / mapa) */
.btn-open{display:inline-flex;align-items:center;gap:5px;font-size:12px;font-weight:var(--fw-semi);color:var(--accent-ink);background:color-mix(in srgb,var(--signal) 12%,transparent);border:1px solid color-mix(in srgb,var(--signal) 36%,transparent);border-radius:var(--radius-sm);padding:4px 9px;white-space:nowrap;flex:0 0 auto;width:auto;cursor:pointer}
.btn-open:hover{background:color-mix(in srgb,var(--signal) 22%,transparent)}
.btn-open svg{width:13px;height:13px;flex:0 0 auto}
.btn-open.btn-open-ic{padding:6px}
.maps-open-row{display:flex;flex-wrap:wrap;gap:6px;margin-top:6px}
/* Lista de tickets (varios por tarea) */
.tk-list{display:flex;flex-direction:column;gap:8px}
.tk-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.tk-row .tk-num{flex:0 0 140px}
.tk-row .tk-tipo{flex:1 1 200px;min-width:0}
.tk-row .tk-url{flex:1 1 180px;min-width:0}
.tk-row .tk-open{flex:0 0 auto;display:flex}
.tk-rotipo{font-size:12px;color:var(--text-dim);border:1px solid var(--border);border-radius:var(--radius-sm);padding:1px 8px}
.tk-choose{display:flex;flex-direction:column;gap:8px}
.tk-choose .tkc{justify-content:flex-start;gap:8px}
.tk-rm{flex:0 0 auto;width:30px;height:30px;border-radius:var(--radius);background:var(--surface-2);border:1px solid var(--border);color:var(--text-faint);font-size:12.5px;cursor:pointer}
.tk-rm:hover{color:var(--red);border-color:var(--red)}
.tk-row.ro{gap:10px}
.tk-row.ro .tk-ronum{font-family:'IBM Plex Mono';font-size:12.5px;color:var(--text)}
.tk-ronum.tk-nonum{color:var(--text-faint);font-style:italic}
.tk-add{align-self:flex-start;margin-top:4px}
@media(max-width:560px){ .tk-row .tk-num{flex:1 1 110px} }
/* ===== Demás modales (#uiDialog): mismo lenguaje visual que el formulario de tarea ===== */
#uiScrim .modal{background:var(--bg)}
/* Encabezado igual que el del formulario de tarea: barra de acento + subtítulo + título */
#uiScrim .modal-head{display:flex;align-items:center;gap:13px;background:var(--surface);border-bottom:1px solid var(--border);padding:13px 20px}
#uiScrim .modal-head::before{content:'';flex:0 0 auto;width:4px;align-self:stretch;min-height:30px;border-radius:var(--radius-sm);background:var(--accent-ink)}
#uiScrim .modal-head .grow{flex:1;min-width:0}
#uiScrim .modal-head h3{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:17px;letter-spacing:-.2px;margin:2px 0 0;line-height:1.2;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#uiScrim .modal-head .mh-id{font-family:'IBM Plex Mono';font-size:11px;color:var(--accent-ink);letter-spacing:.06em;text-transform:uppercase}
#uiScrim .modal-body{padding:14px 22px;gap:0}
/* si el diálogo tiene widgets propios (equipo, OLT, agenda, permisos, etc.) NO se toca su layout: se restaura el espaciado */
#uiScrim .modal-body:has(.eq-grid),#uiScrim .modal-body:has(.dbt-wrap),#uiScrim .modal-body:has(.ad-list),#uiScrim .modal-body:has(.ad-newbox),#uiScrim .modal-body:has(.aps-row),#uiScrim .modal-body:has(.wn-block),#uiScrim .modal-body:has(.amod),#uiScrim .modal-body:has(.so-chks){gap:14px}
/* campos simples → filas tipo ficha (etiqueta a la izquierda + divisoria) */
#uiScrim .modal-body > .grid2{display:flex;flex-direction:column;gap:0}
#uiScrim .modal-body > .field,
#uiScrim .modal-body > .grid2 > .field{display:grid;grid-template-columns:140px minmax(0,1fr);align-items:center;column-gap:14px;row-gap:3px;margin:0;padding:9px 0;border-bottom:1px solid var(--border)}
#uiScrim .modal-body > .field:last-child,#uiScrim .modal-body > .grid2 > .field:last-child{border-bottom:0}
#uiScrim .modal-body .field > label{font-size:12px;text-transform:none;letter-spacing:0;color:var(--text-dim);font-weight:var(--fw-semi)}
#uiScrim .modal-body .field .inp,#uiScrim .modal-body .field .sel{padding:8px 10px;border-radius:var(--radius);font-size:12.5px}
/* campos que van a lo ancho con etiqueta arriba: textareas, checkboxes */
#uiScrim .modal-body > .field:has(.ta),
#uiScrim .modal-body > .field:has(.chk-line),
#uiScrim .modal-body > .field:has(label.chk-line){display:block;border-bottom:0}
#uiScrim .modal-body > .field:has(.ta) > label,#uiScrim .modal-body > .field:has(label.chk-line) > label{margin-bottom:6px}
#uiScrim .modal-body .f-sec{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);text-transform:uppercase;color:var(--text);font-size:11px;letter-spacing:.14em;margin:8px 0 2px;padding:0 0 6px;border-top:0;border-bottom:1.5px solid var(--border-strong)}
#uiScrim .modal-foot{background:var(--surface);border-top:1px solid var(--border)}
@media(max-width:560px){
  #uiScrim .modal-body > .field,
  #uiScrim .modal-body > .grid2 > .field{grid-template-columns:1fr;align-items:stretch;row-gap:5px}
}
/* ===== Anotaciones: dejar su tablero y sus popups como ANTES (sin el rediseño) ===== */
.note-col{background:linear-gradient(180deg,var(--surface),var(--bg-2))}
#uiScrim .modal:has(.nremind),#uiScrim .modal:has(.amod),#uiScrim .modal:has(.ad-newbox){width:min(440px,100%)!important}
#uiScrim .modal:has(.nremind) .modal-head,#uiScrim .modal:has(.amod) .modal-head,#uiScrim .modal:has(.ad-newbox) .modal-head{background:var(--bg-2);padding:16px 22px 14px;gap:8px}
#uiScrim .modal:has(.nremind) .modal-head::before,#uiScrim .modal:has(.amod) .modal-head::before,#uiScrim .modal:has(.ad-newbox) .modal-head::before{display:none}
#uiScrim .modal:has(.nremind) .modal-head h3,#uiScrim .modal:has(.amod) .modal-head h3,#uiScrim .modal:has(.ad-newbox) .modal-head h3{font-size:18px;margin-top:3px}
#uiScrim .modal:has(.nremind) .modal-head .mh-id,#uiScrim .modal:has(.amod) .modal-head .mh-id,#uiScrim .modal:has(.ad-newbox) .modal-head .mh-id{text-transform:none;color:var(--text-faint)}
#uiScrim .modal:has(.nremind) .modal-body,#uiScrim .modal:has(.amod) .modal-body,#uiScrim .modal:has(.ad-newbox) .modal-body{padding:20px 22px;gap:18px}
#uiScrim .modal:has(.nremind) .modal-body > .field,#uiScrim .modal:has(.amod) .modal-body > .field,#uiScrim .modal:has(.ad-newbox) .modal-body > .field{display:flex;flex-direction:column;gap:7px;border-bottom:0;padding:0;grid-template-columns:none}
#uiScrim .modal:has(.nremind) .modal-body .field>label,#uiScrim .modal:has(.amod) .modal-body .field>label,#uiScrim .modal:has(.ad-newbox) .modal-body .field>label{font-size:11px;text-transform:uppercase;letter-spacing:.13em;color:var(--text-faint);font-weight:var(--fw-semi)}
#uiScrim .modal:has(.nremind) .modal-foot,#uiScrim .modal:has(.amod) .modal-foot,#uiScrim .modal:has(.ad-newbox) .modal-foot{background:var(--bg-2)}
.mpanel[data-panel="datos"]{gap:11px}
.f-sec{font-family:'IBM Plex Sans';font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--text-faint);font-weight:var(--fw-bold);margin:4px 0 -1px;padding-top:11px;border-top:1px solid var(--border)}
.inp,.ta,.sel{
  background:var(--surface-2);border:1px solid var(--border);color:var(--text);
  padding:10px 12px;border-radius:var(--radius);font-size:12.5px;transition:.15s;width:100%;
}
.inp:focus,.ta:focus,.sel:focus{outline:none;border-color:var(--accent-ink);background:var(--surface)}
/* campos bloqueados = solo lectura: se ven como texto plano (no como caja editable) */
.inp:disabled,.ta:disabled,.sel:disabled{opacity:1;background:transparent;border-color:transparent;color:var(--text-dim);cursor:default;padding-left:2px;padding-right:2px}
.sel:disabled{background-image:none}
.field > label.chk-line input:disabled{opacity:.45}
.tec-hint{display:flex;align-items:flex-start;gap:8px;font-size:12px;color:var(--text-dim);background:rgba(147,37,90,.08);border:1px solid rgba(147,37,90,.32);border-radius:var(--radius);padding:10px 12px;line-height:1.45}
.tec-hint svg{flex:0 0 auto;margin-top:1px;color:var(--accent-ink)}
.tec-hint b{color:var(--text)}
.ta{resize:vertical;min-height:74px;line-height:1.55}
.ta-tall{min-height:118px}
.field > label.chk-line{display:flex;align-items:center;gap:9px;font-size:12.5px;letter-spacing:0;text-transform:none;color:var(--text);font-weight:var(--fw-medium);cursor:pointer}
.chk-line input{width:16px;height:16px;flex:0 0 auto;cursor:pointer;accent-color:var(--accent-ink)}
.chk-line + .chk-line{margin-top:9px}
.chk-sub{color:var(--text-faint);font-weight:var(--fw-normal);font-size:12px}
.chk-blk{color:var(--red);font-weight:var(--fw-semi)}
.chk-blk input{accent-color:var(--red)}
.lbl-sub{color:var(--text-faint);font-weight:var(--fw-normal);font-size:12px}
.pasos-list{display:flex;flex-direction:column;gap:7px}
.paso-row{display:flex;align-items:flex-start;gap:7px;border-radius:var(--radius)}
.paso-row.dragging{opacity:.4}
.paso-row.drop-above{box-shadow:inset 0 3px 0 -1px var(--accent-ink)}
.paso-row.drop-below{box-shadow:inset 0 -3px 0 -1px var(--accent-ink)}
.paso-grip{flex:0 0 auto;display:flex;align-items:center;justify-content:center;width:24px;height:38px;color:var(--text-faint);cursor:grab;border-radius:var(--radius-sm);transition:.12s}
.paso-grip:hover{color:var(--text);background:var(--surface-3)}
.paso-grip:active{cursor:grabbing}
.paso-grip svg{width:17px;height:17px}
.paso-chk{flex:0 0 auto;width:17px;height:17px;margin-top:11px;accent-color:var(--accent-ink);cursor:pointer}
.paso-n{flex:0 0 auto;font-size:12.5px;font-weight:var(--fw-bold);color:var(--text-dim);min-width:50px;padding-top:10px}
.paso-row.done .paso-n{text-decoration:line-through;color:var(--text-faint)}
.paso-row.done .paso-inp{color:var(--text-faint)}
.paso-row .paso-inp{flex:1 1 auto;resize:none;overflow:hidden;min-height:0;line-height:1.45}
.paso-x{flex:0 0 auto;width:26px;height:26px;margin-top:5px;border:none;background:none;color:var(--text-faint);cursor:pointer;border-radius:var(--radius-sm);font-size:12.5px}
.paso-x:hover{color:var(--red);background:var(--surface-3)}
.btn.paso-add{gap:7px;justify-content:center}
.btn.paso-add svg{width:16px;height:16px}
.sel{appearance:none;cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%2394a0b8' stroke-width='2'%3E%3Cpath d='M3 5l3 3 3-3'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 12px center;padding-right:32px}

/* checklist */
.chk-add{display:flex;gap:8px}
.chk-list{display:flex;flex-direction:column;gap:7px}
.chk-item{display:flex;align-items:center;gap:10px;padding:9px 11px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);transition:.15s}
.chk-item:hover{border-color:var(--border-strong)}
.chk-box{width:19px;height:19px;border-radius:var(--radius-sm);border:1.5px solid var(--border-strong);display:grid;place-items:center;flex:0 0 auto;transition:.15s;color:transparent}
.chk-box.on{background:var(--signal);border-color:var(--accent-ink);color:var(--on-signal)}
.chk-box svg{width:12px;height:12px}
.chk-item .tx{flex:1;font-size:12.5px}
.chk-item.done .tx{text-decoration:line-through;color:var(--text-faint)}
.chk-del{color:var(--text-faint);opacity:0;transition:.15s}
.chk-item:hover .chk-del{opacity:1}
.chk-del:hover{color:var(--red)}

/* bitácora */
.log-add{display:flex;gap:8px}
.log-list{display:flex;flex-direction:column;gap:10px}
.log-entry{display:flex;gap:11px}
.log-entry .avatar{width:30px;height:30px;border-radius:var(--radius);font-size:11px;flex:0 0 auto}
.log-bubble{flex:1;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:9px 12px}
.log-bubble .lh{display:flex;align-items:baseline;gap:8px;margin-bottom:3px}
.log-bubble .lh .a{font-size:12.5px;font-weight:var(--fw-semi)}
.log-bubble .lh .t{font-size:11px;color:var(--text-faint);font-family:'IBM Plex Mono'}
.log-bubble .lt{font-size:12.5px;color:var(--text-dim);line-height:1.5}
.log-entry.sys .log-bubble{background:transparent;border-style:dashed}
.log-entry.sys .lt{font-style:italic;color:var(--text-faint)}

.modal-foot{display:flex;align-items:center;gap:10px;padding:16px 22px;border-top:1px solid var(--border);background:var(--bg-2)}
.modal-foot .grow{flex:1}
.btn-danger{background:rgba(255,91,110,.1);border:1px solid rgba(255,91,110,.3);color:var(--red)}
.btn-danger:hover{background:rgba(255,91,110,.18)}
.iconinput{display:flex;gap:8px}

.empty-hint{font-size:12.5px;color:var(--text-faint);font-style:italic;text-align:center;padding:10px}

@keyframes rise{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:none}}

/* ====================== VIEW SWITCH ====================== */
/* SOLAPAS CLÁSICAS: sin caja y sin relleno. La activa se marca con la línea de abajo, que es como
   lo hace un sistema de escritorio. */
.area-switch{display:flex;background:transparent;border:0;border-bottom:1px solid var(--border-strong);border-radius:0;padding:0;gap:0}
.area-switch button{display:flex;align-items:center;gap:7px;padding:6px 14px;font-size:12.5px;background:transparent;border:0;border-bottom:2px solid transparent;border-radius:0;color:var(--text-dim);font-weight:var(--fw-normal);transition:none}
.area-switch button svg{width:16px;height:16px}
.area-switch button.on{background:transparent;color:var(--text);font-weight:var(--fw-semi);border-bottom-color:var(--accent-ink);box-shadow:none}
.area-switch button:not(.on):hover{color:var(--text)}
.area-mobtrig{display:none}
@media(max-width:760px){
  .area-mobtrig{display:flex;align-items:center;gap:8px;width:100%;padding:11px 13px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);color:var(--text);font-size:14px;font-weight:var(--fw-bold);cursor:pointer}
  .area-mobtrig>svg:first-child{width:18px;height:18px;flex:0 0 auto;color:var(--accent-ink)}
  .area-mobtrig .amt-chev{width:18px;height:18px;margin-left:auto;color:var(--text-dim);transition:transform .18s}
  .area-mobtrig.open .amt-chev{transform:rotate(180deg)}
  #areaSwitch{display:none;flex-direction:column;flex-wrap:nowrap;gap:3px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:6px;margin-top:6px;max-width:100%}
  #areaSwitch.area-open{display:flex}
  #areaSwitch button{width:100%;justify-content:flex-start;padding:12px 12px;font-size:14px;height:auto}
  #flBar{flex-wrap:wrap;gap:8px} #flBar>.area-mobtrig,#flBar>#areaSwitch{flex:1 1 100%;order:-1}
}
.view-switch{display:flex;background:transparent;border:0;border-bottom:1px solid var(--border-strong);border-radius:0;padding:0;gap:0}
.view-switch button{display:flex;align-items:center;gap:7px;padding:6px 13px;font-size:12.5px;background:transparent;border:0;border-bottom:2px solid transparent;border-radius:0;color:var(--text-dim);font-weight:var(--fw-normal);transition:none}
/* par de acciones (Nueva tarea / Nuevo proyecto): mismo estilo que el view-switch, ambos igual color */
.act-switch{display:flex;align-items:center;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:3px;gap:2px;height:36px;align-self:center}
.act-switch button{display:flex;align-items:center;gap:7px;height:100%;padding:0 13px;border-radius:var(--radius-sm);font-size:12.5px;font-weight:var(--fw-semi);color:var(--text);transition:.15s;white-space:nowrap}
.act-switch button:hover{background:var(--surface-3)}
.act-switch button svg{width:16px;height:16px}
.view-switch button svg{width:15px;height:15px}
.view-switch button.on{background:transparent;color:var(--text);font-weight:var(--fw-semi);border-bottom-color:var(--accent-ink);box-shadow:none}
.view-switch button.on svg{color:var(--on-signal)}
.view-switch button:not(.on):hover{color:var(--text)}

/* barra superior: todos los controles al mismo alto (36px) y estilo parejo */
.topbar .area-switch, .topbar .view-switch{height:36px}
.topbar .area-switch button, .topbar .view-switch button{height:100%;padding-top:0;padding-bottom:0}
.topbar .btn{height:36px;padding:0 16px}
.topbar .btn-primary{box-shadow:none}
.topbar .icon-btn{width:36px;height:36px}

/* nav de la barra superior: pastillero + overflow con flechita (en vez de bajar a 2 filas) */
@media(min-width:900px){ .topbar{flex-wrap:nowrap} #viewSwitch{overflow:hidden;min-width:0} }
.vs-more-wrap{display:none;align-items:stretch;flex:0 0 auto}
.vs-more-wrap.show{display:flex}
.vs-more{display:flex;align-items:center;justify-content:center;height:100%;padding:0 9px;border-radius:var(--radius-sm);color:var(--text-dim);font-weight:var(--fw-semi)}
.vs-more:hover{color:var(--text);background:var(--surface-3)}
.vs-more.on{background:var(--selected);color:var(--text);border-color:var(--accent-ink)}
.vs-more svg{width:15px;height:15px}
.vs-ov{position:fixed;display:none;flex-direction:column;gap:2px;min-width:194px;background:var(--surface);border:1px solid var(--border-strong);border-radius:var(--radius);padding:6px;z-index:660;box-shadow:0 18px 44px -14px rgba(0,0,0,.6)}
.vs-ov.open{display:flex}
#viewSwitch .vs-ov>button{height:auto;width:100%;justify-content:flex-start;border-radius:var(--radius);padding:9px 11px;color:var(--text-dim)}
#viewSwitch .vs-ov>button svg{display:inline;width:16px;height:16px}
#viewSwitch .vs-ov>button:hover{background:var(--surface-2);color:var(--text)}
#viewSwitch .vs-ov>button.on{background:var(--selected);color:var(--text);border-color:var(--accent-ink)}
#viewSwitch .vs-ov>button.on svg{color:var(--on-signal)}
/* acciones consolidadas en el menú del avatar: ocultar íconos sueltos duplicados */
.topbar>#logoutBtn{display:none}

/* título de la vista en la barra (solo visible en modo lateral) */
.top-title{display:none;font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:17px;letter-spacing:-.3px;color:var(--text)}
/* ===== Modo barra lateral (conmutable desde el menú del avatar) ===== */
#sideNav{display:none}
/* En el menú ancho manda el nombre: el ícono del grupo sólo hace falta donde el nombre no entra, o
   sea en el riel angosto. Fuera de ahí no se muestra —y eso hay que decirlo en una regla GLOBAL.
   Estaba dentro de `@media(min-width:900px)`, así que en el celular no había NINGUNA regla que lo
   tocara, y un SVG sin ancho ni alto se dibuja en su tamaño por defecto: 300×150 px. */
#sideNav .sn-gico{display:none;width:18px;height:18px;flex:0 0 auto}
@media(min-width:900px){
  /* EL MISMO COLOR QUE LA PANTALLA, con el token del fondo. Estaba escrito a mano en #191d27:
     distinto del cuerpo en los dos temas y, encima, azulado —39 de azul contra 33 de rojo— cuando
     todos los grises del sistema son neutros. Era un resto del estilo anterior que la migración no
     alcanzó porque no era un token. */
  /* El fondo sale de `--rail` y no de `--bg`: medio escalon aparte del cuerpo, para que el menu se
     lea como el marco. La linea sigue estando; esto se suma, no la reemplaza. */
  body.nav-side #sideNav{display:flex;flex-direction:column;position:fixed;left:0;top:0;bottom:0;width:252px;z-index:45;background:var(--rail);border-right:1px solid var(--border);padding:12px 12px 16px;overflow:hidden}
  #sideNav .sn-nav{flex:1;min-height:0;overflow-y:auto;overflow-x:hidden}
  /* La regla que ponía el menú en blanco para tema claro ya no hace falta: existía para tapar el
     hexadecimal fijo, y ahora el color sale del token, que cambia solo. */
  body.nav-side #app{padding-left:252px}
  /* Riel de íconos: el estado normal. Cuesta 64 px, que en el tablero son 13 px por columna. */
  body.nav-side.nav-rail #sideNav{width:64px;padding:12px 8px 16px;overflow:visible;transition:width .15s ease,padding .15s ease}
  body.nav-side.nav-rail #app{padding-left:64px}
  /* ASOMARSE AL PASAR EL MOUSE. El contenido se corre junto con el menú en vez de quedar tapado
     detrás: se probó de las dos formas y lo que se pierde de vista molesta más que el movimiento.
     Las dos transiciones usan la misma duración para que se muevan juntas y no una atrás de la otra. */
  body.nav-side.nav-rail.nav-peek #sideNav{width:252px;padding:12px 12px 16px;overflow:hidden;
    box-shadow:8px 0 34px rgba(0,0,0,.34)}
  body.nav-side.nav-rail #app{transition:padding-left .15s ease}
  body.nav-side.nav-rail.nav-peek #app{padding-left:252px}
  @media (prefers-reduced-motion: reduce){
    body.nav-side.nav-rail #sideNav, body.nav-side.nav-rail #app{transition:none}
  }
  body.nav-side.nav-rail:not(.nav-peek) #sideNav .sn-item span,
  body.nav-side.nav-rail:not(.nav-peek) #sideNav .sn-brand h1{display:none}
  /* Compacto a propósito: con 22 destinos, así el riel entra entero en una pantalla de 1080p sin scroll. */
  body.nav-side.nav-rail:not(.nav-peek) #sideNav .sn-item{justify-content:center;padding:4px 0;position:relative}
  body.nav-side.nav-rail #sideNav .sn-sep{margin:4px 6px}
  body.nav-side.nav-rail:not(.nav-peek) #sideNav .sn-brand{padding:4px 0 8px;justify-content:center}
  body.nav-side.nav-rail #sideNav .sn-pie{padding-top:6px;margin-top:6px}
  /* el nombre del ícono se dibuja flotando (ver .sn-tip), fuera del menú, para que no lo recorte el scroll */
  /* Modo enfoque: sin menú, para el tablero en pantalla chica o en el televisor */
  body.nav-focus #sideNav{display:none}
  body.nav-side.nav-focus #app{padding-left:0}   /* dos clases, para ganarle a la regla del riel */
  #sideNav .sn-pie{flex:0 0 auto;padding-top:8px;border-top:1px solid var(--border);margin-top:8px}
  #sideNav .sn-toggle{margin-top:0}
  /* Grupos plegables: el encabezado abre y cierra su lista. Sólo en el menú ancho. */
  #sideNav .sn-group{display:flex;align-items:center;gap:6px;width:100%;background:transparent;border:0;cursor:pointer;text-align:left}
  #sideNav .sn-group:hover{color:var(--text-dim)}
  #sideNav .sn-group .sn-chev{margin-left:auto;width:13px;height:13px;flex:0 0 auto;transition:transform .16s ease;opacity:.65}
  #sideNav .sn-g.open .sn-group .sn-chev{transform:rotate(90deg)}
  #sideNav .sn-items{display:none;flex-direction:column;gap:2px}
  #sideNav .sn-g.open .sn-items{display:flex}
  /* EL RIEL RESPETA LOS GRUPOS, igual que el menú ancho. Antes mostraba TODOS los íconos, y estaba
     bien argumentado: con 22 destinos entraban en una pantalla de 1080p sin scroll, así que «se ven
     todos» era verdad y valía la pena. Con 61 el contenido mide 1.749 px contra 731 visibles: hay
     que scrollear igual, así que ya no se ven todos y lo único que queda es la tira larga.
     El encabezado del grupo se muestra como ÍCONO —clickeable— para poder abrir otro sin salir del
     riel; el nombre y la flecha se esconden porque no entran. */
  body.nav-side.nav-rail:not(.nav-peek) #sideNav .sn-group{display:flex;justify-content:center;padding:5px 0}
  body.nav-side.nav-rail:not(.nav-peek) #sideNav .sn-gico{display:block}
  body.nav-side.nav-rail:not(.nav-peek) #sideNav .sn-gico{width:16px;height:16px;opacity:.55}
  body.nav-side.nav-rail:not(.nav-peek) #sideNav .sn-group:hover .sn-gico,
  body.nav-side.nav-rail:not(.nav-peek) #sideNav .sn-g.open .sn-gico{opacity:1}
  body.nav-side.nav-rail:not(.nav-peek) #sideNav .sn-gtxt,
  body.nav-side.nav-rail:not(.nav-peek) #sideNav .sn-group .sn-chev{display:none}
  /* El grupo abierto se marca con una línea al costado: sin el nombre, es lo único que dice cuál es. */
  body.nav-side.nav-rail:not(.nav-peek) #sideNav .sn-g.open .sn-group{color:var(--accent-ink);
    box-shadow:inset 2px 0 0 var(--accent-ink)}
  /* Buscador de funciones: encuentra cualquier pantalla del sistema por nombre o por sinónimo. */
  #sideNav .sn-find{position:relative;flex:0 0 auto;margin:0 2px 8px}
  #sideNav .sn-find input{width:100%;box-sizing:border-box;background:var(--surface-2);border:1px solid var(--border);
    border-radius:var(--radius);color:var(--text);padding:8px 10px 8px 32px;font-size:12.5px;font-family:inherit;outline:none}
  #sideNav .sn-find input::placeholder{color:var(--text-faint)}
  #sideNav .sn-find input:focus{border-color:var(--accent-ink)}
  #sideNav .sn-find svg{position:absolute;left:10px;top:50%;transform:translateY(-50%);width:15px;height:15px;color:var(--text-faint);pointer-events:none}
  #sideNav .sn-item small{display:block;font-size:11px;font-weight:var(--fw-semi);color:var(--text-faint);text-transform:uppercase;letter-spacing:.06em;margin-top:1px}
  #sideNav .sn-item .sn-txt{min-width:0}
  #sideNav .sn-nada{padding:16px 10px;font-size:12.5px;color:var(--text-faint);text-align:center}
  /* En el riel el campo se reduce a la lupa: al tocarla se ensancha el menú y queda listo para escribir. */
  body.nav-side.nav-rail:not(.nav-peek) #sideNav .sn-find input{padding:8px 0;text-indent:-9999px;cursor:pointer}
  body.nav-side.nav-rail:not(.nav-peek) #sideNav .sn-find svg{left:50%;transform:translate(-50%,-50%)}
  #sideNav .sn-sep{height:1px;background:var(--border);margin:6px 4px;opacity:.6}
  /* SE VE. Antes era a propósito discreto —«es una preferencia, no un destino»— y tenía sentido
     mientras el menú se asomaba solo al pasar el mouse: casi nunca hacía falta tocarlo. Desde que
     se sacó el asomado (25/08/2026) este botón es la ÚNICA forma de ver los nombres de los destinos,
     así que esconderlo es esconder la única llave. Va con recuadro, fondo propio y color de acento. */
  /* Discreto a propósito: es una preferencia de cómo se ve el menú, no una acción del trabajo.
     Vestido de acción principal (fondo, borde y texto en el acento) competía con lo que sí importa. */
  #sideNav .sn-toggle{margin-top:auto;display:flex;align-items:center;gap:9px;width:100%;box-sizing:border-box;
    background:transparent;border:1px solid var(--border);
    border-radius:var(--radius);color:var(--text-dim);padding:9px 10px;cursor:pointer;font-size:12.5px;font-weight:var(--fw-medium);
    font-family:inherit;transition:background .15s ease,border-color .15s ease,color .15s ease}
  #sideNav .sn-toggle svg{width:17px;height:17px;flex:0 0 auto;transition:transform .18s ease}
  #sideNav .sn-toggle:hover{background:var(--surface-2);border-color:var(--border-strong);color:var(--text)}
  #sideNav .sn-toggle:active{transform:translateY(1px)}
  /* La flecha apunta hacia donde va a ir el menú: al riel señala a la derecha (ensanchar),
     y con el menú ancho señala a la izquierda (angostar). */
  body.nav-side.nav-rail #sideNav .sn-toggle svg{transform:rotate(180deg)}
  body.nav-side.nav-rail:not(.nav-peek) #sideNav .sn-toggle{justify-content:center;padding:9px 0}
  body.nav-side.nav-rail:not(.nav-peek) #sideNav .sn-toggle span{display:none}

  body.nav-side .topbar>.brand,
  body.nav-side #viewSwitch,
  body.nav-side .topbar .divider{display:none}
  body.nav-side .top-title{display:block}
  #sideNav .sn-brand{display:flex;align-items:center;gap:11px;padding:6px 8px 10px}
  #sideNav .sn-brand .glyph{width:34px;height:34px;border-radius:var(--radius);display:grid;place-items:center;background:var(--signal);color:var(--on-signal);flex:0 0 auto}
  #sideNav .sn-brand .glyph svg{width:20px;height:20px}
  #sideNav .sn-brand h1{font-family:'Archivo';font-weight:var(--fw-max);font-size:17px;letter-spacing:-.4px}
  #sideNav .sn-brand h1 span{color:var(--accent-ink)}
  #sideNav .sn-nav{display:flex;flex-direction:column;gap:2px}
  /* Sin versales: en una columna de 252 px «ADMINISTRACIÓN» en mayúsculas llega al borde, y es lo
     mismo que ya se sacó de las cabeceras de las tablas y de los contadores. */
  #sideNav .sn-group{font-family:'IBM Plex Sans';font-size:12px;font-weight:var(--fw-semi);text-transform:none;letter-spacing:0;color:var(--text-dim);padding:9px 10px 5px}
  /* ENCABEZADOS DE GRUPO: que se vea dónde empieza cada sección.
     El problema no era que fueran chicos sino que nada marcaba el corte — treinta destinos seguidos
     con seis rótulos apagados en el medio se leen como una lista sola. La solución no es gritar más
     fuerte (eso ensucia un menú que se mira de reojo todo el día) sino marcar el límite: una línea
     fina arriba de cada grupo, aire para que respire, y algo más de contraste en el texto.
     En el riel angosto los rótulos se ocultan pero la línea queda, así los íconos siguen
     leyéndose agrupados en vez de como una tira continua. */
  /* UNA sola línea entre grupos: ya la dibuja el separador (.sn-sep) que pone navRender. Con el
     borde además, había dos líneas de 1 px y el menú se veía rayado. */
  #sideNav .sn-g{margin-top:3px}
  #sideNav .sn-g:first-of-type{border-top:0;margin-top:0}
  #sideNav .sn-group{padding:13px 10px 6px;color:color-mix(in srgb, var(--text) 55%, var(--text-dim))}
  /* El hover de antes ponía el color MÁS apagado que el estado normal, así que no hacía nada. */
  #sideNav .sn-group:hover{color:var(--text)}
  /* El grupo abierto subia a full brillo, y ahi el rotulo terminaba gritando igual que los
     destinos que anuncia. Ya se sabe cual esta abierto: se ve por los destinos desplegados abajo y
     por la flecha. Con un escalon alcanza. */
  #sideNav .sn-g.open>.sn-group{color:color-mix(in srgb, var(--text) 72%, var(--text-dim))}
  /* El menú se lee de reojo todo el día: acá gana la legibilidad sobre el gris del resto del sistema. */
/* Los 19 destinos estaban TODOS en semibold, asi que el peso no distinguia nada y el activo se
   apoyaba solo en el color y el fondo. Bajando el resto a 500, el activo queda como lo unico en
   semibold del menu: se encuentra sin buscarlo. El tamanio no se toca — el menu esta justo al
   limite de alto y crecer obligaria a scrollear para llegar a Configuracion y Ayuda. */
#sideNav .sn-item{display:flex;align-items:center;gap:11px;width:100%;padding:7px 11px;border-radius:var(--radius);font-size:14px;font-weight:var(--fw-medium);color:var(--text);text-align:left;position:relative;transition:.14s}
  #sideNav .sn-item svg{width:17px;height:17px;flex:0 0 auto}
  #sideNav .sn-item:hover{background:var(--surface-2);color:var(--text)}
  #sideNav .sn-item svg{opacity:.85}
  #sideNav .sn-item.on svg,#sideNav .sn-item:hover svg{opacity:1}
  #sideNav .sn-item.on{background:color-mix(in srgb,var(--signal) 14%,transparent);color:var(--accent-ink);font-weight:var(--fw-semi)}
  #sideNav .sn-item.on::before{content:"";position:absolute;left:0;top:8px;bottom:8px;width:3px;border-radius:0 var(--radius-sm) var(--radius-sm) 0;background:var(--accent-ink)}
}
/* ===== Menú móvil: hamburguesa + cajón (drawer) — escala a cualquier cantidad de vistas ===== */
#navBurger{display:none;align-items:center;justify-content:center;width:38px;height:38px;border-radius:var(--radius);border:1px solid var(--border);background:var(--surface);color:var(--text);flex:0 0 auto;margin-right:10px}
#navBurger:active{background:var(--surface-2)}
#navBurger svg{width:21px;height:21px}
#navScrim{display:none}
@media(max-width:899px){
  #navBurger{display:inline-flex}
  #sideNav .sn-pie{display:none}   /* en el celular el cajón ocupa todo: angostar no aplica */
  .topbar>.brand{display:none}
  .topbar>#viewSwitch{display:none}
  .topbar .divider{display:none}
  .topbar .top-title{display:block;font-size:17px}
  /* Antes acá se ocultaba el título en los mapas, porque el selector de 3 mapas ya decía cuál era.
     Ese selector se sacó (los tres están en el menú lateral), así que el título vuelve: si no, en el
     celular los mapas quedaban sin ningún nombre arriba. */
  #themeBtn{display:none}   /* en el celular el cambio de tema está en el menú del perfil */
  #navScrim{display:block;position:fixed;inset:0;background:rgba(0,0,0,.55);z-index:1190;opacity:0;pointer-events:none;transition:opacity .2s}
  body.drawer-open #navScrim{opacity:1;pointer-events:auto}
  /* En el teléfono el menú NO está al lado del contenido: está ENCIMA, flotando con su sombra, así
     que acá sí corresponde que se despegue de lo que tapa. Pero con el token de superficie y no con
     un hexadecimal azulado. */
  #sideNav{display:flex;flex-direction:column;position:fixed;left:0;top:0;bottom:0;width:min(286px,86vw);z-index:1200;background:var(--surface);border-right:1px solid var(--border);padding:14px 12px calc(20px + env(safe-area-inset-bottom));overflow-y:auto;transform:translateX(-104%);transition:transform .22s ease;box-shadow:8px 0 44px rgba(0,0,0,.5)}
  html[data-theme="light"] #sideNav{background:var(--surface)}
  body.drawer-open #sideNav{transform:none}
  #sideNav .sn-brand{display:flex;align-items:center;gap:11px;padding:4px 8px 14px;margin-bottom:4px;border-bottom:1px solid var(--border)}
  #sideNav .sn-brand .glyph{width:34px;height:34px;border-radius:var(--radius);display:grid;place-items:center;background:var(--signal);color:var(--on-signal);flex:0 0 auto}
  #sideNav .sn-brand .glyph svg{width:20px;height:20px}
  #sideNav .sn-brand h1{font-family:'Archivo';font-weight:var(--fw-max);font-size:18px;letter-spacing:-.4px}
  #sideNav .sn-brand h1 span{color:var(--accent-ink)}
  #sideNav .sn-nav{display:flex;flex-direction:column;gap:3px}
  #sideNav .sn-group{font-family:'IBM Plex Sans';font-size:12px;font-weight:var(--fw-semi);text-transform:none;letter-spacing:0;color:var(--text-faint);padding:16px 10px 6px}
  #sideNav .sn-item{display:flex;align-items:center;gap:13px;width:100%;padding:13px 12px;border-radius:var(--radius);font-size:14px;font-weight:var(--fw-semi);color:var(--text-dim);text-align:left;position:relative}
  #sideNav .sn-item svg{width:20px;height:20px;flex:0 0 auto}
  #sideNav .sn-item.on{background:color-mix(in srgb,var(--signal) 16%,transparent);color:var(--accent-ink)}
  #sideNav .sn-item.on::before{content:"";position:absolute;left:0;top:9px;bottom:9px;width:3px;border-radius:0 var(--radius-sm) var(--radius-sm) 0;background:var(--accent-ink)}
}
.topbar .me{height:36px}

/* ====================== MAP VIEW ====================== */
#mapView{flex:1;display:none;overflow:hidden;position:relative}
#mapView.on{display:flex}
.map-aside-toggle{display:none;position:absolute;left:12px;top:12px;z-index:650;align-items:center;gap:7px;background:rgba(14,18,28,.94);border:1px solid var(--border);color:var(--text);padding:8px 12px;border-radius:var(--radius);font-size:12.5px;font-weight:var(--fw-semi);box-shadow:var(--shadow);cursor:pointer}
.ea-close{display:none;margin-left:auto;align-items:center;justify-content:center;background:transparent;border:0;color:var(--text-faint);cursor:pointer;padding:5px;border-radius:var(--radius)}
#earthZoomHint{position:absolute;left:50%;bottom:14px;transform:translateX(-50%);z-index:640;align-items:center;gap:6px;background:rgba(14,18,28,.94);border:1px solid var(--border);color:var(--text);padding:6px 12px;border-radius:var(--radius);font-size:12.5px;font-weight:var(--fw-semi);box-shadow:var(--shadow);pointer-events:none;white-space:nowrap}
.ea-close:hover{background:rgba(255,255,255,.08);color:var(--text)}
.map-aside-toggle svg{width:16px;height:16px}
.map-aside{
  flex:0 0 296px;display:flex;flex-direction:column;border-right:1px solid var(--border);
  background:var(--surface);overflow:hidden;
}
.map-aside-head{padding:16px 16px 12px;border-bottom:1px solid var(--border)}
.oz-brand{padding:0 4px 0;border:0}
.map-aside-head .sync{font-size:11px;color:var(--text-faint);margin-top:10px;font-family:'IBM Plex Mono'}
.import-btn{margin-top:12px;width:100%;justify-content:center}
.sector-list{flex:1;overflow-y:auto;padding:8px;display:flex;flex-direction:column;gap:2px}
.sector-label{font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--text-faint);font-weight:var(--fw-semi);padding:6px 10px 8px}
.sector-item{
  width:100%;text-align:left;padding:10px 12px;border-radius:var(--radius);border:0;
  background:transparent;cursor:pointer;transition:.12s;color:var(--text-dim);font-family:inherit;
}
.sector-item:hover{background:var(--surface-2);color:var(--text)}
.sector-item.on{background:color-mix(in srgb,var(--signal) 18%,var(--surface-2));color:var(--text);box-shadow:inset 3px 0 0 var(--accent-ink)}
.sector-item .sn{font-weight:var(--fw-bold);font-size:13.5px;display:flex;align-items:center;gap:8px}
.sector-item .sn .pin{width:7px;height:7px;border-radius:var(--radius-circ);background:var(--accent-ink);box-shadow:0 0 8px var(--accent-ink);flex:0 0 auto}
.sector-item .smeta{display:flex;gap:14px;margin-top:5px;font-size:11px;color:var(--text-faint)}
.sector-item .smeta b{color:var(--text-dim);font-weight:var(--fw-semi)}
.map-wrap{flex:1;position:relative}
#leaflet{position:absolute;inset:0;background:#0a0d14}
.map-legend{
  position:absolute;right:14px;bottom:14px;z-index:500;background:rgba(14,18,28,.92);
  border:1px solid var(--border);border-radius:var(--radius);padding:12px 14px;font-size:12px;box-shadow:var(--shadow);
  display:none;
}
.map-legend.shown{display:block}
.map-toggles{display:none;position:absolute;right:12px;top:12px;z-index:540;flex-direction:column;gap:8px}
.map-tg{width:38px;height:38px;border-radius:var(--radius);display:grid;place-items:center;background:rgba(14,18,28,.94);border:1px solid var(--border);color:var(--text-dim);cursor:pointer;box-shadow:var(--shadow)}
.map-tg svg{width:18px;height:18px}
.map-tg.on{background:var(--selected);color:var(--text);border-color:var(--accent-ink)}
.map-legend .lt{font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--text-faint);font-weight:var(--fw-semi);margin-bottom:8px}
.map-legend .lr{display:flex;align-items:center;gap:8px;margin-top:6px;color:var(--text-dim)}
.map-legend .ld{width:11px;height:11px;border-radius:var(--radius-circ);flex:0 0 auto}
.map-legend .ll{width:16px;height:3px;border-radius:var(--radius-sm);flex:0 0 auto}
.map-empty{position:absolute;inset:0;display:grid;place-items:center;z-index:400;text-align:center;color:var(--text-faint);padding:30px}
.map-empty .me-ttl{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:17px;color:var(--text-dim);margin-bottom:8px}

/* leaflet dark theme */
.leaflet-container{background:#0a0d14;font-family:'IBM Plex Sans',sans-serif}
.leaflet-tile{filter:none}
.leaflet-popup-content-wrapper,.leaflet-popup-tip{background:var(--surface-2);color:var(--text);border:1px solid var(--border-strong);box-shadow:var(--shadow)}
/* Sin relleno propio: cada franja del globo pone el suyo y las divisiones llegan
   de borde a borde, como las tablas del resto del sistema. */
.leaflet-popup-content{margin:0;font-size:12.5px}
.leaflet-popup-content .cm-pop-h,.leaflet-popup-content .cm-motivo{padding-left:12px;padding-right:12px}
/* LUGAR PARA LA ✕ DE LEAFLET, que va pegada arriba a la derecha del globo y no
   se puede mover. Sin esto el botón de leer la OLT se le montaba encima: se ve en
   la captura, con el botón partido contra el borde. */
/* ===== LA ✕ DE LEAFLET =====
   Nunca se le había dado estilo, así que quedaba con el de fábrica: 18×14 px,
   pegada al borde de arriba a la derecha y descentrada por su propia tipografía.
   Al lado de dos botones nuestros se notaba. Se le da la misma caja que ellos,
   para que la fila de arriba se lea como UNA fila de acciones y no como dos cosas
   de distinta época. */
/* Queda donde la pone Leaflet —en absoluto, arriba a la derecha— pero alineada con
   la fila de botones del encabezado: 9 px del borde la dejan a 6 px del botón de
   al lado, así los tres se leen seguidos. */
.leaflet-container a.leaflet-popup-close-button{top:9px;right:9px;font-size:15px;line-height:1}
/* Y el encabezado le deja exactamente ese lugar: 26 de la cruz + 9 del borde. */
.leaflet-popup-content .cm-pop-h{padding-top:9px;padding-right:41px}
.leaflet-popup-content b{font-family:'IBM Plex Sans'}
.leaflet-popup-content .pk{font-family:'IBM Plex Mono';font-size:11px;color:var(--text-faint)}
.leaflet-popup-content .badge{display:inline-block;font-size:11px;font-weight:var(--fw-semi);padding:2px 7px;border-radius:var(--radius-sm);margin-top:6px}
.oz-fus-wrap{margin-top:8px;border-top:1px solid var(--border);padding-top:6px}
.oz-fus-load,.oz-fus-empty{font-size:12px;color:var(--text-faint);padding:3px 0}
.oz-fus-tot{font-family:'IBM Plex Mono';font-size:11px;color:var(--text-faint);margin-bottom:4px}
.oz-fus-list{max-height:210px;overflow-y:auto;margin:0 -2px}
.fpz{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:6px;padding:4px 2px;border-bottom:1px solid var(--border)}
.fpz:last-child{border-bottom:none}
.fend{display:flex;align-items:center;gap:4px;min-width:0}
.fend.fr{justify-content:flex-end}
.fsw{width:11px;height:11px;border-radius:var(--radius-circ);flex:0 0 auto;border:1px solid rgba(0,0,0,.35);box-shadow:0 0 0 1px rgba(255,255,255,.12)}
.ftxt{display:flex;flex-direction:column;min-width:0}
.fend.fr .ftxt{text-align:right}
.ftxt b{font-size:12px;font-weight:var(--fw-semi);line-height:1.15;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ftxt small{font-size:10px;color:var(--text-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fmid{display:flex;align-items:center;gap:3px;flex:0 0 auto}
.fmid .fmdot{width:4px;height:4px;border-radius:var(--radius-circ);background:var(--text-faint)}
.fmid .fat{font-family:'IBM Plex Mono';font-size:9px;color:var(--text-faint)}
.leaflet-bar a{background:var(--surface-2);color:var(--text);border-color:var(--border)}
.leaflet-bar a:hover{background:var(--surface-3)}
.leaflet-control-attribution{background:rgba(14,18,28,.8)!important;color:var(--text-faint)!important}
.leaflet-control-attribution a{color:var(--text-dim)!important}

/* botón "ver mapa" en la tarjeta */
.sector-field{display:flex;gap:8px;align-items:flex-end}
.sector-field .field{flex:1}
.btn-map{background:var(--surface-3);border:1px solid var(--border-strong);color:var(--accent-ink);white-space:nowrap}
.btn-map:hover{background:var(--surface-2)}
.card-sector{display:inline-flex;align-items:center;gap:5px;font-size:11px;color:var(--accent-ink);margin-top:9px;font-weight:var(--fw-medium)}
.card-sector svg{width:12px;height:12px}

/* ====================== GRUPOS / FASES ====================== */
.grupo-chip{display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:var(--fw-semi);letter-spacing:.03em;padding:3px 8px;border-radius:var(--radius-sm);white-space:nowrap}
.grupo-dot{width:7px;height:7px;border-radius:var(--radius-circ);flex:0 0 auto}
/* ====================== CONFIGURACIÓN ====================== */
.set-tabs{display:flex;flex-wrap:wrap;gap:4px;padding:0 22px;border-bottom:1px solid var(--border);background:var(--bg-2)}
.set-tabs .modal-x{margin-left:auto;width:30px;height:30px;align-self:center;position:sticky;right:0;background:var(--bg-2);box-shadow:-10px 0 8px -4px var(--bg-2)}
.modal-idline{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:0}
.modal-idline .mid-date{font-family:'IBM Plex Mono';font-size:11px;color:var(--text-faint);letter-spacing:.04em}
.ro-val{padding:9px 11px;font-size:12.5px;color:var(--text);background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius)}
.set-tab{padding:14px 18px;font-size:14px;font-weight:var(--fw-bold);letter-spacing:-.1px;color:var(--text-dim);border-bottom:2.5px solid transparent;margin-bottom:-1px;transition:.15s}
.set-tab:hover{color:var(--text)}
.set-tab.on{color:var(--text);border-bottom-color:var(--accent-ink)}
.set-hint{font-size:12.5px;color:var(--text-faint);margin:2px 0 16px;line-height:1.5}
.mpanel > .set-hint{margin:0}
.set-row{display:flex;align-items:center;gap:10px;padding:9px 0;border-bottom:1px solid var(--border)}
.set-row:last-child{border-bottom:none}
.set-row .avatar{width:34px;height:34px;border-radius:var(--radius);font-size:12px}
.swatch{display:block;width:34px;height:34px;border-radius:var(--radius);border:1px solid var(--border);overflow:hidden;flex:0 0 auto;position:relative}
.swatch.swatch-sm{width:22px;height:22px;border-radius:var(--radius-sm)}
.swatch input[type=color]{-webkit-appearance:none;appearance:none;position:absolute;inset:-4px;width:calc(100% + 8px);height:calc(100% + 8px);border:none;padding:0;cursor:pointer;background:none}
.swatch input[type=color]::-webkit-color-swatch-wrapper{padding:0}
.swatch input[type=color]::-webkit-color-swatch{border:none}
.swatch.cpal-btn{cursor:pointer}
.cpal{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:9px;box-shadow:0 10px 30px rgba(0,0,0,.45);z-index:99999}
.cpal-grid{display:grid;grid-template-columns:repeat(5,28px);gap:7px}
.cpal-sw{width:28px;height:28px;border-radius:var(--radius);border:2px solid transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:#fff;font-size:13.5px;font-weight:var(--fw-black);padding:0;line-height:1}
.cpal-sw.sel{border-color:#fff;box-shadow:0 0 0 2px var(--signal)}
.cpal-sw.used{opacity:.28;cursor:not-allowed}
.aps-row{align-items:center;gap:12px}
.aps-lbl{flex:1;display:flex;flex-direction:column;gap:1px;min-width:0}
.aps-lbl b{font-size:12.5px}
.aps-lbl span{font-size:12px;color:var(--text-faint)}
.aps-tg{flex:0 0 auto;width:44px;height:26px;border-radius:var(--radius);border:1px solid var(--border);background:var(--surface-3);position:relative;cursor:pointer;transition:.15s;padding:0}
.aps-tg.on{background:var(--selected);color:var(--text);border-color:var(--accent-ink)}
.aps-knob{position:absolute;top:2px;left:2px;width:20px;height:20px;border-radius:var(--radius-circ);background:#fff;transition:.15s}
.aps-tg.on .aps-knob{left:20px}
.aps-prev-h{font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-faint);margin:18px 0 9px;font-weight:var(--fw-bold)}
.aps-prev{max-width:320px;display:flex;flex-direction:column;gap:8px}
/* el color del proyecto (--pc) pinta la tarjeta según lo elegido en Apariencia */
body.tint-bg .card,body.tint-bg .mt-task,body.tint-bg .fl-mini{background:color-mix(in srgb,var(--pc,var(--surface-2)) 20%,var(--surface-2));border-color:color-mix(in srgb,var(--pc,var(--border)) 45%,var(--border))}
body.tint-bg .flt-row{background:color-mix(in srgb,var(--pc,transparent) 13%,transparent);border-radius:var(--radius)}
body.tint-title .card-title,body.tint-title .mt-ttl,body.tint-title .flt-ttl,body.tint-title .fl-mini-ttl{color:var(--pc,inherit)}
body.tint-num .card-id,body.tint-num .flt-id,body.tint-num .flt-num,body.tint-num .fl-mini-id{color:var(--pc,inherit)}
body.tint-bg .proj-item{background:color-mix(in srgb,var(--pc,transparent) 13%,transparent)}
body.tint-title .proj-nm{color:var(--pc,inherit)}
.set-inp{flex:1;background:var(--surface-2);border:1px solid var(--border);color:var(--text);padding:9px 11px;border-radius:var(--radius);font-size:12.5px;min-width:0;transition:.15s}
.set-inp:focus{outline:none;border-color:var(--accent-ink);background:var(--surface)}
.set-del{color:var(--text-faint);width:32px;height:32px;border-radius:var(--radius);display:grid;place-items:center;flex:0 0 auto;transition:.15s}
.set-del:hover{color:var(--red);background:var(--surface-2)}
.set-del svg{width:16px;height:16px}
.add-row{display:flex;gap:8px;align-items:center;margin-top:16px;padding-top:16px;border-top:1px dashed var(--border);flex-wrap:wrap}
.proj-types{margin:2px 0 14px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2);padding:2px 12px}
.proj-types>summary{cursor:pointer;font-size:12.5px;font-weight:var(--fw-bold);color:var(--text-dim);padding:9px 2px;list-style:none}
.proj-types>summary::-webkit-details-marker{display:none}
.proj-types>summary::before{content:'▸';margin-right:7px;color:var(--text-faint);font-size:11px}
.proj-types[open]>summary::before{content:'▾'}
.proj-types .add-row{margin-top:10px;padding-top:12px}
.proj-types .set-row:first-child{border-top:1px solid var(--border)}
.set-user{flex-wrap:wrap}
.user-sub{display:flex;gap:9px;align-items:center;flex-wrap:wrap;flex:1 1 100%;margin-top:7px;padding-left:44px}
.set-pass{font-size:12px;padding:7px 12px}
.no-pass{font-size:12px;color:var(--amber);font-weight:var(--fw-semi)}
.has-pass{font-size:12px;color:var(--green)}

/* ====================== ADJUNTOS / FOTOS ====================== */
.att-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(94px,1fr));gap:9px;margin-bottom:10px}
.att{position:relative;aspect-ratio:1;border-radius:var(--radius);overflow:hidden;border:1px solid var(--border);background:var(--surface-2);cursor:pointer}
.att img{width:100%;height:100%;object-fit:cover;display:block;transition:.2s}
.att:hover img{transform:scale(1.06)}
.att .att-del{position:absolute;top:5px;right:5px;width:24px;height:24px;border-radius:var(--radius-sm);background:rgba(10,13,20,.78);color:#fff;display:grid;place-items:center;opacity:0;transition:.15s}
.att:hover .att-del{opacity:1}
.att .att-del:hover{background:var(--red)}
/* fotos de evidencia dentro de la ficha técnica */
.evid-thumb{position:relative;width:64px;height:64px;border-radius:var(--radius);overflow:hidden;border:1px solid var(--border)}
.evid-thumb img{width:100%;height:100%;object-fit:cover;cursor:pointer;display:block}
.evid-x{position:absolute;top:2px;right:2px;width:18px;height:18px;border:none;border-radius:var(--radius-sm);background:rgba(10,13,20,.7);color:#fff;font-size:11px;cursor:pointer;display:flex;align-items:center;justify-content:center}
.evid-x:hover{background:var(--red)}
.att .att-del svg{width:13px;height:13px}
.att-add{display:inline-flex;align-items:center;gap:8px;padding:11px 14px;border:1.5px dashed var(--border-strong);border-radius:var(--radius);color:var(--text-dim);font-size:12.5px;font-weight:var(--fw-semi);transition:.15s;cursor:pointer}
.att-add:hover{border-color:var(--accent-ink);color:var(--accent-ink)}
.att-add svg{width:16px;height:16px}
.att-add.busy{opacity:.6;pointer-events:none}
.card-cover{margin:-13px -14px 11px;height:118px;background-size:cover;background-position:center;border-bottom:1px solid var(--border)}
.att-count{display:inline-flex;align-items:center;gap:4px;font-size:11px;color:var(--text-faint);font-weight:var(--fw-semi)}
.att-count svg{width:12px;height:12px}
.map-actions{display:flex;gap:8px;margin-top:8px}
.map-actions .btn{flex:1;justify-content:center}

/* selector de base (calle/satelite) */
.map-basemap{position:absolute;left:14px;top:14px;z-index:500;display:flex;gap:2px;background:rgba(14,18,28,.9);border:1px solid var(--border);border-radius:var(--radius);padding:3px}
.map-basemap button{padding:6px 11px;border-radius:var(--radius-sm);font-size:12px;font-weight:var(--fw-semi);color:var(--text-dim);transition:.15s}
.map-basemap button.on{background:var(--surface-3);color:var(--text)}
html[data-theme="light"] .map-basemap{background:rgba(255,255,255,.92)}
.map-layers{position:absolute;right:14px;top:14px;z-index:500;background:rgba(14,18,28,.9);border:1px solid var(--border);border-radius:var(--radius);padding:9px 12px;display:flex;flex-direction:column;gap:5px;min-width:118px}
html[data-theme="light"] .map-layers{background:rgba(255,255,255,.94)}
.map-layers .ml-h{font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--text-faint);font-weight:var(--fw-semi);margin-bottom:3px}
.map-layers label{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--text-dim);cursor:pointer}
.map-layers input{accent-color:var(--accent-ink);width:14px;height:14px;cursor:pointer;margin:0}
.map-layers .ml-sep{margin-top:4px;padding-top:6px;border-top:1px solid var(--border)}
.leaflet-tooltip.mlbl{background:rgba(14,18,28,.82);border:none;color:#fff;font-size:11px;font-weight:var(--fw-semi);padding:1px 5px;border-radius:var(--radius-sm);box-shadow:none;white-space:nowrap}
.leaflet-tooltip.mlbl::before{display:none}
html[data-theme="light"] .leaflet-tooltip.mlbl{background:rgba(255,255,255,.92);color:#111;border:1px solid #ccc}

/* barra de captura */
.capture-bar{position:absolute;left:50%;top:14px;transform:translateX(-50%);z-index:600;display:flex;align-items:center;gap:10px;
  background:rgba(14,18,28,.94);border:1px solid var(--signal);border-radius:var(--radius);padding:9px 10px 9px 16px;box-shadow:var(--shadow);max-width:calc(100% - 28px)}
html[data-theme="light"] .capture-bar{background:rgba(255,255,255,.96)}
.capture-bar .cb-txt{font-size:12.5px;color:var(--text-dim);max-width:340px;line-height:1.4}
.capture-bar .btn{padding:8px 13px;font-size:12.5px}
.capture-bar #cbMark.on{background:var(--red-fill);color:#fff;border-color:var(--red-fill)}

/* ====================== ESTADÍSTICAS ====================== */
/* La vista Novedades: oculta salvo cuando está activa. Sin esta regla el contenido quedaba encima
   de las demás pantallas al cambiar de sección. */
/* Control de gastos: mismo patron que las demas vistas. Va con display:flex —no block— porque
   adentro lleva su propio menu al costado y necesita repartir el alto entre menu y cuerpo. */
#cajaView{flex:1;min-height:0;display:none}
#cajaView.on{display:flex}
#novView{flex:1;display:none;overflow:auto;padding:0}
#novView.on{display:block}
#novWrap{padding:18px 20px calc(24px + env(safe-area-inset-bottom))}
#statsView{flex:1;display:none;overflow:auto;padding:22px 24px calc(28px + env(safe-area-inset-bottom))}
#statsView.on{display:block}
/* ===== Pantalla TV · Avance ===== */
#tvView{flex:1;display:none;overflow:auto;padding:26px clamp(20px,3vw,56px) 40px;}
#tvView.on{display:block}
.tv-head{display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;margin-bottom:18px}
.tv-title{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:clamp(20px,2.4vw,30px);letter-spacing:-.3px;display:flex;align-items:center;gap:12px}
.tv-title .tv-dot{width:12px;height:12px;border-radius:var(--radius-circ);background:var(--green);box-shadow:0 0 0 4px color-mix(in srgb,var(--green) 25%,transparent)}
.tv-range{font-family:'IBM Plex Mono';font-size:12.5px;color:var(--text-faint);font-weight:var(--fw-medium)}
.tv-period{display:flex;gap:3px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:4px}
.tv-period button{padding:9px 20px;border-radius:var(--radius);font-size:14px;font-weight:var(--fw-bold);color:var(--text-dim)}
.tv-period button.on{background:var(--selected);color:var(--text);border-color:var(--accent-ink)}
.tv-actions{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.tv-btn{display:inline-flex;align-items:center;gap:7px;padding:9px 16px;border-radius:var(--radius);background:var(--surface-2);border:1px solid var(--border);color:var(--text-dim);font-size:13.5px;font-weight:var(--fw-bold);cursor:pointer}
.tv-btn:hover{color:var(--text);border-color:var(--border-strong)}
.tv-btn.on{background:var(--green);color:#06210a;border-color:var(--green)}
.tv-btn-ic{padding:9px 11px}
@keyframes tvSpin{to{transform:rotate(360deg)}}
.tv-btn-ic.on svg{animation:tvSpin 3.5s linear infinite}
#tvView:fullscreen{overflow:auto;background:var(--bg)}
#tvView:fullscreen{padding:32px clamp(24px,4vw,80px)}
.tv-sec-l{font-family:'IBM Plex Mono';font-size:12px;text-transform:uppercase;letter-spacing:.14em;color:var(--text-faint);font-weight:var(--fw-bold);margin:22px 0 12px}
.tv-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:16px}
.tv-tile{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:22px 22px 18px;display:flex;flex-direction:column;gap:6px}
.tv-tile.good{border-color:color-mix(in srgb,var(--green) 35%,var(--border))}
.tv-tile.bad{border-color:color-mix(in srgb,var(--red) 50%,var(--border));background:color-mix(in srgb,var(--red) 7%,var(--surface))}
.tv-tile.warn{border-color:color-mix(in srgb,var(--amber) 50%,var(--border));background:color-mix(in srgb,var(--amber) 7%,var(--surface))}
.tv-n{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:clamp(44px,5.5vw,76px);line-height:1;letter-spacing:-1px}
.tv-tile.good .tv-n{color:var(--green)} .tv-tile.bad .tv-n{color:var(--red)} .tv-tile.warn .tv-n{color:var(--amber)}
.tv-l{font-size:14px;font-weight:var(--fw-semi);color:var(--text)}
.tv-cmp{margin-top:6px;font-size:12.5px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.tv-delta{font-weight:var(--fw-black);font-family:'IBM Plex Mono';font-size:12.5px;padding:2px 8px;border-radius:var(--radius-sm)}
.tv-delta.up{color:var(--green);background:color-mix(in srgb,var(--green) 15%,transparent)}
.tv-delta.down{color:var(--red);background:color-mix(in srgb,var(--red) 15%,transparent)}
.tv-delta.eq{color:var(--text-faint);background:var(--surface-2)}
.tv-prev{color:var(--text-faint)}
/* Lista de trabajos hechos: desliza vertical en continuo (tipo créditos), abajo */
.tv-vlist{margin-top:6px;height:clamp(300px,50vh,720px);overflow:hidden;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);-webkit-mask:linear-gradient(180deg,transparent,#000 6%,#000 94%,transparent);mask:linear-gradient(180deg,transparent,#000 6%,#000 94%,transparent)}
.tv-vlist-track{display:flex;flex-direction:column;will-change:transform;animation:tvVScroll linear infinite}
.tv-vlist:hover .tv-vlist-track{animation-play-state:paused}
@keyframes tvVScroll{from{transform:translateY(0)}to{transform:translateY(-50%)}}
.tv-vrow{display:flex;align-items:center;gap:14px;padding:14px 22px;border-bottom:1px solid var(--border);font-size:clamp(16px,1.7vw,24px);font-weight:var(--fw-semi);color:var(--text)}
.tv-vrow .tv-vic{width:30px;height:30px;flex:0 0 auto;display:flex;align-items:center;justify-content:center;border-radius:var(--radius);background:color-mix(in srgb,var(--cc) 18%,transparent);color:var(--cc)}
.tv-vrow .tv-vic svg{width:18px;height:18px}
.tv-vrow .tv-vname{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tv-vrow .tv-vmeta{flex:0 1 auto;display:inline-flex;align-items:center;gap:6px;max-width:46%;overflow:hidden;font-size:.7em;font-weight:var(--fw-bold);font-family:'IBM Plex Mono';color:var(--text-faint);text-transform:uppercase;letter-spacing:.04em}
.tv-vrow .tv-vmeta svg{width:14px;height:14px;flex:0 0 auto;opacity:.7}
.tv-vrow .tv-vmeta span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tv-vrow.proj{background:color-mix(in srgb,var(--cc) 9%,transparent)}
.tv-vrow.proj .tv-vname{font-weight:var(--fw-black)}
#tvView:fullscreen .tv-vrow{font-size:clamp(20px,1.9vw,30px);padding:17px 28px}
/* Avance mudado a Estadísticas de soporte (stage dentro del panel) */
.av-stage{}
.av-head{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:4px}
.av-per-lbl{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:clamp(16px,1.6vw,22px);letter-spacing:-.2px}
.av-actions{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.av-actions .tv-period button{padding:6px 14px;font-size:12.5px} .av-actions .tv-btn{padding:7px 12px;font-size:12.5px} .av-actions .tv-btn-ic{padding:7px 9px}
.av-sopgrid{grid-template-columns:repeat(auto-fit,minmax(190px,1fr))} .av-sopgrid .tv-tile{padding:16px 18px 14px} .av-sopgrid .tv-n{font-size:clamp(34px,4vw,52px)}
.av-pend{margin-top:12px;padding:9px 13px;border:1px solid color-mix(in srgb,var(--amber) 45%,var(--border));background:color-mix(in srgb,var(--amber) 8%,transparent);border-radius:var(--radius);font-size:12.5px;color:var(--text-dim)} .av-pend b{color:var(--text)}
.av-stage .tv-sec-l:first-of-type{margin-top:8px}
.av-stage:fullscreen{background:var(--bg);overflow:auto;padding:30px clamp(24px,4vw,72px)}
.av-stage .tv-vlist{height:clamp(240px,38vh,520px)}
@media(max-width:820px){ .av-stage .tv-cols{flex-direction:column} }
/* Ranking de técnicos (Avance) */
.av-lead-h{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin:24px 0 10px}
.av-scope{display:inline-flex;gap:3px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:3px}
.av-scope button{padding:6px 15px;border-radius:var(--radius-sm);font-size:12.5px;font-weight:var(--fw-bold);color:var(--text-dim)} .av-scope button.on{background:var(--selected);color:var(--text);border-color:var(--accent-ink)}
.av-lead{display:flex;flex-direction:column;gap:7px}
.av-lrow{display:grid;grid-template-columns:38px minmax(120px,1.7fr) 3fr 74px 92px;align-items:center;gap:14px;padding:9px 14px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius)}
.av-lrow.av-top{border-color:color-mix(in srgb,var(--green) 55%,var(--border));background:color-mix(in srgb,var(--green) 7%,var(--surface))}
.av-rank{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:clamp(16px,1.6vw,22px);color:var(--text-faint);text-align:center}
.av-lrow.av-top .av-rank{color:var(--green)}
.av-lname{font-weight:var(--fw-bold);font-size:clamp(14px,1.4vw,18px);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.av-remoto{font-size:10px;font-weight:var(--fw-bold);color:var(--text-faint);text-transform:uppercase;letter-spacing:.04em;background:var(--surface-2);padding:1px 6px;border-radius:var(--radius-sm);margin-left:4px}
.av-lbar{position:relative;height:26px;border-radius:var(--radius);background:var(--surface-2);overflow:hidden;display:flex;align-items:center}
.av-lbar>span{position:absolute;left:0;top:0;bottom:0;background:linear-gradient(90deg,color-mix(in srgb,var(--signal) 55%,transparent),var(--signal));border-radius:var(--radius);min-width:3px}
.av-lbar>em{position:relative;z-index:1;display:flex;gap:7px;padding:0 9px;font-style:normal;font-size:12px;font-variant-numeric:tabular-nums;overflow:hidden;flex-wrap:nowrap}
.av-lbar>em b{font-weight:var(--fw-bold);padding:2px 9px;border-radius:var(--radius-sm);white-space:nowrap}
.av-lbar>em b.s-inst{color:#dfe9ff;background:color-mix(in srgb,#2f6fed 60%,rgba(0,0,0,.35))}
.av-lbar>em b.s-sop{color:#fff2df;background:color-mix(in srgb,#c47d10 62%,rgba(0,0,0,.35))}
.av-lbar>em b.s-ret{color:#efe6ff;background:color-mix(in srgb,#7c53e0 62%,rgba(0,0,0,.35))}
.av-lnum{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:clamp(20px,2vw,30px);text-align:right;font-variant-numeric:tabular-nums}
.av-lpend{font-size:11px;font-weight:var(--fw-bold);color:var(--amber);margin-left:3px}
.av-ldelta{text-align:right}
.av-lead-note{margin-top:12px;font-size:12.5px;color:var(--text-dim);line-height:1.4} .av-lead-note b{color:var(--text)} .av-lead-note .av-lpend2{color:var(--amber)}
@media(max-width:760px){ .av-lrow{grid-template-columns:28px 1.4fr 2fr 52px;gap:8px} .av-ldelta{display:none} }
/* Avance dividido: Mantenimiento | Proyectos de red */
.tv-cols{display:flex;gap:clamp(16px,2.2vw,34px);align-items:flex-start}
.tv-col{flex:1 1 0;min-width:0;display:flex;flex-direction:column}
.tv-col-h{display:flex;align-items:center;gap:11px;font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:clamp(17px,1.7vw,25px);letter-spacing:-.2px;padding:4px 2px 12px;border-bottom:2px solid var(--border-strong)}
.tv-col-h .tv-col-ic{width:31px;height:31px;flex:0 0 auto;display:grid;place-items:center;border-radius:var(--radius)}
.tv-col-h .tv-col-ic svg{width:19px;height:19px}
.tv-col.mant .tv-col-ic{background:color-mix(in srgb,var(--green) 20%,transparent);color:var(--green)}
.tv-col.infra .tv-col-ic{background:color-mix(in srgb,#c58af9 22%,transparent);color:#c58af9}
.tv-col.mant .tv-col-h{border-bottom-color:color-mix(in srgb,var(--green) 55%,var(--border-strong))}
.tv-col.infra .tv-col-h{border-bottom-color:color-mix(in srgb,#c58af9 55%,var(--border-strong))}
/* tarjetas de Logros tintadas con el color de su columna */
.tv-col.mant .tv-tile.good{border-color:color-mix(in srgb,var(--green) 38%,var(--border));background:color-mix(in srgb,var(--green) 6%,var(--surface))}
.tv-col.mant .tv-tile.good .tv-n{color:var(--green)}
.tv-col.infra .tv-tile.good{border-color:color-mix(in srgb,#c58af9 42%,var(--border));background:color-mix(in srgb,#c58af9 7%,var(--surface))}
.tv-col.infra .tv-tile.good .tv-n{color:#c58af9}
.tv-col .tv-grid{grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
.tv-col .tv-tile{padding:17px 18px 15px}
.tv-col .tv-n{font-size:clamp(36px,4vw,58px)}
.tv-col .tv-sec-l{margin:16px 0 10px}
.tv-col .tv-vlist{height:clamp(240px,38vh,560px)}
.tv-empty{margin-top:6px;padding:30px 20px;border:1px dashed var(--border);border-radius:var(--radius);color:var(--text-faint);font-size:13.5px;text-align:center;background:var(--surface)}
@media(max-width:900px){ .tv-cols{flex-direction:column} .tv-col .tv-vlist{height:clamp(220px,32vh,420px)} }
#histView{flex:1;display:none;overflow:auto;padding:22px 24px calc(28px + env(safe-area-inset-bottom))}
#histView.on{display:block}
.hist-cols{display:flex;gap:clamp(12px,1.6vw,24px);align-items:flex-start;min-height:100%}
.hist-col{flex:1 1 0;min-width:0;display:flex;flex-direction:column}
.hist-col-h{display:flex;align-items:center;gap:9px;padding:10px 6px 11px;font-weight:var(--fw-black);font-size:12.5px;color:var(--text)}
.hist-col-h b{color:var(--text-faint);font-weight:var(--fw-bold)}
.hist-col-h .hist-dot{width:10px;height:10px;border-radius:var(--radius-circ);flex:0 0 auto}
.hist-col.mant .hist-dot{background:var(--green)}
.hist-col.infra .hist-dot{background:#c58af9}
.hist-col.mant .hist-col-h{border-bottom:2px solid color-mix(in srgb,var(--green) 45%,var(--border-strong))}
.hist-col.infra .hist-col-h{border-bottom:2px solid color-mix(in srgb,#c58af9 45%,var(--border-strong))}
.hist-col .dbt-wrap{width:100%;border:0;border-radius:0}
@media(max-width:1000px){ .hist-cols{flex-direction:column} }
#myTasksView{flex:1;display:none;overflow:auto;padding:16px 16px calc(24px + env(safe-area-inset-bottom))}
#myTasksView.on{display:block}
/* ---- Anotaciones ---- */
.notes-cap{display:flex;gap:9px;align-items:flex-start;margin-bottom:12px}
.notes-cap textarea{flex:1;min-height:48px;max-height:220px;resize:none;padding:13px 15px;font:inherit;font-size:14px;line-height:1.45;background:var(--surface-2);color:var(--text);border:1px solid var(--border-strong);border-radius:var(--radius);outline:none;overflow:hidden}
.notes-cap textarea:focus{border-color:var(--accent-ink)}
.notes-cap .btn-add{flex:0 0 auto;height:48px;padding:0 17px;border:none;border-radius:var(--radius);background:var(--signal);color:var(--on-signal);font-weight:var(--fw-bold);font-size:13.5px;cursor:pointer;display:inline-flex;align-items:center;gap:6px}
.notes-cap .btn-add svg{width:18px;height:18px}
.notes-tools{display:flex;gap:9px;align-items:center;flex-wrap:wrap;margin-bottom:6px}
.notes-tools .nsearch{flex:1;min-width:150px;padding:9px 13px;background:var(--surface-2);color:var(--text);border:1px solid var(--border);border-radius:var(--radius);outline:none;font-size:13.5px}
.notes-tools .nsearch:focus{border-color:var(--border-strong)}
.nfilter{display:flex;gap:6px;flex-wrap:wrap}
.nfilter button{padding:7px 12px;border:1px solid var(--border);background:var(--surface-2);color:var(--text-faint);border-radius:var(--radius);font-size:12.5px;font-weight:var(--fw-semi);cursor:pointer;display:inline-flex;align-items:center;gap:6px}
.nfilter button.on{color:var(--text);border-color:var(--border-strong);background:var(--surface)}
.nfilter .ndot{width:9px;height:9px;border-radius:var(--radius-circ)}
.notes-sec{margin:20px 0 9px;font-size:12px;font-weight:var(--fw-bold);letter-spacing:.05em;text-transform:uppercase;color:var(--text-faint)}
.note{background:var(--surface-2);border:1px solid var(--border);border-left:3px solid var(--tagc,#5e6a82);border-radius:var(--radius);padding:12px 14px 11px;margin-bottom:10px;position:relative;contain:content}
.note.done{opacity:.6}
.note-top{display:flex;align-items:center;gap:6px;margin-bottom:5px}
.note-tag{display:inline-flex;align-items:center;gap:5px;font-size:12px;font-weight:var(--fw-bold);color:var(--tagc);cursor:pointer;border:1px solid transparent;padding:3px 6px;border-radius:var(--radius-sm);user-select:none}
.note-tag:hover{border-color:var(--border)}
/* La marca de seguridad al lado del nombre. Chica y con palabra: el color solo obliga a distinguir
   tonos y no dice qué es. Va en su propio renglón para no empujar el nombre ni la dirección. */
/* La marca propia, arriba de la celda de gestión. Cada estado con su color: «cancelado» es final,
   «sin contacto» es que falta insistir, «para revisión» es que falta decidir. */
/* La caja de las chapitas: en fila, y bajan si no entran. El margen de abajo lo pone ella y no cada
   chapita, así que con una o con dos la separación con los botones es la misma. */
/* El puerto que no debería estar abierto. En rojo y sin cursor de enlace: no lleva a ningún lado,
   es un hallazgo. La explicación entera va en el globito. */
.eq-riesgo{display:inline-flex;align-items:center;gap:5px;margin:0 6px 4px 0;padding:2px 8px;
  border-radius:var(--radius-sm);font-size:11px;font-weight:var(--fw-bold);white-space:nowrap;cursor:help;
  color:var(--red);background:color-mix(in srgb,var(--red) 12%,transparent);
  border:1px solid color-mix(in srgb,var(--red) 40%,transparent)}
.fg-chips{display:flex;flex-wrap:wrap;align-items:center;gap:4px;margin-bottom:4px}
.fg-chips:empty{display:none}
/* Mismo alto, misma letra y mismo radio que la chapita del ticket: juntas tienen que leerse como dos
   datos de la misma fila y no como dos cosas de sistemas distintos. Lo que las distingue es el color
   y las MAYÚSCULAS, que dicen «esto lo escribió alguien». */
.fg-marca{display:inline-flex;align-items:center;font-size:10px;font-weight:var(--fw-bold);letter-spacing:.02em;
  text-transform:uppercase;padding:2px 7px;border-radius:var(--radius-sm);white-space:nowrap;cursor:help;
  border:1px solid transparent;line-height:1.3}
.fg-marca-sincontacto{color:var(--amber);background:color-mix(in srgb,var(--amber) 14%,transparent);
  border-color:color-mix(in srgb,var(--amber) 36%,transparent)}
.fg-marca-revision{color:var(--violet);background:color-mix(in srgb,var(--violet) 14%,transparent);
  border-color:color-mix(in srgb,var(--violet) 36%,transparent)}
.fg-marca-cancelado{color:var(--text-faint);background:color-mix(in srgb,var(--text-faint) 12%,transparent);
  border-color:var(--border)}
.ct-chk{width:1%;text-align:center} .ct-chk input{cursor:pointer;width:16px;height:16px}
tr.ct-on{background:color-mix(in srgb,var(--signal) 8%,transparent)}
.fg-est{opacity:.75}
.fg-est:hover{opacity:1}
/* El cuadro para elegir. Todo con span/label porque va dentro del <p> del diálogo; el aspecto de
   filas lo da esto y no la etiqueta. */
.fg-mk-box{display:flex;flex-direction:column;gap:2px;text-align:left}
.fg-op{display:flex;align-items:flex-start;gap:9px;padding:7px 9px;border-radius:var(--radius);cursor:pointer}
.fg-op:hover{background:var(--surface-2)}
.fg-op-t{display:flex;flex-direction:column;gap:1px}
.fg-op small{color:var(--text-faint);font-size:11px}
.fg-op-nota{flex-direction:column;align-items:stretch;cursor:default;margin-top:6px}
.fg-op-nota:hover{background:none}
.fg-op-nota .inp{margin-top:5px;width:100%}
/* Sin `resize` a mano: se acomoda solo. El tope es para que una nota larga no empuje «Guardar»
   fuera de la pantalla; a partir de ahí scrollea adentro. */
.fg-op-nota textarea.inp{resize:none;min-height:48px;max-height:180px;overflow-y:auto;
  line-height:1.45;font-family:inherit;padding:7px 9px}
.seg-mk{display:inline-block;margin-top:3px;font-size:10px;font-weight:var(--fw-bold);letter-spacing:.02em;
  text-transform:uppercase;padding:1px 6px;border-radius:var(--radius-sm);border:1px solid transparent;white-space:nowrap;cursor:help}
.seg-mk-mal{color:var(--red);background:color-mix(in srgb,var(--red) 14%,transparent);
  border-color:color-mix(in srgb,var(--red) 38%,transparent)}
.seg-mk-ojo{color:var(--amber);background:color-mix(in srgb,var(--amber) 14%,transparent);
  border-color:color-mix(in srgb,var(--amber) 36%,transparent)}
/* Para quién es el trabajo. Va al lado de la etiqueta y en voz más baja que ella cuando está vacía:
   «sin destino» es una pregunta pendiente, no un dato. */
.note-dest{display:inline-flex;align-items:center;font-size:11px;font-weight:var(--fw-bold);color:var(--destc);
  cursor:pointer;border:1px solid color-mix(in srgb,var(--destc) 40%,transparent);
  background:color-mix(in srgb,var(--destc) 12%,transparent);
  padding:2px 7px;border-radius:var(--radius-sm);user-select:none;margin-left:4px;white-space:nowrap}
.note-dest.vacio{color:var(--text-faint);border-style:dashed;border-color:var(--border);background:none;font-weight:var(--fw-semi)}
.note-dest:hover{border-color:var(--destc)}
.note-spacer{flex:1}
.note-act{width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;border:none;background:transparent;color:var(--text-faint);border-radius:var(--radius);cursor:pointer}
.note-act:hover{background:var(--surface);color:var(--text)}
.note-act.on{color:var(--accent-ink)}
.note-act svg{width:17px;height:17px}
.note-body{width:100%;border:none;background:transparent;color:var(--text);font:inherit;font-size:14px;line-height:1.5;resize:none;outline:none;overflow:hidden;min-height:22px;padding:0;display:block}
.note.done .note-body{text-decoration:line-through;text-decoration-color:var(--text-faint)}
.note-chk{margin-top:9px;display:flex;flex-direction:column;gap:6px}
.note-chk-row{display:flex;align-items:center;gap:9px}
.note-chk-row .cbox{flex:0 0 auto;width:19px;height:19px;border-radius:var(--radius-sm);border:1.5px solid var(--border-strong);background:transparent;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;color:transparent;padding:0}
.note-chk-row .cbox.on{background:var(--green);border-color:var(--green);color:#04140f}
.note-chk-row .cbox svg{width:12px;height:12px}
.note-chk-row input{flex:1;border:none;background:transparent;color:var(--text);font:inherit;font-size:13.5px;outline:none;min-width:0}
.note-chk-row.done input{text-decoration:line-through;color:var(--text-faint)}
.note-chk-row .crm{flex:0 0 auto;opacity:.3;border:none;background:transparent;color:var(--text-faint);cursor:pointer;font-size:17px;line-height:1;padding:0 2px}
.note-chk-row:hover .crm{opacity:1}
.note-chk-add{font-size:12.5px;color:var(--text-faint);background:none;border:none;cursor:pointer;padding:3px 0 0;text-align:left;display:inline-flex;align-items:center;gap:6px}
.note-chk-add svg{width:13px;height:13px;flex:0 0 auto}
.note-chk-add:hover{color:var(--text)}
.note-foot{display:flex;align-items:center;gap:9px;margin-top:10px;flex-wrap:wrap;font-size:12px;color:var(--text-faint)}
.note-chip{display:inline-flex;align-items:center;gap:5px;cursor:pointer;padding:3px 8px;border-radius:var(--radius-sm);border:1px solid var(--border);color:var(--text-faint)}
.note-chip:hover{color:var(--text);border-color:var(--border-strong)}
.note-chip svg{width:13px;height:13px}
.note-chip.due{color:var(--red);border-color:var(--red)}
.note-chip.soon{color:var(--amber);border-color:var(--amber)}
.note-author{margin-left:auto;font-size:11px}
.note-empty{text-align:center;color:var(--text-faint);padding:46px 12px;font-size:13.5px;line-height:1.7}
@media(max-width:680px),(max-height:480px){
  .notes-cap .btn-add span{display:none}
  .notes-cap .btn-add{padding:0 14px}
}
/* ---- Ayuda (pantalla completa) ---- */
#helpView{flex:1;display:none;overflow:auto;padding:22px 24px calc(28px + env(safe-area-inset-bottom))}
#helpView.on{display:block}
#helpWrap{max-width:none;margin:0}
.help-top{display:flex;align-items:center;gap:16px;flex-wrap:wrap;margin-bottom:18px}
.help-h h2{margin:0;font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:19px;letter-spacing:-.3px}
.help-h p{margin:2px 0 0;color:var(--text-faint);font-size:12.5px}
.help-search{margin-left:auto;flex:1;min-width:200px;max-width:360px;padding:9px 13px;background:var(--surface-2);border:1px solid var(--border-strong);border-radius:var(--radius);color:var(--text);font-size:13.5px;outline:none}
.help-search:focus{border-color:var(--accent-ink)}
/* encabezado uniforme de todas las vistas: título arriba, controles en fila abajo a la izquierda */
.vhead{margin:0 0 12px}
.vhead h2{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:19px;letter-spacing:-.3px;margin:0;line-height:1.1}
.vhead .vsub{color:var(--text-faint);font-size:12.5px;margin:3px 0 0}
.vtools{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 14px}
.vtools .help-search,.vtools .hist-search{margin-left:0;flex:0 1 340px;width:auto;max-width:360px;min-width:160px}
#helpSearch{flex:0 0 240px;width:240px;max-width:240px;min-width:0}
.help-grid{display:grid;grid-template-columns:240px 1fr;gap:22px;align-items:start}
.help-side{display:flex;flex-direction:column;gap:12px;position:sticky;top:0;align-self:start}
.help-side .help-search{margin-left:0;flex:none;width:100%;max-width:none}
.help-side .help-index{position:static}
.help-index{position:sticky;top:0;display:flex;flex-direction:column;gap:2px}
.help-ix{display:block;padding:8px 11px;border-radius:var(--radius);color:var(--text-faint);text-decoration:none;font-size:12.5px;font-weight:var(--fw-semi);cursor:pointer}
.help-ix:hover{background:var(--surface-2);color:var(--text)}
.help-content{display:flex;flex-direction:column;gap:16px;min-width:0}
.help-card{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:16px 18px;scroll-margin-top:12px}
.help-card h3{margin:0 0 10px;font-family:'IBM Plex Sans';font-size:15px}
.help-card ul{margin:0;padding-left:18px;display:flex;flex-direction:column;gap:6px}
.help-card li{font-size:13.5px;line-height:1.5;color:var(--text)}
.help-card li b{font-weight:var(--fw-bold)}
.help-card p{font-size:13.5px;line-height:1.5;color:var(--text);margin:0 0 10px}
.help-empty{padding:50px;text-align:center;color:var(--text-faint)}
.hflow{display:flex;flex-wrap:wrap;align-items:stretch;gap:8px;margin:6px 0 12px}
.hstep{display:flex;flex-direction:column;justify-content:center;gap:2px;background:var(--surface);border:1px solid var(--border);border-left:3px solid var(--sc,var(--signal));border-radius:var(--radius);padding:8px 12px;min-width:92px}
.hstep .hs-ic{font-size:14px;line-height:1}
.hstep .hs-lb{font-size:12.5px;font-weight:var(--fw-bold)}
.hstep .hs-sub{font-size:11px;color:var(--text-faint)}
.harrow{align-self:center;color:var(--text-faint);font-size:16px}
.help-note{background:var(--surface);border:1px dashed var(--border-strong);border-radius:var(--radius);padding:10px 12px;font-size:12.5px;color:var(--text-faint);line-height:1.5}
/* ---- Planos ---- */
#planosView{flex:1;display:none;overflow:hidden;padding:0}
#planosView.on{display:flex}
#planosWrap{max-width:none;margin:0}
.planos-top .help-search{margin-left:auto}
.planos-list{display:flex;flex-direction:column;gap:16px}
.planos-folder{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:16px 18px}
.planos-folder h3{margin:0 0 10px;font-family:'IBM Plex Sans';font-size:15px;display:flex;align-items:center;gap:8px}
.pf-count{font-family:'IBM Plex Mono';font-size:12px;font-weight:var(--fw-semi);color:var(--text-faint);background:var(--surface-3);padding:2px 8px;border-radius:var(--radius)}
.pf-files{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:8px}
.pfile{display:flex;align-items:center;gap:4px}
.pfile-link{flex:1;min-width:0;display:flex;align-items:center;gap:9px;text-decoration:none;color:var(--text);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:9px 11px;font-size:12.5px}
.pfile-link:hover{border-color:var(--accent-ink)}
.pfile-link svg{width:17px;height:17px;flex:0 0 auto;color:#c2555f}
.pfile-name{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pfile-sz{flex:0 0 auto;font-size:11px;color:var(--text-faint);font-family:'IBM Plex Mono'}
.pfile-del{flex:0 0 auto;border:none;background:transparent;color:var(--text-faint);cursor:pointer;border-radius:var(--radius-sm);width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center}
.pfile-del:hover{color:var(--red);background:var(--surface)}
.pfile-del svg{width:15px;height:15px}
/* ---- Agenda (módulo a pantalla completa) ---- */
#agendaView{flex:1;display:none;overflow:auto;padding:22px 24px calc(28px + env(safe-area-inset-bottom))}
#agendaView.on{display:block}
#agendaWrap{max-width:none;margin:0}
.agenda-tabs{display:flex;gap:6px;flex-wrap:wrap}
.ag-tab{padding:8px 14px;border:1px solid var(--border);background:var(--surface-2);color:var(--text-faint);border-radius:var(--radius);font-size:12.5px;font-weight:var(--fw-semi);cursor:pointer}
.ag-tab.on{color:var(--text);border-color:var(--border-strong);background:var(--surface);box-shadow:inset 0 -2px 0 var(--signal)}
.agenda-nav{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.agenda-panel{border:1px solid var(--border-strong);border-radius:var(--radius);overflow:hidden;background:var(--surface-2)}
.agenda-top{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:11px 12px;border-bottom:1px solid var(--border)}
.agenda-cal{padding:14px}
.cal-month{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:14px;margin-left:6px}
.cal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:6px}
.cal-dow{font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--text-faint);font-weight:var(--fw-bold);text-align:center;padding:2px 0 4px}
.cal-cell{min-height:108px;background:var(--bg-2,var(--surface-2));border:1px solid var(--border);border-radius:var(--radius);padding:5px 5px 6px;display:flex;flex-direction:column;gap:3px;overflow:hidden}
.cal-cell.empty{background:transparent;border:none}
.cal-cell.today{border-color:var(--accent-ink)}
.cal-cell.drag-over{border-color:var(--accent-ink);background:var(--surface)}
.cal-dnum{font-size:12px;font-weight:var(--fw-bold);color:var(--text-faint);flex:0 0 auto}
.cal-cell.today .cal-dnum{color:var(--accent-ink)}
.cal-tasks{display:flex;flex-direction:column;gap:3px;overflow:auto;min-height:0}
.cal-chip{font-size:11px;line-height:1.3;padding:3px 6px;border-radius:var(--radius-sm);background:var(--surface);border-left:3px solid var(--cc,var(--signal));overflow:hidden;cursor:pointer;display:flex;align-items:center;gap:3px}
.cal-ctxt{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cal-x{flex:0 0 auto;border:none;background:none;color:inherit;cursor:pointer;opacity:.5;font-size:13.5px;line-height:1;padding:0 1px;font-weight:var(--fw-bold)}
.cal-x:hover{opacity:1;color:var(--red)}
.cal-chip:hover{filter:brightness(1.15)}
.cal-chip.over{border-left-color:var(--red);color:var(--red)}
.cal-chip.done{opacity:.5;text-decoration:line-through}
.cal-chip.dragging{opacity:.4}
.cal-nodate{margin-top:14px;display:flex;flex-wrap:wrap;gap:6px;align-items:center;font-size:12.5px;color:var(--text-faint)}
.cal-cell[data-day]{cursor:pointer}
.cal-cell[data-day]:hover{border-color:var(--border-strong)}
/* diálogo Planificar (tocar un día) */
.ad-list{display:flex;flex-direction:column;gap:4px;max-height:46vh;overflow:auto}
.ad-row{display:flex;align-items:center;gap:9px;padding:8px 10px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2);cursor:pointer}
.ad-row.on{border-color:var(--accent-ink);background:color-mix(in srgb,var(--signal) 10%,var(--surface-2))}
.ad-row input{flex:0 0 auto;width:17px;height:17px;cursor:pointer}
.ad-dot{width:8px;height:8px;border-radius:var(--radius-circ);flex:0 0 auto}
.ad-main{min-width:0;font-size:12.5px;line-height:1.3}
.ad-main b{font-family:'IBM Plex Mono';font-size:12px}
.ad-sub{display:block;font-size:11px;color:var(--text-faint);margin-top:1px}
.ad-newbox{border:1px solid var(--border);border-radius:var(--radius);padding:10px;margin-bottom:14px;background:var(--surface-2)}
.ad-newrow{display:flex;gap:8px;margin-top:8px;align-items:center}
.ad-notes{display:flex;flex-direction:column;gap:8px;margin-bottom:6px}
.ad-note{border:1px solid var(--border);border-left:3px solid var(--cc,var(--signal));border-radius:var(--radius);padding:9px}
.ad-ntxt{resize:vertical}
.ad-nact{display:flex;align-items:center;gap:8px;margin-top:7px}
.ad-tag{padding:5px 10px;font-size:12px}
@media(max-width:760px){
  #agendaView{padding:12px 10px calc(22px + env(safe-area-inset-bottom))}
  .cal-grid{gap:3px}
  .cal-cell{min-height:60px;padding:3px;border-radius:var(--radius-sm)}
  .cal-dow{font-size:9px}
  .cal-chip{font-size:9px;padding:2px 4px;border-left-width:2px}
}
/* ---- Stock / Depósito (tabla densa, ancho completo) ---- */
#stockView{flex:1;display:none;overflow:auto;padding:22px 24px calc(28px + env(safe-area-inset-bottom))}
#stockView.on{display:block}
#stockWrap{max-width:none;margin:0}
.nav-badge{display:inline-flex;align-items:center;justify-content:center;min-width:16px;height:16px;padding:0 4px;margin-left:6px;font-size:10px;font-weight:var(--fw-bold);color:#fff;background:var(--red);border-radius:var(--radius);font-family:'IBM Plex Mono'}
/* panel único que une solapas + barra + grilla (ventana tipo Excel) */
.stock-panel{border:1px solid var(--border-strong);border-radius:var(--radius);overflow:hidden;background:var(--surface-2)}
.stock-tabs{display:flex;gap:0;flex-wrap:wrap;background:var(--surface-3,var(--surface-2));border-bottom:1px solid var(--border-strong)}
.stock-tabs .set-tab{border:none;border-radius:0;background:none;padding:11px 16px;font-size:12.5px;font-weight:var(--fw-semi);color:var(--text-faint);border-bottom:2px solid transparent;cursor:pointer;display:inline-flex;align-items:center;gap:6px}
.stock-tabs .set-tab.on{color:var(--text);border-bottom-color:var(--accent-ink);background:var(--surface-2)}
.low-badge{display:inline-flex;align-items:center;justify-content:center;min-width:16px;height:16px;padding:0 4px;font-size:10px;font-weight:var(--fw-bold);color:#fff;background:var(--red);border-radius:var(--radius)}
.stock-bar{display:flex;align-items:center;gap:9px;flex-wrap:nowrap;padding:11px 12px;border-bottom:1px solid var(--border)}
.stock-panel .dbt-wrap{border:none;border-radius:0;background:transparent}
.stock-bar .help-search{margin-left:0;flex:1 1 140px;min-width:0;max-width:none}
.stock-sel{flex:0 0 auto;width:auto;min-width:150px;font-size:12.5px}
.stock-count{flex:0 0 auto;font-size:12px;color:var(--text-faint);font-family:'IBM Plex Mono';white-space:nowrap}
.stock-bar .nt-arch,.stock-bar .onu-filter,.stock-bar .btn{flex:0 0 auto}
/* tabla */
/* tabla densa estilo planilla / Excel (grilla, encabezado sombreado, zebra) */
.dbt-wrap{border:1px solid var(--border-strong);border-radius:var(--radius);background:var(--surface-2);overflow:hidden}
@media(max-width:760px){ .dbt-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch} }
.dbt-body{display:flex;flex-direction:column}
.dbt-head,.dbt-row{display:grid;align-items:stretch;gap:0}
.dbt-head>*,.dbt-row>*{min-width:0;padding:3px 10px;border-right:1px solid var(--border);border-bottom:1px solid var(--border);display:flex;align-items:center;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}
.dbt-head>*:last-child,.dbt-row>*:last-child{border-right:none}
.dbt-head{position:sticky;top:0;z-index:3}
.dbt-head>*{background:var(--surface-3,var(--surface-2));border-bottom:2px solid var(--border-strong);font-size:11px;text-transform:uppercase;letter-spacing:.03em;color:var(--text-faint);font-weight:var(--fw-bold);user-select:none}
.dbt-row{font-size:12.5px;content-visibility:auto;contain-intrinsic-size:auto 28px}
.dbt-row:nth-child(even){background:var(--zebra)}
.dbt-row:hover{background:var(--surface)}
.dbt-row.low{background:#c2555f14}
.dbt-row.low:hover{background:#c2555f22}
.db-th[data-sort]{cursor:pointer}
.db-th[data-sort]:hover{color:var(--text)}
.db-arr{font-style:normal;color:var(--accent-ink);font-size:11px;margin-left:3px}
.dbt-head .r,.dbt-row .r{justify-content:flex-end;text-align:right}
.dbt-row select,.dbt-row input{max-width:100%}
.db-name{font-weight:var(--fw-semi);min-width:0}
.db-cat,.db-mut{color:var(--text-faint);font-size:12.5px}
/* Señal RX/TX en la lista del Monitor OLT: el RX (dato clave) se colorea por calidad (verde/ámbar/rojo) y el TX en tono legible — el gris tenue no contrastaba en tema oscuro. */
.db-sig{font-size:12.5px;font-weight:var(--fw-bold)}
.db-sig.ok{color:var(--green)}.db-sig.warn{color:var(--amber)}.db-sig.bad{color:var(--red)}
.db-tx{color:var(--text-dim);font-size:12.5px}
.db-serial{font-family:'IBM Plex Mono';font-weight:var(--fw-semi);font-size:12.5px}
.db-qty{gap:6px;justify-content:flex-end}
.db-qty b{min-width:34px;text-align:right;font-family:'IBM Plex Mono';font-weight:var(--fw-bold);font-size:13.5px}
.dbt-row.low .db-qty b{color:var(--red)}
.qb{width:22px;height:22px;flex:0 0 auto;border:1px solid var(--border);background:var(--surface);color:var(--text-faint);border-radius:var(--radius-sm);cursor:pointer;font-size:14px;line-height:1;padding:0;display:inline-flex;align-items:center;justify-content:center}
.qb.in:hover{color:var(--green);border-color:var(--green)}
.qb.out:hover{color:var(--amber);border-color:var(--amber)}
.db-dot{font-size:10px;font-weight:var(--fw-bold);padding:2px 9px;border-radius:var(--radius);text-transform:uppercase}
.db-dot.ok{color:var(--green);background:#4f9e781a}
.db-dot.low{color:#fff;background:var(--red)}
.db-acts{display:flex;align-items:center;gap:4px;justify-content:flex-end}
.stk-b{width:28px;height:28px;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--border);background:var(--surface);color:var(--text-faint);border-radius:var(--radius-sm);cursor:pointer;font-size:16px;line-height:1;padding:0}
.stk-b:hover{color:var(--text);border-color:var(--border-strong)}
.stk-b svg{width:14px;height:14px}
.db-ticket{display:flex;align-items:center;gap:4px;min-width:0}
.db-ticket .inp{font-size:12px;padding:5px 8px;min-width:0}
.onu-st{font-size:12.5px;padding:5px 7px}
.onu-st.st-instalado{color:var(--green)} .onu-st.st-baja{color:var(--red)}
.onu-open{display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;flex:0 0 auto;color:var(--text-faint);border-radius:var(--radius-sm)}
.onu-open:hover{color:var(--accent-ink)}
.onu-open svg{width:14px;height:14px}
.onu-filter{display:flex;gap:5px;flex-wrap:wrap}
.onu-fb{padding:6px 10px;border:1px solid var(--border);background:var(--surface-2);color:var(--text-faint);border-radius:var(--radius);font-size:12px;font-weight:var(--fw-semi);cursor:pointer}
.onu-fb.on{color:var(--text);border-color:var(--border-strong);background:var(--surface)}
.mv-ty{font-weight:var(--fw-bold);white-space:nowrap}
.db-note{font-size:12px}
/* Insumos por categorías (secciones colapsables) */
.stk-lowbar{display:flex;align-items:center;gap:8px;background:#c2555f14;border:none;border-bottom:1px solid var(--border);color:var(--red);border-radius:0;padding:9px 13px;font-size:12.5px;margin:0}
.stk-sec{border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2);margin-bottom:10px;overflow:hidden}
.stk-sec-h{width:100%;display:flex;align-items:center;gap:10px;padding:12px 15px;background:none;border:none;color:var(--text);cursor:pointer;font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:13.5px;text-align:left}
.stk-sec-h svg{width:15px;height:15px;color:var(--text-faint);transition:transform .2s;flex:0 0 auto}
.stk-sec.collapsed .stk-sec-h svg{transform:rotate(-90deg)}
.stk-sec-nm{flex:0 0 auto}
.stk-sec-low{margin-left:auto;font-size:11px;font-weight:var(--fw-bold);color:#fff;background:var(--red);border-radius:var(--radius);padding:2px 9px}
.stk-sec.collapsed .stk-sec-body{display:none}
.stk-sec-body{border-top:1px solid var(--border);padding:6px 8px}
.stk-irow{display:grid;grid-template-columns:minmax(0,1fr) 168px 92px 70px 76px;align-items:center;gap:10px;padding:8px 9px;border-radius:var(--radius);content-visibility:auto;contain-intrinsic-size:auto 42px}
.stk-irow>*{min-width:0}
.stk-irow+.stk-irow{margin-top:2px}
.stk-irow:hover{background:var(--surface)}
.stk-irow.low{box-shadow:inset 3px 0 0 var(--red)}
.stk-iname{font-size:13.5px;font-weight:var(--fw-semi);display:flex;flex-direction:column;gap:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.stk-iname small{font-size:10px;color:var(--text-faint);font-family:'IBM Plex Mono';font-weight:var(--fw-normal)}
.stk-iqty{display:flex;align-items:center;gap:6px;justify-content:flex-end}
.stk-iqty b{min-width:40px;text-align:right;font-family:'IBM Plex Mono';font-weight:var(--fw-bold);font-size:14px}
.stk-iqty small{color:var(--text-faint);font-size:11px;width:22px}
.stk-irow.low .stk-iqty b{color:var(--red)}
.stk-imin{color:var(--text-faint);font-size:12px;font-family:'IBM Plex Mono';text-align:right}
.stk-iest{display:flex;justify-content:flex-start}
.stk-iacts{display:flex;gap:5px;justify-content:flex-end}
.dbt-ins{grid-template-columns:minmax(0,2fr) minmax(0,1.1fr) minmax(0,0.9fr) 118px 68px 76px 74px 68px}
.dbt-onu{grid-template-columns:90px minmax(0,1.2fr) minmax(0,1.1fr) minmax(0,0.9fr) 124px minmax(0,1.3fr) 44px}
.pager{display:flex;align-items:center;gap:6px;flex-wrap:wrap;padding:10px 4px 2px}
.pg-b{min-width:32px;height:32px;padding:0 9px;border:1px solid var(--border);background:var(--surface-2);color:var(--text);border-radius:var(--radius);cursor:pointer;font-size:12.5px}
.pg-b:hover:not(:disabled){border-color:var(--accent-ink)} .pg-b.on{background:var(--selected);color:var(--text);border-color:var(--accent-ink);font-weight:var(--fw-semi)}
.pg-b:disabled{opacity:.4;cursor:default} .pg-x{color:var(--text-faint);padding:0 2px}
.pg-info{margin-left:auto;color:var(--text-faint);font-size:12px}
/* ===== Stock Oficina (app-shell: marco fijo, menú fijo, contenido encastrado) ===== */
#stockView.on,#helpView.on,#statsView.on,#histView.on,#configView.on,#planosView.on,#oltView.on,#rtView.on,#planView.on,#zonasView.on,#repView.on,#supView.on,#cajasView.on,#recoordView.on,#pruebaView.on,#avanceView.on,#hoyView.on{display:flex;padding:0;overflow:hidden}
#stockWrap,#helpWrap,#statsWrap,#histWrap,#configWrap,#planosWrap,#oltWrap,#rtWrap,#planWrap,#zonasWrap,#cajasWrap,#recoordWrap,#pruebaWrap,#avanceWrap,#hoyWrap,#respWrap,#sopregWrap,#lupaWrap,#missopWrap,#vistazoWrap{flex:1;min-height:0;display:flex}
#oltView,#rtView,#planView,#zonasView,#repView,#earthView,#cajasView,#recoordView,#pruebaView,#avanceView,#hoyView{flex:1;display:none;overflow:hidden;padding:0}
#earthView.on{display:flex}
#respView, #sopregView, #lupaView, #missopView, #vistazoView{flex:1;display:none;overflow:hidden;padding:0}
#respView.on, #sopregView.on, #lupaView.on, #missopView.on, #vistazoView.on{display:flex}
#earthWrap{flex:1;position:relative;min-height:0;display:flex}
#earthMap{position:relative;flex:1;min-height:0;z-index:1;background:var(--bg-2)}
.earth-panel{position:absolute;top:56px;left:12px;bottom:12px;z-index:600;width:min(320px,calc(100% - 24px));display:flex;flex-direction:column;background:var(--surface);border:1px solid var(--border-strong);border-radius:var(--radius);box-shadow:0 10px 34px rgba(0,0,0,.4);overflow:hidden}
.earth-tree{display:flex;flex-direction:column;gap:1px;margin:2px 0 6px}
.et-row{display:flex;align-items:center;gap:6px;padding:5px 4px;border-radius:var(--radius-sm)}
.et-row:hover{background:var(--surface-2)}
.et-exp{width:16px;height:16px;flex:0 0 auto;display:flex;align-items:center;justify-content:center;color:var(--text-faint);cursor:pointer;font-size:10px;transition:transform .15s}
.et-exp.open{transform:rotate(90deg)}
.et-exp.leaf{visibility:hidden}
.et-chk{width:15px;height:15px;flex:0 0 auto;accent-color:var(--signal);cursor:pointer}
.et-name{flex:1;min-width:0;font-size:12.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:pointer}
.et-cnt{font-size:11px;color:var(--text-faint);flex:0 0 auto}
.et-row.et-off .et-name{color:var(--text-faint)}
.earth-fl-h{display:flex;align-items:center;gap:8px;padding:2px 2px}
.earth-fbtns{display:flex;gap:6px;margin:2px 0 4px}
.earth-fbtns button{flex:1;padding:6px;border-radius:var(--radius-sm);border:1px solid var(--border);background:var(--surface-2);color:var(--text-dim);font-size:12px;font-weight:var(--fw-semi);cursor:pointer}
.earth-fbtns button:hover{color:var(--text)}
.earth-ph{display:flex;align-items:center;gap:9px;padding:12px 14px;border-bottom:1px solid var(--border)}
.earth-ph b{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:14px}
.earth-ph svg{width:18px;height:18px;color:var(--accent-ink);flex:0 0 auto}
.earth-body{padding:10px 12px;overflow-y:auto;display:flex;flex-direction:column;gap:8px;flex:1;min-height:0}
.earth-up{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;border:1px dashed var(--border-strong);border-radius:var(--radius);padding:12px;color:var(--accent-ink);font-weight:var(--fw-bold);font-size:13.5px;cursor:pointer;background:var(--surface-2)}
.earth-up:hover{border-color:var(--accent-ink)}
.earth-list{display:flex;flex-direction:column;gap:6px}
.earth-legend{margin-top:4px;padding:9px 11px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);display:flex;flex-wrap:wrap;gap:5px 12px;font-size:12px;color:var(--text-dim)}
.earth-legend .el-t{flex:1 1 100%;font-weight:var(--fw-bold);color:var(--text);font-size:12px;margin-bottom:2px}
.earth-legend span{display:inline-flex;align-items:center;gap:5px;white-space:nowrap}
.earth-legend i{font-style:normal;font-size:13.5px;line-height:1}
.earth-row{display:flex;align-items:center;gap:9px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:9px 10px}
.earth-row .er-chk{width:16px;height:16px;flex:0 0 auto;accent-color:var(--signal)}
.earth-row .er-main{flex:1;min-width:0}
.earth-row .er-name{font-size:12.5px;font-weight:var(--fw-semi);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.earth-row .er-sub{font-size:11px;color:var(--text-faint)}
.earth-row .er-del{display:flex;align-items:center;justify-content:center;width:34px;height:34px;border-radius:var(--radius);background:var(--surface-3);border:1px solid var(--border);color:var(--red);cursor:pointer;flex:0 0 auto}
.earth-row .er-del svg{width:17px;height:17px}
.earth-row .er-del:hover{background:rgba(220,85,99,.16);border-color:var(--red)}
.earth-empty{color:var(--text-dim);font-size:12.5px;text-align:center;padding:10px 6px}
.earth-msg{font-size:12px;padding:7px 9px;border-radius:var(--radius)}
.earth-msg.err{background:rgba(220,85,99,.14);color:var(--red)} .earth-msg.ok{background:rgba(63,185,138,.14);color:var(--green)}
.earth-base{position:absolute;bottom:12px;right:12px;z-index:600;display:flex;gap:4px;background:rgba(14,18,28,.9);border:1px solid var(--border);border-radius:var(--radius);padding:4px}
.earth-base button{padding:6px 11px;border-radius:var(--radius-sm);font-size:12.5px;font-weight:var(--fw-bold);color:var(--text-dim);background:none;border:0;cursor:pointer}
.earth-base button.on{background:var(--selected);color:var(--text);border-color:var(--accent-ink)}
@media(max-width:760px){ .earth-panel{width:calc(100% - 24px);bottom:auto;max-height:58%} }
@media(max-width:760px){
  #cajasWrap{padding-top:0}                       /* ya no hay barra fija que despejar */
}
/* Pasa a ser columna y NO scrollea él: ahora adentro hay un .so-panel, y el que tiene que
   scrollear es el cuerpo del panel, para que la barra de título quede fija como en el resto del
   sistema. Si scrolleara el contenedor, el título se iría de pantalla al bajar. */
#repWrap{flex:1;min-height:0;display:flex;flex-direction:column;width:100%}
/* NACIÓ PARA EL CELULAR: una columna de 820 px centrada, que en el teléfono es exactamente lo que
   corresponde. Desde el sistema esa misma columna deja media pantalla vacía y obliga a scrollear 120
   zonas de a una. En pantalla ancha se ensancha y las zonas van en grilla; el panel de trabajo sigue
   en columna, porque ahí se lee una lista de equipos y a lo ancho se perdería el renglón. */
/* Dentro del panel: la barra va a todo el ancho como en el resto del sistema y el contenido sigue
   siendo una columna centrada, que es lo que le da su forma a esta pantalla. */
.rep-wrap{max-width:820px;margin:0 auto;padding:14px 14px 40px}
/* Adentro del Monitor OLT el contenido cuelga del cuerpo del panel, que no lleva padding propio:
   el margen lateral lo pone acá, como el `so-pad` de las demás pantallas del módulo. */
#oltMain .rep-wrap{padding:14px 16px 24px}
.rep-h{display:flex;align-items:center;gap:10px;margin:2px 0 14px}
.rep-h h2{font-size:19px;font-weight:var(--fw-black);margin:0;letter-spacing:-.01em}
.rep-h .rep-sub{color:var(--text-dim);font-size:12.5px}
/* Sin el h2, el icono y el subtitulo van en un solo renglon a la misma altura. */
.rep-h.rep-h-sub{align-items:center;gap:9px;margin:2px 0 12px}
.rep-h.rep-h-sub .rep-sub{font-size:13.5px}
.rep-sect-t{font-size:12px;font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:.06em;color:var(--text-faint);margin:16px 2px 8px}
.rep-search{width:100%;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:11px 13px;color:var(--text);font-size:14px}
.rep-stick{position:sticky;top:0;z-index:6;background:var(--bg);padding-top:4px;margin-top:-4px}
#oltMain .rep-stick{background:var(--panel-bg,var(--surface))}
.rep-zcount{color:var(--text-faint);font-weight:var(--fw-semi);font-size:11px}
.rep-zlist{display:flex;flex-direction:column;gap:7px;margin-top:8px}
.rep-zrow{display:flex;align-items:center;gap:12px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:11px 13px;cursor:pointer;text-align:left;width:100%;transition:border-color .12s,background .12s}
.rep-zrow:hover{border-color:var(--border-strong);background:var(--surface-2)}
.rep-zrow.down{border-left:3px solid var(--red)}
.rep-zrow .rz-dot{width:10px;height:10px;border-radius:var(--radius-circ);flex:none}
.rep-zrow .rz-main{flex:1;min-width:0}
.rep-zrow .rz-zona{font-weight:var(--fw-bold);font-size:14px}
.rep-zrow .rz-meta{color:var(--text-dim);font-size:12.5px;margin-top:1px}
.rep-zrow .rz-go{color:var(--text-faint);flex:none}
.rz-dot.ok{background:var(--green)}.rz-dot.bad{background:var(--red)}.rz-dot.off{background:var(--text-faint)}
.rep-manual{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:12px 14px;margin-top:6px}
.rep-manual summary{cursor:pointer;font-weight:var(--fw-semi);font-size:13.5px;color:var(--text-dim)}
.rep-mrow{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin-top:12px}
.rep-mrow select{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:9px 11px;color:var(--text);font-size:13.5px;flex:1;min-width:150px}
.rep-gbtns{display:flex;gap:7px;flex-wrap:wrap}
.rep-gbtn{width:42px;height:42px;border-radius:var(--radius);border:1px solid var(--border);background:var(--surface-2);color:var(--text);font-weight:var(--fw-bold);font-size:14px;cursor:pointer}
.rep-gbtn:hover{border-color:var(--border-strong)}
.rep-back{display:inline-flex;align-items:center;gap:6px;background:none;border:none;color:var(--accent-ink);font-size:13.5px;font-weight:var(--fw-semi);cursor:pointer;padding:4px 0;margin-bottom:8px}
.rep-panel{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:16px;margin-top:4px}
.rep-ptop{display:flex;align-items:flex-start;gap:12px;margin-bottom:14px}
.rep-ptop .rp-zona{font-size:18px;font-weight:var(--fw-black);letter-spacing:-.01em}
.rep-ptop .rp-meta{color:var(--text-dim);font-size:12.5px;margin-top:2px}
.rep-ptop .rp-dot{width:11px;height:11px;border-radius:var(--radius-circ);margin-top:6px;flex:none}
/* Los dos botones del panel van UNO AL LADO DEL OTRO en pantalla ancha —«ver cómo va» y «cerrar» son
   la decisión del momento y conviene verlos juntos— y apilados en el teléfono, que es donde la
   columna manda. La pantalla nació para el celular; ahora también se usa desde el sistema. */
.rep-actions{display:flex;flex-wrap:wrap;gap:10px;margin:6px 0 4px}
.rep-actions .rep-btn{flex:1 1 220px}
@media(max-width:560px){ .rep-actions{flex-direction:column} }
/* Lo que quedó a medio hacer, arriba de todo: es lo primero que uno necesita ver al entrar. */
.rep-abiertas{margin:10px 0 4px;padding:12px;border:1px solid var(--amber);border-radius:var(--radius);
  background:color-mix(in srgb,var(--amber) 8%,transparent)}
.rep-arow{display:flex;align-items:center;gap:11px;width:100%;text-align:left;padding:10px 12px;margin-top:7px;
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);color:var(--text);
  font:inherit;cursor:pointer;transition:.13s}
.rep-arow:hover{border-color:var(--accent-ink)}
.rep-arow .ra-ic{font-size:16px;flex:none}
.rep-arow .ra-go{color:var(--accent-ink);font-weight:var(--fw-bold);font-size:12.5px;flex:none}
.rep-tag-ab{display:inline-block;font-size:10px;font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:.05em;
  color:var(--amber);background:color-mix(in srgb,var(--amber) 16%,transparent);padding:2px 8px;border-radius:var(--radius);
  vertical-align:middle;margin-left:6px}
.rep-zrow.abierta{border-color:var(--amber)}
/* El saldo: el número que contesta «¿sirvió?». Va grande porque es lo que se informa y lo que se
   recuerda; el desglose por equipo queda abajo para el que quiere el detalle. */
.rep-saldo{display:flex;align-items:center;gap:14px;padding:12px 14px;margin:4px 0 10px;
  background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius)}
.rep-saldo .rs-n{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:27px;line-height:1;letter-spacing:-.02em}
.rep-saldo .rs-t b{display:block;font-size:13.5px}
.rep-saldo .rs-t span{display:block;color:var(--text-faint);font-size:12px;margin-top:2px}
.rep-nota{margin:10px 0 4px}
.rep-nota label{display:block;font-size:12px;color:var(--text-dim);margin-bottom:5px}
.rep-nota input{width:100%;box-sizing:border-box;background:var(--surface-2);border:1px solid var(--border-strong);
  border-radius:var(--radius);padding:9px 11px;color:var(--text);font:inherit;font-size:13.5px}
.rep-nota input:focus{outline:0;border-color:var(--accent-ink)}
.rep-notaver{padding:10px 12px;margin:0 0 10px;background:var(--surface-2);border-radius:var(--radius);font-size:13.5px}
.rep-tk tbody tr{cursor:pointer}
/* ===== Dónde está el corte ===== */
.cor-card{padding:14px 16px;margin:0 0 10px}
.cor-h{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap;margin-bottom:7px}
.cor-lbl{font-size:11px;font-weight:var(--fw-black);letter-spacing:.07em}
.cor-h b{font-size:15px}
.cor-meta{color:var(--text-faint);font-size:12px}
.cor-n{font-size:13.5px;margin-bottom:8px}
.cor-n b{font-size:16px}
.cor-vivo{color:var(--red);font-weight:var(--fw-bold)}
.cor-ok{color:var(--green)}
.cor-nota{font-size:12.5px;color:var(--text-dim);background:var(--surface-2);padding:8px 11px;border-radius:var(--radius);margin-bottom:8px}
/* El tramo es la conclusión: va destacado porque es lo que decide a dónde sale la cuadrilla. */
.cor-tramo{font-size:13.5px;padding:10px 12px;border-radius:var(--radius);margin-bottom:9px;
  background:color-mix(in srgb,var(--red) 9%,transparent);border:1px solid color-mix(in srgb,var(--red) 30%,transparent)}
.cor-tramo a{color:var(--accent-ink);font-weight:var(--fw-bold)}
.cor-tramo-t{background:color-mix(in srgb,var(--amber) 9%,transparent);border-color:color-mix(in srgb,var(--amber) 30%,transparent)}
.cor-tramo-flojo{background:var(--surface-2);border-color:var(--border);color:var(--text-dim)}
.cor-cajas{display:flex;flex-wrap:wrap;gap:7px}
.cor-caja{display:flex;flex-direction:column;gap:1px;padding:7px 11px;border-radius:var(--radius);background:var(--surface-2);
  border:1px solid var(--border);color:var(--text);text-decoration:none;font-size:12px;transition:.13s}
.cor-caja:hover{border-color:var(--accent-ink)}
.cor-caja b{font-size:12.5px}
.cor-caja span{color:var(--text-faint)}
/* La caja que perdió TODOS sus clientes es la que marca el tramo: se ve distinta de las parciales. */
.cor-caja.entera{border-color:var(--red);background:color-mix(in srgb,var(--red) 10%,transparent)}
/* ===== Clientes reincidentes ===== */
.re-ab{display:inline-block;font-size:11px;font-weight:var(--fw-bold);color:var(--red);
  background:color-mix(in srgb,var(--red) 13%,transparent);padding:2px 9px;border-radius:var(--radius)}
.re-vec{display:inline-block;font-size:12px;font-weight:var(--fw-bold);color:var(--amber);
  background:color-mix(in srgb,var(--amber) 14%,transparent);padding:2px 9px;border-radius:var(--radius)}
.re-cajas{display:flex;flex-wrap:wrap;gap:8px;padding:12px 14px}
.re-caja{display:flex;flex-direction:column;gap:1px;padding:8px 12px;border-radius:var(--radius);background:var(--surface-2);
  border:1px solid var(--border);color:var(--text);text-decoration:none;font-size:12px;transition:.13s}
.re-caja:hover{border-color:var(--accent-ink)}
.re-caja b{font-size:13.5px} .re-caja span{color:var(--text-faint)}
.re-caja-s{font-family:ui-monospace,monospace;font-size:11px}
/* Las pruebas debajo del veredicto en «Caídas de clientes». Se leen si las buscás y no le pelean el
   renglón al veredicto, que es lo que se mira de un vistazo. El ancho tope es para que la columna no
   se coma la tabla: sin él, «se quedó sin energía 4 veces sin que cayera ningún vecino» estira la
   celda y empuja la señal y los vecinos fuera de la pantalla. */
.fl-pistas{display:block;margin-top:3px;color:var(--text-dim);font-size:11px;line-height:1.45;
  max-width:270px;white-space:normal}
.fl-mas{display:inline-block;margin-left:6px;color:var(--text-faint);border-bottom:1px dotted var(--border);cursor:help}
/* De tres para arriba ya casi no es casualidad, y en una lista de cincuenta chapitas eso tiene que
   verse sin leer el numerito de cada una. */
.re-caja-alta{border-color:color-mix(in srgb,var(--amber) 55%,transparent);
  background:color-mix(in srgb,var(--amber) 9%,var(--surface-2))}
/* ===== Reclamos abiertos ===== */
.rec-tag{display:inline-block;font-size:11px;font-weight:var(--fw-bold);padding:3px 10px;border-radius:var(--radius);white-space:nowrap}
.rec-que{font-size:12.5px;color:var(--text-dim);max-width:280px}
/* La acción va destacada: es lo único que hay que leer si se está apurado. */
.rec-acc{font-size:12.5px;max-width:300px;color:var(--text)}
/* ===== Parte del mes ===== */
.pa-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:11px}
.pa-b{padding:14px 16px;border-radius:var(--radius);background:var(--surface-2);border:1px solid var(--border)}
.pa-t{font-size:11px;font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:.06em;color:var(--text-dim)}
.pa-n{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:29px;line-height:1.1;margin:6px 0 2px;letter-spacing:-.02em}
.pa-s{font-size:12px;color:var(--text-faint)}
.pa-c{margin-top:9px;font-size:12.5px}
/* La diferencia se pinta por lo que SIGNIFICA, no por el signo: menos cortes es verde aunque sea un
   número negativo. */
.pa-d{font-weight:var(--fw-black)} .pa-d.ok{color:var(--green)} .pa-d.mal{color:var(--red)}
.pa-vs{color:var(--text-faint);font-size:12px}
.pa-igual{color:var(--text-faint)}
.pa-sin{color:var(--amber);font-size:12px}
.pa-fr{font-size:12px;color:var(--text-dim)}
.wn-mas{margin-top:10px;font-size:12.5px;color:var(--text-faint)}
/* ===== Qué hacer hoy ===== */
.prio-list{display:flex;flex-direction:column;gap:8px}
/* Cada renglón es una decisión: número de orden, qué es, qué hacer y cuánto pesa. Se toca y lleva
   a la pantalla donde está el detalle. */
.prio-it{display:flex;align-items:flex-start;gap:12px;padding:12px 14px;border-radius:var(--radius);
  background:var(--surface-2);border:1px solid var(--border);border-left-width:3px;cursor:pointer;transition:.13s}
.prio-it:hover{border-color:var(--accent-ink);background:var(--surface)}
.prio-it.prio-nodo{border-left-color:var(--red)}
.prio-it.prio-corte{border-left-color:var(--red)}
.prio-it.prio-gpon{border-left-color:var(--amber)}
.prio-it.prio-caja{border-left-color:var(--amber)}
.prio-it.prio-cliente{border-left-color:var(--text-faint)}
.prio-n{flex:0 0 26px;text-align:center;font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:14px;color:var(--text-faint);padding-top:2px}
.prio-ic{flex:0 0 auto;color:var(--accent-ink);padding-top:2px}
.prio-ic svg{width:19px;height:19px}
.prio-m{flex:1;min-width:0}
.prio-h{display:flex;align-items:baseline;gap:9px;flex-wrap:wrap}
.prio-acc{font-size:10px;font-weight:var(--fw-black);letter-spacing:.06em;text-transform:uppercase;color:var(--accent-ink);
  background:color-mix(in srgb,var(--signal) 14%,transparent);padding:2px 8px;border-radius:var(--radius);flex:0 0 auto}
.prio-h b{font-size:13.5px}
.prio-d{font-size:12.5px;color:var(--text-dim);margin-top:4px}
.prio-p{font-size:12px;color:var(--text-faint);margin-top:4px;font-style:italic}
.prio-s{flex:0 0 auto;text-align:right;padding-left:6px}
.prio-s b{display:block;font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:19px;line-height:1}
.prio-s span{display:block;font-size:11px;color:var(--text-faint);margin-top:3px}
@media(max-width:640px){
  .prio-it{flex-wrap:wrap}
  .prio-s{width:100%;text-align:left;padding-left:38px;display:flex;align-items:baseline;gap:7px}
  .prio-s b{font-size:15px}
}

.cor-inter{font-size:12.5px;padding:9px 12px;border-radius:var(--radius);margin:0 0 9px;color:var(--text);
  background:color-mix(in srgb,var(--amber) 10%,transparent);border:1px solid color-mix(in srgb,var(--amber) 32%,transparent)}
.cor-tanda{display:flex;flex-wrap:wrap;gap:6px;margin-top:7px}
.cor-tanda span{font-size:12px;color:var(--text-dim);background:var(--surface-2);padding:3px 8px;border-radius:var(--radius)}
.cor-tanda i{font-style:normal;font-weight:var(--fw-bold);color:var(--text)}
.cor-pend{font-size:12.5px;padding:10px 12px;border-radius:var(--radius);margin:0 0 9px;
  background:var(--surface-2);border:1px solid var(--border)}
.cor-pendl{display:flex;flex-wrap:wrap;gap:7px;margin-top:8px}
.cor-pendl a{display:flex;flex-direction:column;gap:1px;padding:6px 11px;border-radius:var(--radius);background:var(--surface);
  border:1px solid var(--border-strong);color:var(--text);text-decoration:none;font-size:12.5px;font-weight:var(--fw-semi)}
.cor-pendl a:hover{border-color:var(--accent-ink);color:var(--accent-ink)}
.cor-pendl a span{font-weight:var(--fw-normal);font-size:11px;color:var(--text-faint)}

/* VA AL FINAL A PROPOSITO: un @media no suma especificidad, así que si esto fuera antes de
   `.rep-zlist{display:flex}` la regla base ganaría por ir después y la grilla no se aplicaría.
   (Pasó: se desplegó, se vio una sola columna y el getComputedStyle engañaba porque
   grid-template-columns devuelve valor aunque el display no sea grid.) */
}

.rep-btn{display:flex;align-items:center;justify-content:center;gap:9px;width:100%;border:none;border-radius:var(--radius);padding:15px;font-size:15px;font-weight:var(--fw-bold);cursor:pointer}
.rep-btn:disabled{opacity:.5;cursor:default}
.rep-btn.primary{background:var(--signal);color:var(--on-signal)}
.rep-btn.second{background:var(--surface-3);color:var(--text);border:1px solid var(--border-strong)}
.rep-baseinfo{display:flex;align-items:center;gap:8px;flex-wrap:wrap;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:10px 12px;font-size:12.5px;color:var(--text-dim);margin:2px 0 6px}
.rep-reset{background:none;border:none;color:var(--accent-ink);font-size:12.5px;font-weight:var(--fw-semi);cursor:pointer;margin-left:auto;padding:0}
.rep-sum{display:flex;gap:8px;flex-wrap:wrap;margin:12px 0}
.rep-chip{display:flex;align-items:baseline;gap:6px;border-radius:var(--radius);padding:8px 12px;font-size:12.5px;font-weight:var(--fw-semi);border:1px solid var(--border)}
.rep-chip b{font-size:17px;font-weight:var(--fw-black)}
.rep-chip.g{background:rgba(63,185,138,.12);border-color:rgba(63,185,138,.35);color:var(--green)}
.rep-chip.up{background:rgba(63,185,138,.08);color:var(--green)}
.rep-chip.dn{background:rgba(220,85,99,.12);border-color:rgba(220,85,99,.35);color:var(--red)}
.rep-chip.warn{background:rgba(217,146,47,.12);border-color:rgba(217,146,47,.35);color:var(--amber)}
.rep-chip.mut{color:var(--text-dim)}
.rep-onts{display:flex;flex-direction:column;gap:7px;margin-top:6px}
.rep-ont{display:flex;align-items:center;gap:11px;background:var(--surface-2);border:1px solid var(--border);border-left-width:3px;border-radius:var(--radius);padding:11px 12px}
.rep-ont.st-recuperada{border-left-color:var(--green)}
.rep-ont.st-mejoro{border-left-color:var(--green)}
.rep-ont.st-empeoro{border-left-color:var(--amber)}
.rep-ont.st-cayo{border-left-color:var(--red)}
.rep-ont.st-igual{border-left-color:var(--border-strong)}
.rep-ont .ro-main{flex:1;min-width:0}
.rep-ont .ro-sn{font-weight:var(--fw-bold);font-size:13.5px;font-family:var(--mono,monospace);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.rep-ont .ro-sub{color:var(--text-dim);font-size:12px;margin-top:1px}
.rep-ont .ro-sig{text-align:right;flex:none}
.rep-ont .ro-rx{font-weight:var(--fw-black);font-size:14px;font-variant-numeric:tabular-nums}
.rep-ont .ro-rx.ok{color:var(--green)}.rep-ont .ro-rx.warn{color:var(--amber)}.rep-ont .ro-rx.err{color:var(--red)}
.rep-ont .ro-tag{font-size:11px;font-weight:var(--fw-bold);margin-top:2px}
.rep-ont .ro-tag.g{color:var(--green)}.rep-ont .ro-tag.dn{color:var(--red)}.rep-ont .ro-tag.warn{color:var(--amber)}.rep-ont .ro-tag.mut{color:var(--text-faint)}
.rep-empty{text-align:center;color:var(--text-dim);font-size:13.5px;padding:22px 10px}
.rep-msg{font-size:12.5px;padding:9px 12px;border-radius:var(--radius);margin-top:8px}
.rep-msg.err{background:rgba(220,85,99,.12);color:var(--red)}
.rep-spin{display:inline-block;width:15px;height:15px;border:2px solid currentColor;border-right-color:transparent;border-radius:var(--radius-circ);animation:repspin .7s linear infinite;vertical-align:-2px}
/* PANTALLA COMPLETA en el navegador. La columna centrada de 820 px es la que corresponde en el
   teléfono, pero en el sistema esta pantalla ocupa una vista entera y tiene que llenarla como las
   demás: sin tope de ancho y con el mismo margen lateral que el resto (22 px). */
@media(min-width:1000px){
  .rep-wrap{max-width:none;margin:0;padding:18px 22px 44px}
  /* Las zonas se acomodan solas: cuantas entren de 300 px. En un monitor ancho son cinco o seis por
     renglón en vez de tres, que es de lo que se trata aprovechar la pantalla. */
  .rep-zlist{display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:9px}
  /* El panel tampoco tiene tope. El de 1100 px se puso pensando que estirarlo dejaría el serial en
     una punta y la señal en la otra, pero eso vale para renglones a lo ancho, y los equipos ya se
     muestran en tarjetas dentro de una grilla: estirar el panel no estira la tarjeta, agrega otra
     columna. Medido en un monitor de 1600: sobraban 254 px a la derecha y los equipos entraban de
     a tres cuando entran cinco.
     Lo que sí conserva un tope son los CONTROLES: un campo de nota de 1.300 px o dos botones de
     660 px no se leen mejor, se leen peor. Van a un ancho de lectura y pegados a la izquierda,
     para que al volver de la lista nada salte de lugar. */
  .rep-panel,.rep-back{max-width:none}
  .rep-actions,.rep-nota,.rep-notaver,.rep-baseinfo,.rep-saldo,.rep-sum{max-width:940px}
  /* Y los equipos aprovechan todo. Cada tarjeta lleva el serial, el número de ONT y la señal: con
     250 px alcanza y sobra (medido, el contenido ocupa unos 210). Así entran cinco por renglón en
     1600 px y seis en 1920, y un GPON de 87 ONT pasa de 29 renglones a 18. */
  .rep-onts{display:grid;grid-template-columns:repeat(auto-fill,minmax(238px,1fr));gap:7px}
}

@keyframes repspin{to{transform:rotate(360deg)}}
/* ===== Módulo Zonas (fichero por zona) ===== */
.zn-side{display:flex;flex-direction:column;min-width:0}
.zn-search{padding:10px 12px;border-bottom:1px solid var(--border)}
.zn-list{flex:1;overflow:auto;padding:6px}
.zn-item{display:flex;align-items:stretch;width:100%;border:1px solid transparent;border-radius:var(--radius);overflow:hidden;transition:.1s}
.zn-item:hover{background:var(--surface-2)}
.zn-item.on{background:color-mix(in srgb,var(--signal) 16%,var(--surface-2));box-shadow:inset 3px 0 0 var(--accent-ink)}
.zn-item-main{flex:1;min-width:0;text-align:left;background:none;border:none;color:var(--text);padding:9px 11px;cursor:pointer;font:inherit}
.zn-item-main b{font-size:13.5px;display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.zn-item-main span{font-size:11px;color:var(--text-faint);display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;margin-top:2px}
.zn-item-edit{flex:0 0 auto;align-self:center;background:none;border:none;color:var(--text-faint);cursor:pointer;padding:6px 9px;border-radius:var(--radius-sm);margin-right:2px}
.zn-item-edit:hover{color:var(--accent-ink);background:var(--surface-3)}
.zn-item-edit svg{width:15px;height:15px;display:block}
.zn-back{display:none;align-items:center;gap:3px;background:var(--surface-2);border:1px solid var(--border);color:var(--text);border-radius:var(--radius);padding:5px 11px 5px 7px;font-size:12.5px;font-weight:var(--fw-semi);cursor:pointer;margin-right:6px}
.zn-back svg{width:16px;height:16px}
.zn-back:hover{border-color:var(--accent-ink)}
@media(max-width:760px){
  .zn-back{display:inline-flex}
  #zonasWrap .zn-wrap{flex-direction:column}
  #zonasWrap .zn-wrap .so-side{flex:1;min-height:0;overflow-x:hidden;overflow-y:auto;border-bottom:0;padding:12px 10px;gap:10px}
  #zonasWrap .zn-side .zn-list{flex:1;min-height:0;overflow:auto}
  #zonasWrap .zn-wrap .so-main{display:none}
  #zonasWrap .zn-wrap.zn-mobficha .so-side{display:none}
  #zonasWrap .zn-wrap.zn-mobficha .so-main{display:flex;flex:1;min-height:0}
}
/* Fichas de zonas: shell con toggle Fichas/Árbol */
.zn-shell{flex:1;min-width:0;display:flex;flex-direction:column}
.zn-content{flex:1;min-height:0;display:flex}
/* Una sola barra arriba y la ficha abajo. Antes eran tres barras apiladas: ~160 px antes de ver un
   solo dato, y la tercera repetía lo que ya decía el desplegable de la segunda. */
.zn-topbar{flex:0 0 auto;margin:0;padding:8px 14px;border-bottom:1px solid var(--border);background:var(--surface-2)}
#znIdent{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.zn-content>.zn-main{flex:1;min-height:0;overflow:auto}
/* LOS QUE HAY QUE IR A VER, marcados en la fila. La lista va de lo más nuevo a lo más viejo, así
   que los cortes de fibra ya no quedan agrupados arriba: se los señala acá, que es donde se leen.
   Barrita a la izquierda, el mismo recurso que usa el resto del sistema para marcar una fila. */
.sup-tk tbody tr.hoy-ir > td:first-child{box-shadow:inset 3px 0 0 var(--red)}
/* Ya tiene un reclamo abierto en Telwinet: no hace falta abrir otro. */
.fg-chip-tk{border-color:var(--text-dim);color:var(--text-dim);background:var(--surface-2)}
/* La marca de «además transmite con errores»: va pegada al dato con el que se cruza, no en una
   columna aparte, porque lo que importa es la combinación y no el dato suelto. */
.tx-mal{display:block;font-size:11px;font-weight:var(--fw-bold);line-height:1.3;margin-top:3px}
.tx-mal .mono{font-weight:var(--fw-medium);opacity:.8}
/* «Contra la última vez». Va arriba del veredicto y con su barra de color a la izquierda, que es
   el recurso que usa el resto del sistema para decir de qué se trata sin leer. */
.dg-antes{border-left:3px solid var(--text-dim);background:var(--surface-2);border-radius:0 var(--radius) var(--radius) 0;
  padding:10px 13px;margin:0 0 12px;font-size:12.5px;color:var(--text-dim)}
.dg-antes-t{color:var(--text);margin-bottom:6px}
.dg-cmb-l{display:flex;flex-direction:column;gap:4px}
.dg-cmb{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}
.dg-cmb > span:first-child{font-weight:var(--fw-semi);color:var(--text);min-width:150px}
.dg-cmb small{color:var(--text-faint);font-size:11px}
.dg-cmb-ig{color:var(--text-dim)}
/* En «¿Quedó resuelto?» el indicador ES el filtro: se toca y la tabla de abajo muestra sólo ésos.
   Es el mismo recurso que en «Qué hacer hoy», donde el KPI hace de selector. */
.gs-vk{cursor:pointer;text-align:left;font:inherit}
.gs-vk:hover{border-color:var(--border-strong)}
.gs-vk.on{border-color:var(--signal);background:color-mix(in srgb,var(--signal) 10%,transparent)}
/* La ventana del diagnóstico se abre por ENCIMA de la ficha del cliente, que ya es un diálogo
   (z-index 90): con el 60 de un scrim normal quedaba detrás y no se veía. */
#dgScrim{z-index:120;align-items:center}
/* El historial de diagnósticos de la ficha: una línea por foto guardada. */
.dgh-lista{display:flex;flex-direction:column;gap:6px}
.dgh-fila{display:flex;align-items:center;gap:10px;width:100%;text-align:left;padding:7px 10px;
  border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2);color:var(--text);
  cursor:pointer;font:inherit}
.dgh-fila:hover{border-color:var(--border-strong)}
.dgh-est{flex:0 0 auto;font-size:11px;font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:.04em;
  border:1px solid;border-radius:var(--radius-sm);padding:1px 7px}
.dgh-t{display:flex;flex-direction:column;gap:1px;min-width:0}
.dgh-t b{font-size:12.5px;font-weight:var(--fw-semi)}
.dgh-t small{font-size:11px;color:var(--text-faint)}

/* El encabezado de cada bloque en UNA fila: el número, qué es y de qué está hecho. Eran dos
   renglones (tres en reincidentes) diciendo lo mismo a distinta profundidad. Se envuelve solo en
   pantalla angosta, así que en el celular vuelve a dos renglones en vez de cortarse. */
/* ===== LA BANDA DE LA EXPLICACIÓN =====
   Ya no lleva el número ni el nombre de la lista —los dice la tira de indicadores de arriba— sino
   sólo lo que la lista agrega. Sigue siendo una banda con línea abajo, como en «La red ahora»: lo
   que separa un bloque de otro es la LÍNEA, no el aire. */
.hoy-bh{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin:0;
  padding:6px 12px;background:var(--surface-3);border-bottom:1px solid var(--border-strong)}
.hoy-bh .hoy-bh-d{font-weight:var(--fw-normal);color:var(--text-dim)}
/* LA TARJETA NO ENCAJONA. Tenía 12px 14px de relleno, así que la tabla flotaba adentro en vez de ir
   pegada a los bordes. Cada parte pone el suyo: la banda y el filtro, no la caja. */
/* DOS CLASES A PROPOSITO: `.sup-card` y `.sup-tk-card` estan mas abajo en la hoja y con una sola
   clase les ganaban por orden. Esta es la excepcion de una pantalla sobre una regla general, y el
   selector tiene que decirlo. */
.sup-card.hoy-card{padding:0;border-radius:0;overflow:hidden;margin-top:0}
.hoy-card > .hoy-bh{margin:0}
.hoy-card > .hoy-causas{margin:0}
/* Tres clases: la general `.sup-tk-card > .sup-tk-wrap` tira -14 px para cancelar el relleno de la
   tarjeta, y esta tarjeta ya no tiene relleno que cancelar. */
.sup-tk-card.hoy-card > .sup-tk-wrap{margin:0}
/* Cuando no hay nada que mostrar, el aviso queda solo adentro de la caja: sin el margen suelto. */
.hoy-card > .find-count{margin:0}
.hoy-bh .hoy-bh-n{font-family:'IBM Plex Mono';font-size:21px;font-weight:var(--fw-black);line-height:1.2;flex:0 0 auto}
.hoy-bh .hoy-bh-t{flex:0 0 auto}
/* La explicación cede espacio antes que el título: es la aclaración, no el dato. */
.hoy-bh .hoy-bh-d{flex:1 1 auto;min-width:0;font-size:12px;font-weight:var(--fw-bold);color:var(--text-faint)}

/* ===== «Qué hacer hoy»: los dos sectores, lado a lado ===== */
/* Separados en el ESPACIO y por una línea, no sólo por un título: son dos trabajos distintos. */
/* Cada sector es una CAJA cerrada, no dos mitades con una linea al medio: encabezado en franja
   arriba y el cuerpo adentro, la misma forma que las barras de titulo del sistema. */
/* UNA SOLA COLUMNA: eran dos porque eran dos sectores —clientes e infraestructura—, y el de
   infraestructura se fue a «La red ahora». Con dos columnas y un solo grupo, la fila de indicadores
   ocuparía media pantalla y la otra mitad quedaría vacía. */
/* ===== LOS INDICADORES, PEGADOS A LA TABLA =====
   Eran tres botones flotando en su propia caja con 14 px de aire alrededor y otros 12 hasta la
   tarjeta. Ahora son una tira pareja apoyada sobre la tabla: sin hueco entre ellos y sin hueco
   hasta lo de abajo. La línea los separa. */
.hoy-secs{display:grid;grid-template-columns:1fr;gap:0;margin-bottom:0}
/* La línea que dice a dónde fueron los clientes que no entran en estas listas. Va pegada a los
   indicadores porque los CORRIGE: sin ella, «12 sin servicio» se lee como si fueran doce. */
/* La fila del filtro por causa. Va adentro de la tarjeta, entre el encabezado y la tabla, con la
   misma línea de abajo que separa el encabezado del contenido en el resto del sistema. */
/* Pegado a la banda de arriba y a la tabla de abajo: lo que lo separa son las líneas. */
.hoy-causas{padding:7px 12px;border-bottom:1px solid var(--border)}
.hoy-causas .sup-tab b{font-weight:var(--fw-semi);margin-left:2px}
.hoy-otros{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin:0 0 12px;
  padding:8px 12px;background:var(--surface);border:1px solid var(--border);
  border-left:3px solid var(--amber);font-size:12.5px;color:var(--text-dim)}
.hoy-otros span{flex:1 1 auto;min-width:0}
.hoy-otros b{color:var(--text);font-weight:var(--fw-semi)}
/* Sin redondeo y sin línea abajo: la tira y la tabla de abajo tienen que leerse como una sola
   pieza, y la línea que las separa la pone el borde de la tarjeta. */
.hoy-secs > *{border:1px solid var(--border);border-bottom:0;border-radius:0;overflow:hidden;background:var(--surface)}
@media(max-width:900px){
  .hoy-secs{grid-template-columns:1fr;gap:10px}
}
/* Sin versales, por lo mismo. Es el rótulo de sección de «Qué hacer hoy» y de la ficha de la lupa
   —«En números», «Mediciones», «Diagnóstico»—. */
.hoy-sec-h{font-size:12px;font-weight:var(--fw-semi);text-transform:none;letter-spacing:0;color:var(--text-dim);
  margin:0;padding:6px 12px;background:var(--surface-2);border-bottom:1px solid var(--border)}
/* TRES COLUMNAS: eran dos porque cada sector traia cuatro cajas y entraban 2x2. Con tres listas
   quedaba 2 + 1, con la ultima sola en un renglon. */
.hoy-sec-k{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:0;padding:0}
@media(max-width:860px){ .hoy-sec-k{grid-template-columns:1fr 1fr} }
@media(max-width:560px){ .hoy-sec-k{grid-template-columns:1fr} }
/* Celdas de una tira, no botones sueltos: sin radio, sin borde propio más que la línea que las
   separa de la de al lado, y la activa se marca con la barra de abajo —el mismo recurso que usan
   las solapas del resto del sistema— y no con un borde de color. */
.hoy-k{display:flex;align-items:baseline;gap:9px;width:100%;text-align:left;padding:9px 12px;
  border:0;border-left:1px solid var(--border);border-radius:0;background:transparent;color:var(--text);
  cursor:pointer;font:inherit;font-size:12.5px;transition:background .14s ease}
.hoy-sec-k > .hoy-k:first-child{border-left:0}
.hoy-k:hover{background:var(--surface-2)}
.hoy-k.on{background:var(--surface-2);box-shadow:inset 0 -2px 0 var(--accent-ink)}
.hoy-k.on.urg{box-shadow:inset 0 -2px 0 var(--accent-ink),inset 3px 0 0 var(--red)}
/* 14 y no 16: 16 no esta en la escala del sistema (10 / 11 / 11.5 / 12 / 12.5 / 13.5 / 14 / 17 /
   18) y era el unico salto grande de un cuerpo que vive entre 11 y 12.5. Y en monoespaciada con
   `tabular-nums`, porque los tres se comparan entre si: es lo que hace el sistema con todo numero
   que se lee en columna. */
.hoy-k b{font-family:'IBM Plex Mono',monospace;font-variant-numeric:tabular-nums;
  font-size:14px;font-weight:var(--fw-bold);line-height:1.15;flex:0 0 auto;min-width:2.4em;text-align:right}
.hoy-k span{font-size:12.5px;color:var(--text-dim);line-height:1.25;min-width:0}
/* La barrita de la izquierda marca lo más urgente de cada sector: es el mismo recurso que usa el
   resto del sistema para señalar una fila, una línea y no un color de fondo. */
.hoy-k.urg{box-shadow:inset 3px 0 0 var(--red)}
.hoy-k.aten{box-shadow:inset 3px 0 0 var(--amber)}

/* ===== Fusiones de la zona ===== */
/* El lienzo, las líneas y los nodos son los MISMOS del Diagrama de la red (.tp-*): se ve y se usa
   igual, y cualquier retoque de aquél sirve también acá. Sólo se agrega lo propio de las fusiones. */
/* Se le suma `.tp-lienzo` para ganar por especificidad y no por orden: si mañana alguien mueve un
   bloque de CSS, esta pantalla no tiene por qué cambiar de alto. */
.tp-lienzo.fz-lienzo{height:250px}
.fz-cable{font-family:'IBM Plex Mono',monospace;font-size:9px;fill:var(--text-faint);pointer-events:none}
.fz-nn{font-size:12px;font-weight:var(--fw-bold);fill:var(--text)}
.fz-ns{font-size:10px;fill:var(--text-faint)}
.fz-marco{fill:var(--surface-2);stroke:var(--border);stroke-width:1}
.fz-marco.fija{fill:transparent;stroke-dasharray:4 3}
.fz-marco.on{stroke:var(--signal);stroke-width:2}
/* UN SOLO SCROLL para las dos columnas: con dos scrolls independientes, la línea dibujada entre
   ellas se desalinea apenas se mueve una. El dibujo va adentro de lo que scrollea, así que las
   líneas acompañan solas. El hueco de 64 px es para que la unión se vea. */
.fz-cols{position:relative;display:grid;grid-template-columns:1fr 1fr;gap:64px;margin-top:12px;align-items:start;
  max-height:480px;overflow:auto}
@media(max-width:820px){ .fz-cols{grid-template-columns:1fr;gap:14px} .fz-lin{display:none} }
.fz-lin{position:absolute;left:0;top:0;pointer-events:none;overflow:visible}
.fz-lin path{fill:none;stroke:var(--green);stroke-width:1.7;opacity:.7}
.fz-lin .sp{fill:color-mix(in srgb,#8f86d6 22%,transparent);stroke:#8f86d6;stroke-width:1.2;opacity:.9}
.fz-lin .spt{fill:var(--text-faint);font-size:9px;font-family:'IBM Plex Mono',monospace}
.fz-col{border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);min-width:0}
.fz-col-h{display:flex;align-items:center;gap:8px;padding:6px 10px;border-bottom:1px solid var(--border);
  position:sticky;top:0;z-index:2;background:var(--surface);
  font-size:12px;font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:.05em;color:var(--text-dim);
  /* alto mínimo: sin esto el desplegable de «+ cable» sobresalía y el borde de abajo lo cortaba */
  min-height:42px;box-sizing:border-box}
.fz-col-h .sel{height:30px;line-height:28px;padding:0 26px 0 10px;font-size:12px;flex:0 1 auto;min-width:0;
  max-width:190px;text-transform:none;letter-spacing:0;font-weight:var(--fw-medium)}
.fz-col-b{padding:6px}   /* el scroll ahora es del bloque entero, no de cada columna */
.fz-cab{font-size:11px;color:var(--text-faint);padding:7px 6px 4px;display:flex;align-items:center;gap:7px}
.fz-cab b{color:var(--text);font-size:12px}
.fz-pelo{display:flex;align-items:center;gap:7px;width:100%;text-align:left;padding:5px 7px;border-radius:var(--radius-sm);
  border:1px solid transparent;background:none;color:var(--text);cursor:pointer;font:inherit;font-size:12px}
.fz-pelo:hover{background:var(--surface-2)}
.fz-pelo.sel{border-color:var(--signal);background:color-mix(in srgb,var(--signal) 12%,transparent)}
.fz-pelo.ok{background:color-mix(in srgb,var(--green) 9%,transparent)}
.fz-pelo.no{cursor:default;opacity:.75}
.fz-sw{flex:0 0 auto;width:11px;height:11px;border-radius:var(--radius-sm);border:1px solid rgba(128,128,128,.5)}
.fz-n{flex:0 0 26px;font-family:'IBM Plex Mono';font-size:12px;color:var(--text-dim);text-align:right}
.fz-tx{flex:1 1 auto;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fz-par{flex:0 0 auto;font-size:11px;color:var(--green);white-space:nowrap;max-width:47%;overflow:hidden;text-overflow:ellipsis}
.fz-x{flex:0 0 auto;width:19px;height:19px;border-radius:var(--radius-sm);border:1px solid var(--border);background:var(--surface-2);
  color:var(--text-faint);line-height:1;font-size:12px;cursor:pointer;padding:0}
.fz-x:hover{color:var(--red);border-color:var(--red)}
.fz-vacio{font-size:12px;color:var(--text-faint);padding:12px 8px;font-style:italic}
.fz-ayuda{font-size:12px;color:var(--text-faint);padding:7px 2px 0}
/* vista Árbol (planilla de conexión) */
.znt-scroll{flex:1;min-height:0;overflow:auto;padding:14px 16px calc(20px + env(safe-area-inset-bottom))}
.znt-count{margin-left:auto;font-size:12px;color:var(--text-faint);font-family:'IBM Plex Mono';white-space:nowrap}
@media(max-width:520px){ .znt-count{display:none} }
.znt-table{overflow:visible}
.znt-head,.znt-row{grid-template-columns:minmax(90px,1.1fr) minmax(78px,1fr) minmax(74px,1fr) minmax(88px,1fr) minmax(88px,1fr) minmax(92px,1.2fr)}
.znt-row{cursor:pointer}
.znt-zona{font-weight:var(--fw-bold);color:var(--text)}
.znt-empty{color:var(--text-faint)}
@media(max-width:760px){ .znt-table{min-width:640px} }
.zn-newrow{display:flex;gap:6px;padding:10px 12px;border-top:1px solid var(--border)}
.zn-newrow .fl{min-width:0}
.zn-addbtn{flex:0 0 auto;padding:0 13px;font-size:15px;font-weight:var(--fw-bold)}
.zn-act{display:flex;justify-content:center;text-align:center;white-space:normal;line-height:1.2;margin:6px 12px 0;padding:8px 10px}
.zn-main{flex:1;min-width:0;overflow:auto}
.zn-body{padding:16px 20px calc(24px + env(safe-area-inset-bottom))}
.zn-sec-h{display:flex;align-items:center;gap:9px;font-size:12px;font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:.06em;color:var(--text-dim);margin:22px 0 11px;padding-bottom:6px;border-bottom:1px solid var(--border)}
.zn-sec-h:first-child{margin-top:2px}
.zn-top2{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:4px;align-items:start}
.zn-top2.one{grid-template-columns:1fr}
/* Las dos clases de caída se distinguen por el color del borde: la de nodo no se repara en la calle
   y la de fibra sí, así que conviene separarlas de un vistazo. */
.zn-caidas{display:flex;flex-direction:column;gap:8px}
.zn-cd-res{font-size:12.5px;color:var(--text-dim);margin-bottom:2px}
.zn-cd{padding:10px 12px;border-radius:var(--radius);background:var(--surface-2);border:1px solid var(--border);border-left-width:3px}
.zn-cd.nodo{border-left-color:var(--amber)} .zn-cd.fibra{border-left-color:var(--red)}
.zn-cd-h{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap}
.zn-cd-tag{font-size:10px;font-weight:var(--fw-black);letter-spacing:.07em;padding:2px 7px;border-radius:var(--radius)}
.zn-cd.nodo .zn-cd-tag{color:var(--amber);background:color-mix(in srgb,var(--amber) 15%,transparent)}
.zn-cd.fibra .zn-cd-tag{color:var(--red);background:color-mix(in srgb,var(--red) 15%,transparent)}
.zn-cd-h b{font-size:13.5px}
.zn-cd-f{margin-left:auto;color:var(--text-faint);font-size:12px}
.zn-cd-d{font-size:12.5px;color:var(--text-dim);margin-top:4px}
.zn-cd-n{font-size:12.5px;margin-top:6px;padding:7px 9px;border-radius:var(--radius);background:var(--surface)}
.zn-cd-b{margin-top:7px;background:transparent;border:1px solid var(--border-strong);color:var(--text-dim);
  border-radius:var(--radius);padding:3px 11px;font:inherit;font-size:12px;cursor:pointer}
.zn-cd-b:hover{border-color:var(--accent-ink);color:var(--accent-ink)}
/* PARQUE POR MODELO: tres tablas, tres juegos de columnas. La última columna de zona y nodo es la
   lista de modelos y se lleva todo el resto del ancho, que es donde está la información. */
.dbt-pmod{grid-template-columns:minmax(0,2fr) 100px 88px 88px 88px 124px 76px 76px 100px}
.dbt-pzona{grid-template-columns:120px 92px 92px 92px 80px minmax(0,3fr)}
.dbt-pnodo{grid-template-columns:minmax(0,180px) 92px 92px 92px 80px minmax(0,3fr)}
/* «Para retirar» son CINCO columnas, no seis: la de «clientes» no va porque lo que importa es
   cuantos aparatos hay que ir a buscar. */
.dbt-pret{grid-template-columns:120px 104px 100px 88px minmax(0,3fr)}
.dbt-pretn{grid-template-columns:minmax(0,180px) 104px 100px 88px minmax(0,3fr)}
/* Stock ya no tiene barra de secciones propia: sus diez pantallas viven en el menu lateral. Los
   botones siguen en el DOM porque navIr() navega clickeandolos — sin el boton el menu no llega y
   encima no da error. */
#stockWrap .so-tabs{display:none}
/* El Tablero tampoco tiene pastillero propio: sus areas viven en el menu lateral. Se esconde, no se
   borra — navIr() navega clickeando el boton [data-area]. */
#areaSwitch{display:none}
/* El aviso de cuantos tickets siguen frenados, ahora en el menu. */
.sn-badge{margin-left:auto;font-size:11px;font-weight:var(--fw-black);line-height:1;padding:2px 6px;border-radius:var(--radius-pill);
  background:color-mix(in srgb,var(--red) 22%,transparent);color:var(--red)}
body.nav-rail .sn-badge{position:absolute;top:4px;right:6px;margin:0;padding:1px 4px;font-size:10px}
  /* ===== LA MARCA DE «HAY ALGO CAÍDO» =====
     El resto de los contadores del menú son trabajo pendiente y van en gris; éste es «andá a mirar
     ahora» y va en rojo, con la fila teñida y un pulso lento. Es el mismo criterio que el contador
     de cortes de la pantalla: sólo pulsa mientras pasa algo. */
  .sn-badge.sn-badge-mal{background:var(--red);color:#fff}
  #sideNav .sn-item.sn-alerta{background:color-mix(in srgb,var(--red) 10%,transparent);
    box-shadow:inset 3px 0 0 var(--red)}
  @keyframes sn-late{ 0%,100%{ background:color-mix(in srgb,var(--red) 10%,transparent) }
                      50%{ background:color-mix(in srgb,var(--red) 24%,transparent) } }
  #sideNav .sn-item.sn-alerta{animation:sn-late 2s ease-in-out infinite}
  @media(prefers-reduced-motion:reduce){
    #sideNav .sn-item.sn-alerta{animation:none;background:color-mix(in srgb,var(--red) 18%,transparent)}
  }
body.nav-rail .sn-item{position:relative}
/* Conciliación: MAC · modelo · cliente · qué dice el Excel · si coinciden. La del cliente es la que
   se lleva el ancho sobrante: es la que tiene nombres largos. */
.dbt-cvivo{grid-template-columns:minmax(0,1.05fr) minmax(0,.7fr) minmax(0,1.5fr) minmax(0,1.15fr) minmax(0,.75fr)}
/* Un poco de aire arriba, que antes lo daba el padding del cuerpo. */
.so-pad-t{padding-top:12px}
.dbt-pvida{grid-template-columns:minmax(140px,1fr) 92px 88px 104px 92px 104px minmax(170px,1.2fr) minmax(190px,1.4fr)}
/* Los textos sueltos de «Por modelo» se alinean con el contenido de las tablas (8 px), no con el
   borde del panel: apilados uno debajo del otro, 8 px de diferencia se ven como un escalon. */
.pm-linea{padding-left:8px;padding-right:8px}
/* Y un parrafo de 1.366 px de ancho no se lee: se corta donde se termina de leer comodo. */
.pm-linea.pm-parrafo{max-width:1080px}
.zn-box{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:12px 15px}
.zn-box>.zn-sec-h:first-child{margin-top:0}
.zn-box .zn-net{background:var(--surface);}
@media(max-width:900px){ .zn-top2{grid-template-columns:1fr} }
.zn-conn{display:grid;grid-template-columns:repeat(auto-fit,minmax(130px,1fr));gap:12px}
.zn-conn .inp{font-weight:var(--fw-bold)}
.zn-fld{display:flex;flex-direction:column;gap:5px}
.zn-fld label{font-size:11px;font-weight:var(--fw-semi);text-transform:uppercase;letter-spacing:.05em;color:var(--text-faint)}
.zn-net{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:11px 14px;margin-bottom:8px}
.zn-net-h{font-size:13.5px;margin-bottom:6px;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.zn-net-l{font-size:12.5px;color:var(--text-dim);margin-top:3px;display:flex;align-items:center;gap:5px;flex-wrap:wrap}
.zn-net-st{font-size:12px;font-weight:var(--fw-bold)}
.zn-net-st.ok{color:var(--green)} .zn-net-st.bad{color:var(--red)} .zn-net-st.mut{color:var(--text-faint)}
.zn-net-degr{margin-top:6px;font-size:12px;font-weight:var(--fw-bold);color:var(--amber)}
.zn-net-hist{margin-left:auto;padding:4px 11px;font-size:12px}
.zn-planos{display:flex;flex-wrap:wrap;gap:8px}
.zn-plano{display:inline-flex;align-items:center;gap:7px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:8px 12px;cursor:pointer;font-size:12.5px;color:var(--text);max-width:100%}
.zn-plano:hover{border-color:var(--accent-ink)}
.zn-plano svg{width:16px;height:16px;flex:0 0 auto;color:var(--red)}
.zn-plano span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.zn-works{display:flex;flex-direction:column;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}
.zn-work{display:grid;grid-template-columns:minmax(0,1fr) 118px 132px;gap:10px;align-items:center;padding:9px 13px;border-bottom:1px solid var(--border);cursor:pointer;transition:.1s}
.zn-work:last-child{border-bottom:0}
.zn-work:hover{background:var(--surface-2)}
.zn-work-t{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.zn-work-t small{color:var(--text-faint);margin-left:6px}
.zn-work .zn-est{font-size:10px;font-weight:var(--fw-bold);border:1px solid var(--ec,var(--border));color:var(--ec,var(--text-dim));border-radius:var(--radius-sm);padding:1px 6px;justify-self:start}
.zn-work-d{text-align:right;font-size:12px;color:var(--text-faint);font-variant-numeric:tabular-nums}
.zn-pend{display:flex;flex-direction:column;gap:6px}
.zn-p{display:flex;align-items:center;gap:9px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:7px 10px}
.zn-p.done .zn-p-t{text-decoration:line-through;color:var(--text-faint)}
.zn-p-chk{width:18px;height:18px;flex:0 0 auto;border:1.5px solid var(--border-strong);border-radius:var(--radius-sm);background:none;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--green)}
.zn-p-t{flex:1;min-width:0;font-size:12.5px}
.zn-p-conv,.zn-p-del{flex:0 0 auto;border:none;background:none;color:var(--text-faint);cursor:pointer;padding:3px;border-radius:var(--radius-sm)}
.zn-p-conv:hover{color:var(--signal)} .zn-p-del:hover{color:var(--red)}
.zn-p-conv svg,.zn-p-del svg{width:16px;height:16px}
.zn-p.conv .zn-p-t::after{content:' · convertida';color:var(--green);font-size:11px}
.zn-empty2{color:var(--text-faint);font-size:12.5px;padding:12px 4px;font-style:italic}
@media(max-width:640px){ .zn-work{grid-template-columns:minmax(0,1fr) 92px;gap:4px 8px} .zn-work-d{display:none} }
/* Planificador */
.plan-list{display:flex;flex-direction:column;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;margin-bottom:12px}
.plan-row{display:grid;grid-template-columns:minmax(0,1.3fr) minmax(70px,1fr) 300px;gap:12px;align-items:center;padding:9px 13px;border-bottom:1px solid var(--border);font-size:12.5px;transition:.1s}
.plan-row:last-child{border-bottom:0}
.plan-row.clic{cursor:pointer}
.plan-row.clic:hover{background:var(--surface-2)}
.plan-row.bad{box-shadow:inset 3px 0 0 var(--red)}
.plan-row.warn{box-shadow:inset 3px 0 0 var(--amber)}
.plan-row.ok{box-shadow:inset 3px 0 0 var(--green)}
.plan-row.mut{box-shadow:inset 3px 0 0 var(--border-strong)}
.plan-r-t{display:flex;align-items:center;gap:8px;min-width:0}
.plan-r-t b{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.plan-r-t small{color:var(--text-faint);font-weight:var(--fw-normal);flex:0 0 auto}
.plan-dot{width:10px;height:10px;border-radius:var(--radius-circ);flex:0 0 auto}
.plan-chip{font-size:10px;font-weight:var(--fw-bold);color:#fff;padding:2px 6px;border-radius:var(--radius-sm);flex:0 0 auto}
.plan-bar{height:8px;border-radius:var(--radius-sm);background:var(--surface-3,var(--surface-2));overflow:hidden}
.plan-bar i{display:block;height:100%;border-radius:var(--radius-sm);background:var(--accent-ink)}
.plan-bar i.bad{background:var(--red)} .plan-bar i.warn{background:var(--amber)} .plan-bar i.ok{background:var(--green)}
.plan-tags{display:flex;gap:6px;flex-wrap:wrap;justify-content:flex-end}
.plan-tag{font-size:11px;font-weight:var(--fw-bold);padding:2px 8px;border-radius:var(--radius);background:var(--surface-2);border:1px solid var(--border);color:var(--text-dim);white-space:nowrap;font-variant-numeric:tabular-nums}
.plan-tag.red{color:var(--red);border-color:color-mix(in srgb,var(--red) 40%,transparent)}
.plan-tag.amber{color:var(--amber);border-color:color-mix(in srgb,var(--amber) 40%,transparent)}
.plan-tag.green{color:var(--green);border-color:color-mix(in srgb,var(--green) 40%,transparent)}
.plan-eta{text-align:right;font-variant-numeric:tabular-nums;font-weight:var(--fw-bold)}
@media(max-width:640px){ .plan-row{grid-template-columns:minmax(0,1fr) 120px;gap:6px 10px} .plan-bar{display:none} .plan-tags{grid-column:1 / -1;justify-content:flex-start} }
.olt-live{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:var(--fw-bold);color:var(--green);text-transform:uppercase;letter-spacing:.04em}
.olt-live i{width:8px;height:8px;border-radius:var(--radius-circ);background:var(--green);box-shadow:0 0 0 0 color-mix(in srgb,var(--green) 60%,transparent);animation:oltpulse 1.6s ease-out infinite}
.olt-live.off{color:var(--text-faint)} .olt-live.off i{background:var(--text-faint);animation:none;box-shadow:none}
@keyframes oltpulse{0%{box-shadow:0 0 0 0 color-mix(in srgb,var(--green) 55%,transparent)}70%{box-shadow:0 0 0 6px transparent}100%{box-shadow:0 0 0 0 transparent}}
.so-wrap{flex:1;min-height:0;display:flex;background:var(--surface);overflow:hidden}
/* El Monitor OLT ya no tiene menú propio: sus pantallas están en la barra lateral, y a cada OLT se
   entra desde las tarjetas del Dashboard. Los botones siguen en el DOM porque el menú lateral los usa. */
#oltWrap .so-side{display:none}
.so-side{flex:0 0 252px;min-height:0;overflow-y:auto;background:var(--surface);border-right:1px solid var(--border);padding:16px 12px;display:flex;flex-direction:column;gap:12px}
.so-brand{display:flex;align-items:center;gap:11px;padding:4px 8px 14px;border-bottom:1px solid var(--border)}
.so-brand-ic{display:inline-flex;color:var(--accent-ink)} .so-brand-ic svg{width:24px;height:24px}
.so-brand-t{display:flex;flex-direction:column;line-height:1.15}
.so-brand-t b{font-size:14px;letter-spacing:-.2px} .so-brand-t span{font-size:11px;color:var(--text-faint);text-transform:uppercase;letter-spacing:.09em}
.so-nav{display:flex;flex-direction:column;gap:3px}
/* EL MENÚ DE LAS PANTALLAS CON ARMAZÓN (Configuración, Stock, Ayuda, Planos, Historial, Monitor OLT)
   ES EL MISMO QUE EL DEL SISTEMA (#sideNav .sn-item), porque en Configuración los dos se ven uno al
   lado del otro y cualquier diferencia canta. Estaba en 13,5/400 sobre --text-dim contra 14,5/500
   sobre --text: más chico, más flojo y más apagado. Y el activo se marcaba distinto —texto blanco
   sobre un fondo opaco y una barra cuadrada— cuando el del sistema usa el color del acento sobre el
   acento al 14 % y una barra redondeada. Mismo alto de renglón (7 px de relleno) para que las dos
   listas queden a la par. */
.so-navi{display:flex;align-items:center;gap:11px;width:100%;padding:7px 11px;border:0;background:transparent;color:var(--text);border-radius:var(--radius);cursor:pointer;font-size:14px;font-weight:var(--fw-medium);text-align:left;font-family:inherit;transition:.12s;position:relative}
.so-navi:hover{background:var(--surface-2);color:var(--text)}
.so-navi.on{background:color-mix(in srgb,var(--signal) 14%,transparent);color:var(--accent-ink);font-weight:var(--fw-semi)}
.so-navi.on::before{content:"";position:absolute;left:0;top:8px;bottom:8px;width:3px;border-radius:0 var(--radius-sm) var(--radius-sm) 0;background:var(--accent-ink)}
/* Secciones de Stock en barra horizontal (reemplaza al menú lateral propio). Scrollea sola si no
   entran, en vez de apretar los textos o irse de ancho. */
.so-tabs{display:flex;gap:4px;align-items:center;padding:10px 14px;border-bottom:1px solid var(--border);background:var(--surface);overflow-x:auto;scrollbar-width:thin;flex:0 0 auto}
/* La variante horizontal (las secciones de Stock) NO se agranda con el menú lateral: es una barra
   que tiene que entrar a lo ancho, y su marca de activo es la raya de abajo, no la de la izquierda. */
.so-tabs .so-navi{width:auto;flex:0 0 auto;padding:8px 13px;white-space:nowrap;gap:8px;font-size:13.5px}
/* UNA sola marca de activo. Desde que la barra hereda el fondo teñido y el color del acento del
   menú, la raya de abajo quedaba ADEMÁS del fondo: dos marcas para decir lo mismo, y encima la raya
   recta cortada contra el radio de 9 se veía como un error de dibujo. Queda la pastilla, que es la
   misma que usa el menú del sistema — que es de lo que se trataba. */
.so-tabs .so-navi.on{box-shadow:none}
.so-tabs .so-navi.on::before{display:none}
.so-tabs .so-navi-badge{position:static;margin-left:2px}
#stockWrap .so-main{display:flex;flex-direction:column;min-width:0}
/* MISMO ALTO DE CABECERA EN LAS OCHO SECCIONES. Cada una trae lo suyo —unas sólo el título, otras
   botones o el buscador— y la barra medía 38, 51, 56 o 59 px: al cambiar de sección todo lo de abajo
   saltaba de lugar. Con un alto mínimo, el título queda clavado y sólo cambia lo que hay dentro. */
#stockBody .so-panel-bar{min-height:56px}
/* Vale para TODO lo que viva en una barra de Stock, esté o no dentro del grupo de acciones: el campo
   «Técnico destino» de Salidas colgaba suelto de la barra y dejaba esa cabecera 3 px más alta. */
#stockBody .so-panel-bar .help-search,#stockBody .so-panel-bar .btn,#stockBody .so-panel-bar .onu-fb{height:34px;box-sizing:border-box}
/* Subido a la barra del título, el alto lo manda el botón y no la barra donde vivía antes. */
.top-acts .onu-fb{height:auto}
#stockWrap #stockBody{flex:1;min-height:0;overflow:auto}
@media(max-width:760px){ .so-tabs{padding:8px 10px} .so-tabs .so-navi{padding:9px 11px;font-size:12.5px} }
/* 17 y no 20: los íconos ya son de 17 (`_soi`), y con la ranura de 20 el texto arrancaba 3 px más
   a la derecha que en el menú del sistema — que en Configuración está justo al lado. */
.so-navi-ic{width:17px;display:inline-flex;align-items:center;justify-content:center;opacity:.85}
.so-navi.on .so-navi-ic{opacity:1}
.so-collapse{margin-left:auto;flex:0 0 auto;width:28px;height:28px;border:1px solid var(--border);background:var(--surface-2);color:var(--text-dim);cursor:pointer;border-radius:var(--radius);font-size:14px;line-height:1;transition:.12s}
.so-collapse:hover{background:color-mix(in srgb,var(--signal) 16%,var(--surface-2));border-color:var(--accent-ink);color:var(--text)}
@media(min-width:761px){
  .so-wrap.so-collapsed .so-side{flex-basis:58px}
  .so-wrap.so-collapsed .so-navi-l,.so-wrap.so-collapsed .so-soon,.so-wrap.so-collapsed .so-brand-t,.so-wrap.so-collapsed .so-brand-ic{display:none}
  .so-wrap.so-collapsed .so-navi{justify-content:center;padding:10px 0;gap:0}
  .so-wrap.so-collapsed .so-brand{justify-content:center;padding:4px 0 12px}
}
.so-navi-l{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.so-soon{font-size:9px;text-transform:uppercase;letter-spacing:.04em;color:var(--text-faint);border:1px solid var(--border);border-radius:var(--radius-sm);padding:1px 5px}
.so-main{flex:1;min-width:0;min-height:0;display:flex;flex-direction:column;overflow:hidden;padding:0;background:var(--bg)}
.so-main>#stockBody{flex:1;min-height:0;display:flex;flex-direction:column;overflow:auto}
.so-main>#stockBody>.val-wrap2{flex:0 0 auto}
/* panel unificado: barra (título+busqueda+filtros+acciones) + cuerpo (tabla/cards) + pie (paginador), todo en un recuadro de alto completo */
.so-panel{flex:1;min-height:0;display:flex;flex-direction:column;background:var(--bg);overflow:hidden}
.so-panel-bar{display:flex;align-items:center;gap:9px;flex-wrap:wrap;padding:10px 14px;border-bottom:1px solid var(--border);background:var(--surface-2)}
.so-panel-bar h3{margin:0;font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:15px}
.so-panel-bar .so-bar-ic{display:inline-flex;align-items:center;color:var(--accent-ink);flex:0 0 auto;margin-right:-2px}
.so-panel-bar .so-bar-ic svg{width:19px;height:19px}
.so-panel-bar .help-search{flex:1 1 200px;min-width:140px}
/* Las acciones de la pantalla, pegadas a la derecha de la barra del título. Van juntas en su propia
   caja para que, si la barra se parte, no se separen ni queden a la izquierda debajo de los filtros. */
.so-bar-acc{margin-left:auto;display:flex;align-items:center;gap:9px;flex:0 0 auto}
/* ===== EN EL TELÉFONO, LA BARRA DE ACCIONES ENVUELVE =====
   Con `flex:0 0 auto` y sin envolver, en 360 px se sale del panel y lo que sobra queda
   INALCANZABLE: medido, «Nuevo modelo» sobraba 18 px, «Actualizar» 93, «cambiar clave» 159 y en
   Telwinet la barra entera 323. No es un problema estético: es la acción principal de esas
   pantallas, y desde el teléfono no existía.
   Envuelve en vez de deslizar porque son BOTONES: deslizar una fila de botones para encontrar el
   que se busca es peor que verlos en dos renglones.
   Y pasan a 34 px de alto: 28 alcanza con el mouse, con el dedo no. Es lo que ya miden los botones
   de esta misma barra. */
@media(max-width:760px){
  .so-bar-acc{margin-left:0;flex:1 1 100%;flex-wrap:wrap;row-gap:8px}
  .so-panel-bar .onu-fb,
  .so-panel-bar .btn,
  .so-panel-bar .nota-tog{ height:34px; margin-left:0 }
  .so-panel-bar{flex-wrap:wrap;row-gap:8px}
}
/* Y lo que va adentro, a la misma altura de control del sistema: el campo de buscar de Modelos medía
   39 y dejaba esas dos barras 3 px más altas que las otras seis. */
.so-bar-acc .help-search,.so-bar-acc .btn,.so-bar-acc .onu-fb{height:34px;box-sizing:border-box}
/* Los filtros en su propio renglón: arriba qué estoy viendo y qué puedo hacer, acá cómo lo filtro.
   TODOS LOS CONTROLES A LA MISMA ALTURA. Venían de cuatro sitios distintos y medían 38, 32, 39 y
   29 px, con cuatro tamaños de letra y tres radios: como cada uno se centra en su propio alto, ni
   los bordes ni los renglones de texto coincidían y la fila se veía desprolija sin que se pudiera
   decir por qué. 34 px es la altura de control del sistema (la misma de los botones de la barra). */
.so-filtros{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:9px 14px;border-bottom:1px solid var(--border)}
.so-filtros .help-search,.so-filtros .stock-sel,.so-filtros .nfilter button,.so-filtros .onu-fb{
  height:34px;box-sizing:border-box;font-size:12.5px}
/* El buscador ocupaba 409 px de ancho: un rectángulo vacío que empujaba todo lo demás contra el
   borde derecho y dejaba la fila desequilibrada. Con 300 alcanza para una MAC entera. */
/* `margin-left:auto` VIENE EN `.help-search` DE FÁBRICA —está pensada para ir pegada a la derecha de
   una barra— y acá empujaba a los seis controles contra el borde derecho, dejando 79 px muertos a la
   izquierda. Era eso lo que se veía torcido, no el ancho. */
.so-filtros .help-search{flex:0 1 300px;min-width:170px;max-width:300px;border-radius:var(--radius);margin:0 2px 0 0}
/* El relleno vertical del desplegable (10 px arriba y abajo) contra los 34 de alto dejaba 12 px para
   una letra de 13: el texto quedaba recortado. El centrado lo hace la fila. */
.so-filtros .stock-sel{border-radius:var(--radius);padding-top:0;padding-bottom:0}
/* Dos formas, y cada una dice algo: caja de esquina suave = campo donde se escribe o se elige;
   píldora = interruptor que se prende y se apaga. */
.so-filtros .nfilter button,.so-filtros .onu-fb{border-radius:var(--radius);padding:0 13px;display:inline-flex;
  align-items:center;gap:6px;line-height:1}
.so-filtros .nfilter{gap:6px}
.so-count{font-size:12px;color:var(--text-faint)}
/* Cuando además de la bajada hay un número (equipos, modelos, alertas), un punto los separa: son dos
   datos distintos y pegados se leen como una sola frase rara. */
.so-count + .so-count::before{content:"·";margin-right:7px;opacity:.55}
/* DOBLE TÍTULO: desde que la barra de arriba dice en qué pantalla estás (v1.9.400), el <h3> del panel
   repetía el mismo texto palabra por palabra, en TODAS las pantallas del módulo. Cuando coinciden se
   esconde el del panel y el subtítulo pasa a llevar la voz, que es el que aporta algo. */
/* La explicación de la pantalla, plegada: es larga y una vez leída sólo ocupa lugar. */
.seg-nota{margin:0 0 12px}
  /* Los dos plegables de arriba, lado a lado para no gastar dos renglones en dos títulos. */
  .seg-plegables{display:flex;flex-wrap:wrap;gap:10px;align-items:flex-start;margin:0 0 12px}
  .seg-plegables > details{flex:1 1 280px;min-width:0;margin:0}
  .seg-plegables > details[open]{flex-basis:100%}   /* el abierto se lleva el ancho: es texto largo */
.seg-nota>summary{cursor:pointer;list-style:none;display:inline-flex;align-items:center;gap:7px;
  font-size:12.5px;font-weight:650;color:var(--text-dim);padding:6px 10px;border:1px solid var(--border);
  border-radius:var(--radius);user-select:none}
.seg-nota>summary::-webkit-details-marker{display:none}
.seg-nota>summary::before{content:'';width:0;height:0;border-left:5px solid currentColor;
  border-top:4px solid transparent;border-bottom:4px solid transparent;transition:transform .15s ease}
.seg-nota[open]>summary::before{transform:rotate(90deg)}
.seg-nota>summary:hover{color:var(--text);background:color-mix(in srgb,var(--text) 6%,transparent)}
.seg-nota[open]>summary{margin-bottom:8px}
/* La tira de escaneos: un bloque por escaneo del router, del más viejo al más nuevo. Un cliente que
   ataca de verdad se ve como una línea llena; uno que apareció una sola vez, como un bloque suelto. */
.seg-tira{display:inline-flex;gap:2px;margin-top:5px}
/* Los estados de las conexiones iban como spans sueltos con un margen: en pantalla se separaban,
   pero pegados quedaban ilegibles y al copiarlos se juntaban en una sola frase. Como chips cada
   número queda atado a su etiqueta y no hay forma de leer mal dónde termina uno y empieza el otro. */
.seg-ests{display:flex;flex-wrap:wrap;gap:6px 8px;margin-top:6px}
.seg-est{display:inline-flex;align-items:baseline;gap:5px;background:var(--surface-2);border:1px solid var(--border);border-radius:12px;padding:3px 10px;font-size:12px;color:var(--text-faint);white-space:nowrap}
.seg-est b{color:var(--text);font-variant-numeric:tabular-nums}
.seg-tira i{width:7px;height:13px;border-radius:1px;display:block}
/* ===== DIAGRAMA DE LA RED =====
   Cada concentrador es una tarjeta y sus equipos cuelgan como ramas. Se dibuja con bordes, no con
   una librería de grafos: la red es una estrella (grado máximo 79, mediana 1), así que el árbol es
   la forma real y además se puede leer en el teléfono. */
/* El lienzo del mapa. `touch-action:none` para poder arrastrar en el teléfono sin que la página
   entera se mueva; `cursor:grab` para que se entienda que se puede. */
.tp-lienzo{position:relative;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);
  overflow:hidden;height:min(70vh,720px);touch-action:none;cursor:grab}
.tp-lienzo.arrastrando{cursor:grabbing}
.tp-lienzo svg{display:block;width:100%;height:100%}
.tp-enl{stroke:var(--border-strong);stroke-width:1.2;fill:none;opacity:.55}
/* El rosa es «esto importa» en todo el sistema: gastarlo en las 27 líneas normales le saca el
   sentido. Las líneas van apagadas y el acento queda para lo que uno selecciona. */
.tp-enl.tp-tronco{stroke:#5b8def;stroke-width:2;opacity:.5}
/* Punteado = este enlace no lo dijo la red, lo dice el inventario. La diferencia importa: lo medido
   se corrige solo, lo escrito envejece cuando alguien renombra un equipo. */
.tp-enl.tp-inv{stroke:var(--text-faint);stroke-width:1.6;stroke-dasharray:5 4;opacity:.75}
.tp-enl.tp-apagado{stroke:var(--border);opacity:.25}
.tp-enl.tp-resalta{stroke:var(--signal);stroke-width:2.6;opacity:1}
.tp-n{cursor:pointer}
.tp-n rect,.tp-n circle{transition:opacity .12s}
.tp-n.tp-apagado{opacity:.2}
.tp-n text{font-family:'IBM Plex Mono',monospace;pointer-events:none;dominant-baseline:middle}
.tp-cap{font-size:11px;fill:var(--text-faint)}
/* La chapita con el nombre del equipo seleccionado */
.tp-info{position:absolute;right:12px;top:12px;max-width:300px;background:var(--surface-2);
  border:1px solid var(--border-strong);border-radius:var(--radius);padding:11px 13px;font-size:12.5px}
.tp-info b{font-size:13.5px;display:block;margin-bottom:3px}
.tp-info small{display:block;color:var(--text-faint);font-size:12px}
.tp-leyenda{display:flex;gap:14px;flex-wrap:wrap;align-items:center;margin:9px 2px 0;font-size:12px;color:var(--text-faint)}
.tp-leyenda i{display:inline-block;width:9px;height:9px;border-radius:var(--radius-xs);margin-right:5px;vertical-align:middle}
.tp-card{border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);margin-bottom:12px;overflow:hidden}
.tp-h{display:flex;align-items:center;gap:11px;padding:11px 13px;cursor:pointer;background:var(--surface-2)}
.tp-h:hover{background:color-mix(in srgb,var(--surface-2) 80%,var(--text) 6%)}
.tp-chev{width:13px;height:13px;flex:0 0 auto;transition:transform .16s ease;color:var(--text-faint)}
.tp-card.on .tp-chev{transform:rotate(90deg)}
.tp-nom{font-weight:var(--fw-black);font-size:13.5px}
.tp-sub{font-size:12px;color:var(--text-faint)}
.tp-pill{font-size:11px;font-weight:var(--fw-bold);padding:2px 8px;border-radius:var(--radius);white-space:nowrap}
.tp-kids{display:none;padding:12px 13px 14px;gap:8px;
  grid-template-columns:repeat(auto-fill,minmax(228px,1fr))}
.tp-card.on .tp-kids{display:grid}
/* La rama: una línea que entra desde la izquierda, para que se lea como colgando del concentrador. */
.tp-kid{position:relative;padding:7px 9px 7px 20px;border:1px solid var(--border);border-radius:var(--radius);
  background:var(--surface-2);min-width:0}
.tp-kid:before{content:"";position:absolute;left:8px;top:50%;width:7px;height:1px;background:var(--border-strong)}
.tp-kid b{display:block;font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tp-kid small{display:block;font-size:11px;color:var(--text-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.tp-t{display:inline-block;width:7px;height:7px;border-radius:var(--radius-xs);margin-right:5px;vertical-align:middle}
@media(max-width:760px){ .tp-kids{grid-template-columns:1fr} }
.so-panel-bar h3.tit-dup{display:none}
/* Si el título se esconde por repetido, el ícono se queda solo: en la PC pasa desapercibido, pero en
   el teléfono la barra apila y el ícono ocupaba un renglón entero él solo, arriba del subtítulo. Va
   con el título. */
.so-panel-bar h3.tit-dup~.so-bar-ic,.so-panel-bar:has(h3.tit-dup)>.so-bar-ic{display:none}
.so-panel-bar.solo-sub .so-count{font-size:13.5px;color:var(--text-dim)}
/* Al esconderse el titulo repetido, lo que quedaba —el estado y las acciones, que van a la
   derecha— se quedaba con una fila entera para el solo. Se pega a la izquierda y la barra baja de
   alto: la fila vacia se veia mas que el titulo que se saco. */
.so-panel-bar.solo-sub{padding-top:7px;padding-bottom:7px}
.so-panel-bar.solo-sub>:first-child{margin-left:0}
/* Subida a la barra del título, la de la pantalla ya no tiene nada que mostrar. */
/* Con el subtítulo arriba, el de la barra sobra y la barra se achica: pasa de renglón de texto a
   fila de acciones. */
.so-panel-bar.solo-sub.sub-arriba .so-count{display:none}
.so-panel-bar.solo-sub.sub-arriba{padding-top:4px;padding-bottom:4px;min-height:0}
/* En Capacidad la barra ya no tiene NADA que mostrar: el subtítulo está arriba, «Qué es esto» se
   fue y «Actualizar» bajó a la fila de las solapas. Se esconde sólo cuando el subtítulo subió de
   verdad; en pantalla angosta no sube, y entonces la barra se queda para mostrarlo. */
.so-panel-bar.cap-bar.sub-arriba{display:none}
.top-sub{font-size:12.5px;color:var(--text-dim);margin-left:12px;min-width:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.top-sub .so-count{font-size:12.5px;color:var(--text-dim)}
.top-acts{display:flex;align-items:center;gap:8px;flex:0 0 auto}
/* UN SOLO DIBUJO DE BOTÓN, el de la maqueta: chico, rectangular, papel y un borde fino.
   Antes convivían tres pesos distintos —uno con alto fijo, otro sin borde, y el filtro dentro de
   una caja— para tres cosas que se tocan igual. */
.top-acts button{
  font:inherit; font-size:12px; font-weight:var(--fw-normal); line-height:1.5;
  padding:4px 11px; min-height:0; height:28px; color:var(--text);
  background:var(--surface); border:1px solid var(--border-strong);
  border-radius:var(--radius-sm); cursor:pointer; white-space:nowrap;
}
.top-acts button:hover{background:var(--surface-2)}
/* La flechita de «Qué es esto» era para un bloque que se desplegaba hacia abajo. Ahora abre un
   panel flotante, así que ya no anuncia nada. */
.top-acts .nota-chev{display:none}
.top-acts .onu-fb svg{width:13px;height:13px}
/* Si la barra aprieta, el subtítulo cede primero: es la aclaración, no el dato. */
/* Los botones espejados, al lado del título. Mismo dibujo que los de las barras del sistema. */
.top-acc{display:flex;align-items:center;gap:6px;margin-left:12px;flex:0 0 auto}
.top-acc-b{height:26px;padding:0 10px;font-size:12px;font-weight:var(--fw-normal);color:var(--text);
  background:var(--surface);border:1px solid var(--border-strong);border-radius:var(--radius-sm);
  display:inline-flex;align-items:center;gap:6px;white-space:nowrap;cursor:pointer}
.top-acc-b:hover{background:var(--surface-2)}
.top-acc-b svg{width:13px;height:13px;flex:0 0 auto}
.top-acc-b:disabled{opacity:.5;cursor:default}
/* «Qué es esto» sube como ícono: es una explicación que se lee una vez, no un control, y así no
   gasta ancho al lado del título. */
.top-acc-i{width:26px;height:26px;padding:0;color:var(--text-dim);background:transparent;border:0;
  border-radius:var(--radius-circ);display:inline-flex;align-items:center;justify-content:center;cursor:pointer}
.top-acc-i:hover{color:var(--text);background:var(--surface-2)}
.top-acc-i svg{width:15px;height:15px}
/* La barra de la pantalla ya no tiene nada propio que mostrar: sus botones están arriba y su
   subtítulo también. Se esconde SÓLO cuando efectivamente se espejó. */
.so-panel-bar.bar-espejada{display:none}
/* El «Qué es esto» que quedó suelto: su copia está arriba, así que acá no ocupa nada. Se esconde
   sólo cuando efectivamente se lo espejó — la marca la pone quien lo copió. */
.nota-tog.esp-suelto{display:none}
@media(max-width:1280px){ .top-sub, .top-acc{display:none} }
.so-panel-body{flex:1;min-height:0;overflow:auto}
/* ===== EL MARCO NO SE PASA DEL ANCHO DE LA PANTALLA =====
   Sin esto, una tabla ancha estira todo el modulo por afuera del borde derecho (medido: 2073 px
   dentro de una ventana de 1424) y se lleva puesta la franja de KPI, que queda fuera de la vista.
   Es `min-width:auto`: un elemento flexible no se achica por debajo de su contenido salvo que se le
   diga. Esta misma regla ya estaba para el celular; ahora vale en todos los anchos. El contenido no
   se pierde: .so-panel-body scrollea, que es como funciona el resto del sistema. */
.so-wrap,.so-side,.so-main,.so-panel,.so-panel-bar,.so-panel-body,.so-panel-body>.dbt-wrap{min-width:0}
.so-main{max-width:100%}
/* Y el contenedor del modulo, que es el hijo flexible directo de la vista: si no, crece hasta el
   ancho de la tabla mas ancha que tenga adentro y arrastra todo lo de arriba con el. */
#configWrap,#stockWrap,#planosWrap,#helpWrap,#statsWrap,#histWrap,#oltWrap,#cajasWrap,#supWrap,
#repWrap,#zonasWrap,#planWrap,#agendaWrap,#rtWrap,#recoordWrap,#pruebaWrap,#avanceWrap,#hoyWrap{min-width:0;max-width:100%}
.so-panel-body .so-cards{padding:14px}
/* PEGADO AL MENÚ Y AL BORDE. Los 16 px alrededor encajonaban el contenido: la tabla arrancaba a
   dieciséis píxeles del menú y terminaba a dieciséis del borde derecho, con el fondo de la página
   asomando alrededor como un marco. Queda sólo el renglón de abajo: sin él, la última fila de una
   tabla larga toca el borde de la ventana y no se ve dónde termina. */
.so-panel-body.so-pad{padding:0 0 14px}
/* Configuración: contenido de cada pestaña cohesionado dentro del panel */
.so-panel-body#cfgBody{padding:0;display:flex;flex-direction:column;overflow:hidden}
.so-panel-bar .cfg-tools{display:flex;gap:9px;align-items:center;flex:1;min-width:0}
.so-panel-bar .cfg-tools .help-search{flex:1 1 180px;min-width:110px}
#cfgBody>.dbt-wrap{flex:1;min-height:0;overflow:auto;border:0;border-radius:0;max-width:none}
#cfgBody>.dbt-wrap .dbt-head{position:sticky;top:0;z-index:2}
#cfgBody>.cl-list{flex:1;min-height:0;overflow:auto;padding:16px;margin:0}
#cfgBody>.set-hint{margin:14px 16px 0}
/* pestañas no-tabla de Configuración (Proyectos, Apariencia, Mi cuenta, Estado) */
/* Acá vivía `.cfg-flow`: una clase que se le ponía a `#cfgBody` en las solapas que no eran una tabla,
   para darles el aire que las otras no querían. Dejó de hacer falta cuando `#cfgBody` pasó a estar
   adentro de un `.so-panel-body.so-pad`, que ya trae su padding y su scroll para todas por igual. */
/* Mi cuenta */
.acct-head{display:flex;align-items:center;gap:14px}
.acct-av{width:52px!important;height:52px!important;border-radius:var(--radius);font-size:17px;font-weight:var(--fw-black);flex:0 0 auto}
.acct-id b{display:block;font-size:16px;font-weight:var(--fw-black)} .acct-id span{font-family:'IBM Plex Mono';font-size:12.5px;color:var(--text-faint)}
.acct-meta{display:flex;gap:24px;margin-top:14px;padding-top:14px;border-top:1px solid var(--border)}
.acct-meta>div{display:flex;flex-direction:column;gap:3px} .acct-meta span{font-size:11px;text-transform:uppercase;letter-spacing:.03em;color:var(--text-faint)} .acct-meta b{font-size:13.5px}
.acct-h{margin:0 0 12px;font-size:13.5px;font-weight:var(--fw-black)}
.acct-note{margin:0 0 12px;font-size:12px;color:var(--text-dim);line-height:1.5}
/* Aviso flotante (toast). Existía por todos lados como typeof toast==='function' pero nunca estaba
   definido, así que las confirmaciones «se hizo» no se veían. */
#toastHost{position:fixed;left:50%;bottom:24px;transform:translateX(-50%);z-index:99999;display:flex;flex-direction:column;gap:8px;align-items:center;pointer-events:none}
/* Radio y colores del sistema. Tenía 9 px —el único del sistema con ese radio— y colores de
   respaldo escritos a mano, de antes de que existieran los tokens. */
.toast{background:var(--surface-2);color:var(--text);border:1px solid var(--border-strong);padding:10px 16px;border-radius:var(--radius);font-size:12.5px;font-weight:var(--fw-semi);box-shadow:0 8px 26px rgba(0,0,0,.28);opacity:0;transform:translateY(10px);transition:opacity .25s,transform .25s;max-width:90vw;text-align:center}
.toast.show{opacity:1;transform:none}
.toast-ok{border-color:var(--green,#16a34a)}
.toast-err{border-color:var(--red,#e5484d)}
/* Historial de altas: panel colapsable, para que no ocupe toda la pantalla abajo de las altas. */
.afh-det{margin-top:16px;border-top:1px solid var(--border,#e5e7eb);padding-top:10px}
.afh-det>summary{cursor:pointer;list-style:none;user-select:none;display:flex;align-items:center;gap:8px}
.afh-det>summary::-webkit-details-marker{display:none}
.afh-det>summary::before{content:'\25B8';color:var(--text-faint);transition:transform .15s;font-size:11px}
.afh-det[open]>summary::before{transform:rotate(90deg)}
.afh-det-body{margin-top:10px}

/* Respuestas rápidas */
.rq-vars{display:flex;flex-wrap:wrap;gap:10px;margin:0 0 12px}
.rq-vf{display:flex;flex-direction:column;gap:3px;font-size:11px;color:var(--text-dim);font-weight:var(--fw-semi)}
.rq-vf input{min-width:130px}
.rq-cats{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 14px}
/* `--radius` y no 14 px: a esta altura 14 px es una pastilla, y en todo el sistema las solapas y
   las fichas son rectángulos apenas redondeados. */
.rq-cat{padding:5px 12px;border-radius:var(--radius);border:1px solid var(--border);background:var(--surface-2);color:var(--text-dim);font-size:12px;font-weight:var(--fw-bold);cursor:pointer}
.rq-cat.on{background:var(--selected);color:var(--text);border-color:var(--accent-ink)}
.rq-q{width:150px;height:32px}
.rq-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:12px}
.rq-card{border:1px solid var(--border);border-radius:var(--radius-xl);background:var(--surface);padding:12px;display:flex;flex-direction:column;gap:8px}
.rq-card-h{display:flex;align-items:center;gap:8px;justify-content:space-between}
.rq-card-h b{font-size:12.5px}
.rq-card-cat{font-size:10px;text-transform:uppercase;letter-spacing:.04em;color:var(--text-faint);white-space:nowrap}
.rq-body{white-space:pre-wrap;font-size:12px;line-height:1.5;color:var(--text-dim);max-height:210px;overflow:auto;background:var(--surface-2);border-radius:var(--radius);padding:8px 10px}
.rq-tok{color:var(--link,#3b82f6);font-weight:var(--fw-bold)}
.rq-acts{display:flex;gap:6px;flex-wrap:wrap}
@media(max-width:600px){ .rq-grid{grid-template-columns:1fr} .rq-q{width:120px} }

/* Registro de soporte */
.sop-ctrl{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin:0 0 12px}
.sop-in{font-size:10px;text-transform:uppercase;letter-spacing:.04em;color:var(--green,#16a34a);font-weight:var(--fw-black)}
.sop-out{font-size:10px;text-transform:uppercase;letter-spacing:.04em;color:var(--amber,#f5a623);font-weight:var(--fw-black)}
.sop-seg{display:inline-block;background:var(--surface-2);border:1px solid var(--border);border-radius:12px;padding:2px 8px;font-size:11px;margin:2px 4px 2px 0}
.sop-seg a{color:var(--red);text-decoration:none;margin-left:4px;font-weight:var(--fw-bold)}
.sop-segbox{min-height:18px}
/* Registro de soporte · resumen */
.sop-cols{display:grid;grid-template-columns:1fr 1fr;gap:14px}
@media(max-width:700px){ .sop-cols{grid-template-columns:1fr} }
.sopbars{display:flex;flex-direction:column;gap:6px}
.sopbar{display:grid;grid-template-columns:130px 1fr 34px;align-items:center;gap:8px;font-size:12px}
.sopbar-l{color:var(--text-dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sopbar-t{background:var(--surface-2);border-radius:var(--radius-sm);height:12px;overflow:hidden}
.sopbar-t i{display:block;height:100%;background:var(--signal);border-radius:var(--radius-sm)}
.sopbar b{text-align:right}
/* Cliente bajo la lupa */
.lp-add{display:flex;gap:8px;align-items:center;margin:0 0 12px}
.lp-chips{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 16px}
.lp-chip{display:flex;align-items:center;gap:6px;background:var(--surface-2);border:1px solid var(--border);border-radius:16px;padding:5px 10px;cursor:pointer;font-size:12.5px}
.lp-chip.on{border-color:var(--signal);background:var(--surface)}
.lp-chip b{font-weight:var(--fw-bold)}
.lp-chip span{color:var(--text-dim);font-size:12px}
.lp-chip i{font-style:normal;font-size:10px;color:var(--text-faint);background:var(--bg);border-radius:var(--radius-lg);padding:1px 6px}
.lp-chip a{color:var(--text-faint);text-decoration:none;margin-left:2px;font-weight:var(--fw-bold)}
.lp-chip a:hover{color:var(--red)}
/* DOS PANELES, NO DOS PILAS SUELTAS. La lista de la izquierda son fichas con borde y el detalle de la
   derecha era una sucesión de bloques sin contenedor, así que el lado derecho quedaba flotando sobre
   el fondo sin nada que lo sostuviera. Una línea divisoria y un encabezado por columna alcanzan para
   que se lean como dos paneles de una misma pantalla, sin agregar tarjetas adentro de tarjetas. */
/* LA LISTA ARRIBA Y LA FICHA A TODO EL ANCHO. La columna de la izquierda se llevaba 244 px de los
   1.338 del cuerpo para cuatro renglones, mientras seis gráficos se apretaban en lo que quedaba.
   Es sólo CSS: el marcado y los clics no se tocan — lo que rompe es mover nodos, no cambiar cómo se
   acomodan. */
.lp-layout{display:flex;flex-direction:column;gap:0}
.lp-side{flex:none;width:100%;border-right:0;border-bottom:1px solid var(--border-strong);
  padding:0 0 0;position:static;display:flex;align-items:stretch;gap:0;flex-wrap:wrap}
.lp-main-col{flex:1;min-width:0;padding:12px 0 0}
/* El rótulo de cada columna: dice qué es cada lado sin ocupar un renglón entero. */
/* La barra de la lupa: el desplegable, cuántos hay y el botón de sacar, todo en un renglón. */
/* EL ORDEN LO PONE `order` Y NO EL MARCADO: en el HTML los campos para agregar vienen ANTES de la
   lista, y con el `auto` que los manda a la derecha el desplegable quedaba encimado sobre ellos.
   Reordenar el marcado sería mover nodos; reordenar el dibujo, no. */
.lp-side-t{order:0}
.lp-sel,.lp-cuantos,.lp-sacar{order:1}
.lp-side .lp-add{order:2}
/* SIN ALTO FIJO: 28 px con 12,5 de letra le cortaban el texto arriba y abajo —un <select> reserva
   su propio espacio interno y no se le puede imponer la caja—. Y sin encogerse por debajo de 240:
   `flex-shrink` lo achicaba hasta cortar el nombre del cliente, que es lo unico que dice cual estas
   mirando. Lo que cede el ancho son los campos de agregar, que se usan una vez. */
.lp-sel{flex:0 1 340px;min-width:240px;height:auto;padding:4px 8px;font-size:12px}
.lp-cuantos{align-self:center;font-size:11.5px;color:var(--text-faint);margin-left:10px;white-space:nowrap}
.lp-sacar{align-self:center;margin-left:12px;font-size:11.5px;color:var(--text-faint);text-decoration:none;white-space:nowrap}
.lp-sacar:hover{color:var(--red);text-decoration:underline}
/* LOS TEXTOS DE LA FICHA NO TOCAN EL MENÚ. El cuerpo ya no tiene relleno —para que las tablas
   lleguen al borde— y el texto suelto quedaba pegado al menú, cortado. El aire se lo damos a los
   bloques de texto, no al cuerpo: puesto en el cuerpo, las tablas se despegarían otra vez. */
.lp-head,.lp-sub,.lp-actions,.lp-side{padding-left:12px;padding-right:12px}
.lp-main-col > #lupaDet > .lp-ver,.lp-main-col > #lupaDet > .lp-verrow{padding-left:12px;padding-right:12px}
/* El rótulo «En seguimiento» va al principio de la barra, como el «Mostrar» del filtro de Capacidad. */
.lp-side-t{font-size:11.5px;letter-spacing:0;text-transform:none;color:var(--text-faint);
  margin:0;align-self:center;padding:0 12px 0 0;white-space:nowrap}
/* Los dos campos para agregar van juntos al final: se usan una vez por cliente nuevo, no cada vez
   que se entra. El `auto` lo lleva SOLO el primero — puesto en los dos, el segundo se iba al
   extremo y se salia del ancho. Si no entran, la tira los baja a un segundo renglon. */
.lp-side .lp-add{margin:0;align-self:center;gap:6px;flex:0 1 auto;min-width:0}
.lp-side .lp-add:first-of-type{margin-left:auto}
.lp-side .lp-add + .lp-add{margin-left:6px}
.lp-side .lp-add .inp{flex:0 1 150px;min-width:0;max-width:none;height:28px;font-size:12px}
.lp-list{display:flex;flex-direction:row;gap:0;overflow-x:auto;scrollbar-width:none;min-width:0}
.lp-list::-webkit-scrollbar{display:none}
/* Cada vigilado es una solapa: sin caja, con el subrayado marcando cuál está abierto. El mismo
   dibujo que las solapas de Capacidad. */
.lp-row{flex:0 0 auto;display:flex;align-items:center;justify-content:flex-start;gap:8px;
  padding:6px 14px;border:0;border-bottom:2px solid transparent;border-radius:0;background:transparent;cursor:pointer}
.lp-row:hover{background:var(--surface-2)}
.lp-row.on{border-bottom-color:var(--accent-ink);background:transparent;box-shadow:none}
/* En la tira, el nombre y el número van en una línea y el resto se guarda en el título: una solapa
   de tres renglones haría la tira tan alta como era la columna. */
.lp-side .lp-row-main{display:flex;align-items:baseline;gap:7px}
.lp-side .lp-row-main b{display:inline;font-size:12px}
.lp-side .lp-row-main span{display:inline;max-width:140px}
.lp-side .lp-row-since,.lp-side .lp-row-nota{display:none}
.lp-side .lp-row-side i{display:none}
.lp-row-main{min-width:0}
.lp-row-main b{display:block;font-weight:var(--fw-bold);font-size:12.5px}
.lp-row-main span{display:block;color:var(--text-dim);font-size:11.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:160px}
.lp-row-since{display:block;font-style:normal;font-size:10.5px;color:var(--text-faint);margin-top:1px}
.lp-row-main .lp-row-nota{color:var(--text);font-style:italic}
.lp-row-fin{opacity:.7}
.lp-row-side{display:flex;align-items:center;gap:6px;flex:0 0 auto}
.lp-row-side i{font-style:normal;font-size:10px;color:var(--text-faint);background:var(--bg);border-radius:var(--radius-lg);padding:1px 6px}
.lp-row-side a{color:var(--text-faint);text-decoration:none;font-weight:var(--fw-bold);font-size:12.5px}
.lp-row-side a:hover{color:var(--red)}
.lp-ph{color:var(--text-faint);padding:40px 16px;text-align:center;border:1px dashed var(--border);border-radius:var(--radius-xl)}
/* En el teléfono la tira se apila: el rótulo, las solapas y el campo no entran en un renglón. */
/* En el telefono cada cosa toma el ancho entero: el desplegable con un nombre largo y los dos
   campos no entran en un renglon, y apretados se encimaban. */
@media(max-width:900px){
  .lp-side{flex-wrap:wrap;padding:0 12px 8px;gap:8px}
  .lp-sel{flex:1 1 100%}
  .lp-side .lp-add{margin:0;flex:1 1 100%}
  .lp-side .lp-add:first-of-type{margin-left:0}
  .lp-side .lp-add + .lp-add{margin-left:0}
  .lp-side .lp-add .inp{flex:1 1 auto}}
/* El nombre del cliente cierra con una regla: es el título del panel derecho, no un renglón más. */
.lp-head{margin:0 0 14px;padding-bottom:10px;border-bottom:1px solid var(--border)}
.lp-head b{font-size:14px}
.lp-head .lp-sub .lp-mod{font-size:12px;font-weight:var(--fw-semi);color:var(--text-dim)}
.lp-head a{margin-left:8px;font-size:12px}
.lp-sub{color:var(--text-faint);font-size:12px;margin-top:2px}
/* ===== EL VEREDICTO DE LA LUPA =====
   Antes eran renglones todos iguales, en el orden en que estaban escritos en el código. Ahora hay
   una jerarquía y se ve: la línea de acción arriba, la conclusión grande, lo que se desprende de
   ella colgando, y el resto compacto abajo. Todos toman su color de la variable --vc, que la pone
   el propio veredicto: un solo molde y el color lo decide quien sabe. */
.lp-ver{display:flex;flex-direction:column;gap:8px;margin:0 0 14px}
/* La línea de acción: lo primero que se lee, y contesta a quién mandar. Va en mayúsculas chicas y
   con el color de fondo teñido, porque es una instrucción y no una observación más. */
.lp-acc{border-radius:var(--radius-lg);padding:9px 13px;border-left:4px solid var(--vc);
  background:color-mix(in srgb,var(--vc) 12%,var(--surface-2))}
.lp-acc b{display:block;font-size:11px;font-weight:var(--fw-black);text-transform:uppercase;letter-spacing:.05em;color:var(--vc)}
.lp-acc span{display:block;font-size:12px;color:var(--text);line-height:1.45;margin-top:2px}
/* `.lp-verrow` queda porque la usa la TARJETA DE SEGURIDAD, que no es un veredicto y se arma aparte.
   Se cayó una vez al rehacer el diagnóstico y la tarjeta quedó sin estilo: vale la aclaración. */
.lp-verrow{background:var(--surface-2);border-radius:var(--radius-lg);padding:8px 12px}
.lp-verrow b{display:block;font-size:12.5px}
.lp-verrow span{font-size:12px;color:var(--text-dim);line-height:1.5}
/* LA FICHA DEL DIAGNÓSTICO. Un renglón por cosa revisada: punto de color, qué se miró, cómo está y
   la flechita que avisa que hay más. Es una grilla y no una tabla porque el detalle va en su propio
   renglón, a lo ancho, debajo del que lo abre.
   La columna de la izquierda va a ancho fijo para que todos los rótulos queden alineados: alineados
   se barren con la vista de arriba abajo, desalineados hay que leerlos uno por uno. */
.lp-ficha{border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden;background:var(--surface-2)}
.lp-fr{display:grid;grid-template-columns:10px 92px 1fr 14px;align-items:baseline;gap:9px;
  padding:8px 12px;cursor:pointer;border-top:1px solid var(--border);transition:background .12s ease}
.lp-fr:first-child{border-top:0}
.lp-fr:hover{background:color-mix(in srgb,var(--vc) 8%,transparent)}
.lp-fr:focus-visible{outline:2px solid var(--accent-ink);outline-offset:-2px}
.lp-fp{width:8px;height:8px;border-radius:var(--radius-circ);background:var(--vc);align-self:center}
.lp-fk{font-size:10.5px;text-transform:uppercase;letter-spacing:.05em;color:var(--text-faint);font-weight:var(--fw-bold)}
.lp-fv{font-size:12px;color:var(--text);line-height:1.35}
.lp-fc{font-size:9px;color:var(--text-faint);align-self:center;transition:transform .12s ease}
.lp-fr.on .lp-fc{transform:rotate(180deg)}
.lp-fr.on .lp-fv{color:var(--vc);font-weight:var(--fw-semi)}
/* El detalle: sangrado hasta donde arranca el texto de arriba, para que se lea como su continuación
   y no como un renglón nuevo. */
.lp-fd{padding:2px 12px 11px 122px;font-size:12px;color:var(--text-dim);line-height:1.55;
  background:var(--surface-2);border-top:0}
@media(max-width:700px){
  .lp-fr{grid-template-columns:10px 1fr 14px;row-gap:2px}
  .lp-fk{grid-column:2}
  .lp-fv{grid-column:2}
  .lp-fd{padding-left:31px}
}
.lp-hrs-wrap{position:relative;margin-top:2px}
.lp-hrs-peak{position:absolute;top:-4px;right:0;font-size:10px;color:var(--text-faint);font-weight:var(--fw-semi);letter-spacing:.02em}
.lp-hrs{display:flex;gap:3px;align-items:flex-end;padding:14px 2px 0}
.lp-hr{flex:1;display:flex;flex-direction:column;align-items:center}
.lp-hr-t{position:relative;width:100%;height:84px;background:linear-gradient(180deg,var(--surface-2) 0%,transparent 72%);border-radius:3px}
.lp-hr-t span{position:absolute;left:0;right:0;bottom:0;border-radius:3px 3px 0 0;transition:filter .15s,transform .15s;box-shadow:inset 0 1px 0 rgba(255,255,255,.15)}
.lp-hr:hover .lp-hr-t span{filter:brightness(1.25)}
.lp-hr.now .lp-hr-t{box-shadow:inset 0 0 0 1px var(--text-faint)}
.lp-hr i{font-size:9px;color:var(--text-faint);margin-top:5px;height:11px;font-style:normal;font-weight:var(--fw-semi)}
/* Secciones de la lupa como tarjetas */
/* REJILLA CONTINUA, no tarjetas flotando. Cada gráfico era una tarjeta con fondo, borde y esquinas,
   separada de la de al lado por 12 px de aire: seis tarjetas son seis objetos, y una rejilla es una
   sola cosa que se lee de corrido. El bloque lleva el borde; adentro, las líneas separan. */
/* SIN RELLENO EN LA CELDA: lo lleva cada parte. Con el relleno acá, todo lo de adentro —incluida la
   franja del título— arrancaba doce píxeles adentro del borde, y la franja no se podía sacar con
   margen negativo porque la celda recorta lo que se le sale (`overflow:hidden`, para que un gráfico
   ancho no se derrame sobre la de al lado). */
#lupaMain .ocl-sec{background:transparent;border:0;border-radius:0;padding:0;margin-bottom:12px}
/* FONDO DE SUPERFICIE, no el de la pagina. Las celdas son transparentes —para que la rejilla se
   lea como una sola cosa— asi que lo que se veia detras era el gris del cuerpo: los graficos
   quedaban sobre gris cuando en el ejemplo van sobre blanco. El fondo lo pone el bloque, una vez,
   y sirve para los dos temas: blanco en claro, la superficie oscura en oscuro. */
#lupaMain .lp-grid{border:1px solid var(--border);background:var(--surface)}
/* EL TITULO DE CADA GRAFICO, UNA FRANJA GRIS sobre el blanco del dibujo — la misma cabecera que
   tienen las 99 tablas del sistema. Sin fondo, el titulo y el grafico eran la misma superficie y
   habia que separarlos leyendo.
   EL MARGEN NEGATIVO ES LO QUE HACE QUE LA FRANJA CRUCE LA CELDA ENTERA: el titulo vive adentro del
   relleno de la celda, asi que sin sacarlo de ahi la franja arrancaria doce pixeles adentro y se
   leeria como una etiqueta pegada, no como una cabecera. */
#lupaMain .lp-grid > .ocl-sec > .ocl-sec-t{background:var(--surface-3);
  margin:0;padding:5px 12px;border-bottom:1px solid var(--border-strong)}
#lupaMain .lp-grid > .ocl-sec{border-left:1px solid var(--border);border-top:1px solid var(--border)}
/* La primera de cada fila no lleva línea a la izquierda, y la primera fila no lleva la de arriba:
   son el borde del bloque, que ya está. Se resuelve por posición y no marcando las celdas al
   armarlas, porque cuántas entran por fila lo decide el ancho de la pantalla. */
#lupaMain .lp-grid > .ocl-sec:first-child{border-top:0;border-left:0}
#lupaMain .ocl-sec>.ocl-sec-t:first-child{margin:0 0 10px;padding-bottom:8px;border-bottom:1px solid var(--border);font-size:12px;color:var(--text-dim)}
/* El relleno que perdió la celda se lo queda el gráfico, que es lo único que lo necesitaba: pegado
   al borde, el eje de la izquierda quedaría contra la línea de la celda. */
#lupaMain .ocl-graf{margin:0;padding:8px 12px 10px}
#lupaMain .lp-verrow{border-radius:var(--radius-lg)}
#lupaMain .tt-kpis{margin-bottom:14px}
/* Sin `gap`: la separación la hacen las líneas. Con aire Y línea se ven dos separaciones para lo
   mismo. */
/* Sin margen abajo: el rótulo de «Diagnóstico» ya trae su propio aire arriba, así que eran dos
   separaciones para lo mismo. */
#lupaMain .lp-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(340px,1fr));gap:0;align-items:stretch;margin-bottom:0}
#lupaMain .lp-grid>.ocl-sec{margin-bottom:0;min-width:0;overflow:hidden}
#lupaMain .ocl-graf,#lupaMain .graf,#lupaMain .graf-plot{min-width:0}
#lupaMain .lp-grid .ocl-graf .graf-svg{height:150px}
#lupaMain .lp-mot{margin:4px 0 0;padding-left:18px}
#lupaMain .lp-mot li{margin:3px 0;font-size:12px;line-height:1.5;color:var(--text-dim)}
#lupaMain .lp-actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 10px;padding:0 12px}
#lupaMain .lp-desde{font-size:12px;color:var(--text-faint)}
/* LOS INDICADORES, UNA BANDA CON DIVISIONES — no siete recuadros. La misma que quedó en «La red
   ahora»: el borde alrededor y una línea entre uno y otro. */
#lupaMain .tt-kpis{gap:0;border:1px solid var(--border);border-left:0;border-right:0;margin:0}
#lupaMain .tt-kpi{background:transparent;border:0;border-left:1px solid var(--border);border-radius:0;padding:7px 12px}
#lupaMain .tt-kpi:first-child{border-left:0}
#lupaMain .lp-actions-h{font-size:11.5px;color:var(--text-faint)}
.acct-form{display:flex;flex-direction:column;gap:12px;max-width:340px}
.acct-msg{font-size:12.5px;min-height:16px} .acct-msg.ok{color:var(--accent-ink)} .acct-msg.err{color:var(--red)}
/* Estado del sistema */
.est-lbl{font-size:12.5px;font-weight:var(--fw-semi);color:var(--text-dim)} .est-sub{font-size:11px;color:var(--text-faint);min-height:14px}
.est-sec{margin-bottom:22px} .est-bars{display:flex;flex-direction:column;gap:7px;max-width:640px}
.est-barrow{display:grid;grid-template-columns:160px 1fr 40px;align-items:center;gap:10px;font-size:12.5px}
.est-bl{display:flex;align-items:center;gap:7px;color:var(--text-dim);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.est-dot{width:9px;height:9px;border-radius:var(--radius-circ);flex:0 0 auto}
.est-bt{height:8px;border-radius:var(--radius-sm);background:var(--surface-3,rgba(130,140,165,.15));overflow:hidden} .est-bf{display:block;height:100%;border-radius:var(--radius-sm);min-width:2px}
.est-bn{font-weight:var(--fw-bold);text-align:right}
/* Las barras de «Tareas por estado» se pintan con el color crudo de cada columna del tablero. En
   tema claro el sistema le baja la saturación a todos los acentos brillantes para que no queden
   neón, pero esta lista se armó antes que estas dos clases y quedaron afuera: eran las únicas de la
   pantalla que seguían chillando. */
html[data-theme="light"] .est-dot,
html[data-theme="light"] .est-bf{filter:saturate(.68)}

/* ===== LA FILA DE USUARIOS, MÁS TRANQUILA =====
   El avatar es un cuadrado de 42 px con el color a pleno y las iniciales en negrita. Está bien donde
   nació —la tarjeta de una persona, ahí el avatar ES el elemento— pero en una fila de tabla, con el
   nombre escrito al lado, el color pesaba más que el dato y estiraba el alto de todas las filas.
   Encima `.avatar` es `display:grid`, o sea que se comporta como bloque: el cuadrado se ponía en su
   propio renglón y el nombre abajo. Acá pasa a ser una marca chica al lado del nombre: se mantiene
   la identificación por color, que es la misma de todo el sistema, sin que se coma la fila.
   El login va en monoespaciado, que a igual tamaño se lee más pesado que el texto común y le
   competía al nombre. Baja un punto y va en el gris de los datos de apoyo: el nombre es el dato
   principal de esa fila, el login es con qué entra.
   Se apunta con `tr[data-uid]`, que es lo único que tiene la tabla de Usuarios, para no tocar ni el
   avatar del resto del sistema ni las otras columnas monoespaciadas de Configuración —el código de
   color de Tipos y Motivos, y los valores del servidor en Estado, que ahí sí son el dato. */
#cfgBody tr[data-uid] .avatar{
  display:inline-block;width:14px;height:14px;border-radius:var(--radius-sm);
  font-size:0;letter-spacing:0;vertical-align:-2px;margin-right:8px}
#cfgBody tr[data-uid] td.mono{font-size:12px;color:var(--text-faint)}
.so-panel-body .dbt-wrap{border:0;border-radius:0;max-width:none}
.so-panel-body .dbt-head{position:sticky;top:0;z-index:2}
.so-panel-foot{border-top:1px solid var(--border);padding:2px 12px}
.so-panel-foot:empty{display:none}
.so-panel-foot .pager{padding:7px 2px;margin:0}
.so-head h2{margin:0 0 16px;font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:19px}
.so-toolbar{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-bottom:14px}
.so-toolbar .help-search{flex:1 1 220px}
.so-cards{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:12px}
.so-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:13px 14px;display:flex;flex-direction:column;gap:9px}
.so-card:hover{border-color:color-mix(in srgb,var(--signal) 45%,var(--border))}
.so-card-h{display:flex;justify-content:space-between;align-items:flex-start;gap:8px}
.so-card-t{display:flex;flex-direction:column;min-width:0}
.so-card-t b{font-size:13.5px} .so-card-sub{font-size:12px;color:var(--text-faint)}
.so-card-acts{display:flex;gap:4px;flex:0 0 auto}
.so-chips{display:flex;flex-wrap:wrap;gap:5px}
.so-chip{font-size:11px;padding:2px 8px;border-radius:var(--radius);background:var(--surface-2);border:1px solid var(--border);color:var(--text-dim)}
.so-specs{display:flex;flex-direction:column;gap:2px;font-size:12px;color:var(--text-faint);border-top:1px solid var(--border);padding-top:8px}
.so-specs b{color:var(--text-dim);font-weight:var(--fw-semi)}
.so-chks{display:flex;flex-wrap:wrap;gap:14px}
.so-chk{display:flex;align-items:center;gap:6px;font-size:12.5px;color:var(--text-dim);cursor:pointer}
.so-soon-box{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:50px 20px;color:var(--text-faint)}
.so-soon-ic{opacity:.45;margin-bottom:10px} .so-soon-ic svg{width:46px;height:46px}
.so-soon-box h3{margin:0 0 6px;color:var(--text-dim);font-size:15px}
.so-soon-box p{margin:0;font-size:12.5px;max-width:380px;margin-inline:auto;line-height:1.5}
.dbt-baja{grid-template-columns:minmax(0,1.1fr) minmax(0,1.1fr) minmax(0,1fr) minmax(0,1.1fr) minmax(0,1fr) 90px}
.dbt-rver{grid-template-columns:minmax(0,1.1fr) minmax(0,1fr) 110px minmax(0,1fr) minmax(0,1fr) 80px 80px}
.dbt-row.dbt-rver>*{flex-direction:column;align-items:flex-start;justify-content:center;gap:1px;padding-top:6px;padding-bottom:6px}
.dbt-row.dbt-rver>*>*{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dbt-rhab{grid-template-columns:minmax(0,1.3fr) minmax(0,1.1fr) 120px 120px minmax(0,1.4fr) 90px}
.dbt-row.dbt-rhab>*{flex-direction:column;align-items:flex-start;justify-content:center;gap:1px;padding-top:6px;padding-bottom:6px}
.dbt-row.dbt-rhab>*>*{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dbt-row.dbt-baja>*{flex-direction:column;align-items:flex-start;justify-content:center;gap:1px;padding-top:6px;padding-bottom:6px}
.dbt-row.dbt-baja>*>*{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dbt-eq{grid-template-columns:34px minmax(0,1.05fr) minmax(0,.9fr) minmax(0,.8fr) 172px minmax(0,.9fr) 84px 84px 100px}
/* La tabla de equipos tiene grilla PROPIA (`dbt-equip`) desde que Estado + Destino + Custodia son
   una sola columna. No se tocó `.dbt-eq` porque la comparten las dos tablas de conciliación, que
   tienen cinco columnas y se habrían desarmado. */
.dbt-equip{grid-template-columns:34px minmax(0,1.15fr) minmax(0,.95fr) minmax(0,1fr) 84px 84px 100px}
.eq-sit{display:flex;align-items:center;gap:6px;flex-wrap:wrap;min-width:0}
.eq-sit>.db-mut{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.eq-sep{color:var(--text-faint);opacity:.6}
/* SIETE COLUMNAS TAMBIÉN EN EL TELÉFONO, Y QUE LA TABLA SCROLLEE. Acá había cuatro columnas elásticas
   para "achicar" la tabla, pero la fila y el encabezado siguen teniendo SIETE celdas: metidas en una
   grilla de cuatro, se partían en dos renglones y quedaba «MAC / ETIQUETA» arriba y «VALIDADO /
   DISPONIBLE» abajo, desalineado del contenido. Con anchos fijos la fila mide más que la pantalla y
   scrollea sola dentro de `.dbt-wrap`, que es como se comportan todas las demás tablas del sistema. */
@media(max-width:1100px){
  .dbt-equip{grid-template-columns:34px 150px 132px 150px 84px 84px 100px}
  .dbt-row.dbt-equip>*{flex-direction:column;align-items:flex-start;justify-content:center;gap:1px;padding-top:6px;padding-bottom:6px}
  .dbt-row.dbt-equip>*>*{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .dbt-row.dbt-equip .eq-sit{flex-direction:row;flex-wrap:wrap}
}
.db-chk{justify-content:center;padding-left:0;padding-right:0}
.db-chk input{width:15px;height:15px;cursor:pointer;accent-color:var(--accent-ink)}
.dbt-row.dbt-eq.sel{background:color-mix(in srgb,var(--signal) 12%,transparent)}
.onu-bulk{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:8px 14px;border-bottom:1px solid var(--border);background:color-mix(in srgb,var(--signal) 9%,var(--surface-2))}
.onu-bulk .ob-n{font-weight:var(--fw-bold);font-size:12.5px;margin-right:4px}
.mon-port{margin-bottom:16px;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}
.mon-port-h{display:flex;align-items:center;gap:9px;padding:10px 14px;cursor:pointer;user-select:none;background:var(--surface-2)}
.mon-port-h:hover{background:color-mix(in srgb,var(--signal) 7%,var(--surface-2))}
.mon-port-h b{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:13.5px}
.mon-zona{font-size:12px;font-weight:var(--fw-bold);color:var(--accent-ink);background:color-mix(in srgb,var(--signal) 14%,transparent);border-radius:var(--radius-sm);padding:1px 7px}
.mon-zona-ed{border:0;background:transparent;color:var(--text-faint);cursor:pointer;font-size:12px;padding:2px 4px;border-radius:var(--radius-sm);opacity:.6}
.mon-zona-ed:hover{opacity:1;background:var(--surface-3,rgba(130,140,165,.18));color:var(--text)}
.occ-zona{color:var(--accent-ink);font-weight:var(--fw-semi)}
.mon-chev{display:inline-block;transition:transform .15s;color:var(--text-faint);font-size:12px;flex:0 0 auto}
.mon-port:not(.collapsed) .mon-chev{transform:rotate(90deg)}
.mon-port.collapsed .mon-list{display:none}
.mon-list{padding:10px 14px}
.mon-dot{width:9px;height:9px;border-radius:var(--radius-circ);display:inline-block;flex:0 0 auto}
.mon-dot.ok{background:var(--green)} .mon-dot.warn{background:var(--amber)} .mon-dot.bad{background:var(--red)} .mon-dot.off{background:var(--text-faint);opacity:.5}
.mon-occ{display:flex;align-items:center;gap:7px;flex:0 0 auto}
.mon-occ-bar{display:block;width:90px;height:7px;border-radius:var(--radius-sm);background:var(--surface-3,rgba(130,140,165,.18));overflow:hidden}
.mon-occ-bar i{display:block;height:100%;border-radius:var(--radius-sm)}
.mon-occ b{font-size:12px;font-weight:var(--fw-bold);min-width:34px;text-align:right;color:var(--text-dim)}
.mon-sig{display:inline-flex;gap:9px;font-size:12px;font-weight:var(--fw-bold);flex-wrap:wrap}
.mon-sig .ok{color:var(--green)} .mon-sig .warn{color:var(--amber)} .mon-sig .bad{color:var(--red)}
.sdot{display:inline-block;width:9px;height:9px;border-radius:var(--radius-circ);vertical-align:middle;margin:0 3px 1px 0}
.sdot.ok{background:#4f9e78}.sdot.warn{background:#c08a34}.sdot.bad{background:#c2555f}
.olt-degrade{margin:0 0 14px;padding:10px 14px;border-radius:var(--radius);background:color-mix(in srgb,var(--amber) 14%,var(--surface-2));border:1px solid color-mix(in srgb,var(--amber) 40%,var(--border));font-size:12.5px;color:var(--text)}
.olt-degrade .val-sub{color:var(--text-faint);font-size:12px}
.spinner{width:32px;height:32px;border:3px solid var(--border);border-top-color:var(--accent-ink);border-radius:var(--radius-circ);animation:spin .8s linear infinite;flex:0 0 auto}
@keyframes spin{to{transform:rotate(360deg)}}
.olt-loading{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:13px;padding:48px 20px;text-align:center;min-height:180px}
.olt-loading b{font-size:14px;font-weight:var(--fw-bold);color:var(--text)} .olt-loading span{font-size:12.5px;color:var(--text-faint);max-width:340px;line-height:1.5}
.dbt-mon{grid-template-columns:minmax(0,1.5fr) 58px 92px 92px 98px 46px}
/* en el diálogo de confirmación la etiqueta va sobre el valor, si no quedan pegadas */
#uiDialog .ocl-l{display:block;margin-bottom:2px}
#uiDialog .ocl-g{display:grid;gap:10px}
.dbt-alta{grid-template-columns:78px 108px minmax(0,1.25fr) minmax(0,1fr) minmax(0,1.7fr) 96px 116px}
/* la celda de cliente lleva dos líneas: se apila como en Buscar cliente */
.dbt-row.dbt-alta>*{flex-direction:column;align-items:flex-start;justify-content:center;gap:1px;padding-top:6px;padding-bottom:6px}
.dbt-row.dbt-alta>*>*{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dbt-row.dbt-alta .alt-cli{color:var(--accent-ink);text-decoration:none;font-weight:var(--fw-bold)}
.dbt-row.dbt-alta .alt-cli:hover{text-decoration:underline}
.dbt-row.dbt-alta>*>*{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dbt-conc{grid-template-columns:minmax(0,1.1fr) minmax(0,1fr) 128px minmax(0,1.6fr)}
.mon-reboot{width:28px;height:26px;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--border);background:var(--surface-2);border-radius:var(--radius-sm);color:var(--text-dim);cursor:pointer;transition:.12s;padding:0}
.mon-reboot:hover{border-color:var(--amber);color:var(--amber);background:color-mix(in srgb,var(--amber) 12%,var(--surface-2))}
.mon-reboot svg{width:14px;height:14px}
.mon-reboot:disabled{opacity:.5;cursor:default}
.mon-reboot.busy svg{animation:spin .8s linear infinite}
.mon-reboot.done{border-color:var(--green);color:var(--green)}
.mon-reboot.failed{border-color:var(--red);color:var(--red)}
.mon-reboot-all{display:inline-flex;align-items:center;gap:5px;font-size:12px;font-weight:var(--fw-bold);padding:3px 9px;border:1px solid var(--border);background:var(--surface-2);border-radius:var(--radius-sm);color:var(--text-dim);cursor:pointer;flex:0 0 auto}
.mon-reboot-all:hover{border-color:var(--amber);color:var(--amber)}
.mon-reboot-all svg{width:13px;height:13px}
.mon-reboot-prog{font-size:12px;font-weight:var(--fw-bold);color:var(--amber);font-family:'IBM Plex Mono';margin-left:8px;flex:0 0 auto}
.mon-reboot-stop{font-size:11px;font-weight:var(--fw-bold);padding:2px 9px;border:1px solid var(--red);background:color-mix(in srgb,var(--red) 12%,transparent);color:var(--red);border-radius:var(--radius-sm);cursor:pointer;margin-left:8px;flex:0 0 auto}
.dbt-find{grid-template-columns:104px minmax(0,1.7fr) 116px minmax(0,1.1fr) 132px 116px}
/* Las celdas de .dbt-row son de UNA línea (flex en fila + nowrap). Acá cada celda lleva dato + subtítulo,
   así que en esta tabla las apilo en columna; si no, los dos renglones quedan uno encima del otro. */
.dbt-row.dbt-find>*{flex-direction:column;align-items:flex-start;justify-content:center;gap:1px;padding-top:6px;padding-bottom:6px}
.dbt-row.dbt-find>*>*{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dbt-row.dbt-find{contain-intrinsic-size:auto 48px}
.find-via{display:block;font-size:10px;color:var(--text-faint);text-transform:uppercase;letter-spacing:.02em;line-height:1.3}
.find-sub{display:block;font-size:12px;color:var(--text-faint);line-height:1.3}
.find-nom{font-weight:var(--fw-semi)}
.find-deuda{color:var(--red);font-weight:var(--fw-bold)}
.olt-navdot{margin-left:auto;flex:0 0 auto;width:9px;height:9px;border-radius:var(--radius-circ);background:var(--red);box-shadow:0 0 0 2px color-mix(in srgb,var(--red) 25%,transparent)}
.find-box{margin-bottom:14px}
.find-box .inp{width:100%;max-width:520px;font-size:13.5px}
.find-count{font-size:12px;color:var(--text-faint);font-weight:var(--fw-bold);margin-bottom:8px}
/* Histórico de señal */
.sig-ctrls{display:flex;gap:14px;align-items:flex-end;flex-wrap:wrap;margin-bottom:16px}
.sig-f{display:flex;flex-direction:column;gap:5px;font-size:12px;color:var(--text-faint);font-weight:var(--fw-bold)}
.sig-f .sel{min-width:150px}
.sig-period{display:flex;align-items:center;gap:6px;font-size:12px}
.sig-period b{margin-right:4px;font-size:12px;color:var(--text-dim)}
.sig-period .inp{padding:6px 8px;font-size:12.5px;width:140px}
.sig-presets{display:flex;align-items:center;gap:6px}
.sig-plbl{font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-faint);font-weight:var(--fw-bold);margin-right:2px}
.sig-preset{height:32px;padding:0 12px;border:1px solid var(--border);background:var(--surface-2);color:var(--text-dim);border-radius:var(--radius);font-size:12.5px;font-weight:var(--fw-semi);cursor:pointer;transition:.12s}
.sig-preset:hover{border-color:var(--border-strong);color:var(--text)}
.sig-preset.on{background:var(--selected);color:var(--text);border-color:var(--accent-ink)}
#sigCsv{display:inline-flex;align-items:center;gap:6px}
#sigCsv svg{width:15px;height:15px}
/* ranking de red */
.sig-rankbox{display:flex;flex-direction:column;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;margin-bottom:10px}
.sig-rankrow{display:grid;grid-template-columns:minmax(0,1fr) 82px 74px 116px;gap:10px;align-items:center;padding:8px 12px;border-bottom:1px solid var(--border);font-size:12.5px;cursor:pointer;transition:.1s}
.sig-rankrow:last-child{border-bottom:0}
.sig-rankrow:hover{background:var(--surface-2)}
.sig-rankrow.bad{box-shadow:inset 3px 0 0 var(--red)}
.sig-rankrow.ok{box-shadow:inset 3px 0 0 var(--green)}
.sig-rankrow.mut{box-shadow:inset 3px 0 0 var(--border-strong)}
.sig-rank-t{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sig-rank-t i{color:var(--accent-ink);font-style:normal}
.sig-rank-d,.sig-rank-b{text-align:right;font-variant-numeric:tabular-nums;font-weight:var(--fw-bold);color:var(--text-dim)}
.sig-rankrow.bad .sig-rank-d,.sig-rankrow.bad .sig-rank-b{color:var(--red)}
/* tendencia continua */
.sig-trendh{font-size:12px;color:var(--text-faint);font-weight:var(--fw-semi);margin:2px 0 6px;display:flex;align-items:center;gap:10px}
.sig-trendbox{border:1px solid var(--border);border-radius:var(--radius);padding:8px 10px;background:var(--surface-2);margin-bottom:12px}
.sig-trend{width:100%;height:auto;display:block}
.sig-evleg{display:inline-flex;align-items:center;gap:5px;font-size:11px;color:var(--text-faint);font-weight:var(--fw-medium)}
.sig-evleg i{width:2px;height:12px;background:var(--amber);display:inline-block;border-radius:1px}
.sig-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.sig-box{border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;background:var(--surface-2)}
.sig-box-h{padding:9px 12px;background:var(--surface-3,var(--surface));font-weight:var(--fw-bold);font-family:'IBM Plex Sans';font-size:12.5px;border-bottom:1px solid var(--border);display:flex;justify-content:space-between;align-items:baseline;gap:8px}
.sig-box-h span{font-family:'IBM Plex Mono';font-size:11px;font-weight:var(--fw-medium);color:var(--text-faint)}
.sig-row{display:grid;grid-template-columns:minmax(0,1fr) 124px 74px;align-items:center;gap:8px;padding:7px 12px;border-bottom:1px solid var(--border);font-size:12.5px}
.sig-row:last-child{border-bottom:none}
.sig-gp{font-weight:var(--fw-bold);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sig-gp i{font-style:normal;color:var(--accent-ink);font-weight:var(--fw-semi);font-size:11px}
.sig-stackw{display:flex;justify-content:center} .sig-stack{display:block;border-radius:var(--radius-xs)}
.sig-nospk{font-size:10px;color:var(--text-faint)}
.sig-dist{display:flex;gap:6px;justify-content:flex-end;font-family:'IBM Plex Mono';font-weight:var(--fw-bold);font-size:12px}
.sig-dist .ok{color:var(--green)} .sig-dist .warn{color:var(--amber)} .sig-dist .bad{color:var(--red)}
.sig-na{grid-column:2/4;text-align:right;color:var(--text-faint);font-size:11px}
.sig-varbox{display:flex;flex-direction:column;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}
.sig-dist2{font-size:12px;color:var(--text-dim)}
.sig-var{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.4fr) 76px minmax(0,0.9fr);gap:8px;align-items:center;padding:8px 12px;border-bottom:1px solid var(--border);font-size:12.5px}
.sig-var:last-child{border-bottom:none}
.sig-var.bad{background:#c2555f12} .sig-var.ok{background:#4f9e7810}
.sig-ab{font-family:'IBM Plex Mono';color:var(--text-dim);font-size:12px}
.sig-delta{font-family:'IBM Plex Mono';font-weight:var(--fw-black);text-align:right}
.sig-var.bad .sig-delta{color:var(--red)} .sig-var.ok .sig-delta{color:var(--green)} .sig-var.mut .sig-delta{color:var(--text-faint)}
.sig-tag{font-size:12px;font-weight:var(--fw-bold);text-align:right}
.sig-var.bad .sig-tag{color:var(--red)} .sig-var.ok .sig-tag{color:var(--green)} .sig-var.mut .sig-tag{color:var(--text-faint)}
@media(max-width:720px){ .sig-grid{grid-template-columns:1fr} .sig-var{grid-template-columns:minmax(0,1fr) 76px;gap:4px 8px} .sig-var .sig-dist2,.sig-var .sig-tag{display:none} }
/* Histórico: gráfico grande de área + selector de GPON */
.sig-chips{display:flex;gap:7px;flex-wrap:wrap;margin-bottom:14px}
.sig-chip{border:1px solid var(--border);background:var(--surface-2);color:var(--text-dim);border-radius:var(--radius);padding:6px 13px;font-size:12.5px;font-weight:var(--fw-semi);cursor:pointer;transition:.12s}
.sig-chip:hover{background:var(--surface-3,var(--surface))}
.sig-chip.on{background:color-mix(in srgb,var(--signal) 18%,var(--surface-2));color:var(--text);border-color:var(--accent-ink);font-weight:var(--fw-bold)}
.sig-chip.worse{border-color:color-mix(in srgb,var(--red) 55%,var(--border))}
.sig-chip.worse.on{background:color-mix(in srgb,var(--red) 18%,var(--surface-2));border-color:var(--red)}
.sig-panbox{display:flex;flex-direction:column;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;margin-bottom:6px}
.sig-pan{display:grid;grid-template-columns:minmax(0,1fr) 86px minmax(0,1.25fr) 128px;gap:10px;align-items:center;padding:8px 12px;border-bottom:1px solid var(--border);font-size:12.5px;cursor:pointer;transition:.1s}
.sig-pan:last-child{border-bottom:none}
.sig-pan:hover{background:var(--surface-2)}
.sig-pan.sel{box-shadow:inset 3px 0 0 var(--accent-ink);background:var(--surface-2)}
.sig-pan.bad{background:#c2555f0f} .sig-pan.bad:hover{background:#c2555f1c}
.sig-miniw{display:flex;justify-content:center}
.sig-mini{display:block} .sig-mini-flat{color:var(--text-faint);font-size:11px}
.sig-pan .sig-tag{text-align:right;font-weight:var(--fw-bold);font-size:12px}
.sig-pan.bad .sig-tag{color:var(--red)} .sig-pan.ok .sig-tag{color:var(--green)} .sig-pan.mut .sig-tag{color:var(--text-faint)}
.sig-two{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-bottom:8px}
.sig-twobox{border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2);padding:10px 12px}
.sig-twoh{display:flex;justify-content:space-between;align-items:baseline;gap:8px;font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:12.5px;margin-bottom:4px}
.sig-twoh span{font-family:'IBM Plex Mono';font-size:11px;font-weight:var(--fw-medium);color:var(--text-faint)}
.sig-line,.sig-bars{width:100%;height:auto;display:block}
.sig-barval{fill:var(--text);font-weight:var(--fw-black);font-size:15px;font-family:'IBM Plex Mono'}
.sig-barlbl{font-weight:var(--fw-bold);font-size:12px;font-family:'IBM Plex Sans'}
.sig-baravg{font-weight:var(--fw-black);font-size:17px;font-family:'IBM Plex Mono'}
.sig-baravg-l{fill:var(--text-faint);font-size:10px;font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:.05em}
.sig-two .sig-bars{max-width:300px;margin:0 auto}
.sig-empty2{padding:40px 10px;text-align:center;color:var(--text-faint);font-size:12px}
.sig-chartwrap{border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2);padding:14px 16px 8px;margin-bottom:6px;max-width:620px}
.sig-chart-h{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px;margin-bottom:8px}
.sig-chart-h b{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:14px}
.sig-legend{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--text-dim)}
.sig-legend i{display:inline-block;width:11px;height:11px;border-radius:var(--radius-sm);margin-left:8px;vertical-align:-1px}
.sig-legend i.ok{background:var(--green)} .sig-legend i.warn{background:var(--amber)} .sig-legend i.bad{background:var(--red)}
.sig-area{width:100%;height:auto;display:block}
.sig-axt{fill:var(--text-faint);font-size:11px;font-family:'IBM Plex Mono'}
.sig-summ{display:flex;align-items:center;gap:16px;flex-wrap:wrap;margin-top:8px;padding-top:10px;border-top:1px solid var(--border)}
.sig-summ-c{display:flex;flex-direction:column;gap:3px}
.sig-summ-c>span{font-size:11px;text-transform:uppercase;letter-spacing:.05em;color:var(--text-faint);font-weight:var(--fw-bold)}
.sig-summ-c>div{display:flex;gap:8px;font-family:'IBM Plex Mono';font-weight:var(--fw-black);font-size:14px}
.sig-summ-c>div .ok{color:var(--green)} .sig-summ-c>div .warn{color:var(--amber)} .sig-summ-c>div .bad{color:var(--red)}
.sig-summ-c>i{font-style:normal;font-size:11px;color:var(--text-faint);font-family:'IBM Plex Mono'}
.sig-arrow{font-size:19px;color:var(--text-faint)}
.sig-summ-d{margin-left:auto;display:flex;flex-direction:column;align-items:flex-end;font-family:'IBM Plex Mono';font-weight:var(--fw-black);font-size:15px}
.sig-summ-d small{font-weight:var(--fw-medium);font-size:11px;opacity:.8}
.sig-summ-d.bad{color:var(--red)} .sig-summ-d.ok{color:var(--green)} .sig-summ-d.mut{color:var(--text-faint)}
.sig-var[data-gp]{cursor:pointer} .sig-var.sel{box-shadow:inset 3px 0 0 var(--accent-ink)}
.sig-summ{margin:4px 0 6px}
.sig-summ-d{display:inline-block;font-family:'IBM Plex Mono';font-weight:var(--fw-bold);font-size:13.5px;padding:5px 12px;border-radius:var(--radius);background:var(--surface-2)}
.sig-summ-d.bad{color:var(--red)} .sig-summ-d.ok{color:var(--green)} .sig-summ-d.mut{color:var(--text-faint)}
#sigDetH{display:flex;justify-content:space-between;align-items:baseline;gap:10px;flex-wrap:wrap}
@media(max-width:620px){ .sig-two{grid-template-columns:1fr} }
@media(max-width:560px){ .sig-pan{grid-template-columns:minmax(0,1fr) 70px 96px;gap:6px 8px} .sig-pan .sig-dist2{display:none} }
.rt-card{max-width:580px;margin:6px auto;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:24px}
.rt-card h4{margin:0 0 6px;font-family:'IBM Plex Sans';font-size:15px;font-weight:var(--fw-bold)}
.rt-appdl-row{display:flex;gap:9px;align-items:center;flex-wrap:wrap;margin-top:4px}
.rt-appdl-h{font-size:12px;color:var(--text-faint);margin-top:7px;display:block}
/* Acceso remoto — diseño */
.rt-steps{display:flex;gap:10px;flex-wrap:wrap;max-width:840px;margin:0 auto 16px}
.rt-step{flex:1;min-width:170px;display:flex;align-items:center;gap:11px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:11px 14px}
.rt-stepn{flex:0 0 auto;width:28px;height:28px;border-radius:var(--radius-circ);background:color-mix(in srgb,var(--signal) 20%,transparent);color:var(--accent-ink);font-weight:var(--fw-black);display:flex;align-items:center;justify-content:center;font-size:13.5px}
.rt-stept b{font-weight:var(--fw-bold);font-size:13.5px;display:block}
.rt-stept small{color:var(--text-faint);font-size:12px}
.rt-cards2{display:grid;grid-template-columns:1.5fr 1fr;gap:14px;max-width:840px;margin:0 auto;align-items:start}
.rt-card{margin:0}
.rt-adv{margin:12px 0 4px;font-size:12.5px}
.rt-adv summary{cursor:pointer;color:var(--text-dim);font-weight:var(--fw-semi);user-select:none}
.rt-adv summary:hover{color:var(--text)}
.rt-genbtn{margin-top:16px;width:100%;justify-content:center}
.rt-appcard{text-align:center;display:flex;flex-direction:column;align-items:center}
.rt-appcard h4{margin-top:6px}
.rt-appicon{width:52px;height:52px;border-radius:var(--radius);background:color-mix(in srgb,var(--signal) 14%,transparent);color:var(--accent-ink);display:flex;align-items:center;justify-content:center;margin-bottom:6px}
.rt-appicon svg{width:26px;height:26px}
.rt-appcard .rt-appdl-row{justify-content:center}
@media(max-width:680px){ .rt-cards2{grid-template-columns:1fr} }
.rt-sub{color:var(--text-dim);font-size:12.5px;margin:0 0 14px;line-height:1.5}
.rt-token{font-family:'IBM Plex Mono',monospace;font-size:27px;font-weight:var(--fw-semi);letter-spacing:4px;background:var(--surface);border:1px dashed var(--border-strong);border-radius:var(--radius);padding:18px;text-align:center;word-break:break-all;margin-bottom:10px;color:var(--accent-ink)}
.rt-status{margin:18px 0 6px}
.rt-st{display:inline-flex;align-items:center;gap:8px;font-weight:var(--fw-bold);font-size:13.5px}
.rt-st.ok{color:var(--green)} .rt-st.wait{color:var(--amber)} .rt-st.off{color:var(--text-faint)}
.rt-actions{display:flex;gap:10px;align-items:center;margin-top:6px;flex-wrap:wrap}
.rt-actions .btn-primary[disabled]{opacity:.45;pointer-events:none}
.rt-note{color:var(--text-faint);font-size:12px;margin-top:16px;line-height:1.5}
.rt-https{display:flex;align-items:center;gap:7px;font-size:12.5px;color:var(--text-dim);margin-top:12px;cursor:pointer}
.spinner.sm{width:14px;height:14px;border-width:2px}
/* Caja de carga reutilizable (spinner + texto) para las pantallas que cargan datos */
.ld-box{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:11px;padding:34px 18px;text-align:center;color:var(--text-dim)}
.ld-box .spinner{width:26px;height:26px;border-width:3px}
.ld-box b{font-size:13.5px;font-weight:var(--fw-bold);color:var(--text-dim)}
.ld-box span{font-size:12px;color:var(--text-faint);max-width:320px;line-height:1.5}
.ld-inline{display:inline-flex;align-items:center;gap:8px;color:var(--text-dim)}
/* Barra de carga superior (indeterminada) para transiciones/cargas globales */
/* ===== EL AVISO DE CARGA, CHIQUITO Y AL COSTADO =====
   Antes era un cartel FIJO EN EL CENTRO de la pantalla —justo donde uno está mirando—, que tapaba
   una fila de la tabla o medio panel. Ahora es un punto que gira al lado de «FTTHGestión»: se ve si
   lo mirás y no se te viene encima si no. En el celular la barra lateral es un cajón cerrado, así
   que ahí el mismo punto va al lado del botón ☰. */
@keyframes cgSpin{to{transform:rotate(360deg)}}
.cg-mini{width:14px;height:14px;flex:0 0 auto;box-sizing:border-box;border-radius:var(--radius-circ);
  border:2px solid var(--border);border-top-color:var(--accent-ink);
  opacity:0;transition:opacity .18s}
body.cargando .cg-mini{opacity:1;animation:cgSpin .85s linear infinite}
/* Cuando de verdad está tardando cambia de color: es lo único que el cartel decía y que cambia
   lo que uno puede hacer (esperar o recargar). El detalle va en el globito. */
body.cargando.carga-lenta .cg-mini{border-top-color:var(--amber)}
#sideNav .sn-brand .cg-mini{margin-left:auto}
body.nav-side.nav-rail:not(.nav-peek) #sideNav .sn-brand{gap:6px}
body.nav-side.nav-rail:not(.nav-peek) #sideNav .sn-brand .cg-mini{margin-left:0;width:12px;height:12px}
/* El de la barra de arriba existe sólo para el celular, donde el cajón está cerrado. */
.cg-mini-movil{display:none;margin-right:10px}
@media(max-width:899px){ .cg-mini-movil{display:block} }
/* Barra en línea, para las pantallas que antes mostraban un spinner mientras cargaban. */
.cg-inline{display:flex;flex-direction:column;align-items:center;gap:10px;padding:34px 16px;text-align:center}
/* La marca, al 22%: tiene que acompañar la espera, no competir con el texto que dice qué carga. */
.cg-inline .cg-marca{display:flex;align-items:center;gap:9px;opacity:.22;margin-bottom:2px;
  font-family:'Archivo',system-ui,sans-serif;font-weight:var(--fw-black);font-size:14px;letter-spacing:-.2px;color:var(--text)}
.cg-inline .cg-marca b{color:var(--accent-ink);font-weight:var(--fw-black)}
.cg-inline .cg-marca-sp{width:15px;height:15px;flex:0 0 auto;box-sizing:border-box;border-radius:var(--radius-circ);
  border:2px solid var(--border);border-top-color:var(--accent-ink);animation:cgSpin .85s linear infinite}
.cg-inline b{font-size:13.5px;color:var(--text)}
.cg-inline span{font-size:12px;color:var(--text-faint);max-width:460px}
.cg-inline .cg-bar{width:min(280px,70%)}
.cg-inline .cg-fill{animation:cgIndet 1.4s ease-in-out infinite;width:38%}
@keyframes cgIndet{0%{margin-left:-38%}55%{margin-left:100%}100%{margin-left:100%}}
.rt-mode{margin:14px 0;padding:14px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface)}
.rt-mode-h{font-size:12.5px;margin-bottom:6px}
.rt-mode-h .ma{color:var(--green);font-weight:var(--fw-bold)} .rt-mode-h .mm{color:var(--amber);font-weight:var(--fw-bold)}
.rt-detected{font-size:12.5px;color:var(--text-dim);margin-bottom:8px}
.rt-mf-row{display:flex;gap:8px;align-items:center;margin-top:8px;flex-wrap:wrap}
.rt-mf-row .inp{max-width:200px}
.occ-list{display:flex;flex-direction:column}
/* La franja reemplaza a la línea: con las dos, una lista de 118 renglones queda rayada. */
.occ-row{display:grid;grid-template-columns:minmax(0,1fr) 92px minmax(0,1.3fr) 120px;align-items:center;gap:10px;padding:4px 8px;font-size:12.5px}
.occ-row:nth-child(even){background:var(--zebra)}
.occ-row:last-child{border-bottom:0}
.occ-olt{font-weight:var(--fw-bold);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.occ-port{color:var(--text-faint);font-size:12px}
.occ-bar{height:8px;border-radius:var(--radius-sm);background:var(--surface-3,var(--surface-2));overflow:hidden}
.occ-bar i{display:block;height:100%;border-radius:var(--radius-sm)}
.occ-bar i.warn{background:var(--amber)} .occ-bar i.err{background:var(--red)}
.occ-val{text-align:right;font-variant-numeric:tabular-nums;font-weight:var(--fw-bold)}
.occ-val.warn{color:var(--amber)} .occ-val.err{color:var(--red)}
@media(max-width:560px){ .occ-row{grid-template-columns:minmax(0,1fr) 110px;gap:4px 10px} .occ-bar{display:none} }
.occ-bar i.ok{background:var(--green)}
.occ-val.ok{color:var(--green)}
/* Vista Temperatura: columna ancha para RX/TX/V (sin cortar el voltaje) y todas las filas iguales */
.temp-list .occ-row{grid-template-columns:minmax(0,1.1fr) minmax(0,1.7fr) 60px 52px}
.temp-list .occ-port{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
@media(max-width:560px){
  .temp-list .occ-row{grid-template-columns:1fr auto;grid-template-areas:"a v" "p p";gap:1px 8px}
  .temp-list .occ-olt{grid-area:a}.temp-list .occ-port{grid-area:p;font-size:11px}.temp-list .occ-val{grid-area:v}.temp-list .occ-bar{display:none}
}
/* Anomalías de red */
.anom-chips{display:flex;flex-wrap:wrap;gap:7px;margin:4px 0 12px}
.anom-chip{display:inline-flex;align-items:center;gap:6px;font-size:12px;padding:3px 10px;border-radius:var(--radius-sm);border:1px solid color-mix(in srgb,var(--kc) 45%,var(--border));background:color-mix(in srgb,var(--kc) 9%,transparent);color:var(--text-dim)} .anom-chip b{color:var(--text)}
.anom-list{display:flex;flex-direction:column;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}
.anom-row{display:grid;grid-template-columns:8px minmax(120px,150px) minmax(150px,1.4fr) minmax(180px,2.4fr) 84px;align-items:center;gap:12px;padding:9px 13px;border-top:1px solid var(--border)}
.anom-row:first-child{border-top:none}
.anom-row.anom-head{background:var(--surface-2);color:var(--text-dim);font-size:11px;text-transform:uppercase;letter-spacing:.03em;font-weight:var(--fw-bold);padding:6px 13px}
.anom-row:not(.anom-head){cursor:pointer} .anom-row:not(.anom-head):hover{background:color-mix(in srgb,var(--accent-ink) 7%,transparent)}
.anom-sev{width:8px;height:8px;border-radius:var(--radius-circ);background:var(--text-faint)} .anom-sev.sev1{background:var(--amber,#f5a623)} .anom-sev.sev2{background:var(--signal,#e5484d)}
.anom-kind{font-weight:var(--fw-bold);font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.anom-dev{font-size:12.5px;font-weight:var(--fw-semi);overflow:hidden;text-overflow:ellipsis;white-space:nowrap} .anom-dev small{display:block;color:var(--text-faint);font-weight:var(--fw-normal);font-size:11px}
.anom-msg{font-size:12.5px;color:var(--text-dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.anom-since{font-size:12px;color:var(--text-faint);text-align:right;white-space:nowrap}
.anom-ok{display:flex;align-items:center;gap:14px;padding:22px;border:1px solid color-mix(in srgb,var(--green) 35%,var(--border));background:color-mix(in srgb,var(--green) 6%,var(--surface));border-radius:var(--radius)}
.anom-ok-ic{width:44px;height:44px;flex:0 0 auto;display:grid;place-items:center;border-radius:var(--radius-circ);background:color-mix(in srgb,var(--green) 20%,transparent);color:var(--green);font-size:21px;font-weight:var(--fw-black)}
@media(max-width:820px){ .anom-row{display:flex;flex-wrap:wrap;gap:4px 10px} .anom-row.anom-head{display:none} .anom-sev{align-self:center} .anom-since{margin-left:auto} .anom-dev,.anom-msg{flex:1 1 100%;white-space:normal} }
/* Ficha de cliente de la ONU (buscador) */
a.dbt-find.clk,a.sn-cli{color:inherit;text-decoration:none}
.dbt-find.clk{cursor:pointer} .dbt-find.clk:hover{background:color-mix(in srgb,var(--accent-ink) 8%,transparent)}
/* ===== FICHA DEL CLIENTE, DENSA =====
   Cada dato venía en su propia TARJETA con fondo, borde y 12 px de relleno: 57 px de alto para
   mostrar una etiqueta y un valor. Con 26 campos, la solapa técnica medía 1538 px y había que
   scrollear 930 para llegar al final. Ahora cada dato es UN RENGLÓN etiqueta-valor separado por un
   filete finito —la forma de una ficha técnica de toda la vida— y las secciones van en dos columnas.
   El chrome de las tarjetas no aportaba nada: lo que separa un dato del otro es el filete. */
.ocl-sec{margin-bottom:11px;break-inside:avoid}
/* Sin versales: se lee «Latencia · cada minuto» y no «LATENCIA · CADA MINUTO». Es lo mismo que ya
   se sacó de las cabeceras de las tablas, de los contadores y del menú. */
/* EL NOMBRE DEL GRAFICO, EN EL COLOR DEL TEXTO. Iba en --text-dim, el mismo gris que su propia
   aclaracion, asi que «Latencia» y «cada minuto» pesaban igual y el titulo no se despegaba del
   dibujo. El nombre dice QUE estas mirando: va en el color de lectura, y el gris queda para la
   aclaracion, que es lo secundario. */
.ocl-sec-t{font-size:12px;text-transform:none;letter-spacing:0;color:var(--text);
  font-weight:var(--fw-semi);margin-bottom:5px;padding-bottom:3px;border-bottom:1px solid var(--border)}
/* La aclaracion —«· cada minuto», «· 30 dias»— apagada y sin negrita: acompania al nombre. */
.ocl-sec-t span{color:var(--text-faint)}
.ocl-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(290px,1fr));gap:0 24px}
.ocl-f{display:grid;grid-template-columns:minmax(84px,34%) 1fr;gap:10px;align-items:baseline;
  padding:2.5px 0;background:none;border:0;border-radius:0;
  border-bottom:1px dotted color-mix(in srgb,var(--border) 80%,transparent)}
/* Dos columnas para lo que no es una tabla. Con la ventana en 1180 entra el doble de datos sin
   scrollear, que era el pedido. */
.ocl-cols{columns:2;column-gap:26px}
/* Dos paneles enteros, uno al lado del otro. No se usa `columns` acá porque reparte el contenido y
   puede cortar una tabla por la mitad: con grid cada uno se queda entero en su lado. */
.ocl-par{display:grid;grid-template-columns:1fr 1fr;gap:24px;align-items:start}
.ocl-tk.ocl-tk5{grid-template-columns:minmax(0,84px) minmax(0,74px) minmax(0,66px) minmax(0,96px) minmax(0,1fr)}
@media(max-width:900px){ .ocl-par{grid-template-columns:1fr} }
/* En el celular, una sola columna: dos de 190 px no son dos columnas, son dos recortes. */
@media(max-width:820px){ .ocl-cols{columns:1} .ocl-f{grid-template-columns:minmax(84px,42%) 1fr} }
.ocl-full{column-span:all}
/* Las listas largas (el historial de red, los soportes) scrollean ADENTRO, con su encabezado fijo:
   así el historial completo se ve primero sin empujar todo lo demás fuera de la pantalla. */
.ocl-scroll{max-height:262px;overflow:auto;border:1px solid var(--border);border-radius:var(--radius);padding:0 10px 4px}
.ocl-graf{margin:6px 0 2px}
/* El lugar reservado mientras se busca el dato: un punto tenue que respira. No una barra de carga
   por celda, que llena la tabla de ruido y hace parecer que algo se rompió. */
.olt-esq{color:var(--text-faint);opacity:.45;animation:oltEsq 1.1s ease-in-out infinite}
/* El cuadro del vivo en pausa: se ve lo que va a aparecer, atenuado, con el play encima. Se atenúa
   la tabla y NO se la esconde para que el lugar quede ocupado desde el principio. */
.vivo-velo{position:relative}
.vivo-pausa .vivo-velo table{opacity:.28;filter:saturate(.4)}
.vivo-play{position:absolute;inset:0;margin:auto;width:max-content;height:max-content;
  display:flex;align-items:center;gap:9px;background:var(--surface);border:1px solid var(--border-strong);
  color:var(--text);border-radius:var(--radius-sm);padding:9px 18px 9px 15px;font:inherit;font-size:13.5px;
  font-weight:var(--fw-semi);cursor:pointer;box-shadow:0 8px 26px rgba(0,0,0,.35);transition:.14s}
.vivo-play:hover{border-color:var(--accent-ink);color:var(--accent-ink)}
.vivo-play span{font-weight:var(--fw-medium)}
/* PARAR va en el encabezado, no encima de la tabla. El botón de arrancar se centra sobre el cuadro
   en pausa —ahí tapar no molesta, no hay nada que leer—, pero mientras corre lo que se mira es la
   tabla y un botón flotando en el medio la taparía justo. */
.vivo-stop{margin-left:auto;display:inline-flex;align-items:center;gap:7px;background:transparent;
  border:1px solid var(--border-strong);color:var(--text-dim);border-radius:var(--radius-sm);padding:5px 13px 5px 11px;
  font:inherit;font-size:12.5px;font-weight:var(--fw-semi);cursor:pointer;transition:.14s;flex:0 0 auto}
.vivo-stop:hover{border-color:var(--red);color:var(--red)}
.vivo-vivo{display:inline-flex;align-items:center;gap:6px;color:var(--green);font-size:12px;font-weight:var(--fw-bold);
  text-transform:uppercase;letter-spacing:.06em}
.vivo-vivo i{width:7px;height:7px;border-radius:var(--radius-circ);background:var(--green);animation:oltpulse 1.8s infinite}
@keyframes oltEsq{0%,100%{opacity:.25}50%{opacity:.6}}
.ocl-scroll .ocl-tk-h{position:sticky;top:0;background:var(--surface);z-index:1;padding-top:7px}
/* El cuerpo de la ficha aprovecha más alto que un modal común (62vh): es una pantalla de consulta,
   no un formulario de tres campos. Y menos relleno, que con dos columnas se nota. */
.ocl-body{max-height:76vh;padding:15px 20px;gap:12px}
.ocl-l{font-size:11px;color:var(--text-faint);text-transform:uppercase;letter-spacing:.02em;line-height:1.35}
.ocl-v{font-size:12.5px;line-height:1.4;color:var(--text);word-break:break-word} .ocl-v a{color:var(--accent-ink)} .ocl-v small{color:var(--text-faint);font-weight:var(--fw-normal)}
.ocl-foot{margin-top:12px;display:flex;gap:8px;flex-wrap:wrap}
.ocl-tk{display:grid;grid-template-columns:minmax(0,1.6fr) 108px minmax(0,1fr) 104px;gap:6px 12px;font-size:12.5px}
/* En el celular estas grillas no entran: las columnas quedan de ~70 px y el texto, en vez de recortarse,
   SE ENCIMA con el de la columna de al lado (se veía «84:D8:1B:D0:XNQ2Q7», la MAC pisada por el modelo).
   Se les da su ancho real y el contenedor scrollea de costado, que es lo que ya hacen las demás tablas
   anchas del sistema. */
.tk-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;max-width:100%}
@media(max-width:760px){
  .ocl-sec{overflow-x:auto}
  .ocl-tk{min-width:540px}
}
.ocl-tk-h{font-size:11px;color:var(--text-faint);text-transform:uppercase;letter-spacing:.02em;padding-bottom:2px;border-bottom:1px solid var(--border)}
.ocl-tk-r{padding:3px 0;border-bottom:1px solid var(--border)}
.ocl-warn{padding:8px 10px;border:1px solid var(--amber);border-radius:var(--radius);background:color-mix(in srgb,var(--amber) 10%,transparent);font-size:12.5px;margin-bottom:12px}
.live-wrap{margin-top:10px;border:1px solid var(--border);border-radius:var(--radius);padding:8px 10px;background:var(--surface-2)}
.live-head{display:flex;align-items:center;gap:7px;font-size:12.5px;margin-bottom:6px}
.live-head .grow{flex:1}
.live-dot{width:8px;height:8px;border-radius:var(--radius-circ);background:var(--red);animation:livep 1.2s infinite}
/* Herramientas de diagnóstico de la ficha: van juntas porque hacen lo mismo. */
.diag-bar{margin-top:12px;padding-top:10px;border-top:1px solid var(--border)}
.diag-bar-t{font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--text-faint);font-weight:var(--fw-bold);margin-bottom:8px}
.diag-btns{display:flex;gap:8px;flex-wrap:wrap}
.diag-btns .btn{padding:8px 13px;font-size:12.5px}
.diag-btns .btn svg{width:15px;height:15px;flex:0 0 auto}
/* Corriendo: se nota sin leer, por el color y por el punto que late. */
.btn.diag-on{background:color-mix(in srgb,var(--red) 16%,transparent);border-color:var(--red);color:var(--red)}
.btn.diag-on .live-dot{background:currentColor}
.diag-res{margin-top:10px}
/* Las dos consolas, una al lado de la otra: se puede mirar el ping mientras corre el trazado. */
.diag-dos{display:grid;grid-template-columns:1fr;gap:16px;align-items:start}
.diag-col-t{font-size:11px;letter-spacing:.05em;text-transform:uppercase;color:var(--text-faint);font-weight:var(--fw-bold);margin-bottom:5px}

/* Los tres números del ping, como fichas y no como un renglón de texto. */
.diag-kpis{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:8px}
.diag-kpi{flex:1 1 110px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:8px 11px}
.diag-kpi .k-l{font-size:11px;letter-spacing:.05em;text-transform:uppercase;color:var(--text-faint);font-weight:var(--fw-bold)}
.diag-kpi .k-v{font-size:18px;font-weight:var(--fw-black);line-height:1.25;font-family:'IBM Plex Mono'}
.diag-kpi .k-s{font-size:11px;color:var(--text-faint)}
/* Cada respuesta del ping como una barrita: se ve de un vistazo si pierde de a ráfagas o parejo. */
.diag-tiras{display:flex;gap:3px;align-items:flex-end;height:32px;margin-top:2px;justify-content:flex-start}
.diag-tira{flex:0 0 auto;width:9px;border-radius:var(--radius-xs) var(--radius-xs) 0 0;background:var(--signal);opacity:.85}
.diag-tira.perdido{background:var(--red);opacity:.5}
/* La consola. Fondo propio y no el del tema: una terminal se lee así en claro y en oscuro. */
.cmd{margin-top:10px;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;background:#0c1117}
.cmd-bar{display:flex;align-items:center;gap:8px;padding:7px 11px;background:#131a23;border-bottom:1px solid #1e2733}
.cmd-luz{width:9px;height:9px;border-radius:var(--radius-circ);background:#3f4c5c;flex:0 0 auto}
.cmd-luz.on{background:#4ade80;animation:livep 1.2s infinite}
.cmd-cmd{font-family:'IBM Plex Mono';font-size:12px;color:#8ba3bd;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cmd-x{background:none;border:0;color:#5d7391;cursor:pointer;font-size:11px;padding:2px 6px;border-radius:var(--radius-sm)}
.cmd-x:hover{color:#cfe0f2;background:#1e2733}
.cmd-out{font-family:'IBM Plex Mono';font-size:12px;line-height:1.65;color:#c6d4e3;
  padding:9px 12px;max-height:280px;overflow:auto;white-space:pre-wrap;word-break:break-word}
.cmd-out .l-ok{color:#c6d4e3}
.cmd-out .l-mal{color:#ff8b8b}
.cmd-out .l-tit{color:#7fd1ff}
.cmd-out .l-res{color:#ffd47f}
.cmd-out .l-eco{color:#5d7391}
@keyframes livep{0%,100%{opacity:1}50%{opacity:.25}}
.eq-info{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:8px 12px;margin-bottom:12px;font-size:12.5px}
.eq-info summary{cursor:pointer;font-weight:var(--fw-bold);color:var(--text-faint);text-transform:uppercase;font-size:11px;letter-spacing:.04em}
.eq-info ul{margin:8px 0 4px;padding-left:18px;color:var(--text-dim)} .eq-info li{margin-bottom:3px}
.eq-info-n{color:var(--text-faint);font-size:12px;margin-top:4px}
.eq-controles{border-color:var(--amber)}
.eq-controles summary{color:var(--amber)}
.eq-como{font-size:12.5px;color:var(--text-dim);background:var(--surface-2);border-left:3px solid var(--accent-ink);padding:7px 10px;border-radius:0 var(--radius-sm) var(--radius-sm) 0;margin:10px 0}
.btn-mini{font-size:11px;padding:2px 8px;margin-left:8px}
.eq-modelo{font-size:12px;font-weight:var(--fw-bold);color:var(--accent-ink);background:color-mix(in srgb,var(--accent-ink) 12%,transparent);border-radius:var(--radius-sm);padding:1px 7px}
.eq-card{border:1px solid var(--border);border-radius:var(--radius);padding:10px 12px;margin-bottom:8px;background:var(--surface-2)}
.eq-card-h{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-bottom:6px}
.eq-card-b>div{margin-bottom:4px;font-size:12.5px}
.eq-card-b .ocl-l{display:inline-block;min-width:150px}
.eq-cand{margin:3px 0 3px 150px;font-size:12.5px}
/* Tabla de equipos APILADA (5 columnas → cada equipo ocupa dos renglones). Esto es para pantallas
   angostas, donde las 9 columnas no entran. Estaba SUELTO, fuera de todo media query, así que pisaba
   también al escritorio: con 1440 px de pantalla cada equipo seguía partido en dos renglones y con los
   encabezados duplicados, había que aparear las filas de a dos para leer un solo equipo. */
@media(max-width:1100px){
  .dbt-eq{grid-template-columns:minmax(0,1.2fr) minmax(0,1.1fr) minmax(0,1fr) minmax(0,1.2fr) minmax(0,1fr)}
  .dbt-row.dbt-eq>*{flex-direction:column;align-items:flex-start;justify-content:center;gap:1px;padding-top:6px;padding-bottom:6px}
  .dbt-row.dbt-eq>*>*{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
}
/* Aviso de dato congelado en el mapa: cuando una OLT viene contestando lecturas incompletas,
   el estado de sus cajas es el de la lectura anterior. Mostrar rojo con confianza sobre un dato viejo
   es peor que avisar. */
.cm-aviso{margin:0 14px 10px;padding:9px 13px;border-radius:var(--radius);font-size:12.5px;line-height:1.45;
  background:color-mix(in srgb,var(--amber) 13%,transparent);border:1px solid color-mix(in srgb,var(--amber) 34%,transparent);color:var(--text)}
.cm-aviso b{font-weight:var(--fw-bold)}
.cm-kchip.on{outline:2px solid var(--accent-ink)}
.salud-g{margin-bottom:18px}
.salud-g-h{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:4px;font-size:12.5px}
.sig-spark{width:100%;height:54px;margin-top:10px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius)}
.sig-spark-l{display:flex;justify-content:space-between;font-size:11px;color:var(--text-faint);margin-top:2px}
/* Panel de red unificado */
.anom-sev.up{background:var(--green)}
.pnl-cats{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px;margin:4px 0 14px}
.pnl-cat{border:1px solid var(--border);border-radius:var(--radius);padding:11px 13px;background:var(--surface)}
.pnl-cat-t{font-weight:var(--fw-bold);font-size:12.5px;margin-bottom:4px}
.pnl-cat-n{font-size:12.5px} .pnl-cat-n b{font-family:'IBM Plex Sans';font-size:18px;color:var(--green)}
.pnl-cat-tr{font-size:12px;color:var(--text-dim);font-variant-numeric:tabular-nums;margin-top:2px}
.pnl-cat-an{font-size:12px;font-weight:var(--fw-bold);color:var(--amber,#f5a623);margin-top:4px} .pnl-cat-an.ok{color:var(--text-faint);font-weight:var(--fw-normal)}
.pnl-info{margin:0 0 12px;border:1px solid var(--border);border-radius:var(--radius);background:color-mix(in srgb,var(--accent-ink) 4%,var(--surface));overflow:hidden}
.pnl-info>summary{cursor:pointer;padding:9px 13px;font-size:12.5px;font-weight:var(--fw-bold);color:var(--text-dim);list-style:none;user-select:none} .pnl-info>summary::-webkit-details-marker{display:none}
.pnl-info>summary::before{content:'▸';display:inline-block;margin-right:7px;color:var(--text-faint);transition:transform .15s} .pnl-info[open]>summary::before{transform:rotate(90deg)}
.pnl-info>summary:hover{color:var(--text)}
.pnl-info-b{padding:2px 14px 12px;border-top:1px solid var(--border)} .pnl-info-b p{margin:9px 0;font-size:12.5px;line-height:1.5;color:var(--text-dim)} .pnl-info-b b{color:var(--text)}
.pnl-seg{margin:0 0 10px}
/* Editor de capacidades */
.cap-list{border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}
.cap-row{display:grid;grid-template-columns:minmax(150px,1.8fr) minmax(120px,1.1fr) 150px 96px;align-items:center;gap:12px;padding:8px 12px;border-top:1px solid var(--border)} .cap-row:first-child{border-top:none}
.cap-row.cap-head{background:var(--surface-2);color:var(--text-dim);font-size:11px;text-transform:uppercase;letter-spacing:.03em;font-weight:var(--fw-bold);padding:6px 12px}
.cap-dev{font-weight:var(--fw-semi);font-size:12.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap} .cap-dev small{display:block;color:var(--text-faint);font-weight:var(--fw-normal);font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.cap-tr{font-size:12px;color:var(--text-dim);font-variant-numeric:tabular-nums} .cap-tr small{display:block;color:var(--text-faint)}
.cap-in{display:flex;align-items:center;gap:6px} .cap-in input{width:80px;padding:5px 8px;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface-2);color:var(--text);font-variant-numeric:tabular-nums} .cap-in input:focus{outline:none;border-color:var(--accent-ink)} .cap-in span{font-size:11px;color:var(--text-faint)}
.cap-sug{font-size:11px;font-weight:var(--fw-bold);padding:4px 8px;border-radius:var(--radius-sm);border:1px solid color-mix(in srgb,var(--green) 45%,var(--border));background:color-mix(in srgb,var(--green) 10%,transparent);color:var(--green);cursor:pointer;white-space:nowrap} .cap-sug:hover{background:color-mix(in srgb,var(--green) 18%,transparent)}
@media(max-width:720px){ .cap-row{grid-template-columns:1.4fr 120px 80px;gap:8px} .cap-row .cap-sugc,.cap-row.cap-head{display:none} }
.pnl-list{border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}
.pnl-row{display:grid;grid-template-columns:16px minmax(150px,2fr) 62px minmax(96px,1.1fr) minmax(120px,1.3fr) 52px;align-items:center;gap:11px;padding:8px 12px;border-top:1px solid var(--border)}
.pnl-row:first-child{border-top:none}
.pnl-row.pnl-head,.pnl-trow.pnl-head,.nd-row.nd-head{background:var(--surface-2);color:var(--text-dim);font-size:11px;text-transform:uppercase;letter-spacing:.03em;font-weight:var(--fw-bold);padding:6px 12px}
.pnl-row:not(.pnl-head){cursor:pointer} .pnl-row:not(.pnl-head):hover,.pnl-trow:not(.pnl-head):hover,.nd-row:not(.nd-head):hover{background:color-mix(in srgb,var(--accent-ink) 7%,transparent)}
.pnl-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:var(--fw-semi);font-size:12.5px} .pnl-name small{display:block;color:var(--text-faint);font-weight:var(--fw-normal);font-size:11px;overflow:hidden;text-overflow:ellipsis}
.pnl-ports,.pnl-tr,.pnl-trv{font-size:12px;font-variant-numeric:tabular-nums;color:var(--text-dim)} .pnl-tr small,.pnl-trv small{display:block;color:var(--text-faint)}
.pnl-util,.nd-util{display:flex;align-items:center;gap:7px;font-size:12px;font-variant-numeric:tabular-nums} .pnl-util b{min-width:30px;text-align:right}
.pnl-utilbar{flex:1;height:8px;border-radius:var(--radius-sm);background:var(--surface-3,var(--surface-2));overflow:hidden} .pnl-utilbar i{display:block;height:100%;border-radius:var(--radius-sm)}
.pnl-an{text-align:right}
.pnl-anb{display:inline-block;min-width:22px;text-align:center;font-size:11px;font-weight:var(--fw-black);padding:1px 7px;border-radius:var(--radius-sm);background:color-mix(in srgb,var(--amber) 18%,transparent);color:var(--amber,#f5a623)} .pnl-anb.crit{background:color-mix(in srgb,var(--signal) 20%,transparent);color:var(--signal,#e5484d)} .pnl-anb.ok{background:color-mix(in srgb,var(--green) 15%,transparent);color:var(--green)}
.pnl-trow{display:grid;grid-template-columns:minmax(150px,1.6fr) minmax(120px,2fr) minmax(96px,1.1fr) 58px;align-items:center;gap:12px;padding:8px 12px;border-top:1px solid var(--border);cursor:pointer} .pnl-trow:first-child{border-top:none}
.pnl-trbar{height:9px;border-radius:var(--radius-sm);background:var(--surface-3,var(--surface-2));overflow:hidden} .pnl-trbar i{display:block;height:100%;border-radius:var(--radius-sm);background:linear-gradient(90deg,color-mix(in srgb,var(--signal) 45%,transparent),var(--signal))}
.pnl-tru{text-align:right;font-variant-numeric:tabular-nums;font-weight:var(--fw-bold)}
.nd-anoms{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px}
.nd-anb{font-size:11px;font-weight:var(--fw-bold);padding:2px 9px;border-radius:var(--radius-sm);border:1px solid} .nd-anb.sev2{color:var(--signal);border-color:color-mix(in srgb,var(--signal) 50%,var(--border))} .nd-anb.sev1{color:var(--amber);border-color:color-mix(in srgb,var(--amber) 50%,var(--border))}
.nd-list{border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;max-height:56vh;overflow-y:auto}
.nd-row{display:grid;grid-template-columns:minmax(140px,1.6fr) minmax(140px,1.5fr) minmax(110px,1.2fr) 44px;align-items:center;gap:11px;padding:7px 12px;border-top:1px solid var(--border)} .nd-row:first-child{border-top:none}
.nd-row:not(.nd-head){cursor:pointer} .nd-row.nd-alert{background:color-mix(in srgb,var(--signal) 6%,transparent)}
.nd-if{display:flex;align-items:center;gap:8px;font-size:12.5px;font-weight:var(--fw-semi);overflow:hidden} .nd-if small{color:var(--text-faint);font-weight:var(--fw-normal)}
.nd-tr{font-size:12px;color:var(--text-dim);font-variant-numeric:tabular-nums} .nd-tr span{color:var(--text-faint)}
.nd-x{text-align:right}
@media(max-width:820px){ .pnl-row{grid-template-columns:16px 1.5fr 70px 46px} .pnl-row .pnl-tr,.pnl-row .pnl-util,.pnl-row.pnl-head{display:none} .pnl-trow{grid-template-columns:1.5fr 1fr 50px} .pnl-trow .pnl-trbar{display:none} .nd-row{grid-template-columns:1.4fr 1.2fr 44px} .nd-row .nd-util{display:none} }
/* Avisos de red (alertas LibreNMS) */
.av-list .occ-row{grid-template-columns:92px minmax(0,1fr) minmax(0,1.7fr) 78px}
.red-list .occ-row{grid-template-columns:minmax(0,1.3fr) minmax(0,1.4fr) 96px}
@media(max-width:560px){ .red-list .occ-row{grid-template-columns:minmax(0,1fr) 90px} .red-list .occ-port{display:none} }
.sev-chip{display:inline-block;font:600 10.5px/1 ui-monospace,"Consolas",monospace;letter-spacing:.03em;padding:5px 7px;border-radius:var(--radius-xs);white-space:nowrap}
.sev-chip.err{background:color-mix(in srgb,var(--red) 16%,transparent);color:var(--red)}
.sev-chip.warn{background:color-mix(in srgb,var(--amber) 16%,transparent);color:var(--amber)}
.sev-chip.ok{background:color-mix(in srgb,var(--green) 16%,transparent);color:var(--green)}
@media(max-width:560px){ .av-list .occ-row{grid-template-columns:80px minmax(0,1fr);gap:2px 8px} .av-list .occ-port{grid-column:1/-1;white-space:normal!important;text-align:left!important} }
/* Enlaces: filas clickeables → gráfico */
.lg-row{cursor:pointer}
.lg-row:hover{background:color-mix(in srgb,var(--accent-ink,#227d73) 9%,transparent)}
.lg-graph{min-height:230px;display:flex;flex-direction:column;align-items:center;justify-content:center;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-sm);overflow:auto;padding:6px}
.lg-note{align-self:stretch;font-size:12.5px;line-height:1.45;color:var(--text-faint);background:color-mix(in srgb,var(--amber) 12%,transparent);border-radius:var(--radius-sm);padding:9px 12px;margin-bottom:8px}
.lg-note b{color:var(--text)}
/* Planificador de capacidad */
/* Mismo aspecto que `.tt-kpi`, que es el contador del resto del sistema. */
/* UNA FRANJA, no cuatro cajitas. Los totales de una pantalla son un bloque: se leen juntos y se
   comparan entre sí. Separados por 8 px de aire cada uno parecía una tarjeta aparte. */
.cap-kpis{display:flex;gap:0;flex-wrap:wrap;margin-bottom:0;background:var(--surface);
  border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}
/* DOS LÍNEAS: el número arriba, el rótulo abajo. En una sola línea el número y su rótulo compiten
   con los del indicador de al lado y hay que separarlos con la vista. */
.cap-kpis .kpi{flex:0 1 auto;background:transparent;border:0;border-right:1px solid var(--border);
  border-radius:0;padding:10px 18px;display:flex;align-items:baseline;gap:0 7px;
  flex-wrap:wrap;min-width:0}
.cap-kpis .kpi .k-num{flex:0 0 100%}   /* fuerza el corte de línea después del número */
.cap-kpis .kpi:last-child{border-right:0}
/* En el telefono la franja se apila: ahi la division va ABAJO y no al costado, o queda un pedacito
   de linea vertical colgando a la derecha de cada renglon. */
@media(max-width:700px){
  .cap-kpis .kpi{width:100%;border-right:0;border-bottom:1px solid var(--border)}
  .cap-kpis .kpi:last-child{border-bottom:0}
}
/* TRES clases a propósito: la regla de base `.kpi .k-num` tiene dos y está más abajo en el
   archivo, así que con dos empatábamos y ganaba ella por orden. */
.cap-kpis .kpi .k-num{order:1;font-size:18px;line-height:1.2;margin-top:0;letter-spacing:0;white-space:nowrap}
/* En minúscula y en gris: el rótulo acompaña al número, no compite con él. En versalitas y negrita
   pesaba más que la cifra, que es justo al revés de lo que uno viene a leer. */
.cap-kpis .kpi .k-lbl{order:2;font-size:11.5px;letter-spacing:0;text-transform:none;
  font-weight:var(--fw-normal);color:var(--text-faint);white-space:nowrap}
.cap-kpis .kpi .k-sub{order:3;flex:0 1 auto;font-size:11.5px;color:var(--text-faint);margin-top:0;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}
.cap-kpis .kpi .k-num small{font-size:12px;margin-left:4px}
.cap-kpis .kpi .k-sub:not(:empty)::before{content:'· '}
/* En pantalla angosta la aclaración es lo primero que sobra: el número y su rótulo no. */
@media(max-width:1100px){ .cap-kpis .k-sub{display:none} }
/* Mismo aspecto que `.sup-tabseg`: era el otro estilo de filtro que quedaba en el sistema. */
/* El filtro comparte renglon con las solapas para no gastar una linea entera, pero NO es una solapa:
   se separa con una linea vertical y un poco de aire, y lleva su rotulo. Sin eso se leia como una
   cuarta solapa al lado de «Por zona». */
/* EL FILTRO, EN GENERAL: botones chicos con borde, el mismo dibujo que los de la barra del título.
   Sin caja alrededor — cada botón se defiende solo, que es como los dibuja la maqueta. */
.cap-filter{display:inline-flex;align-items:center;gap:6px;border:0;border-radius:0;overflow:visible;
  width:max-content;max-width:100%;margin:0 0 0 18px;vertical-align:middle;background:transparent}
.cap-filter button{font:inherit;font-size:12px;font-weight:var(--fw-normal);line-height:1.5;
  padding:4px 11px;min-height:0;height:28px;color:var(--text);background:var(--surface);
  border:1px solid var(--border-strong);border-radius:var(--radius-sm);cursor:pointer;white-space:nowrap}
.cap-filter button:hover{background:var(--surface-2)}
.cap-filter button.on{background:var(--selected);color:var(--text);border-color:var(--accent-ink);
  font-weight:var(--fw-semi)}

/* EN LA BARRA DE CAPACIDAD va como las solapas —subrayado y sin caja—, porque comparte renglón con
   ellas y son dos cosas que se tocan igual. En las demás pantallas no hay solapas al lado y un
   subrayado suelto en el medio del cuerpo no se lee como un control. */
.cap-barra > .cap-filter{gap:0;margin:0 0 0 auto;align-items:stretch}
/* El rótulo va SÓLO acá: es lo único que distingue los dos grupos de la fila —el de la izquierda
   cambia de pantalla, éste filtra la que ya estás viendo—. En las otras pantallas `.cap-filter` no
   comparte renglón con nada, y varias traen su propio rótulo adentro. */
.cap-barra > .cap-filter::before{content:"Mostrar";display:flex;align-items:center;padding:0 10px 0 0;
  font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--text-faint);white-space:nowrap}
.cap-barra > .cap-filter button{font-size:12.5px;padding:8px 16px;height:auto;color:var(--text-dim);
  background:transparent;border:0;border-bottom:2px solid transparent;border-radius:0}
.cap-barra > .cap-filter button+button{margin-left:2px}
.cap-barra > .cap-filter button:hover{background:transparent;color:var(--text)}
.cap-barra > .cap-filter button.on{background:transparent;color:var(--text);font-weight:var(--fw-semi);
  border-bottom-color:var(--accent-ink)}
/* El período de Registro de soporte va en la barra del título, al lado de los botones de acción:
   mismo dibujo que ellos y sin caja alrededor. */
.sop-per{margin:0 10px 0 0}
/* Alguno lleva un rótulo adentro del grupo («Caídos hace:»); sin esto quedaba pegado al borde. */
.cap-filter>span{display:flex;align-items:center;padding:0 11px;font-size:12px;color:var(--text-dim);
  background:var(--surface-2);border-right:1px solid var(--border)}
@media(max-width:760px){
  .cap-filter{overflow-x:auto;overflow-y:hidden;flex-wrap:nowrap;scrollbar-width:none}
  .cap-filter::-webkit-scrollbar{display:none}
  .cap-filter>button,.cap-filter>span{flex:0 0 auto}
}
.cap-oltcard{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:11px 16px 6px;margin-bottom:12px}
.cap-oltcard-h{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-bottom:2px}
.cap-oltcard-h b{font-size:13.5px}
.cap-oltcard-sum{margin-left:auto;font-size:12.5px;color:var(--text-faint);font-variant-numeric:tabular-nums}
.cap-legend{display:inline-flex;gap:18px;flex-wrap:wrap;align-items:center;font-size:12px;color:var(--text-dim);margin:2px 0 12px;padding:8px 14px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius)}
.cap-legend span{display:inline-flex;align-items:center;gap:7px}
.cap-legend i{width:10px;height:10px;border-radius:var(--radius-circ);display:inline-block;flex:0 0 auto}
/* Salud de señal */
.sig-list .occ-row{grid-template-columns:minmax(0,1.1fr) minmax(0,1.1fr) 132px}
.sig-l1 small{color:var(--text-faint);font-weight:var(--fw-normal);font-size:12px}
.sig-dist{display:flex;height:8px;border-radius:var(--radius-sm);overflow:hidden;background:var(--surface-3,var(--surface-2))}
.sig-dist i{height:100%}
.sig-dist i.ok{background:var(--green)} .sig-dist i.warn{background:var(--amber)} .sig-dist i.bad{background:var(--red)}
.sig-counts{display:inline-flex;gap:9px;align-items:center;justify-content:flex-end;font-variant-numeric:tabular-nums;font-weight:var(--fw-bold);font-size:12.5px}
.sig-badv{color:var(--red)}
/* Online/Offline por OLT + estado de los offline */
.off-bar{display:flex;height:9px;border-radius:var(--radius-sm);overflow:hidden;background:var(--surface-3,var(--surface-2));margin:8px 0}
.off-bar i{height:100%}
.off-bar i.ok{background:var(--green)} .off-bar i.bad{background:var(--red)} .off-bar i.warn{background:var(--amber)} .off-bar i.mut{background:color-mix(in srgb,var(--text-faint) 55%,transparent)}
.off-h{cursor:pointer;display:flex;align-items:center;gap:8px}
.off-sum{margin-left:auto;font-size:12.5px;color:var(--text-dim);font-variant-numeric:tabular-nums}
.off-badv{color:var(--amber)}
.off-chev{color:var(--text-faint);font-size:12px;width:14px;text-align:center}
.off-chips{display:flex;flex-wrap:wrap;gap:6px}
.off-chip{font-size:12px;font-weight:var(--fw-bold);border-radius:var(--radius-sm);padding:1px 8px}
.off-chip.bad{background:color-mix(in srgb,var(--red) 16%,transparent);color:var(--red)}
.off-chip.warn{background:color-mix(in srgb,var(--amber) 15%,transparent);color:var(--amber)}
.off-chip.mut{background:color-mix(in srgb,var(--text-faint) 16%,transparent);color:var(--text-dim)}
.off-detail{margin-top:9px;border-top:1px solid var(--border);max-height:360px;overflow:auto}
.off-ont{display:flex;align-items:center;gap:10px;padding:6px 2px;border-bottom:1px solid var(--border);font-size:12.5px}
.off-ont:last-child{border-bottom:0}
.off-ont .db-serial{flex:0 0 auto;min-width:118px}
.off-cli{color:var(--accent-ink);text-decoration:none;font-weight:var(--fw-semi);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1 1 auto;min-width:0}
.off-cli:hover{text-decoration:underline}
.off-nocli{color:var(--text-faint);flex:1 1 auto;min-width:0}
/* Lista consolidada de habilitados sin señal */
.off-vseg{margin-bottom:12px}
.ehl-list{border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}
.ehl-row{display:grid;grid-template-columns:minmax(140px,1.7fr) 92px minmax(88px,0.9fr) minmax(100px,1fr) minmax(140px,1.4fr);align-items:center;gap:12px;padding:8px 12px;border-top:1px solid var(--border)} .ehl-row:first-child{border-top:none}
.ehl-row.ehl-head{background:var(--surface-2);color:var(--text-dim);font-size:11px;text-transform:uppercase;letter-spacing:.03em;font-weight:var(--fw-bold);padding:6px 12px}
.ehl-cli a{color:var(--accent-ink);text-decoration:none;font-weight:var(--fw-bold)} .ehl-cli a:hover{text-decoration:underline} .ehl-cli small{display:block;color:var(--text-faint);font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ehl-loc{font-size:12px;color:var(--text-dim)} .ehl-sn{font-size:12px;color:var(--text-dim)}
.ehl-since{font-size:12px;color:var(--text-dim);font-variant-numeric:tabular-nums;display:flex;flex-direction:column;gap:2px;align-items:flex-start}
.ehl-cause{font-size:10px;font-weight:var(--fw-bold);padding:0 5px;border-radius:var(--radius-sm);background:var(--surface-2);color:var(--text-faint);white-space:nowrap}
.ehl-cause.pow{background:color-mix(in srgb,var(--amber) 18%,transparent);color:var(--amber,#f5a623)}
.ehl-cause.fib{background:color-mix(in srgb,var(--signal) 18%,transparent);color:var(--signal,#e5484d)}
.ehl-caja{font-size:12px;font-weight:var(--fw-semi);color:var(--text)} .ehl-clus{font-size:11px;font-weight:var(--fw-black);color:var(--amber,#f5a623);background:color-mix(in srgb,var(--amber) 16%,transparent);padding:0 5px;border-radius:var(--radius-sm)}
.ehl-tkb{display:inline-block;font-size:12px;font-weight:var(--fw-bold);padding:3px 10px;border-radius:var(--radius-sm);text-decoration:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.ehl-tkb.ok{background:color-mix(in srgb,var(--green) 14%,transparent);color:var(--green)}
.ehl-tkb.new{background:color-mix(in srgb,var(--signal) 14%,transparent);color:var(--signal);border:1px solid color-mix(in srgb,var(--signal) 45%,var(--border))} .ehl-tkb.new:hover{background:color-mix(in srgb,var(--signal) 24%,transparent)}
.ehl-tel{display:block;color:var(--green);text-decoration:none;font-size:11px;font-weight:var(--fw-semi);margin-top:1px} .ehl-tel:hover{text-decoration:underline}
.off-flbl{font-size:12px;color:var(--text-faint);align-self:center;margin-right:2px}
/* Agrupado por caja */
.ehc-list{display:flex;flex-direction:column;gap:7px}
.ehc-caja{border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;background:var(--surface)}
.ehc-caja.ehc-mult{border-color:color-mix(in srgb,var(--amber) 45%,var(--border))}
.ehc-h{display:flex;align-items:center;gap:10px;padding:9px 13px;cursor:pointer} .ehc-h:hover{background:color-mix(in srgb,var(--accent-ink) 6%,transparent)}
.ehc-chev{color:var(--text-faint);width:12px} .ehc-h b{font-size:13.5px}
.ehc-cnt{font-size:12px;font-weight:var(--fw-bold);color:var(--text-dim);background:var(--surface-2);padding:1px 9px;border-radius:var(--radius-sm)} .ehc-cnt.mult{background:color-mix(in srgb,var(--amber) 18%,transparent);color:var(--amber,#f5a623)}
.ehc-olt{font-size:12px;color:var(--text-faint)}
.ehc-flag{margin-left:auto;font-size:11px;font-weight:var(--fw-bold);color:var(--amber,#f5a623)}
.ehc-det{border-top:1px solid var(--border);background:var(--surface-2)}
.ehc-row{grid-template-columns:minmax(150px,1.8fr) 92px minmax(110px,1fr) minmax(140px,1.4fr) !important;padding-left:22px}
@media(max-width:760px){ .ehl-row{grid-template-columns:1.5fr 1.3fr;gap:8px} .ehl-row .ehl-since,.ehl-row .ehl-caja,.ehl-row .ehl-loc,.ehl-row.ehl-head{display:none} .ehc-row{grid-template-columns:1.5fr 1.3fr !important} .ehc-flag{display:none} }
.off-st{margin-left:auto;flex:0 0 auto;font-weight:var(--fw-bold);font-size:11px;border-radius:var(--radius-sm);padding:1px 7px;white-space:nowrap}
.off-st.bad{background:color-mix(in srgb,var(--red) 16%,transparent);color:var(--red)}
.off-st.warn{background:color-mix(in srgb,var(--amber) 15%,transparent);color:var(--amber)}
.off-st.mut{background:color-mix(in srgb,var(--text-faint) 15%,transparent);color:var(--text-dim)}
.off-ont{flex-wrap:wrap}
.off-fecha{flex:0 0 auto;font-size:11px;color:var(--text-dim);white-space:nowrap;font-variant-numeric:tabular-nums}
.off-fecha-l{color:var(--text-faint);font-style:italic}
/* Estadísticas de soporte */
#supView{flex:1;display:none;min-height:0}
#supWrap{flex:1;min-width:0;min-height:0;display:flex}
.sup-tools{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-left:auto;justify-content:flex-end}
.sup-dates{display:flex;align-items:center;gap:6px}
.sup-dates input{padding:5px 8px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2);color:var(--text);font-size:12.5px}
.sup-upd{font-size:12px;color:var(--text-faint);margin-bottom:10px}
.sup-clr{background:none;border:0;color:var(--accent-ink);cursor:pointer;font-size:12px;padding:0}
.sup-cols{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:12px}
.sup-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:12px 14px;min-width:0}
.sup-card h4{margin:0 0 10px;font-size:13.5px} .sup-card h4 small{color:var(--text-faint);font-weight:var(--fw-normal);font-size:12px}
/* Encabezado de card con filtro de fecha propio */
.g-cardhead{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}
.g-cardhead h4{margin:0}
.g-cardper{flex:0 0 auto;background:var(--surface-2);color:var(--text-dim);border:1px solid var(--border);border-radius:var(--radius-sm);padding:3px 6px;font-size:12px;cursor:pointer;max-width:135px}
.g-cardper:hover{border-color:var(--border-strong)}
.g-cardbody{margin-top:9px;transition:opacity .15s}
/* Coordinación: tabla de técnicos con barra por tipo + calendario */
.ci{display:inline-block;width:11px;height:11px;border-radius:var(--radius-sm);vertical-align:middle;margin:0 3px 0 10px}.ci:first-child{margin-left:0}
.s-inst{background:#2f6fed}.s-sop{background:#f5a623}.s-ret{background:#8b5cf6}.s-rec{background:#e5484d}
.cal-work{background:#2ecc71}.cal-off{background:#e5484d}.cal-wknd{background:#9aa5b1}.cal-fut{background:transparent;border:1px dashed var(--border-strong)}
.coord-top{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px;margin:2px 0 8px}
.coord-stats{display:flex;gap:16px;font-size:12px;color:var(--text-dim)} .coord-stats b{font-size:14px;color:var(--text)}
.coord-per{display:inline-flex;align-items:center;gap:5px;flex-wrap:wrap} .coord-per select,.coord-per input[type=date]{padding:3px 6px;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface-2);color:var(--text);font-size:12px} .coord-per select:focus,.coord-per input:focus{outline:none;border-color:var(--accent-ink)} .coord-per span{color:var(--text-dim)}
.coord-filt{color:var(--amber,#f5a623);font-size:11px}
.ctec-pend{margin-left:5px;font-size:11px;font-weight:var(--fw-bold);color:var(--amber,#f5a623)}
.ctec-head,.ctec-row .ctec-total{white-space:nowrap}
.ctec-legend{font-size:11px;color:var(--text-dim);margin:0 0 8px}
.ctec-list{border:1px solid var(--border);border-radius:var(--radius);overflow:auto;max-height:460px}
.ctec-head,.ctec-row{display:grid;grid-template-columns:minmax(78px,1.2fr) 62px 1.4fr 34px;align-items:center;gap:8px;padding:5px 9px}
.ctec-head{position:sticky;top:0;z-index:1;background:var(--surface-2);color:var(--text-dim);font-size:10px;text-transform:uppercase;letter-spacing:.02em;font-weight:var(--fw-bold)}
.ctec-head div:last-child,.ctec-row .ctec-total{text-align:right}
.ctec-row{border-top:1px solid var(--border);cursor:pointer;font-size:12px}
.ctec-row:hover{background:color-mix(in srgb,var(--accent-ink) 6%,transparent)}
.ctec-row.on{background:color-mix(in srgb,var(--accent-ink) 13%,transparent)}
.ctec-name{font-weight:var(--fw-semi);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ctec-media b{font-size:13.5px} .ctec-media small{color:var(--text-faint);margin-left:4px;font-size:10px}
.ctec-bar{height:14px;background:var(--surface-2);border-radius:var(--radius-sm);overflow:hidden} .cbar-inner{display:flex;height:100%} .cbar-seg{display:block;height:100%}
.ctec-total{font-weight:var(--fw-bold);font-variant-numeric:tabular-nums}
.cal-head{display:flex;align-items:center;gap:6px;margin-bottom:9px;flex-wrap:wrap} .cal-head b{font-family:'IBM Plex Sans';font-size:13.5px} .cal-head .g-sp{flex:1}
.cal-nav{background:var(--surface-2);border:1px solid var(--border);color:var(--text);width:24px;height:24px;border-radius:var(--radius-sm);cursor:pointer;font-size:13.5px}
.cal-mes{font-weight:var(--fw-bold);min-width:66px;text-align:center;font-size:12.5px} .cal-sum{color:var(--text-dim);font-size:12px}
.cal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:4px}
.cal-dow{text-align:center;font-size:10px;color:var(--text-faint);font-weight:var(--fw-bold);padding-bottom:1px}
.cal-cell{min-height:38px;border-radius:var(--radius-sm);padding:2px 5px;position:relative} .cal-cell.empty{background:transparent}
.cal-cell.cal-work{background:rgba(46,204,113,.16);border:1px solid rgba(46,204,113,.4)}
.cal-cell.cal-off{background:rgba(229,72,77,.2);border:1px solid rgba(229,72,77,.45)}
.cal-cell.cal-wknd{background:color-mix(in srgb,var(--text) 6%,transparent)}
.cal-cell.cal-fut{border:1px dashed var(--border)}
.cal-d{font-size:11px;color:var(--text-dim)} .cal-n{position:absolute;bottom:2px;right:5px;font-weight:var(--fw-black);font-size:12.5px;color:var(--green)}
.cal-leg{margin-top:9px;font-size:11px;color:var(--text-dim)}
.cal-stats{margin-top:11px;border-top:1px solid var(--border);padding-top:9px}
.cal-stats-h{font-size:11px;text-transform:uppercase;letter-spacing:.03em;color:var(--text-dim);font-weight:var(--fw-bold);margin-bottom:7px}
.cal-stats-g{display:grid;grid-template-columns:repeat(auto-fit,minmax(84px,1fr));gap:7px}
.cst{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:6px 9px;display:flex;flex-direction:column;gap:1px;border-left:3px solid var(--border)}
.cst span{font-size:11px;color:var(--text-dim)} .cst b{font-size:16px;font-variant-numeric:tabular-nums}
.cst.cst-tot{border-left-color:var(--text-dim)}
.cst.s-inst{border-left-color:#2f6fed} .cst.s-sop{border-left-color:#f5a623} .cst.s-ret{border-left-color:#8b5cf6} .cst.s-rec{border-left-color:#e5484d}
/* Capacidad por técnico + planificador */
.coord-subseg{margin-bottom:10px}
.cap-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap} .cap-head h4{margin:0} .cap-actions{margin-left:auto;display:flex;gap:6px}
.cap-save:not([disabled]){background:var(--accent-ink);color:#fff;border-color:transparent}
.cap-list{border:1px solid var(--border);border-radius:var(--radius);overflow:auto;max-height:520px;margin-top:8px}
.capr{display:grid;grid-template-columns:minmax(90px,1.5fr) 52px 52px 52px 36px 24px;align-items:center;gap:8px;padding:4px 9px;border-top:1px solid var(--border)}
.capr:first-child{border-top:none}
.capr.caph{position:sticky;top:0;z-index:1;background:var(--surface-2);color:var(--text-dim);font-size:10px;text-transform:uppercase;letter-spacing:.02em;font-weight:var(--fw-bold);text-align:center}
.capr.caph div:first-child{text-align:left}
.capr-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12.5px}
.capr-in{text-align:center} .capr-in input{width:46px;text-align:center;padding:3px 2px;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface-2);color:var(--text);font-size:12.5px;font-variant-numeric:tabular-nums}
.capr-in input:focus{outline:none;border-color:var(--accent-ink)}
.capr-tot{text-align:right;font-variant-numeric:tabular-nums;color:var(--text-dim)}
.capr-x{border:none;background:transparent;color:var(--text-dim);font-size:15px;line-height:1;cursor:pointer;padding:2px;border-radius:var(--radius-sm);opacity:.5} .capr-x:hover{opacity:1;color:var(--red);background:color-mix(in srgb,#e5484d 14%,transparent)}
.cap-add{display:flex;gap:6px;margin-top:8px} .cap-add input{flex:1;padding:5px 8px;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface-2);color:var(--text);font-size:12.5px} .cap-add input:focus{outline:none;border-color:var(--accent-ink)}
.cap-loadcard{margin-top:12px}
.capl-list{border:1px solid var(--border);border-radius:var(--radius);overflow:auto}
.capl-row{display:grid;grid-template-columns:minmax(120px,1.6fr) 64px 78px minmax(150px,2fr) 118px;align-items:center;gap:10px;padding:5px 11px;border-top:1px solid var(--border)}
.capl-row:first-child{border-top:none}
.capl-row.caplh{position:sticky;top:0;z-index:1;background:var(--surface-2);color:var(--text-dim);font-size:10px;text-transform:uppercase;letter-spacing:.02em;font-weight:var(--fw-bold)}
.capl-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:12.5px}
.capl-cap{font-variant-numeric:tabular-nums;color:var(--text-dim)}
.capl-med{font-variant-numeric:tabular-nums;font-weight:var(--fw-bold)} .capl-med small{color:var(--text-dim);font-weight:var(--fw-normal);margin-left:4px}
.capl-bar{display:flex;align-items:center;gap:8px} .capl-bar .capl-bt{flex:1;height:9px;border-radius:var(--radius-sm);background:var(--surface-3,var(--surface-2));overflow:hidden} .capl-bt i{display:block;height:100%;border-radius:var(--radius-sm)} .capl-bar b{font-variant-numeric:tabular-nums;min-width:42px;text-align:right}
.capl-pill{display:inline-block;font-size:11px;font-weight:var(--fw-bold);padding:1px 8px;border-radius:var(--radius-sm);border:1px solid}
.capl-seg{display:inline-flex}
.cap-week{margin:8px 0;font-size:12.5px;color:var(--text-dim)} .cap-week b{color:var(--text)}
.cap-planbox{border:1px solid var(--border);border-radius:var(--radius);padding:10px 12px;margin-top:6px}
.cap-planh{font-weight:var(--fw-bold);font-size:12.5px;margin-bottom:8px}
.cap-planrow{display:grid;grid-template-columns:1fr 78px 84px;align-items:center;gap:8px;margin-bottom:6px}
.cap-planrow label{font-size:12px;color:var(--text-dim)}
.cap-planrow input{padding:4px 6px;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--surface-2);color:var(--text);font-variant-numeric:tabular-nums}
.cap-plandays{text-align:right;font-weight:var(--fw-bold);font-variant-numeric:tabular-nums;color:var(--accent-ink)}
.cap-plannote{display:block;margin-top:6px;font-size:11px;color:var(--text-dim);line-height:1.35}
.sup-bars{display:flex;flex-direction:column;gap:5px;max-height:420px;overflow:auto}
.sup-bar{display:grid;grid-template-columns:minmax(90px,40%) 1fr 46px;align-items:center;gap:8px;font-size:12.5px;padding:1px 2px}
.sup-bar-l{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--text-dim)}
.sup-bar-t{height:9px;border-radius:var(--radius-sm);background:var(--surface-3,var(--surface-2));overflow:hidden}
.sup-bar-t i{display:block;height:100%;border-radius:var(--radius-sm);background:var(--accent-ink)}
.sup-bar-t i.ok{background:var(--green)} .sup-bar-t i.bad{background:var(--signal)} .sup-bar-t i.warn{background:var(--amber)}
.sup-bar b{text-align:right;font-variant-numeric:tabular-nums;font-weight:var(--fw-bold)}
.sup-bar.clk{cursor:pointer;border-radius:var(--radius-sm)} .sup-bar.clk:hover{background:color-mix(in srgb,var(--accent-ink) 9%,transparent)}
.sup-months{display:flex;align-items:flex-end;gap:6px;height:160px;overflow-x:auto;padding-top:4px}
.sup-mo{display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:3px;flex:1 0 32px;height:100%}
.sup-mo b{font-size:11px;font-variant-numeric:tabular-nums;color:var(--text-dim)}
.sup-mo-bar{width:68%;min-height:2px;background:var(--accent-ink);border-radius:var(--radius-sm) var(--radius-sm) 0 0}
.sup-mo-l{font-size:11px;color:var(--text-faint)}
.sup-tk-card{margin-top:12px}
.sup-tk-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 10px}
.sup-tk-head h4{margin:0;font-size:13.5px} .sup-tk-head h4 small{color:var(--text-faint);font-weight:var(--fw-normal);font-size:12px}
.sup-tk-find{margin-left:auto;padding:5px 9px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2);color:var(--text);font-size:12.5px;min-width:180px}
.sup-tk-wrap{overflow:auto;max-height:540px;border:1px solid var(--border);border-radius:var(--radius)}
/* LA TABLA LLEGA AL BORDE DE SU TARJETA. Vive dentro de `.sup-card`, que tiene 14 px de relleno a
   cada lado: medido, eso le dejaba entre 42 y 52 px de aire alrededor en 21 pantallas, mientras
   Capacidad la tiene pegada. Se sale del relleno con un margen negativo y no repartiendo el relleno
   hijo por hijo: así la cabecera y las notas conservan el suyo, y un bloque que alguien agregue
   mañana no queda pegado al borde sin que se entienda por qué.
   Sin bordes laterales: pegada al borde de la tarjeta, el suyo quedaría encima del de ella y se
   verían dos líneas juntas. Queda el de arriba y el de abajo. Es lo mismo que hace `.cap-tabla-w`. */
.sup-tk-card > .sup-tk-wrap{margin-left:-14px;margin-right:-14px;
  border-left:0;border-right:0;border-radius:0}
/* La tendencia va pegada al numero que compara, no en una franja aparte. Acá BAJAR es lo bueno. */
.ss-tend{display:block;margin-top:2px;font-size:11px;font-weight:var(--fw-bold)}
.ss-tend.baja{color:var(--green)}
.ss-tend.sube{color:var(--red)}
.ss-tend.igual{color:var(--text-faint);font-weight:var(--fw-semi)}
/* «Cómo viene la red»: una sola linea debajo de los contadores. Los contadores son la foto de hoy;
   esto dice si va mejorando, que es lo unico que contesta si sirve lo que se hace. */
.seg-red{display:flex;align-items:center;gap:16px;flex-wrap:wrap;margin:-2px 0 12px;padding:9px 13px;
  background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);font-size:12px}
/* Sin versales: es el rótulo de la tira de seguridad y aparece en las 7 pantallas del grupo.
   Quedó afuera de la migración porque es una clase propia y no una de las comunes. */
.seg-red-t{font-size:11px;text-transform:none;letter-spacing:0;color:var(--text-faint);font-weight:var(--fw-semi)}
.seg-red-i{color:var(--text-dim);white-space:nowrap}
.seg-red-i b{color:var(--text);font-family:'IBM Plex Mono';font-size:13.5px;margin-right:3px}
.seg-red-d{margin-left:auto;font-size:11px;color:var(--text-faint)}
/* Bajar es mejorar: verde. */
.seg-ev{font-weight:var(--fw-bold);margin-left:4px}
.seg-ev.baja{color:var(--green)}
.seg-ev.sube{color:var(--red)}
.seg-ev.igual{color:var(--text-faint)}
@media(max-width:900px){ .seg-red-d{margin-left:0;flex:1 1 100%} }
/* ===== REGISTRO DE SOPORTE: EL FILTRO, ADENTRO DEL ENCABEZADO DE SU COLUMNA =====
   El desplegable vive en el `<th>`, debajo del rótulo, y no arriba de la tabla. Se ve chico y gris
   hasta que se usa: cuando hay un filtro puesto, el encabezado entero se marca con el color de
   acento y una barrita abajo. Eso resuelve el problema clásico de los filtros escondidos —abrir una
   pantalla, ver poca cosa y no darse cuenta de que hay algo filtrado— sin ocupar lugar. */
.sop-th{vertical-align:top}
.sop-th .sop-th-l{display:block}
/* EL FONDO VA EXPLÍCITO, Y EL DE LAS OPCIONES TAMBIÉN. Esto arrancó con `background:transparent`
   para que el desplegable se viera liviano dentro del encabezado, y era un error: la lista que se
   abre al tocarlo NO hereda el fondo del select —la dibuja el sistema operativo, en blanco— pero SÍ
   hereda el color del texto. Resultado: gris claro sobre blanco, ilegible justo cuando hay que
   elegir. Todos los desplegables del sistema tienen fondo opaco propio y por eso no les pasa.
   El texto pasa de `--text-faint` a `--text-dim`: a 11 px, que es de los cuerpos más chicos de la
   pantalla, el tenue queda al filo. Con `--text-dim` da 6,8 sobre el fondo del encabezado en oscuro
   y 6,1 en claro. */
/* El filtro del encabezado es un BOTÓN que abre un menú de marcar varios, no un desplegable: con un
   desplegable había que elegir entre ver «Pendiente» o ver «No accesible», y lo que uno quiere es
   ver los dos juntos. El botón dice qué hay elegido sin abrirlo. */
.sop-thf{display:flex;align-items:center;gap:4px;width:100%;margin-top:3px;padding:2px 5px;font-size:11px;
  background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-sm);
  color:var(--text-dim);font-family:inherit;font-weight:var(--fw-medium);cursor:pointer;text-transform:none;letter-spacing:0;
  text-align:left}
.sop-thf-t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sop-thf-c{font-style:normal;font-size:9px;flex:0 0 auto;opacity:.75}
.sop-thf:hover{border-color:var(--border-strong);color:var(--text)}
.sop-thf:focus-visible{outline:none;border-color:var(--accent-ink);color:var(--text)}
.sop-th.on{box-shadow:inset 0 -2px 0 var(--accent-ink)}
.sop-th.on .sop-th-l{color:var(--accent-ink)}
.sop-th.on .sop-thf{color:var(--accent-ink);border-color:var(--accent-ink);font-weight:var(--fw-bold)}
/* El menú: por encima de todo y con posición de pantalla, porque la tabla lo recortaría. */
.sop-fmenu{position:fixed;z-index:2200;background:var(--surface);border:1px solid var(--border-strong);
  border-radius:var(--radius-lg);box-shadow:0 12px 34px -10px rgba(0,0,0,.55);overflow:hidden}
.sop-fm-l{max-height:min(52vh,340px);overflow:auto;padding:5px}
.sop-fm-i{display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:5px;
  font-size:12px;color:var(--text);cursor:pointer}
.sop-fm-i:hover{background:var(--surface-2)}
.sop-fm-i input{flex:0 0 auto;margin:0;cursor:pointer}
.sop-fm-i span{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sop-fm-i b{flex:0 0 auto;font-variant-numeric:tabular-nums;color:var(--text-faint);font-weight:var(--fw-semi);font-size:11px}
.sop-fm-vacio{padding:12px;font-size:12px;color:var(--text-faint)}
.sop-fm-pie{border-top:1px solid var(--border);padding:6px 8px}
/* ===== LA FILA, TEÑIDA SEGÚN EL ESTADO =====
   Al 7% del color y con una barrita a la izquierda. Suave a propósito: son doce columnas y un fondo
   fuerte taparía el texto; alcanza para barrer la lista con la vista. La barrita es lo que de verdad
   se ve, y es el recurso que ya usa el resto del sistema para marcar filas.
   Van con `!important` sobre el `td` porque la tabla tiene filas alternadas —un gris al 6%— que si no
   le gana a la mitad de las filas y el color aparecería sólo en las impares. */
.sup-tk tbody tr.sop-r-ok  > td{background:color-mix(in srgb,var(--green) 7%,transparent)!important}
.sup-tk tbody tr.sop-r-mal > td{background:color-mix(in srgb,var(--red) 7%,transparent)!important}
.sup-tk tbody tr.sop-r-esp > td{background:color-mix(in srgb,var(--amber) 7%,transparent)!important}
.sup-tk tbody tr.sop-r-ok  > td:first-child{box-shadow:inset 3px 0 0 var(--green)}
.sup-tk tbody tr.sop-r-mal > td:first-child{box-shadow:inset 3px 0 0 var(--red)}
.sup-tk tbody tr.sop-r-esp > td:first-child{box-shadow:inset 3px 0 0 var(--amber)}
.sup-tk tbody tr.sop-r-ok:hover  > td,
.sup-tk tbody tr.sop-r-mal:hover > td,
.sup-tk tbody tr.sop-r-esp:hover > td{filter:brightness(1.12)}
/* La observación conserva los renglones que se escribieron: la gente anota una línea por contacto y
   todo seguido se perdía la cronología. Se le da un ancho de trabajo para que no estire la tabla. */
.sop-obs{white-space:pre-wrap;min-width:200px;max-width:340px}
/* ===== REGISTRO DE SOPORTE: UN BLOQUE POR MES, PLEGABLE =====
   El encabezado del mes ES el control, así que se comporta como tal: cursor de mano, cambia al pasar
   por encima y tiene foco visible para el teclado. La flechita va antes del título y no al final,
   porque es lo primero que se mira para saber si hay algo adentro. Cuando el mes está cerrado el
   encabezado no lleva margen abajo: sin tabla, ese margen dejaba un hueco raro entre bloques. */
.sop-mes-h{cursor:pointer;display:flex;align-items:center;gap:9px;transition:color .12s ease}
.sop-mes-h:hover{color:var(--accent-ink)}
.sop-mes-h:focus-visible{outline:2px solid var(--accent-ink);outline-offset:3px;border-radius:var(--radius-sm)}
.sop-mes-ch{color:var(--text-faint);font-size:11px;width:11px;flex:0 0 auto}
.sop-mes-h:hover .sop-mes-ch{color:var(--accent-ink)}
.sop-mes:not(.on) .sup-tk-head{margin-bottom:0}
/* El gráfico va pegado a la tira, sin caja propia: es la misma pieza, no una sección aparte. */
.seg-red-g{margin:-8px 0 14px}
/* La tira abre y cierra el gráfico, así que tiene que verse tocable: cambia el borde al pasar por
   encima, como cualquier otra cosa del sistema que responde al clic. El rótulo de la derecha dice
   qué va a pasar —«ver» o «ocultar»—, que es más claro que una flecha sola. */
.seg-red-clic{cursor:pointer;transition:border-color .12s ease}
.seg-red-clic:hover{border-color:var(--border-strong)}
.seg-red-clic:focus-visible{outline:2px solid var(--accent-ink);outline-offset:2px}
.seg-red-tog{margin-left:12px;font-size:11px;font-weight:var(--fw-bold);color:var(--accent-ink);white-space:nowrap}
/* «Por qué está acá»: el hecho en una pastilla corta. El texto entero, en el globo de ayuda. */
.c-porque{max-width:300px}
.seg-mot{display:block;font-size:12px;line-height:1.35;color:var(--text-dim);
  background:var(--surface-3);border-radius:var(--radius-sm);padding:2px 7px;margin-bottom:3px;cursor:help;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* «+2 motivos»: dice que hay mas sin ocupar renglones. El detalle esta en la evidencia. */
.seg-mas{display:inline-block;font-size:11px;font-weight:var(--fw-bold);color:var(--text-faint);
  border:1px solid var(--border);border-radius:var(--radius);padding:0 7px;margin-right:6px;cursor:help}
.c-porque a{display:inline-block;font-size:12px;margin-top:2px}
table.sup-tk{width:100%;border-collapse:collapse;font-size:12.5px}
/* La cabecera, igual que la de Capacidad: mismo fondo, mismo relleno y una línea de 1 px que la
   separa de los datos. */
.sup-tk th{position:sticky;top:0;background:var(--surface-3);color:var(--text-dim);text-align:left;font-weight:var(--fw-semi);padding:6px 10px;border-bottom:1px solid var(--border-strong);white-space:nowrap;z-index:1}
/* La línea entre filas, la de Capacidad: --border se perdía contra el fondo en las tablas largas. */
.sup-tk td{padding:7px 10px;border-bottom:1px solid var(--border-strong);vertical-align:top}
.sup-tk tbody tr:hover td{background:color-mix(in srgb,var(--accent-ink) 6%,transparent)}
.sup-tk .c-id{font-variant-numeric:tabular-nums;color:var(--text-faint);white-space:nowrap}
.sup-tk .c-dt{white-space:nowrap;font-variant-numeric:tabular-nums;color:var(--text-dim)}
.sup-tk .c-cli a{color:var(--accent-ink);text-decoration:none} .sup-tk .c-cli a:hover{text-decoration:underline}
.sup-tk .c-cli small{display:block;color:var(--text-faint);font-size:11px}
.sup-tk-empty{padding:14px;color:var(--text-faint);font-size:12.5px;text-align:center}
/* Modificador: le da a una tabla `.sup-tk` los tres rasgos que la diferenciaban de la grilla densa
   —cebra, encabezado en mayusculas chiquitas y separadores de columna— sin tocar las otras 34. */
/* SIN MAYÚSCULAS. El encabezado se lee como está escrito —«Cómo viene», no «CÓMO VIENE»—, con el
   mismo peso 600 que en Capacidad y la misma línea de 1 px. Las mayúsculas forzadas y el espaciado
   entre letras eran lo que hacía que estas tablas se leyeran como de otro sistema.
   El borde vertical se queda: son tablas de hasta diez columnas angostas, donde la línea es lo que
   deja seguir la fila. */
.sup-tk.tk-grid th{font-size:11px;font-weight:var(--fw-semi);border-right:1px solid var(--border);border-bottom:1px solid var(--border-strong)}
.sup-tk.tk-grid td{border-right:1px solid var(--border)}
.sup-tk.tk-grid th:last-child,.sup-tk.tk-grid td:last-child{border-right:none}
.sup-tk.tk-grid tbody tr:nth-child(even) td{background:var(--zebra)}
.sup-tk.tk-grid tbody tr:hover td{background:color-mix(in srgb,var(--accent-ink) 6%,transparent)}
/* La cabecera que ordena, igual que en la grilla densa. */
.sup-tk.tk-grid th[data-flcol],.sup-tk.tk-grid th[data-offcol],
.sup-tk.tk-grid th[data-ehcol],.sup-tk.tk-grid th[data-eccol]{cursor:pointer;user-select:none}
/* Sin señal por caja: los clientes van dentro de la fila, uno debajo del otro. */
.ehc-tabla .ehc-clis{padding:4px 8px}
.ehc-tabla .ehc-uno{display:flex;align-items:center;gap:14px;flex-wrap:wrap;padding:4px 0}
.ehc-tabla .ehc-uno + .ehc-uno{border-top:1px dashed var(--border)}
.ehc-tabla .ehc-cj{white-space:nowrap}
.ehc-tabla .ehc-cj .ehc-flag{display:block;font-size:11px;color:var(--amber);margin-top:2px}
.ehc-tabla .ehc-cj .ehc-nota{display:block;font-size:11px;color:var(--text-faint);margin-top:2px;white-space:normal;max-width:150px}
.ehc-tabla .ehc-n{color:var(--amber);font-size:14px}
.ehc-tabla .ehc-olt{color:var(--text-faint);white-space:nowrap}
.ehc-tabla tbody tr.ehc-mult-row td:first-child{box-shadow:inset 3px 0 0 var(--amber)}
/* Online/Offline por OLT: el cero apagado para que los numeros que importan salten. */
.off-tabla .off-cero{color:var(--text-faint);font-weight:var(--fw-normal)}
.off-tabla .off-nom{white-space:nowrap;font-size:13.5px}
.off-tabla .off-nom .off-chev{margin-right:6px;color:var(--text-faint)}
.off-tabla tbody tr.off-fila{cursor:pointer}
.off-tabla tbody tr.off-fila.on td{background:color-mix(in srgb,var(--accent-ink) 10%,transparent)}
.off-tabla .off-ocu{min-width:150px}
.off-tabla .off-ocu small{display:block;color:var(--text-faint);font-size:11px;margin-top:3px}
.off-tabla tr.off-detrow td{padding:0;background:var(--surface)}
.sup-tk.tk-grid th[data-flcol]:hover{color:var(--text)}
/* Sin caja: el listado corre hasta abajo y scrollea la pagina, como el de «Consumo sin servicio».
   El tope de 540 px que trae `.sup-tk-wrap` tiene sentido en las tablas cortas que conviven con
   otras cosas en la misma pantalla; en una lista larga que ES la pantalla, sobra. */
.sup-tk-wrap:has(> .sup-tk.tk-largo){max-height:none;overflow:visible;overflow-x:auto}
/* El encabezado se agarra de la barra del panel, que es lo que queda fijo arriba. */
.sup-tk.tk-grid th{top:0;z-index:4}
/* Las que SI conservan su caja de 540 px siguen scrolleando adentro; el encabezado se agarra de
   esa caja, que es lo que ya hacia. */
.sup-resbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:16px 0 2px}
.sup-seg{display:inline-flex;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}
.sup-seg-b{background:var(--surface);color:var(--text-dim);border:0;padding:5px 12px;font-size:12.5px;cursor:pointer}
.sup-seg-b+.sup-seg-b{border-left:1px solid var(--border)}
.sup-seg-b.on{background:var(--accent-ink);color:#fff}
/* Pestaña Soporte / Crecimiento y zonas */
/* Sin margen abajo: la tira es la cabecera de lo que hay debajo, no un elemento suelto. Su borde
   inferior tiene que ser la línea que separa de la tabla —así quedó Capacidad—. Lo que necesite
   aire lo pone quien la usa, no la regla general. */
.sup-tabseg{display:inline-flex;background:transparent;border:0;border-bottom:1px solid var(--border-strong);border-radius:0;overflow:hidden;margin-bottom:0}
/* En el teléfono la tira de filtros no entra: se corta y los de la derecha no se pueden tocar
   (en «Ataques e infectados» quedaban 262 px afuera, tres filtros enteros). Se desliza de
   costado, como la tira de contadores del tablero, y sin barra a la vista. */
@media(max-width:760px){
  .sup-tabseg{overflow-x:auto;overflow-y:hidden;flex-wrap:nowrap;scrollbar-width:none;-webkit-overflow-scrolling:touch}
  .sup-tabseg::-webkit-scrollbar{display:none}
  .sup-tabseg>.sup-tab,.sup-tabseg>button{flex:0 0 auto}
}
.sup-tab{padding:8px 16px;font-size:12.5px;cursor:pointer;background:transparent;border:0;border-bottom:2px solid transparent;border-radius:0;color:var(--text-dim);font-weight:var(--fw-normal);transition:none}
.sup-tab+.sup-tab{margin-left:2px}
.sup-tab.on{background:transparent;color:var(--text);font-weight:var(--fw-semi);border-bottom-color:var(--accent-ink);box-shadow:none}
.sup-tabseg-bar{margin-bottom:0} .sup-tabseg-bar .sup-tab{padding:6px 13px;font-size:12.5px}
@media(max-width:920px){ .sup-tabseg-bar .sup-tab{padding:6px 10px;font-size:12px} }
.sup-geoseg{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:2px 0 10px}
.sup-geoseg small{color:var(--text-faint);font-size:12px}
/* Tendencia mensual: altas (verde) vs bajas (rojo) */
.sup-trend{display:flex;align-items:flex-end;gap:8px;height:150px;padding-top:4px;overflow-x:auto}
.sup-tm{display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:4px;flex:1 0 34px;height:100%}
.sup-tm-bars{display:flex;align-items:flex-end;justify-content:center;gap:3px;width:100%;height:100%}
.sup-tm-bars span{width:12px;min-height:2px;border-radius:var(--radius-sm) var(--radius-sm) 0 0}
.tm-a{background:#2ecc71}.tm-b{background:#e5484d}
.sup-trend-leg{display:flex;gap:16px;margin-top:8px;font-size:12px;color:var(--text-dim)}
.sup-trend-leg i{display:inline-block;width:10px;height:10px;border-radius:var(--radius-sm);margin-right:4px;vertical-align:middle}
.sup-exp{white-space:nowrap}
.sup-note{font-size:12px;color:var(--text-dim);background:color-mix(in srgb,#f5a623 12%,transparent);border:1px solid color-mix(in srgb,#f5a623 30%,transparent);border-radius:var(--radius);padding:6px 9px;margin:0 0 8px;line-height:1.4}
/* Modal de drill-down (ver los tickets/clientes detrás de un ranking) */
.g-modal{position:fixed;inset:0;z-index:3000;background:rgba(0,0,0,.5);display:flex;align-items:center;justify-content:center;padding:20px}
.g-modal-card{background:var(--surface);border:1px solid var(--border-strong);border-radius:var(--radius);box-shadow:var(--shadow);width:min(860px,96vw);max-height:88vh;display:flex;flex-direction:column;overflow:hidden}
.g-modal-h{display:flex;align-items:center;gap:10px;padding:14px 16px;border-bottom:1px solid var(--border);background:var(--surface-2)}
.g-modal-h b{font-family:'IBM Plex Sans';font-size:14px}
.g-modal-h .g-sp{flex:1}
.g-modal-x{background:transparent;border:0;color:var(--text-dim);font-size:17px;cursor:pointer;width:30px;height:30px;border-radius:var(--radius-sm)}
.g-modal-x:hover{background:color-mix(in srgb,var(--text) 10%,transparent)}
.g-modal-b{overflow:auto;padding:0}
.g-tab{width:100%;border-collapse:collapse;font-size:12.5px}
/* El dibujo común: mismo fondo de cabecera que el resto, sin versales y con la línea marcada. */
.g-tab th{position:sticky;top:0;text-align:left;background:var(--surface-3);color:var(--text-dim);padding:6px 10px;border-bottom:1px solid var(--border-strong);font-size:11px;font-weight:var(--fw-semi);text-transform:none;letter-spacing:0;z-index:1}
.g-tab td{padding:7px 10px;border-bottom:1px solid var(--border-strong)}
.g-tab tbody tr:hover{background:color-mix(in srgb,var(--accent-ink) 6%,transparent)}
.g-tab a{color:var(--accent-ink);text-decoration:none}.g-tab a:hover{text-decoration:underline}
.g-mono{font-family:'IBM Plex Mono';font-size:.9em;color:var(--text-faint)}
.g-est{font-size:12px;color:var(--text-dim);white-space:nowrap}
.g-empty{color:var(--text-faint);padding:14px}
.sup-res-note{font-size:12px;color:var(--text-faint)}
.sup-map{height:380px;border-radius:var(--radius);overflow:hidden;border:1px solid var(--border);background:var(--surface-2)}
.sup-map .leaflet-container{background:var(--surface-2)}
.rc-dx{border:1px solid;border-radius:var(--radius-sm);padding:0 5px;font-size:10px;white-space:nowrap;margin-left:4px}
.rc-sub{font-size:11px;color:var(--text-faint)}
.rc-flag{color:var(--signal);font-size:10px;font-weight:var(--fw-bold)}
.sup-bar.rc-hasbtn{grid-template-columns:minmax(80px,38%) 1fr 40px 26px}
.rc-task{background:var(--surface-2);border:1px solid var(--border);color:var(--accent-ink);width:24px;height:22px;border-radius:var(--radius-sm);cursor:pointer;font-size:14px;line-height:1;padding:0;display:flex;align-items:center;justify-content:center}
.rc-task:hover{background:color-mix(in srgb,var(--accent-ink) 15%,transparent)}
/* --signal es para RELLENOS; como texto no da contraste en ninguno de los dos temas (medido 1,99).
   La variante para texto es --accent-ink, que cada tema define a su medida. */
.rc-rebote{color:var(--accent-ink);font-weight:var(--fw-semi);font-size:11px;white-space:nowrap}
#cmBody{display:flex;flex-direction:column;overflow:hidden}   /* llena todo el alto del panel */
#cmBody .cap-kpis{flex:0 0 auto}
/* Barra superior compacta (navegador): título + 2 KPIs a la izquierda, buscar + actualizar a la derecha, todo en una fila */
.cm-bar{flex-wrap:nowrap}
.cm-bar .sup-tools{margin-left:auto;flex:0 0 auto}
.cm-bar .cm-find{width:190px}
.cm-barkpis{display:flex;align-items:center;gap:8px;margin-left:4px;flex:0 0 auto}
.cm-kchip{display:inline-flex;align-items:center;gap:7px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);padding:5px 12px;font-size:12.5px;font-weight:var(--fw-semi);color:var(--text-dim);cursor:pointer;white-space:nowrap;line-height:1}
.cm-kchip:hover{border-color:var(--border-strong);background:var(--surface-2)}
.cm-kchip b{font-size:13.5px;font-variant-numeric:tabular-nums}
.cm-kdot{width:8px;height:8px;border-radius:var(--radius-circ);flex:0 0 auto}
.cm-kdot.caida{background:#e5484d}.cm-kdot.degradada{background:#f5a623}
@media(min-width:761px){ #cmBody>.cap-kpis{display:none} }   /* en el navegador los KPIs van en la barra, no arriba del cuerpo */
@media(max-width:1080px){ .cm-bar .so-count{display:none} }   /* si la fila aprieta, el subtítulo cede primero */
@media(max-width:760px){ .cm-barkpis{display:none} }         /* en el celular los KPIs siguen en el cuerpo (como estaban) */
.cm-cols{display:grid;grid-template-columns:320px 1fr;grid-template-rows:minmax(0,1fr);gap:12px;padding:10px 14px 14px;min-height:0;flex:1 1 auto}
.cm-list{overflow:auto;min-height:0}
.cm-list h4{margin:0 0 8px;font-size:12.5px;display:flex;align-items:center;gap:6px}
.cm-list h4 small{color:var(--text-faint);font-weight:var(--fw-normal)}
.cm-map{height:auto;min-height:0;border-radius:var(--radius);overflow:hidden;border:1px solid var(--border);background:var(--surface-2);min-width:0}
.cm-map .leaflet-container{background:var(--surface-2)}
.cm-row{display:flex;align-items:center;gap:7px;flex-wrap:wrap;padding:5px 7px;border-radius:var(--radius-sm);cursor:pointer;font-size:12.5px}
.cm-row:hover{background:color-mix(in srgb,var(--accent-ink) 8%,transparent)}
/* El renglón de abajo alineado con el nombre y no con el punto: la sangría de 15
   px lo dejaba flotando debajo del punto de estado, que no es de donde cuelga. */
.cm-row-sub{color:var(--text-faint);font-size:11px;width:100%;padding-left:16px;font-variant-numeric:tabular-nums}
/* Los números de cliente en versalita tabular: en una lista de veinte, las cifras
   que no se alinean obligan a leer cada una en vez de barrerlas con la vista. */
.cm-clinum{font-variant-numeric:tabular-nums}
.cm-dot{width:9px;height:9px;border-radius:var(--radius-circ);flex:0 0 auto}
.cm-dot.admin{background:#f5a623}
.cm-dot.nov,.cm-kdot.nov{background:var(--accent-ink)}
.cm-dot.sola,.cm-kdot.sola{background:rgba(229,72,77,.25);box-shadow:inset 0 0 0 2px #e5484d}
.cm-dot.ciega,.cm-kdot.ciega{background:#7c8698}
.cm-row-nov:not([data-cmcaja]){cursor:default}
.cm-row-nov .cm-row-sub a{color:inherit;text-decoration:underline dotted}
.cm-dot.caida{background:#e5484d}.cm-dot.degradada{background:#f5a623}
.cm-empty{color:var(--text-faint);font-size:12px;padding:6px 8px}
/* Sub-lista de clientes bajo cada caja CAÍDA (estado + ticket para saber a quién gestionar) — compacta */
.cm-row-caida{cursor:pointer;padding:3px 7px}
.cm-row-caida .cm-row-sub{width:auto;padding-left:6px}   /* la línea «OLT · N caídos» va al lado del nombre, no en renglón aparte */
.cm-clisub{margin:0 0 5px 14px;padding:1px 0 1px 8px;border-left:2px solid color-mix(in srgb,#e5484d 35%,transparent);display:flex;flex-direction:column;gap:1px}
.cm-clirow{display:flex;align-items:center;gap:5px;flex-wrap:wrap;font-size:12px;line-height:1.6}
.cm-clirow .cm-est{font-size:10px;padding:0 6px}
.cm-clinum{color:var(--link);text-decoration:none;font-variant-numeric:tabular-nums;font-weight:var(--fw-semi)}.cm-clinum:hover{text-decoration:underline}
.cm-clisub-e{color:var(--text-faint);font-size:11px}
.cm-recu-dot{width:13px;height:13px;border-radius:var(--radius-circ);border:2px solid #fff}
/* ===== EL GLOBO DEJA DE CRECER =====
   Sin tope crecía hasta 720 px de ancho y todo lo alto que hiciera falta. Con una
   caja de catorce clientes cerca del borde, Leaflet corre el mapa solo para
   acomodarlo: el contenido se mueve abajo del mouse y el cursor titila. Con un
   alto máximo y la lista desplazándose adentro, el globo mide siempre lo mismo y
   el mapa se queda quieto. */
.cm-pop{font-size:12px;line-height:1.45;
  /* ===== ANCHO FIJO, Y NO «HASTA» =====
     Con `max-width` sola, Leaflet medía el ancho natural del contenido... pero
     desde que el globo es una columna flexible con la lista desplazándose adentro,
     la tabla ya no empuja el ancho —un hijo con `overflow` no le suma ancho al
     padre— así que Leaflet lo dibujaba angosto y la tabla salía cortada por la
     derecha, sin barra para desplazarla. Se vio en la captura, no leyendo el CSS.
     Dándole un ancho, el globo mide siempre lo mismo: la tabla entra, y si algún
     día no entra se desplaza en vez de cortarse. */
  width:min(480px,92vw);min-width:240px;max-width:480px;
  display:flex;flex-direction:column;max-height:min(60vh,440px)}
.cm-pop>.cm-pcli-list{flex:1 1 auto;min-height:0;overflow:auto}
.cm-pop .cm-cltab{min-width:100%}
/* Clientes: en el navegador con muchos, 2 tablas alineadas lado a lado (columnas prolijas) → entra sin scroll */
.cm-clicols{display:flex;gap:12px;align-items:flex-start}
.cm-clicols .cm-cltab{flex:1 1 0;min-width:0;font-size:12px}
/* Iba en 3 px de cuando la tabla se mostraba a dos columnas, una al lado de la
   otra, y no entraba de otra forma. Desde que es una sola lista hacia abajo eso
   es sólo apretado: con 7 px las filas se separan y se puede seguir un renglón
   con la vista sin perderlo. */
.cm-clicols .cm-cltab th{padding:6px 10px}
.cm-clicols .cm-cltab td{padding:7px 10px}
.cm-clicols .cm-td-cli{white-space:nowrap}
.cm-clicols .cm-serial{white-space:nowrap;font-size:11px}
/* ===== EL ENCABEZADO =====
   El nombre, y al lado en tono menor dónde está: OLT, GPON y zona son de
   consulta, no de diagnóstico, y no merecen el mismo peso que el nombre. Las
   acciones a la derecha, separadas del texto. */
.cm-pop-h{display:flex;align-items:center;gap:9px;padding:0 0 8px;border-bottom:1px solid var(--border);margin-bottom:0}
.cm-pop-nom{font-size:14.5px;font-weight:var(--fw-semi);letter-spacing:-.2px}
.cm-pop-ubi{font-size:11.5px;color:var(--text-faint);font-variant-numeric:tabular-nums;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* LA FILA DE ACCIONES NO SE APRIETA NUNCA. Sin esto, cuando el nombre de la caja
   o la línea de OLT crecen, el botón se encoge por debajo de su texto y las
   palabras se salen del relleno azul: se veía «Leer la OLT ahora» con el fondo
   sólo detrás de dos palabras. */
.cm-pop-acc{margin-left:auto;display:flex;gap:5px;align-items:center;flex:0 0 auto;white-space:nowrap}
.cm-pop-acc>*{flex:0 0 auto}
/* Y el nombre tampoco se parte: lo que cede es la línea de OLT, que ya tiene sus
   puntos suspensivos. */
.cm-pop-nom{flex:0 0 auto}
.cm-pop-ubi{flex:0 1 auto}
/* ===== LOS TRES BOTONES DEL ENCABEZADO SON EL MISMO BOTÓN =====
   La ubicación, «Leer la OLT ahora» y la ✕ de cerrar comparten alto, borde, radio
   y color: se leen como UNA fila de acciones y no como tres cosas de distinta
   época. La única diferencia es el ancho, que se la da el texto.
   EL DE LEER LA OLT PERDIÓ EL RELLENO AZUL, y no es sólo por parecerse a los
   otros dos: era el último control relleno de acento que quedaba en el sistema.
   La migración al estilo clásico sacó esos rellenos de todas las pantallas —lo
   elegido pasa a fondo tenue— y éste se había quedado atrás. */
/* EL SELECTOR DE LA ✕ VA CON EL CAMINO COMPLETO Y NO SUELTO. Leaflet la pinta con
   «.leaflet-container a.leaflet-popup-close-button» —dos clases y un elemento— y
   una regla nuestra de una sola clase pierde siempre, sin importar que esté
   después. Se vio en la captura: los otros dos botones ya emparejados y la cruz
   todavía con su dibujo de fábrica. */
.cm-pop-ico,.cm-pop-refresh,.leaflet-container a.leaflet-popup-close-button{
  height:26px;min-width:26px;padding:0 8px;
  display:inline-flex!important;align-items:center;justify-content:center;
  border:1px solid var(--border);border-radius:var(--radius-sm);
  background:var(--surface);color:var(--text-dim);
  font:inherit;font-size:11.5px;font-weight:var(--fw-semi);line-height:1;
  text-decoration:none;cursor:pointer;box-shadow:none}
.cm-pop-ico:hover,.cm-pop-refresh:hover,.leaflet-container a.leaflet-popup-close-button:hover,.leaflet-container a.leaflet-popup-close-button:focus{
  color:var(--text);border-color:var(--border-strong);background:var(--surface-2)}
.cm-pop-ico:focus-visible,.cm-pop-refresh:focus-visible,.leaflet-container a.leaflet-popup-close-button:focus-visible{
  outline:2px solid var(--accent-ink);outline-offset:1px}
.cm-pop-ico,.leaflet-container a.leaflet-popup-close-button{padding:0;width:26px}
.cm-pop-ico svg{width:14px;height:14px}
/* ===== LAS CUATRO MEDIDAS, UNA FRANJA CON DIVISIONES =====
   Mismo dibujo que los indicadores del resto del sistema: una tira dividida y no
   cuatro recuadros, que leen como cuatro objetos cuando son cuatro caras de lo
   mismo. */
.cm-medidas{display:grid;grid-template-columns:repeat(4,1fr);border-bottom:1px solid var(--border)}
.cm-medidas>div{padding:8px 12px;border-right:1px solid var(--border);min-width:0}
.cm-medidas>div:last-child{border-right:0}
.cm-medidas .k{display:block;font-size:10.5px;color:var(--text-faint);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cm-medidas .v{display:block;font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:15px;
  font-weight:var(--fw-semi);font-variant-numeric:tabular-nums;letter-spacing:-.3px;margin-top:1px}
.cm-medidas .v small{font-size:10.5px;font-weight:var(--fw-normal);color:var(--text-faint);margin-left:3px}
.cm-reparto{padding:9px 12px;border-bottom:1px solid var(--border)}
@media(max-width:760px){ .cm-medidas{grid-template-columns:repeat(2,1fr)} .cm-medidas>div:nth-child(2){border-right:0} }
.cm-pop-refresh{white-space:nowrap}
.cm-pop-refresh:disabled{opacity:.55;cursor:default}
.cm-pop-meta{display:grid;grid-template-columns:1fr 1fr;gap:2px 14px;padding:6px 0;border-top:1px solid var(--border);border-bottom:1px solid var(--border);margin-bottom:6px}
.cm-pop-meta>div{display:flex;justify-content:space-between;gap:6px;font-size:11px}
/* ===== LAS FRANJAS NUEVAS NO SON PARES DE RÓTULO Y VALOR =====
   La regla de arriba es para los renglones «rótulo … valor» que vivían acá, y
   alcanza a CUALQUIER div hijo: dejaba la franja de medidas repartida con
   `space-between` en vez de en cuartos iguales, y ponía la barra de colores AL
   LADO de su leyenda en vez de encima, que es por qué se veía como una rayita a
   la izquierda. Gana por especificidad, así que hay que ganarle igual. */
.cm-pop-meta>.cm-medidas{display:grid;grid-template-columns:repeat(4,1fr);justify-content:initial;gap:0;font-size:inherit}
.cm-pop-meta>.cm-reparto{display:block;justify-content:initial;gap:0;font-size:inherit}
.cm-pop-meta span{color:var(--text-faint)}.cm-pop-meta b{font-weight:var(--fw-semi);text-align:right;font-variant-numeric:tabular-nums}
.cm-pcli-list{margin-top:0}
/* Clientes + señal como TABLA con recuadro (popup en blanco → colores claros) */
/* ===== ESTA TABLA VIVE ADENTRO DEL POPUP DEL MAPA, QUE SÍ CAMBIA CON EL TEMA =====
   Estaba escrita con colores fijos de tema claro —#ddd, #f3f4f6, #666 y sobre todo el #1155cc del
   número de cliente—, así que en oscuro quedaba azul marino sobre fondo oscuro y no se leía. Lo
   reportó Matías. La versión del celular (.cm-sheet) ya usaba los tokens; la del escritorio se había
   quedado atrás. Con los tokens anda en los dos temas y no hay que mantener dos paletas. */
.cm-cltab{width:100%;border-collapse:collapse;font-size:12.5px;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}
/* El dibujo común. El relleno chico de `.cm-clicols .cm-cltab` sigue mandando: esa copia vive en el
   panel angosto del mapa, al lado de otra tabla, y ahí 10 px por lado no entran. */
.cm-cltab th{text-align:left;font-weight:var(--fw-semi);color:var(--text-dim);background:var(--surface-3);padding:6px 10px;border-bottom:1px solid var(--border-strong);font-size:11px;text-transform:none;letter-spacing:0}
.cm-cltab th:last-child,.cm-cltab td:last-child{text-align:right}
.cm-cltab th.num,.cm-cltab td.num{text-align:right}
/* ===== LA CABECERA QUE ORDENA SE COMPORTA COMO UN BOTÓN =====
   Cursor, foco visible y una marca de hacia dónde está ordenando. Sin la marca
   uno toca y no sabe si pasó algo o si ya estaba así. */
.cm-cltab th.cm-ord{cursor:pointer;user-select:none}
.cm-cltab th.cm-ord:hover{color:var(--text)}
.cm-cltab th.cm-ord:focus-visible{outline:2px solid var(--accent-ink);outline-offset:-2px}
.cm-cltab th.cm-ord::after{content:'';display:inline-block;width:0;height:0;margin-left:5px;
  border-left:3.5px solid transparent;border-right:3.5px solid transparent;opacity:.45}
.cm-cltab th.cm-ord[data-dir=asc]::after{border-bottom:4px solid currentColor;opacity:1}
.cm-cltab th.cm-ord[data-dir=desc]::after{border-top:4px solid currentColor;opacity:1}
/* La gravedad al borde de la fila: se ve de reojo al bajar por la lista, sin
   leer ni un dígito y sin gastar una columna. */
.cm-cltab tbody td:first-child{border-left:3px solid transparent}
.cm-cltab tr.cm-f-ojo td:first-child{border-left-color:var(--amber)}
.cm-cltab tr.cm-f-mal td:first-child{border-left-color:var(--red)}
/* La cabecera queda fija al desplazar: con catorce clientes, a mitad de lista uno
   ya no se acuerda de qué columna es cuál. */
.cm-cli-scroll thead th{position:sticky;top:0;z-index:1}
.cm-cltab td{padding:7px 10px;border-bottom:1px solid var(--border-strong)}
.cm-cltab tbody tr:last-child td{border-bottom:0}
.cm-cltab a{color:var(--link);text-decoration:none;font-variant-numeric:tabular-nums}.cm-cltab a:hover{text-decoration:underline}
.cm-cltab-empty{color:var(--text-faint);font-size:12px;padding:10px 2px}
.cm-serial{font-family:'IBM Plex Mono',ui-monospace,monospace;font-size:.9em;color:var(--text-faint,#666);letter-spacing:.2px;word-break:break-all}
.cm-est{display:inline-block;padding:1px 7px;border-radius:var(--radius);font-size:.86em;font-weight:var(--fw-semi);white-space:nowrap;line-height:1.5;border:1px solid transparent}
/* El fondo y el borde son translúcidos y sirven en los dos temas; el texto no: #1e9e5a, #c47f10 y
   #d13b40 se eligieron para fondo blanco. Los tokens ya están medidos para cada tema. */
.cm-est.ok{background:rgba(46,204,113,.15);color:var(--green);border-color:rgba(46,204,113,.35)}
.cm-est.warn{background:rgba(245,166,35,.16);color:var(--amber);border-color:rgba(245,166,35,.4)}
.cm-est.bad{background:rgba(229,72,77,.15);color:var(--red);border-color:rgba(229,72,77,.38)}
.cm-est-none{color:var(--text-faint)}
.cm-sig{font-variant-numeric:tabular-nums;font-weight:var(--fw-semi);white-space:nowrap}
.cm-sig.cm-off{color:var(--red)}
.cm-pop-live:not(:empty){padding:7px 12px;border-top:1px solid var(--border);font-size:11.5px;color:var(--text-faint)}
.cm-live-ok{color:var(--green);font-weight:var(--fw-semi)}.cm-live-err{color:var(--red)}.cm-live-load{color:var(--text-dim)}
/* Ficha de caja a PANTALLA COMPLETA en el celular (sheet) */
.cm-sheet{display:none;position:fixed;inset:0;z-index:2000;background:rgba(0,0,0,.5)}
.cm-sheet.open{display:block}
.cm-sheet-card{position:absolute;inset:0;background:var(--surface);overflow:auto;padding:16px 16px 28px;-webkit-overflow-scrolling:touch}
.cm-sheet-close{position:absolute;top:12px;right:12px;width:36px;height:36px;border-radius:var(--radius);border:1px solid var(--border);background:var(--surface-2);color:var(--text);font-size:18px;line-height:1;cursor:pointer;z-index:3}
/* Letras adaptables con clamp: legibles (visión reducida) pero acotadas (no gigantes) */
.cm-sheet .cm-pop{min-width:0;max-width:640px;margin:0 auto;font-size:clamp(14px,4vw,16px);line-height:1.5;color:var(--text)}
.cm-sheet .cm-pop-h{margin-bottom:14px;padding-right:48px;align-items:center}
.cm-sheet .cm-pop-h b{font-size:clamp(19px,5.6vw,23px)}
/* En el celular el mismo botón, pero con altura de dedo: 26 px se toca mal. La
   forma no cambia, sólo la medida. */
.cm-sheet .cm-pop-refresh{font-size:clamp(13px,3.4vw,15px);height:38px;padding:0 14px}
.cm-sheet .cm-pop-ico{width:38px;height:38px}
.cm-sheet .cm-pop-nom{font-size:clamp(19px,5.6vw,23px)}
.cm-sheet .cm-pop-meta{gap:14px 18px;padding:16px 0;border-color:var(--border);font-size:clamp(15px,4.4vw,18px)}
.cm-sheet .cm-pop-meta>div{align-items:baseline}
.cm-sheet .cm-pop-meta span{color:var(--text-dim);font-size:clamp(15px,4.4vw,18px)}
.cm-sheet .cm-pop-meta b{color:var(--text);font-size:clamp(15px,4.4vw,18px)}
.cm-sheet .cm-geo{font-size:clamp(14px,4vw,16px);padding:8px 14px}
.cm-sheet .cm-pcli-list{margin-top:14px}
.cm-sheet .cm-cltab{font-size:clamp(15px,4.4vw,18px);border-color:var(--border)}
.cm-sheet .cm-cltab th{background:var(--surface-2);color:var(--text-dim);border-color:var(--border);padding:10px 12px;font-size:clamp(13px,3.4vw,15px)}
.cm-sheet .cm-cltab td{border-color:var(--border);padding:12px 12px}
.cm-sheet .cm-cltab-empty{color:var(--text-faint)}
/* Celular: tabla de 3 columnas (Serial debajo del nº) → entra TODO sin deslizar */
.cm-sheet .cm-cltab-m{table-layout:fixed;width:100%;font-size:clamp(13.5px,3.9vw,16px)}
.cm-sheet .cm-cltab-m th,.cm-sheet .cm-cltab-m td{padding:11px 9px;word-break:break-word}
.cm-sheet .cm-cltab-m col,.cm-sheet .cm-cltab-m th:nth-child(1){width:40%}
.cm-sheet .cm-cltab-m th:nth-child(2){width:34%}
.cm-sheet .cm-cltab-m th:last-child,.cm-sheet .cm-cltab-m td:last-child{width:26%;text-align:right}
.cm-cltab-m .cm-td-cliM .cm-serial{display:block;font-size:.72em;color:var(--text-dim);margin-top:3px;word-break:break-all;font-weight:var(--fw-normal);letter-spacing:.2px}
.cm-cltab-m .cm-est{white-space:normal}   /* si la etiqueta es larga, envuelve en 2 líneas en vez de desbordar */
.cm-sheet .cm-sig{font-size:clamp(14px,4vw,16px)}
.cm-sheet .cm-pop-live{font-size:clamp(13px,3.6vw,15px);margin-top:14px}
body.cm-sheet-on{overflow:hidden}
/* Con la ficha abierta, oculto TODO lo de atrás (incluidos los <input> nativos que se dibujan encima de las capas fijas en el WebView) */
body.cm-sheet-on #cajasWrap, body.cm-sheet-on #oltMain{visibility:hidden}
/* «Mi ubicación» (GPS) + cajas cercanas */
/* La tira para cambiar entre dibujo y foto. Mismo dibujo que la de «Tierra»
   (.earth-base): fondo tenue en el elegido y no relleno de acento, que es la
   regla del estilo clásico para lo que se elige. */
.cm-base{display:flex;gap:3px;background:var(--surface);border:1px solid var(--border-strong);border-radius:var(--radius);padding:3px;box-shadow:var(--shadow)}
.cm-base button{padding:5px 10px;border-radius:var(--radius-sm);font-size:12px;font-weight:var(--fw-semi);color:var(--text-dim);background:none;border:0;cursor:pointer;line-height:1.2}
.cm-base button:hover{color:var(--text)}
.cm-base button.on{background:var(--selected);color:var(--text)}
/* SOBRE LA FOTO NO HAY PAPEL DETRÁS. La etiqueta de zona se apoya en el color de
   la superficie, que sobre una imagen aérea puede quedar contra cualquier cosa:
   se le pone fondo propio y se le sube el peso. Las de caja ya vienen con su
   propio fondo oscuro y no hacen falta tocar. */
.cm-sat .cm-zlbl{background:rgba(12,16,22,.82);color:#fff;border-width:1px;opacity:1}
.cm-sat .leaflet-tooltip.cm-clbl{background:rgba(12,16,22,.92)}
/* El botón de «mi ubicación» usaba blanco y azul escritos a mano: en tema oscuro
   era un círculo blanco en el medio del mapa. Con los tokens acompaña al tema. */
.cm-loc-ctl{width:42px;height:42px;border-radius:var(--radius-circ);background:var(--surface);border:1px solid var(--border-strong);box-shadow:var(--shadow);cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--accent-ink);padding:0}
.cm-loc-ctl svg{width:23px;height:23px}
.cm-loc-ctl.loading{opacity:.55}
.cm-me-dot{width:14px;height:14px;border-radius:var(--radius-circ);background:#2f6fed;border:3px solid #fff;box-shadow:0 0 0 2px rgba(47,111,237,.5),0 1px 5px rgba(0,0,0,.5)}
.cm-near{display:none;position:fixed;left:0;right:0;bottom:0;z-index:2100}
.cm-near.open{display:block}
.cm-near-card{background:var(--surface);border-radius:var(--radius) var(--radius) 0 0;box-shadow:0 -8px 30px rgba(0,0,0,.45);padding:14px 16px 22px;max-height:64vh;overflow:auto}
.cm-near-h{display:flex;justify-content:space-between;align-items:center}.cm-near-h b{font-size:15px}
.cm-near-close{width:34px;height:34px;border-radius:var(--radius);border:1px solid var(--border);background:var(--surface-2);color:var(--text);font-size:17px;line-height:1;cursor:pointer}
  /* CERRAR LA FICHA DE UNA CAJA. Lo incómodo no era el tamaño: la X vivía DENTRO de `.cm-sheet-card`,
     que es el contenedor que scrollea, así que al bajar para leer la lista de clientes se iba de
     pantalla y había que volver arriba para cerrar. Con `fixed` queda anclada al borde de la
     ventana y está siempre a la vista.
     Y se empareja con el botón de actualizar: los dos cuadrados, del mismo tamaño y radio, uno al
     lado del otro conceptualmente — el de actualizar con el color de acción, éste neutro. */
  /* EL BOTÓN DE LEER LA OLT SALIÓ DE ESTE GRUPO. Estas medidas —36×36, relleno
     cero— son de cuando era un `↻`, un símbolo solo adentro de un cuadrado. Desde
     que dice «Leer la OLT ahora», un cuadrado de 36 px con cuatro palabras adentro
     las desborda por los dos lados y el fondo azul queda detrás del medio: se veía
     así en la pantalla, con «Leer» y «ahora» flotando fuera del botón. */
  .cm-sheet-close, .cm-near-close{
    display:inline-flex;align-items:center;justify-content:center;
    width:36px;height:36px;padding:0;border-radius:var(--radius);font-size:17px;line-height:1;cursor:pointer;
    transition:background .13s, border-color .13s, transform .13s}
  .cm-sheet-close{position:fixed;top:14px;right:14px;z-index:2100}
  .cm-sheet-close:hover, .cm-near-close:hover{background:var(--surface);border-color:var(--text-faint);transform:scale(1.06)}
  /* Y el giro de 45° al pasar por encima también era del `↻`: un botón con texto
     que se inclina no se lee. */
  .cm-sheet-close:active, .cm-near-close:active{transform:scale(.94)}
  /* El área sensible se extiende unos píxeles más allá del borde visible, sin agrandar el botón. */
  .cm-sheet-close::after, .cm-near-close::after{content:'';position:absolute;top:-6px;right:-6px;bottom:-6px;left:-6px}
  @media (pointer:coarse){
    .cm-sheet-close, .cm-near-close{width:44px;height:44px;font-size:20px}
  }

  /* ===== CORRECCIONES DE LA AUDITORÍA VISUAL (12/08/2026) =====
     Salieron de MIRAR las 19 pantallas con el navegador, no de leer el CSS. Ninguna pantalla se va
     de ancho; lo que había era esto. */

  /* 1 · Las casillas del mapa se pisaban entre sí: el contenedor no tenía separación, así que se
     leía «Marcar zonas☑ Áreas de cobertura☑ Nombres» todo pegado y «Agrupar» caía sola abajo. */
  .cm-listtools{display:flex;flex-wrap:wrap;align-items:center;gap:6px 16px}

  /* 2 · Texto cortado a mitad de frase y sin aviso. En «Cajas sin servicio» el motivo terminaba en
     «…avisaron falta de» y uno no sabe si eso es todo. Con puntos suspensivos se entiende que sigue,
     y el título completo queda en el tooltip del navegador. */
  .nov-row > small:last-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0}

  /* 3 · Piso de 11 px para el texto chico. La auditoría de celular ya había fijado ese mínimo y
     estos tres se habían quedado abajo: 10 y 9,5 px no se leen de un vistazo. */
  .cm-est{font-size:11px}
  .zn-est{font-size:11px}
  .nov-row small, .nov-sub small{font-size:11px}

  /* 4 · Los cuatro íconos de acción de cada fila de Usuarios estaban a 17 px y pegados: había que
     apuntar para no borrar cuando se quería editar. Se separan y se les da un blanco de toque
     razonable, sin engordar la fila. */
  .stk-b{min-width:26px;min-height:26px}
  td .stk-b + .stk-b, .cfg-acts .stk-b + .stk-b{margin-left:4px}
  .stk-b:hover{background:var(--surface-2)}
.cm-near-sub{color:var(--text-dim);font-size:12.5px;margin:3px 0 12px}
.cm-near-list{display:flex;flex-direction:column;gap:8px}
.cm-near-row{display:flex;justify-content:space-between;align-items:center;gap:10px;padding:13px 15px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2);color:var(--text);font-size:15px;cursor:pointer;text-align:left}
.cm-near-row.first{border-color:#2f6fed;background:color-mix(in srgb,#2f6fed 12%,var(--surface-2))}
.cm-near-name{font-weight:var(--fw-bold)}.cm-near-d{font-variant-numeric:tabular-nums;color:var(--text-dim);font-weight:var(--fw-semi);white-space:nowrap}
.cm-near-empty{color:var(--text-faint);padding:10px 2px}
/* Coordenadas = botón azul (mismo estilo que «Actualizar») que abre el GPS/Maps */
.cm-pop-meta .cm-meta-geo{grid-column:1/-1;align-items:center}
.cm-geo{display:inline-flex;align-items:center;gap:6px;background:#2f6fed;color:#fff;text-decoration:none;font-weight:var(--fw-semi);font-variant-numeric:tabular-nums;padding:6px 12px;border-radius:var(--radius-sm);font-size:12.5px}
.cm-geo svg{width:15px;height:15px;flex:0 0 auto;color:#fff}
.cm-geo:active{background:#255fd0}
/* Leaflet trae `.leaflet-container a{color:#0078A8}` (mismo peso que .cm-geo) y le pisaba el blanco → azul sobre azul ilegible. Subimos especificidad. */
.cm-meta-geo a.cm-geo, .cm-meta-geo a.cm-geo:link, .cm-meta-geo a.cm-geo:visited, .cm-meta-geo a.cm-geo svg{color:#fff}
.cm-zlbl{transform:translate(-50%,-50%);display:inline-block;background:var(--surface);border:1.5px solid;border-radius:var(--radius-sm);padding:0 5px;font-size:11px;font-weight:var(--fw-bold);white-space:nowrap;opacity:.95}
@keyframes cmpulse{0%{box-shadow:0 0 0 0 rgba(229,72,77,.7)}70%{box-shadow:0 0 0 13px rgba(229,72,77,0)}100%{box-shadow:0 0 0 0 rgba(229,72,77,0)}}
.cm-mudado td{opacity:.55;font-style:italic}
.nov-zrow{display:flex;align-items:center;gap:9px;padding:4px 0;border-bottom:1px dashed var(--border)}
.nov-zrow:last-child{border-bottom:0}
.nov-zrow b{min-width:74px}
.nov-zbar{flex:1;height:7px;border-radius:var(--radius-sm);background:var(--surface);overflow:hidden;min-width:60px}
.nov-zbar i{display:block;height:100%}
.nov-zpct{min-width:38px;text-align:right;font-weight:var(--fw-bold);font-size:12px}
.nov-zrow small{min-width:150px;text-align:right;color:var(--text-faint)}
/* Buscador de destinos (Ctrl+K): con ~50 pantallas, el que sabe lo que busca tipea en vez de navegar. */
/* Nombre flotante del riel: va pegado al body, así ningún scroll lo recorta. */
.sn-tip{position:fixed;transform:translateY(-50%);z-index:2100;display:none;pointer-events:none;
  background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius-sm);padding:5px 10px;
  font-size:12px;white-space:nowrap;color:var(--text);box-shadow:0 8px 24px rgba(0,0,0,.4)}
#cmdk{position:fixed;inset:0;z-index:2000;display:none;align-items:flex-start;justify-content:center;background:rgba(0,0,0,.5);padding-top:12vh}
#cmdk.open{display:flex}
#cmdk .ck-box{width:min(620px,92vw);background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;box-shadow:0 24px 70px rgba(0,0,0,.55)}
#cmdk input{width:100%;background:transparent;border:0;border-bottom:1px solid var(--border);color:var(--text);padding:15px 17px;font-size:14px;outline:none}
#cmdk .ck-list{max-height:52vh;overflow:auto;padding:6px}
#cmdk .ck-it{display:flex;align-items:center;gap:10px;padding:9px 11px;border-radius:var(--radius);cursor:pointer;font-size:13.5px}
#cmdk .ck-it small{margin-left:auto;color:var(--text-faint);font-size:11px}
#cmdk .ck-it.on,#cmdk .ck-it:hover{background:color-mix(in srgb,var(--accent-ink) 16%,transparent)}
#cmdk .ck-empty{padding:18px;color:var(--text-faint);font-size:12.5px;text-align:center}
.nov-head{display:flex;align-items:center;gap:12px;margin:0 0 14px}
.nov-head h2{margin:0;font-family:'IBM Plex Sans';font-size:18px;font-weight:var(--fw-bold)}
.nov-head .btn{margin-left:auto}
.nov-kpis .nov-k{margin:0}
/* Dos columnas en pantalla ancha para que entre todo sin scrollear; una sola en el celular. */
.nov-wrap{display:grid;grid-template-columns:1fr 1fr;gap:10px;align-items:start}
.nov-wrap>.nov-kpis{grid-column:1/-1}
.nov-wrap>.nov-pie{grid-column:1/-1}
@media(max-width:1000px){ .nov-wrap{grid-template-columns:1fr} }
.nov-h{padding:7px 11px;font-size:12.5px}
.nov-b{padding:7px 11px;font-size:12px;line-height:1.4}
.nov-row{padding:2px 0}
.nov-alta-cli{color:var(--accent-ink);cursor:pointer;font-weight:var(--fw-bold);font-size:12px}
.nov-alta-cli:hover{text-decoration:underline}
.nov-alta-est{display:block;font-size:11px;font-weight:var(--fw-semi);text-align:right;opacity:.9}
.nov-alta-new{color:var(--green);font-weight:var(--fw-bold);font-size:12px}
.nov-clk{cursor:pointer;border-radius:var(--radius-sm);margin:0 -5px;padding-left:5px;padding-right:5px}
.nov-clk:hover{background:color-mix(in srgb,var(--accent-ink) 12%,transparent)}
/* Cuando el clicable ES el encabezado no hace falta que se salga: ya ocupa todo el ancho. */
.nov-h.nov-clk{margin-left:0;margin-right:0}
.nov-zrow{padding:2px 0}
.nov-k{flex:1 1 120px;padding:6px 9px}
.nov-k b{font-size:16px}
.nov-kpis{gap:6px;margin-bottom:2px}
/* Todas del mismo alto para que la grilla quede pareja; si a una le sobran filas, scrollea adentro. */
.nov-card{border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2);overflow:hidden;display:flex;flex-direction:column;height:232px}
.nov-card .nov-b{flex:1;overflow:auto}
@media(max-width:1000px){ .nov-card{height:auto;max-height:260px} }
.nov-h{display:flex;align-items:center;gap:8px;padding:9px 12px;border-bottom:1px solid var(--border);font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:12.5px}
.nov-h b{margin-left:auto;font-size:12px;font-weight:var(--fw-bold)}
.nov-b{padding:10px 12px;font-size:12.5px;line-height:1.5}
.nov-row{display:flex;align-items:baseline;gap:8px;padding:3px 0;border-bottom:1px dashed var(--border)}
.nov-row:last-child{border-bottom:0}
/* El ancho fijo era para que los rótulos queden alineados en columna. Sigue estando, pero ahora
   como mínimo y no como jaula: si una palabra no entra, la fila se estira en vez de comérsela.
   «Mantenimiento» necesita 89 px y quedaba en «Mantenimient». */
.nov-row b{min-width:78px;flex:0 0 auto;white-space:nowrap}
.nov-row small{color:var(--text-faint)}
.nov-kpis{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:10px}
.nov-k{flex:1 1 130px;border:1px solid var(--border);border-radius:var(--radius);padding:8px 10px;background:var(--surface-2)}
.nov-k b{display:block;font-size:19px;font-family:'IBM Plex Sans';line-height:1.1}
.nov-k span{font-size:11px;color:var(--text-faint)}
.nov-ok{color:var(--green)}.nov-warn{color:var(--amber)}.nov-bad{color:var(--red)}
.cm-boc{display:block;font-size:11px;color:var(--text-faint);font-weight:var(--fw-medium)}
/* El color de los chips de tipo se resuelve arriba con color-mix (buscar «--cc»): no lleva filtro. */
/* Los niveles de vencimiento (En plazo / Cerca / Vencida / Muy vencida) usan una paleta apagada
   pensada para fondo claro: se aclara igual, sin tocar el tema claro. */
:root:not([data-theme="light"]) .due-bad,:root:not([data-theme="light"]) .tre-est{filter:brightness(1.5) saturate(.9)}
/* Acá había dos parches sólo-para-oscuro —el número de cliente del mapa y la chapita de estado en
   rojo— porque los dos traían colores fijos pensados para fondo claro. Ya no hacen falta: los dos
   usan el token que corresponde y andan en los dos temas con una sola definición. Un parche por
   tema es el camino a tener dos paletas que se desincronizan. */
:root:not([data-theme="light"]) .dbt-head .db-th,:root:not([data-theme="light"]) .db-th{color:var(--text-dim)}
/* Pestaña Tiempos (Estad. Soporte) */
/* UNA SOLA FILA. Con `wrap` y ancho natural, entraban cinco y la sexta bajaba sola: una franja
   entera para un numero. Ahora se reparten el ancho en partes iguales y se achican juntas.
   El piso de 118 px es para que no se aprieten hasta no entenderse: por debajo de eso la fila se
   desplaza de costado, pero sigue siendo una sola fila. */
.tt-kpis{display:flex;gap:8px;flex-wrap:nowrap;margin-bottom:10px;overflow-x:auto;
  scrollbar-width:thin;padding-bottom:2px}
.tt-kpi{flex:1 1 0;min-width:118px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
  padding:6px 12px;display:flex;align-items:baseline;gap:8px;flex-wrap:nowrap}
/* El número primero y la etiqueta al lado: lo que se busca es el número, y leerlo despues de dos
   renglones de titulo es al reves de como se mira un tablero. */
.tt-kpi .k-num{order:1;font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:18px;line-height:1.2;margin:0;white-space:nowrap}
/* La etiqueta cede espacio DESPUES del subtitulo y ANTES del numero. */
/* Sin mayúsculas forzadas ni espaciado entre letras: es el mismo componente que `.cap-kpis`, que ya
   los sacó. Dos dibujos para el mismo contador es lo que hace que dos pantallas se vean de sistemas
   distintos. */
.tt-kpi .k-lbl{order:2;font-size:11.5px;text-transform:none;letter-spacing:0;color:var(--text-faint);font-weight:var(--fw-semi);
  flex:0 1 auto;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* El numero NO se achica ni se corta: es el contenido de la tarjeta. Todo lo demas cede antes. */
.tt-kpi .k-num{flex:0 0 auto}
/* El subtitulo es lo primero que cede: es la aclaracion, no el dato. */
.tt-kpi .k-sub{order:3;flex:1 1 0;font-size:11px;color:var(--text-dim);margin:0;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
@media(max-width:1100px){ .tt-kpi .k-sub{display:none} }
/* EN EL TELÉFONO LA TARJETA SE ENSANCHA PARA QUE ENTRE LA ETIQUETA. Con 118 px el número se lleva
   casi todo y la etiqueta quedaba en «CAÍ… DEL PER…», partida en tres renglones y cortada en cada
   uno: se adivina, pero no se lee. Medido en un teléfono de 360 px, la etiqueta más larga —«Sin
   alimentación»— pedía 92 px, y con el número (46), la separación (8) y los bordes y el relleno
   (26) da 172. Con eso entran enteras.
   Se puede porque la tira YA se desliza de costado: en un teléfono se ven dos tarjetas completas y
   las demás se traen con el dedo. Es preferible a cuatro tarjetas ilegibles. */
@media(max-width:760px){ .tt-kpis > .tt-kpi, #oltWrap .tt-kpis > .tt-kpi{min-width:172px} }
/* Y con 5 tarjetas o mas tampoco: a ese ancho el subtitulo queda en «la OL…», que no dice nada y le
   roba lugar a la etiqueta, que si dice. */
.tt-kpis:has(.tt-kpi:nth-child(5)) .k-sub{display:none}
/* En «Qué hacer hoy» el KPI ES el selector: se toca y abajo cambia la tabla. Reemplaza a la tira de
   solapas, que mostraba el mismo número dos veces y comía una fila entera de alto.
   El seleccionado tiene que verse: un KPI que además es botón y no dice cuál está activo deja al que
   mira sin saber qué tabla está leyendo. */
#hoyMain .tt-kpi[data-hoytab]{cursor:pointer;transition:border-color .14s,background .14s}
#hoyMain .tt-kpi[data-hoytab]:hover{border-color:var(--text-faint)}
#hoyMain .tt-kpi[data-hoytab].on{border-color:var(--signal);background:var(--surface-2);
  box-shadow:inset 0 0 0 1px var(--signal)}
/* ===== LA FRANJA DE CAIDAS: TODO EN UNA FILA =====
   Mismo criterio que los KPI: no envuelve. Si no entra se desplaza de costado, que es una molestia
   chica y ocasional, en vez de partirse en dos filas fijas que empujan la tabla hacia abajo siempre. */
.fl-barra{display:flex;gap:8px;align-items:center;flex-wrap:nowrap;overflow-x:auto;
  scrollbar-width:thin;margin-bottom:12px;padding-bottom:2px}
.fl-barra>*{flex:0 0 auto}
.fl-barra .sup-tabseg{margin:0}
.fl-barra .re-dice{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0;flex:0 1 auto}
/* separa lo que FILTRA de lo que CAMBIA DE VISTA: comparten la fila pero no son lo mismo */
.fl-corte{width:1px;align-self:stretch;margin:2px 4px;background:var(--border)}
/* ===== QUE LA FILA QUEDE DERECHA =====
   Medido: los controles tenían 39, 38, 35 y 15 px de alto y arrancaban a 0, 1, 2 y 8. Además
   sobraban 261 px de hueco a cada lado del buscador. Las dos causas venían de afuera de esta fila:
   · `.help-search` trae `margin-left:auto` de fábrica —sirve en las barras donde el buscador se pega
     a la derecha—. Acá, con el contador que también lo pide, el espacio sobrante SE REPARTE entre
     los dos y el buscador queda flotando en el medio. Es lo mismo que le pasaba a «Actualizar».
     Se lo saca: en una fila de filtros el buscador va al lado del resto, no despegado.
   · `.find-count` trae `margin-bottom:8px` —pensado para cuando va solo, arriba de una tabla—, y en
     una fila centrada eso lo levanta 8 px sobre todo lo demás.
   El contador sí conserva su `margin-left:auto` propio: es el resumen y va contra la derecha. */
.fl-barra .help-search{margin-left:0}
.fl-barra .find-count{margin-bottom:0}
.fl-barra .sel,.fl-barra .inp,.fl-barra .help-search,.fl-barra .sup-tabseg,.fl-barra .btn,
.fl-barra .re-sel,.fl-barra .re-rango input{height:38px;box-sizing:border-box}
.fl-check{display:flex;gap:6px;align-items:center;font-size:12.5px;color:var(--text-dim);
  cursor:pointer;white-space:nowrap}

/* ===== COMO VENIMOS ===== */
/* Dos columnas y no tres: el SVG usa viewBox con height:auto, asi que su alto sale del ANCHO de
   la tarjeta. Con tres columnas los graficos quedaban de 68 px de alto, una hebra. */
.av-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(520px,1fr));gap:12px}
.av-b{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:14px 16px 12px;min-width:0}
.av-h{display:flex;align-items:flex-start;gap:10px;margin-bottom:10px}
.av-h h4{margin:0;font-size:14px;font-weight:var(--fw-black)}
.av-h p{margin:2px 0 0;font-size:12px;color:var(--text-dim)}
.av-ir{margin-left:auto;flex:0 0 auto;font-size:12px;color:var(--accent-ink);cursor:pointer;
  background:none;border:0;padding:4px 6px;border-radius:var(--radius-sm);white-space:nowrap}
.av-ir:hover{background:color-mix(in srgb, var(--accent-ink) 12%, transparent)}
/* El veredicto en palabras. El color acompana, pero la palabra sola ya alcanza: en blanco y negro
   —o para quien no distingue el rojo del verde— sigue diciendo lo mismo. */
.av-ver{display:inline-flex;align-items:baseline;gap:8px;padding:5px 11px;border-radius:var(--radius);
  font-weight:var(--fw-black);font-size:13.5px;border:1px solid transparent;margin-bottom:10px}
.av-ver small{font-weight:var(--fw-semi);font-size:12px;opacity:.85}
.av-mejor{color:var(--green);background:color-mix(in srgb, var(--green) 12%, transparent);
  border-color:color-mix(in srgb, var(--green) 30%, transparent)}
.av-peor{color:var(--red);background:color-mix(in srgb, var(--red) 12%, transparent);
  border-color:color-mix(in srgb, var(--red) 30%, transparent)}
.av-igual{color:var(--text-dim);background:color-mix(in srgb, var(--text-dim) 10%, transparent);
  border-color:var(--border)}
.av-nada{color:var(--text-faint);background:transparent;border-color:var(--border);font-weight:var(--fw-bold)}
/* El minigráfico de la serie del veredicto, arriba del gráfico grande. */
.av-spark{display:flex;align-items:center;gap:10px;margin:2px 0 6px}
.av-spark>span:first-child{font-size:11px;text-transform:uppercase;letter-spacing:.06em;
  color:var(--text-faint);font-weight:var(--fw-bold)}
/* ===== METROS DE FIBRA ===== */
/* Un renglón por técnico: nombre, barra, metros y porcentaje. La barra está para comparar de un
   vistazo sin leer los números, que es para lo que sirve mirar un reparto. */
.pm-list{display:flex;flex-direction:column;gap:6px}
.pm-row{display:flex;align-items:center;gap:10px}
.pm-n{flex:0 0 clamp(110px,26%,190px);font-size:12.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.pm-bar{flex:1 1 auto;height:8px;background:var(--surface-2);border-radius:var(--radius-sm);overflow:hidden;min-width:40px}
.pm-bar>i{display:block;height:100%;background:var(--accent-fill);border-radius:var(--radius-sm)}
.pm-m{flex:0 0 auto;font-variant-numeric:tabular-nums;font-size:12.5px}
.pm-p{flex:0 0 42px;text-align:right;font-size:12px;color:var(--text-faint)}
.proj-sum-fibra{margin-top:10px}
/* La tabla por proyecto de la solapa Fibra. */
.fb-table{display:flex;flex-direction:column}
.fb-row{display:grid;grid-template-columns:minmax(0,1fr) 92px 92px 62px 78px;gap:8px;align-items:center;
  padding:7px 4px;border-bottom:1px solid var(--border)}
.fb-row:last-child{border-bottom:none}
.fb-row[data-pid]{cursor:pointer}
.fb-row[data-pid]:hover{background:var(--surface-2)}
.fb-head{font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--text-faint);font-weight:var(--fw-bold)}
.fb-head span:not(:first-child){text-align:right}
.fb-n{font-size:12.5px;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fb-n small{display:block;color:var(--text-faint);font-size:11px}
.fb-m{text-align:right;font-variant-numeric:tabular-nums;font-size:12.5px}
.fb-real{color:var(--accent-ink)}
/* ===== ERRORES Y ALARMAS DE LAS OLT ===== */
/* El resumen de a qué apunta, arriba de la tabla: si veinte clientes apuntan al mismo tramo, eso es
   UN trabajo. El número grande primero, que es lo que se mira. */
.ol-grps{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin:0 0 10px;padding:9px 12px;
  background:var(--surface);border:1px solid var(--border);border-radius:var(--radius)}
.ol-grps-t{font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--text-faint);font-weight:var(--fw-bold)}
.ol-grp{display:flex;align-items:baseline;gap:7px}
.ol-grp b{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:16px}
.ol-grp span{font-size:12.5px;color:var(--text-dim)}
/* El porqué y el qué hacer van debajo de la conclusión, no en un globito: lo que hay que leer para
   decidir no puede estar escondido detrás de un hover. */
.ol-porque{display:block;color:var(--text-faint);font-size:12px;line-height:1.45;margin-top:3px}
.ol-hacer{display:block;color:var(--text-dim);font-size:12px;line-height:1.45;margin-top:3px}
.ol-hacer b{color:var(--text)}
/* El detalle de cada celda va DEBAJO del número, no pegado: «937» y «44.604 errores» en la misma
   línea se leen como un solo número de siete cifras. En estas tablas el salto no es automático:
   lo da la clase de la celda. */
.ol-tk td small{display:block;color:var(--text-faint);font-size:11px;line-height:1.45;font-weight:var(--fw-normal)}
.ol-tk td.num small{font-variant-numeric:tabular-nums}
/* ===== DIAGNOSTICO ===== */
.dg-inp{flex:1 1 auto;min-width:0}
.dg-res{display:flex;flex-direction:column;gap:6px}
.dg-r{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(0,1.6fr) 150px minmax(0,1fr);gap:12px;
  align-items:center;text-align:left;background:var(--surface);border:1px solid var(--border);
  border-radius:var(--radius);padding:9px 12px;cursor:pointer;color:var(--text);font:inherit}
.dg-r:hover{border-color:var(--accent-ink)}
.dg-r-n{font-weight:var(--fw-bold);font-size:12.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dg-r-d,.dg-r-o{font-size:12px;color:var(--text-dim);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dg-r-m{font-size:12px;color:var(--text-faint)}
.dg-cab{display:flex;align-items:flex-start;gap:16px;flex-wrap:wrap;margin:4px 0 12px}
.dg-cab h4{margin:0;font-size:16px;font-weight:var(--fw-black)}
.dg-cab>div>span{font-size:12.5px;color:var(--text-dim)}
/* LOS DATOS TÉCNICOS VAN EN FILA Y A LA IZQUIERDA. Estaban en columna y pegados a la derecha porque
   antes compartían el renglón con el nombre del cliente, que ocupaba la izquierda. Al mudarse el
   nombre al título de la caja, este bloque quedó solo: cuatro renglones cortos alineados contra el
   borde derecho, con medio ancho de pantalla vacío al lado. En fila entran en un renglón y se leen
   como lo que son: la identificación del equipo. */
/* Los datos se separan con ESPACIO, no con un punto. Con un punto colgaba al final del renglón cada
   vez que la fila envolvía —en el teléfono, siempre—, y quedaba «HWTC61009D40 ·» cortado. El
   espacio separa igual y no deja basura al cortar. */
.dg-cab-d{display:flex;flex-wrap:wrap;align-items:baseline;gap:3px 18px;font-size:12px;color:var(--text-dim)}
/* El veredicto: lo primero que se lee, con el borde del color del estado. */
.dg-ver{border:1px solid;border-left-width:4px;border-radius:var(--radius);padding:12px 15px;background:var(--surface)}
.dg-ver-t{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:15px;margin-bottom:5px}
.dg-ver-d{font-size:13.5px;line-height:1.5}
.dg-ver-h{font-size:12.5px;color:var(--text-dim);margin-top:7px}
.dg-ver-h b{color:var(--text)}
.dg-ver-o{font-size:12px;color:var(--text-faint);margin-top:6px}
.dg-lista{display:flex;flex-direction:column}
.dg-chk{display:flex;gap:12px;align-items:flex-start;padding:9px 2px;border-bottom:1px solid var(--border)}
.dg-chk:last-child{border-bottom:none}
.dg-pill{flex:0 0 78px;text-align:center;font-size:11px;text-transform:uppercase;letter-spacing:.05em;
  font-weight:var(--fw-black);border:1px solid;border-radius:var(--radius-sm);padding:3px 0}
.dg-chk-b{min-width:0;flex:1 1 auto;font-size:12.5px}
.dg-med{color:var(--text-faint);font-size:12px;font-variant-numeric:tabular-nums}
.dg-dice{color:var(--text-dim);font-size:12.5px;line-height:1.5;margin-top:2px}
.dg-hacer{font-size:12.5px;color:var(--text-dim);margin-top:3px}
.dg-hacer b{color:var(--text)}
.dg-sindato{opacity:.72}
@media(max-width:760px){ .dg-r{grid-template-columns:1fr} .dg-cab-d{margin-left:0;align-items:flex-start} }
/* El técnico se despliega y muestra de qué tareas sale su total. */
.fb-tec{border-bottom:1px solid var(--border)}
.fb-tec:last-child{border-bottom:none}
.fb-tec>summary{display:flex;align-items:center;gap:10px;cursor:pointer;padding:6px 2px;list-style:none}
.fb-tec>summary::-webkit-details-marker{display:none}
.fb-tec>summary:hover{background:var(--surface-2)}
.fb-tec[open]>summary{font-weight:var(--fw-bold)}
.fb-dets{padding:2px 0 8px 10px}
.fb-det{display:grid;grid-template-columns:92px minmax(0,1fr) 74px;gap:8px;align-items:center;
  padding:3px 0;font-size:12px;color:var(--text-dim)}
.fb-det b{text-align:right;color:var(--text);font-variant-numeric:tabular-nums}
.fb-det-t{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;cursor:pointer}
.fb-det-t:hover{color:var(--accent-ink);text-decoration:underline}
.fb-av,.fb-d{text-align:right;font-size:12px;color:var(--text-dim);font-variant-numeric:tabular-nums}
@media(max-width:620px){ .fb-row{grid-template-columns:minmax(0,1fr) 78px 78px} .fb-av,.fb-d{display:none} }
/* El editor de la ficha: técnico, metros y la cruz para sacar el renglón. */
/* Grilla y no flex: con flex cada renglón se acomodaba por su cuenta y las columnas quedaban
   corridas entre sí. Acá hay que leer hacia abajo —quién, cuánto, cuándo— y para eso las tres
   tienen que caer siempre en el mismo lugar. */
.mt-row,.mtec-head{display:grid;grid-template-columns:minmax(0,1fr) 110px 160px 34px;gap:8px;align-items:center}
.mt-row{margin-bottom:6px}
.mtec-head{font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--text-faint);
  font-weight:var(--fw-bold);margin-bottom:4px}
.mt-row .mt-u{min-width:0}
@media(max-width:620px){
  .mtec-head{display:none}
  .mt-row{grid-template-columns:minmax(0,1fr) 34px;gap:6px}
  .mt-row .mt-u{grid-column:1}
  .mt-row .mt-x{grid-column:2;grid-row:1}
  .mt-row .mt-m,.mt-row .mt-f{grid-column:1}
}
.mt-ro{display:flex;justify-content:space-between;gap:10px;padding:4px 0;border-bottom:1px solid var(--border);font-size:12.5px}
.mt-ro:last-child{border-bottom:none}
.av-nums{display:flex;flex-wrap:wrap;gap:14px;margin:10px 0 0;padding-top:10px;border-top:1px solid var(--border)}
.av-n{min-width:0}
.av-n b{display:block;font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:15px;line-height:1.2}
.av-n span{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--text-faint);font-weight:var(--fw-bold)}
.av-pie{margin-top:10px;font-size:12px;color:var(--text-faint);line-height:1.5}
.av-flujo{margin-top:10px;padding-top:10px;border-top:1px solid var(--border)}
.cap-filter button i{font-style:normal;color:var(--text-faint);font-weight:var(--fw-bold);margin-left:2px}
.cap-filter button.on i{color:inherit;opacity:.8}
.ct-ya{display:inline-block;margin-left:8px;font-size:10.5px;font-weight:var(--fw-bold);padding:1px 7px;border-radius:var(--radius-sm);
  color:var(--text-dim);background:color-mix(in srgb,var(--text-faint) 22%,transparent);white-space:nowrap}
.ct-res{margin:0 14px 4px;padding:10px 13px;border-radius:var(--radius);border-left:3px solid var(--text-faint);
  background:color-mix(in srgb,var(--text-faint) 8%,transparent)}
.ct-res b{display:block;font-size:13.5px}
.ct-res span{display:block;font-size:12px;color:var(--text-dim);line-height:1.5;margin-top:2px}
.ct-res-ok{border-left-color:var(--green);background:color-mix(in srgb,var(--green) 9%,transparent)}
.ct-res-ok b{color:var(--green)}
.ct-res-mal{border-left-color:var(--red);background:color-mix(in srgb,var(--red) 9%,transparent)}
.ct-res-mal b{color:var(--red)}
.ct-res-ojo{border-left-color:var(--amber);background:color-mix(in srgb,var(--amber) 9%,transparent)}
.ct-res-ojo b{color:var(--amber)}
.ct-ya-fin{color:var(--green);background:color-mix(in srgb,var(--green) 14%,transparent)}
.ct-ya-fila{opacity:.72}
.ct-ya-fila .c-cli{color:var(--text-dim)}
.cap-lib .cap-lib-h{cursor:pointer}
.cap-lib .cap-lib-h:hover{background:color-mix(in srgb,var(--accent-ink) 8%,transparent)}
.cap-lib .cap-lib-x{text-align:right;color:var(--text-faint)}
.cap-lib .cap-lib-d>td{padding:0 0 10px}
.cap-lib-tag{display:inline-block;font-size:10.5px;font-weight:var(--fw-bold);padding:1px 6px;border-radius:var(--radius-sm);margin-left:6px;white-space:nowrap}
.cap-lib-tag.err{color:var(--red);background:rgba(229,72,77,.14)}
.cap-lib-tag.warn{color:var(--amber);background:rgba(245,166,35,.14)}
.av-fl th:first-child{text-align:left;font-weight:var(--fw-semi);text-transform:none;letter-spacing:0;white-space:nowrap}
.av-fl td{text-align:right}
.av-fl-sub th{color:var(--text-faint);font-weight:var(--fw-normal);padding-left:14px}
.av-fl-sub td{color:var(--text-dim)}
.av-fl-tot{font-weight:var(--fw-bold);border-left:1px solid var(--border)}
.av-pie b{color:var(--text-dim)}
.av-err{color:var(--amber);font-size:12.5px;padding:8px 0}
@media(max-width:900px){ .av-grid{grid-template-columns:1fr} }
/* En el telefono si conviene que envuelva: deslizar de costado con el dedo dentro de una pagina que
   ya se desplaza para arriba y abajo pelea con el scroll de la pagina. */
@media(max-width:760px){ .fl-barra,.rc-tools{flex-wrap:wrap;overflow-x:visible} }   /* en pantalla chica, el numero y su nombre alcanzan */
/* PERO un grupo de solapas es UNA pieza y no se puede apilar: con la barra en `wrap` se quedaba
   de su ancho natural y se salía de la pantalla. En Fichas de zonas son 7 solapas = 691 px, y en
   un teléfono de 390 la última quedaba en x 622, inalcanzable. Se limita al ancho disponible y
   scrollea sola, que es lo que hace el resto del contenido ancho de la casa. */
@media(max-width:760px){ .fl-barra .sup-tabseg{max-width:100%;overflow-x:auto;overflow-y:hidden;-webkit-overflow-scrolling:touch} }
.tt-sec{font-size:12px;font-weight:var(--fw-black);text-transform:uppercase;letter-spacing:.08em;color:var(--text-faint);margin:18px 0 8px}
.tt-row{display:grid;grid-template-columns:1fr 62px 92px;gap:10px;align-items:center;padding:8px 10px;border-top:1px solid var(--border);font-size:12.5px}
.tt-row b{font-weight:var(--fw-bold)}
.tt-row .tt-n{text-align:right;font-family:"IBM Plex Mono";font-weight:var(--fw-bold)}
.tt-row .tt-d{text-align:right;color:var(--text-dim);font-size:12px}
.tt-tk{display:grid;grid-template-columns:88px 1fr 130px 92px;gap:10px;align-items:center;padding:8px 10px;border-top:1px solid var(--border);font-size:12.5px}
.tt-tk .tt-est{font-size:11px;font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:.04em;color:var(--text-dim)}
.tt-tk .tt-esp{text-align:right;font-family:"IBM Plex Mono";font-weight:var(--fw-bold)}
.tt-nota{font-size:12px;color:var(--text-dim);background:var(--surface);border:1px solid var(--border);
  border-radius:var(--radius);padding:11px 13px;margin-bottom:14px;line-height:1.5}

/* Notas plegadas. La explicación de «Qué es esto» está bien escrita pero se lee UNA vez, y ocupaba
   media pantalla cada vez que se entraba, empujando la tabla —que es a lo que la persona viene—
   abajo del pliegue. Ahora se ve el título y se abre a pedido; si alguien la abre, queda abierta
   para él. Las notas de una línea (el promedio de una caja, un aviso) NO se pliegan: esconder un
   dato detrás de un clic es peor que mostrarlo. */
.tt-nota.nota-plg,.seg-nota.nota-plg,.rep-nota.nota-plg,.cor-nota.nota-plg{padding:0;overflow:hidden;margin:0}
/* El renglón de «de cuándo es la medición», adentro de la explicación: apagado y separado del
   párrafo de arriba, porque es de otra cosa —no explica la pantalla, dice de cuándo es el dato—. */
.nota-medido{margin-top:10px;padding-top:9px;border-top:1px solid var(--border);
  font-size:12px;color:var(--text-faint)}
.nota-tog{display:flex;align-items:center;gap:8px;width:100%;padding:9px 13px;background:none;border:0;
  color:var(--text-dim);font-family:inherit;font-size:12px;font-weight:var(--fw-semi);text-align:left;cursor:pointer}
.nota-tog:hover{color:var(--text)}
.nota-tog .nota-chev{width:14px;height:14px;flex:0 0 auto;transition:transform .16s ease}
.nota-plg.on .nota-tog .nota-chev{transform:rotate(90deg)}
.nota-cuerpo{display:none;padding:0 13px 11px}
.nota-plg.on .nota-cuerpo{display:block}
/* Con el botón en la barra del título, la nota cerrada no ocupa NADA: es una fila entera de 35 px
   que se recupera en casi todas las pantallas. Abierta vuelve a su lugar, arriba del contenido. */
.nota-plg.nota-barra{display:none}
/* Las abre el único botón de la barra, todas juntas: el estado vive en el panel. */
/* LA EXPLICACIÓN FLOTA, NO EMPUJA. Abierta en el flujo, toda la pantalla se corría hacia abajo y
   al cerrarla volvía a subir: lo que uno estaba leyendo se movía solo. Ahora se abre encima,
   anclada arriba a la derecha —donde está el botón que la abre— y la estructura queda quieta.
   Es un texto que se lee una vez; no tiene por qué reacomodar la pantalla para siempre. */
.so-panel{position:relative}
.so-panel.notas-on .nota-plg.nota-barra{
  display:block; position:absolute; z-index:45; top:6px; right:16px;
  width:min(620px, calc(100% - 32px)); max-height:70vh; overflow:auto;
  padding:13px 15px; background:var(--surface); border:1px solid var(--border-strong);
  box-shadow:0 10px 30px -12px rgba(0,0,0,.45);
}
/* En el teléfono no hay «arriba a la derecha»: ocupa el ancho y se apoya arriba. */
@media(max-width:760px){
  .so-panel.notas-on .nota-plg.nota-barra{ left:8px; right:8px; width:auto; top:4px }
}
.so-panel.notas-on .nota-plg.nota-barra .nota-cuerpo{display:block;padding:0}
.so-panel.notas-on .nota-tog .nota-chev{transform:rotate(90deg)}
/* En la barra el botón es uno más entre los controles: no se estira ni se lleva el renglón. */
.so-panel-bar .nota-tog{width:auto;flex:0 0 auto;padding:5px 10px;border:1px solid var(--border);
  border-radius:var(--radius);background:var(--surface-2);font-size:12px;margin-left:auto}
.so-panel-bar .nota-tog:hover{border-color:var(--accent-ink);color:var(--text)}
/* DOS márgenes automáticos en la misma fila SE REPARTEN el espacio sobrante. `.pf-wrap` —el grupo de
   controles— ya trae el suyo, así que con los dos el botón «Qué es esto» empujaba los controles al
   MEDIO de la barra y se quedaba solo contra la derecha. Cuando hay controles, el que se pega a la
   derecha es el grupo entero y «Qué es esto» va al lado, no separado media pantalla. */
.so-panel-bar .pf-wrap ~ .nota-tog{margin-left:8px}
/* Si además hay buscador, el que se pega a la derecha es el buscador y el botón queda antes. */
.so-panel-bar .nota-tog + .help-search,.so-panel-bar .nota-tog ~ .help-search{margin-left:10px}
@media(max-width:760px){ .tt-row{grid-template-columns:1fr 54px 78px} .tt-tk{grid-template-columns:1fr 90px;row-gap:2px} }

/* En el celular el panel de cercanas no puede taparle el mapa a los caminos que acabamos de dibujar. */
@media(max-width:760px){
  #cmNearSheet .cm-near-card{max-height:44vh;display:flex;flex-direction:column}
  #cmNearSheet .cm-near-list{overflow-y:auto;min-height:0}
}
.cm-near-row .cm-near-calle{font-size:11px;color:var(--text-faint);display:block;font-weight:var(--fw-semi)}

/* La lista de cajas cercanas se achica a una barra para poder mirar el mapa sin perder los metros. */
#cmNearSheet.mini .cm-near-list,#cmNearSheet.mini .cm-near-sub{display:none}
#cmNearSheet.mini .cm-near-card{padding-bottom:10px}
.cm-near-mini{display:none;align-items:center;gap:10px;font-size:13.5px;color:var(--text)}
#cmNearSheet.mini .cm-near-mini{display:flex}
/* Achicada, el título largo partía en dos líneas y apretaba todo: queda sólo el pin. */
#cmNearSheet.mini .cm-near-h{gap:8px;align-items:center}
#cmNearSheet.mini .cm-near-h b{font-size:0}
#cmNearSheet.mini .cm-near-h b:first-letter{font-size:16px}
#cmNearSheet.mini .cm-near-mini{flex:1;min-width:0;white-space:nowrap;overflow:hidden}
#cmNearSheet.mini .cm-near-mini small{overflow:hidden;text-overflow:ellipsis}
.cm-near-mini b{font-weight:var(--fw-black)}
.cm-near-mini small{color:var(--text-faint);font-size:12px}
.cm-near-toggle{margin-left:auto;background:transparent;border:1px solid var(--border);border-radius:var(--radius);
  color:var(--text-dim);padding:6px 12px;font-size:12.5px;cursor:pointer;font-family:inherit}
.cm-near-toggle:hover{color:var(--text);border-color:var(--accent-ink)}

/* Camino desde mi ubicación hasta las cajas más cercanas */
.cm-ruta-lbl{background:#151922;border:1px solid var(--border);border-radius:var(--radius-sm);padding:2px 7px;
  font-family:'IBM Plex Mono';font-size:11px;font-weight:var(--fw-bold);color:#fff;white-space:nowrap;
  box-shadow:0 3px 10px rgba(0,0,0,.55)}
.cm-ruta-lbl.n1{border-color:#2ecc71;color:var(--green)}
.cm-ruta-lbl.n2{border-color:#f5a623;color:var(--amber)}
.cm-ruta-lbl.n3{border-color:#7ab0ff;color:#7ab0ff}
.cm-ruta-aviso{position:absolute;left:50%;transform:translateX(-50%);bottom:14px;z-index:900;
  background:#151922;border:1px solid var(--border);border-radius:var(--radius);padding:6px 12px;
  font-size:12px;color:var(--text-dim);box-shadow:0 6px 18px rgba(0,0,0,.5);pointer-events:none}

/* ===== Menú lateral: estructura común =====
   Vale para la barra del navegador y para el cajón del celular. Antes esto vivía sólo en el bloque
   de escritorio y en el celular los íconos salían a tamaño natural (enormes). */
#sideNav .sn-find{position:relative;flex:0 0 auto;margin:0 2px 10px}
#sideNav .sn-find input{width:100%;box-sizing:border-box;background:var(--surface-2);border:1px solid var(--border);
  border-radius:var(--radius);color:var(--text);padding:10px 10px 10px 34px;font-size:13.5px;font-family:inherit;outline:none}
#sideNav .sn-find input::placeholder{color:var(--text-faint)}
#sideNav .sn-find input:focus{border-color:var(--accent-ink)}
#sideNav .sn-find svg{position:absolute;left:11px;top:50%;transform:translateY(-50%);
  width:16px;height:16px;color:var(--text-faint);pointer-events:none}
/* «Estás acá»: la línea fija que dice en qué pantalla estás sin que el menú se reacomode.
   Va en el bloque COMÚN a propósito —no en el de escritorio— porque el cajón del celular usa el
   mismo menú: meterla en el media query es el error que ya se cometió con la lupa y las flechas,
   que en el celular salían a tamaño natural.
   No se muestra en el riel: ahí se ven los 36 destinos y el marcado ya se distingue solo. */
#sideNav .sn-aqui{display:flex;align-items:center;gap:5px;width:100%;box-sizing:border-box;
  margin:0 2px 10px;padding:7px 9px;border:1px solid var(--border);border-radius:var(--radius);
  background:color-mix(in srgb,var(--signal) 10%,transparent);color:var(--accent-ink);
  font-family:inherit;font-size:12.5px;text-align:left;cursor:pointer;overflow:hidden}
#sideNav .sn-aqui:hover{background:color-mix(in srgb,var(--signal) 18%,transparent)}
#sideNav .sn-aqui svg{width:13px;height:13px;flex:0 0 auto;opacity:.75}
#sideNav .sn-aqui .sa-g{color:var(--text-dim);text-transform:uppercase;letter-spacing:.4px;font-size:11px;flex:0 0 auto}
#sideNav .sn-aqui .sa-sep{color:var(--text-faint);flex:0 0 auto}
#sideNav .sn-aqui b{font-weight:var(--fw-semi);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
body.nav-rail:not(.nav-peek) #sideNav .sn-aqui{display:none}
#sideNav .sn-group{display:flex;align-items:center;gap:6px;width:100%;background:transparent;border:0;cursor:pointer;text-align:left}
#sideNav .sn-group .sn-chev{margin-left:auto;width:15px;height:15px;flex:0 0 auto;transition:transform .16s ease;opacity:.7}
#sideNav .sn-g.open .sn-group .sn-chev{transform:rotate(90deg)}
#sideNav .sn-items{display:none;flex-direction:column;gap:2px}
#sideNav .sn-g.open .sn-items{display:flex}
#sideNav .sn-toggle svg{width:16px;height:16px;flex:0 0 auto}
#sideNav .sn-item small{display:block;font-size:11px;font-weight:var(--fw-semi);color:var(--text-faint);
  text-transform:uppercase;letter-spacing:.06em;margin-top:1px}
#sideNav .sn-item .sn-txt{min-width:0}
#sideNav .sn-nada{padding:16px 10px;font-size:12.5px;color:var(--text-faint);text-align:center}

/* ===== Celular: tamaño de toque y de letra =====
   Medido en un teléfono de 412 px: todo lo que se toca pasa a 34 px de alto como mínimo y ningún
   texto baja de 11 px. No cambia nada en el navegador. */
@media(max-width:760px){
  /* pestañas y botones de barra */
  .sup-tab,.zn-mbtn,.onu-fb,#vistaSwitch button,.view-switch button,.vs-btn{min-height:36px}
  .zn-item-edit{min-width:36px;min-height:36px}
  .col-collapse{min-width:34px;min-height:34px}
  /* filas que se tocan para abrir algo */
  .nov-row,.nov-zrow,.nov-clk{min-height:38px}
  .dbt-row{min-height:38px}
  /* encabezados de tabla: además de tocarse para ordenar, hay que poder leerlos */
  .db-th{min-height:34px;font-size:12px}
  /* casillas de tildar: 15px es imposible de acertar con el dedo */
  input[type="checkbox"],input[type="radio"]{min-width:22px;min-height:22px}
  /* nada por debajo de 11px */
  #sideNav .sn-group{font-size:12px}
  .tipo-chip,.ic-chip,.hs-sub,.nov-bad,.nov-alta-est,.grupo-chip,.proj-chip{font-size:11px}
  .cm-boc,small{font-size:11px}
  /* últimos tres: los filtros de período de Soporte, las casillas de Stock y el subtítulo de Ayuda */
  .sup-range button,.cap-filter button{min-height:36px;padding-left:12px;padding-right:12px}
  input[type="checkbox"],input[type="radio"]{min-width:26px;min-height:26px}
  .hstep .hs-sub,.hs-sub{font-size:11px}
}
/* --- Ventana de la caja: la señal primero --- */
/* Pin de la ubicación: objetivo de toque cómodo (32px) sin ocupar una línea de texto. */
.cm-datos-geo{margin-left:auto;display:inline-flex}
.cm-pop-meta .cm-geo-ic{display:inline-grid;place-items:center;width:32px;height:32px;border-radius:var(--radius);
  background:color-mix(in srgb,var(--accent-ink) 16%,transparent);color:var(--accent-ink);
  border:1px solid color-mix(in srgb,var(--accent-ink) 34%,transparent);text-decoration:none;padding:0}
.cm-pop-meta .cm-geo-ic:hover{background:color-mix(in srgb,var(--accent-ink) 28%,transparent)}
.cm-pop-meta .cm-geo-ic svg{width:17px;height:17px}
.cm-sin-geo{color:var(--text-faint);font-size:11px}
/* en el celular, más grande todavía: se toca con el dedo */
@media(max-width:760px){ .cm-pop-meta .cm-geo-ic{width:40px;height:40px} .cm-pop-meta .cm-geo-ic svg{width:20px;height:20px} }
/* Lista de clientes en una sola columna. Con muchos, scrollea adentro y el encabezado queda fijo. */
.cm-clicols{display:block}
.cm-clicols .cm-cltab{width:100%}
.cm-cli-scroll{max-height:min(46vh,340px);overflow-y:auto;overflow-x:hidden;border:1px solid var(--border);border-radius:var(--radius)}
.cm-cli-scroll .cm-cltab thead th{position:sticky;top:0;z-index:1;background:var(--surface-2)}
/* Línea de datos de la caja: un solo renglón parejo. Cada dato no se parte por la mitad. */
.cm-datos>span{white-space:nowrap}
.cm-pop-meta .cm-datos{align-items:baseline;row-gap:5px}
.cm-pop-meta .cm-datos .cm-boc{display:inline;font-size:11px;color:var(--text-faint);font-weight:var(--fw-medium)}
.cm-pop-meta .cm-datos .cm-geo{align-self:baseline}
/* Los bloques nuevos traen su propia estructura: se los saca de la maqueta vieja de la ficha. */
.cm-pop-meta>.cm-sig-box{display:block;justify-content:initial;gap:0;font-size:12.5px}
.cm-pop-meta>.cm-datos{justify-content:flex-start;font-size:12px}
.cm-pop-meta .cm-sig-leg span,.cm-pop-meta .cm-datos span{color:inherit;font-size:inherit}
.cm-pop-meta .cm-sig-kpis span{color:var(--text-faint);font-size:10px}
.cm-pop-meta .cm-sig-box b,.cm-pop-meta .cm-datos b{text-align:left;font-size:inherit}
.cm-pop-meta .cm-sig-kpis b{font-size:13.5px}
.cm-pop-meta .cm-sig-n{font-size:27px}
.cm-pop-meta .cm-sig-n small{font-size:12.5px;color:var(--text-dim)}
.cm-pop-meta .cm-sig-seg{flex:0 0 auto}   /* si no, los tramos vacíos se encogen a cero */
/* El contenedor ya no reparte en columnas: el contenido trae su propia estructura. */
.cm-pop-meta{display:block;grid-template-columns:none;gap:0;padding:0;border:0;margin:0}
/* Las coordenadas son un dato de consulta: enlace discreto, no un botón que compita con la señal. */
.cm-datos .cm-geo{background:transparent;color:var(--accent-ink);padding:0;border-radius:0;font-size:12px;font-weight:var(--fw-semi)}
.cm-sig-box{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:12px 14px;margin:10px 0}
.cm-sig-top{display:flex;align-items:flex-end;gap:14px;flex-wrap:wrap}
.cm-sig-n{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:27px;line-height:1;letter-spacing:-.5px}
.cm-sig-n small{font-family:inherit;font-weight:var(--fw-bold);font-size:12.5px;color:var(--text-dim);margin-left:5px;letter-spacing:0}
.cm-sig-kpis{display:flex;gap:16px;margin-left:auto;text-align:right}
.cm-sig-kpis div{display:flex;flex-direction:column;gap:2px}
/* La hora de la señal va pegada al rótulo y en chico: es una aclaración del
   número que está abajo, no un dato aparte que compita con él. */
.cm-sig-edad{font-size:9.5px;opacity:.8;white-space:nowrap}
.cm-sig-edad::before{content:'· '}
.cm-sig-kpis span{font-size:10px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-faint);font-weight:var(--fw-bold)}
.cm-sig-kpis b{font-family:'IBM Plex Mono';font-size:13.5px;font-weight:var(--fw-bold)}
.cm-sig-bar{display:flex;height:9px;border-radius:var(--radius-sm);overflow:hidden;margin-top:11px;background:var(--surface-2);border:1px solid var(--border)}
.cm-sig-seg{height:100%}
.cm-sig-leg{display:flex;gap:14px;flex-wrap:wrap;margin-top:8px;font-size:11px;color:var(--text-dim)}
.cm-sig-leg i{display:inline-block;width:8px;height:8px;border-radius:var(--radius-xs);margin-right:5px;vertical-align:middle}
/* la columna de señal, destacada: es el dato que se mira de reojo */
.cm-cltab td.cm-sig{font-family:'IBM Plex Mono';font-size:13.5px;font-weight:var(--fw-bold);text-align:right;white-space:nowrap}
.cm-cltab td.cm-sig.cm-off{color:var(--red)}
.cm-cambio{display:inline-block;margin-left:6px;padding:1px 6px;border-radius:var(--radius-sm);font-size:10px;font-weight:var(--fw-black);
  text-transform:uppercase;letter-spacing:.05em;font-family:inherit}
.cm-cambio.volvio{background:rgba(46,204,113,.18);color:var(--green)}
.cm-cambio.cayo{background:rgba(229,72,77,.18);color:var(--red)}
/* datos de la caja: pie compacto, para consultar */
.cm-datos{display:flex;flex-wrap:wrap;gap:0 18px;align-items:center;margin-top:10px;padding-top:10px;
  border-top:1px solid var(--border);font-size:12px;color:var(--text-dim)}
.cm-datos b{color:var(--text);font-weight:var(--fw-bold)}
.cm-datos .cm-geo{display:inline-flex;align-items:center;gap:5px;color:var(--accent-ink);text-decoration:none}
.cm-datos .cm-geo svg{width:13px;height:13px}
.cm-datos .cm-geo:hover{text-decoration:underline}
.cm-datos .cm-boc{color:var(--text-faint)}
.cm-motivo{display:flex;align-items:center;gap:7px;font-size:12px;font-weight:var(--fw-bold);padding:7px 10px;border-radius:var(--radius);margin:0 0 8px;line-height:1.35}
.cm-caida-pulse{width:14px;height:14px;border-radius:var(--radius-circ);background:#e5484d;border:2px solid #fff;animation:cmpulse 1.4s infinite}
@media(prefers-reduced-motion:reduce){.cm-caida-pulse{animation:none}}
.leaflet-tooltip.cm-clbl{background:rgba(18,24,32,.86);color:#fff;border:0;font-size:10px;font-weight:var(--fw-semi);padding:1px 5px;box-shadow:none;white-space:nowrap}
.leaflet-tooltip.cm-clbl:before{display:none}
.leaflet-tooltip.cm-clbl-caida{background:#e5484d;color:#fff;font-weight:var(--fw-bold)}
.cm-clbl-clk{cursor:pointer}
@media(max-width:760px){ .cm-clbl{font-size:11px;padding:3px 7px}   /* etiqueta un poco más grande = mejor blanco para el dedo */ }
.cm-optf{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--text-faint)}
.cm-optf .sel{font-size:12px;padding:3px 6px;height:auto}
.cm-cl-ic{background:none;border:0}
.cm-cl{display:flex;flex-direction:column;align-items:center;justify-content:center;border-radius:var(--radius-circ);background:color-mix(in srgb,var(--cl) 82%,#0b0f14);border:2px solid var(--cl);color:#fff;box-shadow:0 2px 8px rgba(0,0,0,.35);line-height:1}
.cm-cl b{font-size:12.5px;font-weight:var(--fw-black)}
.cm-cl i{font-style:normal;font-size:10px;opacity:.95}
/* ===== LA BARRA DE HERRAMIENTAS DEL PANEL =====
   Cuatro casillas y un desplegable sueltos sobre el fondo se leían como parte de
   la lista. Enmarcados se entienden como lo que son: los controles de lo que se
   ve en el mapa, no contenido. */
.cm-listtools{margin:0 0 12px;padding:8px 10px;background:var(--surface-2);
  border:1px solid var(--border);border-radius:var(--radius);row-gap:8px}
.cm-zchk{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--text-dim);cursor:pointer;white-space:nowrap}
.cm-zchk:hover{color:var(--text)}
.cm-optf{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--text-dim)}
/* Cuando hay tantas cajas a la vista que los nombres se taparían entre sí, se
   ocultan — y se dice por qué. Sin esto uno prende la casilla, no ve ningún
   nombre y concluye que está rota. */
.cm-names-aviso{flex:1 1 100%;font-size:11px;color:var(--text-faint);line-height:1.4}
.cm-names-aviso:empty{display:none}

/* ===== LOS TÍTULOS DE SECCIÓN =====
   No tenían estilo propio: la explicación entre paréntesis pesaba igual que el
   contenido y se comía tres o cuatro renglones por sección. Ahora el título y su
   cuenta van en una línea, la explicación abajo en tono menor, y una regla marca
   dónde empieza cada bloque — el mismo recurso que usan las tablas del sistema.
   LA EXPLICACIÓN NO SE SACA: en estas pantallas el criterio con el que se arma
   una lista es la mitad del dato. Se subordina, que no es lo mismo que esconder. */
#cmList h4{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  margin:0 0 8px;padding:0 0 6px;border-bottom:1px solid var(--border);
  font-size:12.5px;font-weight:var(--fw-semi);color:var(--text);line-height:1.35}
#cmList h4 small{flex:1 1 100%;font-size:11px;font-weight:var(--fw-normal);
  color:var(--text-faint);line-height:1.45;margin-top:1px}
#cmList h4+*{margin-top:0}
/* Entre secciones, aire de verdad: pegadas se leen como una sola lista larga. */
#cmList h4:not(:first-of-type){margin-top:20px}
.cm-zchk{font-size:12px;color:var(--text-dim);display:inline-flex;align-items:center;gap:6px;cursor:pointer}
.kpi-clk{cursor:pointer}.kpi-clk:hover{background:color-mix(in srgb,var(--accent-ink) 9%,transparent);border-radius:var(--radius)}
.cm-upd{font-size:12px;color:var(--text-faint)}
.cm-find{padding:5px 9px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2);color:var(--text);font-size:12.5px;flex:0 1 190px;min-width:0}
.cm-refbtn{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
.cm-refbtn .cm-upd{font-size:11px;color:var(--text-faint);font-weight:var(--fw-normal)}
@media(max-width:760px){
  /* En Mapas el selector es un desplegable en la barra superior (sin barra fija) → sin padding-top. Oculto el título redundante del panel y dejo solo el buscador/Actualizar → gano espacio para el mapa */
  #cajasWrap .so-panel-bar{padding:6px 10px;gap:6px;border-bottom:0}
  #cajasWrap .so-panel-bar .so-bar-ic,#cajasWrap .so-panel-bar h3,#cajasWrap .so-panel-bar .so-count{display:none}
  #cajasWrap .sup-tools{width:100%;margin:0;gap:6px;justify-content:flex-start;flex-wrap:nowrap}
  #cmBody .cap-kpis{display:grid;grid-template-columns:1fr 1fr;gap:8px;padding:6px 10px 2px}   /* los 2 KPIs ocupan medio y medio (todo el ancho) */
  #cmBody .cap-kpis .kpi{padding:8px 12px;border-radius:var(--radius);min-width:0}
  #cmBody .cap-kpis .k-num{font-size:17px;margin-top:1px}
  #cmBody{display:block;overflow:auto}   /* en el cel el cuerpo scrollea normal (mapa arriba + lista abajo) */
  .cm-cols{display:grid;grid-template-columns:1fr;grid-template-rows:none;padding:6px 8px 10px}
  .cm-map{height:64vh;min-height:340px;order:-1}   /* mapa PRIMERO y lo más grande posible en el celular */
  .cm-list{max-height:220px}
  .cm-find{min-width:0;flex:1 1 auto;padding:13px 13px;font-size:15px;border-radius:var(--radius)}   /* el buscador crece para llenar el ancho, con el botón al lado; más alto (tamaño KPI) */
  .cm-refbtn{flex:0 0 auto;padding:13px 16px;border-radius:var(--radius);font-size:12.5px}
}
.sup-hot{width:28px;height:28px;border-radius:var(--radius-circ);background:#e5484d;color:#fff;font-weight:var(--fw-bold);font-size:13.5px;display:flex;align-items:center;justify-content:center;border:2px solid #fff;box-shadow:0 1px 5px rgba(0,0,0,.55)}
.leaflet-tooltip.sup-hot-tip{background:#e5484d;color:#fff;border:0;font-weight:var(--fw-semi);font-size:11px;padding:2px 7px;white-space:nowrap;box-shadow:0 1px 4px rgba(0,0,0,.4)}
.leaflet-tooltip.sup-hot-tip:before{border-top-color:#e5484d}
@media(max-width:760px){
  .sup-cols{grid-template-columns:1fr}
  .sup-bar{grid-template-columns:minmax(72px,44%) 1fr 40px}
  .sup-tools{width:100%} .sup-range{flex-wrap:wrap} .sup-tk-find{width:100%;margin-left:0}
  /* En 126 px no entran 364 de texto: los puntos suspensivos se comían el chip de causa probable,
     que es el dato que esta pantalla agrega. En el teléfono la etiqueta usa el renglón completo y
     la barra con su número quedan abajo. */
  .sup-bar{grid-template-columns:1fr 40px;grid-template-areas:"l l" "b n";row-gap:2px}
  .sup-bar-l{grid-area:l;white-space:normal;overflow:visible;text-overflow:clip;line-height:1.3}
  /* Las clases reales son .sup-bar-l (etiqueta) y .sup-bar-t (la barra); el número es el último
     hijo y no tiene clase. Nombrarlas mal funcionaba igual por acomodo automático, pero eso se
     rompe solo el día que alguien cambie el orden. */
  .sup-bar-t{grid-area:b}
  .sup-bar > :last-child{grid-area:n}
}
/* zona clickeable → ver ONT malas */
.sig-list .occ-row.sig-zrow{grid-template-columns:minmax(0,1.1fr) minmax(0,1.1fr) 132px 14px;cursor:pointer;border-radius:var(--radius)}
.sig-zrow:hover{background:color-mix(in srgb,var(--red) 9%,transparent)}
.sig-zchev{color:var(--red);font-weight:var(--fw-black);font-size:17px;line-height:1;text-align:right}
.sigz-g{border:1px solid var(--border);border-radius:var(--radius);margin-bottom:10px;overflow:hidden}
.sigz-gh{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:9px 11px;background:var(--surface-2);border-bottom:1px solid var(--border);font-size:13.5px}
.sigz-gh .occ-port{margin-left:auto}
.sigz-ont{display:flex;flex-direction:column;gap:3px;padding:8px 11px;border-bottom:1px solid var(--border)}
.sigz-ont:last-child{border-bottom:0}
.sigz-ont-top{display:flex;align-items:center;gap:10px}
.sigz-ont-top .db-serial{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.sigz-rx{margin-left:auto;flex:0 0 auto;font-variant-numeric:tabular-nums}
.sigz-cli{font-size:12.5px;min-width:0;line-height:1.55}
.sigz-cli-l{color:var(--text-faint);font-style:italic}
.sigz-clilink{color:var(--accent-ink);font-weight:var(--fw-bold);text-decoration:none;white-space:nowrap}
.sigz-clilink:hover{text-decoration:underline}
.sigz-nom{color:var(--text);font-weight:var(--fw-semi)}
.sigz-caja{display:inline-block;background:color-mix(in srgb,var(--accent-ink) 15%,transparent);color:var(--accent-ink);border-radius:var(--radius-sm);padding:0 7px;font-weight:var(--fw-bold);font-size:12px;white-space:nowrap}
.sigz-caja small{opacity:.7;font-weight:var(--fw-semi)}
.sigz-caja-line{margin-top:2px;display:flex;flex-wrap:wrap;align-items:center;gap:6px}
.sigz-verdict{font-size:11px;font-weight:var(--fw-bold);border-radius:var(--radius-sm);padding:1px 7px;white-space:nowrap}
.sigz-verdict.caja{background:color-mix(in srgb,var(--red) 17%,transparent);color:var(--red)}
.sigz-verdict.cli{background:color-mix(in srgb,var(--green) 16%,transparent);color:var(--green)}
.sigz-verdict.mid{background:color-mix(in srgb,var(--amber) 15%,transparent);color:var(--amber)}
.sigz-cli-none{color:var(--text-faint);font-size:12px}
.sigz-more{color:var(--text-dim)}
@media(max-width:560px){
  .sig-list .occ-row{grid-template-columns:minmax(0,1fr) auto;gap:3px 10px}
  /* Con la misma cuenta de clases que la regla de escritorio, si no aquella gana y el teléfono
     se queda con cuatro columnas en 286 px. La flechita de 14 px se conserva. */
  .sig-list .occ-row.sig-zrow{grid-template-columns:minmax(0,1fr) auto 14px}
  .sig-dist{display:none}
  /* Y el nombre se deja envolver: «GPON 0/0/1 · ZONA 1 · peor -30 dBm» necesita 206 px y la celda
     tiene 150, así que los puntos suspensivos se comían justo el peor dBm — el dato por el que uno
     abre esta pantalla. Mejor dos renglones que un dato escondido. */
  .sig-list .occ-olt{white-space:normal;overflow:visible;text-overflow:clip;line-height:1.3}
}
.alt-sn2{font-family:'IBM Plex Mono',monospace;font-size:11px;color:var(--text-faint)}
.alt-vd{font-size:11px;color:var(--text-faint);border:1px solid var(--border);border-radius:var(--radius-sm);padding:0 5px;align-self:flex-start}
.alt-olt{font-weight:var(--fw-bold)}
.alt-banner{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin:0 0 12px;font-size:12.5px}
.alt-pill{display:inline-flex;align-items:center;gap:6px;border-radius:var(--radius-sm);padding:3px 11px;font-weight:var(--fw-bold);font-size:12px}
.alt-pill.has{background:color-mix(in srgb,var(--amber) 18%,transparent);color:var(--amber)}
.alt-pill.none{background:color-mix(in srgb,var(--green) 16%,transparent);color:var(--green)}
/* Aviso de identificación por parecido: no confirmado por serial. */
.alt-prob{display:inline-block;margin-left:6px;padding:1px 6px;border-radius:var(--radius-sm);font-size:10px;font-weight:var(--fw-black);
  text-transform:uppercase;letter-spacing:.04em;background:color-mix(in srgb,var(--amber) 22%,transparent);
  color:var(--amber);border:1px solid color-mix(in srgb,var(--amber) 45%,transparent);cursor:help}
/* Historial de equipos que pidieron alta. */
/* Ubicar por distancia: la lista de cajas candidatas y las marcas de confianza. */
.dbt-ss{grid-template-columns:112px 96px 92px minmax(0,1.5fr) 168px minmax(0,1.45fr) 132px}
@media(max-width:1100px){ .dbt-ss{grid-template-columns:104px 88px 88px minmax(0,1.3fr) 150px minmax(0,1.2fr) 120px} }
.dbt-row.dbt-ss>*{flex-direction:column;align-items:flex-start;justify-content:center;gap:1px;padding-top:6px;padding-bottom:6px}
.dbt-row.dbt-ss>.r{align-items:flex-end}
.dbt-row.dbt-ss>*>*{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.ss-n{font-variant-numeric:tabular-nums}
.ss-n b{font-size:13.5px}
.ss-n small{color:var(--text-faint);font-size:11px}
.ss-sec{color:var(--text-faint);font-size:12px}
.ss-dir{display:block;font-size:11px;color:var(--text-faint)}
.ss-est{font-size:11px;padding:1px 7px;border-radius:var(--radius);background:var(--surface-3);color:var(--text-dim);white-space:nowrap}
/* La franja de la izquierda dice de un vistazo si el numero se explica con WhatsApp o no. */
/* La franja de la izquierda dice de un vistazo si el numero se explica con WhatsApp o no. */
.dbt-row.ss-alto>*:first-child{box-shadow:inset 3px 0 0 var(--red)}
.dbt-row.ss-medio>*:first-child{box-shadow:inset 3px 0 0 var(--amber)}
.dbt-row.ss-bajo>*:first-child{box-shadow:inset 3px 0 0 var(--border)}
.dbt-row.ss-alto .ss-n b{color:var(--red)}
.dbt-row.ss-medio .ss-n b{color:var(--amber)}
.vlbl{font-size:11px;color:var(--text-faint);align-self:center;padding:0 8px 0 2px}
.ub-aviso-i{color:var(--amber)}
.tt-nota-abierta{margin:0 0 12px}
.ub-duenos{grid-column:1/-1;margin-top:8px;padding-top:8px;border-top:1px solid var(--border)}
.ub-duenos.floja{opacity:.75}
/* CENTRADO Y NO POR BASELINE: la barra de color de la izquierda ocupa todo el alto y el texto
   apoyado en la línea de base quedaba corrido respecto de ella. Mismo arreglo que el aviso de «La
   red ahora». */
.ub-d{display:flex;flex-wrap:wrap;align-items:center;gap:3px 8px;padding:6px 9px;margin-top:5px;border-radius:var(--radius-sm);background:var(--surface);border-left:3px solid var(--border);font-size:12.5px}
.ub-d.fuerte{border-left-color:var(--green)}
.ub-d .ub-eq i{font-style:normal;color:var(--amber)}
.ub-d b{font-variant-numeric:tabular-nums}
.ub-d a{color:var(--link);text-decoration:none}
.ub-d a:hover{text-decoration:underline}
.ub-d span{flex:1 1 100%;font-size:12px;color:var(--text-faint)}
.ub-d .ub-eq{color:var(--text-dim)}
.ub-aviso{margin-top:6px;font-size:12px;color:var(--amber)}
.ub-cand{margin:4px 0 0;padding-left:20px}
.ub-cand li{margin:3px 0;font-size:12.5px}
.ub-cand li span{display:block;font-size:12px;color:var(--text-faint)}
/* La que además coincide con el vecino de ONT-ID: son dos indicios independientes de acuerdo. */
.ub-cand li.coincide b{color:var(--green)}
.ub-cand li.coincide::marker{color:var(--green)}
.ub-m{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:12.5px;color:var(--accent-ink);margin-left:auto}
.ub-firme{font-size:11px;font-weight:var(--fw-black);text-transform:uppercase;letter-spacing:.05em;
  background:color-mix(in srgb,var(--green) 20%,transparent);color:var(--green);
  padding:2px 7px;border-radius:var(--radius-sm);margin-left:8px}
.ub-falta{font-size:12.5px;color:var(--text-dim);display:flex;align-items:center;gap:10px;flex-wrap:wrap}
/* Cuando el parque sabe de quien es el equipo huerfano: no hay que salir a buscarlo, hay que
   cargarlo. Se destaca porque cambia la accion. */
.eq-parque{background:color-mix(in srgb,var(--green) 10%,transparent);border-left:3px solid var(--green);
  border-radius:var(--radius);padding:8px 11px;margin:2px 0 8px;font-size:12.5px;color:var(--text-dim)}
.eq-parque b{color:var(--text)}
.afh{margin-top:18px}
.afh-h{display:flex;align-items:center;gap:9px;font-size:12px;font-weight:var(--fw-black);text-transform:uppercase;
  letter-spacing:.08em;color:var(--text-faint);padding:0 2px 8px}
.afh-h .afh-raros{margin-left:auto;text-transform:none;letter-spacing:0;font-weight:var(--fw-bold)}
.afh-row{display:grid;grid-template-columns:78px 62px 1fr 1fr 96px 96px;gap:8px;align-items:center;
  padding:7px 9px;border-top:1px solid var(--border);font-size:12.5px}
.afh-row.raro{background:color-mix(in srgb,var(--amber) 8%,transparent)}
.afh-row small{color:var(--text-faint);font-size:11px}
.afh-row b{font-weight:var(--fw-bold)}
/* La etiqueta de «para revisar» es un botón: filtra el historial. Se le nota que se puede tocar y
   se le nota cuando está puesto, que si no el que llega ve una lista corta y cree que es todo. */
.afh-filtro{cursor:pointer;border:1px solid transparent;font-family:inherit}
.afh-filtro:hover{border-color:var(--amber)}
.afh-filtro.on{background:var(--amber);color:#1a1200}
.afh-aclara{font-size:12px;color:var(--text-dim);padding:8px 10px;margin:0 0 6px;
  background:color-mix(in srgb,var(--amber) 9%,transparent);border-radius:var(--radius)}
.afh-aclara b{color:var(--text)}
.afh-tag{display:inline-block;padding:1px 6px;border-radius:var(--radius-sm);font-size:10px;font-weight:var(--fw-black);
  background:color-mix(in srgb,var(--amber) 22%,transparent);color:var(--amber)}
@media(max-width:760px){ .afh-row{grid-template-columns:1fr 1fr;row-gap:3px} }
.alt-errs{font-size:12px;color:var(--text-faint);margin-top:10px}
.olt-tabs{display:flex;gap:6px;flex-wrap:wrap}
.so-navlabel{font-size:10px;text-transform:uppercase;letter-spacing:.1em;color:var(--text-faint);font-weight:var(--fw-bold);padding:12px 12px 4px}
.so-navi-chev{margin-left:auto;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;opacity:.55;transition:transform .15s}
.so-navi-chev svg{width:15px;height:15px}
.so-navi-toggle.open .so-navi-chev{transform:rotate(90deg)}
.so-navlist{display:flex;flex-direction:column;gap:3px;overflow:hidden}
.so-navlist.collapsed{display:none}
.so-navlist .so-navi{padding-left:22px}
.so-wrap.so-collapsed .so-navi-chev,.so-wrap.so-collapsed .so-navlist .so-navi{padding-left:0}
.so-wrap.so-collapsed .so-navi-chev{display:none}
.dash-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:12px;margin-bottom:8px}
.dash-card{text-align:left;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:14px 16px;cursor:pointer;font-family:inherit;color:var(--text);transition:.12s;display:flex;flex-direction:column;gap:6px}
.dash-card:hover{border-color:var(--accent-ink);background:color-mix(in srgb,var(--signal) 6%,var(--surface))}
.dash-card.down{border-color:color-mix(in srgb,var(--red) 45%,var(--border))}
.dash-card-h{display:flex;align-items:center;justify-content:space-between;gap:8px}
.dash-card-h b{font-size:13.5px;font-weight:var(--fw-black)}
.dash-st{font-size:11px;color:var(--text-dim);display:inline-flex;align-items:center;gap:4px;white-space:nowrap}
.dash-dot{width:8px;height:8px;border-radius:var(--radius-circ);display:inline-block}
.dash-dot.ok{background:var(--green)} .dash-dot.bad{background:var(--red)} .dash-dot.off{background:var(--text-faint);opacity:.5}
.dash-card-n{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:27px;line-height:1;color:var(--accent-ink);display:flex;align-items:baseline;gap:7px}
.dash-card-n span{font-size:11px;font-weight:var(--fw-semi);color:var(--text-faint)}
.dash-card-f{font-size:11px;color:var(--text-faint)}
.dash-card-cpu{display:flex;align-items:baseline;gap:6px;font-size:11px;color:var(--text-faint);text-transform:uppercase;letter-spacing:.04em}
.dash-card-cpu b{font-family:'IBM Plex Sans';font-size:19px;font-weight:var(--fw-bold);letter-spacing:0;color:var(--accent-ink)}
.dash-card-cpu b small{font-size:11px;font-weight:var(--fw-semi);color:var(--text-faint)}
.dash-card-cpu b.err{color:var(--red)} .dash-card-cpu b.warn{color:var(--amber)}
.dash-alerts{display:flex;flex-direction:column;gap:3px}
.dash-alcols{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:14px}
.dash-albox{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:14px 16px}
.dash-albox-h{font-size:12.5px;font-weight:var(--fw-black);letter-spacing:.02em;color:var(--text);display:flex;align-items:center;gap:8px}
.olt-alhist{margin-left:auto;font-size:12px;font-weight:var(--fw-bold);color:var(--accent-ink);background:none;border:none;cursor:pointer;padding:2px 4px;flex:0 0 auto}
.olt-alhist:hover{text-decoration:underline}
.alh-count{font-family:'IBM Plex Mono';font-size:12px;color:var(--text-faint);margin-bottom:10px}
.dash-alsub{font-size:12px;color:var(--text-faint);margin:3px 0 10px;line-height:1.45}
.olt-albox{border-bottom:1px solid var(--border);background:var(--surface-2);padding:8px 16px;max-height:150px;overflow:auto}
.olt-alh{font-size:11px;font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:.04em;color:var(--text-faint);display:block;margin-bottom:4px}
.olt-alsub{font-size:12px;color:var(--text-faint)}
.olt-al{display:flex;gap:10px;align-items:baseline;font-size:12.5px;padding:2px 0}
.olt-al .olt-alt{flex:0 0 96px;font-family:'IBM Plex Mono';font-size:11px;color:var(--text-faint)}
.olt-al .olt-aln{flex:0 0 auto;font-weight:var(--fw-bold)}
.olt-al .olt-alm{color:var(--text-dim);min-width:0}
.olt-al.critical .olt-alm{color:var(--red)} .olt-al.warn .olt-alm{color:var(--amber)}
.dbt-oltm{grid-template-columns:minmax(0,1fr) minmax(0,1.2fr) minmax(0,.9fr) 72px}
.dbt-row.dbt-eq:hover{background:color-mix(in srgb,var(--signal) 7%,transparent)}
.eq-amb{font-weight:var(--fw-semi);font-size:12.5px}
.modal-body.eq-ficha{max-height:82vh}
.eq-ficha .eq-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(205px,1fr));gap:11px 14px}
.eq-ficha .eq-sec-h{font-size:12px;font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:.06em;color:var(--text-dim);margin:16px 0 9px;padding-bottom:5px;border-bottom:1px solid var(--border)}
.eq-ficha .eq-sec-h:first-child{margin-top:0}
.eq-ficha .eq-sec-h.muted{color:var(--text-faint)}
.eq-avail{margin-top:13px;padding:9px 12px;border-radius:var(--radius);font-size:12.5px;font-weight:var(--fw-semi);background:var(--surface-2);border:1px solid var(--border)}
.eq-avail.ok{color:var(--green);border-color:color-mix(in srgb,var(--green) 35%,var(--border))}
.eq-p2{font-size:12px;color:var(--text-faint);line-height:1.5;background:var(--surface-2);border:1px dashed var(--border);border-radius:var(--radius);padding:10px 12px}
/* Igual que los otros dos: número, rótulo al lado, todo en una pastilla. */
.kpi-row{display:flex;gap:8px;flex-wrap:wrap}
.kpi-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
  padding:6px 12px;text-align:left;flex:0 1 auto;display:flex;align-items:baseline;gap:8px;
  flex-wrap:nowrap;min-width:0}
.kpi-card.ok{border-color:color-mix(in srgb,var(--green) 40%,var(--border))}
.kpi-card.warn{border-color:color-mix(in srgb,var(--amber) 40%,var(--border))}
.kpi-val{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:18px;line-height:1.2;white-space:nowrap}
.kpi-card.ok .kpi-val{color:var(--green)} .kpi-card.warn .kpi-val{color:var(--amber)}
.kpi-lbl{font-size:11px;color:var(--text-faint);text-transform:uppercase;letter-spacing:.07em;
  font-weight:var(--fw-bold);margin-top:0;white-space:nowrap}
/* La tira de solapas por estado de proyecto: mismo aspecto que Lista/Árbol, con el número al lado. */
.fl-esttabs > button > b{font-weight:var(--fw-bold);margin-left:5px;opacity:.7;font-variant-numeric:tabular-nums}
.fl-esttabs > button.on > b{opacity:1}
.fl-nota{font-size:11.5px;color:var(--text-dim);align-self:center;white-space:nowrap;cursor:help}
.tab-sec-h{font-size:12px;font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:.06em;color:var(--text-dim);margin:22px 0 11px}
/* Tablero rediseñado: héroe + ámbito apilado + barras de proporción */
.tab-top{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.5fr);gap:14px}
.tab-hero{background:color-mix(in srgb,var(--green) 12%,var(--surface));border:1px solid color-mix(in srgb,var(--green) 35%,var(--border));border-radius:var(--radius);padding:16px 20px;display:flex;align-items:center;gap:16px}
.tab-hero-n{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:39px;line-height:1;color:var(--green)}
.tab-hero-l b{display:block;font-size:14px;font-weight:var(--fw-black)} .tab-hero-l span{font-size:12px;color:var(--text-faint)}
.tab-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:14px 16px}
.tab-card-h{font-size:12px;color:var(--text-faint);font-weight:var(--fw-semi);margin-bottom:10px}
.tab-stack{display:flex;height:14px;border-radius:var(--radius-sm);overflow:hidden;background:var(--surface-3,rgba(130,140,165,.18))}
.tab-stack span{display:block;height:100%}
.tab-leg{display:flex;flex-wrap:wrap;gap:14px;margin-top:10px;font-size:12px;color:var(--text-dim)}
.tab-leg i{display:inline-block;width:9px;height:9px;border-radius:var(--radius-xs);margin-right:5px;vertical-align:middle}
.tab-leg b{color:var(--text)}
.tab-warn{margin-top:9px;font-size:12px;color:var(--amber);font-weight:var(--fw-semi)}
.tab-bars{display:flex;flex-direction:column;gap:7px;max-width:720px}
.tab-bar{display:grid;grid-template-columns:148px 1fr 38px;align-items:center;gap:10px;font-size:12.5px}
.tab-bar[data-eqf]{cursor:pointer;border-radius:var(--radius);padding:3px 5px;margin:-3px -5px;transition:.12s}
.tab-bar[data-eqf]:hover{background:color-mix(in srgb,var(--signal) 9%,transparent)}
.tab-bl{display:flex;align-items:center;gap:7px;color:var(--text-dim);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tab-dot{width:9px;height:9px;border-radius:var(--radius-circ);flex:0 0 auto}
.tab-bt{height:9px;border-radius:var(--radius-sm);background:var(--surface-3,rgba(130,140,165,.18));overflow:hidden}
.tab-bf{display:block;height:100%;border-radius:var(--radius-sm);min-width:3px}
.tab-bn{font-weight:var(--fw-bold);text-align:right}
.tab-cols{display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:4px 26px}
@media(max-width:760px){ .tab-top{grid-template-columns:1fr} .tab-bar{grid-template-columns:116px 1fr 32px} .tab-hero-n{font-size:34px} }
.avl-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(172px,1fr));gap:10px}
.avl-card{display:flex;align-items:center;gap:12px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:12px 14px;cursor:pointer;text-align:left;font-family:inherit;color:var(--text)}
.avl-card:hover{border-color:var(--accent-ink)}
.avl-n{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:21px;color:var(--accent-ink);min-width:32px;text-align:center}
.avl-name{font-size:12.5px;color:var(--text-dim);min-width:0;line-height:1.3}
.dbt-imp{grid-template-columns:minmax(0,1.4fr) minmax(0,1fr) minmax(0,1.2fr) 130px}
.imp-drop{text-align:center;padding:30px 20px;border:1px dashed var(--border);border-radius:var(--radius);background:var(--surface-2)}
.imp-drop-ic{display:inline-flex;color:var(--accent-ink);margin-bottom:8px} .imp-drop-ic svg{width:34px;height:34px}
.imp-drop p{max-width:520px;margin:0 auto 14px;font-size:12.5px;color:var(--text-dim);line-height:1.55}
.imp-summary{margin:16px 0 10px;font-size:13.5px}
.imp-more{font-size:12px;color:var(--text-faint);margin-top:8px}
.imp-done{font-size:13.5px;color:var(--green);background:color-mix(in srgb,var(--green) 10%,var(--surface-2));border:1px solid color-mix(in srgb,var(--green) 30%,var(--border));border-radius:var(--radius);padding:12px 14px}
.al-chips{display:flex;flex-wrap:wrap;gap:10px;padding:14px 16px}
.al-chip{font-size:12.5px;color:var(--text-dim);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:5px 12px}
.al-chip.warn{border-color:color-mix(in srgb,var(--amber) 40%,var(--border))} .al-chip b{color:var(--text)}
.al-chip.bad{border-color:color-mix(in srgb,var(--red) 40%,var(--border))} .al-chip.bad b{color:var(--red)}
.kpi-card.bad{border-color:color-mix(in srgb,var(--red) 40%,var(--border))} .kpi-card.bad .kpi-val{color:var(--red)}
.kpi-card.kpi-click{cursor:pointer;transition:.12s} .kpi-card.kpi-click:hover{border-color:var(--accent-ink);background:color-mix(in srgb,var(--signal) 7%,var(--surface))}
.al-tag.bad{color:var(--red);background:color-mix(in srgb,var(--red) 13%,transparent)}
.dbt-al{grid-template-columns:minmax(0,1.3fr) minmax(0,1fr) 120px minmax(0,1.6fr)}
.dbt-row.dbt-al{content-visibility:visible}
.dbt-row.dbt-al .al-tags{white-space:normal;overflow:visible;display:flex;flex-wrap:wrap;gap:4px;align-items:center}
.dbt-sal{grid-template-columns:40px minmax(0,1.3fr) minmax(0,1fr) minmax(0,1fr)}
/* Parque Telwinet: la MAC y el serial mandan (son por lo que se busca), el resto acompaña. */
.dbt-pq{grid-template-columns:minmax(190px,1.5fr) minmax(120px,1.1fr) minmax(110px,1fr) minmax(100px,.9fr) minmax(80px,.7fr) minmax(110px,1fr) minmax(90px,.8fr)}
@media(max-width:900px){ .dbt-pq{min-width:900px} }
.al-tag{font-size:12px;font-weight:var(--fw-semi);color:var(--amber);background:color-mix(in srgb,var(--amber) 13%,transparent);padding:2px 9px;border-radius:var(--radius)}
.eq-hist{display:flex;flex-direction:column;gap:4px}
.eq-hist-row{display:grid;grid-template-columns:96px 92px 1fr;gap:8px;align-items:baseline;font-size:12.5px;padding:5px 8px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2)}
.eq-hist-d{color:var(--text-faint);font-family:'IBM Plex Mono';font-size:11px}
.eq-hist-ty{font-weight:var(--fw-bold);color:var(--text)}
.eq-hist-x{color:var(--text-dim);min-width:0}
/* badge contador en el menú lateral */
.so-navi-badge{margin-left:auto;flex:0 0 auto;min-width:18px;height:18px;padding:0 5px;border-radius:var(--radius);background:var(--surface-3);color:var(--text-dim);font-size:11px;font-weight:var(--fw-bold);display:inline-flex;align-items:center;justify-content:center;line-height:1}
.so-navi-badge.alert{background:var(--red-fill);color:#fff}
.so-navi-badge.ok{background:var(--green);color:#06210a}
.so-wrap.so-collapsed .so-navi{position:relative}
.so-wrap.so-collapsed .so-navi-badge{position:absolute;margin:0;top:5px;right:7px;min-width:8px;width:8px;height:8px;padding:0;font-size:0;border-radius:var(--radius-circ)}
/* pills de estado uniformes */
.eq-pill{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:var(--fw-semi);padding:2px 9px;border-radius:var(--radius);border:1px solid var(--border);background:var(--surface-2);color:var(--text-dim);white-space:nowrap}
.eq-pill.ok{color:var(--green);border-color:color-mix(in srgb,var(--green) 35%,var(--border));background:color-mix(in srgb,var(--green) 12%,transparent)}
.eq-pill.mut{color:var(--text-faint)}
/* LOS SEIS ESTADOS DEL EQUIPO. El color venía escrito en la línea, con una paleta pensada para
   fondo oscuro: el QA era un celeste #5b7aa8 sobre su propio tinte al 15 %, que en tema claro da
   1,8 de contraste contra los 4,5 que hacen falta — casi no se leía. Ahora cada estado es una clase
   con su tinta por tema, como ya se había hecho con los chips de rol. */
.eq-pill.est{color:var(--e);background:color-mix(in srgb,var(--e) 15%,transparent);
  border-color:color-mix(in srgb,var(--e) 32%,var(--border))}
.eq-pill.est-recibido{--e:#8a93a6} .eq-pill.est-qa{--e:#5b7aa8} .eq-pill.est-config{--e:#8f86d6}
.eq-pill.est-testeo{--e:#c08a34} .eq-pill.est-reparacion{--e:#c2555f} .eq-pill.est-listo{--e:#4f9e78}
html[data-theme="light"] .eq-pill.est-recibido{--e:#4a5464}
html[data-theme="light"] .eq-pill.est-qa{--e:#1a5273}
html[data-theme="light"] .eq-pill.est-config{--e:#5a44c0}
html[data-theme="light"] .eq-pill.est-testeo{--e:#8a5300}
html[data-theme="light"] .eq-pill.est-reparacion{--e:#b3261e}
html[data-theme="light"] .eq-pill.est-listo{--e:#146c43}
.eq-pill.bad{color:var(--red);border-color:color-mix(in srgb,var(--red) 35%,var(--border));background:color-mix(in srgb,var(--red) 12%,transparent)}
.eq-pill.warn{color:var(--amber);border-color:color-mix(in srgb,var(--amber) 35%,var(--border));background:color-mix(in srgb,var(--amber) 12%,transparent)}
/* tablas más pulidas (dentro del panel de Stock) */
.so-panel-body .dbt-row:nth-child(even){background:var(--zebra)}
.so-panel-body .dbt-row:hover{background:color-mix(in srgb,var(--signal) 9%,transparent)}
.so-panel-body .dbt-head{box-shadow:0 5px 10px -8px rgba(0,0,0,.55)}
.so-panel-body .mono{font-family:'IBM Plex Mono';letter-spacing:.2px}
/* skeleton de carga */
.sk{display:block;height:11px;border-radius:var(--radius-sm);background:linear-gradient(90deg,var(--surface-2),var(--surface-3),var(--surface-2));background-size:200% 100%;animation:sksh 1.2s linear infinite}
@keyframes sksh{0%{background-position:200% 0}100%{background-position:-200% 0}}
.sk-row{display:flex;gap:16px;align-items:center;padding:12px 16px;border-bottom:1px solid var(--border)}
.sk-row .sk{flex:1}
/* búsqueda dentro del menú lateral (Ayuda) + tipografía del contenido */
.so-side-search{padding:2px 2px 9px;border-bottom:1px solid var(--border);margin-bottom:4px}
.so-side-search .help-search{width:100%;box-sizing:border-box;min-width:0;max-width:100%;padding:7px 10px;font-size:12.5px;height:auto}
.so-wrap.so-collapsed .so-side-search{display:none}
.so-panel-bar h3 svg{vertical-align:-3px;margin-right:5px;color:var(--text-dim)}
.help-doc p{font-size:13.5px;line-height:1.6;color:var(--text);margin:0 0 11px}
.help-doc ul{margin:0 0 11px;padding-left:18px;display:flex;flex-direction:column;gap:6px}
.help-doc li{font-size:13.5px;line-height:1.5;color:var(--text)}
.help-doc h4{margin:14px 0 8px;font-size:13.5px;font-family:'IBM Plex Sans'}
.help-doc>:first-child{margin-top:0}
/* el contenido de Stock (tablas/barras) va a ancho completo dentro del marco */
.so-main .dbt-wrap{max-width:none}
@media(max-width:760px){
  #stockView,#helpView,#statsView,#histView,#configView{padding:0}
  .so-wrap{flex-direction:column}
  .so-side{flex:0 0 auto;overflow-x:auto;overflow-y:hidden;border-right:0;border-bottom:1px solid var(--border);padding:9px;gap:0}
  .so-brand{display:none} .so-collapse{display:none}
  .so-nav{flex-direction:row;gap:4px;flex-wrap:wrap}
  .so-navi{flex:0 0 auto;width:auto;padding:8px 11px} .so-navi-l{white-space:nowrap} .so-soon{display:none}
  /* En el celular el menú es una tira horizontal: la marca del activo es la raya de abajo, así que
     la barra de la izquierda se esconde (si no, quedan las dos). */
  .so-navi.on{box-shadow:inset 0 -3px 0 var(--signal)}
  .so-navi.on::before{display:none}
  .so-navlist{flex-direction:row;flex-wrap:wrap;width:100%;gap:4px}
  .so-navlist .so-navi{padding-left:11px}
  .so-main{padding:14px}
  /* Sin min-width:0 los paneles del armazón crecen con su contenido: una tabla ancha estiraba el marco
     hasta 818 px dentro de un teléfono de 390, y como .so-wrap recorta, las últimas columnas quedaban
     inalcanzables (pasaba en Configuración, Stock, Planos y Ayuda). Con esto el marco se queda en el ancho
     del teléfono y es la tabla la que scrollea sola, que es la convención del resto del sistema. */
  #configWrap,#stockWrap,#planosWrap,#helpWrap,#statsWrap,#histWrap,#oltWrap,#cajasWrap,#supWrap,
  #repWrap,#zonasWrap,#planWrap,#agendaWrap,#rtWrap,
  .so-wrap,.so-side,.so-main,.so-panel,.so-panel-bar,.so-panel-body,.so-panel-body>.dbt-wrap{min-width:0}
  .so-main{max-width:100%}
  /* El marco se queda en el ancho del teléfono aunque la tabla sea más ancha. */
  #oltWrap,#oltWrap .so-wrap,#oltWrap .so-main,#oltWrap .so-panel,
  #oltWrap .so-panel-body,#oltWrap .so-panel-body>div,#oltWrap .sup-card{max-width:100%;min-width:0}
  /* y es la tabla la que scrollea adentro, como en el resto del sistema */
  .sup-tk-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;max-width:100%}
  .so-panel-bar{flex-wrap:wrap;row-gap:8px}
  .so-panel-bar input,.so-panel-bar select,.so-panel-bar .sel{max-width:100%;min-width:0}
  /* las herramientas de la barra (buscador + contador + botón) iban en una sola línea que se apretaba
     hasta cortar el botón: en el teléfono bajan a su propio renglón y pueden partirse en varios */
  .so-panel-bar .cfg-tools{flex:1 1 100%;flex-wrap:wrap;row-gap:8px}
  .so-panel-bar .cfg-tools-sp{display:none}
  .help-doc img,.help-doc svg,.help-doc pre,.help-doc table{max-width:100%}
  /* ACÁ VIVÍA EL MAESTRO-DETALLE DEL MONITOR OLT y era la pantalla gris del celular.
     Cuando el módulo tenía menú propio, en el teléfono se mostraba ese menú a pantalla completa y al
     tocar una pestaña se veía el contenido con un botón «Menú Monitor OLT» para volver. Después el
     menú propio se eliminó —las pantallas pasaron a la barra lateral— y quedó `#oltWrap .so-side
     {display:none}` arriba, fuera de este bloque. Pero acá seguía `#oltWrap .so-main{display:none}`
     salvo con la clase `olt-detail`: al tocar «volver» se sacaba esa clase y quedaban ESCONDIDOS LOS
     DOS PANELES a la vez. Pantalla vacía, sin error en la consola.
     Ahora no hay maestro-detalle: el menú del teléfono es el cajón lateral, el mismo que en la PC, y
     `.so-main` usa su regla de siempre (ocupa todo). Los botones `.so-navi` siguen en el DOM porque
     navIr() les hace clic, pero no se ven ni se navegan a mano. */
}
.dbt-mv{grid-template-columns:116px 92px minmax(0,1.7fr) 62px 100px minmax(0,1.2fr) minmax(0,1.8fr)}
.dbt-plan{grid-template-columns:minmax(0,1.1fr) minmax(0,3fr) 110px 54px}
.dbt-hist{grid-template-columns:96px 86px minmax(0,2.4fr) minmax(0,1fr) minmax(0,1fr) 84px}
.dbt-row.dbt-hist{cursor:pointer}
.dbt-row.dbt-plan{cursor:pointer}
.dbt-pap{grid-template-columns:120px 86px minmax(0,2.2fr) minmax(0,1fr) minmax(0,1fr) 92px}
.hist-tabs{display:flex;gap:6px;margin:0 0 12px;flex-wrap:wrap}
/* La lista de novedades de cada versión. Vivía anclada a la grilla vieja de Configuración —había un
   bloque entero de reglas sólo para romper esa grilla y dejarla crecer—; ahora vive en una celda de
   tabla, que crece sola, así que le queda su sangría y nada más. */
.cl-items{margin:0;padding-left:16px}
.cl-items li{white-space:normal;word-break:break-word}
/* Configuración como vista (app-shell full-bleed) */
#configView{flex:1;display:none;overflow:hidden;padding:0}
#configView.on{display:flex}
#cfgBody{padding:18px 24px calc(28px + env(safe-area-inset-bottom));-webkit-overflow-scrolling:touch}
#cfgBody .dbt-wrap{overflow-x:auto}
.db-user{display:flex;align-items:center;gap:8px;font-weight:var(--fw-semi);min-width:0;overflow:hidden;text-overflow:ellipsis}
.db-user .avatar{width:26px;height:26px;border-radius:var(--radius-sm);font-size:11px;font-weight:var(--fw-bold);display:flex;align-items:center;justify-content:center;color:#06121a;flex:0 0 auto}
.role-chip{font-size:11px;font-weight:var(--fw-bold);padding:2px 9px;border-radius:var(--radius);text-transform:uppercase;letter-spacing:.02em;white-space:nowrap}
.role-admin{color:var(--red);background:#c2555f1a} .role-coord{color:var(--amber);background:#c08a341a} .role-tec{color:var(--accent-ink);background:rgba(147,37,90,.12)} .role-stock{color:#5b7aa8;background:#5b7aa81a}
/* Los chips de rol se leen sobre su PROPIO tinte, no sobre la superficie: ese fondo teñido sube el
   piso y el texto queda más bajo de lo que da el token suelto. El de Stock era el peor —#5b7aa8 fijo,
   pensado para fondo oscuro, quedaba en 1,77 sobre fondo claro—. Cada tema fija su tinta. */
html[data-theme="light"] .role-stock{color:#2f6591}
html[data-theme="light"] .role-tec{color:#2b56c0}
:root:not([data-theme="light"]) .role-coord{color:#e3a34e}
/* El de Técnico usaba --accent-ink, que es rosa, sobre un tinte AZUL: dos colores distintos peleando
   dan 3,54 sobre fondo oscuro. Va en el mismo azul del tinte, aclarado. */
:root:not([data-theme="light"]) .role-tec{color:#8fbaff}
.req{color:var(--red);font-weight:var(--fw-black);margin-left:1px}
.wn-block{margin-bottom:14px} .wn-block:last-child{margin-bottom:0}
.wn-ver{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:13.5px;margin-bottom:6px;color:var(--accent-ink)}
.wn-list{margin:0;padding-left:18px;line-height:1.6;color:var(--text-dim);font-size:13.5px}
.wn-list li{margin-bottom:4px}
.cl-list{display:flex;flex-direction:column;gap:13px}
.cl-entry{border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2);padding:12px 14px}
.cl-ver{display:flex;align-items:baseline;gap:9px;margin-bottom:7px}
.cl-vnum{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:13.5px;color:var(--accent-ink)}
.cl-date{font-family:'IBM Plex Mono';font-size:11px;color:var(--text-faint)}
.cl-items{margin:0;padding-left:18px;line-height:1.6;color:var(--text-dim);font-size:12.5px}
.cl-items li{margin-bottom:4px}
#offlineBar{position:fixed;left:12px;bottom:-60px;z-index:720;display:flex;align-items:center;gap:8px;background:#c08a34;color:#1a1205;font-size:12.5px;font-weight:var(--fw-bold);padding:9px 14px;border-radius:var(--radius);box-shadow:var(--shadow);transition:bottom .25s ease;max-width:calc(100vw - 24px)}
#offlineBar.show{bottom:calc(16px + env(safe-area-inset-bottom))}
#offlineBar svg{flex:0 0 auto}
.usr-cuad{display:flex;align-items:center;gap:6px;min-width:0;flex-wrap:wrap}
.usr-base{color:var(--text-dim)}
.usr-temp{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:var(--fw-semi);color:var(--amber);background:#c08a341a;border:1px solid #c08a3440;border-radius:var(--radius);padding:1px 8px;white-space:nowrap}
.usr-temp svg{width:12px;height:12px;flex:0 0 auto}
.usr-tools{display:flex;gap:9px;align-items:center;flex-wrap:wrap;margin-bottom:12px}
.stk-b.on{color:var(--amber);border-color:var(--amber);background:#c08a341a}
.lg-act{font-size:11px;font-weight:var(--fw-bold);padding:2px 9px;border-radius:var(--radius);text-transform:uppercase;letter-spacing:.02em;white-space:nowrap}
.lg-green{color:var(--green);background:#4f9e781a} .lg-red{color:var(--red);background:#c2555f1a} .lg-amber{color:var(--amber);background:#c08a341a}
.lg-blue{color:var(--accent-ink);background:rgba(147,37,90,.12)} .lg-violet{color:var(--violet);background:rgba(157,140,255,.14)} .lg-mut{color:var(--text-faint);background:rgba(130,140,165,.12)}
.db-name.pdf{gap:8px}
.db-name.pdf svg{width:15px;height:15px;color:#c2555f;flex:0 0 auto}
.db-asig{font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bulk-row{display:flex;gap:8px;align-items:center;margin-bottom:7px}
.bulk-row .bulk-item{flex:1;min-width:0}
.bulk-row .bulk-qty{flex:0 0 92px;width:92px}
.bulk-rm{flex:0 0 auto;width:30px;height:30px;display:inline-flex;align-items:center;justify-content:center;border:1px solid var(--border);background:var(--surface);color:var(--text-faint);border-radius:var(--radius-sm);cursor:pointer}
.bulk-rm:hover{color:var(--red);border-color:var(--red)}
.bulk-rm svg{width:13px;height:13px}
.stk-act{flex:0 0 auto}
@media(max-width:900px){
  #stockView{padding:12px 10px calc(22px + env(safe-area-inset-bottom))}
  .dbt-wrap{overflow-x:auto}
  .dbt-head,.dbt-row{min-width:780px}
  /* Estas tres necesitan mas que los 780 de arriba: con ese ancho al nombre del modelo le quedaban
     80 px y salia cortado («onu router g»). Van con DOS clases porque la regla de arriba tiene mas
     especificidad que una sola y la pisaba. La tabla scrollea sola, asi que no desborda la pagina. */
  .dbt-head.dbt-pmod,.dbt-row.dbt-pmod{min-width:940px}
  .dbt-head.dbt-pzona,.dbt-row.dbt-pzona{min-width:900px}
  .dbt-head.dbt-pnodo,.dbt-row.dbt-pnodo{min-width:920px}
  .dbt-head.dbt-pret,.dbt-row.dbt-pret{min-width:900px}
  .dbt-head.dbt-pretn,.dbt-row.dbt-pretn{min-width:920px}
  .dbt-head.dbt-pvida,.dbt-row.dbt-pvida{min-width:980px}
  .dbt-head.dbt-cvivo,.dbt-row.dbt-cvivo{min-width:900px}
  .dbt-plan{min-width:460px}
  .dbt-hist{min-width:620px}
  .stock-bar{flex-wrap:wrap}
  .stock-bar .help-search{flex-basis:100%}
  .stk-irow{grid-template-columns:1fr auto;gap:4px 10px}
  .stk-irow .stk-imin,.stk-irow .stk-iest{display:none}
  .stk-irow .stk-iacts{grid-column:1 / -1;justify-content:flex-start}
}
@media(max-width:860px){
  .planos-top .help-search{margin-left:0}
  .pf-files{grid-template-columns:1fr}
}
@media(max-width:860px){
  #helpView{padding:14px 12px calc(24px + env(safe-area-inset-bottom))}
  .help-grid{grid-template-columns:1fr}
  #helpSearch{flex-basis:100%;width:100%;max-width:none}
  .help-side{position:static}
  .help-index{position:static;flex-direction:row;flex-wrap:nowrap;overflow-x:auto;gap:6px;padding-bottom:6px;scrollbar-width:none}
  .help-index::-webkit-scrollbar{display:none}
  .help-ix{flex:0 0 auto;background:var(--surface-2);white-space:nowrap}
  .help-search{margin-left:0;max-width:none}
}
/* ---- Anotaciones como tablero por columnas ---- */
.notes-toolbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.nt-arch{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;color:var(--text-faint);cursor:pointer;white-space:nowrap}
.note-col .note{margin-bottom:0}
.note-col .note-tag{font-size:11px;padding:2px 5px}
.note-col .note-act{width:26px;height:26px}
.note-col .note-act svg{width:15px;height:15px}
.note-col .note{cursor:grab}
.note-col .note:active{cursor:grabbing}
.note-col .note textarea,.note-col .note input{cursor:text}
.note.note-dragging{opacity:.4}
.note-col-add{margin:2px 11px 12px;padding:9px;border:1.5px dashed var(--border);border-radius:var(--radius);background:none;color:var(--text-faint);font-size:12.5px;font-weight:var(--fw-semi);cursor:pointer;display:flex;align-items:center;justify-content:center;gap:6px}
.note-col-add:hover{border-color:var(--border-strong);color:var(--text)}
.note-col-add svg{width:14px;height:14px}
/* ---- Anotaciones: rediseño en columnas (grilla por etiqueta, tarjetas compactas) ---- */
/* `grid-auto-rows:min-content` es lo que hace que la columna crezca con sus notas. Sin eso las
   filas se quedaban en los 120 px del `min-height` de la columna —en el celular, donde la grilla
   queda de una sola columna, eso son cuatro filas de 120— y una columna con 4 notas, que necesita
   951, derramaba sus notas encima de la de abajo. Ojo: `align-items:start` NO alcanza; hace crecer
   la columna pero deja la fila en 120, así que se encima igual. */
.board.notes-board{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));grid-auto-rows:min-content;gap:14px;align-items:start;overflow-y:auto;overflow-x:hidden}
.board.notes-board .note-col{max-height:none;min-height:120px}
.board.notes-board .note-col{height:auto}
.board.notes-board .note-col .col-body{overflow:visible;max-height:none}
.board.notes-board .col-head{background:var(--surface-2);border-left:3px solid var(--nc,var(--border-strong));border-radius:var(--radius);margin:10px 10px 8px;padding:8px 10px;text-transform:uppercase;letter-spacing:.06em;font-size:11px;font-weight:var(--fw-bold);display:flex;align-items:center;gap:8px}
.board.notes-board .col-dot{display:none}
.board.notes-board .col-count{margin-left:auto;background:color-mix(in srgb,var(--nc,var(--text-dim)) 16%,transparent);color:var(--nc,var(--text-dim));border:1px solid color-mix(in srgb,var(--nc,var(--text-dim)) 45%,transparent);border-radius:var(--radius-sm);padding:0 7px;font-size:11px;line-height:16px;font-weight:var(--fw-bold)}
.board.notes-board .note{padding:9px 11px 8px;border-radius:var(--radius);margin:0 10px 8px}
.board.notes-board .note-body{font-size:13.5px;line-height:1.45}
.board.notes-board .note-foot{gap:6px;margin-top:8px;font-size:11px}
.board.notes-board .note-chip{padding:2px 6px;gap:4px}
.board.notes-board .natt-thumb{max-width:100%;max-height:150px}
@media (max-width:1100px){ .board.notes-board{grid-template-columns:repeat(2,minmax(0,1fr))} }
@media (max-width:640px){ .board.notes-board{grid-template-columns:1fr} }
/* ---- Ubicación Maps en la ficha ---- */
.maps-open-row{margin-top:8px}
.maps-open-row:empty{display:none}
.btn-map.maps-open{text-decoration:none}
/* distintivo "cliente a recoordinar" en tarjetas y planilla */
.ic-chip.recoord{background:#c08a341a;color:#c08a34;border:1px solid #c08a3455;cursor:pointer}
.ic-chip.recoord svg{width:13px;height:13px}
.ic-chip.derivada{background:#8f86d622;color:#8f86d6;border:1px solid #8f86d655;cursor:pointer}
.ic-chip.derivada svg{width:13px;height:13px}
.ic-chip.origen{background:#5b7aa822;color:#5b7aa8;border:1px solid #5b7aa855;cursor:pointer}
.ic-chip.origen svg{width:13px;height:13px}
.ic-chip.avisado{background:#4f9e7822;color:#4f9e78;border:1px solid #4f9e7866;cursor:pointer}
.ic-chip.avisado svg{width:13px;height:13px}
.ic-chip.noaviso{background:rgba(255,255,255,.08);color:var(--text);border:1px solid rgba(255,255,255,.42);cursor:pointer}
.ic-chip.noaviso svg{width:13px;height:13px}
/* resaltar los chips clickeables al pasar el mouse */
.ic-chip.recoord,.ic-chip.avisado,.ic-chip.noaviso,.ic-chip.derivada,.ic-chip.origen{transition:background .12s,border-color .12s,transform .12s,box-shadow .12s}
.ic-chip.recoord:hover{background:rgba(255,255,255,.2);border-color:#fff;transform:translateY(-1px);box-shadow:0 4px 12px -6px rgba(255,255,255,.6)}
.ic-chip.noaviso:hover{background:rgba(255,255,255,.2);border-color:#fff;transform:translateY(-1px);box-shadow:0 4px 12px -6px rgba(255,255,255,.6)}
.ic-chip.avisado:hover{background:#4f9e7840;border-color:#4f9e78;transform:translateY(-1px);box-shadow:0 4px 12px -6px #4f9e7899}
.ic-chip.derivada:hover{background:#8f86d640;border-color:#8f86d6}
.ic-chip.origen:hover{background:#5b7aa840;border-color:#5b7aa8;transform:translateY(-1px);box-shadow:0 4px 12px -6px #5b7aa899}
.flt-recoord{display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:var(--fw-semi);color:#ff8a5b;background:#ff8a5b1a;border:1px solid #ff8a5b44;border-radius:var(--radius-sm);padding:1px 7px;cursor:pointer;white-space:nowrap}
.flt-recoord svg{width:12px;height:12px;flex:0 0 auto}
.flt-recoord:hover{background:#ff8a5b2a}
.flt-bloq{display:inline-flex;align-items:center;font-size:10px;font-weight:var(--fw-black);letter-spacing:.04em;padding:2px 7px;border-radius:var(--radius-sm);white-space:nowrap;flex:0 0 auto}
.flt-bloq.bloq-dep,.flt-bloq.bloq-mat{background:var(--red);color:#fff}
.flt-bloq.bloq-prep{background:#5b7aa8;color:#06121a}
.flt-bloq.flt-cierre{background:#c08a34;color:#3a2500}
.flt-bloq.flt-clientes{background:#3f8a9c;color:#06121a}
.flt-bloq.flt-devpend{background:#c08a34;color:#20160a}
.flt-bloq.flt-devno{background:#c2555f;color:#fff}
.proj-obj{color:var(--text-faint)}
.proj-obj.over{color:var(--red);font-weight:var(--fw-bold)}
/* ---- Adjuntos en Anotaciones ---- */
.note-att{display:flex;flex-direction:column;gap:5px;margin-top:9px}
.natt{display:flex;align-items:center;gap:6px}
.natt-link{flex:1;min-width:0;display:flex;align-items:center;gap:7px;text-decoration:none;color:var(--text);background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:6px 9px;font-size:12.5px}
.natt-link:hover{border-color:var(--border-strong)}
.natt-link svg{width:15px;height:15px;flex:0 0 auto;color:var(--text-faint)}
.natt-name{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.natt-rm{flex:0 0 auto;border:none;background:transparent;color:var(--text-faint);cursor:pointer;font-size:17px;line-height:1;padding:0 4px;opacity:.55}
.natt-rm:hover{opacity:1;color:var(--red)}
#myTasksWrap{max-width:760px;margin:0 auto}
.mt-head{display:flex;align-items:center;gap:12px;margin-bottom:14px}
.mt-head h2{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:19px}
.mt-reload{margin-left:auto;flex:0 0 auto}

/* Técnico: sacar «Ayuda» (pestaña + menú del avatar) */
.tec-view #umHelp,
.tec-view #viewSwitch [data-view="help"],
.tec-view #sideNav [data-view="help"]{display:none !important}
.mt-body{padding:8px;display:flex;flex-direction:column;gap:8px}
.mt-task{display:block;width:100%;text-align:left;background:var(--card-bg,var(--surface-2));border:1px solid var(--border);border-radius:var(--radius);padding:11px 13px;cursor:pointer;transition:.12s}
.mt-task:hover{border-color:var(--border-strong);background:var(--surface-3)}
.mt-task.blk{box-shadow:none}
.mt-top{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:7px}
.mt-chips{display:flex;flex-wrap:wrap;align-items:center;gap:6px;margin-bottom:7px}
.mt-proj{font-family:'IBM Plex Mono';font-size:11px;font-weight:var(--fw-bold);color:#fff;padding:2px 7px;border-radius:var(--radius-sm)}
.mt-tipo{font-size:11px;font-weight:var(--fw-bold);color:#fff;padding:2px 8px;border-radius:var(--radius-sm);white-space:nowrap}
.tec-view .mt-tipo,.tec-view .mt-proj{font-size:12px;padding:3px 9px}
.mt-est{margin-left:auto;display:flex;align-items:center;gap:5px;font-size:12px;color:var(--text-dim);white-space:nowrap}
.mt-edot{width:8px;height:8px;border-radius:var(--radius-circ);flex:0 0 auto}
.mt-ttl{font-size:14px;font-weight:var(--fw-semi);line-height:1.3;color:var(--card-title,inherit)}
.mt-meta{display:flex;flex-wrap:wrap;gap:10px;margin-top:7px;font-size:12px;color:var(--text-faint)}
.mt-blk,.mt-over{color:var(--red);font-weight:var(--fw-semi)}
.mt-secdot{width:11px;height:11px;border-radius:var(--radius-circ);flex:0 0 auto}
.mt-reason{font-size:12.5px;color:var(--red);font-weight:var(--fw-semi);margin-top:5px;line-height:1.3}
.tec-view .mt-reason{font-size:13.5px}
/* ===== Vista ampliada para técnicos (vista reducida / anteojos) ===== */
.tec-view .view-switch button{font-size:14px;padding:9px 16px}
.tec-view #meBox .avatar{width:40px;height:40px;font-size:13.5px}
.tec-view .mt-head h2{font-size:22px}
.tec-view .mt-task{padding:15px 16px}
.tec-view .mt-ttl{font-size:16px;line-height:1.35}
.tec-view .mt-top .flt-id{font-size:12.5px;padding:2px 8px}
.tec-view .mt-est{font-size:13.5px}
.tec-view .mt-meta{font-size:13.5px;gap:14px;margin-top:9px}
.tec-view .mt-proj{font-size:12px;padding:3px 9px}
.tec-view .hist-grp-h{padding:14px 16px}
.tec-view .hist-grp-nm{font-size:16px}
.tec-view .hist-grp-ic{min-width:34px;height:24px;font-size:12px}
.tec-view .hist-grp-meta{font-size:13.5px}
/* ficha (modal) para técnico: más legible y botones grandes */
.tec-view .modal-idline .flt-id{font-size:12.5px}
.tec-view .field>label{font-size:12px;letter-spacing:.08em}
.tec-view .inp,.tec-view .ta,.tec-view .sel{font-size:16px;padding:12px 13px}
.tec-view .ro-val{font-size:16px}
.tec-view .set-tab{font-size:14px;padding:14px 16px}
.tec-view #saveBtn,.tec-view #cancelBtn{font-size:15px;padding:12px 18px}
.tec-view .umenu-item{font-size:15px;padding:14px 14px}
.proj-closed-chip{display:inline-flex;align-items:center;gap:5px;font-weight:var(--fw-semi)}
.proj-closed-chip .pc-dot{width:9px;height:9px;border-radius:var(--radius-sm);flex:none}
.tbl tr.click{cursor:pointer}
.tbl tr.click:hover td{background:rgba(255,255,255,.03)}
.hist-search{width:240px;max-width:100%;margin:0;padding:9px 13px;background:var(--surface-2);border:1px solid var(--border-strong);border-radius:var(--radius);color:var(--text);font-size:13.5px;font-family:'IBM Plex Sans'}
.hist-search:focus{outline:none;border-color:var(--accent-ink)}
.hist-count{font-size:12.5px;color:var(--text-faint);font-family:'IBM Plex Sans'}
.hist-grp{border:1px solid var(--border);border-radius:var(--radius);margin-bottom:10px;overflow:hidden;background:var(--surface)}
.hist-grp-h{display:flex;align-items:center;gap:10px;width:100%;padding:11px 14px;border:none;background:none;color:var(--text);cursor:pointer;text-align:left}
.hist-grp-h:hover{background:var(--surface-2)}
.hist-grp-h > svg{width:15px;height:15px;color:var(--text-faint);transition:transform .2s;flex:0 0 auto;transform:rotate(-90deg)}
.hist-grp:not(.open) .hist-grp-h > svg{transform:rotate(180deg)}
.hist-grp-ic{flex:0 0 auto;min-width:30px;height:22px;padding:0 7px;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-sm);color:#fff;font-family:'IBM Plex Mono';font-size:11px;font-weight:var(--fw-bold)}
.hist-grp-nm{font-weight:var(--fw-bold);font-size:13.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.hist-badge{flex:0 0 auto;font-size:10px;font-weight:var(--fw-black);letter-spacing:.05em;color:var(--text-faint);border:1px solid var(--border);border-radius:var(--radius-sm);padding:2px 6px}
.hist-grp-meta{margin-left:auto;flex:0 0 auto;font-size:12px;color:var(--text-faint);font-family:'IBM Plex Mono';white-space:nowrap}
.hist-grp-body{padding:2px 14px 12px}
.hist-grp:not(.open) .hist-grp-body{display:none}
.hist-nomatch{padding:14px 4px;color:var(--text-faint);font-size:12.5px}
.hist-more{margin-top:12px;display:flex;justify-content:center}
.hist-more .btn{font-size:12.5px}

/* ====================== VISTA FLUJO (aditiva) ====================== */
#flowView{flex:1;display:none;flex-direction:column;overflow:hidden}
#flowView.on{display:flex}
.fl-bar{display:flex;align-items:center;gap:8px;padding:2px 22px 10px;flex-wrap:wrap;background:transparent;flex:0 0 auto}
#flBar .area-switch{flex:0 0 auto}
.fl-filters{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.fl-filters .flt-fcount{font-family:'IBM Plex Mono';font-size:12px;color:var(--text-faint)}
.flt-search{appearance:none;background:var(--surface-2);border:1px solid var(--border);color:var(--text);height:36px;padding:0 12px;border-radius:var(--radius);font-size:12.5px;flex:1 1 auto;min-width:120px}
#flBar .fl-filters{flex:1 1 auto;min-width:0}
#flBar > .tb-spacer{flex:0 0 0}
#toolbar > .tb-spacer{flex:0 0 0}
.flt-search:focus{outline:none;border-color:var(--accent-ink)}
.fl-flag{display:inline-flex;align-items:center;gap:6px;height:36px;padding:0 11px;border:1px solid var(--border);background:var(--surface-2);color:var(--text-dim);border-radius:var(--radius);font-size:12.5px;font-weight:var(--fw-semi);cursor:pointer;transition:.14s;white-space:nowrap}
.fl-flag:hover{border-color:var(--border-strong);color:var(--text)}
.fl-flag .fdot{width:8px;height:8px;border-radius:var(--radius-circ);flex:0 0 auto}
.fl-clear{height:36px;padding:0 12px;border:1px solid var(--border);background:none;color:var(--text-dim);border-radius:var(--radius);font-size:12.5px;font-weight:var(--fw-semi);cursor:pointer}
.fl-clear:hover{color:var(--text);border-color:var(--border-strong)}
/* drag de filas (orden por prioridad) y columnas (reordenar) en la planilla — solo admin */
.flt-gh[draggable="true"]{cursor:grab}
.flt-gh[draggable="true"]:active{cursor:grabbing}
.flt-cols .flt-row[draggable="true"]{cursor:grab}
.flt-row.dragging{opacity:.4}
.flt-grp.col-dragging{opacity:.5}
.flt-grp.drag-over{outline:2px dashed var(--signal);outline-offset:3px;border-radius:var(--radius)}

/* === Uniformidad de las 2 barras superiores: todos los controles a 36px y fuente 13px === */
.topbar .view-switch button, .topbar .btn{font-size:12.5px}
#toolbar .area-switch, #flBar .area-switch, #flBar .fl-tabs{height:36px;padding:3px;align-self:center}
#toolbar .area-switch button, #flBar .area-switch button, #flBar .fl-tabs button{height:100%;padding:0 13px;font-size:12.5px}
#toolbar #searchBox, #toolbar .fl-btn, #toolbar .tb-f, #toolbar #filtClear, #flBar .flt-fsel{height:36px;font-size:12.5px}
/* 2da barra: filtros unificados en un desplegable + vistas en un segmentado */
.tb-drop{position:relative;display:inline-flex}
.tb-fbtn{display:inline-flex;align-items:center;gap:7px}
.tb-fbtn svg{width:15px;height:15px}
.tb-fbtn.has-filt{border-color:var(--accent-ink);color:var(--accent-ink)}
.filt-count{display:inline-flex;align-items:center;justify-content:center;min-width:17px;height:17px;padding:0 4px;border-radius:var(--radius);background:var(--signal);color:var(--on-signal);font-size:11px;font-weight:var(--fw-black)}
.tb-pop{display:none;position:absolute;top:calc(100% + 8px);left:0;z-index:60;background:var(--surface);border:1px solid var(--border-strong);border-radius:var(--radius);padding:12px;box-shadow:var(--shadow);min-width:238px;flex-direction:column;gap:9px}
.tb-pop.open{display:flex}
.tb-pop .tb-f{width:100%}
.tb-pop .tb-cancel{display:flex;align-items:center;gap:8px;font-size:12.5px;color:var(--text-dim);cursor:pointer;white-space:nowrap}
.tb-pop #filtClear{width:100%;height:34px;margin-top:2px}
#toolbar .tb-vista{height:36px;align-self:center}
#toolbar .tb-vista button{height:100%}
#toolbar #searchBox{padding:0 12px}
#toolbar .fl-btn{padding:0 14px}
#flBar .flt-fsel{padding:0 28px 0 12px}
#toolbar .tb-counts{border-left:none;padding-left:0;margin-left:0}
#toolbar .tb-counts .sc{height:36px;font-size:12.5px;padding:0 12px}
.fl-tabs{display:flex;background:transparent;border:0;border-bottom:1px solid var(--border-strong);border-radius:0;padding:0;gap:0}
.fl-tabs button{padding:7px 14px;font-size:12.5px;background:transparent;border:0;border-bottom:2px solid transparent;border-radius:0;color:var(--text-dim);font-weight:var(--fw-normal);transition:none}
.fl-tabs button.on{background:transparent;color:var(--text);font-weight:var(--fw-semi);border-bottom-color:var(--accent-ink);box-shadow:none}
.fl-tabs button:not(.on):hover{color:var(--text)}
.fl-hint{font-size:12px;color:var(--text-faint);flex:1 1 200px;line-height:1.4}
/* ===== Vista Flujo · Árbol (genealógico) ===== */
.tre-wrap{padding:12px 16px 28px;max-width:680px;margin:0 auto}
.tre-wrap > .tre-node{margin-bottom:4px}
.board.arbol{display:block;overflow:auto;padding:0}
/* Mantenimiento (árbol a pantalla completa): proyectos/tipos en varias columnas */
.tre-wrap.tre-full{max-width:none;margin:0;padding:14px 18px 30px;column-width:380px;column-gap:24px}
.tre-wrap.tre-full > .tre-node{break-inside:avoid;-webkit-column-break-inside:avoid;page-break-inside:avoid}
.tre-row{display:flex;align-items:center;gap:8px;padding:7px 10px;border-radius:var(--radius);cursor:pointer;user-select:none;position:relative}
.tre-row:hover{background:var(--surface-2)}
.tre-caret{width:12px;font-size:10px;color:var(--text-faint);flex:0 0 auto;text-align:center}
.tre-proj-row{background:var(--surface);border:1px solid var(--border);margin-top:9px}
.tre-pic{width:28px;height:22px;border-radius:var(--radius-sm);display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:var(--fw-bold);color:#06121a;flex:0 0 auto}
.tre-dot{width:9px;height:9px;border-radius:var(--radius-circ);flex:0 0 auto}
.tre-name{font-family:'IBM Plex Sans';font-size:12.5px;text-transform:uppercase;letter-spacing:.02em;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tre-name b{font-weight:var(--fw-bold)}
.tre-bar{flex:1;max-width:130px;height:6px;border-radius:var(--radius-sm);background:var(--surface-3);overflow:hidden;margin-left:auto}
.tre-bar>span{display:block;height:100%;border-radius:var(--radius-sm)}
.tre-pct{font-family:'IBM Plex Mono';font-size:11px;color:var(--text-dim);flex:0 0 auto}
.tre-n{font-family:'IBM Plex Mono';font-size:11px;color:var(--text-faint);background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:0 7px;flex:0 0 auto}
.tre-proj-row .tre-n{margin-left:8px}
.tre-crew-row{margin-top:3px}
.tre-crew-row .tre-n,.tre-crew-row .tre-name{margin-left:0}
.tre-crew-row .tre-name{margin-right:auto}
.tre-children{padding-left:24px;border-left:1.5px solid var(--border);margin-left:14px}
.tre-node.collapsed > .tre-children{display:none}
.tre-children > .tre-node > .tre-row::before,
.tre-children > .tre-leaf::before{content:'';position:absolute;left:-24px;top:50%;width:20px;height:1.5px;background:var(--border)}
.tre-leaf{display:flex;align-items:center;gap:8px;padding:6px 10px;border-radius:var(--radius);cursor:pointer;position:relative}
.tre-leaf:hover{background:var(--surface-2)}
.tre-tipo{width:9px;height:9px;border-radius:var(--radius-xs);flex:0 0 auto}
.tre-id{font-size:11px;font-weight:var(--fw-semi);color:var(--text-faint);flex:0 0 auto}
.tre-ttl{font-size:13.5px;color:var(--text);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1}
.tre-est{font-size:10px;font-weight:var(--fw-bold);color:var(--ec);border:1px solid var(--ec);border-radius:var(--radius-sm);padding:1px 6px;flex:0 0 auto;opacity:.9}
.tre-flag{flex:0 0 auto;font-size:11px}
.tre-empty{padding:6px 10px;color:var(--text-faint);font-size:12px;font-style:italic}
@media(max-width:560px){ .tre-bar{display:none} .tre-children{padding-left:18px;margin-left:10px} .tre-children > .tre-node > .tre-row::before,.tre-children > .tre-leaf::before{left:-18px;width:14px} }
.fl-body{flex:1;overflow:auto;padding:16px 22px calc(20px + env(safe-area-inset-bottom))}

/* --- Etapas (lanes apilables) --- */
.fl-lane{margin-bottom:12px;border:1px solid var(--border);border-radius:var(--radius);background:var(--bg-2);overflow:hidden}
.fl-lane-head{display:flex;align-items:center;gap:10px;width:100%;padding:12px 15px;background:var(--surface);text-align:left}
.fl-lane-head:hover{background:var(--surface-2)}
.fl-dot{width:10px;height:10px;border-radius:var(--radius-circ);flex:0 0 auto}
.fl-lane-ttl{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:13.5px;text-transform:uppercase;letter-spacing:.02em}
.fl-count{font-family:'IBM Plex Mono';font-size:12px;font-weight:var(--fw-semi);color:var(--text-faint);background:var(--surface-3);padding:2px 9px;border-radius:var(--radius)}
.fl-chev{margin-left:auto;color:var(--text-faint);transition:transform .2s}
.fl-lane.collapsed .fl-chev{transform:rotate(-90deg)}
.fl-lane-body{padding:13px;display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:11px}
.fl-lane.collapsed .fl-lane-body{display:none}
.fl-empty{color:var(--text-faint);font-size:12.5px;padding:4px 2px}

/* --- Lista (planilla tipo Excel: tabla por grupo) --- */
.flt-fbar{display:flex;align-items:center;gap:10px;flex-wrap:wrap;padding:2px 0 12px}
.flt-fsel{appearance:none;background:var(--surface-2);border:1px solid var(--border);color:var(--text);padding:7px 28px 7px 11px;border-radius:var(--radius);font-size:12.5px;font-weight:var(--fw-medium);cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' fill='none' stroke='%2394a0b8' stroke-width='2'%3E%3Cpath d='M3 5l3 3 3-3'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right 10px center}
.flt-fcount{font-family:'IBM Plex Mono';font-size:12px;color:var(--text-faint);margin-left:auto}
.flt-grp{margin-bottom:18px}
/* dividir la planilla en columnas (ej. Infra: Tendido | Fusión). Cada columna es angosta,
   así que las filas usan formato compacto: título arriba, datos abajo con etiquetas. */
.flt-cols{display:grid;grid-template-columns:repeat(var(--flt-cols,2),minmax(0,1fr));gap:8px 16px;align-items:start}
/* cada columna (título + contenido) envuelta en su propia caja para diferenciarlas */
.flt-cols .flt-grp{margin-bottom:8px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2);overflow:hidden}
.flt-cols .flt-gh{padding:11px 14px;border-bottom:1px solid var(--border)}
.flt-cols .flt-grp.collapsed .flt-gh{border-bottom:none}
.flt-cols .flt-table{border:none;border-radius:0;background:none}
.flt-cols .flt-projpanel .proj-list{border:none;border-radius:0;background:none}
/* panel resumen de proyectos (3ª columna) */
.flt-projpanel .proj-list{border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;background:var(--surface)}
.proj-item{display:flex;align-items:center;flex-wrap:wrap;gap:10px;width:100%;padding:10px 12px;border:none;border-bottom:1px solid var(--border);background:none;cursor:pointer;text-align:left;transition:.12s}
.proj-item:last-child{border-bottom:none}
.proj-item:nth-child(even){background:var(--zebra)}
.proj-item:hover{background:var(--surface-2);position:relative;z-index:1;transform:translateY(-1px);box-shadow:0 6px 16px -9px rgba(0,0,0,.45);border-radius:var(--radius)}
.proj-item.on{background:var(--surface-2);box-shadow:inset 3px 0 0 var(--accent-ink)}
.proj-item.on:hover{box-shadow:inset 3px 0 0 var(--accent-ink),0 6px 16px -9px rgba(0,0,0,.45)}
.proj-ic{font-size:11px;font-weight:var(--fw-bold);color:#fff;padding:3px 7px;border-radius:var(--radius-sm);flex:0 0 auto}
.proj-meta{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1 1 auto}
.proj-name{display:flex;align-items:baseline;gap:6px;font-size:12.5px;font-weight:var(--fw-semi);white-space:nowrap;overflow:hidden}
.proj-nm{overflow:hidden;text-overflow:ellipsis;min-width:0}
.proj-pct{margin-left:auto;font-size:11px;font-weight:var(--fw-bold);color:var(--green);flex:0 0 auto}
.proj-bar{height:5px;border-radius:var(--radius-sm);background:var(--surface-3);overflow:hidden;margin:5px 0 3px}
.proj-bar > span{display:block;height:100%;background:var(--text-dim);border-radius:var(--radius-sm);transition:width .2s}
.proj-sub{font-size:12px;font-weight:var(--fw-bold);color:var(--text-dim)}
.proj-acts{flex-basis:100%;display:flex;align-items:center;gap:4px;margin-top:2px;min-width:0}
.proj-act{width:26px;height:26px;display:flex;align-items:center;justify-content:center;border:none;background:none;border-radius:var(--radius-sm);color:var(--text-faint);cursor:pointer;flex:0 0 auto;transition:.12s}
.proj-act:hover{background:var(--surface-3);color:var(--text)}
.proj-act.act-curso:hover{color:var(--accent-ink)}
.proj-act.act-fin:hover{color:var(--green)}
.proj-act svg{width:15px;height:15px}
/* chips de acción con etiqueta (Ejecutar/Finalizar · Detalle · Ocultar) */
.proj-act.pa-btn{width:auto;height:auto;flex:1 1 0;min-width:0;justify-content:center;white-space:nowrap;gap:3px;padding:3px 4px;border:1px solid var(--border);background:var(--surface-2);color:var(--text-dim);font-size:10px;font-weight:var(--fw-semi)}
.proj-act.pa-btn:hover{background:var(--surface-3);color:var(--text);border-color:var(--border-strong)}
.proj-act.pa-btn svg{width:11px;height:11px;flex:0 0 auto}
.proj-item.hidden{opacity:.55}
.proj-item.hidden .proj-act[data-hide]{color:var(--accent-ink)}
.proj-item.closed{opacity:.75}
.proj-empty{padding:10px 12px;font-size:12px;color:var(--text-faint)}
.proj-sec{margin-top:16px;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;background:var(--bg-2)}
.proj-sec:first-child{margin-top:0}
.proj-sec-h{display:flex;align-items:center;gap:8px;width:100%;padding:9px 10px 9px 11px;border:none;border-left:3px solid var(--sc,var(--border-strong));background:var(--surface-2);color:var(--text);cursor:pointer;font-size:11px;font-weight:var(--fw-bold);letter-spacing:.06em;text-transform:uppercase;text-align:left}
.proj-sec-h:hover{background:var(--surface-3)}
.proj-sec-n{background:color-mix(in srgb,var(--sc,var(--text-dim)) 16%,transparent);color:var(--sc,var(--text-dim));border:1px solid color-mix(in srgb,var(--sc,var(--text-dim)) 45%,transparent);border-radius:var(--radius-sm);padding:0 7px;font-size:11px;font-weight:var(--fw-bold);line-height:16px;letter-spacing:0}
.proj-sec-h svg{margin-left:auto;width:14px;height:14px;transition:transform .2s;transform:rotate(-90deg)}
.proj-sec.collapsed .proj-sec-h svg{transform:rotate(180deg)}
.proj-sec.collapsed .proj-sec-list{display:none}
.proj-sec[data-estado] .proj-item{cursor:grab}
.proj-sec[data-estado] .proj-item:active{cursor:grabbing}
.proj-item.dragging{opacity:.45}
.flt-empty-col{padding:14px 10px;font-size:12px;color:var(--text-faint);text-align:center}
.proj-sec.drag-over{background:rgba(147,37,90,.07);outline:1px dashed var(--signal);outline-offset:-2px;border-radius:var(--radius)}
/* resumen del proyecto (modal del reloj) */
.proj-sum{display:flex;gap:10px;flex-wrap:wrap}
.ps-item{flex:1 1 0;min-width:92px;display:flex;flex-direction:column;gap:3px;background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);padding:11px 13px}
.ps-item b{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:21px;line-height:1}
.ps-item span{font-size:12px;color:var(--text-faint)}
.ps-curso{color:var(--accent-ink)}
.ps-fin{color:var(--green)}
/* historial de finalizadas por proyecto */
.hist-table{display:flex;flex-direction:column;border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;margin-top:8px;background:var(--surface)}
.hist-row{display:grid;grid-template-columns:86px 72px minmax(0,1fr) 96px 124px;align-items:center;gap:10px;padding:9px 13px;border-bottom:1px solid var(--border)}
.hist-est{display:flex;align-items:center;gap:6px;font-size:12.5px;color:var(--text-dim);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hist-edot{width:8px;height:8px;border-radius:var(--radius-circ);flex:0 0 auto}
.hist-row:last-child{border-bottom:none}
.hist-head{background:var(--surface-2);font-family:'IBM Plex Mono';font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--text-faint);font-weight:var(--fw-semi)}
.hist-row[data-id]{cursor:pointer;transition:.1s}
.hist-row[data-id]:hover{background:var(--surface-2)}
.hist-id{font-size:11px;color:var(--text-dim)}
.hist-ttl{font-size:13.5px;font-weight:var(--fw-semi);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hist-cuad{font-size:12px;color:var(--text-dim)}
.hist-date,.hist-dem{font-size:12px;color:var(--text-faint)}
@media(max-width:680px),(max-height:480px){ .hist-row{grid-template-columns:auto 1fr auto;gap:3px 10px} .hist-row .hist-cuad,.hist-row .hist-date{display:none} }
.flt-cols .flt-hrow{display:none}
.flt-cols .flt-row{display:flex;flex-wrap:wrap;align-items:center;gap:3px 14px;padding:6px 13px}
.flt-cols .flt-task{flex:1 1 100%}
.flt-cols .flt-clabel{display:inline;color:var(--text-faint);font-size:10px;margin-right:2px;text-transform:uppercase;letter-spacing:.04em}
@media(max-width:760px){ .flt-cols{grid-template-columns:1fr !important} }
/* colapsar/expandir columnas */
.flt-collapse{margin-left:auto;width:24px;height:24px;display:flex;align-items:center;justify-content:center;border:none;background:none;border-radius:var(--radius-sm);color:var(--text-faint);cursor:pointer;flex:0 0 auto}
.flt-collapse:hover{background:var(--surface-2);color:var(--text)}
.flt-collapse svg{width:15px;height:15px;transition:transform .2s}
.flt-grp.collapsed .flt-table,.flt-grp.collapsed .proj-list,.flt-grp.collapsed .mat-list,.flt-grp.collapsed .crew-list{display:none}
.flt-grp.collapsed .flt-gh{flex-direction:column;align-items:center;gap:12px;padding:12px 6px}
.flt-grp.collapsed .flt-collapse{order:-1;margin-left:0;transform:rotate(180deg)}
.flt-grp.collapsed .flt-gttl{writing-mode:vertical-rl;transform:rotate(180deg);white-space:nowrap}
/* colapsado con pendientes → titila para llamar la atención (Materiales ámbar, Cierre operativo violeta) */
@keyframes fltPulse{0%,100%{box-shadow:0 0 0 0 transparent;border-color:var(--border)}50%{box-shadow:0 0 15px -2px var(--amber);border-color:var(--amber)}}
@keyframes fltPulseCop{0%,100%{box-shadow:0 0 0 0 transparent;border-color:var(--border)}50%{box-shadow:0 0 15px -2px #c58af9;border-color:#c58af9}}
.flt-cols .flt-grp.collapsed.flt-haspend{animation:fltPulse 1.3s ease-in-out infinite}
.flt-cols .flt-coppanel.collapsed.flt-haspend{animation:fltPulseCop 1.3s ease-in-out infinite}
.flt-gh{display:flex;align-items:center;gap:9px;padding:6px 2px 8px;cursor:pointer}
.flt-gdot{width:9px;height:9px;border-radius:var(--radius-circ)}
.flt-gttl{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:12.5px;letter-spacing:.02em;text-transform:uppercase}
.flt-gn{font-family:'IBM Plex Mono';font-size:12px;color:var(--text-faint);background:var(--surface-2);padding:1px 8px;border-radius:var(--radius)}
.flt-grp.collapsed .flt-table{display:none}
.flt-table{border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;background:var(--surface)}
.flt-hrow,.flt-row{display:grid;grid-template-columns:minmax(0,1fr) 70px 62px 46px 116px 124px;align-items:center;gap:10px;padding:9px 13px}
.flt-hrow{background:var(--surface-2);border-bottom:1px solid var(--border);font-family:'IBM Plex Mono';font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--text-faint);font-weight:var(--fw-semi)}
.flt-row{border-bottom:1px solid var(--border);cursor:pointer;transition:.12s;content-visibility:auto;contain-intrinsic-size:auto 40px}
.flt-row:last-child{border-bottom:none}
.flt-row:nth-child(even){background:var(--zebra)}
.flt-row:hover{background:var(--surface-2);position:relative;z-index:1;transform:translateY(-1px);box-shadow:0 6px 16px -9px rgba(0,0,0,.45);border-radius:var(--radius)}
.flt-row.over{box-shadow:inset 3px 0 0 var(--red)}
.flt-row.blk{box-shadow:none}
.dev-estados{display:flex;flex-direction:column;gap:6px}
.dev-opt{display:flex;align-items:center;gap:9px;padding:9px 11px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2);cursor:pointer;font-size:12.5px;transition:.12s}
.dev-opt:hover{border-color:var(--border-strong)}
.dev-opt.on{border-color:var(--oc);background:color-mix(in srgb,var(--oc) 12%,var(--surface-2));font-weight:var(--fw-semi)}
.dev-opt input{display:none}
.dev-odot{width:15px;height:15px;border-radius:var(--radius-circ);border:2px solid var(--text-faint);flex:0 0 auto;transition:.12s}
.dev-opt.on .dev-odot{border-color:var(--oc);background:radial-gradient(circle,var(--oc) 0 42%,transparent 48%)}
.dev-ubic-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.dev-ubic-row .inp{flex:1 1 200px;min-width:0}
.dev-ubic-row .btn-map{flex:0 0 auto}
.val-wrap{display:flex;flex-direction:column;gap:14px;padding:6px 2px 4px}
.val-hero{display:flex;align-items:center;gap:13px;padding:15px 17px;border:1px solid var(--border);border-radius:var(--radius);background:linear-gradient(180deg,var(--surface),var(--bg-2))}
.val-hero-ic{width:46px;height:46px;flex:0 0 auto;border-radius:var(--radius);display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--signal) 16%,var(--surface-2));color:var(--accent-ink)}
.val-hero-t h3{margin:0;font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:15px;letter-spacing:-.3px}
.val-hero-t span{font-size:12.5px;color:var(--text-faint)}
.val-section{border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2);padding:14px 16px}
.val-sec-h{display:flex;align-items:center;gap:9px;font-size:12px;font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:.06em;color:var(--text-dim);margin-bottom:12px}
.val-num{width:21px;height:21px;border-radius:var(--radius-circ);background:var(--signal);color:var(--on-signal);display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:var(--fw-black);flex:0 0 auto}
.val-section .val-grid{margin:0}
.val-wrap2{display:flex;flex-direction:column;gap:14px;padding:6px 2px 4px}
.val-head2{display:flex;align-items:center;gap:12px;padding:0 2px}
.val-cols{display:grid;grid-template-columns:minmax(0,330px) minmax(0,1fr);gap:14px;align-items:start}
.val-colL,.val-colR{border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2);padding:15px 16px}
.val-col-h{font-size:12px;font-weight:var(--fw-bold);text-transform:uppercase;letter-spacing:.06em;color:var(--text-dim);margin-bottom:11px}
.val-colL .field{margin-bottom:11px}
.val-bigbtn{width:100%;justify-content:center;margin-top:2px}
.val-divider{height:1px;background:var(--border);margin:16px 0}
.val-colL .val-manual{margin-top:11px}
.val-stack{display:flex;flex-direction:column;gap:8px;margin-top:10px}
.val-stack .btn{width:100%;justify-content:center}
.val-colR .val-steps{margin:0 0 12px}
.val-colR .val-out{margin:0}
@media(max-width:760px){ .val-cols{grid-template-columns:1fr} }
.stock-tabs .val-tab{margin-left:auto;color:var(--accent-ink)}
.stock-tabs .val-tab.on{border-bottom-color:var(--accent-ink)}
.val-grid{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin:12px 0}
.val-actions{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:12px}
.val-actions .btn b{margin-right:4px}
.val-out{border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2);padding:14px;min-height:60px;font-size:12.5px}
.val-empty{color:var(--text-faint)}
.val-card.warn{color:var(--amber)} .val-card.ok{color:var(--green)}
.val-list{display:flex;flex-direction:column;gap:6px;margin-top:9px}
.val-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:7px 10px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);color:var(--text)}
.val-row.match{border-color:var(--green);background:color-mix(in srgb,var(--green) 10%,var(--surface))}
.val-pick{cursor:pointer} .val-pick:hover{border-color:var(--accent-ink)}
.val-macfb{font-size:11px;margin-top:4px;min-height:14px;color:var(--text-faint)}
.val-macfb.ok{color:var(--green)} .val-macfb.warn{color:var(--amber)}
.val-sub{font-size:12px;color:var(--text-faint)}
.val-badge{margin-left:auto;font-size:11px;font-weight:var(--fw-bold);padding:2px 8px;border-radius:var(--radius)}
.val-badge.ok{color:var(--green);background:color-mix(in srgb,var(--green) 14%,transparent)}
.val-badge.warn{color:var(--amber);background:color-mix(in srgb,var(--amber) 14%,transparent)}
.val-steps{display:flex;flex-direction:column;gap:8px;margin:6px 0 12px}
.vstep{display:flex;align-items:flex-start;gap:11px;padding:10px 12px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2)}
.vstep-ic{width:22px;height:22px;flex:0 0 auto;border-radius:var(--radius-circ);border:2px solid var(--text-faint);display:flex;align-items:center;justify-content:center;font-size:12px;font-weight:var(--fw-black);color:var(--text-faint);box-sizing:border-box;margin-top:1px}
.vstep.active .vstep-ic{border-color:var(--accent-ink);border-top-color:transparent;color:transparent;animation:valspin .8s linear infinite}
.vstep.ok .vstep-ic{border-color:var(--green);background:var(--green);color:#04130f;animation:none}
.vstep.err .vstep-ic{border-color:var(--red);background:var(--red);color:#fff;animation:none}
.vstep.skip .vstep-ic{border-style:dashed;animation:none}
.vstep-t{display:flex;flex-direction:column;gap:1px;min-width:0;flex:1}
.vstep-t b{font-size:12.5px}
.vstep-s{font-size:12px;color:var(--text-faint)}
.vstep.ok .vstep-s{color:var(--green)} .vstep.err .vstep-s{color:var(--red)}
.vstep-bar{height:4px;border-radius:var(--radius-sm);background:var(--surface-3);overflow:hidden;margin-top:6px;display:none}
.vstep.active .vstep-bar{display:block}
.vstep-bar>i{display:block;height:100%;width:0;background:var(--signal);transition:width .4s}
.vstep-picks:empty{display:none} .vstep-picks{margin-top:8px}
.vstep-picks .vstep-pickhint{font-size:12px;color:var(--text-faint);margin-bottom:6px}
.vstep-picks .val-list{gap:6px}
@keyframes valspin{to{transform:rotate(360deg)}}
.val-manual{margin-bottom:10px} .val-manual summary{cursor:pointer;font-size:12.5px;color:var(--text-faint);user-select:none}
.val-manual summary:hover{color:var(--text)}
.val-hint{margin-top:11px;font-size:12px;line-height:1.5;color:var(--text-faint)}
.val-save-row{display:flex;gap:8px;margin-top:12px}
.val-save-row .btn{flex:1;justify-content:center}
@media(max-width:480px){ .val-save-row{flex-direction:column} }
.val-pre{white-space:pre-wrap;word-break:break-word;font-family:'IBM Plex Mono';font-size:11px;line-height:1.4;max-height:340px;overflow:auto;background:var(--surface);padding:10px;border-radius:var(--radius);border:1px solid var(--border);color:var(--text);margin:0}
@media(max-width:680px){ .val-grid{grid-template-columns:1fr} }
@keyframes flashblink{0%,100%{background-color:transparent}50%{background-color:rgba(207,102,147,.32)}}
.flt-row.flash,.card.flash{animation:flashblink .6s ease-in-out 3;border-radius:var(--radius);outline:2px solid var(--signal);outline-offset:-2px}
.flt-due-bad{color:var(--red);font-weight:var(--fw-bold)}
.flt-done{color:var(--green)}
.flt-task{display:flex;align-items:baseline;gap:7px;min-width:0}
.flt-num{font-size:12px;font-weight:var(--fw-bold);color:var(--card-num,var(--text-faint));flex:0 0 auto}
.flt-id{font-size:11px;font-weight:var(--fw-bold);color:var(--card-num,var(--text));background:var(--surface-3);padding:1px 6px;border-radius:var(--radius-sm);flex:0 0 auto}
.flt-proj{font-size:10px;font-weight:var(--fw-bold);color:#fff;padding:2px 6px;border-radius:var(--radius-sm);flex:0 0 auto;align-self:center}
.flt-ttl{font-size:13.5px;font-weight:var(--fw-semi);line-height:1.3;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:var(--card-title,inherit)}
.flt-c{display:inline-flex;align-items:center;gap:4px;font-size:12px;color:var(--text-dim)}
.flt-c svg{width:13px;height:13px;flex:0 0 auto}
.flt-c.muted{color:var(--text-faint)}
.flt-prio{font-weight:var(--fw-black);font-size:12.5px;color:var(--text)}
.flt-dep{font-family:'IBM Plex Mono';font-size:11px;line-height:1.5}
.dep-link{cursor:pointer}
.flt-dep .dep-link{display:inline-flex;align-items:center;gap:3px;margin:1px 8px 1px 0}
.dep-link:hover{color:var(--accent-ink)}
.dep-link svg{width:12px;height:12px;flex:0 0 auto}
.dep-meta{font-family:'IBM Plex Sans';font-size:10px;color:var(--dc,var(--text-faint));white-space:nowrap}
.dep-wait{color:var(--red)} .dep-ok{color:var(--green)} .dep-gone{color:var(--text-faint);text-decoration:line-through}
.dep-wait .dep-meta{color:var(--red);font-family:inherit;font-size:inherit;font-weight:var(--fw-semi)}
.flt-dep.blk{color:var(--red)}
.flt-cdot{display:inline-block;width:8px;height:8px;border-radius:var(--radius-circ);margin:0 1px;vertical-align:middle}
.flt-cuad b{margin-left:2px}
.st-dot{width:8px;height:8px;border-radius:var(--radius-circ);display:inline-block;flex:0 0 auto;margin-right:5px}
.flt-st .st-lbl{font-size:12px;font-weight:var(--fw-bold)}
.flt-crewpanel .crew-list{display:flex;flex-direction:column;gap:8px;padding:10px}
.crew-item{border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);padding:10px 11px}
.crew-h{display:flex;align-items:center;gap:7px;font-size:12.5px}
.crew-h b{font-weight:var(--fw-bold)}
.crew-curso{margin-left:auto;font-size:11px;color:var(--green);font-weight:var(--fw-semi)}
.crew-mem{font-size:12px;color:var(--text-dim);margin:5px 0 7px;line-height:1.4}
.crew-stats{display:flex;gap:10px;font-size:11px;font-family:'IBM Plex Mono';color:var(--text-faint);flex-wrap:wrap}
.crew-stats .crew-ok{color:var(--green)} .crew-stats .crew-blk{color:var(--red)}
/* Columna Materiales (Proyectos de red) */
.flt-matpanel .mat-list{display:flex;flex-direction:column;gap:7px;padding:10px}
/* panel Cierre operativo */
.cop-item{display:flex;flex-direction:column;gap:8px;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);padding:10px 11px}
.cop-item.blk{border-color:color-mix(in srgb,#c58af9 55%,var(--border))}
.cop-item.ok{border-color:color-mix(in srgb,var(--green) 45%,var(--border))}
.cop-body{cursor:pointer;min-width:0}
.cop-h{display:flex;align-items:center;gap:6px;flex-wrap:wrap;font-size:12.5px}
.cop-chks{display:flex;flex-wrap:wrap;gap:6px}
.cop-it{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:var(--fw-semi);padding:4px 9px;border-radius:var(--radius);border:1px solid var(--border);background:var(--surface-2);color:var(--text-dim);cursor:pointer}
.cop-it .cop-ic{font-weight:var(--fw-max);font-size:12px}
.cop-it.cop-pend{border-color:color-mix(in srgb,var(--amber) 45%,var(--border));color:var(--amber)}
.cop-it.cop-hecho{border-color:var(--green);color:var(--green);background:color-mix(in srgb,var(--green) 12%,transparent)}
.cop-it.cop-na{color:var(--text-faint)}
.cop-close{align-self:flex-start;font-size:12px;font-weight:var(--fw-bold);padding:6px 14px;border-radius:var(--radius);border:1px solid var(--green);background:color-mix(in srgb,var(--green) 14%,transparent);color:var(--green);cursor:pointer}
.cop-close:disabled{border-color:var(--border);background:var(--surface-2);color:var(--text-faint);cursor:default}
.mat-item{display:flex;gap:9px;align-items:flex-start;border:1px solid var(--border);border-radius:var(--radius);background:var(--surface);padding:9px 10px}
.mat-item.done{opacity:.62}
.mat-item.blk{border-color:color-mix(in srgb,var(--red) 55%,var(--border))}
.mat-item.prep{border-color:color-mix(in srgb,#5b7aa8 55%,var(--border))}
.mat-sigla{font-family:'IBM Plex Mono';font-size:10px;font-weight:var(--fw-bold);letter-spacing:.04em;padding:1px 5px;border-radius:var(--radius-sm);flex:0 0 auto}
.mat-chk{flex:0 0 auto;width:22px;height:22px;margin-top:1px;border-radius:var(--radius-sm);border:2px solid var(--border-strong);background:transparent;color:#06210a;font-weight:var(--fw-max);font-size:13.5px;cursor:pointer;display:flex;align-items:center;justify-content:center;line-height:1}
.mat-chk.on{background:var(--green);border-color:var(--green)}
.mat-body{flex:1;min-width:0;cursor:pointer}
.mat-h{display:flex;align-items:center;gap:6px;flex-wrap:wrap;font-size:12.5px}
.mat-h b{font-weight:var(--fw-bold)}
.mat-item.done .mat-h b{text-decoration:line-through}
.mat-blk{font-size:11px;color:var(--red);font-weight:var(--fw-bold)}
.mat-mats{font-size:12px;color:var(--text-dim);margin-top:3px;line-height:1.4;word-break:break-word}
.flt-est{display:inline-flex;align-items:center;gap:6px;font-size:12px;font-weight:var(--fw-semi)}
.flt-estdot{width:7px;height:7px;border-radius:var(--radius-circ);flex:0 0 auto}
.flt-clabel{display:none}
@media(max-width:680px),(max-height:480px){
  .flt-hrow{display:none}
  .flt-row{display:flex;flex-wrap:wrap;align-items:center;gap:5px 14px;padding:11px 13px}
  .flt-task{flex:1 1 100%}
  .flt-clabel{display:inline;color:var(--text-faint);font-size:10px;margin-right:2px;text-transform:uppercase;letter-spacing:.05em}
}

/* --- Matriz (grupo x etapa) --- */
.fl-matrix{display:grid;gap:6px;align-items:stretch}
.fl-mh{position:sticky;top:0;z-index:6;background:var(--bg);padding-bottom:6px}
.fl-gh{display:flex;align-items:center;justify-content:center;gap:6px;background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:8px 6px}
.fl-gh-ttl{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:12px;text-align:center;line-height:1.1}
.fl-stlabel{display:flex;flex-direction:column;justify-content:center;gap:4px;padding:8px 6px;border-radius:var(--radius);background:var(--bg-2);border:1px solid var(--border)}
.fl-stlabel .nm{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:11px;line-height:1.15;color:var(--text-dim)}
.fl-stlabel .cnt{font-family:'IBM Plex Mono';font-size:10px;color:var(--text-faint)}
.fl-cell{background:var(--bg-2);border:1px solid var(--border);border-radius:var(--radius);padding:6px;min-height:44px}
.fl-cell.empty{display:flex;align-items:center;justify-content:center;color:var(--text-faint);opacity:.3}
.fl-mini{position:relative;background:var(--card-bg,var(--surface-2));border:1px solid var(--border);border-radius:var(--radius);padding:6px 7px 6px 11px;margin-bottom:6px;overflow:hidden;cursor:pointer}
.fl-mini:last-child{margin-bottom:0}
.fl-mini:hover{border-color:var(--border-strong)}
.fl-mini.over{border-color:rgba(255,91,110,.5)}
.fl-mini-bar{position:absolute;left:0;top:0;bottom:0;width:3px}
.fl-mini-top{display:flex;align-items:center;gap:5px}
.fl-mini-id{font-size:9px;font-weight:var(--fw-bold);color:var(--card-num,var(--text-faint))}
.fl-mini-proj{font-size:9px;font-weight:var(--fw-bold);color:#fff;padding:1px 4px;border-radius:var(--radius-sm)}
.fl-mini-flag{margin-left:auto;display:inline-flex}
.fl-mini-flag svg{width:12px;height:12px}
.fl-mini-ttl{font-size:11px;font-weight:var(--fw-semi);line-height:1.25;margin-top:3px;color:var(--card-title,inherit)}
.fl-mini-ic{display:flex;flex-wrap:wrap;gap:7px;align-items:center;font-size:10px;color:var(--text-dim);margin-top:4px}
.fl-mini-ic span{display:inline-flex;align-items:center;gap:2px}
.fl-mini-ic svg{width:11px;height:11px}
.fl-mini-ic .over{color:var(--red);font-weight:var(--fw-bold)}
.fl-mini-ic .blk{color:var(--red)}
@media(max-width:680px),(max-height:480px){
  .fl-body{padding:4px 10px calc(20px + env(safe-area-inset-bottom))}
  .fl-lane-body{grid-template-columns:1fr}
  .fl-row{grid-template-columns:auto 1fr;gap:8px}
  .fl-rid{display:none}
  .fl-rright{grid-column:1 / -1;justify-content:flex-start}
  .fl-gh-ttl{font-size:10px}
  .fl-stlabel .nm{font-size:10px}
  .fl-mini-ttl{font-size:10px}
}
.stats-head-l{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.stats-period{display:flex;gap:0;background:transparent;border:0;border-bottom:1px solid var(--border-strong);border-radius:0;padding:0}
.stats-period button{padding:7px 13px;font-size:12.5px;background:transparent;border:0;border-bottom:2px solid transparent;border-radius:0;color:var(--text-dim);font-weight:var(--fw-normal);transition:none}
.stats-period button.on{background:transparent;color:var(--text);font-weight:var(--fw-semi);border-bottom-color:var(--accent-ink)}
.kpi-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:14px;margin-bottom:22px}
/* Sin degradado: el fondo de un panel es un color. Y menos aire, que en clásico los datos van
   apretados y lo que los separa es la línea. */
.kpi{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:13px 16px}
/* Los números se leen en columna y se comparan: con ancho fijo las cifras se alinean. */
.kpi .k-num, .diag-kpi .k-num, .nov-kpi .k-num{font-family:'IBM Plex Mono',ui-monospace,monospace;font-variant-numeric:tabular-nums;letter-spacing:-.01em}
.kpi .k-lbl{font-size:11px;letter-spacing:.11em;text-transform:uppercase;color:var(--text-faint);font-weight:var(--fw-semi)}
.kpi .k-num{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:27px;margin-top:9px;letter-spacing:-.6px;line-height:1}
.kpi .k-num small{font-size:14px;font-weight:var(--fw-bold);color:var(--text-dim);margin-left:5px;letter-spacing:0}
.kpi .k-sub{font-size:12px;color:var(--text-faint);margin-top:6px}
.kpi.accent{border-color:rgba(147,37,90,.35)}
.kpi.accent .k-num{color:var(--accent-ink)}
@media(max-width:560px){ .kpi .k-num{font-size:22px} }
.report{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);overflow:hidden;margin-bottom:18px}
.stats-sec{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:15px;letter-spacing:-.2px;margin:24px 0 13px}
.stats-grid2 .report{margin-bottom:0}
.report > h3{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:13.5px;padding:15px 18px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:9px}
.report > h3 svg{width:16px;height:16px;color:var(--accent-ink)}
.tbl{width:100%;border-collapse:collapse}
/* El dibujo común del sistema: sin versales, cabecera con fondo y la línea en --border-strong.
   Tenía 11 px de alto y 18 de costado, casi el doble que cualquier otra tabla. */
.tbl th,.tbl td{text-align:left;padding:7px 10px;font-size:12.5px;border-bottom:1px solid var(--border-strong);vertical-align:middle}
.tbl th{font-size:11px;letter-spacing:0;text-transform:none;color:var(--text-dim);font-weight:var(--fw-semi);
  background:var(--surface-3);padding:6px 10px}
.tbl tr:last-child td{border-bottom:none}
@media(max-width:680px),(max-height:480px){ .report{overflow-x:auto;-webkit-overflow-scrolling:touch} .tbl th,.tbl td{padding:7px 9px;font-size:12px} }
@media(max-width:680px),(max-height:480px){ .qb{width:34px;height:34px;font-size:16px} .stk-b,.onu-open{width:38px;height:38px} .stk-b svg,.onu-open svg{width:16px;height:16px} }
/* Acá había tres reglas de celular para Configuración y dos apuntaban a elementos que ya no existen:
   `.vhead` y `.set-tabs` son de cuando la pantalla tenía su propio encabezado y su propia tira de
   solapas, antes de pasar al panel del sistema. Sólo aterrizaba la tercera. El relleno de `#cfgBody`
   se resuelve ahora en el bloque de arreglos de celular del final, junto con el del panel. */
.tbl td.num{text-align:right;font-family:'IBM Plex Mono';font-weight:var(--fw-semi)}
.tbl td.idcell{text-align:left;font-family:'IBM Plex Mono';font-weight:var(--fw-semi)}
.tbl .who-cell{display:flex;align-items:center;gap:10px}
.tbl .who-cell .avatar{width:28px;height:28px;border-radius:var(--radius);font-size:11px}
.km-bar{height:6px;border-radius:var(--radius-sm);background:var(--surface-3);overflow:hidden;margin-top:6px;min-width:80px}
.km-bar>div{height:100%;background:linear-gradient(90deg,var(--signal-dim),var(--signal));border-radius:var(--radius-sm)}
.report-empty{padding:26px 18px;text-align:center;color:var(--text-faint);font-size:12.5px}
.stats-grid2{display:grid;grid-template-columns:1fr 1fr;gap:18px;align-items:start;margin-bottom:18px}
@media(max-width:900px){ .stats-grid2{grid-template-columns:1fr} }
@media(max-width:760px){
  #statsWrap,#statsView{overflow-x:hidden;max-width:100%}
  #statsWrap .kpi-grid{grid-template-columns:1fr 1fr;gap:10px}
  #statsWrap .kpi{min-width:0}
  #statsWrap .k-num{font-size:24px}
  #statsWrap .stats-sec{font-size:15px}
}
@media(max-width:400px){ #statsWrap .kpi-grid{grid-template-columns:1fr} }
.bl-label{display:flex;align-items:center;gap:8px;font-size:12.5px;min-width:0}
.bl-label span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bl-label .avatar{width:24px;height:24px;border-radius:var(--radius-sm);font-size:10px}
.oz-sector{padding:13px 18px;border-bottom:1px solid var(--border)}
.oz-sector:last-child{border-bottom:none}
.oz-name{font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:13.5px;margin-bottom:9px}
.oz-line{display:grid;grid-template-columns:54px 1fr 120px;align-items:center;gap:11px;margin-top:6px;font-size:12px;color:var(--text-dim)}
.oz-line b{text-align:right;font-family:'IBM Plex Mono';font-weight:var(--fw-semi);color:var(--text)}
.diag-drop{border:1.5px dashed var(--border-strong);border-radius:var(--radius);padding:14px 12px;text-align:center;cursor:pointer;outline:none;transition:.15s;display:flex;flex-direction:column;align-items:center;gap:8px}
.diag-drop:hover{border-color:var(--accent-ink)}
.diag-drop:focus{border-color:var(--accent-ink);background:var(--surface);box-shadow:0 0 0 3px rgba(147,37,90,.12)}
.diag-drop .dd-txt{font-size:12.5px;color:var(--text-dim);line-height:1.7}
.diag-drop .dd-file{font-size:12px;color:var(--accent-ink);font-weight:var(--fw-semi);text-decoration:underline;background:none;border:none;cursor:pointer}

@media(max-width:780px){
  #login{display:block;overflow:auto;overflow-x:hidden;padding:0}
  .map-aside{flex-basis:200px}
  .login-card{grid-template-columns:1fr !important;min-width:0;width:100% !important;max-width:100% !important;margin:0 !important;border:none;border-radius:0;min-height:100vh;min-height:100dvh}
  .login-aside{padding:30px 22px calc(28px + env(safe-area-inset-top));padding-top:calc(30px + env(safe-area-inset-top));border-right:none;border-bottom:1px solid var(--border);min-width:0}
  .login-aside .tagline{font-size:24px;margin-top:12px;margin-bottom:10px}
  .login-aside p{display:none}
  .login-aside .login-meta{margin-top:14px}
  .login-main{padding:28px 22px;min-width:0}
  .login-form .inp,.login-form .btn-primary{width:100% !important;max-width:100% !important;min-width:0}
  .grid2{grid-template-columns:1fr}
  .stats{flex-wrap:wrap}
}

/* ---------- celular / PWA ---------- */
@media(max-width:680px),(max-height:480px){
  /* barra superior: compacta y respetando el notch */
  .topbar{padding:calc(6px + env(safe-area-inset-top)) 12px 6px;gap:6px;row-gap:6px}
  .topbar .brand h1{font-size:15px}
  .topbar .brand .glyph{width:28px;height:28px}
  .brand-ver{font-size:9px}
  .area-switch button,.view-switch button{padding:6px 9px;font-size:12px}
  .area-switch,.view-switch{padding:2px}
  .me{padding:2px}
  /* orden prolijo: fila 1 = marca + acciones · fila 2 = pestañas */
  .topbar .divider{display:none}
  .topbar .brand{order:1}
  .topbar-spacer{order:2;flex:1 1 auto;height:auto}

  #meBox{order:3}
  #meBox .who{display:none}
  #bellBtn{order:4}
  #themeBtn{order:5}
  #logoutBtn{order:6}
  #viewSwitch{order:7;flex-basis:100%;flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;-webkit-overflow-scrolling:touch}
  #viewSwitch::-webkit-scrollbar{display:none}
  #viewSwitch button{flex:0 0 auto}
  #viewSwitch button svg{display:none}   /* sin íconos en móvil: gana lugar y entran los 4 */
  /* técnico: solo 2 pestañas → que ocupen todo el ancho (mitad y mitad) */
  .tec-view #viewSwitch{overflow-x:visible}
  .tec-view #viewSwitch button{flex:1 1 0;justify-content:center;text-align:center}
  /* dentro de Tablero: ventanas en su fila, separador oculto, hint abajo */
  .fl-wsep{display:none}
  #flowView .fl-hint{flex-basis:100%}
  /* admin/coord: acciones colapsadas en el menú del avatar + botón flotante (FAB) */
  body.can-manage #themeBtn,
  body.can-manage #logoutBtn,
  body.can-manage #actSwitch{display:none !important}
  body.can-manage #bellBtn{order:3}
  body.can-manage #meBox{order:4;cursor:pointer}
  body.can-manage #meBox::after{content:"";margin-left:1px;border-left:4px solid transparent;
    border-right:4px solid transparent;border-top:5px solid var(--text-dim)}
  .umenu.open{display:flex}
  .umscrim.open{display:block}
  .fab-wrap.show{display:flex}
  /* barra de filtros */
  .toolbar{padding:7px 12px;gap:7px;row-gap:7px}
  /* barra de ventanas (Mantenimiento/Infra/Anotaciones/Agenda): que envuelva en 2 filas y no desborde */
  #toolbar .area-switch{flex:1 1 100%;flex-wrap:wrap;height:auto;max-width:100%}
  #toolbar .area-switch button{flex:1 1 auto;justify-content:center;height:34px}
  #searchBox{width:auto!important;flex:1 1 120px;min-width:110px}
  /* emparejar altura de Buscar y Filtros en móvil (Buscar usa 16px por el zoom de iOS) */
  #filtBtn{font-size:15px}
  #searchBox,#filtBtn{height:42px}
  .filt-panel{position:fixed;left:12px;right:12px;top:auto;min-width:0}
  /* conteos: una sola fila deslizable (no apila) */
  .tb-counts{flex-wrap:nowrap;overflow-x:auto;width:100%;padding-left:0;margin-left:0;border-left:none;scrollbar-width:none}
  .tb-counts::-webkit-scrollbar{display:none}
  .sc{padding:4px 8px;font-size:11px;flex:0 0 auto}
  /* tablero en celular: columnas apiladas a lo ancho (sin scroll horizontal), como Proyectos de red */
  /* El colchón de abajo tiene que dejar pasar al botón «+», que mide 115 px de alto y arranca a 133 px del fondo:
     con 14 px, las dos últimas tarjetas quedaban debajo del botón y tapaba justo el renglón del pie
     —medido: ocultaba «Vence 23 jul · 21d / Sin asignar»—, que es la fecha, o sea lo único que
     alguien mira apurado. Se puede scrollear hasta pasarlas. */
  .board{padding:12px 12px calc(150px + env(safe-area-inset-bottom));gap:12px;flex-direction:column;overflow-x:hidden;overflow-y:auto;align-items:stretch}
  .col{flex:0 0 auto;width:100%;max-height:none}
  .col-body{max-height:none;overflow:visible}
  .board-wm .wm-title{font-size:clamp(18px,6.5vw,30px);letter-spacing:.08em}
  /* en Configuración (móvil) ocultamos los chips de preview: liberan ancho para el nombre */
  .set-row .grupo-chip,.set-row .tipo-chip,.set-row .proj-chip{display:none}
  /* ficha de la tarea a PANTALLA COMPLETA */
  #scrim,#setScrim{padding:0;align-items:stretch;overflow:hidden}
  #scrim .modal,#setScrim .modal{width:100%;max-width:100%;height:100%;min-height:0;border-radius:0;display:flex;flex-direction:column;animation:none}
  #scrim .modal-head,#scrim .set-tabs,#scrim .modal-foot,#setScrim .modal-head,#setScrim .modal-foot{flex:0 0 auto}
  #scrim .modal-body,#setScrim .modal-body{max-height:none;flex:1 1 auto;min-height:0;overflow:auto;-webkit-overflow-scrolling:touch}
  .modal-head{padding-top:calc(14px + env(safe-area-inset-top));padding-bottom:11px}
  .modal-head h3{font-size:15px;margin-top:2px}
  /* formulario de tarea COMPACTO en móvil: entra más en pantalla */
  #scrim .modal-body{padding:12px 13px;gap:10px}
  #scrim .mpanel{gap:10px}
  #scrim .field{gap:4px}
  #scrim .field>label{font-size:10px;letter-spacing:.07em}
  #scrim .grid2{grid-template-columns:1fr 1fr;gap:9px}
  #scrim .f-sec{margin:2px 0 -3px;padding-top:5px}
  #scrim .ta{min-height:52px;line-height:1.4}
  #scrim .ta-tall{min-height:78px}
  #scrim .inp,#scrim .ta,#scrim .sel{padding:9px 11px}
  .tec-view #scrim .inp,.tec-view #scrim .ta,.tec-view #scrim .sel{font-size:15px;padding:9px 11px}
  .tec-view #scrim .field>label{font-size:11px;letter-spacing:.05em}
  .tec-view #scrim .set-tab{font-size:13.5px;padding:11px 13px}
  /* pestañas de la ficha: una sola fila deslizable (no se parten). Respetan el notch/barra de estado del iPhone (este modal no tiene modal-head) */
  #scrim .set-tabs{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;gap:2px;padding-top:calc(6px + env(safe-area-inset-top));align-items:center}
  #scrim .set-tabs::-webkit-scrollbar{display:none}
  #scrim .set-tab{flex:0 0 auto;white-space:nowrap;padding:12px 14px}
  /* footer ordenado: secundarios envuelven sin superponerse (2 por fila), "Guardar" a lo ancho abajo */
  .modal-foot{padding:11px 16px calc(12px + env(safe-area-inset-bottom));gap:8px;flex-wrap:wrap;border-top:1px solid var(--border)}
  .modal-foot .grow{display:none}
  .modal-foot .btn-ghost,.modal-foot .btn-danger{flex:1 1 auto;min-width:0;justify-content:center;padding:11px 10px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .modal-foot .btn-primary{flex:1 1 100%;justify-content:center;padding:13px;order:9}
  #uiScrim{padding:16px}
  /* 16px en inputs evita el zoom automático de iOS al enfocar */
  .inp,.ta,.sel,.fl{font-size:15px}
  /* OZmap a pantalla completa: la lista de sectores es un panel deslizable */
  .map-aside-toggle{display:inline-flex;top:52px}
  .map-aside{position:absolute;left:0;top:0;bottom:0;z-index:1100;width:min(85vw,330px);flex-basis:auto;transform:translateX(-100%);transition:transform .25s ease;box-shadow:0 0 40px rgba(0,0,0,.65)}
  .map-aside.open{transform:none}
  .ea-close{display:inline-flex}
  .map-basemap{top:auto;bottom:14px;left:12px}
  /* Capas y Referencias: dos íconos chiquitos que abren/cierran el panel */
  .map-toggles{display:flex}
  .map-layers{display:none;right:12px;top:60px;left:auto;max-height:60vh;overflow-y:auto}
  .map-layers.open{display:flex}
  .map-legend.shown{display:none}
  .map-legend{right:12px;top:60px;bottom:auto;left:auto;max-height:60vh;overflow-y:auto}
  .map-legend.shown.open{display:block}
}

/* ====================== IMPRESIÓN (formulario) ====================== */
@media screen { #printArea{display:none} }
@media print {
  html,body{background:#fff !important}
  body::before{display:none !important}
  body > *{display:none !important}
  #printArea{display:block !important}
  @page{ size:A4 portrait; margin:13mm }
  @page pgland{ size:A4 landscape; margin:10mm }
  .pf{color:#111;font-family:'IBM Plex Sans',Arial,sans-serif;font-size:11.5pt;line-height:1.45;display:flex;flex-direction:column;min-height:calc(100vh - 4mm);box-sizing:border-box}
  .pf-head{display:flex;justify-content:space-between;align-items:center;border-bottom:2px solid #111;padding-bottom:7px;margin-bottom:10px}
  .pf-brand{font-family:'IBM Plex Sans',sans-serif;font-weight:var(--fw-bold);font-size:15pt}
  .pf-brand span{font-weight:var(--fw-semi);color:#666;font-size:11pt}
  .pf-id{font-family:'IBM Plex Mono',monospace;font-weight:var(--fw-bold);font-size:13pt;border:1.5px solid #111;padding:3px 10px;border-radius:var(--radius-sm)}
  .pf-title{font-family:'IBM Plex Sans',sans-serif;font-weight:var(--fw-bold);font-size:17pt;margin:4px 0 8px}
  .pf-chips{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:12px}
  .pf-tag{border:1px solid #888;border-radius:var(--radius-sm);padding:2px 8px;font-size:9.5pt;font-weight:var(--fw-semi)}
  .pf-day{font-size:9.5pt;color:#555;margin-left:4px}
  .pf-grid{display:grid;grid-template-columns:1fr 1fr;gap:4px 24px;margin-bottom:10px}
  .pf-d{display:flex;gap:8px;border-bottom:1px dotted #bbb;padding:3px 0}
  .pf-dl{color:#666;min-width:130px;font-size:10pt}
  .pf-dv{font-weight:var(--fw-semi)}
  .pf-desc{margin:6px 0 10px;font-size:10.5pt}
  .pf-section{font-family:'IBM Plex Sans',sans-serif;font-weight:var(--fw-bold);font-size:11pt;border-bottom:1px solid #111;margin:14px 0 8px;padding-bottom:3px;text-transform:uppercase;letter-spacing:.04em;break-after:avoid;page-break-after:avoid}
  .pf-items div{padding:3px 0;font-size:10.5pt}
  .pf-pasos{margin:6px 0 0;padding:0;font-size:10.5pt;line-height:1.5}
  .pf-paso{padding:9px 0;break-inside:avoid;page-break-inside:avoid}
  .pf-paso b{margin-right:2px}
  .pf-box{display:inline-block;width:13px;height:13px;border:1.5px solid #111;border-radius:var(--radius-xs);margin-right:7px;vertical-align:-2px;text-align:center;line-height:11px;font-size:10px;font-weight:var(--fw-bold)}
  .pf-note{margin-top:6px;font-size:10pt;color:#333}
  .pf-items div{break-inside:avoid;page-break-inside:avoid}
  #printArea img{max-width:100% !important}
  .pf-img{display:block;width:auto;max-width:100%;max-height:78mm;border:1px solid #999;border-radius:var(--radius-sm);margin:7px auto;object-fit:contain;break-inside:avoid;page-break-inside:avoid}
  .pf-imgwrap{break-inside:avoid;page-break-inside:avoid;text-align:center}
  .pf-block{break-inside:avoid;page-break-inside:avoid}
  .pf-imgs{display:grid;gap:8px;break-inside:avoid;page-break-inside:avoid;margin-top:6px}
  .pf-imgs.n1{grid-template-columns:1fr}
  .pf-imgs.n2,.pf-imgs.n3{grid-template-columns:1fr 1fr}
  .pf-imgs .pf-imgcell{break-inside:avoid;page-break-inside:avoid}
  .pf-imgs .pf-imgcell img{width:100%;max-height:155mm;object-fit:contain;border:1px solid #999;border-radius:var(--radius-sm);display:block}
  .pf-imgs.n2 .pf-imgcell img,.pf-imgs.n3 .pf-imgcell img{max-height:108mm}
  /* cada imagen/ubicación en su propia hoja completa, al final */
  .pf-imgpage{page:pgland;break-before:page;page-break-before:always;break-inside:avoid;page-break-inside:avoid;text-align:center}
  .pf-imgcap{font-family:'IBM Plex Mono',monospace;font-size:9pt;color:#555;text-align:left;margin-bottom:4mm}
  .pf-imgpage img{display:block;margin:0 auto;width:auto;height:auto;max-width:100%;max-height:182mm;object-fit:contain;border:1px solid #999;border-radius:var(--radius-sm)}
  .pf-sign{display:flex;justify-content:space-between;align-items:flex-end;margin-top:auto;padding-top:7mm;border-top:1px solid #ccc;font-size:10.5pt;break-inside:avoid;page-break-inside:avoid}
  .pf-foot{margin-top:14px;border-top:1px solid #ccc;padding-top:6px;font-size:8.5pt;color:#888;text-align:center}
  .pf-lines{border:1px dashed #bbb;border-radius:var(--radius-sm);height:52px;margin-top:3px}
  .pf-lines.sm{height:84px}
  .pf-rep{font-size:10pt;margin-top:8px;color:#333}
  .pf-checks{font-size:10pt;margin-bottom:4px;font-weight:var(--fw-semi)}
}

/* ===== Celular, segunda pasada (25/08/2026) — VA AL FINAL A PROPOSITO =====
   La primera version de estas reglas quedo en el medio de la hoja y varias no tomaron: no era el
   selector, era el ORDEN. La regla ".role-chip{font-size:11px}" vive 400 lineas mas abajo y ganaba
   por venir despues; ".cm-clirow .cm-est{font-size:10px}" ganaba por especificidad. Puestas al final
   de la hoja, y con la especificidad justa donde hace falta, se cumplen.
   Es el mismo motivo que ya esta anotado mas arriba en esta hoja: un @media NO suma especificidad,
   asi que meter una regla dentro de un media query no le gana a nada por si solo.
   Que se corrige: la primera pasada fue en agosto y las pantallas que se sumaron despues no la
   heredaron. Medido sobre las 36 en un telefono de 412 px. Se corrige por SELECTOR, no por
   pantalla, para que lo herede lo que venga. */
@media(max-width:760px){
  /* Botones de verdad que quedaron por debajo del dedo */
  button.stk-b,button.rc-task,button.cja-lockbtn,button.graf-lupa,button.alt-alta{min-height:34px;height:auto}
  button.stk-b,button.rc-task{min-width:34px;padding-left:8px;padding-right:8px}
  /* Enlaces dentro de tablas: son la mayoria de los toques chicos (16 px, el alto de una linea).
     No se les pone alto fijo, que rompe la grilla: se les da aire arriba y abajo. */
  /* 9 px arriba y abajo, no 7: con 7 quedaban en 30 px y el objetivo son 34. Se midió uno por uno —
     eran 282 enlaces de tabla, el 93% de todos los toques chicos que quedaban— y con este cambio
     entran todos. El `min-width` es para los códigos cortos tipo «Z2K», que quedaban de 23 px de
     ancho: se ensancha el blanco de toque sin tocar el ancho de la columna, que lo fija la celda. */
  td a,th a,.sup-tk a,a.cm-clinum,.cor-tramo a{display:inline-block;min-width:30px;
    padding-top:9px;padding-bottom:9px;padding-left:3px;padding-right:3px}
  /* Los dos botones de tipo de mapa (Calle / Satélite) quedaron en 27-28 px. */
  .earth-base button,.map-basemap button{min-height:34px}
  /* Los candidatos de «Equipos sin identificar» son enlaces sueltos dentro de una tarjeta, no de
     una tabla, asi que la regla de arriba no los alcanzaba: son 38 y quedaban en 16 px. */
  .eq-cand a{display:inline-block;padding-top:9px;padding-bottom:9px}
  /* Las pastillas del aviso de Equipos (Sin identificar / En otra posicion) quedaban en 26 px. */
  button.cm-kchip{min-height:34px}
  /* Nada por debajo de 11 px. Los dos ultimos necesitan la especificidad de quien los pisaba. */
  /* .ocl-l son las micro-etiquetas en mayuscula que rotulan cada dato (SENAL, OLT, CAJA...).
     Son 282 en las 36 pantallas: de lejos lo mas repetido por debajo de 11 px. */
  .prio-acc,.rc-dx,.rc-sub,.cor-lbl,.so-navi-badge,.sup-tk th,
  .ocl-l,.sector-label,.alt-vd{font-size:11px}
  /* El <small> ya tenia regla mas arriba en la hoja, pero la pisaban las reglas propias de cada
     pantalla que vienen despues. Repetida aca al final, se cumple. */
  small,.sup-tk small,.so-panel small{font-size:11px}
}
/* ===== La celda de senal, tocable =====
   Pedido de Matias (25/08/2026): poder tocar la senal de un cliente y ver la de todos los de su
   caja. El dialogo ya existia —flAbrirCaja(), el mismo que abre el nombre de la caja— asi que lo
   unico que faltaba era la puerta. Se pone en la celda de senal porque es donde la persona ya
   esta mirando cuando le surge la pregunta: «este esta en -30, y los vecinos?».
   Tiene que NOTARSE que se toca: la linea de la caja va en color de acento con una flecha, no en
   gris de nota al pie como estaba. El numero grande sigue siendo el dato principal. */
.fl-sencel{display:block;width:100%;text-align:left;background:none;border:0;padding:2px 0;
  font-family:inherit;color:inherit;cursor:pointer;border-radius:var(--radius-sm)}
.fl-sencel .fs-rx{display:block;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13.5px}
.fl-sencel .fs-caja{display:flex;align-items:center;gap:3px;margin-top:1px;
  font-size:11px;color:var(--accent-ink);white-space:nowrap}
.fl-sencel .fs-caja svg{width:12px;height:12px;flex:0 0 auto;opacity:.8}
.fl-sencel:hover{background:color-mix(in srgb,var(--signal) 12%,transparent)}
.fl-sencel:hover .fs-caja{text-decoration:underline}
@media(max-width:760px){ .fl-sencel{padding:6px 0} .fl-sencel .fs-caja{white-space:normal} }
/* «o peor»: el modelo no informa por debajo de ese valor, así que el número que se ve es un tope y
   no una medición. Va en ámbar y no en rojo a propósito — no dice que esté peor, dice que no
   sabemos cuánto, que es otra cosa y lleva a otra decisión. */
/* La columna de señal de la lista de críticos lleva el dBm, la chapita «o peor» y el aviso de
   errores de transmisión. Sin un ancho mínimo el navegador se la comía y el aviso salía en columna
   de una palabra por renglón: «y / además / transmite / con / errores». */
.fc-sen{min-width:190px}
@media(max-width:760px){ .fc-sen{min-width:0} }
/* MISMA FORMA QUE `.seg-badge`, la chapita que ya usa el sistema en estas mismas tablas para
   «infectado» y «escaneando»: 2px 9px, radio 10, 11,5px, peso 700, borde y fondo sacados de
   `currentColor`. La primera versión de esto tenía radio 999, 10,5px y mayúsculas — una chapita
   distinta a dos centímetros de la otra, en la misma fila. El color va inline, que es como se pinta
   la otra.
   No se reusa `.seg-badge` directamente porque esa regla la inyecta «Ataques e infectados» recién
   cuando se abre esa pantalla: acá quedaría sin estilo hasta que alguien pase por allá. */
.fc-piso{display:inline-block;margin-left:6px;padding:2px 9px;border-radius:var(--radius-xl);font-size:11.5px;
  font-weight:var(--fw-bold);white-space:nowrap;border:1px solid currentColor;
  background:color-mix(in srgb,currentColor 12%,transparent)}
@media(max-width:760px){
  /* Los ultimos dos: encabezados de tabla y las etiquetas de los medidores. */
  /* .tbl th le ganaba a table th: clase+elemento pesa mas que dos elementos. Se IGUALA la
     especificidad en vez de escalarla, y gana por venir despues. */
  table th,.sup-tk th,.db-th,.tbl th{font-size:11px}
  .k{font-size:11px}
  div.cja-mg,.cja-mg{font-size:11px}
  span.role-chip,.cm-est,.cm-clirow .cm-est{font-size:11px}
}

/* ===== Reincidentes y Gestiones: los controles del periodo =====
   La franja que los contiene es `.fl-barra` —la misma de Caidas—, no una propia: habia una
   `.re-perbar` que hacia lo mismo peor (envolvia en dos filas en vez de desplazarse de costado) y
   se quedo sin dueño cuando las dos pantallas pasaron a la franja comun. Lo que sigue es lo de
   adentro: el desplegable, la linea que dice contra que fechas se cuenta, y el rango a mano. */
/* El desplegable del período: un control en lugar de doce botones en dos renglones. */
.re-sel{background:var(--surface-2);border:1px solid var(--border);border-radius:var(--radius);color:var(--text);
  font-family:inherit;font-size:12.5px;font-weight:var(--fw-semi);padding:6px 10px;min-height:32px;cursor:pointer}
.re-sel:focus{outline:none;border-color:var(--accent-ink)}
/* Qué se está contando, al lado y en voz baja: es contexto, no una decisión. */
.re-dice{font-size:12px;color:var(--text-dim)}
.re-dice b{color:var(--text)}
.re-rango{display:flex;align-items:center;gap:8px;flex-wrap:wrap;padding:4px 8px;
  border:1px solid var(--border);border-radius:var(--radius);background:var(--surface-2)}
.re-rango label{display:flex;align-items:center;gap:5px;font-size:12px;color:var(--text-dim);white-space:nowrap}
.re-rango input[type=date]{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-sm);
  color:var(--text);font-family:inherit;font-size:12.5px;padding:5px 7px;min-height:32px}
.re-rango input[type=date]:focus{outline:none;border-color:var(--accent-ink)}
@media(max-width:760px){
  .re-rango{justify-content:space-between}
  .re-rango label{flex:1 1 46%}
  .re-rango input[type=date]{width:100%;min-height:36px}
}

/* ===== Codigo de gestion: el boton de la fila y el aviso ===== */
.fg-btn{display:inline-flex;align-items:center;gap:4px;margin-left:7px;vertical-align:middle;
  background:color-mix(in srgb,var(--signal) 12%,transparent);border:1px solid color-mix(in srgb,var(--signal) 40%,var(--border));
  color:var(--accent-ink);border-radius:var(--radius-sm);padding:3px 7px;font-family:inherit;font-size:11px;
  font-weight:var(--fw-semi);cursor:pointer;line-height:1.2}
.fg-btn:hover{background:color-mix(in srgb,var(--signal) 24%,transparent)}
.fg-btn svg{width:12px;height:12px;flex:0 0 auto}
/* El aviso va fijo abajo a la derecha: no tapa la tabla y se ve sin mover la vista. */
.fg-toast{position:fixed;right:18px;bottom:18px;z-index:9999;max-width:min(420px,92vw);
  display:none;align-items:center;gap:10px;padding:12px 15px;border-radius:var(--radius);
  background:var(--surface);border:1px solid color-mix(in srgb,var(--signal) 55%,var(--border));
  box-shadow:0 12px 34px rgba(0,0,0,.42);font-size:12.5px;color:var(--text)}
.fg-toast.on{display:flex}
.fg-toast b{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12.5px;color:var(--accent-ink);white-space:nowrap}
.fg-toast span{color:var(--text-dim)}
/* Cuando no se pudo copiar el cartel se queda y el codigo se puede seleccionar de un toque. */
.fg-toast.fg-mal{border-color:var(--amber);flex-wrap:wrap}
.fg-toast .fg-sel{cursor:text;user-select:all;background:var(--surface-2);padding:4px 8px;border-radius:var(--radius-sm)}
@media(max-width:760px){ .fg-toast{left:12px;right:12px;bottom:12px;max-width:none} .fg-btn span{display:none} }

/* El enlace a Telwinet de cada fila: mismo peso visual que el boton del codigo, pero distinto
   color para que se distingan de un vistazo — uno lleva afuera, el otro copia. */
.fg-tw{display:inline-flex;align-items:center;gap:4px;margin-left:7px;vertical-align:middle;
  background:var(--surface-2);border:1px solid var(--border);color:var(--text-dim);
  border-radius:var(--radius-sm);padding:3px 7px;font-size:11px;font-weight:var(--fw-semi);text-decoration:none;line-height:1.2}
.fg-tw:hover{color:var(--text);border-color:var(--border-strong);background:var(--surface-3)}
.fg-tw svg{width:12px;height:12px;flex:0 0 auto}
@media(max-width:760px){ .fg-tw span{display:none} }
/* ---- LOS BOTONES DE FILA, EN EL CELULAR, TIENEN QUE PODER TOCARSE ----
   En pantalla angosta a estos dos botones se les esconde el texto y queda sólo el ícono. Eso está
   bien —el nombre no entra—, pero los dejaba en unos 21 px de alto: con 11 px de letra y 3 px de
   relleno no hay dedo que acierte, y son los botones con los que se gestiona un cliente desde la
   calle. Medido en un Pixel emulado sobre «Caídas de clientes»: 477 botones de gestión y 159 de
   ficha, TODOS por debajo de los 32 px.
   32 px es el piso práctico —Google recomienda 48 para un blanco aislado, pero acá van pegados a su
   fila y con separación—. Sólo aplica en el celular: en la computadora el puntero es preciso y
   agrandarlos ahí estiraría todas las filas de todas las tablas sin ganar nada. */
@media(max-width:760px){
  .fg-btn,.fg-tw{min-height:32px;min-width:32px;justify-content:center;padding:6px 9px;margin-left:6px}
  .fg-btn svg,.fg-tw svg{width:14px;height:14px}
  /* Lo mismo para los botones chicos que viven ADENTRO de una celda —«Editar», «✕», «+wsp»,
     «Abrir»— y para los filtros del encabezado de columna. Con 11 px de letra y 2 px de relleno
     quedaban en 19 px. Se acota a las celdas a propósito: el mismo botón en una barra de
     herramientas está rodeado de espacio y agrandarlo ahí desacomoda esas barras. */
  td .btn-mini, th .btn-mini{min-height:32px;padding:6px 10px}
  .sop-thf{min-height:30px;padding:5px 7px}
}

/* La columna «Gestion»: los dos botones juntos, uno arriba del otro. Estaban al lado del nombre
   y quedaban apretados contra el texto; en columna propia se alinean entre filas y se encuentran
   con la vista sin leer. */
/* `1px` y no `1%`: la tabla es `width:100%` y la holgura tiene que ir a ALGUNA columna. Con `1%`
   el navegador le seguia dando 228 px para 72 de botones; con `1px` el pedido de minimo es
   inequivoco y la holgura se va a las columnas que la usan. */
/* Centrados: la tabla le da a esta columna el sobrante del reparto —el contenido pide 100 px y le
   tocan 228— y alineados a la izquierda quedan tres iconitos con 128 px de aire al lado. */
.sup-tk td.c-fg,.sup-tk th.c-fg-h{white-space:nowrap;width:1px;vertical-align:middle;text-align:center}
/* ===== LOS CUATRO, DEL MISMO TAMAÑO, EN DOS POR DOS =====
   El problema no era el texto sino el reparto: el de Telwinet iba solo en su renglón y al 100% del
   ancho, y los otros tres se apretaban en el de abajo. Cuatro botones que hacen lo mismo —actuar
   sobre esta fila— con dos tamaños muy distintos, y una columna que se estiraba de más.
   Con una grilla de dos columnas iguales los cuatro miden lo mismo sin sacarles el nombre, que es
   lo que se probó primero y no gustó: la palabra se lee de un vistazo y el ícono solo hay que
   aprenderlo. Arriba los dos que llevan a Telwinet, abajo los dos nuestros. */
/* ===== UNA FILA DE ÍCONOS, SIEMPRE =====
   Medido: la columna tiene 181 px y los botones con texto suman 233, así que se envolvían 1 + 2. Y
   el chip de estado iba forzado al 100% del ancho, o sea un tercer renglón. Filas de 71 px sin
   gestión y hasta 110 con ella, para una tabla de 4.729 px.
   Los íconos solos ya existían acá abajo de 1.240 px: ahora es el comportamiento de siempre. Tres
   de 24 px con su separación son 80 px, así que el chip entra AL LADO y no arriba.
   `grid-auto-flow:column` en vez de un número fijo de columnas: hay tablas con tres botones y otras
   con cuatro, y así las dos quedan en una fila sin declarar cuántos son en cada una. */
.sup-tk td.c-fg .fg-par{display:inline-grid;grid-auto-flow:column;grid-auto-columns:24px;gap:4px;
  vertical-align:middle}
.sup-tk td.c-fg .fg-par > *{margin-left:0;width:100%;box-sizing:border-box;justify-content:center;
  padding:0;height:24px}
.sup-tk td.c-fg .fg-par > * span{display:none}

/* ===== LA MARCA DE «YA GESTIONADO» =====
   Va al final de la hoja a propósito. Las reglas de arriba tienen la misma especificidad y ganaría
   la última; ya pasó en este archivo con .role-chip y con .tbl th, y se pierde un rato largo
   buscando en el selector un problema que es de orden. */
.fg-chip{display:inline-flex;align-items:center;gap:4px;white-space:nowrap;
  border:1px solid var(--amber);color:var(--amber);background:color-mix(in srgb, var(--amber) 12%, transparent);
  border-radius:var(--radius-sm);padding:2px 8px;font-size:11px;font-weight:var(--fw-bold);line-height:1.3}
.fg-chip-fin{border-color:var(--green);color:var(--green);background:color-mix(in srgb, var(--green) 12%, transparent)}
.fg-chip-mini{font-weight:var(--fw-semi);font-size:10px;padding:1px 6px;border-color:var(--border);color:var(--text-dim);background:var(--surface-2)}
/* EL CHIP VA AL LADO DE LOS BOTONES, no arriba. Estaba forzado al 100% del ancho de la columna, y
   eso es lo que le agregaba un renglón entero a la fila cada vez que un cliente tenía gestión: la
   tabla tenía dos alturas según algo que no es del cliente sino de si alguien ya lo tocó. */
.sup-tk td.c-fg .fg-chip{display:inline-flex;width:auto;margin:0 4px 0 0;vertical-align:middle}
.sup-tk td.c-fg .fg-chips{display:inline-flex;margin:0 4px 0 0;vertical-align:middle}
.sup-tk td.c-fg .fg-tw{margin-left:0;margin-right:4px}
/* Ya gestionado: los botones siguen ahí —a veces hace falta un segundo ticket— pero apagados, para
   que la vista caiga en los que faltan. Se apagan sólo hasta que el mouse encima los devuelve. */
.sup-tk td.c-fg.fg-hecho .fg-tw,.sup-tk td.c-fg.fg-hecho .fg-btn{opacity:.45}
.sup-tk td.c-fg.fg-hecho:hover .fg-tw,.sup-tk td.c-fg.fg-hecho:hover .fg-btn{opacity:1}
/* Y la fila entera se atenúa apenas. Es lo que hace que «cuál falta» se vea de un vistazo sin leer
   fila por fila: lo gestionado se hunde y lo pendiente queda al frente.
   `:has()` mira la celda para decidir sobre la fila, así que no hay que tocar ninguna de las cuatro
   funciones que dibujan estas tablas. Donde no exista, no pasa nada: la fila queda normal y el chip
   sigue estando, que es lo que informa de verdad. */
.sup-tk tbody tr:has(td.c-fg.fg-hecho){background:color-mix(in srgb, var(--text) 3%, transparent)}
.sup-tk tbody tr:has(td.c-fg.fg-hecho) td.c-cli{opacity:.7}
.sup-tk tbody tr:has(td.c-fg.fg-hecho):hover td.c-cli{opacity:1}
/* Números a la derecha y en monoespaciada: la comparación de columnas se hace con la vista, y con
   la tipografía de texto los dígitos no se alinean entre filas. Estaba definido sólo para `.tbl`. */
.sup-tk td.num,.sup-tk th.num{text-align:right}
.sup-tk td.num{font-family:'IBM Plex Mono',ui-monospace,monospace;font-weight:var(--fw-semi)}
.sup-tk tbody tr.on{background:color-mix(in srgb, var(--accent-ink) 14%, transparent)}

/* ===== Los resultados de clientes en el menú lateral =====
   Una línea por dato y nada de partir palabras: con el nombre en dos o tres renglones las filas
   quedaban de alturas distintas, entraban ocho en vez de doce y la lista se leía como un párrafo.
   Y el subtítulo NO va en mayúsculas: la regla general de `small` es para el nombre del grupo
   («RED», «CLIENTES»), y aplicada a «por nombre» lo convertía en lo que parecía un encabezado. */
#sideNav .sn-cli .sn-txt{min-width:0;overflow:hidden}
#sideNav .sn-cli .sn-nom{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  font-weight:var(--fw-semi);font-size:12.5px;line-height:1.3}
#sideNav .sn-cli small{text-transform:none;letter-spacing:0;font-weight:var(--fw-medium);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block}
/* El renglón de estado: es el que evita abrir la ficha sólo para saber si está caído. Va tercero
   porque primero hay que reconocer al cliente; el estado se lee después, y de un vistazo por el
   color. Las filas dejan de estar centradas: con tres renglones, el ícono tiene que ir arriba. */
#sideNav .sn-cli{align-items:flex-start}
#sideNav .sn-cli svg{margin-top:3px}
#sideNav .sn-cli .sn-cli-est{margin-top:2px;font-size:11px;line-height:1.35;color:var(--text-dim)}
#sideNav .sn-cli .sn-cli-est b{font-weight:var(--fw-bold)}
/* Un respiro abajo de todo para que el último no quede pegado al botón del pie. */
#sideNav .sn-nav{padding-bottom:6px}

/* El enlace «abrir en otra pestaña» de la ficha: mismo tamaño y forma que la X de al lado, para
   que se lean como dos acciones del mismo rango y no como un agregado. */
#uiDialog .modal-head a.icon-btn{display:inline-flex;align-items:center;justify-content:center;
  text-decoration:none;margin-right:2px}
#uiDialog .modal-head a.icon-btn svg{width:17px;height:17px}

/* ===== La ficha sola, ocupando la ventana =====
   La pestaña se abre para mirar UN cliente: el menú y la barra de arriba no aportan nada ahí y le
   comen lugar a lo único que se vino a ver. Se esconden, y el modal deja de comportarse como modal:
   sin bordes redondeados, sin sombra flotando y sin el fondo oscuro, que sólo tiene sentido cuando
   hay algo atrás. El alto del cuerpo pasa a ser el de la ventana en vez de 62vh, así el historial y
   las secciones entran de una en vez de scrollear dentro de una caja chica. */
body.ficha-sola #sideNav,body.ficha-sola .topbar,body.ficha-sola #navBurger,
body.ficha-sola #navScrim,body.ficha-sola #anotadorFab{display:none!important}
body.ficha-sola #app{padding-left:0!important}
/* El mapa de cajas en su pestaña: sin menú, sin barra, a todo el ancho. */
body.mapa-solo #sideNav,body.mapa-solo .topbar,body.mapa-solo #navBurger,
body.mapa-solo #navScrim,body.mapa-solo #anotadorFab{display:none!important}
body.mapa-solo #app{padding-left:0!important}
body.mapa-solo #oltView{padding:0}
body.mapa-solo .cm-cols{padding:8px 10px 10px}
body.ficha-sola #uiScrim{background:var(--bg);padding:0;align-items:stretch;overflow:hidden}
body.ficha-sola #uiDialog{width:100vw!important;max-width:none;height:100vh;max-height:none;
  border:0;border-radius:0;box-shadow:none;animation:none;display:flex;flex-direction:column}
body.ficha-sola #uiDialog .modal-body{flex:1;min-height:0;max-height:none}
/* En el celular la ficha sola es directamente la pantalla: sin márgenes que roben ancho. */
@media(max-width:760px){ body.ficha-sola #uiDialog .modal-head{padding:14px 16px}
  body.ficha-sola #uiDialog .modal-body{padding:14px 16px} }

/* Tres columnas en vez de dos: a 1584 px dos dejaban la mitad derecha vacía en varias secciones.
   Con tres de ~500 px los pares etiqueta/valor entran cómodos y el alto baja bastante. Por debajo
   de 1200 px vuelven a ser dos, y en el celular una: tres columnas de 300 px no son tres
   columnas, son tres recortes. */
/* GRILLA, no columnas. `columns` reparte el contenido para emparejar los altos: una sección puede
   arrancar en una columna y seguir en otra, y dos secciones distintas quedan pegadas sin nada que
   las separe. Con grid cada tarjeta se queda entera en su celda y empieza donde se ve que empieza.
   `auto-fill` con mínimo de 430 px decide sola cuántas columnas entran: tres en una pantalla
   ancha, dos en una notebook, una en el celular, sin escribir un solo breakpoint. */
body.ficha-sola .ocl-cols{columns:auto;display:grid;gap:14px;align-items:stretch;
  grid-template-columns:repeat(auto-fill,minmax(430px,1fr))}
/* Las tarjetas de una misma fila terminan a la misma altura. Con los bordes desparejos la fila no
   se lee como fila: el ojo no encuentra la línea horizontal y todo parece flotar suelto. El precio
   es un hueco adentro de la tarjeta corta, que molesta menos que los bordes bailando.
   El contenido se queda ARRIBA —por eso el flex en columna— y no estirado ni centrado: los campos
   separándose entre sí para llenar el alto sería peor que el hueco. */
body.ficha-sola .ocl-sec{display:flex;flex-direction:column}
body.ficha-sola .ocl-sec > .ocl-grid{align-content:start}
/* Cada sección, una tarjeta. El estilo plano de la ficha se decidió para el modal en dos columnas;
   con diez secciones a lo ancho hace falta que se vea dónde termina una y empieza la otra. */
body.ficha-sola .ocl-sec{margin:0;background:var(--surface);border:1px solid var(--border);
  border-radius:var(--radius);padding:12px 14px 8px;break-inside:auto}
body.ficha-sola .ocl-sec-t{font-size:12px;color:var(--accent-ink);letter-spacing:.08em;
  margin:0 0 9px;padding-bottom:7px;border-bottom:1px solid var(--border)}
/* Y adentro de la tarjeta los campos NO se vuelven a partir en columnas: eso era lo que hacía que
   un valor quedara lejos de su etiqueta y que dos secciones parecieran una sola. */
body.ficha-sola .ocl-sec .ocl-grid{grid-template-columns:1fr;gap:0}
/* Lo que es ancho de verdad ocupa la fila entera: los diagnósticos y las tablas de tickets. */
/* Los diagnósticos ocupan DOS celdas, no la fila entera: con las dos consolas a la par entran
   cómodas, y Conexión —que ya no los lleva adentro— vuelve a ser una tarjeta como las demás. */
/* La tarjeta de diagnósticos ocupa la fila entera: adentro van las dos consolas en una mitad y el
   tráfico en vivo en la otra. */
body.ficha-sola .ocl-diag-card{grid-column:1/-1}
body.ficha-sola .ocl-diag-card .diag-res{display:grid;grid-template-columns:1fr 1fr;gap:16px;align-items:start}
@media(max-width:1200px){ body.ficha-sola .ocl-diag-card .diag-res{grid-template-columns:1fr} }
/* El ▶ adentro de la barra del cuadro, del color del acento para que se vea que es la acción. */
/* El botón que dispara la caja, en su barra: mismo aspecto en las tres. Del color del acento para
   que se distinga de «limpiar», que es la acción secundaria. */
body.ficha-sola .cmd-bar .cmd-run,body.ficha-sola .diag-live .cmd-x{
  color:var(--accent-ink);font-weight:var(--fw-semi);display:inline-flex;align-items:center;gap:5px;margin-left:auto}
body.ficha-sola .cmd-bar .cmd-run svg,body.ficha-sola .diag-live .cmd-x svg{width:13px;height:13px}
body.ficha-sola .cmd-bar .cmd-run.diag-on,body.ficha-sola .diag-live .cmd-x.diag-on{color:var(--amber)}
/* Con dos botones en la barra, «limpiar» deja de empujar y queda al lado. */
body.ficha-sola .cmd-bar .cmd-run + [data-limpiar]{margin-left:6px}
/* El gráfico en vivo necesita más alto que una consola de texto. */
body.ficha-sola .diag-live .cmd-out{height:auto;max-height:none;min-height:130px;padding:0}
body.ficha-sola .diag-live .cmd-out .l-eco{padding:9px 12px}
/* El recorte de mapa. Alto fijo: si creciera con la ventana se comería la tarjeta de al lado, y
   para ubicar un cliente y sus cajas vecinas 260 px alcanzan. */
/* Una celda como las demas, no dos: va pegada a Conexion y cierra la fila en vez de abrir una
   nueva y dejar el resto en blanco. Y mas baja: para ubicar un cliente y sus cajas vecinas no
   hace falta mas, y asi no desentona con la altura de las tarjetas de datos de al lado. */
/* Los enlaces para entrar al equipo: pastillas chicas, una por puerto que contestó. */
.eq-abrir{display:inline-block;margin:0 6px 3px 0;padding:2px 8px;border:1px solid var(--border);
  border-radius:var(--radius-sm);font-size:11px;font-weight:var(--fw-semi);text-decoration:none;color:var(--accent-ink);
  background:var(--surface-2);white-space:nowrap}
.eq-abrir:hover{border-color:var(--accent-ink);background:var(--surface-3)}
.ocl-mapa{height:186px;border-radius:var(--radius);overflow:hidden;background:var(--surface-2);
  /* Leaflet le pone z-index de hasta 1000 a sus capas y controles. Sin aislar, esos numeros
     compiten con los del resto de la ficha y el mapa se dibuja ENCIMA del titulo pegajoso: al
     scrollear se veia el mapa pasar por arriba de «Tecnica». `isolation:isolate` arma un contexto
     propio, asi los z-index de Leaflet se ordenan entre ellos y no contra la pagina. */
  position:relative;z-index:0;isolation:isolate}
body.ficha-sola .ocl-mapa-card .find-count{margin-top:8px}
body.ficha-sola .ocl-diag-card .diag-bar{margin:0;padding:0;border:0}
body.ficha-sola .ocl-diag-card .diag-bar-t{display:none}   /* el título lo pone la tarjeta */
body.ficha-sola .ocl-diag-card .diag-res{margin-top:8px}
/* Ping y Trazado, uno al lado del otro. */
body.ficha-sola .diag-dos{grid-template-columns:1fr 1fr;gap:14px}
@media(max-width:1000px){ body.ficha-sola .diag-dos{grid-template-columns:1fr} }
/* Consola de altura FIJA y scroll adentro. Un ping deja una línea por segundo: sin tope la
   tarjeta crece sola mientras la mirás y empuja todo lo de abajo. Entran unas seis líneas, que es
   lo que se lee de un vistazo; el resto se busca scrolleando ahí adentro. */
body.ficha-sola .cmd-out{height:130px;max-height:130px}
/* Señal en el tiempo y Tráfico: mitad y mitad, ocupando el ancho completo. Las dos llevan un
   gráfico adentro, y en la grilla de auto-fill quedaban de 430 px con el dibujo apretado. */
body.ficha-sola .ocl-cols-2{grid-template-columns:1fr 1fr}
/* Si queda una sola —el cliente sin histórico de tráfico— ocupa todo en vez de dejar medio grupo
   en blanco. */
body.ficha-sola .ocl-cols-2 > .ocl-sec:only-child{grid-column:1/-1}
@media(max-width:1000px){ body.ficha-sola .ocl-cols-2{grid-template-columns:1fr} }
/* Lo mismo para «Soporte abierto», que va suelto arriba de todo y ocupa el ancho completo: con un
   campo por línea el valor quedaba a media pantalla de su etiqueta. Se lo reconoce por estar
   colgado directo del cuerpo —es la única sección que no vive adentro de un grupo—. */
body.ficha-sola #oclBody > .ocl-sec > .ocl-grid{
  grid-template-columns:repeat(auto-fit,minmax(330px,1fr));gap:0 28px}
body.ficha-sola .ocl-par{grid-column:1/-1;gap:14px}
/* El nombre del grupo: es lo que daban las solapas y lo que se había perdido. Va pegado arriba
   mientras se scrollea, así nunca se pierde de vista de qué familia es lo que estás mirando. */
body.ficha-sola .ocl-pane{margin-top:22px}
body.ficha-sola .ocl-pane:first-of-type{margin-top:6px}
body.ficha-sola .ocl-grupo{position:sticky;top:0;z-index:3;margin:0 0 12px;padding:9px 0 8px;
  background:var(--bg);font-family:'IBM Plex Sans';font-weight:var(--fw-bold);font-size:14px;color:var(--text);
  border-bottom:2px solid var(--accent-ink);
  /* La franja opaca de arriba: tapa el relleno del cuerpo, que si no deja ver el contenido pasar
     por encima del titulo cuando esta pegado. Sin desenfoque, es un rectangulo de color. */
  box-shadow:0 -20px 0 0 var(--bg)}
/* El pie repetía la X del encabezado y se comía 60 px de ventana. */
body.ficha-sola #uiDialog .modal-foot{display:none}
/* Las acciones, ya en el encabezado, alineadas con el título y pegadas a la derecha. */
body.ficha-sola #uiDialog .modal-head{align-items:center}
body.ficha-sola #uiDialog .modal-head .ocl-foot{margin:0 12px 0 auto;display:flex;gap:8px;align-items:center}
body.ficha-sola #uiDialog .modal-head .ocl-foot .btn{white-space:nowrap}
body.ficha-sola #uiDialog .modal-head h3{font-size:15px}

/* ===== LAS CATEGORÍAS DESAPARECÍAN EN EL RIEL =====
   Los 6 separadores de grupo estaban en el DOM, con su color y su opacidad, y medían CERO.
   La lista es un contenedor flex en columna, y los 37 destinos no entran en el alto disponible
   (1087 px de contenido en 504). Cuando un contenedor flex se desborda, el navegador encoge a sus
   hijos para intentar que entren — y un separador de 1 px se encoge a 0. Los íconos no se notaban
   porque tienen contenido que los sostiene; la línea de 1 px no tiene nada que la sostenga.
   Resultado: en el riel se veían 37 íconos sueltos, sin ninguna división entre categorías.
   `flex:0 0 1px` le prohíbe encogerse. No hace falta tocar el alto: ya estaba bien puesto. */
#sideNav .sn-sep{flex:0 0 1px}

/* ===== Y EL ÚLTIMO ÍCONO QUEDABA CORTADO AL MEDIO =====
   Con 37 destinos en 504 px, el que toca en el borde se ve por la mitad —medido: 16 px de 25— y eso
   se lee como que el menú está roto, no como que hay más abajo. El degradado del borde inferior dice
   «esto sigue»: es la diferencia entre un corte y una continuación.
   Sólo en el riel: en modo ancho los grupos van plegados y la lista entra sin desbordar. */
body.nav-side.nav-rail:not(.nav-peek) #sideNav .sn-nav{
  -webkit-mask-image:linear-gradient(to bottom,#000 calc(100% - 18px),transparent 100%);
          mask-image:linear-gradient(to bottom,#000 calc(100% - 18px),transparent 100%)}

/* ===== ARREGLOS DE CELULAR Y DE APP INSTALADA (auditoría del 04/09) =====
   Van todos juntos y AL FINAL a propósito: así ganan por orden de cascada sin tener que subirles la
   especificidad, y no hay que averiguar adentro de qué media query vive cada regla original. */

@media (pointer:coarse){
  /* EL ZOOM SOLO DE iOS. Safari agranda la página cuando tocás un campo de menos de 16 px y no la
     vuelve a achicar: quedás navegando el sistema en zoom. Los campos son de 13 y 14 px. Ya lo
     habían parchado en tres lugares sueltos —el buscador del mapa, el filtro del tablero y los
     campos de la vista de técnico—, lo que dejaba afuera a admin y coordinador en todo el resto:
     Configuración, Stock, Seguridad y cada modal. Se arregla de una vez para todos los campos. */
  .inp, .ta, .sel, .help-search, .sup-tk-find{ font-size:15px }

  /* EL BLANCO DE TOQUE DE LOS BOTONES DE FILA. Había una regla que quería agrandarlos y no hacía
     nada: pedía `min-width:26px` sobre un botón que ya mide 28 px fijos, o sea un mínimo por debajo
     del valor real. Con el dedo se erraba seguido, y como la fila entera también abre el editor, el
     error terminaba abriendo otra cosa. Con `width`/`height` sí crecen. */
  .stk-b{ width:38px; height:38px }
}

/* LA APP INSTALADA, EN UN TELÉFONO CON NOTCH. La ficha de una caja se abre a pantalla completa: la
   «X» de cerrar quedaba debajo de la barra de estado —no se podía tocar— y la lista de cajas
   cercanas terminaba abajo de la barra de gestos. El resto del sistema ya respeta el área segura
   (la barra de arriba, el menú del avatar, los modales); estas dos se habían quedado afuera. */
.cm-sheet-close{ top:calc(12px + env(safe-area-inset-top)) }
.cm-near-card{ padding-bottom:calc(22px + env(safe-area-inset-bottom)) }

@media(max-width:760px){
  /* LA TIRA DE SOLAPAS NO AVISA QUE SIGUE. Scrollea de costado, pero la barra de scroll está oculta
     a propósito y la píldora tiene el borde redondeado cerrado de los dos lados, así que parece
     completa: en Configuración se ven tres solapas y media de nueve. El degradé del borde derecho
     dice «hay más» sin agregar un control. */
  .sup-tabseg{ -webkit-mask-image:linear-gradient(90deg,#000 calc(100% - 22px),transparent);
               mask-image:linear-gradient(90deg,#000 calc(100% - 22px),transparent) }
}

@media(max-width:560px){
  /* CONFIGURACIÓN: TRES RELLENOS SUMADOS. El cuerpo del panel pone 16 px, `#cfgBody` otros 12 y la
     caja de la tabla 14: 42 px por lado, que en un teléfono de 360 dejan 276 px para una tabla de
     seis columnas. Otras pantallas ya achican su marco en celular; ésta no lo hacía. */
  #configView .so-panel-body.so-pad{ padding:8px }
  #cfgBody{ padding:0 0 calc(22px + env(safe-area-inset-bottom)) }

  /* SEIS INDICADORES EN UNA FILA NO ENTRAN. La tira de indicadores está pensada para cuatro o
     cinco: con seis —la solapa Estado es la única así— se ven dos y medio y los otros nacen fuera
     de la pantalla, sin barra de scroll visible que lo insinúe. En el teléfono van de a dos. */
  #cfgBody .tt-kpis{ flex-wrap:wrap; overflow-x:visible }
  #cfgBody .tt-kpi{ flex:1 1 calc(50% - 6px) }

  /* Y las etiquetas de los indicadores dejan de cortarse en «ABONADOS…»: en pantalla angosta el
     rótulo puede usar dos renglones en vez de perder la mitad de las letras. */
  .tt-kpi .k-lbl{ white-space:normal; line-height:1.15 }
}
