/* ======================================================================
   Consola del operador — hoja de estilo única.

   Esto se mira ocho horas seguidas en un monitor de 1366x768. Las tres
   reglas que mandan sobre cualquier gusto:

   1. Densidad. Cabe más información que aire. Un operador que tiene que
      desplazar la cola para ver la cuarta carrera pierde la cuarta
      carrera.
   2. El color significa algo. Los estados tienen su propia familia de
      colores y el acento (morado) es SOLO de los botones de acción. Si
      el botón principal fuera azul, competiría con el azul de "ocupado"
      y a media tarde nadie distingue una cosa de la otra.
   3. Claro por defecto. La oficina tiene ventana; un tema oscuro con
      reflejo se lee peor que uno claro.
   ====================================================================== */

:root {
  /* --- superficies y texto --- */
  --papel: #f4f5f7;
  --tarjeta: #ffffff;
  --tarjeta-alt: #fafbfc;
  --borde: #d7dbe0;
  --borde-suave: #e6e9ed;
  --tinta: #16191d;
  --tinta-media: #4c545e;
  --tinta-tenue: #79828d;

  /* --- acento: solo acciones, nunca estados --- */
  --acento: #5b21b6;
  --acento-fuerte: #4c1d95;
  --acento-suave: #f2ecfb;

  /* --- semántica de estados --- */
  --libre: #15803d;
  --libre-fondo: #e8f6ec;
  --oferta: #b45309;
  --oferta-fondo: #fdf2e2;
  --ocupado: #1d4ed8;
  --ocupado-fondo: #e8effc;
  --pausa: #6b7280;
  --pausa-fondo: #eef0f2;
  --sinsenal: #8b8f95;
  --alerta: #b91c1c;
  --alerta-fondo: #fdecec;
  --alerta-borde: #f0a6a6;

  /* --- categorías de vehículo ---
     Tres familias que no son ni un estado ni una acción, así que no
     pueden parecerse ni al verde de «libre», ni al azul de «ocupado»,
     ni al ámbar de «con oferta», ni al morado de los botones. El taxi
     es amarillo porque un taxi es amarillo; los otros dos solo tienen
     que verse distintos entre sí y del taxi a media tarde. */
  --taxi: #6b5300;
  --taxi-fondo: #fbf3c4;
  --taxi-borde: #e6d27a;
  --particular: #0f6b6b;
  --particular-fondo: #dff3f3;
  --particular-borde: #a6dad9;
  --moto: #a21c6e;
  --moto-fondo: #fce8f3;
  --moto-borde: #f0b6d6;

  --sombra: 0 1px 2px rgba(16, 20, 26, .08), 0 4px 12px rgba(16, 20, 26, .06);
  --radio: 5px;

  /* Alturas fijas de la rejilla. Al estar aquí, ajustar la consola para
     un monitor distinto es cambiar dos números. */
  --alto-barra: 46px;
  --ancho-carril: 460px;
}

* { box-sizing: border-box; }

/* El atributo `hidden` tiene que ganar SIEMPRE. La regla del navegador
   que lo aplica es de especificidad mínima, así que cualquier clase con
   `display: flex` o `display: grid` la pisa y el elemento se queda
   visible aunque el código lo haya ocultado. Pasó con el bloque de la
   dirección ubicada y con el plegado del formulario. */
[hidden] { display: none !important; }

html, body {
  height: 100%;
  margin: 0;
}

body {
  /* Tipografía del sistema: no se descarga nada, así que la consola pinta
     igual de rápido el primer día que el día que se cae internet. */
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
               "Helvetica Neue", Arial, sans-serif;
  font-size: 13px;
  line-height: 1.35;
  color: var(--tinta);
  background: var(--papel);
  display: grid;
  grid-template-rows: var(--alto-barra) 1fr;
  overflow: hidden;                 /* la página no se desplaza; los paneles sí */
}

/* Todo número que el operador compara de un vistazo va en cifras de ancho
   fijo. Sin esto, un "11" y un "18" ocupan distinto y la columna baila. */
.cifra__valor, .conteo, .reloj, .fila__movil, .ficha b,
.detalle__dato, .oferta__dato, table { font-variant-numeric: tabular-nums; }

/* El foco SIEMPRE se ve. Esta consola se opera con el teclado mientras se
   habla por teléfono, y un foco invisible obliga a soltar el auricular
   para buscar el mouse. */
:focus-visible {
  outline: 2px solid var(--acento);
  outline-offset: 1px;
}

button, input, select, textarea { font: inherit; color: inherit; }

/* ======================================================================
   INGRESO
   ====================================================================== */
.capa-ingreso {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: none;
  align-items: center;
  justify-content: center;
  background: #eceef1;
}
body.sin-sesion .capa-ingreso { display: flex; }
body.sin-sesion > .barra,
body.sin-sesion > .operacion { visibility: hidden; }

.tarjeta-ingreso {
  width: 320px;
  padding: 24px;
  background: var(--tarjeta);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: var(--sombra);
  display: grid;
  gap: 12px;
}
.tarjeta-ingreso__titulo { margin: 0; font-size: 17px; }
.tarjeta-ingreso__nota { margin: -8px 0 4px; color: var(--tinta-tenue); font-size: 12px; }

/* ======================================================================
   BARRA DE INDICADORES
   ====================================================================== */
.barra {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 0 10px;
  background: var(--tarjeta);
  border-bottom: 1px solid var(--borde);
}

.barra__marca { display: flex; align-items: center; gap: 6px; font-weight: 700; }
.barra__logo { color: var(--acento); font-size: 15px; }
.barra__nombre { letter-spacing: .2px; }

.barra__cifras {
  display: flex;
  align-items: center;
  gap: 14px;
  flex: 1;
  min-width: 0;
  overflow: hidden;
}

.cifra { display: flex; flex-direction: column; line-height: 1.1; }
.cifra__valor { font-size: 16px; font-weight: 700; }
.cifra__nombre { font-size: 10px; text-transform: uppercase; letter-spacing: .4px; color: var(--tinta-tenue); }
/* El indicador de "sin conductor" solo se pinta de rojo cuando hay
   alguna: en cero, un número rojo permanente deja de mirarse. */
.cifra--alerta[data-hay="si"] .cifra__valor { color: var(--alerta); }

.barra__separador { width: 1px; height: 26px; background: var(--borde); }

.flota { display: flex; gap: 5px; flex-wrap: nowrap; }

.barra__acciones { display: flex; align-items: center; gap: 8px; }
.barra__usuario { font-size: 12px; color: var(--tinta-media); max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.conexion {
  font-size: 11px;
  padding: 2px 7px;
  border-radius: 10px;
  border: 1px solid transparent;
  white-space: nowrap;
}
.conexion[data-estado="viva"]    { background: var(--libre-fondo); color: var(--libre); border-color: #bfe3c9; }
.conexion[data-estado="cortada"] { background: var(--oferta-fondo); color: var(--oferta); border-color: #edd0a5; }
.conexion[data-estado="muerta"]  { background: var(--alerta-fondo); color: var(--alerta); border-color: var(--alerta-borde); }

/* ======================================================================
   FICHAS DE ESTADO
   Un mismo componente para la leyenda del mapa, el resumen de flota y la
   etiqueta de cada fila: si el verde de "libre" cambia, cambia en todas.
   ====================================================================== */
.ficha {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  padding: 1px 6px;
  border-radius: 3px;
  border: 1px solid transparent;
  white-space: nowrap;
}
.ficha b { font-weight: 700; }

.ficha--libre    { background: var(--libre-fondo);   color: var(--libre);   border-color: #c6e5cf; }
.ficha--oferta   { background: var(--oferta-fondo);  color: var(--oferta);  border-color: #eed6ac; }
.ficha--ocupado  { background: var(--ocupado-fondo); color: var(--ocupado); border-color: #c6d6f5; }
.ficha--pausa    { background: var(--pausa-fondo);   color: var(--pausa);   border-color: #d9dde1; }
.ficha--sinsenal { background: #f1f2f4; color: var(--sinsenal); border-color: #dadde1; border-style: dashed; }
.ficha--total    { background: #eef0f2; color: var(--tinta-media); border-color: #dadde1; }
.ficha--alerta   { background: var(--alerta-fondo);  color: var(--alerta);  border-color: var(--alerta-borde); }
.ficha--origen   { background: var(--acento-suave);  color: var(--acento);  border-color: #d8c9f0; }

/* Etiquetas de estado de CARRERA. Se separan de las de móvil a propósito:
   son dos vocabularios distintos y mezclarlos confunde. */
.ficha--SOLICITADA    { background: #eef0f2; color: var(--tinta-media); border-color: #dadde1; }
.ficha--OFRECIDA      { background: var(--oferta-fondo);  color: var(--oferta);  border-color: #eed6ac; }
.ficha--ACEPTADA      { background: var(--ocupado-fondo); color: var(--ocupado); border-color: #c6d6f5; }
.ficha--EN_CAMINO     { background: var(--ocupado-fondo); color: var(--ocupado); border-color: #c6d6f5; }
.ficha--EN_EL_PUNTO   { background: var(--ocupado-fondo); color: var(--ocupado); border-color: #c6d6f5; }
.ficha--EN_CURSO      { background: var(--libre-fondo);   color: var(--libre);   border-color: #c6e5cf; }
.ficha--TERMINADA     { background: var(--libre-fondo);   color: var(--libre);   border-color: #c6e5cf; }
.ficha--SIN_CONDUCTOR { background: var(--alerta-fondo);  color: var(--alerta);  border-color: var(--alerta-borde); }
.ficha--CANCELADA     { background: #f1f2f4; color: var(--tinta-tenue); border-color: #dadde1; }

/* La categoría del vehículo: taxi, carro particular o moto. El color va
   por atributo y no por clase para que una categoría que el backend
   añada mañana salga en gris neutro y con su texto, no en blanco. La
   misma ficha se usa en la cola, en el detalle, en el diálogo de
   asignar y en la lista de móviles: un solo sitio para el color. */
.ficha--categoria { background: #eef0f2; color: var(--tinta-media); border-color: #dadde1; font-weight: 600; }
.ficha--categoria[data-categoria="taxi"]       { background: var(--taxi-fondo);       color: var(--taxi);       border-color: var(--taxi-borde); }
.ficha--categoria[data-categoria="particular"] { background: var(--particular-fondo); color: var(--particular); border-color: var(--particular-borde); }
.ficha--categoria[data-categoria="moto"]       { background: var(--moto-fondo);       color: var(--moto);       border-color: var(--moto-borde); }

/* La carrera que pidió el pasajero desde su celular. Blanca con borde
   oscuro, sin color de estado ni de acción: no dice qué pasa con la
   carrera, dice que hay una persona mirando su teléfono y que nadie de
   la oficina ha hablado con ella. */
.ficha--app { background: var(--tarjeta); color: var(--tinta); border-color: var(--tinta-media); font-weight: 700; letter-spacing: .3px; }

/* ======================================================================
   BOTONES
   ====================================================================== */
.boton {
  padding: 4px 10px;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--tarjeta);
  color: var(--tinta);
  font-size: 12px;
  cursor: pointer;
  white-space: nowrap;
}
.boton:hover:not(:disabled) { background: #f0f2f4; }
.boton:disabled { opacity: .45; cursor: not-allowed; }

.boton--acento { background: var(--acento); border-color: var(--acento); color: #fff; font-weight: 600; }
.boton--acento:hover:not(:disabled) { background: var(--acento-fuerte); }

.boton--peligro { background: var(--alerta); border-color: var(--alerta); color: #fff; font-weight: 600; }
.boton--peligro:hover:not(:disabled) { background: #8f1616; }

.boton--plano { background: transparent; border-color: transparent; color: var(--tinta-media); }
.boton--plano:hover:not(:disabled) { background: #eceef1; }

.boton--chico { padding: 2px 6px; font-size: 11px; }
.boton--ancho { width: 100%; padding: 7px; }

/* El botón de silencio cambia de aspecto cuando está apagado, porque un
   operador que silenció el aviso a las nueve y se le olvidó, a las cinco
   ya no oye las carreras sin conductor y no sabe por qué. */
#boton-silencio[aria-pressed="true"] {
  background: var(--alerta-fondo);
  border-color: var(--alerta-borde);
  color: var(--alerta);
  font-weight: 600;
}

/* ======================================================================
   CAMPOS
   ====================================================================== */
.campo { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.campo__nombre { font-size: 10px; text-transform: uppercase; letter-spacing: .4px; color: var(--tinta-tenue); }
.obligatorio { color: var(--alerta); }

.campo input, .campo select, .campo textarea {
  /* 26 px de alto y 100% de ancho. Un campo estrecho en el que no cabe
     una dirección obliga a escribir a ciegas. */
  width: 100%;
  min-width: 0;
  padding: 4px 6px;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--tarjeta);
}
.campo input:focus, .campo select:focus { border-color: var(--acento); }
.campo--crece { flex: 1 1 auto; }
.campo--corto { flex: 0 0 118px; }

/* ======================================================================
   REJILLA DE OPERACIÓN
   ====================================================================== */
.operacion {
  display: grid;
  grid-template-columns: 1fr var(--ancho-carril);
  gap: 8px;
  padding: 8px;
  min-height: 0;                    /* sin esto los hijos con scroll crecen sin fin */
}

.panel {
  background: var(--tarjeta);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  display: flex;
  flex-direction: column;
  min-height: 0;
  overflow: hidden;
}

.panel--mapa { position: relative; }

.panel__cabeza {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 5px 8px;
  border-bottom: 1px solid var(--borde-suave);
  background: var(--tarjeta-alt);
}
.panel__titulo { margin: 0; font-size: 12px; text-transform: uppercase; letter-spacing: .5px; color: var(--tinta-media); }
.panel__nota { font-size: 10px; color: var(--tinta-tenue); }
.conteo {
  display: inline-block;
  margin-left: 4px;
  padding: 0 5px;
  border-radius: 8px;
  background: #e9ebee;
  color: var(--tinta);
  font-size: 11px;
}

/* El carril derecho: formulario arriba y las dos listas repartiéndose lo
   que sobre. Las listas comparten el alto en vez de fijarlo, para que en
   un monitor más alto se aproveche todo. */
.carril {
  display: grid;
  grid-template-rows: auto minmax(120px, 1fr) minmax(120px, 1fr);
  gap: 8px;
  min-height: 0;
}
.carril .panel--lista { min-height: 0; }

/* ======================================================================
   MAPA
   ====================================================================== */
.mapa { flex: 1; min-height: 0; }
.mapa__leyenda {
  display: flex;
  gap: 5px;
  flex-wrap: wrap;
  padding: 4px 6px;
  border-top: 1px solid var(--borde-suave);
  background: var(--tarjeta-alt);
}
.mapa__pista {
  position: absolute;
  top: 8px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 500;                     /* por encima de las teselas de Leaflet */
  margin: 0;
  padding: 4px 10px;
  border-radius: 3px;
  background: var(--acento);
  color: #fff;
  font-size: 12px;
  box-shadow: var(--sombra);
}

/* --- marcador de móvil ---
   El número del móvil va escrito encima. Un punto de color sin número
   obliga a pasar el mouse por cada taxi para saber cuál es.

   OJO con el selector: Leaflet SUSTITUYE la clase del divIcon por
   "leaflet-marker-icon " + la que uno le pase, así que la clase
   .leaflet-div-icon que trae por defecto desaparece. Enganchar el estilo
   a ella deja los marcadores sin pintar y el error es silencioso: el
   marcador está en el mapa, pero invisible. */
.leaflet-marker-icon.pin {
  display: flex;
  align-items: center;
  justify-content: center;
  width: auto;
  min-width: 26px;
  height: 18px;
  padding: 0 4px;
  border-radius: 3px;
  border: 1.5px solid #fff;
  background: var(--pausa);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  white-space: nowrap;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .4);
}
.pin[data-estado="LIBRE"]            { background: var(--libre); }
.pin[data-estado="OFERTA_PENDIENTE"] { background: var(--oferta); }
.pin[data-estado="OCUPADO"]          { background: var(--ocupado); }
.pin[data-estado="EN_PAUSA"]         { background: var(--pausa); }

/* Un móvil sin señal PARECE disponible y no lo está. Se atenúa y se le
   pone al lado el tiempo que lleva callado, porque despacharle una
   carrera a un teléfono muerto le cuesta al pasajero veinte segundos. */
.pin[data-fresca="no"] {
  opacity: .5;
  border-style: dashed;
  border-color: #fff;
  filter: grayscale(.55);
}
.pin__mudo { margin-left: 3px; font-weight: 500; opacity: .95; }

/* --- marcador de origen de carrera --- */
.leaflet-marker-icon.origen {
  display: flex;
  align-items: center;
  justify-content: center;
  width: auto;
  min-width: 22px;
  height: 20px;
  padding: 0 5px;
  border-radius: 10px 10px 10px 2px;   /* forma distinta: no se confunde con un móvil */
  border: 1.5px solid #fff;
  background: var(--acento);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
  box-shadow: 0 1px 3px rgba(0, 0, 0, .4);
}
.origen[data-alerta="si"] { background: var(--alerta); }
.leaflet-marker-icon.punto-nuevo {
  width: 14px; height: 14px;
  border-radius: 50%;
  border: 3px solid var(--acento);
  background: #fff;
  box-shadow: 0 0 0 3px rgba(91, 33, 182, .25);
}

/* El de llegada, cuadrado y en otro color. Se distingue del de recogida
   por la FORMA y no solo por el color: en un mapa con doce marcadores,
   dos círculos de tonos parecidos se confunden, y confundirlos es
   mandar el taxi al destino. */
.leaflet-marker-icon.punto-destino {
  width: 14px; height: 14px;
  border-radius: 3px;
  border: 3px solid #0f766e;
  background: #fff;
  box-shadow: 0 0 0 3px rgba(15, 118, 110, .25);
}

.linea-viaje { stroke: #0f766e; opacity: .6; }

/* ======================================================================
   LISTAS DE CARRERAS
   ====================================================================== */
.lista { flex: 1; min-height: 0; overflow-y: auto; }
.vacio { margin: 0; padding: 14px 10px; color: var(--tinta-tenue); font-size: 12px; text-align: center; }

.fila {
  display: grid;
  grid-template-columns: 62px 1fr auto;
  gap: 2px 8px;
  padding: 5px 8px;
  border-bottom: 1px solid var(--borde-suave);
  cursor: pointer;
  background: var(--tarjeta);
}
.fila:hover { background: #f5f6f8; }
.fila[data-seleccionada="si"] { background: var(--acento-suave); box-shadow: inset 3px 0 0 var(--acento); }

/* La fila de una carrera que quedó sin conductor. Es el único rojo
   fuerte de la pantalla, y se queda hasta que alguien la abra: si se
   apagara sola, la carrera que el sistema no pudo resolver se pierde
   entre las demás. */
.fila[data-alerta="si"] {
  background: var(--alerta-fondo);
  box-shadow: inset 3px 0 0 var(--alerta);
}
.fila[data-alerta="si"]:hover { background: #fbe0e0; }

.fila__consecutivo { font-weight: 700; font-size: 12px; font-variant-numeric: tabular-nums; }
.fila__cabeza { display: flex; align-items: center; gap: 6px; min-width: 0; }
.fila__origen {
  font-size: 12.5px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.fila__derecha { display: flex; align-items: center; gap: 6px; justify-self: end; }

.reloj { font-size: 12px; font-weight: 700; color: var(--tinta-media); }
.reloj[data-urgencia="media"] { color: var(--oferta); }
.reloj[data-urgencia="alta"]  { color: var(--alerta); }

.fila__pie {
  grid-column: 2 / -1;
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  font-size: 11px;
  color: var(--tinta-tenue);
  min-width: 0;
}
.fila__pie span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fila__movil { font-weight: 700; color: var(--ocupado); }
.fila__sinpunto { color: var(--alerta); font-weight: 600; }

.fila__acciones { grid-column: 1 / -1; display: flex; gap: 4px; padding-top: 3px; }

/* ======================================================================
   DIÁLOGOS
   ====================================================================== */
.dialogo {
  width: 420px;
  max-width: 94vw;
  max-height: 88vh;
  padding: 0;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: 0 10px 40px rgba(16, 20, 26, .25);
  color: var(--tinta);
  background: var(--tarjeta);
}
.dialogo--ancho { width: 720px; }
.dialogo::backdrop { background: rgba(16, 20, 26, .35); }

.dialogo__cabeza {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 10px;
  border-bottom: 1px solid var(--borde-suave);
  background: var(--tarjeta-alt);
}
.dialogo__titulo { margin: 0; font-size: 14px; }
.dialogo__cuerpo { padding: 10px; display: grid; gap: 10px; max-height: 72vh; overflow-y: auto; }
.dialogo__pie { display: flex; gap: 6px; justify-content: flex-end; }
.dialogo__pista { margin: 0; font-size: 12px; color: var(--tinta-media); }

/* --- detalle de carrera --- */
.detalle__rejilla {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px 12px;
}
.detalle__campo { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.detalle__nombre { font-size: 10px; text-transform: uppercase; letter-spacing: .4px; color: var(--tinta-tenue); }
.detalle__dato { font-size: 12.5px; word-break: break-word; }
.detalle__ancho { grid-column: 1 / -1; }

.detalle__titulo {
  margin: 6px 0 0;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .5px;
  color: var(--tinta-media);
  border-top: 1px solid var(--borde-suave);
  padding-top: 6px;
}

.tabla { width: 100%; border-collapse: collapse; font-size: 12px; }
.tabla th {
  text-align: left;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--tinta-tenue);
  border-bottom: 1px solid var(--borde);
  padding: 3px 5px;
  font-weight: 600;
}
.tabla td { padding: 3px 5px; border-bottom: 1px solid var(--borde-suave); vertical-align: top; }
.tabla tr:nth-child(even) td { background: var(--tarjeta-alt); }
.tabla__hora { color: var(--tinta-tenue); white-space: nowrap; font-variant-numeric: tabular-nums; }

.resultado--aceptada  { color: var(--libre);  font-weight: 600; }
.resultado--rechazada { color: var(--alerta); font-weight: 600; }
.resultado--vencida   { color: var(--oferta); font-weight: 600; }
.resultado--anulada,
.resultado--pendiente { color: var(--tinta-tenue); }

/* --- lista de móviles para asignar --- */
.moviles { display: grid; gap: 3px; max-height: 240px; overflow-y: auto; padding-right: 2px; }
.movil-opcion {
  display: grid;
  grid-template-columns: auto 46px 1fr auto;
  align-items: center;
  gap: 8px;
  padding: 4px 6px;
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  cursor: pointer;
}
.movil-opcion:hover { background: #f5f6f8; }
.movil-opcion:has(input:checked) { border-color: var(--acento); background: var(--acento-suave); }
.movil-opcion__numero { font-weight: 700; font-variant-numeric: tabular-nums; }
.movil-opcion__conductor { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; }
/* La categoría y el estado del móvil en UNA celda de la rejilla: la
   rejilla tiene cuatro columnas y una quinta ficha suelta partiría cada
   opción en dos renglones. */
.movil-opcion__fichas { display: inline-flex; gap: 4px; justify-self: end; }
.movil-opcion[data-fresca="no"] { opacity: .7; }

/* ======================================================================
   AVISOS
   ====================================================================== */
.aviso {
  margin: 0;
  padding: 5px 8px;
  border-radius: var(--radio);
  font-size: 12px;
  background: var(--oferta-fondo);
  border: 1px solid #eed6ac;
  color: #7a3c07;
}
.aviso--malo  { background: var(--alerta-fondo); border-color: var(--alerta-borde); color: var(--alerta); }
.aviso--bueno { background: var(--libre-fondo);  border-color: #c6e5cf; color: #10592c; }

.ubicacion {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 4px 7px;
  border-radius: var(--radio);
  font-size: 12px;
  background: var(--tarjeta-alt);
  border: 1px solid var(--borde-suave);
}
.ubicacion[data-confianza="alta"]  { background: var(--libre-fondo);  border-color: #c6e5cf; }
.ubicacion[data-confianza="media"] { background: var(--oferta-fondo); border-color: #eed6ac; }
/* Confianza baja: el geocodificador devolvió coordenadas válidas que
   pueden apuntar a cualquier parte de la ciudad. Se avisa fuerte porque
   un taxi enviado a un punto inventado es peor que un taxi que se
   demora. */
.ubicacion[data-confianza="baja"]  { background: var(--alerta-fondo); border-color: var(--alerta-borde); color: var(--alerta); font-weight: 600; }

/* El aproximado que el operador le dice al pasajero por teléfono.

   La cifra grande y la advertencia pegada a ella, no en otro sitio de la
   pantalla: lo que se lee es lo que se repite en voz alta, y una cifra
   sola se dice como precio cerrado. La nota tiene que caber en la misma
   mirada. */
.tarifa {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 8px;
  margin: 0;
  padding: 5px 8px;
  border-radius: var(--radio);
  background: var(--libre-fondo);
  border: 1px solid #c6e5cf;
}
.tarifa__cifra {
  font-size: 15px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.tarifa__nota { font-size: 11px; color: var(--tinta-media); }

.forma { padding: 8px; display: grid; gap: 7px; }
.forma__fila { display: flex; gap: 8px; align-items: flex-end; }
.forma__pie { display: flex; gap: 6px; }

/* Los avisos van sobre el mapa, abajo a la izquierda, y NO sobre el
   carril derecho: allí taparían los botones de las últimas filas de la
   cola, que es justo donde el operador va a hacer clic cuando salta un
   aviso. */
.avisos {
  position: fixed;
  left: 14px;
  bottom: 44px;
  z-index: 700;
  display: grid;
  gap: 6px;
  width: 320px;
}
.avisos .aviso { box-shadow: var(--sombra); }

/* ======================================================================
   PANTALLAS CHICAS
   En 1366x768 el carril de 460 px deja el mapa en unos 880: suficiente.
   Por debajo de 1180 se estrecha antes que sacrificar el mapa.
   ====================================================================== */
@media (max-width: 1180px) {
  :root { --ancho-carril: 380px; }
  .barra__cifras { gap: 10px; }
  .flota .ficha--total { display: none; }
}
@media (max-width: 980px) {
  .operacion { grid-template-columns: 1fr; grid-template-rows: 260px 1fr; }
}

/* Quien prefiere menos movimiento no necesita ninguno aquí: esta consola
   no anima nada por gusto. Se deja declarado por si se añade después. */
@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}

/* ======================================================================
   ======================================================================
   MESA DE ATENCIÓN — WhatsApp y llamadas.

   Dos piezas: una barra fija abajo (siempre visible, con el botón de
   "Entra llamada" y el contador de chats) y un cajón que se abre SOBRE
   EL MAPA. El cajón tapa el mapa y no el carril derecho porque mientras
   se contesta un chat lo que no se puede perder de vista es la cola y el
   formulario de carrera nueva —que es donde caen las direcciones
   frecuentes del pasajero—, y los dos están a la derecha.
   ======================================================================
   ====================================================================== */

:root {
  --alto-mesa: 38px;
  --whats: #128c7e;          /* solo para el botón de la bandeja */
  --whats-fondo: #e7f5f2;
}

/* La barra de la mesa es una fila más del cuerpo, no un flotante: así no
   tapa nunca la última fila de la cola, que es justo donde el operador
   hace clic cuando salta un aviso.

   La columna va con `minmax(0, 1fr)` y no con el `auto` que pone la
   rejilla por su cuenta: `auto` la estira hasta lo que mida el hijo más
   ancho, y la barra de llamadas con sus cinco botones de cierre empujaba
   la rejilla entera fuera de la pantalla. Se veía como el carril derecho
   cortado y el botón de Salir a medias. */
body {
  grid-template-rows: var(--alto-barra) 1fr auto;
  grid-template-columns: minmax(0, 1fr);
}
body.sin-sesion > .mesa-barra { display: none; }
body.sin-sesion > .cajon { display: none !important; }

/* Solo para lectores de pantalla: la etiqueta existe, pero en una barra
   de 38 px no cabe escrita. */
.visualmente-oculto {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ----------------------------------------------------------------------
   Indicador de chats en la barra de arriba
   ---------------------------------------------------------------------- */
.cifra--mesa[data-hay="si"] .cifra__valor { color: var(--alerta); }

/* Ninguna cifra parte en dos renglones. La barra mide 46 px: un valor de
   dos líneas ("2 · 15" / "min") sale cortado por abajo y se lee mal justo
   el número que hay que mirar de reojo. Si no caben todas, la barra las
   recorta por la derecha, que ya lo hacía. */
.cifra__valor, .cifra__nombre { white-space: nowrap; }

/* Las dos cifras de la mesa ocupan sitio, y en 1366 empujaban "sin
   señal" fuera de la barra. Lo primero que sobra es el total en turno,
   que es la suma de las otras cinco y no dice nada nuevo. El conteo de
   móviles sin señal NO puede caerse: un taxi mudo parece disponible y no
   lo está. */
@media (max-width: 1400px) {
  .barra { gap: 10px; }
  .barra__cifras { gap: 9px; }
  .flota { gap: 3px; }
  .flota .ficha--total { display: none; }
}

/* Por debajo de 1250 ya no caben todas, y hay que elegir. Se van "sin
   persona" y "canceladas": son totales del día, no cambian de un minuto
   a otro y no deciden nada de lo que el operador va a hacer ahora. Se
   quedan la flota entera —un móvil sin señal parece disponible y no lo
   está— y las dos cifras de la mesa, que son las que se ponen rojas. */
@media (max-width: 1250px) {
  .barra__cifras > .cifra:nth-child(2),
  .barra__cifras > .cifra:nth-child(5) { display: none; }
  .flota .ficha { font-size: 10px; padding: 1px 5px; }
}

/* ----------------------------------------------------------------------
   BARRA DE LA MESA
   ---------------------------------------------------------------------- */
.mesa-barra {
  display: flex;
  align-items: center;
  gap: 8px;
  height: var(--alto-mesa);
  padding: 0 10px;
  min-width: 0;
  overflow: hidden;
  background: var(--tarjeta);
  border-top: 1px solid var(--borde);
}

.mesa-barra__chats {
  background: var(--whats-fondo);
  border-color: #b9ded6;
  color: #0c5f55;
  font-weight: 600;
}
.mesa-barra__chats:hover:not(:disabled) { background: #d9efea; }
/* Con chats esperando, el botón se pone rojo: es el único sitio de la
   pantalla que lo dice cuando el cajón está cerrado. */
.mesa-barra__chats[data-hay="si"] {
  background: var(--alerta-fondo);
  border-color: var(--alerta-borde);
  color: var(--alerta);
}
.mesa-barra__espera { font-size: 11px; color: var(--alerta); font-weight: 600; }
.mesa-barra__dia { margin-left: auto; }

/* --- la llamada que está sonando ahora --- */
.llamada-viva {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 2px 8px;
  border: 1px solid var(--alerta-borde);
  border-radius: var(--radio);
  background: var(--alerta-fondo);
}
.llamada-viva__punto { color: var(--alerta); font-size: 9px; }
.llamada-viva__reloj {
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--alerta);
  min-width: 44px;
}
.llamada-viva .campo--corto { flex: 0 0 130px; }
.llamada-viva__ligada { font-size: 11px; font-weight: 700; color: var(--libre); }
.llamada-viva__cierre { font-size: 11px; color: var(--tinta-tenue); }
.llamada-viva__cierres { display: flex; gap: 3px; }

/* ----------------------------------------------------------------------
   EL CAJÓN
   Ocupa exactamente el hueco del mapa: arriba la barra, abajo la barra
   de la mesa, a la derecha el carril intacto. Que el carril no se mueva
   importa: el operador sabe de memoria dónde está "Crear carrera".
   ---------------------------------------------------------------------- */
.cajon {
  position: fixed;
  top: calc(var(--alto-barra) + 8px);
  left: 8px;
  right: calc(var(--ancho-carril) + 16px);
  bottom: calc(var(--alto-mesa) + 8px);
  /* Por encima de los controles de Leaflet, que se pintan con z-index
     1000 y se colarían por encima del cajón. */
  z-index: 1200;
  display: flex;
  flex-direction: column;
  background: var(--tarjeta);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: 0 10px 40px rgba(16, 20, 26, .25);
  overflow: hidden;
}

/* Los avisos tienen que seguir viéndose por encima del cajón: son los
   errores, y un error tapado es un error que nadie leyó. */
.avisos { z-index: 1300; }

.cajon__cabeza {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 5px 8px;
  border-bottom: 1px solid var(--borde-suave);
  background: var(--tarjeta-alt);
}
.cajon__cabeza .panel__nota { flex: 1; }
.cajon__sin-whatsapp { margin: 10px; }

.cajon__cuerpo {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 250px 1fr 270px;
}

/* ----------------------------------------------------------------------
   LA BANDEJA
   ---------------------------------------------------------------------- */
.bandeja {
  overflow-y: auto;
  border-right: 1px solid var(--borde-suave);
  min-height: 0;
}

.chat {
  display: grid;
  gap: 1px;
  padding: 5px 8px;
  border-bottom: 1px solid var(--borde-suave);
  cursor: pointer;
}
.chat:hover { background: #f5f6f8; }
.chat[data-abierto="si"] {
  background: var(--acento-suave);
  box-shadow: inset 3px 0 0 var(--acento);
}
/* El pasajero que escribió y no ha recibido nada, y que además no está
   atendiendo nadie. Es la única fila que se distingue a un metro, y va
   arriba del todo. */
.chat[data-urgente="si"] {
  background: var(--alerta-fondo);
  box-shadow: inset 3px 0 0 var(--alerta);
}
.chat[data-urgente="si"]:hover { background: #fbe0e0; }

.chat__cabeza { display: flex; align-items: center; gap: 6px; min-width: 0; }
.chat__nombre {
  font-weight: 600;
  font-size: 12.5px;
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.chat__globo {
  background: var(--alerta);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  padding: 0 5px;
  border-radius: 8px;
  font-variant-numeric: tabular-nums;
}
.chat__reloj {
  font-size: 11px;
  font-weight: 700;
  color: var(--tinta-tenue);
  font-variant-numeric: tabular-nums;
}
.chat[data-urgente="si"] .chat__reloj { color: var(--alerta); }

.chat__ultimo {
  font-size: 11.5px;
  color: var(--tinta-media);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.chat__mio { color: var(--tinta-tenue); }
.chat__pie { display: flex; gap: 5px; flex-wrap: wrap; font-size: 10px; }
.chat__tomada { color: var(--oferta); font-weight: 600; }
.chat__bloqueado { color: var(--alerta); font-weight: 700; }
.chat__carrera { color: var(--acento); font-weight: 700; }
.chat__ventana { color: var(--tinta-tenue); }

/* ----------------------------------------------------------------------
   EL HILO
   ---------------------------------------------------------------------- */
.hilo { display: flex; flex-direction: column; min-height: 0; min-width: 0; }

.hilo__cabeza {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 5px 8px;
  border-bottom: 1px solid var(--borde-suave);
  background: var(--tarjeta-alt);
}
/* Las etiquetas de la cabeza no se encogen ni se cortan: "la tienes tú"
   recortado a "la tienes" dice justo lo contrario de lo que hay que
   entender. Si no caben, bajan de línea; lo que se recorta con puntos
   suspensivos es el nombre, que siempre está también en la ficha. */
.hilo__quien {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 1 1 auto;
  flex-wrap: wrap;
  min-width: 0;
}
.hilo__quien .ficha { flex: 0 0 auto; }
.hilo__nombre {
  font-size: 13px;
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.hilo__nombre[data-sin="si"] { color: var(--tinta-tenue); font-weight: 500; }
.hilo__celular { font-size: 11px; color: var(--tinta-tenue); font-variant-numeric: tabular-nums; }
.hilo__acciones { display: flex; gap: 4px; }
.hilo__tomada { width: 100%; margin: 0; }

.hilo__mensajes {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 5px;
  background: var(--papel);
}

.burbuja {
  display: flex;
  flex-direction: column;
  gap: 1px;
  max-width: 78%;
  padding: 4px 8px;
  border-radius: 8px;
  border: 1px solid var(--borde-suave);
  background: var(--tarjeta);
}
.burbuja--suya { align-self: flex-start; border-bottom-left-radius: 2px; }
.burbuja--mia {
  align-self: flex-end;
  background: var(--whats-fondo);
  border-color: #c6e3dc;
  border-bottom-right-radius: 2px;
}
/* Un mensaje que NO llegó tiene que verse distinto a un metro: el
   operador cree que contestó y no contestó, y se queda tranquilo
   mientras el pasajero espera. */
.burbuja[data-malo="si"] {
  background: var(--alerta-fondo);
  border: 1px solid var(--alerta);
  border-left-width: 4px;
}
.burbuja__texto { font-size: 12.5px; white-space: pre-wrap; word-break: break-word; }
.burbuja__pie { font-size: 10px; color: var(--tinta-tenue); align-self: flex-end; }
.burbuja__plantilla { font-size: 10px; color: var(--acento); font-weight: 600; }
.burbuja__error { font-size: 11px; color: var(--alerta); font-weight: 700; }

/* --- el reloj de la ventana de 24 h --- */
.hilo__ventana {
  margin: 0;
  padding: 3px 8px;
  font-size: 11px;
  font-weight: 600;
  border-top: 1px solid var(--borde-suave);
}
.hilo__ventana[data-estado="abierta"]   { background: var(--libre-fondo);  color: #10592c; }
.hilo__ventana[data-estado="por-cerrar"]{ background: var(--oferta-fondo); color: #7a3c07; }
.hilo__ventana[data-estado="cerrada"]   { background: var(--alerta-fondo); color: var(--alerta); }

.hilo__cerrada {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 6px 8px;
  font-size: 12px;
  color: var(--alerta);
  background: var(--alerta-fondo);
  border-top: 1px solid var(--alerta-borde);
}

.hilo__escribir {
  display: flex;
  align-items: flex-end;
  gap: 6px;
  padding: 6px 8px;
  border-top: 1px solid var(--borde-suave);
}
.hilo__escribir textarea { resize: vertical; min-height: 34px; }
.hilo__botones { display: flex; flex-direction: column; gap: 3px; }
/* Un cuadro deshabilitado tiene que PARECER deshabilitado: si se ve
   igual, el operador escribe un párrafo y descubre después que no
   podía. */
.hilo__escribir textarea:disabled {
  background: #f1f2f4;
  color: var(--tinta-tenue);
  cursor: not-allowed;
}

/* ----------------------------------------------------------------------
   FICHA DEL PASAJERO
   Es lo que convierte una carrera de dos minutos en una de veinte
   segundos: si esa persona ya viajó, su dirección está aquí.
   ---------------------------------------------------------------------- */
.ficha-pasajero {
  overflow-y: auto;
  min-height: 0;
  padding: 8px;
  border-left: 1px solid var(--borde-suave);
  background: var(--tarjeta-alt);
  display: grid;
  gap: 6px;
  align-content: start;
}
.ficha-pasajero__nombre { display: flex; align-items: flex-end; gap: 6px; }
.ficha-pasajero__nombre .campo { flex: 1; }
.ficha-pasajero__cifras { display: flex; gap: 10px; font-size: 11.5px; }
.ficha-pasajero__cifras b { font-size: 14px; }
/* Un pasajero con cancelaciones no se esconde: el operador decide si le
   manda el móvil que está a dos cuadras o el que va de salida. */
.ficha-pasajero__cifras span[data-hay="si"] { color: var(--alerta); }
.ficha-pasajero__titulo {
  margin: 4px 0 0;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .4px;
  color: var(--tinta-tenue);
  border-top: 1px solid var(--borde-suave);
  padding-top: 4px;
}

.frecuentes { display: grid; gap: 3px; }
.frecuente { display: flex; align-items: center; gap: 4px; }
.frecuente__principal {
  flex: 1;
  min-width: 0;
  display: grid;
  gap: 0;
  text-align: left;
  padding: 4px 6px;
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background: var(--tarjeta);
  cursor: pointer;
}
.frecuente__principal:hover { background: var(--acento-suave); border-color: var(--acento); }
.frecuente__etiqueta { font-size: 11px; color: var(--acento); }
.frecuente__texto {
  font-size: 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.frecuente__veces { font-size: 10px; color: var(--tinta-tenue); }

.tabla--ficha td { font-size: 11px; }

/* ----------------------------------------------------------------------
   Resultados de llamada, en la tabla del día
   ---------------------------------------------------------------------- */
.resultado--carrera     { color: var(--libre);  font-weight: 600; }
.resultado--informacion { color: var(--tinta-media); }
.resultado--queja       { color: var(--alerta); font-weight: 600; }
.resultado--colgo       { color: var(--tinta-tenue); }
.resultado--equivocada  { color: var(--tinta-tenue); }

/* ----------------------------------------------------------------------
   PANTALLAS CHICAS
   ---------------------------------------------------------------------- */
@media (max-width: 1180px) {
  .cajon__cuerpo { grid-template-columns: 210px 1fr 240px; }
  .llamada-viva__cierre { display: none; }
}
/* Por debajo de 980 el carril ya no está al lado, así que el cajón toma
   la pantalla entera y la ficha se va debajo del hilo. */
@media (max-width: 980px) {
  .cajon { right: 8px; }
  .cajon__cuerpo { grid-template-columns: 200px 1fr; }
  .ficha-pasajero { grid-column: 1 / -1; border-left: none; border-top: 1px solid var(--borde-suave); }
}

/* ======================================================================
   ======================================================================
   ADMINISTRACIÓN — gente y flota.

   Una pantalla de oficina dentro de una consola de operación. Se rige
   por las mismas reglas de la casa (densidad, el acento solo para
   acciones), con una excepción a la vista: la clave recién generada se
   pinta ENORME. Es el único dato de todo el sistema que se muestra una
   vez y no se puede recuperar; si se lee mal, el conductor no entra a la
   app y hay que generarle otra.
   ======================================================================
   ====================================================================== */

/* ----------------------------------------------------------------------
   El menú del usuario, arriba a la derecha
   ---------------------------------------------------------------------- */
.menu-usuario { position: relative; display: flex; align-items: center; }

/* La flechita va en el CONTENEDOR y no dentro del botón: el nombre se
   recorta con puntos suspensivos cuando es largo ("Ana Gómez ·
   Administrador" no cabe en la barra), y una flecha dentro del botón se
   la comía ese mismo recorte. Sin flecha, nadie sabe que ahí hay un
   menú. */
.menu-usuario::after {
  content: "▾";
  color: var(--tinta-tenue);
  font-size: 11px;
  pointer-events: none;
}

/* El nombre pasó de <span> a <button> y tiene que seguir viéndose igual:
   sin caja, sin fondo, y recortado con puntos suspensivos cuando el
   nombre es largo. Solo se le añade la flechita que dice que se abre. */
button.barra__usuario {
  border: 0;
  background: transparent;
  padding: 2px 4px;
  border-radius: var(--radio);
  cursor: pointer;
  text-align: left;
  max-width: 160px;
}
button.barra__usuario:hover { background: #eceef1; }

/* z-index alto a propósito: los paneles de Leaflet llegan a 700 y sus
   controles a 1000, y todos compiten en la misma capa que esto. Con un
   número menor, el menú se abriría DEBAJO del mapa. */
.menu-usuario__lista {
  position: absolute;
  top: calc(100% + 4px);
  right: 0;
  z-index: 1200;
  min-width: 190px;
  padding: 3px;
  display: grid;
  gap: 1px;
  background: var(--tarjeta);
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  box-shadow: var(--sombra);
}
.menu-usuario__opcion {
  border: 0;
  background: transparent;
  padding: 6px 8px;
  border-radius: var(--radio);
  text-align: left;
  font-size: 12px;
  cursor: pointer;
  color: var(--tinta);
}
.menu-usuario__opcion:hover { background: var(--acento-suave); color: var(--acento); }

/* ----------------------------------------------------------------------
   El diálogo grande
   ---------------------------------------------------------------------- */

/* OJO con el selector: va con [open]. El navegador esconde los <dialog>
   cerrados con `display: none` en su hoja de estilo, y un `display: flex`
   sin condición se lo pisaría: la pantalla de administración aparecería
   pegada arriba a la izquierda de la consola desde que carga la página,
   con la lista de conductores a la vista de cualquier operador. */
.dialogo--admin[open] {
  display: flex;
  flex-direction: column;
  width: 1180px;
  max-width: 96vw;
  height: 88vh;
  max-height: 88vh;
}
.dialogo--admin .dialogo__cabeza { gap: 10px; }
.dialogo--admin .panel__nota { flex: 1 1 auto; }

/* El cuerpo es lo único que se desplaza. La cabecera, la clave y las
   pestañas se quedan fijas: la clave sobre todo, que no puede irse
   arriba al desplazar una lista de cuarenta conductores. */
.admin__cuerpo {
  flex: 1 1 auto;
  min-height: 0;
  max-height: none;
  align-content: start;
  gap: 8px;
}
.admin__panel { display: grid; gap: 8px; align-content: start; }

.admin__barra {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

/* ----------------------------------------------------------------------
   Pestañas
   ---------------------------------------------------------------------- */
.admin__pestanas {
  display: flex;
  gap: 2px;
  padding: 0 10px;
  border-bottom: 1px solid var(--borde);
  background: var(--tarjeta-alt);
}
.pestana {
  border: 0;
  border-bottom: 2px solid transparent;
  background: transparent;
  padding: 7px 12px;
  font-size: 12px;
  font-weight: 600;
  color: var(--tinta-media);
  cursor: pointer;
}
.pestana:hover { color: var(--tinta); }
.pestana[aria-selected="true"] {
  color: var(--acento);
  border-bottom-color: var(--acento);
}

/* ----------------------------------------------------------------------
   LA CLAVE RECIÉN GENERADA
   Grande, en cifras monoespaciadas y seleccionable de un doble clic. Se
   dicta por teléfono: una "l" que parece un "1" cuesta una llamada más y
   una clave nueva.
   ---------------------------------------------------------------------- */
.clave-nueva {
  padding: 10px 12px;
  border-bottom: 1px solid var(--borde);
  background: var(--acento-suave);
  display: grid;
  gap: 6px;
}
.clave-nueva__quien { margin: 0; font-size: 12px; font-weight: 600; color: var(--acento-fuerte); }
.clave-nueva__valor {
  margin: 0;
  font-family: "Cascadia Mono", Consolas, "Courier New", monospace;
  font-size: 26px;
  font-weight: 700;
  letter-spacing: 1px;
  color: var(--tinta);
  user-select: all;                /* un clic la selecciona entera */
  word-break: break-all;
}
.clave-nueva__aviso { margin: 0; font-size: 11.5px; color: var(--alerta); font-weight: 600; }
.clave-nueva__botones { display: flex; align-items: center; gap: 6px; }
.clave-nueva__copiado { font-size: 11px; color: var(--acento-fuerte); }

/* ----------------------------------------------------------------------
   Las tres listas
   ---------------------------------------------------------------------- */
.tabla--admin td { vertical-align: middle; }
.tabla--admin .ficha { margin-right: 2px; }

/* Un inactivo no se esconde —nada se borra, y su historial sigue
   colgando de él— pero se apaga: en una lista de cuarenta filas, el que
   ya no trabaja no puede pesar lo mismo que el que sí. */
.tabla--admin tr[data-inactivo="si"] td { opacity: .55; }
.tabla--admin tr[data-inactivo="si"] .ficha { opacity: 1; }

.admin__usuario, .admin__movil { font-weight: 600; font-variant-numeric: tabular-nums; }
.admin__aldia { color: var(--tinta-tenue); font-size: 11px; }
.admin__acciones { white-space: nowrap; text-align: right; }

/* La confirmación se pregunta en la propia fila, con el nombre delante:
   una ventana aparte con dos botones iguales es como se desactiva al
   conductor equivocado. */
.admin__confirma {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 2px 6px;
  border: 1px solid var(--alerta-borde);
  border-radius: var(--radio);
  background: var(--alerta-fondo);
  color: var(--alerta);
  font-size: 11.5px;
  font-weight: 600;
  white-space: normal;
  text-align: left;
}

/* ----------------------------------------------------------------------
   Formularios de alta
   ---------------------------------------------------------------------- */
.forma--alta {
  padding: 8px;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--tarjeta-alt);
}
.forma--alta .forma__fila { flex-wrap: wrap; }
.forma__pista { margin: 0; font-size: 11.5px; color: var(--tinta-media); }
#conductor-sugerido { color: var(--acento-fuerte); font-weight: 600; }

/* ----------------------------------------------------------------------
   PANTALLAS CHICAS
   En 1366x768 el diálogo ocupa 96 vw y 88 vh: caben las siete columnas
   de conductores sin desplazar en horizontal, que es lo que se paga con
   una tabla que se sale.
   ---------------------------------------------------------------------- */
@media (max-width: 1400px) {
  .tabla--admin { font-size: 11.5px; }
  .tabla--admin th, .tabla--admin td { padding: 3px 4px; }
  .clave-nueva__valor { font-size: 22px; }
}


/* ======================================================================
   ======================================================================
   REVISIÓN DE SOLICITUDES — los papeles de quien se registró solo.

   Cuarta pestaña de la administración. Tiene una forma distinta a las
   otras tres y por una razón: las demás son listas que se consultan, y
   esta es una cola que se trabaja. Por eso la bandeja y la solicitud
   abierta se ven a la vez —quien revisa pasa de una a otra sin volver a
   buscar dónde iba— y por eso la foto tiene un visor propio a pantalla
   casi completa: una cédula fotografiada de lejos no se lee en una caja
   de 400 px, y de eso depende poder decir si el número es el que la
   persona escribió.
   ======================================================================
   ====================================================================== */

/* ----------------------------------------------------------------------
   El aviso de «hay gente esperando», fuera del diálogo
   ---------------------------------------------------------------------- */

/* El punto rojo sobre el nombre del usuario. Es lo único de esta pantalla
   que se ve con todo cerrado, y tiene que verse: alguien que mandó sus
   papeles el viernes no puede quedarse sin respuesta hasta que a un
   administrador se le ocurra desplegar su menú. */
.menu-usuario__punto {
  position: absolute;
  top: -1px;
  right: 8px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--alerta);
  box-shadow: 0 0 0 2px var(--tarjeta);
  pointer-events: none;
}

/* El contador de la pestaña se pone rojo solo cuando hay algo que hacer.
   En gris pasa por decoración, que es lo que tiene que ser cuando la
   bandeja está vacía. */
#conteo-pendientes[data-hay="si"],
#conteo-mensual-pendientes[data-hay="si"],
#conteo-solicitudes {
  background: var(--alerta);
  color: #fff;
  font-weight: 700;
}

/* ----------------------------------------------------------------------
   La pestaña: bandeja a la izquierda, solicitud a la derecha
   ---------------------------------------------------------------------- */
.solic {
  display: grid;
  grid-template-columns: 320px minmax(0, 1fr);
  gap: 10px;
  align-items: start;
}

/* La bandeja se desplaza sola y no arrastra al detalle: son dos lecturas
   distintas, y una sola barra para las dos obligaría a subir la
   solicitud abierta para poder ver la siguiente de la cola. */
.solic__bandeja {
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  overflow: hidden;
  background: var(--tarjeta);
}
.solic__lista { max-height: 62vh; overflow-y: auto; }

.solic-fila {
  display: grid;
  gap: 2px;
  width: 100%;
  padding: 6px 8px;
  border: 0;
  border-bottom: 1px solid var(--borde-suave);
  border-left: 3px solid transparent;
  background: transparent;
  text-align: left;
  cursor: pointer;
  color: inherit;
}
.solic-fila:hover { background: #f5f6f8; }
.solic-fila[data-abierta="si"] {
  background: var(--acento-suave);
  border-left-color: var(--acento);
}

/* Las que esperan revisión se distinguen sin leer nada: son las que hay
   que trabajar hoy, y van arriba. */
.solic-fila[data-espera="si"] { background: #fff8ee; }
.solic-fila[data-espera="si"]:hover { background: #fdf0dc; }
.solic-fila[data-espera="si"][data-abierta="si"] { background: var(--acento-suave); }

.solic-fila__cabeza {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  min-width: 0;
}
.solic-fila__nombre {
  font-weight: 600;
  font-size: 12.5px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.solic-fila__pie {
  display: flex;
  gap: 6px;
  font-size: 11px;
  color: var(--tinta-tenue);
  min-width: 0;
}
.solic-fila__pie span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.solic-fila__placa { font-weight: 600; color: var(--tinta-media); text-transform: uppercase; }
.solic-fila__cuando { margin-left: auto; white-space: nowrap; flex: 0 0 auto; }
.solic-fila__faltan { color: var(--alerta); font-weight: 700; white-space: nowrap; }

/* Los colores de estado los decide el ESTADO y no el texto de la
   etiqueta: la redacción la puede cambiar el backend mañana. */
.ficha--sol-ENVIADA     { background: var(--oferta-fondo);  color: var(--oferta);  border-color: #eed6ac; }
.ficha--sol-EN_REVISION { background: var(--ocupado-fondo); color: var(--ocupado); border-color: #c6d6f5; }
.ficha--sol-SUBSANAR    { background: var(--alerta-fondo);  color: var(--alerta);  border-color: var(--alerta-borde); }
.ficha--sol-BORRADOR    { background: #f1f2f4; color: var(--tinta-tenue); border-color: #dadde1; border-style: dashed; }
.ficha--sol-APROBADA    { background: var(--libre-fondo);   color: var(--libre);   border-color: #c6e5cf; }
.ficha--sol-RECHAZADA   { background: #f1f2f4; color: var(--tinta-media); border-color: #dadde1; }

/* ----------------------------------------------------------------------
   La solicitud abierta
   ---------------------------------------------------------------------- */
.solic__detalle {
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--tarjeta);
  padding: 8px 10px;
  display: grid;
  gap: 8px;
  align-content: start;
  min-height: 200px;
}
.solic-det__cabeza { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.solic-det__nombre { margin: 0; font-size: 14px; }
.solic-det__acciones { display: flex; gap: 6px; flex-wrap: wrap; }
.solic-det__forma {
  display: grid;
  gap: 6px;
  padding: 8px;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  background: var(--tarjeta-alt);
}
.solic-det__forma .forma__fila { align-items: flex-end; flex-wrap: wrap; }

.solic-det__motivo {
  margin: 0;
  padding: 5px 8px;
  border-radius: var(--radio);
  background: var(--oferta-fondo);
  border: 1px solid #eed6ac;
  color: #7a3c07;
  font-size: 12px;
  display: grid;
  gap: 1px;
}
.solic-det__cerrada {
  margin: 0;
  font-size: 12px;
  font-weight: 600;
  color: var(--tinta-media);
}
.solic-det__resumen { margin: 0; }

/* LA AUTORIZACIÓN DE DATOS.
   Se pinta siempre y arriba del todo. Es la prueba que exige la Ley 1581
   de 2012 y va ANTES que los papeles a propósito: primero se mira si la
   persona consintió y desde cuándo, y después se abre su cédula. */
.solic-ley {
  margin: 0;
  padding: 5px 8px;
  border-radius: var(--radio);
  font-size: 11.5px;
  background: var(--libre-fondo);
  border: 1px solid #c6e5cf;
  color: #10592c;
}
.solic-ley--falta {
  background: var(--alerta-fondo);
  border-color: var(--alerta-borde);
  color: var(--alerta);
}

/* Los datos a un lado y los papeles al otro. Es la comparación que hace
   quien revisa: el número de cédula que la persona escribió contra el
   que sale en la foto. Con una cosa encima de la otra habría que
   recordar el número mientras se desplaza. */
.solic-det__cuerpo {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 12px;
  align-items: start;
}
.solic-det__datos, .solic-det__papeles { display: grid; gap: 6px; align-content: start; }

/* ----------------------------------------------------------------------
   Las tarjetas de cada papel
   ---------------------------------------------------------------------- */
.papeles { display: grid; gap: 4px; }
.papel {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 6px;
  padding: 4px 6px;
  border: 1px solid var(--borde-suave);
  border-left: 3px solid var(--borde);
  border-radius: var(--radio);
  background: var(--tarjeta);
  font-size: 12px;
}
.papel__rotulo { font-weight: 600; }
.papel__nota { font-size: 10.5px; color: var(--tinta-tenue); grid-column: 1; grid-row: 2; }
.papel .ficha { grid-column: 2; grid-row: 1 / span 2; }
.papel__ver { grid-column: 3; grid-row: 1 / span 2; }
.papel__motivo {
  grid-column: 1 / -1;
  margin: 0;
  font-size: 11px;
  color: var(--alerta);
}
.papel[data-estado="aprobado"]  { border-left-color: var(--libre); }
.papel[data-estado="rechazado"] { border-left-color: var(--alerta); background: var(--alerta-fondo); }
.papel[data-estado="pendiente"] { border-left-color: var(--oferta); }
/* Un obligatorio sin subir se ve como lo que es: el motivo por el que
   esta solicitud todavía no se puede aprobar. */
.papel[data-estado="falta"] {
  border-left-color: var(--alerta);
  border-style: dashed;
  color: var(--alerta);
}
.papel[data-estado="opcional"] { opacity: .6; }

/* ----------------------------------------------------------------------
   EL VISOR DE PAPELES
   Un segundo diálogo encima del de administración. Ocupa casi toda la
   pantalla porque el papel es el trabajo: todo lo demás de esta pantalla
   existe para llegar hasta aquí.
   ---------------------------------------------------------------------- */
.dialogo--visor[open] {
  display: flex;
  flex-direction: column;
  width: 1100px;
  max-width: 96vw;
  height: 92vh;
  max-height: 92vh;
}
.dialogo--visor .dialogo__cabeza { gap: 10px; }
.dialogo--visor #visor-posicion { flex: 1 1 auto; }

/* El lienzo es lo único que se desplaza, y el fondo es oscuro a
   propósito: una cédula sobre blanco se confunde con la página y cuesta
   ver dónde termina el papel y empieza la pantalla. */
.visor__lienzo {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  background: #2b2f36;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 8px;
}
.visor__imagen {
  display: block;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  background: #fff;
}
/* Ampliada: manda el ancho y el alto se va por debajo del borde, que es
   como se lee una cédula de cerca. */
.visor__imagen--zoom {
  max-width: none;
  max-height: none;
  height: auto;
  object-fit: fill;
  flex: 0 0 auto;
}
.visor__pdf {
  width: 100%;
  height: 100%;
  min-height: 60vh;
  border: 0;
  background: #fff;
}
.visor__enlace { margin: 6px 0 0; font-size: 12px; color: #fff; }
.visor__enlace a { color: #cbb7f2; }
.visor__cargando { margin: 20px; color: #d7dade; font-size: 12px; }

.visor__pie {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 6px 10px;
  border-top: 1px solid var(--borde);
  background: var(--tarjeta-alt);
  flex-wrap: wrap;
}
.visor__grupo { display: flex; align-items: center; gap: 4px; }
/* El juicio se va a la derecha del todo, lejos de «Siguiente»: aprobar un
   papel y pasar al siguiente son botones que se pulsan seguidos y muy
   rápido, y juntos se confunden. */
.visor__juicio { margin-left: auto; }
.visor__escala {
  min-width: 62px;
  text-align: center;
  font-size: 11px;
  color: var(--tinta-media);
  font-variant-numeric: tabular-nums;
}

.visor__motivo {
  display: flex;
  align-items: flex-end;
  gap: 6px;
  padding: 6px 10px;
  border-top: 1px solid var(--borde);
  background: var(--alerta-fondo);
}
/* El motivo que ya tiene el papel, para no escribir uno distinto cada vez
   que se vuelve a mirar. */
.visor__rechazo {
  margin: 0;
  padding: 4px 10px;
  font-size: 11.5px;
  color: var(--alerta);
  background: var(--alerta-fondo);
}
#visor-error { margin: 6px 10px 0; }

/* ----------------------------------------------------------------------
   PANTALLAS CHICAS
   En 1366x768 la bandeja se estrecha y los datos y los papeles pasan a
   una sola columna: es preferible desplazar el detalle a que el nombre de
   la persona salga cortado en dos líneas de cuatro letras.
   ---------------------------------------------------------------------- */
/* Dentro del detalle, los datos van a DOS columnas y no a las tres de
   siempre: aquí comparten el ancho con los papeles, y a tres columnas la
   fecha de la tecnomecánica quedaría en 130 px con el rótulo partido en
   dos renglones. */
.solic-det__datos .detalle__rejilla {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}

/* ----------------------------------------------------------------------
   PANTALLAS CHICAS
   En 1366x768 la bandeja se estrecha, pero los datos y los papeles siguen
   uno al lado del otro: son las dos mitades de la misma comparación
   —lo que la persona escribió contra lo que se ve en la foto— y ponerlos
   uno debajo del otro deja los papeles fuera de la pantalla.
   Solo por debajo de 1100 px, donde ya no caben, se apilan.
   ---------------------------------------------------------------------- */
@media (max-width: 1400px) {
  .solic { grid-template-columns: 240px minmax(0, 1fr); gap: 8px; }
  .solic__lista { max-height: 56vh; }
  .solic-det__cuerpo { gap: 10px; }
}

@media (max-width: 1100px) {
  .solic { grid-template-columns: minmax(0, 1fr); }
  .solic__lista { max-height: 30vh; }
  .solic-det__cuerpo { grid-template-columns: minmax(0, 1fr); gap: 8px; }
}

/* ==================================================================== */
/* RADIO — notas de voz con los móviles                                 */
/* ==================================================================== */
/* Misma forma que la bandeja de WhatsApp: el operador ya sabe usarla y
   son la misma cosa —mensajes que entran y hay que atender—. */

/* El cuerpo del cajón de WhatsApp es una rejilla de dos columnas —lista
   de chats y conversación— y la radio la heredaba: su lista caía en la
   columna de 200 px y «Móvil 101 · Conductor de Prueba» se partía en
   cuatro renglones. La radio no necesita dos columnas: es una lista y una
   barra para contestar, una debajo de otra. */
#cajon-radio .cajon__cuerpo {
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.radio-lista {
  display: flex;
  flex-direction: column;
  overflow-y: auto;
  flex: 1;
  min-height: 0;
}

.radio-nota {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  text-align: left;
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--borde, #2c3542);
  padding: 10px 12px;
  cursor: pointer;
}
.radio-nota:hover { background: rgba(255, 255, 255, .04); }
.radio-nota strong {
  /* El nombre cede antes que la hora: si algo se recorta, que sea el
     apellido del conductor y no cuándo habló. */
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Barra de color a la izquierda para saber de un vistazo quién habló
   sin tener que leer. Entra = del móvil, sale = de la mesa. */
.radio-nota--entra { border-left: 4px solid #17b866; }
.radio-nota--sale  { border-left: 4px solid #6b7a8c; }

/* Sin oír. En negrita y con punto: el operador tiene veinte móviles y
   necesita saber qué le falta sin abrir nada. */
.radio-nota--nueva strong { font-weight: 800; }
.radio-nota--nueva strong::before {
  content: "● ";
  color: #17b866;
}

/* Una nota de la MESA que el conductor todavía no ha oído. En ámbar y no
   en rojo: no es un error, es información que el operador necesita para
   decidir si lo llama por teléfono. Sin esta marca daría por hecho que su
   mensaje llegó, que es justo lo que pasaba. */
.radio-nota--sin-oir strong { color: #f2b705; }
.radio-nota--sin-oir strong::before {
  content: "○ ";
  color: #f2b705;
}

.radio-nota__hora {
  font-size: .82rem;
  opacity: .7;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.radio-responder {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px;
  border-top: 1px solid var(--borde, #2c3542);
}
.radio-responder__a { font-size: .9rem; opacity: .8; white-space: nowrap; }
.radio-responder__reloj {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  color: #e5484d;
}
/* El botón de hablar tiene que verse pulsado sin mirarlo: el operador
   está oyendo, no mirando la pantalla. */
#boton-hablar { flex: 1; user-select: none; touch-action: none; }
#boton-hablar.grabando {
  background: #e5484d;
  border-color: #e5484d;
  color: #2b0405;
}

/* ======================================================================
   LA TARIFA
   ====================================================================== */

/* Los grupos van rotulados y separados porque la separación ES el
   contenido: arriba lo que fija el municipio, abajo lo que decide la
   empresa. Un formulario con los diez campos seguidos invita justo al
   error que hay que impedir — bajar el banderazo para que salga más
   barato, y perder para siempre la referencia de lo que marca el
   aparato. */
.grupo {
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  padding: 6px 10px 10px;
  margin: 0;
}
.grupo__titulo {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--tinta-media);
  padding: 0 4px;
  margin: 0;
}
.grupo__nota {
  margin: 2px 0 8px;
  font-size: 12px;
  color: var(--tinta-tenue);
}
/* El bloque de la decisión comercial se distingue del decreto. Es el
   único de los tres que la empresa elige. */
.grupo--decision {
  border-color: var(--acento);
  background: var(--acento-suave);
}

.forma--tarifa { gap: 10px; }

/* Las tres muestras. Es lo que de verdad se mira en esta pantalla:
   nadie sabe leer un banderazo, pero todo el mundo sabe si tres mil
   pesos por cruzar la ciudad está bien o mal. */
.muestras {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 8px;
}
.muestra {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 8px 10px;
  border-radius: var(--radio);
  background: var(--libre-fondo);
  border: 1px solid #c6e5cf;
}
.muestra__nombre { font-size: 12px; font-weight: 600; }
.muestra__km { font-size: 11px; color: var(--tinta-tenue); }
.muestra__cifra {
  font-size: 20px;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 1.15;
}
/* Lo que marcaría el taxímetro, tachado y al lado de lo que se cotiza.
   Se enseñan las DOS: con solo la de cotizar no hay forma de saber
   cuánto se está apartando del decreto, que es la decisión que se está
   tomando aquí. */
.muestra__tachado {
  font-size: 12px;
  color: var(--tinta-tenue);
  text-decoration: line-through;
  font-variant-numeric: tabular-nums;
}

/* Una muestra que quedó por debajo de la carrera mínima del decreto.
   No se impide —la decisión es de Gerencia— pero no puede pasar
   inadvertida: el porcentaje se elige mirando la carrera larga, y la
   corta es la que más se repite en un día. */
.muestra--alerta {
  background: var(--alerta-fondo);
  border-color: var(--alerta-borde);
}
.muestra__alerta {
  font-size: 11px;
  font-weight: 700;
  color: var(--alerta);
}

/* ----------------------------------------------------------------------
   El segmento de categoría: Taxi · Carro · Moto
   Son tres botones pegados y no un <select> porque hay que ver de un
   golpe CUÁL tarifa se está editando. El pulsado toma el color de su
   categoría —el mismo de la ficha en la cola— y no el morado: elegir
   qué se mira no es una acción.
   ---------------------------------------------------------------------- */
.segmento {
  display: inline-flex;
  flex: 0 0 auto;
  border: 1px solid var(--borde);
  border-radius: var(--radio);
  overflow: hidden;
  background: var(--tarjeta);
}
.segmento__boton {
  border: 0;
  border-right: 1px solid var(--borde);
  background: transparent;
  padding: 4px 14px;
  font-size: 12px;
  font-weight: 600;
  color: var(--tinta-media);
  cursor: pointer;
}
.segmento__boton:last-child { border-right: 0; }
.segmento__boton:hover { background: #f0f2f4; }
.segmento__boton[aria-pressed="true"] { color: var(--tinta); box-shadow: inset 0 -2px 0 currentColor; }
.segmento__boton[aria-pressed="true"][data-categoria="taxi"]       { background: var(--taxi-fondo);       color: var(--taxi); }
.segmento__boton[aria-pressed="true"][data-categoria="particular"] { background: var(--particular-fondo); color: var(--particular); }
.segmento__boton[aria-pressed="true"][data-categoria="moto"]       { background: var(--moto-fondo);       color: var(--moto); }

/* ======================================================================
   LAS MENSUALIDADES — el recaudo de la plataforma.

   No hay comisión por carrera: cada móvil paga una cuota fija al mes y
   la oficina la apunta aquí. La pantalla responde «¿quién falta?», así
   que el pendiente pesa más que el pagado en todo: en el color de la
   cifra, en la ficha de la fila y en que el botón de registrar solo
   sale donde hace falta.
   ====================================================================== */
.mensual__nav { display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto; }
.mensual__mes {
  min-width: 150px;
  text-align: center;
  font-size: 13px;
  font-weight: 700;
}
/* Atenuado mientras llega el mes pedido. La cabecera no cambia hasta
   que el servidor conteste (ver cargarMensualidades en admin.js), así
   que esto es lo que dice que el clic en la flecha entró. */
.mensual__mes[aria-busy="true"] { opacity: 0.45; }

/* Las tres cifras del mes. Pendientes en rojo solo cuando hay alguno:
   un cero en rojo permanente deja de mirarse. */
.mensual__resumen { display: flex; gap: 8px; flex-wrap: wrap; }
.mensual-cifra {
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 130px;
  padding: 6px 12px;
  border: 1px solid var(--borde-suave);
  border-radius: var(--radio);
  background: var(--tarjeta-alt);
}
.mensual-cifra__valor { font-size: 18px; font-weight: 800; line-height: 1.15; font-variant-numeric: tabular-nums; }
.mensual-cifra__nombre { font-size: 10px; text-transform: uppercase; letter-spacing: .4px; color: var(--tinta-tenue); }
.mensual-cifra--pagados .mensual-cifra__valor { color: var(--libre); }
.mensual-cifra--pendientes[data-hay="si"] { background: var(--alerta-fondo); border-color: var(--alerta-borde); }
.mensual-cifra--pendientes[data-hay="si"] .mensual-cifra__valor { color: var(--alerta); }

.tabla--mensual td { vertical-align: middle; }
.mensual__cuota { font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Cuándo, cómo y quién lo apuntó, en letra chica al lado de «Pagada»:
   es lo que se lee cuando el conductor dice «yo ya pagué». */
.mensual__detalle { font-size: 11px; color: var(--tinta-tenue); }
.mensual__accion { white-space: nowrap; text-align: right; }

/* El formulario de pago vive en un renglón pegado a la fila del móvil,
   con su número a la vista: es el dato que se equivoca cuando el pago
   se apunta en una ventana aparte con veinte móviles detrás. */
.mensual__forma-fila td {
  background: var(--acento-suave) !important;
  border-left: 3px solid var(--acento);
  padding: 8px 10px;
}
.mensual__forma {
  display: flex;
  align-items: flex-end;
  gap: 8px;
  flex-wrap: wrap;
}
.mensual__forma .campo--corto { flex: 0 0 150px; }
.mensual__forma .campo--crece { flex: 1 1 180px; }
.mensual__forma .forma__pie { flex: 0 0 auto; }
.mensual__forma .aviso { flex: 1 1 100%; }
.mensual__forma-quien { flex: 1 1 100%; font-size: 12px; font-weight: 600; color: var(--acento-fuerte); }


/* ------------------------------------------------------------------ */
/* La pestaña de lugares                                               */
/* ------------------------------------------------------------------ */
/* El alta va en UNA fila: nombre, dirección, punto y el botón. Quien
   carga lugares carga varios seguidos, y un formulario que hay que
   abrir y cerrar por cada uno convierte diez lugares en diez minutos. */
.lugar__alta {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 2fr) minmax(0, 1.2fr) auto;
  gap: 8px;
  margin: 10px 0 14px;
}
@media (max-width: 900px) {
  .lugar__alta { grid-template-columns: 1fr; }
}
/* Un lugar apagado se queda en la lista, gris: si desapareciera, quien
   lo apagó no tendría cómo volver a encenderlo. */
.fila--apagada td { opacity: 0.5; }


/* ------------------------------------------------------------------ */
/* El cuadro de rendimiento                                            */
/* ------------------------------------------------------------------ */
.rend__filtros {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 10px;
  margin: 10px 0 14px;
}
.rend__campo {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 0.85rem;
  color: var(--texto-apagado, #667);
}

/* Las fichas del resumen: lo que se mira de lejos antes de leer la
   tabla. La primera es la respuesta a la pregunta que trajo Gerencia. */
.rend__resumen {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 12px;
}
.rend__ficha {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 14px;
  border: 1px solid var(--borde, #d8d8e0);
  border-radius: 10px;
  min-width: 96px;
}
.rend__ficha span { font-size: 0.78rem; color: var(--texto-apagado, #667); }
.rend__ficha strong { font-size: 1.15rem; font-variant-numeric: tabular-nums; }

/* La tabla es ANCHA a propósito: un mes son treinta columnas de días.
   Se desplaza dentro de su caja en vez de encoger las columnas hasta
   que los números no se lean. */
.rend__tabla { overflow-x: auto; }
.tabla--rend { min-width: max-content; font-variant-numeric: tabular-nums; }
.tabla--rend th, .tabla--rend td { white-space: nowrap; }
.tabla--rend .num { text-align: right; }

/* La primera columna se queda quieta al desplazar: sin ella, a la mitad
   del mes uno ya no sabe de qué móvil es la fila que está leyendo. */
.rend__fija {
  position: sticky;
  left: 0;
  background: var(--superficie, #fff);
  z-index: 1;
}
.rend__dia { text-align: center; }
.rend__dia small { display: block; font-size: 0.68rem; font-weight: 400; opacity: 0.7; }
/* Terminadas por debajo de asignadas: el número que hay que mirar. */
.rend__menos { color: #C1271F; font-weight: 700; }
.rend__igual { color: #146C3A; font-weight: 700; }
.rend__nada { opacity: 0.35; }
/* El primero de la lista, que es el que más carreras terminó. */
.rend__mejor td { background: rgba(255, 196, 0, 0.10); }


/* ------------------------------------------------------------------ */
/* La hoja de renovar papeles                                          */
/* ------------------------------------------------------------------ */
/* Las tres fechas en fila: son tres y se cambian juntas cuando el carro
   vuelve de la revisión. En columna obligaban a desplazar una hoja de
   tres campos. */
.papeles__campos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 10px;
  margin: 12px 0;
}
/* Tres fechas en fila no caben en los 420 px del diálogo normal. */
#capa-papeles { width: 620px; }


/* ------------------------------------------------------------------ */
/* Lo que hace el agente en la bandeja                                  */
/* ------------------------------------------------------------------ */
/* Apagado: es contexto, no una alarma. El operador tiene que poder
   pasar la vista por encima de los chats que el agente lleva bien. */
.chat__agente {
  font-size: 11px;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--pausa-fondo);
  color: var(--tinta-tenue);
}
/* Salvo cuando levanta la mano. Ese sí es el que hay que abrir, y va
   con el rojo de alerta que la consola ya usa para «sin conductor». */
.chat__agente[data-ayuda="si"] {
  background: var(--alerta-fondo);
  color: var(--alerta);
  font-weight: 600;
}


/* ------------------------------------------------------------------ */
/* El dictamen del agente de papeles                                    */
/* ------------------------------------------------------------------ */
.solic-agente {
  margin: 10px 0;
  padding: 10px 12px;
  border: 1px solid var(--borde-suave);
  border-left: 4px solid var(--borde);
  border-radius: 8px;
  background: var(--tarjeta-alt);
  font-size: .9rem;
}
.solic-agente__cabeza { margin: 0 0 6px; }
/* El color dice de un vistazo si hay que abrir los papeles o no. Verde
   NO significa «apruebe»: significa que la máquina no vio nada raro. */
.solic-agente--sin_reparos { border-left-color: var(--libre); }
.solic-agente--revisar     { border-left-color: var(--oferta); }
.solic-agente--devolver    { border-left-color: var(--alerta); background: var(--alerta-fondo); }
.solic-agente--yendo       { border-left-color: var(--ocupado); color: var(--tinta-media); }
.solic-agente__alertas { margin: 6px 0 8px; padding-left: 18px; }
.solic-agente__alertas li { margin-bottom: 4px; line-height: 1.4; }
.solic-agente__detalle { margin-bottom: 8px; }
.solic-agente__detalle summary { cursor: pointer; color: var(--tinta-media); }
.solic-agente__detalle p { margin: 4px 0; color: var(--tinta-media); }
