/* Estilos de la aplicación. Un solo archivo: el proyecto no usa empaquetador,
   y partirlo obligaría a varias peticiones sin ganar nada a esta escala. */

:root {
  /* Medidas del armazón de la página. Están aquí y no repartidas porque el alto al
     que aparecen las ventanas modales se calcula a partir de ellas: si se ajustan
     en un solo sitio, todo lo que depende de ellas se mueve junto. */
  --pad-contenido: 22px;
  --alto-encabezado: 32px;
  --sep-encabezado: 18px;

  --tinta: #1f2933;
  --tinta-suave: #5c6b7a;
  --linea: #dfe4ea;
  --fondo: #f5f7fa;
  --papel: #ffffff;
  --acento: #0d7f8c;
  --acento-oscuro: #0a6572;
  --error: #a32626;
  --ok: #1e7a45;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font: 14px/1.5 -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  color: var(--tinta);
  background: var(--fondo);
}

a { color: var(--acento); text-decoration: none; }
a:hover { text-decoration: underline; }

/* ── Estructura ─────────────────────────────────────────── */

.marco { display: flex; min-height: 100vh; }

.lateral {
  width: 220px;
  flex: 0 0 220px;
  background: var(--tinta);
  color: #cfd8e0;
  padding: 18px 0;
  display: flex;
  flex-direction: column;
}

.marca {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .04em;
  color: #fff;
  padding: 0 18px 18px;
  border-bottom: 1px solid #33414f;
  margin-bottom: 12px;
}
.marca span { color: var(--acento); }

.lateral a {
  display: block;
  padding: 8px 18px;
  color: #cfd8e0;
  font-size: 13px;
}
.lateral a:hover { background: #2b3743; color: #fff; text-decoration: none; }
.lateral a.activo {
  background: #2b3743;
  color: #fff;
  box-shadow: inset 3px 0 0 var(--acento);
}

.grupo {
  margin: 16px 0 4px;
  padding: 0 18px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: #7d8b99;
}

/* margin-top:auto empuja el bloque al fondo sin fijar alturas. */
.pie-lateral {
  margin-top: auto;
  padding: 14px 18px 0;
  border-top: 1px solid #33414f;
}
.pie-lateral .quien { font-size: 13px; color: #fff; }
.pie-lateral .rol { font-size: 11px; color: #7d8b99; text-transform: capitalize; }

.salir {
  margin-top: 8px;
  background: none;
  border: 1px solid #4a5967;
  color: #cfd8e0;
  padding: 4px 10px;
  border-radius: 4px;
  font-size: 12px;
  cursor: pointer;
}
.salir:hover { background: #33414f; color: #fff; }

.contenido { flex: 1; padding: var(--pad-contenido) 28px; min-width: 0; }

.encabezado {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  /* El alto va fijo, y no lo decide el contenido, porque las ventanas modales se
     alinean con lo que hay debajo del encabezado (ver --modal-tope). Con un alto
     variable, el mismo diálogo quedaría a distinta altura en cada pantalla. */
  min-height: var(--alto-encabezado);
  margin-bottom: var(--sep-encabezado);
}
.encabezado h1 { font-size: 20px; margin: 0; }
.acciones { display: flex; gap: 8px; }

h2 { font-size: 15px; margin: 24px 0 10px; }

/* Título de sección con un botón al lado. El h2 conserva su margen, así que la
   fila se alinea por la base del texto y no queda el botón flotando arriba. */
.titulo-con-accion {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 10px;
}

/* ── Aviso flotante ─────────────────────────────────────── */

/* Aparece sobre la pantalla actual sin taparla: quien recibe el aviso conserva a la
   vista lo que estaba haciendo. Por eso no hay fondo oscuro ni <dialog> modal, que
   obligarían a atender el mensaje antes de poder seguir leyendo. */
.flotante {
  position: fixed;
  top: 16px;
  right: 16px;
  z-index: 60;
  display: flex;
  align-items: flex-start;
  gap: 10px;
  max-width: min(380px, calc(100vw - 32px));
  padding: 12px 14px;
  background: var(--papel);
  /* Franja del color de error a la izquierda: se reconoce como rechazo de un
     vistazo, sin pintar toda la tarjeta de rojo. */
  border-left: 4px solid var(--error);
  border-radius: 6px;
  box-shadow: 0 8px 24px rgba(31, 41, 51, 0.18);
}

.flotante strong { display: block; font-size: 13px; margin-bottom: 2px; }
.flotante p { margin: 0; font-size: 13px; color: var(--tinta-suave); }

.flotante-cerrar {
  flex: 0 0 auto;
  padding: 0 2px;
  border: 0;
  background: none;
  color: var(--tinta-suave);
  font-size: 13px;
  line-height: 1.4;
  cursor: pointer;
}

.flotante-cerrar:hover { color: var(--tinta); }

/* En pantallas angostas ocupa el ancho disponible: a la derecha quedaría encimado
   con el contenido. */
@media (max-width: 720px) {
  .flotante { top: 10px; right: 10px; left: 10px; max-width: none; }
}

/* ── Controles ──────────────────────────────────────────── */

.principal, button.principal {
  display: inline-block;
  background: var(--acento);
  color: #fff;
  border: 0;
  padding: 8px 14px;
  border-radius: 4px;
  font-size: 13px;
  cursor: pointer;
}
.principal:hover { background: var(--acento-oscuro); text-decoration: none; color: #fff; }

.aviso {
  padding: 9px 12px;
  border-radius: 4px;
  margin-bottom: 14px;
  font-size: 13px;
}
.aviso.error { background: #fdecea; color: var(--error); border: 1px solid #f3c4bf; }
.aviso.ok { background: #e9f6ee; color: var(--ok); border: 1px solid #bfe2cd; }

.ayuda { color: var(--tinta-suave); font-size: 12px; }
.vacio { color: var(--tinta-suave); padding: 24px 0; }
.derecha { text-align: right; }

/* ── Tarjetas y listados ────────────────────────────────── */

.tarjetas { display: flex; gap: 12px; flex-wrap: wrap; }

.tarjeta {
  background: var(--papel);
  border: 1px solid var(--linea);
  border-radius: 6px;
  padding: 14px 18px;
  min-width: 120px;
  color: var(--tinta);
}
.tarjeta:hover { border-color: var(--acento); text-decoration: none; }
.tarjeta .cifra { font-size: 24px; font-weight: 600; }
.tarjeta .etiqueta { font-size: 12px; color: var(--tinta-suave); }

/* Contadores por estado del listado de cotizaciones. Vinieron del panel, que se
   eliminó, y ahora además filtran: reemplazan a las pestañas, que hacían lo mismo
   sin decir cuántas hay. La activa se marca con el acento, igual que las pestañas
   de antes, para que se vea qué se está mirando. */
.contadores { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 14px; }
.contadores .tarjeta { flex: 0 1 auto; text-align: center; padding: 10px 16px; }
.contadores .tarjeta .cifra { font-size: 20px; }
.contadores .tarjeta.activa {
  border-color: var(--acento);
  box-shadow: inset 0 -3px 0 var(--acento);
}

/* overflow-x propio: una tabla ancha no debe desplazar la página entera. */
.listado {
  width: 100%;
  border-collapse: collapse;
  background: var(--papel);
  border: 1px solid var(--linea);
  border-radius: 6px;
  overflow-x: auto;
  display: block;
}
.listado thead, .listado tbody, .listado tr { display: table; width: 100%; table-layout: fixed; }
.listado th, .listado td {
  padding: 8px 10px;
  text-align: left;
  border-bottom: 1px solid var(--linea);
  font-size: 13px;
  overflow: hidden;
  text-overflow: ellipsis;
}
.listado th { background: #f0f3f6; font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--tinta-suave); }
.listado tbody tr:last-child td { border-bottom: 0; }

.chip {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 10px;
  font-size: 11px;
  background: #eef1f4;
  color: var(--tinta-suave);
}
.chip.estado-borrador { background: #eef1f4; }
.chip.estado-enviada { background: #e6f0fb; color: #1f4e9c; }
.chip.estado-aprobada { background: #e9f6ee; color: var(--ok); }
.chip.estado-rechazada { background: #fdecea; color: var(--error); }
.chip.estado-cancelada { background: #f0f0f0; color: #7d8b99; text-decoration: line-through; }

/* ── Pantallas públicas ─────────────────────────────────── */

.acceso {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.tarjeta-acceso {
  background: var(--papel);
  border: 1px solid var(--linea);
  border-radius: 8px;
  padding: 26px;
  width: 100%;
  max-width: 340px;
  display: flex;
  flex-direction: column;
}

.marca-acceso {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: .04em;
  margin-bottom: 18px;
  text-align: center;
}
.marca-acceso span { color: var(--acento); }

.tarjeta-acceso label {
  font-size: 12px;
  color: var(--tinta-suave);
  margin: 10px 0 4px;
}
.tarjeta-acceso input {
  padding: 8px 10px;
  border: 1px solid var(--linea);
  border-radius: 4px;
  font-size: 14px;
  font-family: inherit;
}
.tarjeta-acceso input:focus { outline: 2px solid var(--acento); outline-offset: -1px; }
.tarjeta-acceso .principal { margin-top: 18px; width: 100%; }

.enlace-menor {
  margin-top: 12px;
  font-size: 12px;
  text-align: center;
  color: var(--tinta-suave);
}

/* Portada de ingreso: marca a la izquierda, credenciales a la derecha. */
.portada {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  width: 100%;
  max-width: 860px;
  background: var(--papel);
  border: 1px solid var(--linea);
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 10px 30px rgba(31, 41, 51, .09);
}

.portada-marca {
  background: linear-gradient(160deg, var(--acento) 0%, var(--acento-oscuro) 100%);
  color: #fff;
  padding: 34px 30px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 12px;
}
.portada-marca h1 { margin: 4px 0 0; font-size: 19px; line-height: 1.35; }
.portada-marca p { margin: 0; font-size: 13px; line-height: 1.6; color: rgba(255, 255, 255, .88); }

/* Los logos son tinta oscura sobre transparente, así que van sobre una pastilla
   clara: sin ella se perderían contra el fondo de la columna. Comparten una sola
   pastilla en vez de una cada uno, para que se lean como el grupo que son. */
.portada-logos {
  display: flex;
  align-items: center;
  gap: 14px;
  background: var(--papel);
  border-radius: 6px;
  padding: 9px 12px;
  max-width: 100%;
  flex-wrap: wrap;
}

/* Se igualan por ALTO y no por ancho: sus proporciones son distintas (5.5 y 4.3),
   así que repartir el ancho por igual dejaría uno más alto que el otro. Con la
   misma altura se leen como una fila pareja y cada uno conserva su forma. */
.portada-logos img { display: block; height: 30px; width: auto; }

/* Dentro de la portada la tarjeta es la columna derecha, no una tarjeta suelta:
   cede su borde y su ancho máximo al contenedor. */
.portada .tarjeta-acceso {
  max-width: none;
  border: 0;
  border-radius: 0;
  padding: 30px 28px;
  justify-content: center;
}

.campo-clave { position: relative; display: flex; }
/* El relleno derecho reserva el hueco del botón para que el texto no pase debajo. */
.campo-clave input { flex: 1; min-width: 0; padding-right: 38px; }

.ojito {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 4px;
  background: none;
  color: var(--tinta-suave);
  cursor: pointer;
}
/* Sin esta regla el «display: flex» de arriba anularía el atributo «hidden» con
   el que el botón viaja hasta que ojito.js lo activa. */
.ojito[hidden] { display: none; }
.ojito:hover { color: var(--acento); }
.ojito:focus-visible { outline: 2px solid var(--acento); outline-offset: -2px; }
.ojito svg { width: 17px; height: 17px; }
.ojito .icono-ocultar { display: none; }
.ojito.viendo .icono-mostrar { display: none; }
.ojito.viendo .icono-ocultar { display: block; }

@media (max-width: 720px) {
  /* Las columnas se apilan y la banda de marca se comprime para que el
     formulario entre en pantalla sin desplazar. */
  .acceso { align-items: flex-start; padding: 14px; }
  .portada { grid-template-columns: 1fr; max-width: 420px; }
  .portada-marca { padding: 18px 20px; gap: 8px; }
  .portada-logos { padding: 7px 10px; gap: 10px; }
  .portada-logos img { height: 24px; }
  .portada-marca h1 { font-size: 16px; }
  .portada-marca p { font-size: 12px; }
  .portada .tarjeta-acceso { padding: 20px; }
}

/* Pantallas bajas (teléfono acostado): el texto de contexto es lo prescindible;
   lo que no puede quedar fuera de vista es el formulario. */
@media (max-height: 560px) {
  .portada-marca p { display: none; }
}

.pantalla-error { max-width: 480px; }
.pantalla-error h2 { margin-top: 0; }
.pantalla-error .principal { margin-top: 14px; }

/* ── Pantallas angostas ─────────────────────────────────── */

@media (max-width: 720px) {
  .marco { flex-direction: column; }
  .lateral { width: 100%; flex: none; }
  .pie-lateral { margin-top: 12px; }
  .contenido { padding: 16px; }
}

/* ── Fichas de catálogo ─────────────────────────────────── */

.fichas { display: flex; gap: 14px; flex-wrap: wrap; }

.ficha {
  background: var(--papel);
  border: 1px solid var(--linea);
  border-radius: 6px;
  overflow: hidden;
  width: 300px;
  color: var(--tinta);
}
.ficha:hover { border-color: var(--acento); text-decoration: none; }
.ficha .franja { height: 5px; }
.ficha .cuerpo { padding: 12px 14px; }
.ficha h3 { margin: 0 0 8px; font-size: 14px; }

.dato { font-size: 12px; color: var(--tinta); margin-bottom: 3px; }
.dato span {
  display: inline-block;
  min-width: 96px;
  color: var(--tinta-suave);
  text-transform: uppercase;
  font-size: 10px;
  letter-spacing: .05em;
}

/* ── Formularios ────────────────────────────────────────── */

.formulario { max-width: 720px; }

.formulario fieldset {
  background: var(--papel);
  border: 1px solid var(--linea);
  border-radius: 6px;
  padding: 14px 16px 16px;
  margin: 0 0 14px;
}
.formulario legend {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .06em;
  color: var(--tinta-suave);
  padding: 0 4px;
}

.formulario label {
  display: block;
  font-size: 12px;
  color: var(--tinta-suave);
  margin-bottom: 10px;
}
.formulario input,
.formulario textarea {
  display: block;
  width: 100%;
  margin-top: 3px;
  padding: 7px 9px;
  border: 1px solid var(--linea);
  border-radius: 4px;
  font: inherit;
  color: var(--tinta);
}
.formulario textarea { resize: vertical; }
.formulario input:focus,
.formulario textarea:focus { outline: 2px solid var(--acento); outline-offset: -1px; }
.formulario input[type="color"] { width: 60px; height: 32px; padding: 2px; }

/* Los cuatro encabezados de detalle van en una fila; se apilan si no caben. */
.cuatro { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }

.casilla { display: flex; align-items: center; gap: 8px; color: var(--tinta); }
.casilla input { width: auto; margin: 0; }

.muestra {
  display: inline-block;
  width: 14px;
  height: 14px;
  border-radius: 3px;
  border: 1px solid var(--linea);
  vertical-align: -2px;
  margin-right: 3px;
}

.botonera { display: flex; align-items: center; gap: 14px; }

@media (max-width: 720px) {
  .cuatro { grid-template-columns: repeat(2, 1fr); }
  .ficha { width: 100%; }
}

/* ── Variantes de botón ─────────────────────────────────── */

.secundario {
  display: inline-block;
  background: var(--papel);
  color: var(--tinta);
  border: 1px solid var(--linea);
  padding: 7px 13px;
  border-radius: 4px;
  font-size: 13px;
  cursor: pointer;
}
.secundario:hover { border-color: var(--acento); color: var(--acento); text-decoration: none; }

.peligro {
  background: var(--papel);
  color: var(--error);
  border: 1px solid #f3c4bf;
  padding: 7px 13px;
  border-radius: 4px;
  font-size: 13px;
  cursor: pointer;
}
.peligro:hover { background: #fdecea; }

/* ── Rejillas de contenido ──────────────────────────────── */

.tres { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }

.dos-columnas {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: 22px;
  align-items: start;
}

.filtros { margin-bottom: 12px; }
.filtros .casilla { font-size: 12px; color: var(--tinta-suave); }

/* Una fila de recurso dado de baja se atenúa, sin ocultar el dato. */
.listado tr.inactivo td { color: var(--tinta-suave); }
.listado tr.vigente td { background: #f2f9fa; font-weight: 600; }

@media (max-width: 900px) {
  .dos-columnas { grid-template-columns: 1fr; }
}
@media (max-width: 720px) {
  .tres { grid-template-columns: 1fr; }
}

/* ── Edición en línea dentro de un listado ──────────────── */

.en-linea { display: inline-flex; align-items: center; gap: 6px; margin: 0; }
.en-linea input { margin: 0; }

.enlace-boton {
  background: none;
  border: 0;
  padding: 0;
  color: var(--acento);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
  text-decoration: underline;
}
.enlace-boton:hover { color: var(--acento-oscuro); }

/* Iconos de fila. Nada flotante: las celdas de .listado recortan con overflow. */
.acciones-tarea { white-space: nowrap; }
.icono-boton {
  display: inline-block;
  background: none;
  border: 0;
  padding: 2px 4px;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  text-decoration: none;
}
.icono-boton:hover { text-decoration: none; opacity: 0.65; }
.acciones-tarea form { display: inline; }

.angosto { width: 200px; padding: 4px 7px; border: 1px solid var(--linea); border-radius: 4px; font: inherit; }
.minimo { width: 64px; padding: 4px 7px; border: 1px solid var(--linea); border-radius: 4px; font: inherit; }

code {
  font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
  font-size: 12px;
  background: #f0f3f6;
  padding: 1px 5px;
  border-radius: 3px;
}

/* ── Pestañas de filtro ─────────────────────────────────── */

.pestanas { display: flex; gap: 4px; flex-wrap: wrap; margin-bottom: 14px; }
.pestanas a {
  padding: 5px 11px;
  border: 1px solid var(--linea);
  border-radius: 14px;
  font-size: 12px;
  color: var(--tinta-suave);
  background: var(--papel);
}
.pestanas a:hover { border-color: var(--acento); color: var(--acento); text-decoration: none; }
.pestanas a.activa { background: var(--acento); border-color: var(--acento); color: #fff; }

.chip.vencida { background: #fdecea; color: var(--error); }

.aviso.info { background: #eef4fb; color: #1f4e9c; border: 1px solid #c9dcf3; }
.aviso.compacto { margin: 8px 0 0; padding: 7px 10px; font-size: 12px; }
.aviso.compacto ul { margin: 4px 0 4px 18px; padding: 0; }

/* ── Cabecera y totales de una cotización ───────────────── */

.cabecera-cotizacion {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 6px 18px;
  background: var(--papel);
  border: 1px solid var(--linea);
  border-radius: 6px;
  padding: 14px 16px;
}
.par { font-size: 13px; }
.par span {
  display: block;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--tinta-suave);
}

.asignaciones { margin: 6px 0 0 16px; padding: 0; font-size: 12px; color: var(--tinta-suave); }
.asignaciones li { margin-bottom: 2px; }

.totales {
  margin-top: 12px;
  margin-left: auto;
  border-collapse: collapse;
  min-width: 280px;
  background: var(--papel);
  border: 1px solid var(--linea);
  border-radius: 6px;
}
/* Filas apretadas a propósito: son cuatro cifras que se leen de un vistazo, no una
   tabla que se recorre. Con el alto de una fila de listado, el bloque ocupaba más
   pantalla que el detalle que resume. */
.totales td { padding: 3px 12px; font-size: 13px; border-bottom: 1px solid var(--linea); }
.totales tr:last-child td { border-bottom: 0; }
.totales tr.gran-total td { font-weight: 600; font-size: 15px; background: #f2f9fa; }

/* Barra de búsqueda y filtros del listado. Los campos se acomodan en una línea y
   bajan solos cuando no entran; el buscador es el que se estira, porque es el que
   se usa. */
.barra-filtros {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 10px 14px;
  margin: 0 0 14px;
  padding: 12px 14px;
  background: var(--papel);
  border: 1px solid var(--linea);
  border-radius: 6px;
}

.barra-filtros label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
  color: var(--tinta-suave);
}

.barra-filtros .busca { flex: 1 1 260px; }
.barra-filtros input, .barra-filtros select { font-size: 13px; padding: 6px 8px; }
.barra-filtros .acciones-filtro { display: flex; gap: 8px; align-items: center; }

/* Encabezados que ordenan: el enlace ocupa la celda para que el clic caiga en
   cualquier parte, y la columna activa se distingue del resto. */
.listado th a { color: inherit; text-decoration: none; display: block; }
.listado th a:hover { text-decoration: underline; }
.listado th.ordenando { color: var(--tinta); }
.listado th .flecha { margin-left: 4px; font-size: 11px; }

/* Listado de cotizaciones: el título en una sola línea.
   Las columnas de contenido conocido se fijan y la del título queda sin ancho, así
   que se lleva todo lo que sobra. Si aun así no entra, se recorta con puntos
   suspensivos en vez de partirse en dos renglones, y el texto completo sigue
   disponible en el `title` de la celda.

   Los anchos van por posición y no con un `<colgroup>`: en `.listado` cada `tr` es
   su propia tabla —así la tabla ancha scrollea sola—, y un colgroup no alcanza a
   las filas, queda decorativo. */
.listado-cotizaciones th:nth-child(1), .listado-cotizaciones td:nth-child(1) { width: 92px; }
.listado-cotizaciones th:nth-child(2), .listado-cotizaciones td:nth-child(2) { width: 190px; }
.listado-cotizaciones th:nth-child(4), .listado-cotizaciones td:nth-child(4) { width: 116px; }
.listado-cotizaciones th:nth-child(5), .listado-cotizaciones td:nth-child(5) { width: 104px; }
.listado-cotizaciones th:nth-child(6), .listado-cotizaciones td:nth-child(6) { width: 86px; }
.listado-cotizaciones th:nth-child(7), .listado-cotizaciones td:nth-child(7) { width: 78px; }
.listado-cotizaciones th:nth-child(8), .listado-cotizaciones td:nth-child(8) { width: 116px; }

.listado-cotizaciones td,
.listado-cotizaciones th {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Cierre de la cotización: eliminar a la izquierda y los totales a la derecha, a
   la misma altura. Los totales ya se empujan solos con su `margin-left: auto`, así
   que la fila no necesita repartir el espacio.

   `stretch` iguala el alto de los dos bloques: el más alto manda y el otro lo
   acompaña, en vez de quedar uno flotando corto al lado del otro. */
.fila-cierre {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  gap: 22px;
  margin-top: 12px;
}

/* El formulario de eliminar no debe estirarse a lo ancho hasta ocupar la fila: es
   una acción suelta, no un panel. A lo alto sí acompaña a los totales. */
.fila-cierre .formulario { flex: 0 1 380px; display: flex; }
.fila-cierre .formulario fieldset { flex: 1; display: flex; flex-direction: column; }

/* El botón queda abajo: el texto explica arriba y la acción cierra el bloque, a la
   altura del Total. */
.fila-cierre .formulario .botonera { margin-top: auto; }
.fila-cierre .totales { margin-top: 0; }

.dos { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; }

.formulario select {
  display: block;
  width: 100%;
  margin-top: 3px;
  padding: 7px 9px;
  border: 1px solid var(--linea);
  border-radius: 4px;
  font: inherit;
  background: var(--papel);
  color: var(--tinta);
}

@media (max-width: 720px) { .dos { grid-template-columns: 1fr; } }

/* Catálogo cerrado de formato para descripciones enriquecidas.
   Debe existir igual en cotizacion_imprimir.html y cotizacion_pdf.html:
   son las únicas clases que sanear() deja pasar. */
.rico p { margin: 0 0 4px; }
.rico ul, .rico ol { margin: 4px 0; padding-left: 18px; }
.rico .txt-sm { font-size: 0.85em; }
.rico .txt-md { font-size: 1em; }
.rico .txt-lg { font-size: 1.2em; }
.rico .txt-xl { font-size: 1.45em; }
.rico .c-negro { color: #1c2529; }
.rico .c-gris { color: #5c6670; }
.rico .c-rojo { color: #c0392b; }
.rico .c-azul { color: #1f5f9e; }
.rico .c-verde { color: #1e7d54; }
.rico .c-naranja { color: #c8791a; }

/* Editor de descripción. Sin capas flotantes: la barra y el lienzo van en
   flujo normal, así ninguna celda con overflow los recorta. */
.etiqueta-suelta { display: block; font-size: 12px; color: var(--tinta-suave); margin-bottom: 4px; }
.editor-rico { margin-bottom: 12px; }
.barra-formato {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  padding: 5px 6px;
  border: 1px solid var(--linea);
  border-bottom: 0;
  border-radius: 6px 6px 0 0;
  background: #f0f3f6;
}
.barra-formato button {
  min-width: 26px;
  padding: 3px 6px;
  border: 1px solid transparent;
  border-radius: 4px;
  background: none;
  font-size: 13px;
  cursor: pointer;
}
.barra-formato button:hover { border-color: var(--linea); background: #fff; }
/* Los selectores de la barra son controles de una fila, no campos del
   formulario: hay que deshacer el «block al 100%» que .formulario select
   les aplica, o se apilan a todo lo ancho y parten la barra en tres. */
.barra-formato select {
  display: inline-block;
  width: auto;
  margin-top: 0;
  font-size: 12px;
  padding: 2px 4px;
}
.barra-formato .separador { width: 1px; height: 18px; background: var(--linea); margin: 0 2px; }
.editor-rico .lienzo {
  min-height: 90px;
  padding: 8px 10px;
  border: 1px solid var(--linea);
  border-radius: 0 0 6px 6px;
  background: var(--papel);
  font-size: 13px;
  line-height: 1.5;
  overflow-y: auto;
}
.editor-rico .lienzo:focus { outline: 2px solid var(--acento); outline-offset: -2px; }

/* Quill toma el lienzo como contenedor y crea su propia zona editable dentro.
   Su hoja base trae tres cosas que hay que devolver a lo que ya tenía la
   aplicación: fuente Helvetica, `height: 100%` —que sobre un contenedor sin alto
   fijo colapsa la caja— y un relleno propio que se sumaría al del lienzo. */
.editor-rico .lienzo.ql-container {
  padding: 0;
  height: auto;
  font-family: inherit;
  font-size: inherit;
}

.editor-rico .lienzo .ql-editor {
  padding: 8px 10px;
  min-height: 90px;
  height: auto;
  line-height: 1.5;
  /* El texto se guarda como HTML, así que los saltos los dan las etiquetas: con
     `pre-wrap` los saltos del marcado se verían duplicados. */
  white-space: normal;
}

/* El foco ya no lo recibe el lienzo sino la zona editable de Quill. */
.editor-rico .lienzo:focus-within { outline: 2px solid var(--acento); outline-offset: -2px; }

/* Flujo de estados: hace visible la secuencia y el punto actual. */
.flujo-estado {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin: 0 0 6px;
  padding: 0;
  list-style: none;
}
.flujo-estado .paso {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px 4px 6px;
  border: 1px solid var(--linea);
  border-radius: 999px;
  font-size: 12px;
  color: var(--tinta-suave);
  background: var(--papel);
}
.flujo-estado .paso + .paso::before {
  content: "→";
  margin-right: 2px;
  color: var(--tinta-suave);
}
.flujo-estado .marca {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: #e6ebf0;
  font-size: 11px;
  font-weight: 700;
}
.flujo-estado .hecho { color: var(--tinta); }
.flujo-estado .hecho .marca { background: #cfe3d5; color: #1e7d54; }
.flujo-estado .actual {
  border-color: var(--acento);
  color: var(--tinta);
  font-weight: 700;
}
.flujo-estado .actual .marca { background: var(--acento); color: #fff; }
.flujo-estado .rechazada .marca,
.flujo-estado .cancelada .marca { background: #e8c4bf; color: #c0392b; }
.flujo-estado .desenlace { border-color: #e8c4bf; color: #c0392b; font-weight: 700; }
.flujo-nota { margin: 0 0 14px; }

/* Ventana flotante. <dialog> se pinta en la capa superior del navegador, así
   que ningún contenedor con overflow la recorta.

   Por lo mismo el navegador la centra en la pantalla, y una ventana corta
   quedaba flotando en el medio, lejos de los datos que explica. Se ancla al
   tope con el mismo desnivel que tiene el contenido de la página (padding del
   marco más el encabezado), para que salga a la altura de la ventana de datos
   de la ficha. */
.modal {
  /* Deriva del armazón en vez de ser un número medido a ojo: padding del contenido
     + alto del encabezado + su separación. Ajustar cualquiera de los tres mueve las
     ventanas con él, sin tener que recordar este cálculo. */
  --modal-tope: calc(var(--pad-contenido) + var(--alto-encabezado) + var(--sep-encabezado));
  width: min(720px, calc(100vw - 32px));
  /* Nunca más alta que la pantalla: el sobrante lo desplaza el cuerpo. */
  max-height: calc(100vh - var(--modal-tope) - 24px);
  margin: var(--modal-tope) auto auto;
  padding: 0;
  border: 1px solid var(--linea);
  border-radius: 10px;
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.28);
  color: var(--tinta);
}
/* El display va sobre [open] a propósito: `display` en `.modal` pisaría el
   `display: none` que el navegador le da al <dialog> cerrado y las ventanas se
   verían siempre. Con la columna flexible, la barra se lleva su alto y el
   cuerpo el resto, sin que nadie tenga que adivinar cuánto mide la barra. */
.modal[open] {
  display: flex;
  flex-direction: column;
}
@media (max-width: 720px) {
  /* En pantalla angosta el encabezado ya no roba altura: casi todo es ventana. */
  .modal { --modal-tope: 24px; }
}
.modal::backdrop { background: rgba(16, 24, 32, 0.45); }
.modal-barra {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 16px;
  border-bottom: 1px solid var(--linea);
  background: #f0f3f6;
  /* Conserva su alto aunque el cuerpo pida más espacio del que hay. */
  flex: 0 0 auto;
}
.modal-barra h3 { margin: 0; font-size: 14px; }
.modal-barra button {
  border: 0;
  background: none;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  padding: 2px 4px;
}
/* min-height:0 es lo que permite que un hijo flexible se encoja por debajo de su
   contenido; sin él el cuerpo empuja la ventana y el scroll nunca aparece. */
.modal-cuerpo { padding: 16px; overflow-y: auto; flex: 1 1 auto; min-height: 0; }
.modal-cuerpo h4 { margin: 18px 0 6px; font-size: 13px; }
.modal-cuerpo .formulario { margin: 0; }

/* Tabla de consulta dentro de una ventana: 80 filas se recorren con scroll en la
   propia tabla, no con paginación de botones.

   El POR QUÉ de descartar paginar: esto es una lista para mirar, no para
   navegar. Paginar obligaría a llevar el número de página en el servidor (y en
   la URL de la ficha) y a paginar también el total, que debe seguir siendo el
   de todas las filas y no el de las visibles — un total que cambia al pasar de
   página miente. Con scroll el encabezado y el total quedan fijos y el dato
   completo sigue siendo uno.

   El mismo contenedor se lleva los dos ejes: la tabla ancha se desplaza aquí
   dentro y la página nunca se corre en horizontal. */
.listado-desplazable {
  max-height: min(50vh, 420px);
  overflow: auto;
}
/* tfoot necesita `display: table` como thead y tbody (ver .listado): sticky no
   funciona sobre un table-footer-group. */
.listado-desplazable tfoot { display: table; width: 100%; table-layout: fixed; }
.listado-desplazable thead { position: sticky; top: 0; z-index: 2; }
.listado-desplazable tfoot { position: sticky; bottom: 0; z-index: 2; }
/* Fondo opaco: las filas pasan por debajo al desplazarse. */
.listado-desplazable tfoot th {
  background: #f0f3f6;
  border-top: 1px solid var(--linea);
  border-bottom: 0;
}

.lapiz-encabezado { align-self: start; }
.pie-cotizacion {
  display: grid;
  gap: 4px;
  margin: 0 0 18px;
  padding: 10px 12px;
  border: 1px solid var(--linea);
  border-radius: 6px;
  background: var(--papel);
  font-size: 13px;
}
.pie-cotizacion .par span {
  display: inline-block;
  min-width: 120px;
  color: var(--tinta-suave);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .04em;
}
/* El valor de varias líneas es un <span> más dentro de .par, así que hay que
   devolverle el aspecto de texto: la regla de arriba viste al rótulo. */
.pie-cotizacion .par .multilinea {
  display: inline-block;
  vertical-align: top;
  min-width: 0;
  color: inherit;
  font-size: inherit;
  text-transform: none;
  letter-spacing: normal;
  white-space: pre-line;
}

/* Asignaciones en rejilla, no en tabla: un <form> no puede ser hijo de <tr>.
   El recurso se lleva el espacio sobrante para que no se corte el nombre. */
.rejilla-asignaciones { display: grid; gap: 6px; }
.rejilla-asignaciones .fila {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 11rem 6rem auto;
  gap: 8px;
  align-items: center;
}
.rejilla-asignaciones .fila.encabezado {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--tinta-suave);
}
.rejilla-asignaciones select,
.rejilla-asignaciones input { width: 100%; min-width: 0; }
@media (max-width: 640px) {
  .rejilla-asignaciones .fila { grid-template-columns: 1fr 1fr; }
  .rejilla-asignaciones .fila.encabezado { display: none; }
}

/* Botón de formato activo bajo el cursor. */
.barra-formato button.activo {
  border-color: var(--acento);
  background: #fff;
  box-shadow: inset 0 0 0 1px var(--acento);
}
/* Los saltos del editor llegan como <div>: se ven como renglones. */
.rico div { min-height: 1em; }

/* Ficha de un recurso: resumen arriba y cada apartado detrás de un botón. */
.ficha {
  background: var(--papel);
  border: 1px solid var(--linea);
  border-radius: 6px;
  padding: 18px;
}

.datos-ficha {
  display: grid;
  /* Se acomodan solas: cuatro datos en pantalla ancha, dos o uno en angosta. */
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 14px 18px;
  margin: 0 0 18px;
}

.datos-ficha dt {
  font-size: 12px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--tinta-suave);
  margin-bottom: 3px;
}

.datos-ficha dd { margin: 0; font-size: 15px; }

.botonera-ficha {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding-top: 14px;
  border-top: 1px solid var(--linea);
}
