/*
  Dos familias, autoalojadas. `swap` a proposito: el texto se lee desde el
  primer fotograma con la del sistema y cambia cuando llega la propia. Un
  `block` dejaria la pantalla en blanco al tecnico con mala cobertura.

  La division es semantica y no decorativa: monoespaciada para lo que escupe
  una maquina (comprobante, fecha, simbolo de moneda, columna numerica,
  etiqueta de sistema) y proporcional para lengua humana.
*/
@font-face {
  font-family: "Instrument Sans";
  src: url("/fonts/instrument-sans.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "JetBrains Mono";
  src: url("/fonts/jetbrains-mono.woff2") format("woff2");
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}

/*
  Sistema visual. Sin paso de compilacion a proposito: son custom properties,
  que es tambien como se resuelve la marca blanca -- el operador sobreescribe
  UNA variable y el acento entero se adapta, sin generar un CSS por tenant.

  Este bloque es la paleta CLARA y es la completa. El media query y el selector
  de atributo que vienen debajo SOLO redefinen valores; ninguno introduce un
  token nuevo. Lo vigila `SistemaVisualTest`.
*/
:root {
  --display: "Instrument Sans", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --datos: "JetBrains Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;
  /* Posicion del puntero para el resplandor. Las reescribe `brillo.js`; sin
     el, el centro es un valor tan valido como cualquier otro. */
  --mx: 50%;
  --my: 50%;
  /* La cifra que cuenta en el Resumen: `--n` es el entero que se anima y
     `--fin` su destino, que escribe el Blade. Sin valor de partida aqui, la
     animacion arranca contra un token que no existe y no cuenta nada. */
  --n: 0;
  --fin: 0;
  --ease: cubic-bezier(.22, 1, .30, 1);
  --suave: cubic-bezier(.4, 0, .2, 1);
  --r: 14px;

  /* Lo unico que cambia por operador. El resto del acento se deriva de aqui. */
  --brand: #2A5BD7;

  --void: #EBEFF6;
  --tinta: #0A1017;
  --tinta-2: #4E5867;
  --tinta-3: #646D7C;

  --vidrio: rgba(255, 255, 255, .76);
  --vidrio-2: rgba(255, 255, 255, .56);
  --filo: rgba(14, 24, 40, .10);
  --filo-grad: linear-gradient(150deg, rgba(255,255,255,.95), rgba(255,255,255,.4) 38%, rgba(14,24,40,.05) 66%, rgba(14,24,40,.09));
  --hondo: 0 1px 2px rgba(14,24,40,.05), 0 26px 54px -22px rgba(14,24,40,.30);
  --hueco: rgba(255, 255, 255, .7);
  --hover-fila: rgba(14, 24, 40, .032);
  --reja: rgba(14, 24, 40, .07);
  --raya: rgba(14, 24, 40, .06);

  /* La señal sale de la marca del operador, oscurecida hasta que contrasta
     contra el papel. Un operador con un amarillo claro sigue siendo legible. */
  --luz: color-mix(in oklab, var(--brand) 88%, #05070C);
  --luz-dim: color-mix(in oklab, var(--brand) 70%, #05070C);
  --luz-hot: color-mix(in oklab, var(--brand) 60%, #05070C);

  /* Niveles semanticos: el color dice CUANTO importa, no que es. */
  --verde: #0A6E4C;
  --ambar: #7E590C;
  --rojo: #B5322A;

  /* Ambiente: las tres luces que derivan y los hilos de fibra. */
  --a1: rgba(70, 130, 240, .26);
  --a2: rgba(40, 180, 190, .20);
  --a3: rgba(140, 110, 240, .16);
  --hebra: rgba(40, 80, 170, .10);
  --pulso: rgba(40, 90, 200, .45);
  --pulso-hot: #2A5BD7;
  --grano: .035;
  --grano-mezcla: multiply;

  /* Degradado del texto grande: da profundidad a una cifra de 68 px. */
  --g1: #0A1017;
  --g2: #59667A;

  --btn-1: color-mix(in oklab, var(--brand) 92%, white);
  --btn-2: var(--brand);
  --btn-ink: #FFFFFF;
  --btn-sombra: color-mix(in oklab, var(--brand) 45%, transparent);
}

/*
  Oscuro. Dos veces a proposito: el media query cubre a quien no ha elegido
  nada, guardado con `:not([data-tema="claro"])` para que una eleccion
  explicita de claro le gane a un sistema operativo en oscuro; y el selector
  de atributo cubre a quien si eligio. Sin los dos, el conmutador solo
  funciona en una direccion.

  Es el mismo bloque escrito dos veces: sin paso de compilacion no hay forma
  de compartirlo, y es preferible a que el conmutador funcione a medias.
*/
@media (prefers-color-scheme: dark) {
  :root:not([data-tema="claro"]) {
    --void: #04060B;
    --tinta: #F0F4FA;
    --tinta-2: #95A2B6;
    --tinta-3: #717D94;

    --vidrio: rgba(255, 255, 255, .045);
    --vidrio-2: rgba(255, 255, 255, .014);
    --filo: rgba(255, 255, 255, .09);
    --filo-grad: linear-gradient(150deg, rgba(255,255,255,.26), rgba(255,255,255,.05) 38%, rgba(255,255,255,.015) 62%, rgba(255,255,255,.07));
    --hondo: 0 1px 1px rgba(0,0,0,.6), 0 28px 64px -24px rgba(0,0,0,.9);
    --hueco: rgba(0, 0, 0, .3);
    --hover-fila: rgba(255, 255, 255, .032);
    --reja: rgba(255, 255, 255, .05);
    --raya: rgba(255, 255, 255, .04);

    /* Aqui la marca se ACLARA en vez de oscurecerse: un azul corporativo
       oscuro sobre negro no se ve, y el operador no tiene por que saberlo. */
    --luz: color-mix(in oklab, var(--brand) 62%, #FFFFFF);
    --luz-dim: color-mix(in oklab, var(--brand) 82%, #FFFFFF);
    --luz-hot: color-mix(in oklab, var(--brand) 32%, #FFFFFF);

    --verde: #39D89B;
    --ambar: #F2BE5B;
    --rojo: #FF7C6D;

    --a1: rgba(34, 80, 200, .32);
    --a2: rgba(12, 116, 146, .26);
    --a3: rgba(48, 56, 178, .22);
    --hebra: rgba(138, 178, 240, .09);
    --pulso: rgba(176, 212, 255, .85);
    --pulso-hot: #E6F1FF;
    --grano: .05;
    --grano-mezcla: overlay;

    --g1: #FFFFFF;
    --g2: #AFBED4;

    --btn-1: color-mix(in oklab, var(--brand) 92%, white);
    --btn-2: var(--brand);
    --btn-ink: #FFFFFF;
    --btn-sombra: color-mix(in oklab, var(--brand) 60%, transparent);
  }
}
:root[data-tema="oscuro"] {
  --void: #04060B;
  --tinta: #F0F4FA;
  --tinta-2: #95A2B6;
  --tinta-3: #717D94;

  --vidrio: rgba(255, 255, 255, .045);
  --vidrio-2: rgba(255, 255, 255, .014);
  --filo: rgba(255, 255, 255, .09);
  --filo-grad: linear-gradient(150deg, rgba(255,255,255,.26), rgba(255,255,255,.05) 38%, rgba(255,255,255,.015) 62%, rgba(255,255,255,.07));
  --hondo: 0 1px 1px rgba(0,0,0,.6), 0 28px 64px -24px rgba(0,0,0,.9);
  --hueco: rgba(0, 0, 0, .3);
  --hover-fila: rgba(255, 255, 255, .032);
  --reja: rgba(255, 255, 255, .05);
  --raya: rgba(255, 255, 255, .04);

  --luz: color-mix(in oklab, var(--brand) 62%, #FFFFFF);
  --luz-dim: color-mix(in oklab, var(--brand) 82%, #FFFFFF);
  --luz-hot: color-mix(in oklab, var(--brand) 32%, #FFFFFF);

  --verde: #39D89B;
  --ambar: #F2BE5B;
  --rojo: #FF7C6D;

  --a1: rgba(34, 80, 200, .32);
  --a2: rgba(12, 116, 146, .26);
  --a3: rgba(48, 56, 178, .22);
  --hebra: rgba(138, 178, 240, .09);
  --pulso: rgba(176, 212, 255, .85);
  --pulso-hot: #E6F1FF;
  --grano: .05;
  --grano-mezcla: overlay;

  --g1: #FFFFFF;
  --g2: #AFBED4;

  --btn-1: color-mix(in oklab, var(--brand) 92%, white);
  --btn-2: var(--brand);
  --btn-ink: #FFFFFF;
  --btn-sombra: color-mix(in oklab, var(--brand) 60%, transparent);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--void);
  color: var(--tinta);
  font: 400 15px/1.55 var(--display);
  /* Cifras de igual ancho en todo el panel: sin esto las columnas de dinero
     bailan entre filas, que es lo que mas delata un panel descuidado. */
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--luz); }
::selection { background: color-mix(in srgb, var(--luz) 28%, transparent); }

/* ---------- Armazon ---------- */
.layout { display: flex; min-height: 100vh; }

/*
  La barra deja de ser una franja negra fija y pasa a ser vidrio, como todo lo
  demas: con dos temas, una barra oscura pintada a mano solo cuadra en uno.
*/
.sidebar {
  width: 252px; flex: 0 0 252px;
  background: linear-gradient(180deg, var(--vidrio), var(--vidrio-2));
  border-right: 1px solid var(--filo);
  color: var(--tinta-2); padding: 16px 0;
  display: flex; flex-direction: column;
}
/* Columna tambien aqui: es lo que deja el pie pegado abajo del todo con su
   `margin-top: auto` en vez de colgando de la ultima seccion del menu. */
.menu { display: flex; flex-direction: column; flex: 1; min-height: 0; }
.sidebar .marca { padding: 0 20px 20px; font-weight: 600; color: var(--tinta); letter-spacing: -0.01em; }

/* En escritorio el menu esta siempre visible y la palanca no existe. El
   <summary> por defecto trae triangulo gris y repetiria el nombre del
   operador justo encima de .marca. */
.palanca { display: none; }
.sidebar a, .menu-movil a {
  display: flex; align-items: center; gap: 11px;
  padding: 9px 20px; color: var(--tinta-2); text-decoration: none;
  font-size: 13px; font-weight: 500; border-left: 2px solid transparent;
}
/* El icono del menu baja de opacidad hasta que la seccion importa: asi el
   apoyo visual no compite con la etiqueta, que es lo que de verdad se lee. */
/* Diez enlaces seguidos son una lista que hay que leer entera cada vez. En
   grupos, el ojo salta al bloque y no al item. */
.sidebar .grupo, .menu-movil .grupo {
  padding: 18px 20px 6px;
  font-size: 10px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--tinta-3);
}
.sidebar .grupo:first-of-type, .menu-movil .grupo:first-of-type { padding-top: 6px; }

.sidebar a .ico, .menu-movil a .ico { opacity: 0.55; }
.sidebar a:hover .ico, .sidebar a[aria-current="page"] .ico, .menu-movil a[aria-current="page"] .ico { opacity: 1; }
.sidebar a .crece, .menu-movil a .crece { flex: 1; }
.sidebar a .estado, .menu-movil a .estado { height: 18px; padding: 1px 7px; }
.sidebar a:hover, .menu-movil a:hover { background: var(--hover-fila); }
.sidebar a[aria-current="page"] {
  background: color-mix(in srgb, var(--luz) 10%, transparent);
  color: var(--tinta); border-left-color: var(--luz);
}

.contenido {
  flex: 1; min-width: 0; padding: 24px 28px 40px;
  /* A 1600px sin tope, una tabla de siete columnas separa "Deuda" de "Cobrar"
     medio metro y las tarjetas de cifra quedan enormes y vacias. El tope es
     generoso para que quepan las tablas anchas, no para leer prosa. */
  max-width: 1360px;
}

/*
  Cabecera de pagina.

  Antes el <h1> flotaba solo sobre una pila de cajas: ni contexto, ni sitio fijo
  para la accion principal, ni separacion entre "donde estoy" y "que hay aqui".
  Cada pantalla resolvia lo suyo por su cuenta y ninguna se parecia a otra.
*/
.pagina {
  display: flex; align-items: flex-end; gap: 16px; flex-wrap: wrap;
  padding-bottom: 16px; margin-bottom: 24px;
  border-bottom: 1px solid var(--filo);
}
.pagina .crece { flex: 1; min-width: 0; }
.pagina h1 {
  font-size: 21px; font-weight: 650; line-height: 1.15;
  margin: 0; letter-spacing: -0.02em;
}
/* Eyebrow: dice de que seccion es esta pantalla, que es lo que el <h1> solo no
   puede decir sin repetirse a si mismo. */
.pagina .seccion {
  display: block; margin-bottom: 3px;
  font-size: 11px; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--tinta-3);
}
.pagina .sub { margin: 5px 0 0; color: var(--tinta-2); font-size: 12px; max-width: 62ch; }

/* ---------- Superficie ---------- */
/*
  El borde no es una linea plana: es un degradado de 1 px que se aclara arriba
  a la izquierda y se apaga abajo, recortado con `mask-composite`. Es lo que
  hace que un panel parezca tener canto en vez de estar dibujado.
*/
.vidrio, .panel {
  position: relative;
  border-radius: var(--r);
  background: linear-gradient(180deg, var(--vidrio), var(--vidrio-2));
  box-shadow: var(--hondo);
}
.vidrio::before, .panel::before {
  content: "";
  position: absolute; inset: 0; border-radius: inherit;
  padding: 1px; pointer-events: none;
  background: var(--filo-grad);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
}
.panel { padding: 20px; }

/*
  El resplandor que sigue al puntero. Las coordenadas las escribe `brillo.js`;
  sin el, el gradiente se queda en el centro y la tarjeta simplemente se
  ilumina un poco al pasar. No se rompe nada si el script no llega.
*/
.brillo {
  position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; opacity: 0;
  background: radial-gradient(340px circle at var(--mx, 50%) var(--my, 50%),
              color-mix(in srgb, var(--luz) 16%, transparent), transparent 62%);
  transition: opacity 340ms var(--suave);
}
@media (hover: hover) and (pointer: fine) {
  .vidrio:hover .brillo, .panel:hover .brillo { opacity: 1; }
}

/*
  `backdrop-filter` SOLO en lo que no se desplaza.
  Repinta en cada scroll, y una tabla larga en un portatil flojo lo nota. En la
  barra lateral y la cabecera no cuesta nada porque no se mueven; en los
  paneles de contenido el fondo translucido plano se ve casi igual y no cobra
  peaje. La maqueta no tenia que aguantar un turno de ocho horas.
*/
.sidebar, .pagina { backdrop-filter: blur(22px) saturate(1.3); }

/* Los paneles de las demas pantallas no llevan `<span class="brillo">` en el
   marcado. Se les pinta con un pseudo-elemento para no tocar veinte vistas. */
.panel::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; opacity: 0;
  background: radial-gradient(340px circle at var(--mx, 50%) var(--my, 50%),
              color-mix(in srgb, var(--luz) 14%, transparent), transparent 62%);
  transition: opacity 340ms var(--suave);
}
@media (hover: hover) and (pointer: fine) { .panel:hover::after { opacity: 1; } }

/* ---------- Iconos ---------- */
/* Sprite en linea, `currentColor`, tamaño ligado al texto: un icono que no
   acompaña al tamaño de su etiqueta se desalinea en cuanto alguien usa zoom. */
.ico { width: 1.15em; height: 1.15em; flex: none; vertical-align: -0.2em; }

/* Pastilla del icono en cabeceras y tarjetas. El fondo sale del propio color
   del nivel, no de un color decorativo elegido por seccion. */
.ico-pastilla {
  width: 32px; height: 32px; flex: none;
  display: grid; place-items: center;
  border-radius: 8px; background: currentColor;
}
.ico-pastilla .ico { width: 18px; height: 18px; color: var(--void); }

/* ---------- Cabecera de panel ---------- */
.panel-cab {
  display: flex; align-items: center; gap: 12px;
  margin: -2px 0 16px;
  /* La accion de la derecha se cae debajo antes que empujar el titulo fuera. */
  flex-wrap: wrap;
}
.panel-cab h2 { margin: 0; }
.panel-cab .crece { flex: 1; min-width: 0; }
.panel-cab .secundario { font-size: 12px; }

/* ---------- Tarjeta de cifra ---------- */
/* El riel de color es lo unico que se permite gritar, y grita por NIVEL: verde
   lo que esta bien, rojo lo que cuesta dinero. En el original cada tarjeta
   tenia su color por decoracion, asi que el color no significaba nada. */
/* El riel va en el borde y no en un pseudo-elemento: `::before` es ya el filo
   del vidrio y `::after` el resplandor del puntero, y en un pseudo compartido
   siempre desaparecia uno de los dos. */
.kpi { position: relative; overflow: hidden; border-left: 3px solid currentColor; }
.kpi-cifra {
  font-size: 38px; font-weight: 600; letter-spacing: -0.025em; line-height: 1.05;
  color: var(--tinta);
}
.kpi-ok { color: var(--verde); }
.kpi-critico { color: var(--rojo); }
/* --tinta-3 dejaba el glifo blanco casi ilegible sobre la pastilla. */
.kpi-neutro { color: var(--tinta-2); }

/* ---------- Controles ---------- */
.btn {
  position: relative; overflow: hidden;
  display: inline-flex; align-items: center; gap: 8px;
  padding: 10px 17px; border-radius: 10px; cursor: pointer;
  font: 550 13.5px/1 var(--display); text-decoration: none;
  border: 1px solid var(--filo); color: var(--tinta);
  background: linear-gradient(180deg, var(--vidrio), var(--vidrio-2));
  box-shadow: inset 0 1px 0 var(--filo);
  transition: transform 160ms var(--ease), border-color 160ms var(--suave), box-shadow 160ms var(--suave);
}
@media (hover: hover) and (pointer: fine) {
  .btn:hover { transform: translateY(-1px); border-color: color-mix(in srgb, var(--luz) 45%, transparent); }
}
/* La presion es el efecto mas barato y el que mas cambia la sensacion: la
   interfaz parece que te oye. */
.btn:active { transform: scale(.97); box-shadow: none; transition-duration: 90ms; }

.btn-primario {
  border: 0; color: var(--btn-ink);
  background: linear-gradient(180deg, var(--btn-1), var(--btn-2));
  box-shadow: inset 0 1px 0 rgba(255,255,255,.3), 0 8px 22px -8px var(--btn-sombra);
}
/* Destello que barre el boton al pasar. Dura 700 ms y no se repite. */
.btn-primario::after {
  content: ""; position: absolute; inset: 0; transform: translateX(-110%);
  background: linear-gradient(105deg, transparent 30%, rgba(255,255,255,.3), transparent 70%);
}
@media (hover: hover) and (pointer: fine) {
  .btn-primario:hover::after { transform: translateX(110%); transition: transform 700ms var(--ease); }
}
.btn-sm { padding: 6px 12px; font-size: 12.5px; }

/* Lo que no se deshace no puede parecerse a lo que si. */
.btn-peligro { color: var(--rojo); border-color: color-mix(in srgb, var(--rojo) 40%, transparent); }
.btn-peligro:hover { background: color-mix(in srgb, var(--rojo) 12%, transparent); }

.zona-peligro {
  margin-top: 16px; padding: 14px 16px;
  border: 1px solid color-mix(in srgb, var(--rojo) 40%, transparent);
  border-radius: var(--r); background: color-mix(in srgb, var(--rojo) 6%, transparent);
}

.campo {
  padding: 10px 13px; border-radius: 10px; width: 100%;
  border: 1px solid var(--filo); background: var(--hueco); color: var(--tinta);
  font: 400 13.5px/1.3 var(--display);
  transition: border-color 180ms var(--suave);
}
.campo::placeholder { color: var(--tinta-3); }
.campo:focus-visible { outline: 2px solid var(--luz); outline-offset: 1px; }

/* El anillo por defecto del navegador es azul y desaparecia sobre el boton
   principal, que tambien es azul: quien navega con teclado perdia el foco. */
.btn:focus-visible, .sidebar a:focus-visible, .paginacion a:focus-visible,
a:focus-visible, select:focus-visible, button:focus-visible {
  outline: 2px solid var(--tinta); outline-offset: 2px;
}
.sidebar a:focus-visible { outline-color: var(--tinta); }

.conmutador { display: flex; gap: 4px; margin-top: 10px; }
.conmutador .btn { flex: 1; justify-content: center; padding: 6px 4px; font-size: 11.5px; }
.conmutador .btn[aria-pressed="true"] { color: var(--luz); border-color: color-mix(in srgb, var(--luz) 45%, transparent); }

.barra { display: flex; gap: 10px; align-items: center; margin-bottom: 16px; flex-wrap: wrap; }

/* ---------- Tabla ---------- */
/*
  El envoltorio que la deja desplazarse sola en vez de estirar la pagina.
  Fuera de todo media query a proposito: una tabla de siete columnas tampoco
  cabe en una ventana de escritorio a media pantalla, y el desbordamiento
  horizontal del `<body>` es de los defectos que peor envejecen.

  Las dos sombras de los bordes dicen que hay mas a la derecha. Se pintan con
  cuatro capas de fondo: las dos `local` viajan con el contenido y tapan la
  sombra al llegar al extremo, asi que la pista aparece SOLO cuando de verdad
  hay algo escondido. Sin JavaScript y sin medir nada.
*/
.tabla-scroll {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  background:
    linear-gradient(to right, var(--void), transparent) left / 26px 100% no-repeat local,
    linear-gradient(to left, var(--void), transparent) right / 26px 100% no-repeat local,
    radial-gradient(farthest-side at 0 50%, color-mix(in srgb, var(--tinta) 18%, transparent), transparent) left / 13px 100% no-repeat scroll,
    radial-gradient(farthest-side at 100% 50%, color-mix(in srgb, var(--tinta) 18%, transparent), transparent) right / 13px 100% no-repeat scroll;
}

.tabla { width: 100%; border-collapse: collapse; }
.tabla th {
  text-align: left; padding: 0 12px 11px; white-space: nowrap;
  font: 600 9.5px/1 var(--datos); letter-spacing: .16em; text-transform: uppercase;
  color: var(--tinta-3); border-bottom: 1px solid var(--filo);
}
.tabla td { padding: 13px 12px; border-bottom: 1px solid var(--raya); height: 54px; font-size: 13.5px; }
.tabla tbody tr:last-child td { border-bottom: 0; }
.tabla tbody tr { transition: background 160ms var(--suave); }
@media (hover: hover) and (pointer: fine) { .tabla tbody tr:hover { background: var(--hover-fila); } }
.tabla tbody td:first-child { font-weight: 550; }
.num, .tabla th.num { text-align: right; font-family: var(--datos); font-size: 13px; }
/* En una tabla el subrayado de cada enlace es ruido: hay uno por fila. */
.tabla a { color: inherit; text-decoration: none; }
.tabla a:hover { color: var(--luz); text-decoration: underline; }
.mono, .doc { font: 500 12.5px/1 var(--datos); color: var(--tinta-2); }
.secundario { color: var(--tinta-2); font-size: 13px; }

/* ---------- Estados ---------- */
/* El color dice el nivel; el punto y el texto lo dicen tambien, para quien no
   distingue el rojo del verde. */
.estado, .pastilla {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px; border-radius: 20px; white-space: nowrap;
  font: 600 11px/1 var(--datos); border: 1px solid transparent;
}
.estado::before, .pastilla::before {
  content: ""; width: 5px; height: 5px; border-radius: 50%;
  background: currentColor; box-shadow: 0 0 7px currentColor;
}
.estado-ok       { color: var(--verde); background: color-mix(in srgb, var(--verde) 11%, transparent); border-color: color-mix(in srgb, var(--verde) 20%, transparent); }
.estado-atencion { color: var(--ambar); background: color-mix(in srgb, var(--ambar) 11%, transparent); border-color: color-mix(in srgb, var(--ambar) 20%, transparent); }
.estado-critico  { color: var(--rojo);  background: color-mix(in srgb, var(--rojo) 11%, transparent);  border-color: color-mix(in srgb, var(--rojo) 20%, transparent); }
.estado-inactivo { color: var(--tinta-2); background: var(--hover-fila); border-color: var(--filo); }
/* Condicion comercial, no estado de salud: se distingue por forma, sin color. */
.estado-excepcion { color: var(--tinta-2); background: transparent; border-color: var(--filo); }
.estado-excepcion::before { display: none; }

.aviso { padding: 11px 15px; border-radius: 10px; margin-bottom: 16px; font-size: 13.5px; }
.aviso-ok    { color: var(--verde); background: color-mix(in srgb, var(--verde) 12%, transparent); }
.aviso-error { color: var(--rojo);  background: color-mix(in srgb, var(--rojo) 12%, transparent); }
.vacio { padding: 44px 20px; text-align: center; color: var(--tinta-2); }

/* ---------- Cifras ---------- */
.k { font: 600 9.5px/1 var(--datos); letter-spacing: .18em; text-transform: uppercase; color: var(--tinta-2); }
.sello {
  width: 31px; height: 31px; flex: none; border-radius: 9px;
  display: grid; place-items: center; box-shadow: inset 0 1px 0 var(--filo);
}
.sello .ico { width: 15px; height: 15px; }
.sello-ok    { background: color-mix(in srgb, var(--verde) 14%, transparent); color: var(--verde); }
.sello-critico { background: color-mix(in srgb, var(--rojo) 14%, transparent); color: var(--rojo); }
.sello-luz   { background: color-mix(in srgb, var(--luz) 14%, transparent); color: var(--luz); }

/* El degradado da profundidad a una cifra de 68 px. En plano parece pegada. */
.enorme, .media {
  font-weight: 600; letter-spacing: -.045em; line-height: .98;
  background: linear-gradient(178deg, var(--g1) 18%, var(--g2) 122%);
  -webkit-background-clip: text; background-clip: text; color: transparent;
}
.enorme { font-size: 68px; }
.media  { font-size: 38px; letter-spacing: -.042em; }
/* El simbolo de moneda es notacion, no cifra: mono, menor y apagado. */
.enorme i, .media i {
  font-style: normal; font-family: var(--datos); font-weight: 500;
  font-size: .36em; letter-spacing: 0; margin-right: .22em; vertical-align: .42em;
  -webkit-text-fill-color: var(--tinta-3);
}

.pie-lateral { margin-top: auto; padding: 16px 20px 0; border-top: 1px solid var(--filo); }
.pie-lateral .secundario { font-size: 12.5px; }
.sello-hora { font: 500 10.5px/1.6 var(--datos); color: var(--tinta-3); margin-bottom: 10px; }

/* Acciones plegadas dentro de una fila de tabla. Sin JavaScript: <details> y el
   summary con pinta de boton. El desplegable se saca del flujo para que abrirlo
   no empuje las filas de abajo -- si empujara, cerrar y abrir movería la fila
   que el operador estaba mirando. */
.acciones-fila { display: inline-block; position: relative; }
.acciones-fila > summary { list-style: none; cursor: pointer; display: inline-block; }
.acciones-fila > summary::-webkit-details-marker { display: none; }
.acciones-fila > summary::after { content: " ▾"; }
.acciones-fila[open] > summary::after { content: " ▴"; }
.acciones-fila .desplegado {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 5;
  /* Vidrio SOBRE fondo solido, no vidrio a secas: este panel flota encima de
     CONTENIDO, y con `--vidrio` (4,5% de blanco en oscuro) el texto de las
     tarjetas de abajo se leia a traves del formulario de cierre. El degradado
     mantiene el lenguaje del panel; `--void` debajo lo hace opaco. */
  background: linear-gradient(180deg, var(--vidrio), var(--vidrio-2)), var(--void);
  border: 1px solid var(--filo);
  border-radius: var(--r); box-shadow: var(--hondo);
  padding: 12px; white-space: nowrap;
}

/* Los anchos por CLASE y no en el marcado: el movil los tiene que poder pisar,
   y un `style="width:380px"` inline le gana a cualquier media query. */
.desplegado.desplegado-medio { width: min(92vw, 320px); white-space: normal; }
.desplegado.desplegado-ancho { width: min(92vw, 380px); white-space: normal; }

/* La franja del corte: el estado del vigilante, primero y en grande. Toma el
   color de la clase de estado que ya trae comoSeCuenta(). */
.franja-caida {
  display: block; width: 100%;
  margin: 10px 0 4px;
  padding: 10px 14px;
  border-radius: 10px;
  font-size: 14px;
  border: 1px solid var(--filo);
}
.franja-caida.estado-critico {
  border-color: color-mix(in srgb, var(--rojo) 45%, transparent);
  background: color-mix(in srgb, var(--rojo) 10%, transparent);
  color: var(--tinta);
}
.franja-caida.estado-atencion {
  border-color: color-mix(in srgb, var(--ambar) 45%, transparent);
  background: color-mix(in srgb, var(--ambar) 10%, transparent);
  color: var(--tinta);
}
.franja-caida.estado-inactivo { color: var(--tinta-2); }

/* La vista previa de las fotos elegidas, antes de subirlas. */
.previa-fotos { display: flex; flex-wrap: wrap; gap: 8px; }
.previa-fotos:not(:empty) { margin: 10px 0 4px; }
.previa-fotos img {
  width: 84px; height: 64px; object-fit: cover;
  border-radius: 6px; border: 1px solid var(--filo);
}

/* Las acciones de una tarjeta de ticket: a la derecha en escritorio... */
.acciones-ticket { margin-left: auto; display: flex; gap: 8px; align-items: center; }

/* La ficha a dos columnas (ticket): el trabajo a la izquierda, el contexto a
   la derecha. Es una CLASE y no un grid inline porque un estilo inline no
   puede tener media query: asi era como el telefono se quedaba con las dos
   columnas forzadas y la ficha ilegible. */
.ficha-dos-columnas {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(280px, 1fr);
  gap: 16px;
  align-items: start;
}
/* `.barra` envuelve por defecto, y aqui eso partia cada campo de su boton en
   dos lineas. Dentro del desplegable cada accion ocupa una fila y no se parte. */
.acciones-fila .desplegado .barra { flex-wrap: nowrap; }

@media (max-width: 860px) {
  /* En móvil no hay sitio para flotar: se despliega en el propio flujo, a lo
     ancho, y CONSERVA borde y fondo -- sin ellos el formulario se fundia con
     la tarjeta de abajo y "la ventana se superpone y no se ve". */
  .acciones-fila .desplegado,
  .desplegado.desplegado-medio,
  .desplegado.desplegado-ancho {
    position: static; width: 100%; margin-top: 8px;
    box-shadow: none; white-space: normal;
  }

  /* ...y a lo ancho en móvil: tres botones apretados a la derecha de una
     pantalla de 6 pulgadas se fallan con el pulgar. */
  .acciones-ticket { width: 100%; margin-left: 0; flex-wrap: wrap; }
  .acciones-ticket > form.barra { width: 100%; }
  .acciones-ticket > form.barra > .campo { flex: 1; min-width: 0; }
  .acciones-ticket > details { flex: 1 1 auto; }
  .acciones-ticket > details > summary { display: block; text-align: center; }

  /* Nada dentro de una tarjeta puede desbordarla en horizontal. */
  .tarjeta-ticket select, .tarjeta-ticket input, .tarjeta-ticket textarea { max-width: 100%; }

  /* En movil la ficha es UNA columna: primero el trabajo, debajo el contexto.
     `minmax(0, 1fr)` y no `1fr` a secas -- el minimo automatico de grid deja
     que un hijo ancho (una descripcion sin espacios, una tabla) desborde la
     pantalla entera. */
  .ficha-dos-columnas { grid-template-columns: minmax(0, 1fr); }
}

.paginacion {
  display: flex; align-items: center; gap: 12px; margin-top: 16px;
}
.paginacion [aria-disabled] { opacity: 0.5; cursor: default; }

/* Visible solo para lectores de pantalla. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; left: 8px; top: -48px; z-index: 10;
  background: var(--void); color: var(--tinta); padding: 8px 14px;
  border-radius: var(--r); border: 1px solid var(--filo);
}
.skip-link:focus { top: 8px; }

/* Panel plegable ("Nuevo artículo", "Nuevo plan", "Nuevo equipo"...). El
   marcador del navegador es un triangulito gris distinto en cada plataforma;
   este dice con un signo si va a abrir o a cerrar. */
details.panel > summary {
  list-style: none; cursor: pointer; font-weight: 600;
  display: flex; align-items: center; gap: 10px;
}
details.panel > summary::-webkit-details-marker { display: none; }
details.panel > summary::before {
  content: "+"; flex: none;
  width: 22px; height: 22px; border-radius: 5px;
  display: grid; place-items: center;
  background: var(--hover-fila); color: var(--tinta-2);
  font-size: 15px; font-weight: 600; line-height: 1;
}
details.panel[open] > summary::before { content: "−"; }
details.panel > summary:hover::before { background: color-mix(in srgb, var(--tinta) 10%, transparent); color: var(--tinta); }

.panel h2 {
  font-size: 16px; font-weight: 620; margin: 0 0 12px; letter-spacing: -0.015em;
}
.panel-cab h2 { margin: 0; }

/* ---------- Ambiente ---------- */
.cielo { position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
.layout { position: relative; z-index: 1; }

.luz-fondo { position: absolute; border-radius: 50%; filter: blur(100px); will-change: transform; }
.l1 { width: 880px; height: 880px; left: -18%; top: -36%; background: var(--a1); animation: deriva-1 46s ease-in-out infinite alternate; }
.l2 { width: 740px; height: 740px; right: -16%; top: 4%;  background: var(--a2); animation: deriva-2 57s ease-in-out infinite alternate; }
.l3 { width: 960px; height: 960px; left: 24%; bottom: -50%; background: var(--a3); animation: deriva-3 64s ease-in-out infinite alternate; }
/* Solo `transform`: lo mueve la GPU y la CPU ni se entera. */
@keyframes deriva-1 { to { transform: translate3d(130px, 96px, 0) scale(1.22); } }
@keyframes deriva-2 { to { transform: translate3d(-118px, 74px, 0) scale(1.16); } }
@keyframes deriva-3 { to { transform: translate3d(96px, -86px, 0) scale(1.26); } }

/*
  Los hilos. No es un fondo bonito generico: es la señal viajando por la fibra,
  que es lo que el operador vende. Las ocho duraciones no encajan entre si, asi
  que el patron no se repite a la vista.
*/
.hebras { position: absolute; inset: -12%; transform: rotate(-10deg); }
.hebras i {
  position: absolute; top: 0; height: 100%; width: 1px; overflow: hidden;
  background: linear-gradient(to bottom, transparent, var(--hebra) 14%, var(--hebra) 86%, transparent);
}
.hebras i::after {
  content: ""; position: absolute; left: -1px; width: 3px; height: 170px; top: -170px;
  background: linear-gradient(to bottom, transparent, var(--pulso) 55%, var(--pulso-hot) 67%, transparent);
  filter: blur(1.1px); will-change: transform;
  animation: viaje 13s linear infinite;
  animation-play-state: paused;
}
@keyframes viaje { to { transform: translateY(150vh); } }
.hebras i:nth-child(1) { left: 6%; }  .hebras i:nth-child(1)::after { animation-delay: -1.4s;  animation-duration: 13.1s; }
.hebras i:nth-child(2) { left: 18%; } .hebras i:nth-child(2)::after { animation-delay: -7.2s;  animation-duration: 16.7s; }
.hebras i:nth-child(3) { left: 30%; } .hebras i:nth-child(3)::after { animation-delay: -3.6s;  animation-duration: 14.3s; }
.hebras i:nth-child(4) { left: 42%; } .hebras i:nth-child(4)::after { animation-delay: -10.1s; animation-duration: 18.2s; }
.hebras i:nth-child(5) { left: 54%; } .hebras i:nth-child(5)::after { animation-delay: -5.3s;  animation-duration: 15.1s; }
.hebras i:nth-child(6) { left: 66%; } .hebras i:nth-child(6)::after { animation-delay: -9.0s;  animation-duration: 17.4s; }
.hebras i:nth-child(7) { left: 78%; } .hebras i:nth-child(7)::after { animation-delay: -2.7s;  animation-duration: 14.8s; }
.hebras i:nth-child(8) { left: 90%; } .hebras i:nth-child(8)::after { animation-delay: -11.6s; animation-duration: 19.3s; }

/* Grano finisimo: mata las bandas del degradado en pantallas de 8 bits y da
   una textura que un degradado limpio no tiene. */
.grano {
  position: absolute; inset: 0;
  opacity: var(--grano); mix-blend-mode: var(--grano-mezcla);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='150' height='150'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.78' numOctaves='4'/%3E%3C/filter%3E%3Crect width='150' height='150' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---------- Intensidad ---------- */
/* Por defecto el panel va en `sutil`: aqui se trabaja ocho horas. El acceso y
   el portal lo suben a `maximo` desde su propia plantilla. */
[data-fondo="apagado"] .cielo { display: none; }
[data-fondo="sutil"] .luz-fondo { opacity: .55; }
[data-fondo="sutil"] .hebras { opacity: 0; }
[data-fondo="medio"] .hebras { opacity: .7; }
[data-fondo="maximo"] .hebras i::after { animation-play-state: running; }

/* ---------- Resumen ---------- */
.tablero { display: grid; grid-template-columns: 1.72fr 1fr; gap: 16px; margin-bottom: 16px; align-items: stretch; }
.columna { display: grid; grid-template-rows: 1fr 1fr; gap: 16px; min-width: 0; }
.heroe { padding: 24px 26px 0; display: flex; flex-direction: column; overflow: hidden; }
.apoyo { display: flex; flex-direction: column; overflow: hidden; }
.heroe-cab { display: flex; align-items: center; gap: 11px; margin-bottom: 18px; }
.heroe-cab .crece { flex: 1; min-width: 0; }
.heroe-pie { display: flex; align-items: center; gap: 9px; margin-top: 14px; flex-wrap: wrap; }
.apoyo .media { margin-top: auto; }

.grafico { margin: 18px -26px 0; }
.grafico svg { display: block; width: 100%; height: auto; }
/* Los degradados del SVG toman los tokens desde el CSS y no desde atributos:
   asi cambian solos con el tema y con la marca del operador. */
.reja line { stroke: var(--reja); stroke-width: 1; }
#relleno stop:first-child { stop-color: var(--luz); stop-opacity: .34; }
#relleno stop:last-child  { stop-color: var(--luz); stop-opacity: 0; }
#linea stop:first-child   { stop-color: var(--luz-dim); }
#linea stop:last-child    { stop-color: var(--luz-hot); }
.ejes { display: flex; justify-content: space-between; padding: 8px 26px 14px; font: 500 10px/1 var(--datos); color: var(--tinta-3); }

/* El trazo se dibuja solo. Es un evento raro -- una vez por carga del
   Resumen -- asi que aqui si vale la pena. */
.trazo { stroke-dasharray: 1500; stroke-dashoffset: 1500; animation: dibuja 2.1s var(--ease) .3s forwards; }
@keyframes dibuja { to { stroke-dashoffset: 0; } }
.area { opacity: 0; animation: aparecer 1.4s ease .9s forwards; }
@keyframes aparecer { to { opacity: 1; } }

/*
  La cifra de abonados cuenta desde cero, con CSS puro.
  `@property` hace animable un entero, y `counter()` lo pinta. Solo sirve para
  enteros: no hay forma de que produzca "1,847.00" con su coma de millar y sus
  decimales, asi que el dinero entra con la cascada y no cuenta. El valor final
  llega desde Blade en `--fin`.
*/
@property --n { syntax: "<integer>"; initial-value: 0; inherits: false; }
.cuenta { --n: 0; counter-reset: v var(--n); animation: contar 1.6s var(--ease) .45s forwards; }
.cuenta::after { content: counter(v); }
@keyframes contar { to { --n: var(--fin); } }

.fila-pendiente { display: flex; align-items: center; gap: 12px; padding: 12px 0; border-bottom: 1px solid var(--raya); }
.fila-pendiente:last-child { border-bottom: 0; }

@media (max-width: 1080px) {
  .tablero { grid-template-columns: 1fr; }
  .columna { grid-template-columns: 1fr 1fr; grid-template-rows: auto; }
}
@media (max-width: 860px) {
  .columna { grid-template-columns: 1fr; }
  .enorme { font-size: 46px; }
  .media { font-size: 31px; }
}

/* ---------- Acceso ---------- */
.pantalla-acceso { min-height: 100vh; display: grid; place-items: center; padding: 24px; }
.acceso {
  position: relative; z-index: 1;
  width: 100%; max-width: 320px; margin: auto;
  padding: 26px;
  display: flex; flex-direction: column; gap: 14px;
}
.acceso .logo { max-height: 40px; max-width: 220px; }
.acceso .marca-n { font-size: 17px; font-weight: 600; letter-spacing: -.02em; }
.acceso .marca-s { font: 500 10px/1 var(--datos); letter-spacing: .16em; text-transform: uppercase; color: var(--tinta-3); margin-top: 4px; }
.acceso label { display: block; margin-bottom: 6px; font: 600 9.5px/1 var(--datos); letter-spacing: .14em; text-transform: uppercase; color: var(--tinta-2); }
/* La casilla y su texto van en la misma linea, y ese texto es lengua humana:
   no lleva la version en versalitas de las etiquetas de campo. */
.acceso .recuerdame {
  display: flex; align-items: center; gap: 8px; margin: 14px 0;
  font: 400 13px/1.3 var(--display); letter-spacing: 0; text-transform: none; color: var(--tinta-2);
}
.acceso .btn-primario { width: 100%; justify-content: center; }
.acceso .promesa {
  margin: 0; padding-top: 14px; border-top: 1px solid var(--filo);
  font-size: 12px; color: var(--tinta-2); line-height: 1.5;
}

/* ---------- Movimiento ---------- */
/*
  Transicion entre paginas. El panel recarga entera en cada clic; con esto el
  navegador funde la vieja con la nueva y la barra lateral ni se inmuta. Se
  comporta como una aplicacion de una sola pagina sin serlo, sin JavaScript y
  sin tocar un controlador. Chrome y Edge lo animan; Firefox y Safari no
  animan y todo sigue funcionando igual.
*/
@view-transition { navigation: auto; }
::view-transition-old(root) { animation: sale 130ms var(--suave) both; }
::view-transition-new(root) { animation: entra 200ms var(--ease) both; }
@keyframes entra { from { opacity: 0; transform: translateY(7px); } }
@keyframes sale  { to   { opacity: 0; transform: translateY(-5px); } }

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

/* Corto a proposito: esto se ve cien veces al dia. Por encima de 300 ms la
   entrada deja de ser un detalle y se convierte en espera. */
.sube { opacity: 0; animation: surge 620ms var(--ease) forwards; }
.d1 { animation-delay: .04s; } .d2 { animation-delay: .10s; } .d3 { animation-delay: .16s; }
.d4 { animation-delay: .23s; } .d5 { animation-delay: .31s; }

.sidebar a { opacity: 0; animation: surge 500ms var(--ease) forwards; }
.sidebar a:nth-of-type(1) { animation-delay: .04s; } .sidebar a:nth-of-type(2) { animation-delay: .07s; }
.sidebar a:nth-of-type(3) { animation-delay: .10s; } .sidebar a:nth-of-type(4) { animation-delay: .13s; }
.sidebar a:nth-of-type(5) { animation-delay: .16s; } .sidebar a:nth-of-type(6) { animation-delay: .19s; }
.sidebar a:nth-of-type(7) { animation-delay: .22s; } .sidebar a:nth-of-type(8) { animation-delay: .25s; }

.tabla tbody tr { opacity: 0; animation: surge 520ms var(--ease) forwards; }
.tabla tbody tr:nth-child(1) { animation-delay: .26s; } .tabla tbody tr:nth-child(2) { animation-delay: .31s; }
.tabla tbody tr:nth-child(3) { animation-delay: .36s; } .tabla tbody tr:nth-child(4) { animation-delay: .41s; }
.tabla tbody tr:nth-child(5) { animation-delay: .46s; }
/* A partir de la sexta, todas a la vez: una tabla de cincuenta filas con
   cascada tarda tres segundos en poder leerse. */
.tabla tbody tr:nth-child(n+6) { animation-delay: .50s; }

/* El mensaje de sesion cae desde arriba en vez de aparecer de golpe. Sin
   JavaScript: `@starting-style` describe de donde viene al pintarse. */
.aviso {
  opacity: 1; transform: translateY(0);
  transition: opacity 260ms var(--ease), transform 260ms var(--ease);
}
@starting-style { .aviso { opacity: 0; transform: translateY(-9px); } }

/* Las acciones de fila crecen desde SU esquina, no desde el centro. El panel
   ya usa <details> para esto: solo habia que animarlo. */
.acciones-fila::details-content {
  opacity: 0; transform: scale(.94); transform-origin: top right;
  transition: opacity 170ms var(--ease), transform 170ms var(--ease),
              content-visibility 170ms allow-discrete;
}
.acciones-fila[open]::details-content { opacity: 1; transform: scale(1); }

/*
  El movimiento se apaga entero si el sistema lo pide. No se negocia.
  Las cifras animadas quedan en su valor FINAL, nunca en cero: apagar la
  animacion no puede dejar a nadie leyendo "S/ 0" donde hay 1.847.
*/
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
  .sube, .sidebar a, .tabla tbody tr { opacity: 1; animation: none; }
  .luz-fondo, .hebras i::after { animation: none; }
  .trazo { stroke-dashoffset: 0; animation: none; }
  .area { opacity: 1; animation: none; }
  /* En su valor final, nunca en cero: apagar la animacion no puede dejar a
     nadie leyendo "0 abonados" donde hay 312. */
  .cuenta { --n: var(--fin); animation: none; }
  @view-transition { navigation: none; }
}

@media (max-width: 860px) {
  .layout { flex-direction: column; }
  .sidebar { width: 100%; flex: none; padding: 8px 0; border-right: 0; border-bottom: 1px solid var(--filo); }
  .contenido { padding: 16px; }

  /*
    La tabla adelgaza antes de desplazarse: en un telefono, 54 px de fila y
    12 px a cada lado de cada celda sacan de la pantalla columnas que si
    cabrian. Primero se aprieta, y solo lo que siga sin caber se desplaza.
  */
  .tabla td { padding: 10px 9px; height: auto; font-size: 13px; }
  .tabla th { padding: 0 9px 9px; letter-spacing: .1em; }
  /* El panel tambien: 20 px a cada lado en una pantalla de 360 se comen
     media columna, y aqui el aire cuesta mas de lo que aporta. */
  .panel { padding: 16px; }

  /*
    En movil la barra lateral desaparece ENTERA: la navegacion es la barra
    inferior (lo frecuente, en la zona del pulgar) y el menu a pantalla
    completa (#menu-movil, por :target y sin JavaScript). La palanca <details>
    que se plegaba aqui murio con este cambio: dos menus moviles son uno de
    mas, y el que quedara detras seria el del tecnico en la calle.
  */
  .sidebar { display: none; }

  /* La barra deja sitio: sin este margen, la ultima tarjeta de la cola queda
     debajo de la barra y su boton de Cerrar no se puede tocar. */
  .contenido { padding-bottom: 90px; }

  /* Los formularios en fila obligaban a scroll horizontal para llegar al
     primer campo. En movil se apilan y ocupan el ancho. */
  .acciones { flex-direction: column; align-items: stretch; }
  .acciones .campo, .acciones .btn { width: 100%; }
  .btn-sm { padding: 9px 12px; }
}

/* Rotar la credencial de un equipo es opcional y se confirma escribiendo la
   palabra: la advertencia y el campo solo aparecen con la casilla marcada.
   Hermanos adyacentes (input + label + div) a proposito, sin JS. */
.rotar-check + label + .rotar-confirmar { display: none; }
.rotar-check:checked + label + .rotar-confirmar { display: block; margin-top: 8px; }

/* ---------- Vista rapida de conexion (ficha del abonado) ---------- */
/* La cifra en proporcional y grande, el juicio en palabra y color: quien no
   sabe que es un dBm lee «Bien» y ya esta. La mono queda para identificadores. */
.vital { padding: 12px 14px; border: 1px solid var(--filo); border-radius: 10px; background: var(--hover-fila); }
.vital .cifra { font: 640 22px/1.1 var(--display); letter-spacing: -0.02em; font-variant-numeric: tabular-nums; margin: 8px 0 4px; }
.vital .cifra small { font-size: 12px; font-weight: 550; color: var(--tinta-2); }
.juicio { display: inline-flex; align-items: center; gap: 5px; font-size: 12px; font-weight: 560; }
.juicio::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
.juicio-ok { color: var(--verde); }
.juicio-atencion { color: var(--ambar); }
.juicio-critico { color: var(--rojo); }
.juicio-neutro, .juicio-inactivo { color: var(--tinta-2); }

/* La cola de tickets: filtros con contador y tarjetas. La tabla recortaba la
   descripcion -- que es lo que el tecnico quiere leer -- y apretaba el cierre
   dentro de una celda; la tarjeta da dos lineas y la descripcion entera. */
.filtro { display: inline-flex; align-items: center; gap: 7px; padding: 7px 13px; border-radius: 20px; font: 550 12.5px/1 var(--display); border: 1px solid var(--filo); color: var(--tinta-2); background: transparent; text-decoration: none; }
.filtro strong { font: 640 12.5px/1 var(--datos); color: var(--tinta); }
.filtro:hover { background: var(--hover-fila); color: var(--tinta); }
.filtro-activo, .filtro-activo:hover { background: color-mix(in srgb, var(--brand) 10%, transparent); border-color: color-mix(in srgb, var(--brand) 30%, transparent); color: var(--luz, var(--brand)); }
.filtro-activo strong { color: var(--luz, var(--brand)); }
.tarjeta-ticket { border: 1px solid var(--filo); border-radius: 12px; background: var(--hover-fila); padding: 14px 16px; margin: 0 0 10px; }
.tarjeta-ticket .linea { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.tarjeta-ticket .descripcion { font-size: 13.5px; margin: 8px 0 10px; line-height: 1.5; max-width: 70ch; }

/*
  La navegacion del pulgar (solo movil). Lo que el tecnico abre veinte veces al
  dia -- su cola, la agenda, buscar, la red -- fijo abajo, que es donde esta el
  pulgar, con contadores encima: 3 sin tomar se ve ANTES de tocar nada. Cada
  destino con su texto; un icono sin palabra es una adivinanza.
*/
.barra-inferior { display: none; }

@media (max-width: 860px) {
  .barra-inferior {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
    display: flex;
    border-top: 1px solid var(--filo);
    /* Opaco, como todo lo que flota sobre contenido. */
    background: linear-gradient(180deg, var(--vidrio), var(--vidrio-2)), var(--void);
    padding: 6px 4px calc(6px + env(safe-area-inset-bottom));
  }
  .barra-inferior a {
    flex: 1;
    display: grid; justify-items: center; gap: 3px;
    padding: 7px 2px;
    min-height: 48px;
    border-radius: 10px;
    text-decoration: none;
    color: var(--tinta-2);
    font-size: 10.5px; font-weight: 600;
    position: relative;
  }
  .barra-inferior a[aria-current="page"] { color: var(--brand); }
  .barra-inferior a .ico { width: 21px; height: 21px; }
  .barra-inferior .globo {
    position: absolute; top: 2px; right: 18%;
    min-width: 16px; height: 16px; padding: 0 4px;
    border-radius: 99px;
    background: var(--rojo); color: var(--void);
    font: 700 10px/16px var(--datos); font-style: normal; text-align: center;
  }
  .barra-inferior .globo.atencion { background: var(--ambar); }
}

/*
  La campanita de la cabecera: <details> nativo, sin JavaScript. El panel es
  OPACO como todos los desplegables: lo translucido sobre texto es ilegible.
*/
.campanita { position: relative; }
.campanita > summary {
  list-style: none; cursor: pointer;
  display: grid; place-items: center; position: relative;
  width: 40px; height: 40px; border-radius: 10px;
  border: 1px solid var(--filo);
  background: linear-gradient(180deg, var(--vidrio), var(--vidrio-2)), var(--void);
}
.campanita > summary::-webkit-details-marker { display: none; }
.campanita > summary .ico { width: 18px; height: 18px; }
.campanita-globo {
  position: absolute; top: -6px; right: -6px;
  min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: 99px;
  background: var(--rojo); color: var(--void);
  font: 700 10px/16px var(--datos); text-align: center;
}
.campanita-globo.atencion { background: var(--ambar); }
.campanita-panel {
  position: absolute; right: 0; top: calc(100% + 8px);
  width: min(360px, calc(100vw - 32px));
  max-height: 60vh; overflow-y: auto;
  z-index: 80;
  padding: 6px;
  border: 1px solid var(--filo); border-radius: 12px;
  background: linear-gradient(180deg, var(--vidrio), var(--vidrio-2)), var(--void);
  box-shadow: 0 18px 40px rgba(0, 0, 0, .35);
}
.campanita-fila {
  display: flex; gap: 10px; align-items: center;
  padding: 10px 12px; border-radius: 8px;
  color: inherit; text-decoration: none; font-size: 13.5px;
}
a.campanita-fila:hover { background: var(--vidrio); }
.campanita-vacia { padding: 14px; color: var(--tinta-2); font-size: 13px; }

/*
  El menu completo del movil: los MISMOS enlaces del escritorio (parcial
  compartido), a pantalla entera y con filas para dedos. Se abre por :target
  desde «Más» y se cierra con el enlace a #. En escritorio no existe.
*/
.menu-movil { display: none; }

@media (max-width: 860px) {
  .menu-movil:target {
    display: flex; flex-direction: column;
    position: fixed; inset: 0; z-index: 60;
    overflow-y: auto;
    background: linear-gradient(180deg, var(--vidrio), var(--vidrio-2)), var(--void);
    padding: 10px 10px calc(16px + env(safe-area-inset-bottom));
  }
  .menu-movil-cab {
    display: flex; align-items: center; justify-content: space-between;
    padding: 8px 10px 14px;
    color: var(--tinta); font-weight: 600;
  }
  .menu-movil a { padding: 13px 14px; border-radius: 12px; font-size: 15px; }
  .menu-movil .pie-lateral { margin-top: 18px; padding: 16px 10px 0; border-top: 1px solid var(--filo); }
}

/*
  Las losas del aterrizaje (el "Resumen del tecnico"): sus numeros, no los del
  negocio, y cada losa es un destino. Grandes a proposito: imposibles de fallar
  con el pulgar, con guantes, en la moto. Valen tambien en escritorio -- una
  cuadricula de accesos con contadores no le sobra a nadie.
*/
.losas {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 12px;
}
.losa {
  display: flex; flex-direction: column; gap: 6px;
  min-height: 128px;
  padding: 16px 15px;
  border: 1px solid var(--filo); border-radius: 14px;
  background: linear-gradient(180deg, var(--vidrio), var(--vidrio-2));
  box-shadow: var(--hondo);
  text-decoration: none; color: var(--tinta);
}
.losa:hover { border-color: color-mix(in srgb, var(--brand) 45%, transparent); }
.losa .cifra { font: 700 32px/1 var(--datos); color: var(--brand); }
.losa .cifra.critico { color: var(--rojo); }
.losa .cifra.atencion { color: var(--ambar); }
.losa .que { font-weight: 620; font-size: 15px; }
.losa .detalle { margin-top: auto; font-size: 12.5px; color: var(--tinta-3); }
@media (max-width: 860px) {
  .losas { grid-template-columns: 1fr 1fr; }
}
