/* =================================================================
 * The Carriers — sistema de diseño de la aplicación
 *
 * Los tokens son los mismos del sitio público, sin excepción: la página
 * blanca, navy-50 para lo hundido, el verde de marca y la Inter
 * self-hosted. Quien entra desde la landing no debe notar que cambió de
 * sitio.
 *
 * Contrastes ya medidos y que no hay que bajar:
 *   muted  #5a6780  5.5:1 sobre blanco, 5.2:1 sobre navy-50
 *   accent #0f9d6e  3.3:1 sobre blanco: NO sirve como texto. Para leerlo
 *                   va --enlace, y como relleno de botón --accent-solido
 *                   con texto blanco encima (4.7:1)
 *   field  rgba(18,28,51,.45)  cumple el 3:1 de 1.4.11 para bordes de
 *                              control, hairline NO
 * ================================================================= */

@font-face {
  font-family: Inter;
  src: url("fonts/InterVariable.woff2") format("woff2");
  font-weight: 100 900;
  font-display: swap;
}

:root {
  /* ---------------------------------------------------------------
   * Identidad. Los mismos valores que el sitio público, sin excepción.
   * ------------------------------------------------------------- */
  --navy: #1b2a4a;
  --navy-900: #121c33;
  --navy-700: #2b3a67;
  --navy-50: #f4f5f9;
  --accent: #0f9d6e;
  --accent-600: #0b7f58;

  /* ---------------------------------------------------------------
   * Papeles: qué hace cada color, no cuál es.
   *
   * La escalera de superficies va al revés que en oscuro. Allí subían
   * desde el fondo —abyss, navy-900, navy—; aquí no hay nada más claro
   * que el blanco, así que la tarjeta se separa de la página con una
   * sombra y lo que va DENTRO de ella baja a navy-50.
   * ------------------------------------------------------------- */
  --pagina: #ffffff;         /* contenido, barra superior, panel */
  --tarjeta: #ffffff;        /* una tarjeta; la separa la sombra */
  --hundido: var(--navy-50); /* pieza dentro de una tarjeta, y la barra lateral */
  --hundido-fuerte: #e7eaf1;/* su estado activo o pulsado */
  --hover: var(--navy-50);

  --ink: #16233d;
  --muted: #5a6780;
  --hairline: rgba(18, 28, 51, 0.12);
  --hairline-fuerte: rgba(18, 28, 51, 0.22);
  --field: rgba(18, 28, 51, 0.45);

  /* El trazo de los diagramas: la línea por la que corre el pulso verde.
     Escrito a mano era blanco al 14% y sobre blanco no existe. */
  --trazo: rgba(18, 28, 51, 0.22);
  --trazo-fuerte: rgba(18, 28, 51, 0.26);

  /* El verde de marca da 3.3:1 sobre blanco y no sirve como texto: para
     leerlo hace falta un paso más oscuro, y como relleno de botón lleva
     texto blanco encima. El verde intacto se queda para trazos y puntos,
     donde basta 3:1. */
  --enlace: #0a7350;
  --accent-solido: var(--accent-600);
  --sobre-accent: #ffffff;

  /* Superficie de marca: lo que está señalado como nuestro. Es el mismo papel
     que en el sitio público, donde viste el nodo del diagrama y la ficha
     elegida. Aquí no existía, así que todo lo seleccionado se vestía de gris y
     la aplicación salía apagada al lado de su propia portada. */
  --destacado: rgba(15, 157, 110, 0.1);
  --destacado-fuerte: rgba(15, 157, 110, 0.16);
  --destacado-borde: rgba(15, 157, 110, 0.32);
  --destacado-borde-fuerte: rgba(15, 157, 110, 0.5);
  /* Más claro que `--destacado` a propósito: es el lavado de una franja que
     afirma un resultado, y al peso de una pastilla se leería como un estado
     que exige algo. */
  --destacado-tenue: rgba(15, 157, 110, 0.07);

  /* Estados. */
  --mal: #b42318;
  --mal-fondo: rgba(248, 113, 113, 0.14);
  --mal-borde: rgba(220, 38, 38, 0.35);
  --aviso: #92610a;
  --aviso-fondo: rgba(251, 191, 36, 0.18);
  --aviso-borde: rgba(217, 119, 6, 0.35);

  --sombra-tarjeta: 0 1px 2px rgba(18, 28, 51, 0.04),
                    0 12px 32px -20px rgba(18, 28, 51, 0.14);
  --sombra-tarjeta-hover: 0 1px 2px rgba(18, 28, 51, 0.05),
                          0 22px 48px -24px rgba(18, 28, 51, 0.2);

  /* Lo que va marcado como nuestro se levanta con una sombra tibiamente verde,
     no con un halo: sobre blanco un brillo de color se lee como un error de
     impresión. La misma lección que el sitio público ya había aprendido para
     el hover de sus tarjetas. */
  --sombra-destacado: 0 1px 2px rgba(18, 28, 51, 0.05),
                      0 18px 44px -26px rgba(15, 157, 110, 0.45);

  --lateral: 236px;
  --superior: 60px;

  --r-sm: 6px;
  --r: 10px;
  --r-lg: 14px;

  --sombra: 0 30px 70px -40px rgba(18, 28, 51, 0.35);
  --curva: cubic-bezier(0.16, 1, 0.3, 1);

  color-scheme: light;
}

*,
*::before,
*::after { box-sizing: border-box; }

html, body { max-width: 100%; overflow-x: clip; }

/* El hueco de la barra se reserva siempre: si no, bloquear el scroll al abrir
   un panel hace saltar toda la página unos píxeles. */
html { scrollbar-gutter: stable; }

/* Con un panel abierto, la página de atrás no scrollea ni muestra su barra.
   Tres barras a la derecha —la de la página, la del diálogo y la del cuerpo—
   era exactamente eso: tres capas que podían moverse a la vez. */
html:has(dialog[open]) { overflow: hidden; }

body {
  margin: 0;
  background: var(--pagina);
  color: var(--ink);
  font-family: Inter, ui-sans-serif, system-ui, sans-serif;
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 { margin: 0; font-weight: 600; letter-spacing: -0.015em; }
p { margin: 0; }
a { color: inherit; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}

::placeholder { color: var(--muted); opacity: 1; }

/* Varios componentes declaran display:flex o grid, y eso le gana al atributo
   hidden. Sin esta regla, los avisos de error se ven siempre, vacíos. */
[hidden] { display: none !important; }
.tabular { font-variant-numeric: tabular-nums; }
.nowrap { white-space: nowrap; }

/* `apagado` y `mono` solo estaban definidos dentro de una celda de tabla, y
   las pantallas los usan en todas partes. Fuera de una tabla, el texto
   secundario salía del color del cuerpo —y entonces no era secundario— y un
   número de guía salía en la misma tipografía que la prosa, donde el uno y la
   ele se confunden. Distinguirlos es la única razón por la que una guía se
   escribe en monoespaciado. */
.apagado { color: var(--muted); }
.mono { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; }

.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;
}

/* Barras de scroll internas a tono. */
.scroll-fino { scrollbar-width: thin; scrollbar-color: var(--hairline-fuerte) transparent; }
.scroll-fino::-webkit-scrollbar { width: 9px; height: 9px; }
.scroll-fino::-webkit-scrollbar-thumb { background: var(--hairline-fuerte); border-radius: 999px; }

/* -----------------------------------------------------------------
 * Armazón: barra lateral fija + columna de contenido
 * --------------------------------------------------------------- */
.armazon { display: grid; grid-template-columns: var(--lateral) minmax(0, 1fr); min-height: 100vh; }

/* La barra se hunde y el contenido se queda en blanco: con las dos del mismo
   color, la pantalla entera era un solo plano y la navegación perdía su sitio.
   En oscuro esa separación la daba el navy-900 sobre el abyss. */
.lateral {
  position: sticky; top: 0; height: 100vh;
  display: flex; flex-direction: column; gap: 4px;
  padding: 16px 12px;
  border-right: 1px solid var(--hairline);
  background: var(--hundido);
}
.lateral__marca { display: flex; align-items: center; padding: 8px 10px 18px; }
.lateral__marca img { height: 22px; width: auto; }
.lateral__grupo {
  padding: 16px 10px 6px; font-size: 10px; font-weight: 600;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted);
}

.nav-item {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px; border-radius: var(--r);
  color: var(--muted); text-decoration: none; font-weight: 500;
  transition: background-color .2s var(--curva), color .2s var(--curva);
}
.nav-item:hover { background: var(--hover); color: var(--ink); }
.nav-item[aria-current="page"] { background: var(--destacado); color: var(--enlace); font-weight: 600; }
.nav-item[aria-current="page"] svg { color: var(--accent); }
.nav-item svg { width: 17px; height: 17px; flex: none; }
.nav-item__cuenta {
  margin-left: auto; font-size: 11px; font-weight: 600;
  padding: 1px 7px; border-radius: 999px;
  background: var(--mal-fondo); color: var(--mal);
}


/* -----------------------------------------------------------------
 * Barra superior
 * --------------------------------------------------------------- */
.superior {
  position: sticky; top: 0; z-index: 20;
  display: flex; align-items: center; gap: 14px;
  height: var(--superior); padding: 0 24px;
  border-bottom: 1px solid var(--hairline);
  background: rgba(255, 255, 255, 0.85);
  backdrop-filter: blur(10px);
}
.superior__empresa {
  display: flex; align-items: center; gap: 9px;
  padding: 6px 11px 6px 8px; border: 1px solid var(--hairline);
  border-radius: var(--r); background: var(--tarjeta);
  font-weight: 500; cursor: pointer;
}
.superior__empresa:hover { border-color: var(--hairline-fuerte); }
.avatar {
  display: grid; place-items: center; width: 26px; height: 26px; flex: none;
  border-radius: 7px; background: var(--hundido-fuerte); color: var(--ink);
  font-size: 11px; font-weight: 600;
}
.buscador { position: relative; flex: 1; max-width: 420px; }

/* Dentro de una barra de filtros el buscador se queda con el ancho que
   sobra: los atajos y las fechas ocupan lo suyo y él el resto. Con el tope
   de 420px quedaba un buscador diminuto y un hueco muerto a la derecha. */
.filtros .buscador { flex: 1 1 260px; max-width: none; }
.buscador svg {
  position: absolute; left: 11px; top: 50%; transform: translateY(-50%);
  width: 15px; height: 15px; color: var(--muted); pointer-events: none;
}
.buscador input { padding-left: 34px; }

/* Los datos son inventados y hay que decirlo donde siempre se vea. */
.insignia-demo {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 5px 11px; border-radius: 999px;
  border: 1px solid var(--aviso-borde); background: var(--aviso-fondo);
  color: var(--aviso); font-size: 12px; font-weight: 500; white-space: nowrap;
}

/* -----------------------------------------------------------------
 * Contenido
 * --------------------------------------------------------------- */
.contenido { padding: 28px 24px 56px; }
.contenido--ancho { max-width: 1600px; }

.encabezado {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 20px; flex-wrap: wrap; margin-bottom: 22px;
}
.encabezado h1 { font-size: 24px; }
.encabezado p { margin-top: 5px; color: var(--muted); max-width: 68ch; }
.encabezado__acciones { display: flex; gap: 9px; flex-wrap: wrap; }

.tarjeta {
  border: 1px solid var(--hairline); border-radius: var(--r-lg);
  background: var(--tarjeta); box-shadow: var(--sombra-tarjeta); overflow: hidden;
}
.tarjeta__cabeza {
  display: flex; align-items: center; justify-content: space-between;
  gap: 14px; flex-wrap: wrap;
  padding: 14px 18px; border-bottom: 1px solid var(--hairline);
}
.tarjeta__cabeza h2 { font-size: 15px; }
.tarjeta__cuerpo { padding: 18px; }
.tarjeta__pie {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; flex-wrap: wrap;
  padding: 11px 18px; border-top: 1px solid var(--hairline);
  color: var(--muted); font-size: 12px;
}

.rejilla { display: grid; gap: 14px; }
.rejilla--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.rejilla--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.rejilla--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

/* -----------------------------------------------------------------
 * Controles
 * --------------------------------------------------------------- */
/* Se seleccionan POR EXCLUSIÓN, no enumerando tipos.
 *
 * Un <input> sin atributo `type` se comporta como texto, pero NO lo empareja
 * el selector `input[type="text"]`: el atributo no está en el DOM. Con la lista
 * de tipos, la mitad de un formulario salía con el estilo gris del navegador
 * —Arial 13.3px, 21.5px de alto, borde de 2px— mientras el campo de al lado,
 * que sí declaraba type="email", se veía bien. Así no hay forma de olvidarlo.
 */
input:not([type="checkbox"], [type="radio"], [type="range"], [type="file"],
           [type="color"], [type="submit"], [type="button"], [type="reset"], [type="image"]),
select,
textarea {
  width: 100%; padding: 8px 11px;
  border: 1px solid var(--field); border-radius: var(--r);
  background: var(--hundido); color: var(--ink);
  font: inherit; transition: border-color .2s var(--curva);
}
input:not([type="checkbox"], [type="radio"]):hover,
select:hover,
textarea:hover { border-color: var(--hairline-fuerte); }
select { cursor: pointer; }

/* ---------- Fecha y hora ----------
   El panel del calendario lo dibuja el navegador y no se puede estilar. Lo
   que sí es nuestro es el campo: su icono, los segmentos, el separador y el
   resalte del foco. Sin tocarlos, un `input[type=date]` mete en la interfaz
   un icono azul de sistema y una tipografía que no es la nuestra.

   Se usa `mask` y no `background-image` a propósito: así el icono toma el
   color de una variable y puede cambiar al pasar por encima. Con una imagen
   incrustada el color quedaría fijo dentro del SVG. */
input[type="date"], input[type="time"] {
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}

/* El de fecha se apaga del todo: abre el panel del navegador, que es el que
   no se puede vestir. En su lugar va `.campo-fecha__abrir`, que abre el
   nuestro. El de hora se queda: un selector de horas es otro componente y
   todavía no lo tenemos. */
input[type="date"]::-webkit-calendar-picker-indicator { display: none; }

input[type="time"]::-webkit-calendar-picker-indicator {
  width: 16px; height: 16px; padding: 0; margin-left: 4px;
  background: var(--muted);
  cursor: pointer;
  transition: background-color .16s var(--curva);
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
  -webkit-mask-size: 16px 16px; mask-size: 16px 16px;
}

input[type="time"]::-webkit-calendar-picker-indicator {
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v5.5l3.5 2'/%3E%3C/svg%3E");
  mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.8' stroke-linecap='round'%3E%3Ccircle cx='12' cy='12' r='9'/%3E%3Cpath d='M12 7v5.5l3.5 2'/%3E%3C/svg%3E");
}

input[type="time"]:hover::-webkit-calendar-picker-indicator,
input[type="time"]:focus-within::-webkit-calendar-picker-indicator { background: var(--ink); }

/* ---------- Campo de fecha con su botón ---------- */
.campo-fecha { position: relative; display: inline-flex; flex: 0 0 auto; max-width: 100%; }

/* Un rango es una sola cosa: se parte entero o no se parte. */
.rango-fechas { display: flex; align-items: center; gap: 8px; }
/* Dentro de un formulario sí ocupa la celda entera, como cualquier campo. */
.campo .campo-fecha { width: 100%; }
.campo .campo-fecha input { width: 100%; }
.campo-fecha input { padding-right: 34px; }
.campo-fecha__abrir {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  display: grid; place-items: center; width: 26px; height: 26px;
  padding: 0; border: 0; border-radius: var(--r-sm);
  background: transparent; color: var(--muted); cursor: pointer;
  transition: color .16s var(--curva), background .16s var(--curva);
}
.campo-fecha__abrir svg { width: 16px; height: 16px; }
.campo-fecha__abrir:hover { color: var(--ink); background: var(--hover); }

/* ---------- El calendario ----------
   Va en `body` y con posición fija: `.tarjeta` recorta lo que se sale, y
   dentro de una barra de filtros se cortaría por la mitad. */
.calendario {
  position: fixed; z-index: 60; width: 280px; padding: 12px;
  border: 1px solid var(--hairline-fuerte); border-radius: var(--r-lg);
  background: var(--hundido); box-shadow: var(--sombra);
}
.calendario__cabeza {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  margin-bottom: 10px;
}
.calendario__cabeza b { font-size: 14px; }
.calendario__mover {
  display: grid; place-items: center; width: 28px; height: 28px;
  border: 1px solid var(--hairline); border-radius: var(--r-sm);
  background: transparent; color: var(--muted); font-size: 15px; cursor: pointer;
  transition: all .16s var(--curva);
}
.calendario__mover:hover { border-color: var(--hairline-fuerte); color: var(--ink); }

.calendario__semana, .calendario__dias {
  display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px;
}
.calendario__semana span {
  padding: 4px 0; text-align: center; color: var(--muted);
  font-size: 11px; font-weight: 600;
}
.calendario__dia {
  aspect-ratio: 1; padding: 0; border: 1px solid transparent; border-radius: var(--r-sm);
  background: transparent; color: var(--ink); font: inherit; font-size: 13px;
  font-variant-numeric: tabular-nums; cursor: pointer;
  transition: background .12s var(--curva), color .12s var(--curva);
}
.calendario__dia:hover { background: var(--hover); }
/* Hoy se marca con el borde; el elegido, con el relleno. Así se distinguen
   cuando son el mismo día. */
.calendario__dia--hoy { border-color: var(--field); }
.calendario__dia--elegido {
  background: var(--accent-solido); color: var(--sobre-accent); font-weight: 600;
}
.calendario__dia--elegido:hover { background: var(--accent); filter: brightness(1.1); }

.calendario__pie {
  display: flex; gap: 8px; margin-top: 10px; padding-top: 10px;
  border-top: 1px solid var(--hairline);
}
.calendario__pie .boton { flex: 1; justify-content: center; }

@media (prefers-reduced-motion: reduce) {
  .calendario__dia, .calendario__mover, .campo-fecha__abrir { transition: none; }
}

/* Las barras entre día, mes y año son separadores, no datos. */
::-webkit-datetime-edit-text { color: var(--muted); padding: 0 1px; }
::-webkit-datetime-edit-fields-wrapper { padding: 0; }

/* Un campo vacío dice "dd/mm/aaaa": es un marcador, no un valor, y a plena
   intensidad compite con los datos de al lado. `data-lleno` lo pone el
   armazón al cargar y en cada cambio. */
input[type="date"]:not([data-lleno])::-webkit-datetime-edit,
input[type="time"]:not([data-lleno])::-webkit-datetime-edit { color: var(--muted); }

/* El segmento que se está editando, con el acento de la casa en vez del azul
   del sistema. Texto oscuro encima, que sobre el acento da 5.3:1. */
::-webkit-datetime-edit-day-field:focus,
::-webkit-datetime-edit-month-field:focus,
::-webkit-datetime-edit-year-field:focus,
::-webkit-datetime-edit-hour-field:focus,
::-webkit-datetime-edit-minute-field:focus,
::-webkit-datetime-edit-ampm-field:focus {
  background: var(--accent-solido); color: var(--sobre-accent);
  border-radius: 3px; outline: none;
}

@media (prefers-reduced-motion: reduce) {
  input[type="date"]::-webkit-calendar-picker-indicator,
  input[type="time"]::-webkit-calendar-picker-indicator { transition: none; }
}
select option { background: var(--pagina); }

/* La columna es minmax(0, 1fr) y no `auto`: un <select> se mide por su opción
   más larga, y con la columna en auto "Caja mediana — 40 × 30 × 25 cm" estiraba
   el campo hasta 524px dentro de un panel de 390. El campo crecía, la caja que
   lo contiene crecía, y aparecía una barra horizontal dentro del panel. */
.campo { display: grid; gap: 6px; grid-template-columns: minmax(0, 1fr); }
.campo > span { font-weight: 500; }
.campo__ayuda { color: var(--muted); font-size: 12px; }

.boton {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 8px 15px; border-radius: var(--r); border: 1px solid transparent;
  /* Sin esto, un <button> hereda el gris claro del navegador (buttonface) y
     .boton--sutil queda con texto tenue sobre fondo claro: 2.17:1. */
  background: transparent; color: inherit;
  font: inherit; font-weight: 600; text-decoration: none; cursor: pointer;
  white-space: nowrap; transition: filter .2s var(--curva),
    background-color .2s var(--curva), border-color .2s var(--curva);
}
.boton svg { width: 16px; height: 16px; }
/* Texto abyss sobre el verde: blanco encima da 3.46:1 y reprueba. El hover
   ACLARA, porque oscurecer dejaría el texto oscuro sin contraste. */
.boton--primario { background: var(--accent-solido); color: var(--sobre-accent); }
.boton--primario:hover { filter: brightness(1.1); }
.boton--fantasma { border-color: var(--hairline-fuerte); background: var(--hundido); color: var(--ink); }
.boton--fantasma:hover { border-color: var(--destacado-borde-fuerte); background: var(--hundido-fuerte); }
.boton--sutil { color: var(--muted); }
.boton--sutil:hover { background: var(--hover); color: var(--ink); }
.boton--bloque { width: 100%; }
.boton[disabled] { opacity: .55; cursor: not-allowed; filter: none; }

.filtros {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  padding: 13px 18px; border-bottom: 1px solid var(--hairline);
}
.filtros select, .filtros input { width: auto; min-width: 150px; }
.filtros .buscador input { width: 100%; }
.filtros__sep { flex: 1; }
/* Separador entre grupos de filtros: agrupa visualmente lo que se combina. */
.filtros__div { width: 1px; align-self: stretch; background: var(--hairline); margin: 0 3px; }
.filtros__etiqueta { color: var(--muted); font-size: 12px; white-space: nowrap; }
.filtros input[type="date"] { min-width: 0; width: 138px; padding: 5px 9px; font-size: 13px; }
.filtros select { padding: 5px 9px; font-size: 13px; }

/* ---------- El panel de filtros ----------
   Lo que no es el caso normal vive aquí dentro, colgado del único control cuyo
   ancho no cambia con lo que haya seleccionado. Dentro se comporta como un
   formulario y no como una barra: los campos ocupan el ancho del panel, que es
   justo lo que `.filtros` les quita fuera. */
/* El ancho lo pone `.colgante__panel`: un panel flotante que mide distinto
   según de qué cuelgue son dos paneles. */
.filtros__panel .campos { padding: 14px; gap: 12px; }
.filtros__panel .campo { gap: 6px; }
.filtros__panel select,
.filtros__panel input[type="date"] { width: 100%; min-width: 0; }
/* El campo de fecha va envuelto en `.campo-fecha` —se lo pone `app.js` para
   colgarle su botón de calendario—, así que es ese envoltorio el que tiene que
   encoger: repartir el ancho entre los `input` deja los dos a ancho completo y
   el segundo se sale del panel. */
.filtros__panel .rango-fechas .campo-fecha { flex: 1 1 0; min-width: 0; }
.filtros__panel .rango-fechas input { width: 100%; }
/* El quitar de cada campo, pegado a su derecha: centrado bajo el control se
   lee como una acción del panel y no de ese filtro. */
.filtros__panel .campo > .boton { justify-self: end; }
.filtros__panel .marca-campo { margin-top: 2px; }
/* El mismo "Quitar filtros" que está fuera, al alcance de quien ya abrió el
   panel para mirarlos: ahí es donde se decide quitarlos. */
.filtros__panel-pie {
  display: flex; justify-content: flex-end;
  padding: 10px 14px; border-top: 1px solid var(--hairline);
}

.ficha-filtro {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 5px 11px; border: 1px solid var(--hairline); border-radius: 999px;
  background: transparent; color: var(--muted); font: inherit; font-size: 12px;
  cursor: pointer; transition: all .2s var(--curva);
}
.ficha-filtro:hover { border-color: var(--hairline-fuerte); color: var(--ink); }
.ficha-filtro[aria-pressed="true"] {
  border-color: var(--destacado-borde-fuerte); background: var(--destacado-fuerte); color: var(--enlace);
}
/* La cuenta dentro de la ficha dice si vale la pena pulsarla antes de
   pulsarla. Vacía no ocupa nada, y en cero la ficha se apaga y deja de ser
   pulsable: un atajo que no lleva a ningún sitio es una promesa rota. */
.ficha-filtro__cuenta:not(:empty) {
  display: inline-block; margin-left: 2px;
  padding: 0 5px; border-radius: 999px;
  background: var(--destacado); color: var(--enlace);
  font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.ficha-filtro[aria-pressed="true"] .ficha-filtro__cuenta:not(:empty) {
  background: var(--tarjeta);
}
.ficha-filtro:disabled {
  opacity: .5; cursor: default; border-color: var(--hairline);
}
.ficha-filtro:disabled:hover { border-color: var(--hairline); color: var(--muted); }

/* Ficha que se quita: la pone la franja al enfocar un pendiente. Sin ella la
   lista se queda corta y nada en pantalla dice por qué. */
.ficha-filtro--quitable span { opacity: .7; font-size: 13px; line-height: 1; }
.ficha-filtro--quitable:hover span { opacity: 1; }

/* -----------------------------------------------------------------
 * Tabla
 * --------------------------------------------------------------- */
/* `position: relative` no es decorativo: sin él, los hijos con
   `position: absolute` —los rótulos `.sr-only` de las últimas columnas— se
   miden contra un antepasado que está FUERA de la caja, así que el
   `overflow-x` no los recorta y empujan el ancho de la página entera. Una
   tabla ancha hacía que se desplazara toda la pantalla y no solo la tabla. */
.tabla-caja { position: relative; overflow-x: auto; }
table { width: 100%; border-collapse: collapse; text-align: left; }
/* top:0, no la altura de la barra superior. `.tabla-caja` lleva overflow-x:auto,
   y eso convierte la caja en contenedor de scroll: el sticky se mide contra ella,
   no contra la página, así que un top de 60px bajaba el encabezado 60px y lo
   montaba encima de la primera fila. */
thead th {
  position: sticky; top: 0; z-index: 5;
  padding: 9px 16px; background: var(--hundido);
  border-bottom: 1px solid var(--hairline);
  font-size: 11px; font-weight: 500; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--muted); white-space: nowrap;
}
tbody td,
tbody th { padding: 11px 16px; border-bottom: 1px solid var(--hairline); }
tbody tr:last-child td,
tbody tr:last-child th { border-bottom: 0; }
tbody tr { transition: background-color .15s var(--curva); }
tbody tr:hover { background: var(--hover); }
tbody tr[data-href] { cursor: pointer; }
td .apagado { color: var(--muted); }
td .mono { font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: 12.5px; }

/* El reparto automático mide cada columna por su contenido más largo, y con
   una columna más en la tabla de Pedidos el destino se quedaba en 139px: la
   calle salía en cuatro renglones de una palabra y la fila pasaba de 83 a
   122px. En la pantalla donde se trabaja todo el día eso son cuatro filas
   menos por pantallazo. El destino pide lo que mide una calle con su número;
   el ancho lo cede el cliente, cuyo correo ya se recorta con puntos
   suspensivos. Van aquí y no en un `style=` de la fila: en línea, la consulta
   de medios no los puede corregir. */
.celda-cliente { max-width: 150px; }
.celda-destino { min-width: 180px; max-width: 260px; }

/* -----------------------------------------------------------------
 * Pastillas de estado
 * --------------------------------------------------------------- */
.pastilla {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 2px 9px; border-radius: var(--r-sm); border: 1px solid;
  font-size: 12px; font-weight: 500; white-space: nowrap;
}
.pastilla--info { border-color: var(--hairline-fuerte); background: var(--hundido-fuerte); color: var(--ink); }
.pastilla--ok   { border-color: var(--destacado-borde-fuerte); background: var(--destacado); color: var(--enlace); }
.pastilla--mal  { border-color: var(--mal-borde); background: var(--mal-fondo); color: var(--mal); }
.pastilla--aviso{ border-color: var(--aviso-borde); background: var(--aviso-fondo); color: var(--aviso); }
.pastilla--neutra { border-color: var(--hairline); background: var(--hundido); color: var(--muted); }

/* -----------------------------------------------------------------
 * Métricas
 * --------------------------------------------------------------- */
.metrica { padding: 16px 18px; border: 1px solid var(--hairline); border-radius: var(--r-lg); background: var(--tarjeta); box-shadow: var(--sombra-tarjeta); }
.metrica__etiqueta { color: var(--muted); font-size: 12px; }
.metrica__valor { margin-top: 7px; font-size: 27px; font-weight: 600; letter-spacing: -0.02em; }
.metrica__nota { margin-top: 5px; font-size: 12px; color: var(--muted); }

/* -----------------------------------------------------------------
 * Estado vacío
 * --------------------------------------------------------------- */
.vacio { padding: 56px 24px; text-align: center; }
.vacio__icono {
  display: grid; place-items: center; width: 46px; height: 46px; margin: 0 auto 16px;
  border-radius: var(--r-lg); border: 1px solid var(--destacado-borde);
  background: var(--destacado); color: var(--enlace);
}
.vacio h3 { font-size: 16px; }
.vacio p { margin: 8px auto 0; max-width: 46ch; color: var(--muted); }
.vacio__acciones { margin-top: 20px; display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }

/* -----------------------------------------------------------------
 * Línea de tiempo
 * --------------------------------------------------------------- */
.linea { display: grid; gap: 0; }
.linea__evento { position: relative; display: grid; grid-template-columns: 22px 1fr; gap: 14px; padding-bottom: 20px; }
.linea__evento:last-child { padding-bottom: 0; }
.linea__evento::before {
  content: ""; position: absolute; left: 10px; top: 20px; bottom: 0; width: 1px;
  background: var(--hundido-fuerte);
}
.linea__evento:last-child::before { display: none; }
.linea__punto {
  width: 21px; height: 21px; border-radius: 999px; display: grid; place-items: center;
  border: 1px solid var(--hairline); background: var(--tarjeta); position: relative; z-index: 1;
}
.linea__punto i { width: 7px; height: 7px; border-radius: 999px; background: var(--muted); }
.linea__evento--activo .linea__punto { border-color: var(--destacado-borde-fuerte); background: var(--destacado-fuerte); }
.linea__evento--activo .linea__punto i { background: var(--accent); }
.linea__evento--mal .linea__punto { border-color: var(--mal-borde); background: var(--mal-fondo); }
.linea__evento--mal .linea__punto i { background: var(--mal); }
.linea__cuando { color: var(--muted); font-size: 12px; margin-top: 3px; }
.linea__original {
  margin-top: 7px; padding: 7px 10px; border-radius: var(--r-sm);
  background: var(--hundido); border: 1px solid var(--hairline);
  font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 12px; color: var(--muted);
}

/* -----------------------------------------------------------------
 * Definiciones (detalle de envío)
 * --------------------------------------------------------------- */
.definiciones { display: grid; gap: 13px; }
.definiciones > div { display: grid; grid-template-columns: 128px 1fr; gap: 14px; align-items: baseline; }
.definiciones dt { color: var(--muted); font-size: 13px; }
.definiciones dd { margin: 0; }

/* -----------------------------------------------------------------
 * Gráfica de barras (SVG inline, sin librerías)
 * --------------------------------------------------------------- */
.barras { display: grid; gap: 13px; }
.barras__fila { display: grid; grid-template-columns: 112px 1fr 56px; gap: 14px; align-items: center; }
/* display:block a fuerza: son <span>, y en un elemento en línea no aplican
   ni width ni height, así que la barra se pintaba siempre del mismo largo. */
.barras__pista {
  display: block; height: 9px; border-radius: 999px;
  background: var(--hundido); overflow: hidden;
}
.barras__valor {
  display: block; height: 100%; border-radius: 999px; background: var(--accent);
  transition: width .5s var(--curva);
}
.barras__valor--aviso { background: var(--aviso); }
.barras__valor--mal { background: var(--mal); }
.barras__num { text-align: right; color: var(--muted); font-size: 13px; }

/* -----------------------------------------------------------------
 * Autenticación
 * --------------------------------------------------------------- */
.auth { display: grid; grid-template-columns: 1.05fr 1fr; min-height: 100vh; }
.auth__arte {
  position: relative; overflow: hidden; padding: 48px;
  display: flex;
  border-right: 1px solid var(--hairline); background: var(--hundido);
}

/* El contenido va en un bloque de ancho acotado y centrado dentro del panel.
   Sin esto, en una pantalla ancha el panel llega a 1300px y todo se queda
   pegado al borde izquierdo con medio metro de vacío a la derecha.
   Y NO se usa align-items:flex-start en el panel: eso encoge a cada hijo a su
   ancho natural, comprime el diagrama y le corta el texto a las fichas. */
.auth__panel {
  position: relative; z-index: 1;
  width: 100%; max-width: 560px; margin-inline: auto;
  display: flex; flex-direction: column; justify-content: center; gap: 34px;
}
.auth__panel > img { align-self: flex-start; } /* si no, se estira a todo el ancho */
.auth__brillo {
  position: absolute; inset: -30% -20% auto -20%; height: 760px; pointer-events: none;
  background: radial-gradient(52% 58% at 50% 0%, rgba(27, 42, 74, 0.07), transparent 72%);
}
/* El verde detrás del contenido, no encima de él: flotando arriba se leía
   como una mancha en un sitio donde no hay nada. */
.auth__brillo--verde {
  inset: 24% -10% auto -10%; height: 520px;
  background: radial-gradient(38% 52% at 50% 0%, var(--destacado-fuerte), transparent 70%);
}
.auth__contenido { position: relative; }
.auth__contenido h2 { font-size: 30px; line-height: 1.15; max-width: 16ch; }
.auth__contenido p { margin-top: 14px; color: var(--muted); max-width: 44ch; }
.auth__formulario { display: grid; align-content: center; justify-items: stretch; padding: 48px; }
.auth__caja { width: 100%; max-width: 372px; margin: 0 auto; display: grid; gap: 16px; }
.auth__caja h1 { font-size: 23px; }
.auth__pie { color: var(--muted); font-size: 13px; text-align: center; }
.auth__lema { color: var(--muted); font-size: 13px; margin-top: 8px; }
.auth__pie a { color: var(--enlace); }

.aviso {
  display: flex; gap: 10px; padding: 10px 13px; border-radius: var(--r);
  border: 1px solid; font-size: 13px;
}
/* `.aviso` es flex para poner un icono junto a una línea de texto. En cuanto
   lleva título, lista y explicación, esos hijos se vuelven columnas y el texto
   queda en tiras verticales. Con contenido estructurado, se apila. */
.aviso--bloque { display: block; }
.aviso--bloque > b { display: block; }
.aviso--bloque > p { margin-top: 9px; }
.aviso--info { border-color: var(--hairline); background: var(--hundido); color: var(--muted); }
.aviso--mal { border-color: var(--mal-borde); background: var(--mal-fondo); color: var(--mal); }
.aviso--ok { border-color: var(--destacado-borde); background: var(--destacado); color: var(--enlace); }
/* Ni error ni dato suelto: algo que sí se puede hacer y conviene mirar antes.
   Medido sobre la tarjeta: 8.9:1. */
.aviso--alerta { border-color: var(--aviso-borde); background: var(--aviso-fondo); color: var(--aviso); }

/* -----------------------------------------------------------------
 * Diagrama de convergencia, en miniatura.
 * El mismo lenguaje del sitio: muchos canales, una plataforma, muchas fichas.
 * --------------------------------------------------------------- */
/* El ancho y el margen viven aquí, no en un style= en el HTML: si están
   en línea, la consulta de medios no los puede corregir. */
.mini-red {
  display: flex; align-items: center; justify-content: center; gap: 0;
  max-width: 560px; margin-top: 28px;
}
.mini-red__col { display: grid; gap: 7px; flex: 1; min-width: 0; }
/* Alto fijo y sin saltos de línea: el SVG de los cables asume tres fichas de
   36 con 7 de hueco (4*36 + 3*7 = 165). Si "Mercado Libre" parte en dos
   líneas, la columna crece y los cables dejan de apuntar al centro de cada
   ficha. */
.mini-red__ficha {
  display: flex; align-items: center; gap: 8px; padding: 0 10px; height: 36px; min-width: 0;
  border: 1px solid var(--hairline); border-radius: var(--r); background: var(--hundido);
  font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mini-red__sigla {
  display: grid; place-items: center; width: 22px; height: 22px; flex: none;
  border: 1px solid var(--hairline); border-radius: var(--r-sm);
  background: var(--hundido); color: var(--muted);
  font-family: ui-monospace, Menlo, monospace; font-size: 10px;
}
.mini-red__nodo {
  flex: none; margin: 0 2px; display: grid; place-items: center; gap: 7px; padding: 14px 12px;
  border: 1px solid var(--destacado-borde); border-radius: var(--r-lg);
  background: var(--destacado); text-align: center;
  box-shadow: var(--sombra-destacado);
}
.mini-red__nodo img { width: 26px; height: 26px; }
.mini-red__nodo b { font-size: 12px; }

@keyframes pulso { from { stroke-dashoffset: 100; } to { stroke-dashoffset: -8; } }
@media (prefers-reduced-motion: no-preference) {
  .pulso { animation: pulso var(--dur, 3s) linear infinite; animation-delay: var(--retardo, 0s); }
}

/* =================================================================
 * Piezas que la plataforma va a necesitar.
 * Documentadas y renderizadas en sistema.html.
 * ================================================================= */

/* ---------- Botones: variantes que faltaban ---------- */

/* Destructivo. NO va en rojo sólido: el rojo que se necesita para que el
   texto blanco cumpla AA ya no se lee como advertencia, y un botón rojo
   macizo invita a pulsarlo. Delineado y teñido: 8.5:1 y menos accidentes. */
.boton--peligro {
  border-color: var(--mal-borde);
  background: var(--mal-fondo);
  color: var(--mal);
}
.boton--peligro:hover { border-color: var(--mal-borde); background: var(--mal-fondo); }

.boton--chico { padding: 5px 11px; font-size: 13px; border-radius: var(--r-sm); }
.boton--chico svg { width: 14px; height: 14px; }

/* Cargando: el ancho no cambia, para que el botón no salte bajo el cursor. */
.boton[aria-busy="true"] { pointer-events: none; opacity: .75; }
.boton[aria-busy="true"] .girador {
  width: 14px; height: 14px; border-radius: 999px;
  border: 2px solid currentColor; border-top-color: transparent;
  animation: girar .7s linear infinite;
}
@keyframes girar { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .girador { animation: none; } }

.grupo-botones { display: flex; gap: 9px; flex-wrap: wrap; align-items: center; }

/* ---------- Casillas, radios e interruptor ---------- */
.marca-campo {
  display: inline-flex; align-items: flex-start; gap: 9px;
  cursor: pointer; line-height: 1.45;
}
.marca-campo input[type="checkbox"], .marca-campo input[type="radio"] {
  appearance: none; flex: none; width: 17px; height: 17px; margin: 1px 0 0;
  border: 1px solid var(--field); background: var(--hundido);
  border-radius: 5px; cursor: pointer; display: grid; place-content: center;
  transition: background-color .15s var(--curva), border-color .15s var(--curva);
}
.marca-campo input[type="radio"] { border-radius: 999px; }
.marca-campo input:checked { background: var(--accent); border-color: var(--accent); }
/* El símbolo va en abyss: sobre el verde, blanco da 3.46:1 y reprueba. */
.marca-campo input[type="checkbox"]:checked::before {
  content: ""; width: 9px; height: 5px; border: 2px solid var(--sobre-accent);
  border-top: 0; border-right: 0; transform: rotate(-45deg) translate(1px, -1px);
}
.marca-campo input[type="radio"]:checked::before {
  content: ""; width: 7px; height: 7px; border-radius: 999px; background: var(--sobre-accent);
}
.marca-campo input:disabled { opacity: .45; cursor: not-allowed; }

.interruptor { display: inline-flex; align-items: center; gap: 10px; cursor: pointer; }
.interruptor input {
  appearance: none; position: relative; flex: none; width: 38px; height: 22px; margin: 0;
  border-radius: 999px; border: 1px solid var(--field);
  background: var(--hundido); cursor: pointer;
  transition: background-color .2s var(--curva), border-color .2s var(--curva);
}
.interruptor input::after {
  content: ""; position: absolute; top: 2px; left: 2px; width: 16px; height: 16px;
  border-radius: 999px; background: var(--muted);
  transition: transform .2s var(--curva), background-color .2s var(--curva);
}
.interruptor input:checked { background: var(--accent); border-color: var(--accent); }
.interruptor input:checked::after { transform: translateX(16px); background: var(--sobre-accent); }

/* ---------- Paqueterías activas ----------
   Con mejor costo no hay orden que mostrar: cada paquetería es un nombre y
   un interruptor. El interruptor va a la derecha, donde se busca. */
.activa {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 12px 18px;
}
.activa + .activa { border-top: 1px solid var(--hairline); }
.activa__quien { min-width: 0; }
.activa__quien b { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; font-size: 14px; }
.activa__quien .apagado { display: block; margin-top: 2px; font-size: 11px; }
.activa__conectar { margin-top: 6px; }
.activa--apagada .activa__quien b { color: var(--muted); }

/* ---------- Campo con error ---------- */
/* Un campo que solo recibe una cifra no gana nada con ocupar toda la fila:
   el ancho de una caja es una pista de cuánto se espera que se escriba. */
.campo--corto > input { max-width: 180px; }

.campo--error input, .campo--error select, .campo--error textarea { border-color: var(--mal); }
.campo__error { color: var(--mal); font-size: 12px; }
input:disabled, select:disabled, textarea:disabled {
  opacity: .55; cursor: not-allowed; background: var(--hundido);
}

/* ---------- Pestañas ---------- */
.pestanas {
  display: flex; gap: 2px; border-bottom: 1px solid var(--hairline);
  overflow-x: auto; scrollbar-width: none;
}
.pestanas::-webkit-scrollbar { display: none; }
.pestana {
  padding: 10px 14px; border: 0; background: transparent; color: var(--muted);
  font: inherit; font-weight: 500; cursor: pointer; white-space: nowrap;
  border-bottom: 2px solid transparent; margin-bottom: -1px;
  transition: color .2s var(--curva), border-color .2s var(--curva);
}
.pestana:hover { color: var(--ink); }
.pestana[aria-selected="true"] { color: var(--ink); border-bottom-color: var(--accent); }

/* ---------- Diálogo ---------- */
dialog.dialogo {
  width: min(520px, calc(100vw - 32px)); padding: 0; border: 1px solid var(--hairline);
  border-radius: var(--r-lg); background: var(--tarjeta); color: var(--ink);
  box-shadow: var(--sombra);
}
dialog.dialogo::backdrop { background: rgba(18, 28, 51, 0.5); backdrop-filter: blur(2px); }
.dialogo__cabeza { padding: 18px 20px 0; }
.dialogo__cabeza h2 { font-size: 17px; }
.dialogo__cuerpo { padding: 10px 20px 18px; color: var(--muted); }
.dialogo__pie {
  display: flex; justify-content: flex-end; gap: 9px; flex-wrap: wrap;
  padding: 14px 20px; border-top: 1px solid var(--hairline);
}

/* ---------- Paginación ---------- */
.paginacion { display: flex; align-items: center; gap: 6px; }
.paginacion button {
  min-width: 32px; height: 32px; padding: 0 9px; border-radius: var(--r-sm);
  border: 1px solid transparent; background: transparent; color: var(--muted);
  font: inherit; cursor: pointer; transition: all .15s var(--curva);
}
.paginacion button:hover:not([disabled]) { background: var(--hover); color: var(--ink); }
.paginacion button[aria-current="page"] {
  border-color: var(--hairline-fuerte); background: var(--hundido-fuerte); color: var(--ink);
}
.paginacion button[disabled] { opacity: .4; cursor: not-allowed; }

/* ---------- Carga ---------- */
.esqueleto {
  border-radius: var(--r-sm); background: var(--hundido);
  animation: latir 1.4s ease-in-out infinite;
}
@keyframes latir { 50% { opacity: .45; } }
@media (prefers-reduced-motion: reduce) { .esqueleto { animation: none; } }

/* ---------- Insignia de canal conectado ---------- */
.insignia-tienda {
  display: inline-flex; align-items: center; gap: 8px; white-space: nowrap;
  padding: 5px 11px; border: 1px solid var(--hairline); border-radius: 999px;
  background: var(--hundido); font-size: 12px; color: var(--muted);
}
.insignia-tienda__punto {
  width: 7px; height: 7px; border-radius: 999px; background: var(--accent); flex: none;
}
.insignia-tienda b { color: var(--ink); font-weight: 500; }

/* ---------- Conmutador de vista ---------- */
.conmutador {
  display: inline-flex; padding: 2px; gap: 2px;
  border: 1px solid var(--hairline); border-radius: var(--r); background: var(--hundido);
}
.conmutador button {
  padding: 5px 13px; border: 0; border-radius: var(--r-sm); background: transparent;
  color: var(--muted); font: inherit; font-size: 13px; font-weight: 500; cursor: pointer;
  transition: background-color .15s var(--curva), color .15s var(--curva);
}
.conmutador button:hover { color: var(--ink); }
.conmutador button[aria-pressed="true"] { background: var(--hundido-fuerte); color: var(--ink); }

/* ---------- Inicio ----------
   Tres niveles de peso, no tres diseños: lo que exige atención, lo que toca
   hacer hoy y lo que solo informa. La diferencia la llevan el tamaño de la
   cifra, el color del borde y la densidad, no componentes distintos.

   Sin iconos: un icono por tarjeta añade seis formas que hay que descifrar
   antes de poder leer el número. */
/* Una sola escala: 12px dentro de una sección, 24px entre secciones. Antes
   convivían 26, 22, 12, 10 y 9 sin relación entre sí. */
.zona { margin-bottom: 24px; }

/* "Tu operación" es analítica, no operación, y la regla lo dice.

   Sin ella, el selector de periodo caía justo debajo de la última tarjeta de
   "Por hacer hoy" y alineado a su mismo borde derecho: a 29px de distancia,
   se leía como parte de esa tarjeta en vez de como encabezado de la sección
   siguiente. */
.zona--analitica { border-top: 1px solid var(--hairline); padding-top: 24px; }
.zona__titulo {
  margin-bottom: 12px;
  color: var(--muted); font-size: 11px; font-weight: 600;
  letter-spacing: .14em; text-transform: uppercase;
}
.tarjetas { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }

/* La tarjeta entera es el enlace. Un número grande con su etiqueta es un
   blanco mucho más obvio que un botón escondido en una esquina, y además
   evita tener dos destinos distintos dentro de la misma caja. */
.tarjeta-cifra {
  display: flex; flex-direction: column; gap: 3px;
  padding: 14px 16px 13px;
  border: 1px solid var(--hairline); border-radius: var(--r-lg);
  background: var(--tarjeta); box-shadow: var(--sombra-tarjeta); color: inherit; text-decoration: none;
  transition: border-color .16s var(--curva), box-shadow .16s var(--curva),
              transform .16s var(--curva);
}
.tarjeta-cifra__n {
  font-size: 27px; font-weight: 600; letter-spacing: -0.02em; line-height: 1.15;
  font-variant-numeric: tabular-nums;
}
.tarjeta-cifra__et { font-size: 13px; }
.tarjeta-cifra__nota { font-size: 11px; color: var(--muted); }

/* La acción va como texto, no como botón: dentro de una tarjeta que ya es
   pulsable, un botón compite con ella y hace dudar de dónde hay que dar clic. */
.tarjeta-cifra__ir {
  margin-top: auto; padding-top: 9px; border-top: 1px solid var(--hairline);
  display: flex; align-items: center; gap: 6px;
  color: var(--muted); font-size: 12px; font-weight: 500;
  transition: color .16s var(--curva);
}
.tarjeta-cifra__ir i {
  font-style: normal; transition: transform .16s var(--curva);
}

a.tarjeta-cifra:hover {
  border-color: var(--hairline-fuerte); box-shadow: var(--sombra-tarjeta-hover);
  transform: translateY(-1px);
}
a.tarjeta-cifra:hover .tarjeta-cifra__ir { color: var(--ink); }
a.tarjeta-cifra:hover .tarjeta-cifra__ir i { transform: translateX(2px); }
a.tarjeta-cifra:active { transform: none; }

/* El foco tiene que verse igual de claro que el hover: se navega con teclado. */
a.tarjeta-cifra:focus-visible .tarjeta-cifra__ir { color: var(--ink); }

@media (prefers-reduced-motion: reduce) {
  .tarjeta-cifra, .tarjeta-cifra__ir i { transition: none; }
  a.tarjeta-cifra:hover { transform: none; }
}

/* Tonos.

   El rojo marca dónde mirar, no que todo esté roto. Por eso el borde es un
   apunte —no llega a leerse como alarma— y el color fuerte se reserva para
   la cifra, que es lo que hay que encontrar rápido. */
.tarjeta-cifra--alerta { border-color: var(--mal-fondo); }
.tarjeta-cifra--alerta .tarjeta-cifra__n { color: var(--mal); font-size: 30px; }
a.tarjeta-cifra--alerta:hover { border-color: var(--mal-borde); }

.tarjeta-cifra--pendiente .tarjeta-cifra__n { color: var(--enlace); }

/* En cero la cifra se apaga y la tarjeta deja de ser enlace: un atajo que no
   lleva a ningún lado es una promesa rota. */
.tarjeta-cifra--cero { border-color: var(--hairline); }
.tarjeta-cifra--cero .tarjeta-cifra__n { color: var(--muted); }

/* Nada pendiente: las dos zonas se colapsan en una línea. */
.nada-pendiente {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 10px;
  padding: 13px 18px; margin-bottom: 26px;
  border: 1px solid var(--hairline); border-radius: var(--r-lg); background: var(--tarjeta);
}
.nada-pendiente b { font-weight: 600; }
.nada-pendiente span { font-size: 12px; color: var(--muted); }

/* Conexiones: franja, y solo cuando algo dejó de responder. */
.franja-conexion {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px;
  padding: 12px 16px; margin-bottom: 26px;
  border: 1px solid var(--aviso-borde); border-radius: var(--r-lg);
  background: var(--aviso-fondo);
}
.franja-conexion b { color: var(--aviso); font-size: 14px; }
.franja-conexion span { color: var(--muted); font-size: 12px; }
.franja-conexion__sep { flex: 1; }

/* ---------- Tu operación ----------
   Analítica secundaria: más compacta y sin tono, para que no compita con lo
   que sí exige una acción. No son botones y por eso son una lista de
   definición, no enlaces. */
.periodo__cabeza {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px; margin-bottom: 12px;
}
.periodo__cabeza .zona__titulo { margin-bottom: 0; }
.periodo__mando { display: flex; flex-wrap: wrap; gap: 6px; margin-left: auto; }

.periodo__mando .ficha-filtro { transition: all .16s var(--curva); }

.periodo { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.periodo__dato {
  padding: 8px 13px 9px;
  border: 1px solid var(--hairline); border-radius: var(--r);
  background: var(--tarjeta);
}
.periodo__dato dt { color: var(--muted); font-size: 11px; line-height: 1.35; }
.periodo__dato dd {
  margin: 2px 0 0; font-size: 17px; font-weight: 600; line-height: 1.2;
  letter-spacing: -0.01em; font-variant-numeric: tabular-nums;
}
/* La variación solo aparece cuando el periodo anterior tiene datos de verdad:
   comparar contra cero no es una variación. */
.periodo__var { display: block; margin-top: 2px; font-size: 11px; font-weight: 400; color: var(--muted); }
.periodo__var--sube { color: var(--enlace); }
.periodo__var--baja { color: var(--mal); }

/* Ayuda de una FILA de campos, no de uno solo.

   "Define la colonia, la ciudad y el estado" habla de la relación entre el
   código postal y los otros tres campos, así que colgada debajo del input del
   CP —una columna de 148px— se partía en dos renglones y quedaba apretada
   contra la fila siguiente. Abajo y a todo lo ancho se lee de corrido. */
.campos__ayuda {
  margin-top: -8px;
  color: var(--muted); font-size: 12px; line-height: 1.45;
}

/* Confirmación de un cambio que se guardó solo. No es un aviso flotante:
   aparece donde ocurrió la acción y se va sin que nadie la cierre. */
.guardado {
  margin-bottom: 14px; padding: 10px 14px;
  border: 1px solid var(--destacado-borde); border-radius: var(--r);
  background: var(--destacado); color: var(--enlace); font-size: 13px;
}

/* La cifra que importa de una ficha: se lee antes que su rótulo. */
.ficha__cifra { font-size: 19px; font-weight: 600; letter-spacing: -0.01em; }

.acciones-fila {
  display: flex; gap: 6px; justify-content: flex-end; flex-wrap: nowrap;
}
.acciones-fila .boton { min-width: 104px; justify-content: center; white-space: nowrap; }

/* El día, como fila que ocupa el ancho de la tabla. */
.tabla-reco .fila-dia th {
  padding-top: 18px; text-align: left;
  color: var(--ink); font-size: 13px; font-weight: 600;
  text-transform: none; letter-spacing: 0;
}
.tabla-reco .fila-dia:first-child th { padding-top: 12px; }

.nota-celda { white-space: nowrap; }

/* Una nota que va DEBAJO del contenido de su celda, no al lado. `.nota-celda`
   no sirve para esto: su `nowrap` es para notas de tres palabras, y una frase
   entera ensancharía la tabla hasta sacarla de la pantalla. */
.nota-bajo {
  display: block; margin-top: 3px;
  color: var(--muted); font-size: 11.5px; line-height: 1.45; font-weight: 400;
}

/* ---------- Hallazgos del buscador global ----------
   Cuelga del buscador de la barra superior. Los resultados van agrupados por
   tipo porque una lista plana obliga a adivinar qué es cada fila: un número
   largo puede ser una guía o un folio. */
.hallazgos {
  position: absolute; z-index: 70; top: calc(100% + 6px); left: 0; right: 0;
  max-height: min(70vh, 460px); overflow-y: auto;
  padding: 6px; border: 1px solid var(--hairline-fuerte); border-radius: var(--r-lg);
  background: var(--hundido); box-shadow: var(--sombra);
}
.hallazgos__grupo {
  padding: 9px 10px 5px;
  color: var(--muted); font-size: 11px; font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase;
}
.hallazgos__vacio { padding: 14px 10px; color: var(--muted); font-size: 13px; line-height: 1.5; }

.hallazgo {
  display: block; padding: 8px 10px; border-radius: var(--r-sm);
  color: inherit; text-decoration: none;
  transition: background .12s var(--curva);
}
.hallazgo b { display: block; font-size: 13px; font-weight: 500; }
.hallazgo span { display: block; margin-top: 2px; color: var(--muted); font-size: 12px; }
.hallazgo:hover, .hallazgo:focus-visible { background: var(--hover); }
.hallazgo:hover b, .hallazgo:focus-visible b { color: var(--enlace); }

@media (prefers-reduced-motion: reduce) { .hallazgo { transition: none; } }

/* ---------- Orden de preferencia ----------
   Una fila por paquetería: su puesto, su papel y su porqué. El porqué va en
   la misma fila y no escondido tras un icono: es lo que evita que alguien
   "arregle" el orden y tire por tierra un criterio que costó meses de
   incidencias. */
.orden, .orden__cabecera {
  --orden-cols: 18px 30px minmax(130px, 1fr) 150px minmax(180px, 2fr) auto;
}
.orden__fila {
  display: grid; align-items: center; gap: 12px;
  grid-template-columns: var(--orden-cols);
  padding: 12px 18px;
}

/* Un campo de texto sin rótulo parece un comentario suelto. La columna dice
   para qué sirve antes de que nadie tenga que deducirlo. */
.orden__cabecera {
  display: grid; gap: 12px; grid-template-columns: var(--orden-cols);
  padding: 10px 18px; border-bottom: 1px solid var(--hairline);
  color: var(--muted); font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
}
.orden__et { display: none; }
.orden__fila + .orden__fila { border-top: 1px solid var(--hairline); }

/* El papel se ve antes de leerlo: una barra a la izquierda. */
.orden__fila { position: relative; }
.orden__fila::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 3px;
}
.orden__fila--normal::before { background: var(--hairline-fuerte); }
.orden__fila--manda::before { background: var(--accent); }
.orden__fila--evitar::before { background: var(--aviso-borde); }
.orden__fila--no-usar::before { background: var(--mal-borde); }

.orden__puesto {
  display: grid; place-items: center; width: 26px; height: 26px;
  border-radius: 999px; border: 1px solid var(--hairline);
  color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums;
}
.orden__fila--no-usar .orden__quien b { text-decoration: line-through; color: var(--muted); }
.orden__quien b { display: flex; align-items: center; gap: 8px; font-size: 14px; }
.orden__quien .pastilla { text-decoration: none; }
.orden__quien span { display: block; margin-top: 2px; font-size: 11px; }
.orden__porque textarea {
  width: 100%; min-height: 0; padding: 8px 10px; resize: none; overflow: hidden;
  font-size: 13px; line-height: 1.45;
}
/* ---------- Arrastrar ----------
   El asa es lo único arrastrable: con la fila entera arrastrable, seleccionar
   texto en la nota movería la paquetería. */
.orden__asa {
  display: grid; place-items: center; width: 18px; height: 28px;
  color: var(--muted); cursor: grab;
  transition: color .15s var(--curva);
}
.orden__asa:active { cursor: grabbing; }
.orden__fila:hover .orden__asa { color: var(--ink); }
.orden__fila--viaja { opacity: .4; }

/* El destino es un hueco entre filas, no una fila: se marca con una línea. */
.orden__fila--antes::after, .orden__fila--despues::after {
  content: ""; position: absolute; left: 0; right: 0; height: 2px;
  background: var(--accent); pointer-events: none;
}
.orden__fila--antes::after { top: -1px; }
.orden__fila--despues::after { bottom: -1px; }

.orden__mover { display: flex; gap: 4px; }
.orden__mover .boton { min-width: 32px; justify-content: center; }

/* ---------- Lo técnico, plegado ---------- */
.avanzado > summary {
  padding: 12px 16px; border: 1px solid var(--hairline); border-radius: var(--r-lg);
  background: var(--tarjeta); color: var(--ink); font-size: 14px; cursor: pointer;
  list-style: none;
}
.avanzado > summary::-webkit-details-marker { display: none; }
.avanzado > summary::before { content: "▸ "; color: var(--muted); }
.avanzado[open] > summary::before { content: "▾ "; }
.avanzado > summary:hover { border-color: var(--hairline-fuerte); }
.avanzado > div { padding: 18px 2px 4px; }

/* Plegado dentro de una tarjeta: más discreto que el de página, porque ahí ya
   hay un título que manda. Así cada credencial vive junto a la conexión que
   explica, en vez de repetirse en un bloque técnico al final. */
.avanzado--ficha > summary { padding: 8px 12px; font-size: 13px; }
.avanzado--ficha > div { padding: 12px 0 0; }
.avanzado--sangrado { margin: -2px 0 6px 30px; }

/* El arrastre nativo no existe con el dedo. Donde no se puede arrastrar no se
   enseña el asa: quedan las flechas, que son además el camino del teclado.
   Los rótulos de columna pasan entonces a ir sobre cada campo. */
/* Prometer "arrastra" en una pantalla donde no se puede arrastrar es mentir
   con el texto igual que con un interruptor que no hace nada. */
.solo-tacto { display: none; }

@media (pointer: coarse), (max-width: 767px) {
  .solo-raton { display: none; }
  .solo-tacto { display: inline; }
  .orden__asa, .orden__cabecera { display: none; }
  .orden, .orden__cabecera { --orden-cols: 30px minmax(130px, 1fr) 150px minmax(180px, 2fr) auto; }
  .orden__et {
    display: block; margin-bottom: 4px;
    color: var(--muted); font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  }
}

@media (max-width: 767px) {
  /* Las flechas viajan con el nombre que mueven, no al final de la fila. */
  /* minmax(0, …): con 1fr a secas, un botón largo como "Conectar
     Paquetexpress" fijaba el mínimo de la columna y a 360px la fila sacaba
     Papel y Motivo fuera de la tarjeta. */
  .orden, .orden__cabecera { --orden-cols: 30px minmax(0, 1fr) auto; }
  .orden__fila { row-gap: 10px; align-items: start; }
  .orden__quien .boton { max-width: 100%; white-space: normal; text-align: left; }
  .orden__quien b { flex-wrap: wrap; row-gap: 4px; }
  .orden__puesto, .orden__quien, .orden__mover { grid-row: 1; }
  .orden__mover { grid-column: 3; }
  .orden__papel, .orden__porque { grid-column: 2 / -1; }
}

/* ---------- Ficha ----------
   Tarjeta de un registro que se administra: una dirección de origen, una
   plantilla de paquete. Nombre arriba, datos en medio, acciones al pie.

   El predeterminado lleva una barra del acento a la izquierda. Es el que se
   usa cuando nada dice lo contrario, y tiene que distinguirse sin leer. */
/* Barra de la lista: buscar, cuántas hay y en qué forma verlas. El buscador
   solo aparece cuando hay suficientes como para que buscar gane a mirar. */
.fichas-barra {
  display: flex; align-items: center; flex-wrap: wrap; gap: 12px; margin-bottom: 14px;
}
.fichas-barra__sep { flex: 1; }

.fichas { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(340px, 1fr)); }

/* Con auto-fill en vez de auto-fit, una sola conexión no se estira a lo ancho
   de la pantalla: ocupa su columna y deja ver que caben más. */
.fichas--conexiones { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }

.tarjeta--solo-pie { margin-top: 14px; }
.tarjeta--solo-pie .tarjeta__pie { border-top: 0; }

/* En la lista, el predeterminado se marca con la misma barra que en la
   tarjeta: es el mismo hecho y tiene que verse igual en las dos vistas. */
tr.fila--principal td:first-child { position: relative; }
tr.fila--principal td:first-child::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 3px; background: var(--accent);
}

.ficha {
  display: grid; align-content: start; gap: 12px;
  position: relative; overflow: hidden;
  padding: 18px 20px;
  border: 1px solid var(--hairline); border-radius: var(--r-lg);
  background: var(--tarjeta); box-shadow: var(--sombra-tarjeta);
}
.ficha--principal::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 3px; background: var(--accent);
}
.ficha__cabeza { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.ficha__cabeza h2 { font-size: 16px; }
.ficha__sub { margin-top: 3px; color: var(--muted); font-size: 12px; }
.ficha__nowrap { white-space: nowrap; }

.ficha__cuerpo { font-style: normal; font-size: 13px; line-height: 1.55; }

.ficha__datos { display: grid; gap: 10px; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); }
.ficha__datos dt { color: var(--muted); font-size: 11px; }
.ficha__datos dd { margin: 3px 0 0; font-size: 13px; }
.ficha__nota { margin-top: -4px; color: var(--muted); font-size: 12px; }

.ficha__pie {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  padding-top: 12px; border-top: 1px solid var(--hairline);
}
.ficha__pie-sep { flex: 1; }

/* ---------- El menú de la cuenta ----------
   Cuelga del avatar, que era un adorno. Lo de la cuenta —quién eres, qué plan
   pagas, salir— no es navegación de la operación y no compite con ella en la
   barra lateral. */
/* Todo lo que no es navegación ni búsqueda se agrupa y se empuja al borde.
   El buscador deja de crecer a los 420px, así que sin esto el resto se queda
   pegado a él —a dos tercios de la barra— con un hueco muerto hasta el borde. */
.superior__fin { display: flex; align-items: center; gap: 12px; margin-left: auto; }
.solo-angosto { display: none; }

/* ---------- Desplegables de la barra ----------
   La campana y la cuenta comparten posición y comportamiento; solo cambia lo
   que llevan dentro. */
.cuenta, .colgante { position: relative; }

.colgante__abrir {
  display: grid; place-items: center; position: relative;
  width: 34px; height: 34px;
  border: 1px solid transparent; border-radius: 10px;
  background: none; color: var(--muted); cursor: pointer;
  transition: border-color .15s var(--curva), background .15s var(--curva),
              color .15s var(--curva);
}
.colgante__abrir svg { width: 19px; height: 19px; }
.colgante__abrir:hover,
.colgante__abrir[aria-expanded="true"] {
  border-color: var(--hairline-fuerte); background: var(--hundido); color: var(--ink);
}

/* La cuenta la lleva el punto y aquí la cifra: son dos cosas distintas y por
   eso se ven distintas. Lo que hay sin leer se puede contar; lo del plan no. */
.colgante__punto {
  position: absolute; top: 1px; right: 1px;
  min-width: 15px; height: 15px; padding: 0 4px;
  border: 2px solid var(--pagina); border-radius: 999px;
  background: var(--accent-solido); color: var(--sobre-accent);
  font-size: 10px; font-weight: 700; line-height: 11px;
  font-variant-numeric: tabular-nums;
}

.colgante__panel {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 60;
  width: 360px; max-width: calc(100vw - 32px);
  border: 1px solid var(--hairline); border-radius: var(--r-lg);
  background: var(--tarjeta); box-shadow: 0 16px 40px rgba(18, 28, 51, .18);
}

/* ---------- Novedades ---------- */
.avisos__cabeza {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 14px; border-bottom: 1px solid var(--hairline);
}
.avisos__cabeza b { font-size: 13px; }
.avisos__lista { max-height: min(60vh, 460px); overflow: auto; }
.avisos__vacio { padding: 20px 14px; color: var(--muted); font-size: 13px; line-height: 1.55; }

.aviso-fila { padding: 13px 14px; }
.aviso-fila + .aviso-fila { border-top: 1px solid var(--hairline); }

/* Lo no leído se marca con una barra, no con un fondo: el fondo lo convierte
   en un bloque de color y deja de poder leerse la jerarquía de dentro. */
.aviso-fila--nuevo { position: relative; }
.aviso-fila--nuevo::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 2px; background: var(--accent);
}
.aviso-fila__meta { display: flex; align-items: center; gap: 8px; margin-bottom: 5px; }
.aviso-fila__meta span:last-child { color: var(--muted); font-size: 11px; }
.aviso-fila__tipo {
  padding: 1px 7px; border-radius: 999px;
  font-size: 10px; letter-spacing: .06em; text-transform: uppercase;
  background: var(--hundido); color: var(--muted);
}
.aviso-fila__tipo--novedad { background: var(--destacado-fuerte); color: var(--enlace); }
.aviso-fila__tipo--mantenimiento { background: var(--aviso-fondo); color: var(--aviso); }
.aviso-fila b { display: block; font-size: 13px; line-height: 1.4; }
.aviso-fila p { margin-top: 3px; color: var(--muted); font-size: 12px; line-height: 1.5; }
.aviso-fila__ir {
  display: inline-block; margin-top: 7px;
  color: var(--enlace); font-size: 12px; text-decoration: none;
}
.aviso-fila__ir:hover { text-decoration: underline; }

/* Un círculo con dos letras no se distingue de las insignias de al lado, que
   no hacen nada. La flecha dice que abre algo. */
.cuenta__abrir {
  display: flex; align-items: center; gap: 6px; position: relative;
  padding: 4px 6px 4px 4px; border: 1px solid transparent; border-radius: 10px;
  background: none; color: var(--muted); cursor: pointer; font: inherit;
  transition: border-color .15s var(--curva), background .15s var(--curva);
}
.cuenta__abrir:hover,
.cuenta__abrir[aria-expanded="true"] {
  border-color: var(--hairline-fuerte); background: var(--hundido); color: var(--ink);
}
.cuenta__flecha { transition: transform .15s var(--curva); }
.cuenta__abrir[aria-expanded="true"] .cuenta__flecha { transform: rotate(180deg); }

/* El punto solo aparece cuando hay algo dentro que mirar. Un adorno
   permanente deja de leerse a la semana. */
.cuenta__punto {
  position: absolute; top: 2px; left: 22px; width: 8px; height: 8px;
  border: 2px solid var(--pagina); border-radius: 999px; background: #d97706;
}
.cuenta__cuenta {
  margin-left: auto; padding: 1px 7px; border-radius: 999px;
  background: var(--aviso-fondo); color: var(--aviso);
  font-size: 11px; font-variant-numeric: tabular-nums;
}

.cuenta__menu {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 60;
  min-width: 232px; max-width: calc(100vw - 32px); padding: 6px;
  border: 1px solid var(--hairline); border-radius: var(--r-lg);
  background: var(--tarjeta); box-shadow: 0 16px 40px rgba(18, 28, 51, .18);
}
.cuenta__quien {
  padding: 10px 10px 12px; margin-bottom: 4px;
  border-bottom: 1px solid var(--hairline);
}
.cuenta__quien b { display: block; font-size: 13px; }
.cuenta__quien span { display: block; margin-top: 2px; color: var(--muted); font-size: 12px; }

.cuenta__opcion {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 10px; border-radius: var(--r);
  color: var(--ink); font-size: 13px; text-decoration: none;
}
.cuenta__opcion svg { width: 17px; height: 17px; color: var(--muted); }
.cuenta__opcion:hover { background: var(--hundido); }
.cuenta__opcion:hover svg { color: var(--ink); }

/* En una pantalla angosta, colgar de un botón que no está pegado al borde
   saca el panel por la izquierda: la campana tiene la cuenta a su derecha, así
   que 360px medidos desde ella caen fuera. Ahí el panel deja de colgar del
   botón y se ancla a la ventana. */
@media (max-width: 767px) {
  .colgante__panel, .cuenta__menu {
    position: fixed; top: calc(var(--superior) + 8px);
    left: 16px; right: 16px; width: auto; max-width: none;
  }
}

/* Lo que no cuadra se marca en su sitio, dentro de la fila: sacarlo a una
   columna aparte obliga a buscarlo de vuelta en el texto. */
.caso__malo { color: var(--aviso); }


/* ---------- Consumo del plan ----------
   La pregunta es "¿me alcanza?". Lo que se lee primero es lo que QUEDA; el
   porcentaje solo existe para pintar la barra, porque nadie decide con un 92 %. */
.uso { display: grid; gap: 14px; }
.uso__cifras { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 18px; }
.uso__n { font-size: 38px; font-weight: 600; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
.uso__n--aviso { color: var(--aviso); }
.uso__n--alerta { color: var(--mal); }
.uso__et { margin-left: 8px; color: var(--muted); font-size: 13px; }
.uso__detalle { color: var(--muted); font-size: 13px; line-height: 1.5; }
.uso__nota { color: var(--muted); font-size: 12px; }

.barra {
  height: 8px; border-radius: 999px; overflow: hidden;
  background: var(--hundido-fuerte);
}
.barra__lleno { display: block; height: 100%; border-radius: 999px; background: var(--accent); }
.barra__lleno--aviso { background: var(--aviso); }
.barra__lleno--alerta { background: var(--mal); }

/* Una conexión que todavía no existe se ve, pero no compite con las que sí:
   sin ella la lista de lo conectado y la de lo conectable pesarían igual. */
.ficha--apagada { background: transparent; border-style: dashed; }
.ficha--apagada h2 { color: var(--muted); }



/* ---------- Barra de selección múltiple ----------
   Aparece dentro de la tarjeta, no flotando: el usuario ya está mirando
   la tabla y no hay que llevarle la vista a otro lado. */
/* El motivo por el que ninguna acción aplica. Va en la barra y no solo en un
   `title`: con el dedo no hay `title` que valga, y ese aviso es justo el que
   hace falta cuando se llega desde un atajo que prometía trabajo. */
.barra-seleccion__nota { flex: 1 1 100%; color: var(--muted); font-size: 12px; }

.barra-seleccion {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 11px 18px; border-bottom: 1px solid var(--hairline);
  background: var(--destacado);
}
.barra-seleccion__cuenta { font-weight: 600; }
.barra-seleccion__sep { flex: 1; }

/* ---------- Tarea del inicio ---------- */
.tarea {
  display: flex; align-items: center; gap: 14px; padding: 15px 18px;
  border-bottom: 1px solid var(--hairline); transition: background-color .15s var(--curva);
}
.tarea:last-child { border-bottom: 0; }
.tarea:hover { background: var(--hover); }
.tarea__icono {
  display: grid; place-items: center; width: 36px; height: 36px; flex: none;
  border-radius: var(--r); border: 1px solid var(--hairline); background: var(--hundido);
  color: var(--muted);
}
.tarea__icono svg { width: 17px; height: 17px; }
.tarea--urge .tarea__icono { border-color: var(--mal-borde); background: var(--mal-fondo); color: var(--mal); }
.tarea--atender .tarea__icono { border-color: var(--aviso-borde); background: var(--aviso-fondo); color: var(--aviso); }
.tarea--ok .tarea__icono { border-color: var(--destacado-borde); background: var(--destacado); color: var(--enlace); }
.tarea__cuerpo { flex: 1; min-width: 0; }
.tarea__cuerpo b { font-weight: 600; }
.tarea__cuerpo p { margin-top: 2px; color: var(--muted); font-size: 13px; }

/* Ítems del menú que existen en la app pero todavía no están vestidos. */
.nav-item--pendiente { opacity: .62; }
/* Un punto, no una palabra: "sin vestir" junto a "Configuración" no cabe en
   236px y parte el ítem en dos líneas. El porqué va en el title del enlace. */
.nav-item__marca {
  margin-left: auto; flex: none; width: 6px; height: 6px; border-radius: 999px;
  border: 1px solid var(--hairline-fuerte);
}

/* =================================================================
 * Panel de detalle del pedido.
 *
 * Cajón lateral, no pantalla aparte: el operador va bajando una lista,
 * abre, revisa, actúa y sigue. Navegar a otra página le tira el filtro,
 * la página y el lugar donde iba.
 *
 * Es un <dialog> nativo a propósito: trae foco atrapado, Escape y fondo
 * inerte sin una línea de JavaScript. Reescribir eso a mano es como se
 * pierde la accesibilidad.
 * ================================================================= */
dialog.panel {
  margin: 0 0 0 auto; padding: 0; border: 0;
  border-left: 1px solid var(--hairline);
  width: min(660px, 100vw); max-width: 100vw;
  height: 100dvh; max-height: 100dvh;
  background: var(--pagina); color: var(--ink);
  box-shadow: -40px 0 80px -40px rgba(18, 28, 51, 0.28);
}
dialog.panel::backdrop { background: rgba(18, 28, 51, 0.45); }
/* El contenedor recibe el foco al abrir; su anillo sobra. */
dialog.panel:focus { outline: none; }
/* El propio <dialog> nunca scrollea: solo su cuerpo. */
dialog.panel { overflow: hidden; }
dialog.panel[open] { display: flex; flex-direction: column; }

@keyframes entrar-panel { from { transform: translateX(24px); opacity: 0; } }
@media (prefers-reduced-motion: no-preference) {
  dialog.panel[open] { animation: entrar-panel .24s var(--curva); }
}

.panel__cabeza {
  position: sticky; top: 0; z-index: 2; flex: none;
  display: flex; align-items: flex-start; gap: 14px;
  padding: 18px 22px; border-bottom: 1px solid var(--hairline);
  background: var(--tarjeta);
}
/* El folio va en monoespaciado; la palabra "Pedido", no. */
.panel__cabeza h2 {
  display: flex; align-items: center; gap: 11px; flex-wrap: wrap;
  font-size: 19px;
}
.panel__cabeza h2 .mono { font-size: 19px; }
.panel__cabeza p { margin-top: 4px; color: var(--muted); font-size: 13px; }
.panel__cerrar {
  margin-left: auto; flex: none; width: 34px; height: 34px; padding: 0;
  display: grid; place-items: center; border-radius: var(--r);
  border: 1px solid var(--hairline); background: transparent; color: var(--muted);
  cursor: pointer; transition: all .15s var(--curva);
}
.panel__cerrar:hover { border-color: var(--hairline-fuerte); color: var(--ink); }
/* min-height:0 no es opcional. Un hijo de flex trae min-height:auto, así que
   el cuerpo crece hasta su contenido en vez de encogerse, el diálogo se
   desborda y aparece una SEGUNDA barra de scroll sobre la del cuerpo. */
/* La columna es minmax(0, 1fr) por la misma razón que en `.campo`: una rejilla
   sin columnas declaradas mide su única columna por el contenido más ancho, y
   la tabla de artículos lleva un mínimo de 560px en pantallas angostas. Sin
   esto, el cuerpo del panel medía 562px dentro de una pantalla de 390 y la
   tabla, que tiene su propio scroll, arrastraba al panel entero con ella. */
.panel__cuerpo {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: 22px; display: grid; gap: 22px; align-content: start;
  grid-template-columns: minmax(0, 1fr);
}
/* Un formulario que solo envuelve bloques no puede romper el ritmo del panel:
   sin esto, los bloques de dentro se quedan sin la separación que el cuerpo da
   a sus hijos y se leen encimados. */
.panel__cuerpo > form {
  display: grid; gap: 22px; align-content: start;
  grid-template-columns: minmax(0, 1fr);
}

.panel__pie {
  flex: none; display: flex; gap: 9px; justify-content: flex-end; flex-wrap: wrap;
  padding: 14px 22px; border-top: 1px solid var(--hairline); background: var(--tarjeta);
}

/* ---------- Bloques del detalle ----------
   Columna declarada, igual que en `.panel__cuerpo` y en `.campo`: la tabla de
   artículos lleva `min-width: 560px` en pantallas angostas, y con la columna
   en auto el bloque la medía entera en vez de dejar que la tabla se desplazara
   dentro de su propia caja. Un scroll por capa: el de la tabla es de la tabla. */
.bloque { display: grid; gap: 11px; grid-template-columns: minmax(0, 1fr); }
.bloque__titulo {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  font-size: 11px; font-weight: 600; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted);
}
.bloque__caja {
  border: 1px solid var(--hairline); border-radius: var(--r-lg);
  background: var(--tarjeta); padding: 15px 17px;
}

.dato { display: flex; justify-content: space-between; gap: 16px; padding: 5px 0; }
.dato + .dato { border-top: 1px solid var(--hairline); }
.dato dt, .dato > span:first-child { color: var(--muted); }
.dato dd, .dato > span:last-child { margin: 0; text-align: right; }
.dato--fuerte { font-weight: 600; font-size: 15px; padding-top: 9px; }

.direccion { line-height: 1.6; }
.direccion b { display: block; font-weight: 600; }
.direccion span { display: block; color: var(--muted); }

/* ---------- Corrección de dirección ----------
   No se muestran dos bloques de texto para que alguien los compare con el
   dedo: se muestra QUÉ cambió, campo por campo. */
.cambio {
  display: grid; grid-template-columns: 104px minmax(0, 1fr) 14px minmax(0, 1fr);
  gap: 10px; align-items: baseline; padding: 7px 0; font-size: 13px;
}
.cambio + .cambio { border-top: 1px solid var(--hairline); }
.cambio__campo { color: var(--muted); font-size: 12px; }
.cambio__antes { color: var(--muted); text-decoration: line-through; text-decoration-color: var(--hairline-fuerte); }
.cambio__flecha { color: var(--accent); text-align: center; }
.cambio__despues { color: var(--ink); font-weight: 500; }

.desplegable > summary {
  cursor: pointer; color: var(--muted); font-size: 13px; padding: 7px 0;
  list-style: none; display: flex; align-items: center; gap: 7px;
}
.desplegable > summary::-webkit-details-marker { display: none; }
.desplegable > summary::before {
  content: "›"; display: inline-block; transition: transform .2s var(--curva);
}
.desplegable[open] > summary::before { transform: rotate(90deg); }
.desplegable > summary:hover { color: var(--ink); }
.desplegable__cuerpo { padding: 10px 0 4px 16px; }

@media (max-width: 767px) {
  /* El tachado lo pinta el elemento padre sobre todo su contenido, así que
     una flecha metida dentro del "antes" sale tachada también. Va fuera, en
     su propia línea, girada para que apunte hacia abajo. */
  .cambio { grid-template-columns: minmax(0, 1fr); gap: 2px; }
  .cambio__flecha {
    display: inline-block; text-align: left;
    transform: rotate(90deg); transform-origin: left center;
    line-height: 1; margin: 4px 0 4px 3px;
  }
  .panel__cuerpo { padding: 16px; }
  .panel__cabeza, .panel__pie { padding: 14px 16px; }
}

/* =================================================================
 * Franja de desenlace.
 *
 * Los mismos datos piden tratamiento opuesto según sean un RESULTADO o
 * una DECISIÓN:
 *
 *   resuelto   ya pasó, no hay nada que hacer  → se celebra y se pliega
 *   pendiente  alguien tiene que decidir       → se despliega y se explica
 *
 * Antes todo se mostraba igual, con la lista de cambios tachados como
 * elemento más grande de la tarjeta. Eso es una vista forense: sirve
 * cuando algo falló, y estorba cuando se resolvió solo.
 * ================================================================= */
.franja {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 14px 16px; border: 1px solid; border-radius: var(--r);
}
.franja__icono {
  flex: none; display: grid; place-items: center;
  width: 28px; height: 28px; border-radius: 999px;
}
.franja__icono svg { width: 16px; height: 16px; }
.franja b { display: block; font-weight: 600; }
.franja p { margin-top: 3px; font-size: 13px; line-height: 1.5; }

.franja--resuelto {
  border-color: var(--destacado-borde);
  background:
    radial-gradient(70% 160% at 0% 0%, var(--destacado-fuerte), transparent 70%),
    var(--destacado-tenue);
}
.franja--resuelto .franja__icono { background: var(--destacado-fuerte); color: var(--enlace); }
.franja--resuelto p { color: var(--muted); }

.franja--pendiente {
  border-color: var(--mal-borde); background: var(--mal-fondo);
}
.franja--pendiente .franja__icono { background: var(--mal-fondo); color: var(--mal); }
.franja--pendiente p { color: var(--mal); }

.franja--editada {
  border-color: var(--hairline-fuerte); background: var(--hundido);
}
.franja--editada .franja__icono { background: var(--hundido-fuerte); color: var(--muted); }
.franja--editada p { color: var(--muted); }

/* ---------- Comparación de tarifas ----------
   Lista con radios y no un desplegable: el trabajo de esta pantalla es
   COMPARAR, y un desplegable esconde justo lo que hay que comparar. */
.tarifas { display: grid; gap: 8px; }
.tarifa {
  display: grid; grid-template-columns: 17px minmax(0, 1fr) auto; gap: 12px;
  align-items: center; padding: 11px 13px; cursor: pointer;
  border: 1px solid var(--hairline); border-radius: var(--r);
  transition: border-color .15s var(--curva), background-color .15s var(--curva);
}
.tarifa:hover { border-color: var(--hairline-fuerte); background: var(--hover); }
.tarifa:has(input:checked) {
  border-color: var(--destacado-borde-fuerte); background: var(--destacado);
}
.tarifa:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
.tarifa input { margin: 0; }
.tarifa__nombre b { font-weight: 600; }
.tarifa__meta { margin-top: 2px; color: var(--muted); font-size: 12px; }
.tarifa__precio { font-weight: 600; font-variant-numeric: tabular-nums; }
.tarifa__cumple { color: var(--muted); }
.tarifa__cumple[data-bajo="true"] { color: var(--aviso); }

/* =================================================================
 * REQ-01 · Lote
 *
 * El diálogo no cambia de ventana entre resumen, progreso y resultado:
 * es el mismo, y el contenido se reemplaza. Cambiar de ventana a mitad
 * de una operación hace perder de vista qué se estaba haciendo.
 * ================================================================= */
dialog.lote { width: min(620px, calc(100vw - 32px)); }
.lote__lista {
  max-height: min(46vh, 380px); overflow-y: auto;
  border: 1px solid var(--hairline); border-radius: var(--r);
}
/* El detalle del error va DEBAJO del motivo, no en otra columna: es prosa
   y competía por el ancho, partiendo "Sin cobertura para el código postal"
   en cuatro líneas. La cuarta columna queda solo para el importe. */
.lote__fila {
  display: grid; grid-template-columns: 22px 84px minmax(0, 1fr) auto;
  gap: 12px; align-items: baseline; padding: 11px 13px;
}
.lote__fila > :nth-child(4) { white-space: nowrap; }
.lote__detalle { display: block; margin-top: 3px; color: var(--muted); font-size: 12px; }
.lote__fila + .lote__fila { border-top: 1px solid var(--hairline); }
.lote__fila b { font-family: ui-monospace, Menlo, monospace; font-weight: 500; }
.lote__fila span { color: var(--muted); font-size: 13px; }
.lote__estado { display: grid; place-items: center; width: 22px; height: 22px; }
.lote__estado svg { width: 15px; height: 15px; }
.lote__estado--generado { color: var(--enlace); }
.lote__estado--fallido { color: var(--mal); }
.lote__estado--omitido { color: var(--muted); }
.lote__estado--cola { color: var(--muted); opacity: .5; }
.lote__estado--procesando i {
  display: block; width: 13px; height: 13px; border-radius: 999px;
  border: 2px solid var(--accent); border-top-color: transparent;
  animation: girar .7s linear infinite;
}
@media (prefers-reduced-motion: reduce) { .lote__estado--procesando i { animation: none; } }

.lote__conteo { display: flex; gap: 18px; flex-wrap: wrap; }
.lote__conteo div b { display: block; font-size: 21px; font-weight: 600; font-variant-numeric: tabular-nums; }
.lote__conteo div span { color: var(--muted); font-size: 12px; }

.lote__barra {
  height: 4px; border-radius: 999px; background: var(--hundido-fuerte); overflow: hidden;
}
.lote__barra i { display: block; height: 100%; background: var(--accent); transition: width .25s var(--curva); }

/* Fila de la tabla que falló en el lote. */
tbody tr[data-fallido="true"] { background: var(--mal-fondo); }

@media (max-width: 520px) {
  .lote__fila { grid-template-columns: 22px minmax(0, 1fr); }
  .lote__fila > :nth-child(4) { grid-column: 2; }
}

/* =================================================================
 * Formularios: rejilla y campos compuestos.
 *
 * Estas piezas existen porque se estaban improvisando con estilos en
 * línea dentro de las pantallas, que es exactamente lo que el sistema
 * sirve para evitar: cada formulario acababa con su propio ancho de
 * columna y su propio hueco.
 * ================================================================= */

/* align-items:start es obligatorio: si un campo de la fila lleva texto de
   ayuda debajo, su celda crece y el de al lado queda centrado en vez de
   alineado con él. */
.campos { display: grid; gap: 14px; align-items: start; }
.campos--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.campos--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* Para un par donde el primero es corto y fijo: código postal, número. */
.campos--corto-largo { grid-template-columns: 148px minmax(0, 1fr); }

.campos__titulo {
  grid-column: 1 / -1; margin-top: 8px;
  font-size: 11px; font-weight: 600; letter-spacing: .12em;
  text-transform: uppercase; color: var(--muted);
}

/* ---------- Teléfono con lada ----------
   La lada va DENTRO del campo, no en uno aparte: son un solo dato y
   separarlos hace que la gente escriba el país dos veces. */
.campo-tel {
  display: flex; align-items: stretch;
  border: 1px solid var(--field); border-radius: var(--r);
  background: var(--hundido);
  transition: border-color .2s var(--curva);
}
.campo-tel:hover { border-color: var(--hairline-fuerte); }
.campo-tel:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }
.campo-tel select {
  width: auto; flex: none; border: 0; border-right: 1px solid var(--hairline);
  border-radius: var(--r) 0 0 var(--r); background: transparent;
  padding-inline: 11px 8px; color: var(--ink);
}
.campo-tel input { border: 0; background: transparent; border-radius: 0 var(--r) var(--r) 0; }
.campo-tel select { padding-block: 8px; }
.campo-tel select:focus-visible, .campo-tel input:focus-visible { outline: none; }

/* ---------- Contador de caracteres ----------
   Debajo y a la derecha del campo, discreto hasta que importa. */
/* Una cifra con su unidad al lado: "[3] veces". La unidad dentro de la
   etiqueta obliga a leerla dos veces, y de ayuda se lee como una frase suelta. */
.campo-sufijo { display: flex; align-items: center; gap: 8px; }
.campo-sufijo input { max-width: 96px; }
.campo-sufijo > span { color: var(--muted); font-size: 13px; }

.campo__pie { display: flex; justify-content: space-between; gap: 12px; }
.campo__contador { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }
.campo__contador[data-cerca="true"] { color: var(--aviso); }
.campo__contador[data-lleno="true"] { color: var(--mal); }

/* ---------- Separador con palabra ---------- */
.separador-o {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 14px;
  color: var(--muted); font-size: 12px;
}
.separador-o::before, .separador-o::after {
  content: ""; height: 1px; background: var(--hairline);
}

/* ---------- Búsqueda dentro de un formulario ---------- */
.campo-buscar { display: flex; align-items: center; gap: 9px; }
.campo-buscar .buscador { flex: 1; max-width: none; }

@media (max-width: 640px) {
  .campos--2, .campos--3, .campos--corto-largo { grid-template-columns: minmax(0, 1fr); }
}

/* =================================================================
 * La instrucción.
 *
 * Lo que le toca a la persona cuando la paquetería no expone la acción. No
 * sirve ninguno de los que ya hay: el diálogo confirma acciones NUESTRAS, la
 * franja describe un problema y el aviso afirma un hecho. Ninguno dicta un
 * procedimiento que ejecuta otra persona por otro canal, que es donde la capa
 * de en medio se hace visible sin mentir.
 *
 * Las dos ausencias se ven distinto porque llevan a acciones distintas: "no lo
 * hace" cierra el tema y se pinta en neutro; "no lo hemos confirmado" es una
 * llamada que el comerciante todavía puede hacer, y se pinta como lo que está
 * abierto.
 * ================================================================= */
.instruccion {
  display: grid; gap: 10px;
  padding: 14px 16px; border: 1px solid; border-radius: var(--r);
}
.instruccion > b { display: block; font-weight: 600; }
.instruccion ol { margin: 0; padding-left: 20px; display: grid; gap: 9px; }
.instruccion__paso { font-size: 13px; line-height: 1.55; }
/* El dato que hay que citar por teléfono: copiable y en monoespaciado, porque
   se dicta dígito por dígito. */
.instruccion__dato {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace; font-size: 12.5px;
  padding: 1px 6px; border-radius: var(--r-sm);
  background: var(--hundido-fuerte); color: var(--ink);
  user-select: all;
}
.instruccion--no { border-color: var(--hairline-fuerte); background: var(--hundido); }
.instruccion--no > b { color: var(--ink); }
.instruccion--sin-registro { border-color: var(--aviso-borde); background: var(--aviso-fondo); }
.instruccion--sin-registro > b { color: var(--aviso); }
.instruccion--sin-registro .instruccion__dato { background: var(--pagina); }

/* =================================================================
 * El cobro: la consecuencia primero, el porqué después.
 *
 * "Te cobran 6 kg" y debajo "pesa 4, pero una caja de 40 × 30 × 25 se cobra
 * como si pesara 6". Estaba escrito tres veces con estilos en línea dentro de
 * Plantillas, y un patrón repetido a mano deja de ser el mismo patrón, igual
 * que un color.
 * ================================================================= */
.cobro {
  display: grid; gap: 4px; padding: 11px 13px;
  border: 1px solid var(--hairline); border-radius: var(--r); background: var(--hundido);
}
.cobro__cifra { font-weight: 600; font-size: 14px; }
.cobro__porque { color: var(--muted); font-size: 12.5px; line-height: 1.5; }
.cobro .grupo-botones { margin-top: 4px; }
.cobro--aviso { border-color: var(--aviso-borde); background: var(--aviso-fondo); }
.cobro--aviso .cobro__cifra { color: var(--aviso); }
.cobro--mal { border-color: var(--mal-borde); background: var(--mal-fondo); }
.cobro--mal .cobro__cifra { color: var(--mal); }

/* =================================================================
 * La condición, leída dentro de una fila.
 *
 * "Cantidad 1 a 3 piezas", "Contiene MON-VEN-16". No es una pastilla —eso es
 * un estado— ni un `.dato` —eso es un par de etiqueta y valor—: es un
 * enunciado con rango, y no se lee bien como ninguno de los dos.
 * ================================================================= */
.condiciones { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 5px; }
.condicion {
  display: inline-flex; align-items: baseline; gap: 5px;
  padding: 2px 8px; border-radius: var(--r-sm);
  border: 1px solid var(--hairline); background: var(--pagina);
  color: var(--muted); font-size: 11.5px; line-height: 1.7;
}
.condicion b { color: var(--ink); font-weight: 500; }
/* Su SKU no aparece en ningún pedido reciente: la condición no se puede
   evaluar y la regla nunca va a ganar por ella. Apagada y marcada, no
   escondida. */
.condicion--sin-dato { border-style: dashed; border-color: var(--aviso-borde); }
.condicion--sin-dato b { color: var(--aviso); }

/* =================================================================
 * El orden, aplicado a las reglas de embalaje.
 *
 * Misma mecánica de arrastre, puesto y flechas que el orden de paqueterías,
 * porque es el mismo tipo de criterio humano y un segundo modelo mental para
 * el mismo problema es un modelo de más. Cambia la rejilla: una regla lleva
 * condiciones y caja donde una paquetería lleva papel.
 *
 * Los cortes repiten los del orden base y van DESPUÉS, porque tienen la misma
 * especificidad: escritos antes, el ancho de escritorio ganaría en el móvil.
 * ================================================================= */
/* La última columna mide 150px y no `auto`: cada fila es su propia rejilla, y
   la de por defecto —que no lleva flechas ni editar— dejaba esa columna en
   cero y repartía el sobrante entre las demás. Su caja y su motivo quedaban
   corridos respecto de todas las de arriba, en una lista cuyo trabajo es
   justamente compararse renglón a renglón. */
.orden--reglas, .orden__cabecera--reglas {
  --orden-cols: 18px 30px minmax(120px, 1.6fr) 150px minmax(140px, 1.4fr) 140px;
}
.orden--reglas .orden__fila::before { background: var(--hairline-fuerte); }
.orden--reglas .orden__quien b { display: block; }
.orden--reglas .orden__porque textarea { min-height: 38px; }

/* La caja y sus medidas: el nombre decide y la medida explica. */
.orden__caja select { width: 100%; }
.orden__caja .apagado { display: block; margin-top: 4px; font-size: 11px; }

/* Lo que la regla cobró va a lo ancho de la fila, debajo de todo: es una
   consecuencia de la fila entera, no de una de sus celdas. */
.orden__fila .cobro, .orden__fila .aviso { grid-column: 1 / -1; margin-top: 2px; }

/* La de por defecto no se mueve ni se borra: su condición está vacía y
   siempre se cumple, de modo que ningún pedido se queda sin caja. Se marca
   con la línea más tenue de la lista, no con una barra de estado. */
.orden__fila--defecto::before { background: var(--hairline); }
.orden__fila--defecto .orden__puesto { border-style: dashed; }

/* Entre 768 y 1023 no cabe la fila completa: sin el asa quedan cinco columnas y
   el contenido pedía 746px en un contenedor de 718. Se corta antes de que se
   note —el botón se leía "Edita" y el cobro se salía por la derecha— bajando
   los mínimos y apilando las flechas con el nombre, que es el mismo camino que
   ya toma el orden de paqueterías más abajo. */
@media (min-width: 768px) and (max-width: 1023px) {
  .orden--reglas, .orden__cabecera--reglas {
    --orden-cols: 18px 26px minmax(120px, 1.4fr) 130px minmax(120px, 1fr) 96px;
  }
  .orden--reglas .orden__fila { gap: 9px; padding-inline: 12px; }
  .orden__cabecera--reglas { padding-inline: 12px; }
  /* Tres botones no caben en 96px en una fila: se parten en dos renglones
     antes que recortarse a media palabra. */
  .orden--reglas .orden__mover { flex-wrap: wrap; justify-content: flex-end; }
}

@media (pointer: coarse), (max-width: 767px) {
  .orden--reglas, .orden__cabecera--reglas {
    --orden-cols: 30px minmax(150px, 1fr) 160px minmax(160px, 1fr) auto;
  }
}
@media (max-width: 767px) {
  .orden--reglas, .orden__cabecera--reglas { --orden-cols: 30px minmax(0, 1fr) auto; }
  .orden--reglas .orden__caja, .orden--reglas .orden__porque { grid-column: 2 / -1; }
  /* Texto y botón en un renglón dejaban el texto en una tira de una palabra
     por línea y el botón fuera de la tarjeta. En móvil se apilan. */
  .orden__fila .aviso { flex-direction: column; align-items: flex-start; }
  .orden__fila .aviso .boton { max-width: 100%; white-space: normal; text-align: left; }
}

/* =================================================================
 * El buscador de fichas.
 *
 * Devuelve REGISTROS PARA ELEGIR dentro de un formulario, que es algo que
 * ningún control del sistema hacía: el buscador de la barra superior encuentra
 * y lleva a otra pantalla, y un <select> necesita una lista cerrada. Aquí la
 * lista sale de los pedidos y crece sola.
 *
 * El nombre es neutro a propósito. Hoy busca productos; el mismo componente va
 * a buscar destinatarios, y una clase nombrada por uno de sus dos usos deja de
 * ser la misma clase. Por eso el tipo de fila —`.producto`— va aparte.
 *
 * El panel va en `position: fixed` y colocado por JS. Vive dentro del <dialog>
 * a propósito: un <dialog> abierto se pinta en la capa superior, y un panel
 * colgado del <body> quedaría DEBAJO del diálogo que lo abrió. Fijo y dentro
 * escapa además del scroll de `.panel__cuerpo`, que si no lo recortaría.
 * ================================================================= */
.buscador-ficha { position: relative; display: grid; gap: 6px; }

.buscador-ficha__panel {
  position: fixed; z-index: 80;
  max-height: min(52vh, 360px); overflow-y: auto;
  padding: 6px; border: 1px solid var(--hairline-fuerte); border-radius: var(--r-lg);
  background: var(--hundido); box-shadow: var(--sombra);
}
.buscador-ficha__vacio { padding: 12px 10px; }
.buscador-ficha__vacio b { display: block; font-size: 13px; font-weight: 500; }
.buscador-ficha__vacio .grupo-botones { margin-top: 10px; }

/* ---------- La fila de producto ----------
   El nombre identifica, el SKU confirma y el uso dice si el producto sigue
   vivo. Sin catálogo, el uso es lo único que distingue el que vendes hoy del
   que vendiste una vez hace un año, y es la diferencia que decide si una regla
   va a ganar alguna vez. */
.producto, .destinatario {
  display: block; width: 100%; text-align: left;
  padding: 8px 10px; border: 0; border-radius: var(--r-sm);
  background: transparent; color: inherit; font: inherit; cursor: pointer;
  transition: background .12s var(--curva);
}
.producto:hover, .producto:focus-visible,
.destinatario:hover, .destinatario:focus-visible { background: var(--hover); }
.producto:hover > b, .producto:focus-visible > b,
.destinatario:hover > b, .destinatario:focus-visible > b { color: var(--enlace); }
.producto > b, .destinatario > b { display: block; font-size: 13px; font-weight: 500; }
.producto__sku {
  font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  font-size: 12px; color: var(--muted);
}
.producto__uso, .destinatario__uso { color: var(--muted); font-size: 12px; }
.producto__sku + .producto__uso::before { content: " · "; }

/* ---------- La fila de destinatario ----------
   El mismo buscador con otra fuente. Aquí la ciudad hace el trabajo que hace
   el SKU en un producto: es lo que deja distinguir dos Arturo García. */
.destinatario__lugar { color: var(--muted); font-size: 12px; }
.destinatario__lugar + .destinatario__uso::before { content: " · "; }

/* Elegido: el campo enseña el producto, no su clave. */
.producto--elegido {
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px;
  padding: 9px 11px; border: 1px solid var(--field); border-radius: var(--r);
  background: var(--hundido); cursor: default;
}
.producto--elegido:hover { background: var(--hundido); }
.producto--elegido > b { display: inline; }
.producto--elegido .boton { margin-left: auto; }

/* Escrito a mano y todavía sin aparecer en ningún pedido. La marca se cura
   sola el día que entre en uno: lo mal escrito sigue marcado y lo que solo era
   nuevo deja de estarlo sin que nadie vuelva a tocar la regla. */
.producto--sin-ver { border-style: dashed; border-color: var(--aviso-borde); }
.producto--sin-ver .producto__uso { color: var(--aviso); }

@media (prefers-reduced-motion: reduce) { .producto, .destinatario { transition: none; } }

/* En angosto el panel no se ancla al campo: se sale a los bordes de la
   pantalla, igual que ya hace el panel de hallazgos. */
@media (max-width: 767px) {
  .buscador-ficha__panel { left: 12px !important; right: 12px; width: auto !important; }
}

/* =================================================================
 * Adaptable — SIEMPRE AL FINAL DEL ARCHIVO.
 *
 * Estas reglas tienen la misma especificidad que las de arriba, así que
 * ganan solo por venir después. Si alguien agrega un componente nuevo
 * al final, su regla base pisa el display:none de aquí y el componente
 * reaparece en móvil. Ya pasó con la insignia de la tienda.
 * ================================================================= */

.lateral__cerrar, .abrir-menu { display: none; }

@media (max-width: 1023px) {
  .armazon { grid-template-columns: minmax(0, 1fr); }
  .lateral {
    position: fixed; inset: 0 auto 0 0; z-index: 60; width: 272px;
    transform: translateX(-100%); transition: transform .25s var(--curva);
  }
  .lateral[data-abierto="true"] { transform: none; }
  .lateral__cerrar { display: inline-flex; margin-left: auto; }
  .abrir-menu { display: inline-flex; }
  .velo {
    position: fixed; inset: 0; z-index: 50; background: rgba(18, 28, 51, 0.5);
    backdrop-filter: blur(2px);
  }
  .rejilla--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

  /* La barra superior no da para seis cosas. Se queda con lo que sirve en un
     teléfono: abrir el menú, buscar y el aviso de que los datos son de ejemplo.
     El conmutador de empresa se reduce a su avatar y la tienda conectada se va:
     ya se ve en Inicio, y aquí empujaba al buscador fuera de la pantalla. */
  .insignia-tienda { display: none; }
  .superior__empresa { padding: 6px; }
  .superior__empresa > span:last-child { display: none; }
  .rejilla--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* -----------------------------------------------------------------
 * Acceso en angosto.
 *
 * El panel dividido no cabe por debajo de 1280, pero esconderlo entero
 * dejaba un formulario pelón sobre un fondo plano: sin marca, sin color
 * y sin la animación. Así que el arte no desaparece, se compacta y pasa
 * a ser la cabecera del formulario:
 *
 *   - el diagrama se queda, con sus pulsos, pero las fichas muestran
 *     solo el monograma; la geometría del SVG no cambia porque el alto
 *     de ficha y los huecos siguen siendo los mismos;
 *   - el resplandor verde pasa a verse sobre el fondo de la página;
 *   - se cae la bajada larga, que en un teléfono estorba antes del
 *     formulario.
 * --------------------------------------------------------------- */
@media (max-width: 1279px) {
  .auth { grid-template-columns: minmax(0, 1fr); }

  .auth__arte {
    padding: 40px 24px 0;
    border-right: 0;
    background: transparent; /* que el resplandor caiga sobre el fondo */
  }
  .auth__brillo { inset: -34% 0 auto 0; height: 560px; }
  .auth__brillo--verde { inset: -8% 0 auto 0; height: 420px; }

  .auth__panel {
    max-width: 420px; gap: 26px;
    align-items: center; text-align: center;
  }
  .auth__panel > img { align-self: center; }
  /* balance reparte las líneas en vez de dejar una huérfana. */
  .auth__contenido h2 { font-size: 23px; max-width: none; text-wrap: balance; }
  .auth__contenido p { display: none; } /* la bajada larga estorba aquí */
  .auth__lema { display: none; }

  /* Solo monogramas: el nombre no cabe y el sentido del diagrama se
     entiende igual — muchos entran, uno en medio, muchos salen. */
  .mini-red { max-width: 300px; margin: 26px auto 0; }
  .mini-red__col { flex: none; width: 42px; }
  .mini-red__ficha { justify-content: center; padding: 0; }
  .mini-red__nombre { display: none; }

  .auth__formulario { padding: 30px 24px 48px; }
}

@media (max-width: 767px) {
  .contenido { padding: 20px 16px 48px; }
  .superior { padding: 0 16px; gap: 10px; }
  .superior__empresa { display: none; }
  /* La insignia de la tienda ocupa el sitio que necesita el buscador, y en
     una pantalla de teléfono el buscador es lo único de esa barra que sirve
     para algo. */
  .insignia-tienda { display: none; }
  /* Con la campana y la cuenta en la barra, "Datos de ejemplo" dejaba al
     buscador en 40px: un icono donde el comentario de arriba dice que está lo
     único que sirve. El aviso se queda —es lo que evita tomar estos números
     por reales— pero en una palabra. */
  .solo-ancho { display: none; }
  .solo-angosto { display: inline; }
  .superior .buscador { flex: 1 1 auto; min-width: 120px; }
  /* A 360px el mínimo de 120px sacaba el avatar de la pantalla: el buscador
     cede lo que falta antes que cortar la cuenta. */
  @media (max-width: 400px) {
    .superior { gap: 8px; }
    .superior .buscador { min-width: 0; }
  }

  /* El panel de hallazgos no se ancla al buscador: anclado, hereda su ancho
     —116px medidos— y no cabe ni un folio. Se sale a la pantalla completa,
     debajo de la barra. */
  .hallazgos {
    position: fixed; top: calc(var(--superior) + 6px);
    left: 12px; right: 12px;
    max-height: calc(100dvh - var(--superior) - 24px);
  }
  /* Cuatro cifras cortas caben en dos columnas; una sola convierte el
     encabezado en una escalera de cuatro pantallazos. */
  .rejilla--2, .rejilla--3 { grid-template-columns: minmax(0, 1fr); }
  /* Objetivo táctil de 44px: los chips de 27px se fallan con el pulgar. */
  .periodo__mando .ficha-filtro { min-height: 44px; padding-inline: 14px; }

  /* Una barra de filtros en el móvil es una columna, no una fila que se
     parte: cada control tomaba el ancho de su texto y quedaban seis cajas de
     anchos distintos alineadas a la izquierda, como una escalera. */
  .filtros { gap: 8px; }
  .filtros .buscador,
  .filtros select { flex: 1 1 100%; width: 100%; min-width: 0; }
  .filtros select { max-width: none; }
  /* Las dos fechas sí comparten renglón: son un rango y se leen juntas. */
  .filtros .campo-fecha { flex: 1 1 40%; }
  .filtros .campo-fecha input { width: 100%; min-width: 0; }
  .filtros__div { display: none; }
  .filtros__sep { display: none; }
  .filtros .boton { flex: 1 1 100%; justify-content: center; }

  /* Una tabla de datos no se comprime hasta romper las palabras: se desplaza.
     Sin un ancho mínimo, "15 piezas sin recoger" salía en cuatro renglones de
     una palabra cada uno. */
  .tabla-caja table { min-width: 560px; }
  /* La bitácora lleva una frase de motivo en cada fila: con el mínimo general
     se rompe en dos palabras por renglón. Mejor desplazarse a lo ancho. */
  #tabla-corr { min-width: 760px; }
  .periodo__cabeza { gap: 12px; }
  .periodo__mando { margin-left: 0; width: 100%; }
  .definiciones > div { grid-template-columns: minmax(0, 1fr); gap: 3px; }
  .encabezado h1 { font-size: 20px; }
}

