/* =====================================================================
   ClimIA — consola de trabajo
   ---------------------------------------------------------------------
   Desde el 23-sep-2026 el software se llama ClimIA y la app entera va en
   tema oscuro: navy profundo, cyan como acento, bordes finos. Doctor Frío
   es la primera empresa que lo usa, y por eso el documento que recibe el
   cliente —`.hoja`, más abajo— conserva su propia paleta clara y su
   Calibri: el papel es de la empresa, la herramienta es de ClimIA.

   Cómo está armado:

   - Los colores de marca van una sola vez, con su nombre (`--climia-*`).
     Todo lo demás de la hoja sigue pidiendo colores **por rol**
     —`--papel`, `--superficie`, `--tinta`, `--frio`, `--calor`…—, igual
     que antes del cambio. Por eso pasar a oscuro fue redefinir los roles
     y no reescribir cuatro mil líneas: una regla que pedía «la tinta
     principal» sigue pidiéndola, y ahora le llega el celeste claro.
   - El documento (`.hoja`) vuelve a definir esos mismos roles con los
     valores claros de siempre. Cualquier regla genérica —`th`, `a`, `p`,
     `h1`— que caiga adentro de una hoja se pinta clara sin saberlo.
   - El resplandor es escaso a propósito: la acción principal, lo activo,
     el total, el foco y la IA. Una herramienta que se usa ocho horas no
     puede ser un cartel luminoso.

   Tipografía: Inter para la interfaz y JetBrains Mono para cifras y
   códigos, servidas desde `/fuentes` y no desde Google. La app corre en
   la red local; una pantalla que cambia de letra cuando no hay internet
   no es una mejora.
   ===================================================================== */

@font-face {
  font-family: "Inter";
  src: url("/fuentes/inter-latin-wght-normal.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "JetBrains Mono";
  src: url("/fuentes/jetbrains-mono-latin-wght-normal.woff2") format("woff2");
  font-weight: 100 800;
  font-style: normal;
  font-display: swap;
}

:root {
  color-scheme: dark;

  /* ---------------------------------------------------------- la marca */
  --climia-bg-950:      #03111f;
  --climia-bg-900:      #06192b;
  --climia-surface-900: #071d31;
  --climia-surface-850: #0a243b;
  --climia-surface-800: #0c2b47;
  --climia-line-700:    #123c5d;
  --climia-line-600:    #0d5c8c;
  --climia-blue-500:    #087de8;
  --climia-cyan-400:    #12c8ff;
  --climia-cyan-300:    #00e5ff;
  --climia-text-primary:   #eaf8ff;
  --climia-text-secondary: #a8c8dc;
  --climia-text-muted:     #78a8c7;
  --climia-text-disabled:  #496d83;
  --climia-success: #35e8a0;
  --climia-warning: #ffc866;
  --climia-danger:  #ff6b7a;
  --climia-overlay: rgba(1, 12, 24, 0.72);

  --climia-gradient-panel: linear-gradient(180deg, rgba(12, 43, 71, 0.92), rgba(7, 29, 49, 0.96));
  --climia-gradient-brand: linear-gradient(90deg, #087de8 0%, #12c8ff 55%, #00e5ff 100%);
  --climia-gradient-accion: linear-gradient(180deg, #0b88d8, #0763a4);

  --climia-glow-soft:    0 0 0 1px rgba(18, 200, 255, 0.18), 0 0 18px rgba(18, 200, 255, 0.08);
  --climia-glow-active:  0 0 0 1px rgba(18, 200, 255, 0.45), 0 0 20px rgba(18, 200, 255, 0.18);
  --climia-glow-primary: 0 0 24px rgba(18, 200, 255, 0.28);

  /* La paleta del documento impreso, con su nombre propio. En la app ya
     no pinta nada —lo pinta ClimIA—, pero `.hoja` y un par de acentos
     heredados la siguen usando. */
  --azul-marino:   #0D3B66;
  --azul-inst:     #1B75BC;
  --celeste-fondo: #E2EDF7;
  --celeste-suave: #EDF3F9;
  --ambar-fondo:   #FFF3DC;
  --ambar-borde:   #E8A33D;
  --verde-fondo:   #E8F4E9;
  --verde-borde:   #4C9A51;
  --borde-ext:     #B9CFE3;
  --borde-int:     #D2E1EE;

  /* ------------------------------------------------------------ roles */
  --papel:        var(--climia-bg-950);
  --superficie:   var(--climia-surface-900);
  --superficie-2: var(--climia-surface-850);
  --superficie-3: var(--climia-surface-800);

  /* Tres pesos de texto, igual que antes: lo que hay que leer primero, la
     lectura normal y lo accesorio. */
  --tinta:        var(--climia-text-primary);
  --tinta-media:  var(--climia-text-secondary);
  --tinta-suave:  var(--climia-text-muted);
  --tinta-apagada: var(--climia-text-disabled);

  --linea:        var(--climia-line-700);
  --linea-fuerte: #174d70;

  /* Los acentos. Sobre fondo oscuro los «claros» dejan de ser un fondo
     pastel y pasan a ser el mismo color casi transparente: un velo que
     tiñe sin encender. El borde es un paso más visible que el velo. */
  --frio:         var(--climia-cyan-400);
  --frio-claro:   rgba(18, 200, 255, 0.10);
  --frio-borde:   rgba(18, 200, 255, 0.35);
  --calor:        var(--climia-warning);
  --calor-claro:  rgba(255, 200, 102, 0.10);
  --calor-claro-fuerte: rgba(255, 200, 102, 0.18);
  --calor-borde:  rgba(255, 200, 102, 0.40);
  --alerta:       var(--climia-danger);
  --alerta-claro: rgba(255, 107, 122, 0.10);
  --alerta-borde: rgba(255, 107, 122, 0.40);
  --ok:           var(--climia-success);
  --ok-claro:     rgba(53, 232, 160, 0.10);
  --ok-borde:     rgba(53, 232, 160, 0.35);

  /* La acción principal: el azul de marca en degradé, con letra blanca.
     El cyan queda para enlaces, foco y lo activo — un botón cyan con letra
     blanca no se lee. */
  --accion:        var(--climia-blue-500);
  --accion-hover:  #0a92f5;
  --sobre-accion:  #ffffff;

  /* Semáforo de las columnas de plata del catálogo: los mismos tres
     significados —costo, bolivianos, dólares—, en tonos que se leen sobre
     navy. */
  --plata-rojo:  #ff8a95;
  --plata-azul:  #5cc8ff;
  --plata-verde: var(--climia-success);

  /* Encabezados de tabla: una franja un paso más oscura que la tarjeta,
     con rótulos apagados. Lo que tiene que resaltar son los datos. */
  --cabecera:    rgba(6, 26, 44, 0.72);
  --th-texto:    #6fa9c8;

  --plomo:       #0a2238;

  --cebra:        rgba(255, 255, 255, 0.018);
  --fila-mouse:   rgba(18, 200, 255, 0.07);
  --fila-elegida: rgba(255, 200, 102, 0.10);

  --sombra: rgba(0, 0, 0, 0.45);

  /* Fondos y líneas de la pantalla de propuestas que en oscuro son velos
     sobre navy y en claro son superficies: van como roles para que el
     diseño claro los pueda cambiar. */
  --barra-prop-fondo: linear-gradient(180deg, rgba(6, 25, 43, 0.8), rgba(3, 17, 31, 0.74));
  --pie-fondo:        rgba(6, 25, 43, 0.84);

  /* El vidrio de ClimIA (23-sep-2026): el fondo dinámico está para verse,
     así que la barra lateral y las tarjetas lo dejan pasar. Sin
     backdrop-filter —con algo animado detrás se recalcularía en cada
     cuadro—: la transparencia sola, con la opacidad justa para que una
     tabla se siga leyendo. Los campos de texto quedan opacos. */
  --lateral-fondo: linear-gradient(180deg, rgba(6, 25, 43, 0.72), rgba(3, 17, 31, 0.8));
  --panel-vidrio:  linear-gradient(180deg, rgba(12, 43, 71, 0.66), rgba(7, 29, 49, 0.76));
  --velo:             rgba(3, 17, 31, 0.38);
  --velo-fuerte:      rgba(3, 17, 31, 0.8);
  --linea-tenue:      rgba(18, 60, 93, 0.68);
  --fila-mouse-items: rgba(9, 45, 72, 0.45);

  /* Alias que usaba la ficha del técnico y nunca existieron: quedaban en
     transparente sin que nadie lo notara. */
  --color-fondo-suave: var(--superficie-2);
  --color-principal:   var(--frio);
  --color-texto-suave: var(--tinta-suave);
  --color-borde:       var(--linea);

  --fuente: "Inter", "Segoe UI", system-ui, sans-serif;
  --prosa: var(--fuente);
  --mono: "JetBrains Mono", "Cascadia Mono", "Consolas", ui-monospace, monospace;

  /* Radios: controles, tarjetas y píldoras. `--r` es el de siempre y lo
     usan decenas de reglas: ahora vale lo de un control. */
  --r: 7px;
  --r-boton: 8px;
  --r-tarjeta: 12px;
  --r-panel: 14px;

  /* El armazón. */
  --ancho-lateral: 196px;
  --ancho-riel: 304px;
  --alto-cabecera: 0px;
}

@media screen and (max-width: 1439px) {
  :root { --ancho-lateral: 176px; --ancho-riel: 284px; }
}

@media screen and (max-width: 1023px) {
  :root { --alto-cabecera: 52px; }
}

/* ---------------------------------------------------------- diseño claro

   Parámetros → Diseño de la plataforma (desde el 23-sep-2026). ClimIA
   tiene dos diseños y los dos se mantienen: el oscuro, que es el de
   arriba, y el claro, que es el que tenía la app antes de ClimIA —celeste,
   azul institucional, Calibri—. El layout pone `data-tema="claro"` en
   `<html>` y este bloque redefine los mismos roles; ninguna regla de la
   hoja tiene que saber en qué diseño está.

   La barra lateral y la marca son las mismas en los dos. En claro la barra
   va en azul marino, como iba la franja de menú de antes: es donde el logo
   de ClimIA, que trae su fondo oscuro, se sigue viendo bien. */

:root[data-tema="claro"] {
  color-scheme: light;

  --climia-bg-950:      #E2EDF7;
  --climia-bg-900:      #ffffff;
  --climia-surface-900: #ffffff;
  --climia-surface-850: #EDF3F9;
  --climia-surface-800: #DCE7F1;
  --climia-line-700:    #D2E1EE;
  --climia-line-600:    #9DBBD6;
  --climia-blue-500:    #1B75BC;
  --climia-cyan-400:    #1B75BC;
  --climia-cyan-300:    #1B75BC;
  --climia-text-primary:   #0D3B66;
  --climia-text-secondary: #3D3D3D;
  --climia-text-muted:     #6B6B6B;
  --climia-text-disabled:  #9AA7B2;
  --climia-success: #3F8144;
  --climia-warning: #8A5A12;
  --climia-danger:  #A32A28;
  --climia-overlay: rgba(13, 59, 102, 0.35);
  --climia-gradient-panel:  linear-gradient(#ffffff, #ffffff);
  --climia-gradient-accion: linear-gradient(#1B75BC, #1B75BC);
  --climia-glow-soft:    0 0 0 0 transparent;
  --climia-glow-active:  0 0 0 0 transparent;
  --climia-glow-primary: 0 0 0 0 transparent;

  --papel:         #E2EDF7;
  --superficie:    #ffffff;
  --superficie-2:  #EDF3F9;
  --superficie-3:  #DCE7F1;
  --tinta:         #0D3B66;
  --tinta-media:   #3D3D3D;
  --tinta-suave:   #6B6B6B;
  --tinta-apagada: #9AA7B2;
  --linea:         #D2E1EE;
  --linea-fuerte:  #B9CFE3;

  --frio:          #1B75BC;
  --frio-claro:    #E2EDF7;
  --frio-borde:    #A8C9E6;
  --calor:         #8A5A12;
  --calor-claro:   #FFF3DC;
  --calor-claro-fuerte: #F3DCB6;
  --calor-borde:   #E9C68C;
  --alerta:        #A32A28;
  --alerta-claro:  #FBE7E6;
  --alerta-borde:  #EFC2C0;
  --ok:            #3F8144;
  --ok-claro:      #E8F4E9;
  --ok-borde:      #B4D9B7;

  --accion:        #1B75BC;
  --accion-hover:  #155F9B;
  --sobre-accion:  #ffffff;

  --plata-rojo:  #A32A28;
  --plata-azul:  #1B5FA0;
  --plata-verde: #2E7D51;

  --cabecera:    #1B75BC;
  --th-texto:    #ffffff;
  --plomo:       #D6E4F0;
  --cebra:       #EDF3F9;
  --fila-mouse:  #CFE2F2;
  --fila-elegida: #FFF3DC;
  --sombra:      rgba(15, 22, 29, 0.14);

  --barra-prop-fondo: #ffffff;
  --pie-fondo:        #ffffff;
  --lateral-fondo:    #0D3B66;
  --panel-vidrio:     #ffffff;
  --velo:             #FBFDFE;
  --velo-fuerte:      #ffffff;
  --linea-tenue:      #D2E1EE;
  --fila-mouse-items: #E2EDF7;

  --fuente: "Calibri", "Carlito", "Segoe UI", system-ui, sans-serif;
  --mono: "Cascadia Mono", "Consolas", ui-monospace, "SF Mono", "Menlo", monospace;

  --r: 3px;
  --r-boton: 3px;
  --r-tarjeta: 5px;
  --r-panel: 6px;
}

/* El cuerpo de antes: 14 px de Calibri, los 10,5 pt del documento.
   Con `:where()` para que pesen lo mismo que `body` y `table` a secas: si
   pesaran más, le ganarían a las tablas del documento (`.hoja table`,
   `.doc-tabla`) y el PDF saldría con otra letra. Pasó, y lo detectó la
   comparación contra `main`. */
:where(:root[data-tema="claro"]) body { font-size: 14px; }
:where(:root[data-tema="claro"]) table { font-size: 13.5px; }

/* La barra lateral en azul marino, con los tonos de la franja de antes. Los
   roles se redefinen sólo acá adentro: la barra es oscura en los dos
   diseños. */
:root[data-tema="claro"] .lateral {
  background: #0D3B66;
  border-right-color: #1D5B94;
  --tinta:         #ffffff;
  --tinta-media:   #BBD3E8;
  --tinta-suave:   #7FA3C4;
  --tinta-apagada: #7FA3C4;
  --linea:         #1D5B94;
  --linea-fuerte:  #1D5B94;
  --frio:          #8FCBFF;
  --frio-claro:    #154C80;
  --frio-borde:    #3C86C8;
  --superficie:    #0A3257;
  --superficie-2:  #154C80;
  --sombra:        rgba(0, 0, 0, 0.35);
}

/* El banner es una foto oscura: su texto va claro en los dos diseños. */
:root[data-tema="claro"] .riel-banner { --tinta: #ffffff; --frio: #8FCBFF; }

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--papel);
  color: var(--tinta-media);
  font-family: var(--fuente);
  /* 13,5 px de Inter ocupan lo que ocupaban los 14 px de Calibri, que es
     bastante más estrecha: con 14 las tablas del catálogo pasaban a
     necesitar scroll horizontal. El documento conserva sus 14 px de
     Calibri (ver `.hoja`). */
  font-size: 13.5px;
  line-height: 1.5;
  /* Lo que hacía falta de la monoespaciada: que 1.234,50 y 987,00
     ocupen lo mismo y las columnas de precio queden a plomo. */
  font-variant-numeric: tabular-nums;
}

p, .prosa { font-family: var(--prosa); }

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

:focus-visible {
  outline: 2px solid var(--frio);
  outline-offset: 2px;
}

/* ------------------------------------------------------ armazón ClimIA

   Barra lateral fija a la izquierda y el contenido al lado. La barra
   mide lo que la ventana y se desplaza sola si la lista de Configuración
   no entra: el contenido nunca se mueve por ella. */

.app {
  display: grid;
  grid-template-columns: var(--ancho-lateral) minmax(0, 1fr);
  min-height: 100vh;
}

.app__principal { min-width: 0; }

.lateral {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px 10px 12px;
  background:
    radial-gradient(120% 40% at 0% 0%, rgba(18, 200, 255, 0.07), transparent 60%),
    var(--lateral-fondo);
  border-right: 1px solid var(--linea);
  overflow-y: auto;
  overscroll-behavior: contain;
  z-index: 50;
  scrollbar-width: thin;
  scrollbar-color: var(--linea-fuerte) transparent;
}

.lateral__marca { display: block; padding: 0 4px; }
.lateral__marca img { display: block; width: 100%; height: auto; border-radius: 8px; }

/* El tipo de cambio, en su tarjeta: es un dato que manda sobre todos los
   precios de la app, y por eso se ve siempre. */
.lateral__tc {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 7px 9px;
  border: 1px solid var(--linea);
  border-radius: var(--r-boton);
  background: rgba(7, 29, 49, 0.6);
  color: var(--tinta-suave);
}

.lateral__tc:hover { text-decoration: none; border-color: var(--frio-borde); }
.lateral__tc:hover .digitos b { border-color: var(--frio-borde); }

.lateral__tc-rotulo,
.lectura__rotulo {
  font-size: 9.5px;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--tinta-suave);
}

.lectura__rotulo { margin-bottom: 5px; }

.lateral__nav { display: flex; flex-direction: column; gap: 2px; }

.lateral__nav a,
.lateral__grupo > summary {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 36px;
  padding: 0 10px;
  border: 1px solid transparent;
  border-radius: var(--r-boton);
  color: var(--tinta-media);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  list-style: none;
  user-select: none;
}

.lateral__grupo > summary::-webkit-details-marker { display: none; }
.lateral__icono { flex: none; color: var(--tinta-suave); }

.lateral__nav a:hover,
.lateral__grupo > summary:hover {
  color: var(--tinta);
  background: rgba(18, 200, 255, 0.05);
  text-decoration: none;
}

.lateral__nav a:hover .lateral__icono,
.lateral__grupo > summary:hover .lateral__icono { color: var(--frio); }

/* Lo activo: velo cyan, borde cyan y un resplandor contenido. Es uno de
   los pocos lugares donde se permite brillo: dice dónde se está. */
.lateral__nav > a[aria-current="page"],
.lateral__nav > .lateral__grupo > summary[aria-current="page"] {
  color: var(--tinta);
  background: linear-gradient(90deg, rgba(8, 125, 232, 0.32), rgba(18, 200, 255, 0.08));
  border-color: var(--frio-borde);
  box-shadow: var(--climia-glow-soft);
}

.lateral__nav > a[aria-current="page"] .lateral__icono,
.lateral__nav > .lateral__grupo > summary[aria-current="page"] .lateral__icono { color: var(--frio); }

/* La flecha del desplegable, dibujada con bordes: gira al abrir. */
.lateral__grupo > summary::after {
  content: "";
  width: 6px;
  height: 6px;
  margin-left: auto;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: rotate(-45deg);
  opacity: 0.6;
  transition: transform 120ms ease;
}

.lateral__grupo[open] > summary::after { transform: rotate(45deg); }

.lateral__sub {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin: 2px 0 6px 18px;
  padding-left: 10px;
  border-left: 1px solid var(--linea);
}

.lateral__sub a,
.lateral__grupo--hondo > summary {
  min-height: 30px;
  font-size: 12.5px;
  font-weight: 400;
  padding: 0 8px;
}

.lateral__sub a[aria-current="page"],
.lateral__grupo--hondo > summary[aria-current="page"] {
  color: var(--frio);
  background: var(--frio-claro);
  border-color: transparent;
}

.lateral__sub .lateral__sub { margin-left: 8px; }
.lateral__sub .lateral__sub a { overflow-wrap: anywhere; }

.lateral__rotulo {
  padding: 8px 8px 2px;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--tinta-apagada);
}

.lateral__vacio { padding: 6px 8px; font-size: 12px; color: var(--tinta-suave); }

.lateral__pie { margin-top: auto; display: flex; flex-direction: column; gap: 8px; }

.lateral__robot {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--r-tarjeta);
  border: 1px solid var(--linea);
}

/* En ventanas bajas el robot cede su lugar: primero está llegar a la
   cuenta sin scroll. */
@media screen and (max-height: 900px) { .lateral__robot { display: none; } }

.lateral__yo { position: relative; }

.lateral__yo > summary {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 8px;
  border: 1px solid var(--linea);
  border-radius: var(--r-boton);
  background: rgba(7, 29, 49, 0.6);
  cursor: pointer;
  list-style: none;
}

.lateral__yo > summary::-webkit-details-marker { display: none; }
.lateral__yo > summary:hover,
.lateral__yo[open] > summary { border-color: var(--frio-borde); }

.lateral__avatar {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  flex: none;
  border-radius: 50%;
  border: 1px solid var(--frio-borde);
  background: var(--superficie-2);
  color: var(--frio);
  font-size: 11.5px;
  font-weight: 700;
}

.lateral__quien { display: flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.lateral__quien b { font-size: 12.5px; font-weight: 600; color: var(--tinta); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lateral__quien small { font-size: 11px; color: var(--tinta-suave); }

/* El menú de la cuenta abre hacia arriba: está al pie de la barra. */
.lateral__menu-yo {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(100% + 6px);
  padding: 5px;
  background: var(--superficie-2);
  border: 1px solid var(--linea-fuerte);
  border-radius: var(--r-boton);
  box-shadow: 0 10px 28px var(--sombra);
}

.lateral__menu-yo a,
.lateral__menu-yo button {
  display: block;
  width: 100%;
  padding: 7px 9px;
  font: inherit;
  font-size: 12.5px;
  text-align: left;
  color: var(--tinta-media);
  background: none;
  border: none;
  border-radius: 6px;
  cursor: pointer;
}

.lateral__menu-yo a:hover,
.lateral__menu-yo button:hover { background: var(--frio-claro); color: var(--tinta); text-decoration: none; }

/* ------------------------------------------------ el menú contraído

   La flechita asoma sobre el borde derecho de la barra, a la altura del
   tipo de cambio: se encuentra sin buscarla y no compite con nada. Va
   `fixed` porque la barra se desplaza sola y recortaría lo que asoma. */
.lateral__plegar {
  position: fixed;
  top: 108px;
  left: calc(var(--ancho-lateral) - 12px);
  z-index: 55;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  padding: 0;
  color: var(--tinta-suave);
  background: var(--superficie-2);
  border: 1px solid var(--linea-fuerte);
  border-radius: 50%;
  cursor: pointer;
  opacity: 0.75;
  transition: opacity 120ms ease, color 120ms ease, border-color 120ms ease;
}

.lateral__plegar:hover,
.lateral__plegar:focus-visible { opacity: 1; color: var(--frio); border-color: var(--frio-borde); }
.lateral__plegar svg { transition: transform 160ms ease; }

/* Contraído: 68 px, sólo íconos. El nombre de cada sección sigue ahí para
   el lector de pantalla, y al pasar el mouse sale en el `title`. */
/* Sólo desde 1024 px: más angosto, la barra es un panel que se abre
   entero y la preferencia de contraerla no aplica. */
@media screen and (min-width: 1024px) {
  :root[data-lateral="plegado"] { --ancho-lateral: 68px; }
  :root[data-lateral="plegado"] .lateral__plegar svg { transform: rotate(180deg); }

  :root[data-lateral="plegado"] .lateral { padding: 14px 8px 12px; }

  /* Del logo queda el emblema: la parte izquierda del archivo. */
  :root[data-lateral="plegado"] .lateral__marca { padding: 0; height: 38px; overflow: hidden; border-radius: 8px; }
  :root[data-lateral="plegado"] .lateral__marca img { width: 150px; max-width: none; margin: -6px 0 0 -9px; border-radius: 0; }

  :root[data-lateral="plegado"] .lateral__tc { flex-direction: column; gap: 1px; padding: 5px 2px; }
  :root[data-lateral="plegado"] .lateral__tc-rotulo { font-size: 8px; letter-spacing: 0.04em; }
  :root[data-lateral="plegado"] .lateral__tc .digitos { gap: 0; }
  :root[data-lateral="plegado"] .lateral__tc .digitos b { min-width: 0; padding: 0; font-size: 11.5px; background: none; border: none; }

  :root[data-lateral="plegado"] .lateral__nav a,
  :root[data-lateral="plegado"] .lateral__grupo > summary { justify-content: center; padding: 0; }

  :root[data-lateral="plegado"] .lateral__nav span,
  :root[data-lateral="plegado"] .lateral__quien {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
  }

  :root[data-lateral="plegado"] .lateral__grupo > summary::after,
  :root[data-lateral="plegado"] .lateral__sub,
  :root[data-lateral="plegado"] .lateral__robot { display: none; }

  :root[data-lateral="plegado"] .lateral__yo > summary { justify-content: center; padding: 6px 0; }
  :root[data-lateral="plegado"] .lateral__menu-yo { right: auto; width: 170px; }
}

@media screen and (max-width: 1023px) {
  .lateral__plegar { display: none; }
}

.lateral__velo[hidden] { display: none; }

/* La cabecera angosta sólo existe debajo de 1024 px. */
.movil { display: none; }

@media screen and (max-width: 1023px) {
  .app { grid-template-columns: minmax(0, 1fr); }

  .lateral {
    position: fixed;
    left: 0;
    top: 0;
    bottom: 0;
    width: 264px;
    transform: translateX(-102%);
    transition: transform 160ms ease;
    box-shadow: 0 0 40px var(--sombra);
    z-index: 70;
  }

  .lateral-abierta .lateral { transform: none; }

  .lateral__velo {
    position: fixed;
    inset: 0;
    z-index: 65;
    background: var(--climia-overlay);
  }

  .movil {
    position: sticky;
    top: 0;
    z-index: 45;
    display: flex;
    align-items: center;
    gap: 12px;
    height: var(--alto-cabecera);
    padding: 0 12px;
    background: var(--climia-bg-900);
    border-bottom: 1px solid var(--linea);
  }

  .movil__menu {
    display: grid;
    place-items: center;
    width: 38px;
    height: 38px;
    color: var(--tinta);
    background: none;
    border: 1px solid var(--linea);
    border-radius: var(--r-boton);
    cursor: pointer;
  }

  .movil__marca { font-size: 19px; font-weight: 800; letter-spacing: -0.01em; color: var(--tinta); }
  .movil__marca b { color: var(--frio); }
  .movil__marca:hover { text-decoration: none; }
  .movil__tc { margin-left: auto; font-family: var(--mono); font-size: 13px; color: var(--tinta); }
  .movil__tc small { font-family: var(--fuente); font-size: 10px; color: var(--tinta-suave); }
}

/* Los dígitos del tipo de cambio, en tamaño de lectura. Es el formato de
   la pantalla de impacto, donde el número es el asunto de la página. */
.digitos { display: flex; gap: 2px; }

.digitos b {
  display: block;
  min-width: 25px;
  padding: 3px 0 5px;
  text-align: center;
  font-family: var(--mono);
  font-size: 26px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.01em;
  color: var(--tinta);
  background: var(--superficie-2);
  border: 1px solid var(--linea);
  border-radius: 4px;
}

.digitos b.sep {
  min-width: 12px;
  background: none;
  border-color: transparent;
  color: var(--tinta-suave);
}

.digitos--fantasma b { opacity: 0.45; }

/* En la barra el número es referencia, no tema: entra chico. */
.lateral__tc .digitos b {
  min-width: 15px;
  padding: 2px 0 3px;
  font-size: 14px;
  background: var(--superficie);
}

.lateral__tc .digitos b.sep { min-width: 6px; background: none; }

/* La franja de lectura de la pantalla de impacto. */
.tablero {
  display: flex;
  align-items: flex-end;
  gap: 28px;
  flex-wrap: wrap;
}

/* ------------------------------------------------------------ contenido */

/* 1760 px: el ancho útil de ClimIA en un monitor de 1920 con la barra
   lateral al costado. Más ancho, las filas de las tablas se leen mal. */
.contenido {
  padding: 22px 28px 64px;
  max-width: 1760px;
}

/* --------------------------------------------------------------- textos */

h1 {
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -0.01em;
  /* Marino, como los títulos del documento: hasta ahora heredaba el
     gris del cuerpo y el título de pantalla no pesaba más que una
     fila de la tabla. */
  color: var(--tinta);
  margin: 0 0 4px;
}

h2 {
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--tinta-suave);
  font-weight: 600;
  margin: 0 0 10px;
}

.bajada {
  font-family: var(--prosa);
  color: var(--tinta-media);
  margin: 0 0 20px;
  max-width: 68ch;
}

.encabezado {
  display: flex;
  align-items: flex-start;
  gap: 20px;
  margin-bottom: 18px;
}

.encabezado > :first-child { flex: 1; min-width: 0; }

/* Encabezado de los informes: título, conteo, columnas y alta en una sola
   línea. Sin bajada y sin cabecera de bloque, la tabla arranca ~90 px más
   arriba y entran tres o cuatro productos más en la primera pantalla. */
.encabezado--compacto { align-items: center; margin-bottom: 12px; }

.encabezado__barra {
  display: flex;
  align-items: center;
  gap: 12px;
  flex: none;
}

.conteo { font-size: 11.5px; color: var(--tinta-media); white-space: nowrap; }
.conteo b { color: var(--tinta); font-weight: 600; }

/* La X de las pantallas que son un desvío: se entra a hacer una cosa y se
   vuelve de donde se vino. Arriba a la derecha, donde se la busca. */
.cerrar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  flex: none;
  color: var(--tinta-suave);
  border: 1px solid var(--linea-fuerte);
  border-radius: 2px;
  background: var(--superficie);
}

.cerrar:hover {
  color: var(--climia-bg-950);
  background: var(--alerta);
  border-color: var(--alerta);
  text-decoration: none;
}

/* -------------------------------------------------------------- bloques */

.bloque {
  background: var(--climia-gradient-panel);
  border: 1px solid var(--linea);
  border-radius: var(--r-tarjeta);
  margin-bottom: 20px;
}

.bloque__cabeza {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 11px 16px;
  border-bottom: 1px solid var(--linea);
}

.bloque__cabeza h2 { margin: 0; }
.bloque__cabeza .derecha { margin-left: auto; }

.bloque__cuerpo { padding: 16px; }

.rejilla {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 20px;
}

/* --------------------------------------------------------------- cifras */

.cifra__rotulo {
  font-size: 9.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--tinta-suave);
  margin-bottom: 4px;
}

.cifra__valor { font-size: 21px; font-weight: 600; line-height: 1.15; }
.cifra__pie { font-size: 11px; color: var(--tinta-media); margin-top: 3px; }

/* --------------------------------------------------------------- tablas */

/* Una fila que el filtro escondió. El navegador ya lo hace solo con el
   atributo `hidden`, pero el `display: table-row` de su propia hoja de
   estilos anda cerca en especificidad y no conviene depender de quién
   gana: se dice explícito. */
tbody tr[hidden] { display: none; }

.tabla-marco { overflow-x: auto; }

table {
  width: 100%;
  border-collapse: collapse;
  /* 13 px de Inter: la barra lateral de ClimIA le quita a las tablas unos
     200 px de ancho, y Inter es más ancha que Calibri. Con el cuerpo de
     antes el catálogo perdía dos columnas de precio de la vista. */
  font-size: 13px;
}

th {
  text-align: left;
  font-size: 10px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--th-texto);
  background: var(--cabecera);
  font-weight: 700;
  padding: 8px 10px;
  border-bottom: 1px solid var(--cabecera);
  white-space: nowrap;
}

td {
  padding: 8px 10px;
  border-bottom: 1px solid var(--linea);
  vertical-align: baseline;
}

tbody tr:last-child td { border-bottom: none; }

/* Estados de fila, en orden de precedencia creciente. Todos pintan la
   celda y no el `tr`, porque el fondo del `tr` queda por debajo del de
   las celdas y no se vería. */
tbody tr:nth-child(even) td { background: var(--cebra); }
tbody tr:hover td { background: var(--fila-mouse); }
tbody tr.fila--elegida td { background: var(--fila-elegida); }

.num { text-align: right; white-space: nowrap; }
th.num { text-align: right; }

/* Las columnas de plata van centradas, encabezado y valores. Los importes
   ya vienen redondeados a entero, así que no hay comas que alinear: el
   centrado deja cada columna como un bloque parejo y hace más fácil
   recorrerlas de izquierda a derecha comparando proveedores. */
.moneda, th.moneda { text-align: center; white-space: nowrap; }

/* El valor derivado se ve derivado: la moneda de origen es la verdad. */
.derivado { color: var(--tinta-suave); }
.origen { font-weight: 600; }

/* ------------------------------------------------- semáforo del catálogo

   En el catálogo el color no decora: dice qué clase de número es cada
   columna, de un vistazo y sin leer el encabezado.

     rojo  = lo que se paga (costo)
     azul  = lo que se cobra en bolivianos
     verde = lo que se cobra en dólares

   La negrita marca, dentro de cada familia, la variante con factura.
   Gana sobre .derivado porque acá manda la clase de número, no de dónde
   se derivó. */

.plata-costo      { color: var(--plata-rojo); }
.plata-costo-iva  { color: var(--plata-rojo); font-weight: 700; }
.plata-bob        { color: var(--plata-azul); }
.plata-bob-iva    { color: var(--plata-azul); font-weight: 700; }
.plata-usd        { color: var(--plata-verde); }
.plata-usd-iva    { color: var(--plata-verde); font-weight: 700; }

/* La utilidad es el número que el operador busca, así que se destaca el
   valor y no el encabezado: la franja verde recorre la columna hacia
   abajo y se lee de un saque cuánto deja cada equipo. Sólo se pinta
   cuando hay utilidad calculada; un guión o un "sin regla" van sobrios.

   Los selectores llevan `tbody tr` adelante para pesar lo mismo que la
   cebra y los estados de fila, que están más arriba en la hoja: sin eso
   la franja verde desaparecería en las filas pares. */
/* Sobre navy la franja es un velo verde con la cifra en verde, y no un
   verde lleno con letra blanca: con el verde de ClimIA, que es claro, el
   blanco encima no se leía. */
tbody tr td.plata-utilidad {
  background: rgba(53, 232, 160, 0.13);
  color: var(--plata-verde);
  font-weight: 700;
}

td.plata-utilidad .sub,
td.plata-utilidad .derivado { color: var(--tinta-media); }

/* El hover y la selección pintan la fila; la utilidad mantiene su verde
   y sólo cambia de tono para acompañar el resaltado. */
tbody tr:hover td.plata-utilidad { background: rgba(53, 232, 160, 0.2); }
tbody tr.fila--elegida td.plata-utilidad { background: rgba(53, 232, 160, 0.28); }

.sub { display: block; font-size: 10.5px; color: var(--tinta-suave); }

/* El último mensaje de una conversación (panel de WhatsApp) puede ser
   un párrafo entero: se corta en una línea, con el resto disponible al
   pasar el mouse, en vez de estirar la fila o desbordar la tabla. */
.celda-recorte {
  max-width: 260px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Lápiz al lado del SKU: lleva a editar el producto sin pasar por la
   ficha. Se mantiene tenue hasta que el mouse entra en la fila, para no
   competir con los números, que son el motivo de la tabla. */
.lapiz {
  display: inline-flex;
  vertical-align: -2px;
  margin-left: 5px;
  color: var(--tinta-suave);
  opacity: 0.45;
}

tbody tr:hover .lapiz { opacity: 1; color: var(--frio); }
.lapiz:hover { color: var(--frio); opacity: 1; text-decoration: none; }

/* ------------------------------------------------- ancho de las columnas

   Cada encabezado lleva un tirador invisible en su borde derecho. Al
   primer arrastre la tabla congela los anchos que tenía en ese momento
   (`table-layout: fixed` más un ancho total explícito) y a partir de ahí
   cada columna vale lo que el operador diga; el marco se encarga del
   scroll horizontal si la suma pasa el ancho de la pantalla. */

th { position: relative; }

.redim {
  position: absolute;
  top: 0;
  right: -3px;
  width: 7px;
  height: 100%;
  cursor: col-resize;
  z-index: 2;
  user-select: none;
}

/*
 * El tirador para cambiar el ancho de una columna.
 *
 * Va blanco y no en el azul de acento: desde que el encabezado de tabla
 * usa el mismo azul institucional que los acentos de la app, un tirador
 * de ese color era azul sobre azul y no se veía. Blanco sobre el azul
 * del encabezado es el único par que se lee siempre.
 *
 * Se muestra apenas siempre, para que se sepa que se puede arrastrar, y
 * pasa a blanco pleno al apuntarlo o mientras se arrastra.
 */
.redim::after {
  content: "";
  position: absolute;
  top: 25%;
  left: 2px;
  width: 2px;
  height: 50%;
  background: rgba(255, 255, 255, 0.35);
}

.redim:hover::after,
.redim--activo::after {
  top: 0;
  height: 100%;
  background: #fff;
}

/* Con anchos fijos el contenido más largo que la columna se recorta en
   vez de empujar a las vecinas. */
table.anchos-fijos td,
table.anchos-fijos th { overflow: hidden; }
table.anchos-fijos .sub { text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }

/* Mientras se arrastra, el cursor no cambia al pasar sobre el texto ni
   se selecciona media tabla sin querer. */
body.redimensionando { cursor: col-resize; user-select: none; }

.vacio {
  padding: 34px 16px;
  text-align: center;
  color: var(--tinta-media);
  font-family: var(--prosa);
}

.vacio strong { display: block; font-weight: 600; color: var(--tinta); margin-bottom: 6px; }

/* ----------------------------------------------------------------- tags */

.tag {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 5px;
  font-weight: 600;
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  border: 1px solid var(--linea-fuerte);
  color: var(--tinta-media);
  background: var(--superficie-2);
  white-space: nowrap;
}

.tag--usd  { color: var(--frio);  background: var(--frio-claro);  border-color: var(--frio-borde); }
.tag--bob  { color: var(--calor); background: var(--calor-claro); border-color: var(--calor-borde); }
.tag--ok   { color: var(--ok);    background: var(--ok-claro);    border-color: var(--ok-borde); }
.tag--aviso{ color: var(--calor); background: var(--calor-claro); border-color: var(--calor-borde); }
.tag--alto { color: var(--alerta);background: var(--alerta-claro); border-color: var(--alerta-borde); }
.tag--mejor{ color: var(--ok);    background: var(--ok-claro);    border-color: var(--ok-borde); }
/* Para qué sirve algo, no cómo le va: el rol de una foto, por ejemplo. */
.tag--rol  { color: var(--frio);  background: var(--frio-claro);  border-color: var(--frio-borde); }
/* Dado de baja: apagado y no rojo. No es un problema que haya que
   atender, es un producto que alguien sacó del catálogo a propósito. */
.tag--baja { color: var(--tinta-media); background: var(--superficie-2); border-color: var(--linea-fuerte); }

/* Estados de una cotización. */
.tag--borrador  { color: var(--tinta-media); background: var(--superficie-2); border-color: var(--linea-fuerte); }
.tag--enviada   { color: var(--frio);   background: var(--frio-claro);   border-color: var(--frio-borde); }
.tag--aceptada  { color: var(--ok);     background: var(--ok-claro);     border-color: var(--ok-borde); }
.tag--rechazada { color: var(--alerta); background: var(--alerta-claro); border-color: var(--alerta-borde); }

/* Lo que pidió el cliente, en la lista de servicios: una línea recortada.
   Sin el tope, una descripción larga estira la columna y las cifras de
   plata —que son la razón de ser de la tabla— se van fuera de la
   pantalla. El texto completo va en el `title` y en la ficha. */
.celda-pedido {
  max-width: 260px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--tinta-media);
}

/* Estados de una orden de servicio.

   Éstos van rellenos y con letra blanca, al revés que el resto de los
   tags de la app —que son fondo pálido y letra del color—. Es a
   propósito: el estado del trabajo es la columna que se barre con la
   vista en una lista de treinta órdenes para encontrar las que faltan
   hacer, y un tag pálido se pierde entre las demás celdas.

   Los tonos no son los «claros» de la paleta sino un paso más oscuros.
   El pedido era fondo claro con letra blanca, y eso no se puede tener
   las dos cosas: blanco sobre #E8F4E9 es ilegible. Se conservó el matiz
   —verde, rojo, naranja, celeste, azul— y se bajó la luminosidad hasta
   donde el blanco se lee. Sobre fondo blanco de tabla siguen leyéndose
   como colores claros. */
.tag--solicitada { color: #fff; background: #E8934A; border-color: #D67F33; }
.tag--agendada   { color: #fff; background: #4FA8D8; border-color: #3691C4; }
.tag--en_curso   { color: #fff; background: #2D6FA8; border-color: #1F5B8F; }
.tag--realizada  { color: #fff; background: #57A85C; border-color: #43904A; }
.tag--anulada    { color: #fff; background: #D26A63; border-color: #BC534C; }

/* Notas al pie de una pantalla: lo que conviene saber, pero no antes de
   trabajar. Van sobrias a propósito; un aviso de color arriba compite con
   el contenido cada vez que se entra. */
.notas {
  margin-top: 26px;
  padding-top: 14px;
  border-top: 1px solid var(--linea);
  max-width: 760px;
}

.notas p {
  font-family: var(--prosa);
  font-size: 11.5px;
  line-height: 1.55;
  color: var(--tinta-media);
  margin: 0 0 8px;
}

.notas p:last-child { margin-bottom: 0; }

/* ------------------------------------------------------ hoja de cotización

   La vista de impresión. En pantalla se ve como una hoja sobre el fondo
   plomo; al imprimir desaparece todo lo que no es la hoja —menú, barra
   de acciones, avisos— y queda el documento solo. */

/* La hoja en sí está definida más abajo, junto al resto del diseño del
   documento. Acá arranca la parte de pantalla: el editor de plantillas. */

code {
  font-family: var(--mono);
  font-size: 0.92em;
  padding: 1px 4px;
  background: var(--superficie-2);
  border: 1px solid var(--linea);
  border-radius: 2px;
}

/* ------------------------------------------------- editor de plantillas */

.rejilla-plantillas {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: 20px;
  align-items: start;
}

.ayuda-marcadores { position: sticky; top: calc(var(--alto-cabecera) + 16px); }

textarea.codigo {
  font-family: var(--mono);
  font-size: 11.5px;
  line-height: 1.5;
  white-space: pre;
  overflow-wrap: normal;
  overflow-x: auto;
  tab-size: 2;
}

.tabla-marcadores { font-size: 11px; }
.tabla-marcadores td { padding: 3px 0; border: none; vertical-align: top; }
.tabla-marcadores td:first-child { padding-right: 10px; white-space: nowrap; }
.tabla-marcadores code { font-size: 10.5px; }

@media screen and (max-width: 1100px) {
  .rejilla-plantillas { grid-template-columns: 1fr; }
  .ayuda-marcadores { position: static; }
}
/* ============================================================
   El documento: propuesta comercial
   ------------------------------------------------------------
   Paleta y escala tipográfica propias, encerradas en `.hoja`.
   Van acá adentro y no en `:root` a propósito: la consola de
   precios es una herramienta interna —monoespaciada, acero y
   ámbar— y el documento que ve el cliente es otra cosa. Mezclar
   los dos juegos de variables terminaría tiñendo el catálogo con
   los azules de la propuesta, o al revés.

   La geometría —cabecera a 10 mm del borde, pie apoyado en el de
   abajo, una hoja por página— no se define acá: vive en el bloque
   @media print y en `public/impresion.js`.
   ============================================================ */

.hoja {
  /* Geometría. En pantalla es una tarjeta blanca; al imprimir se estira
     al alto exacto de la página (`100vh`, en el bloque @media print) para
     que la cabecera caiga en el margen de arriba y el pie en el de abajo.
     `--hoja-alto` y `--hoja-pie` los escribe `public/impresion.js`, que
     es quien puede medir: el primero para que la vista previa muestre
     dónde va a caer el pie, el segundo para reservarle su hueco. Sin el
     script la hoja mide lo que mide su contenido y no pasa nada malo. */
  background: #fff;
  border: 1px solid var(--linea);
  border-radius: var(--r);
  padding: 34px 38px calc(40px + var(--hoja-pie, 0px));
  max-width: 820px;
  position: relative;
  min-height: var(--hoja-alto, auto);

  /* Color */
  --azul-marino:   #0D3B66;
  --azul-inst:     #1B75BC;
  --gris-texto:    #3D3D3D;
  --gris-claro:    #6B6B6B;

  --celeste-fondo: #E2EDF7;
  --celeste-suave: #EDF3F9;
  --ambar-fondo:   #FFF3DC;
  --ambar-borde:   #E8A33D;
  --verde-fondo:   #E8F4E9;
  --verde-borde:   #4C9A51;

  --borde-ext:     #B9CFE3;
  --borde-int:     #D2E1EE;

  /* Los roles de la app, devueltos a los valores claros de antes de
     ClimIA. La app es oscura; el papel no. Todo lo genérico que cae
     adentro de una hoja —`th`, `a`, `p`, la cebra de las tablas, los
     avisos— pide colores por rol, y acá los recibe claros sin que haya
     que repetir una sola regla. Sin este bloque el PDF que recibe el
     cliente salía con letra celeste sobre blanco. */
  color-scheme: light;
  --papel:         var(--celeste-fondo);
  --superficie:    #ffffff;
  --superficie-2:  var(--celeste-suave);
  --superficie-3:  #DCE7F1;
  --tinta:         var(--azul-marino);
  --tinta-media:   #3D3D3D;
  --tinta-suave:   #6B6B6B;
  --linea:         var(--borde-int);
  --linea-fuerte:  var(--borde-ext);
  --frio:          var(--azul-inst);
  --frio-claro:    var(--celeste-fondo);
  --frio-borde:    #A8C9E6;
  --calor:         #8A5A12;
  --calor-claro:   var(--ambar-fondo);
  --calor-borde:   #E9C68C;
  --alerta:        #A32A28;
  --alerta-claro:  #FBE7E6;
  --alerta-borde:  #EFC2C0;
  --ok:            #3F8144;
  --ok-claro:      var(--verde-fondo);
  --ok-borde:      #B4D9B7;
  --cabecera:      var(--azul-inst);
  --th-texto:      #ffffff;
  --cebra:         var(--celeste-suave);
  --fila-mouse:    #CFE2F2;
  --fila-elegida:  var(--ambar-fondo);
  --plomo:         #D6E4F0;
  --prosa:         var(--fuente);
  --mono:          "Cascadia Mono", "Consolas", ui-monospace, "SF Mono", "Menlo", monospace;
  --r:             3px;

  /* Tipografía. En puntos y no en píxeles: el destino es papel, y
     un cuerpo de 10,5 pt mide lo mismo impreso salga de la máquina
     que salga. Carlito es la métrica-compatible libre de Calibri,
     por si el documento se abre donde no hay Office. */
  --fuente: "Calibri", "Carlito", "Segoe UI", system-ui, sans-serif;

  --fs-portada:    22pt;
  --fs-titular:    30pt;
  --fs-antetitulo: 11pt;
  --fs-bajada:     12pt;
  --fs-seccion:    13pt;
  --fs-subtitulo:  11.5pt;
  --fs-subsub:     10.5pt;
  --fs-cuerpo:     10.5pt;
  --fs-th:         10pt;
  --fs-td:         10pt;
  --fs-aux:        9.5pt;
  --fs-caption:    8.5pt;
  --fs-pie:        8pt;
  --fs-cita:       12.5pt;

  --lh-cuerpo: 1.32;
  --lh-tabla:  1.26;

  font-family: var(--fuente);
  font-size: var(--fs-cuerpo);
  line-height: var(--lh-cuerpo);
  color: var(--gris-texto);
}

/* La app le pone `--prosa` a todo `<p>`; adentro del documento manda
   la fuente del documento. Sin esto los párrafos quedarían en otra
   familia que los títulos y las tablas. */
.hoja p, .hoja li, .hoja td, .hoja th, .hoja h1, .hoja h2, .hoja h3,
.hoja h4, .hoja figcaption, .hoja blockquote { font-family: inherit; }

.hoja p {
  margin: 0 0 2.1mm;
  text-align: justify;
  /* Justificado sin partir palabras: un guión de corte en medio de
     un modelo —«TW12HQ3A»— se leería como parte del código. */
  hyphens: none;
  orphans: 3;
  widows: 3;
}

.hoja td p, .hoja th p, .hoja figcaption { text-align: left; }
.hoja .destacado { color: var(--azul-marino); font-weight: 700; }

/* La app tiene su propia jerarquía de títulos para las pantallas —su `h2`
   es una versalita gris de 10 px con 0,2 em de tracking— y esa herencia no
   tiene nada que hacer en un documento impreso: dejaba «LAS MARCAS QUE
   COTIZAMOS» espaciado como un rótulo de tablero. Se neutraliza de una
   vez y cada título del documento define lo suyo más abajo. */
.hoja h1, .hoja h2, .hoja h3, .hoja h4 {
  font-size: inherit;
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
  color: var(--azul-marino);
  margin: 0;
}

/* ---------------------------------------------------- cabecera y pie

   Los dos son HTML que escribe el operador en Configuración, así que
   acá sólo se define el marco: cuerpo de letra, el filete que los
   separa y de dónde arrancan. Lo de adentro es suyo. */

.hoja__plantilla--cabecera {
  font-size: var(--fs-aux);
  color: var(--gris-texto);
  padding-bottom: 3mm;
  border-bottom: 1.5pt solid var(--azul-inst);
}

.hoja__plantilla--cabecera b,
.hoja__plantilla--cabecera strong { color: var(--azul-marino); }

/* El margen del primer y del último elemento de la plantilla se anula.
   Sin esto un `<p>` al principio de la cabecera —lo más natural de
   escribir— se lleva su margen hacia afuera del bloque y empuja el
   membrete un renglón para abajo: la cabecera dejaría de empezar en el
   centímetro que se pidió. Lo mismo con el pie contra el borde de abajo.
   Adentro el operador sigue maquetando como quiera. */
.hoja__plantilla--cabecera > *:first-child,
.hoja__plantilla--pie > *:first-child { margin-top: 0; }
.hoja__plantilla--cabecera > *:last-child,
.hoja__plantilla--pie > *:last-child { margin-bottom: 0; }

.hoja__plantilla--pie {
  font-size: var(--fs-pie);
  color: var(--gris-claro);
  padding-top: 2.5mm;
  border-top: 0.75pt solid var(--borde-ext);
  /* Pegado al borde de abajo de la hoja, no al final del texto. El hueco
     que ocupa se lo reserva la hoja con `--hoja-pie`, así el contenido
     nunca le pasa por encima. Los valores de acá son los de pantalla, que
     tiene que respetar el margen de la tarjeta; al imprimir van a cero,
     donde el margen lo pone @page. */
  position: absolute;
  left: 38px;
  right: 38px;
  bottom: 40px;
}

/* Si el operador arma su membrete con una tabla, es para acomodar el
   contenido, no para mostrar una tabla: sale sin bordes ni fondos. */
.hoja__plantilla table { border: none; margin: 0; }
.hoja__plantilla td, .hoja__plantilla th {
  border: none;
  padding: 0 2mm 0 0;
  background: none;
  color: inherit;
  font-size: inherit;
  font-weight: inherit;
  white-space: normal;
}

/* ------------------------------------------------------------- portada

   Foto a sangre con el titular encima, y abajo, sobre blanco, dos filas:
   el logo con la descripción de la empresa, y los datos del cliente
   contra las fechas de la cotización.

   La proporción es la que hace que funcione: la foto se lleva algo menos
   de dos tercios de la hoja y el bloque blanco el resto. Una foto más
   chica deja de ser portada y pasa a ser ilustración; una más grande
   arrincona los datos contra el borde de abajo.

   La estructura la escribe el operador en Configuración → Plantillas, con
   estas clases. No está fija en el código a propósito: quién es el
   cliente, qué dice el antetítulo y qué datos de la empresa van al pie
   son decisiones suyas, no del programa. */

.hoja--caratula {
  display: flex;
  flex-direction: column;
  margin-bottom: 20px;
  /* También en pantalla: la portada es a sangre, y una vista previa con
     el marco blanco de las otras hojas no muestra lo que se va a
     imprimir. */
  padding: 0;
}

/* ------------------------------------------------------ la foto y su titular */

.portada__foto {
  position: relative;
  flex: none;
  /* 62 % de la hoja. En pantalla se calcula sobre el alto que
     `public/impresion.js` le da a la hoja, así la proporción de la vista
     previa es la misma que la del papel; si el script no corrió, un valor
     fijo razonable. Al imprimir manda la regla en milímetros de abajo. */
  height: calc(var(--hoja-alto, 680px) * 0.62);
  overflow: hidden;
  background: var(--azul-marino);
}

/* La foto que trae {{imagen_caratula}}. Llena el bloque y se recorta por
   el centro: las fotos las sube el operador con el recorte que tengan y
   una apaisada no puede decidir el alto de la portada. */
.portada__foto .caratula__foto,
.portada__foto img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  margin: 0;
  max-height: none;
}

/* Sin velo sobre la foto: el degradado lo dibujaba el navegador en cada
   impresión y era lo que más tardaba en aparecer en el PDF. La foto de
   portada se sube ya con su capa oscura encima, que además da control
   sobre dónde oscurecer. El fondo marino de acá abajo sigue sirviendo de
   respaldo para cuando no hay foto cargada. */

.portada__titular {
  position: absolute;
  left: 15mm;
  right: 15mm;
  bottom: 12mm;
}

.portada__antetitulo {
  font-size: var(--fs-antetitulo);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: #9FC8EA;
  margin-bottom: 3mm;
}

/* El titular es lo más grande del documento y por eso tiene su propio
   cuerpo, aparte del `--fs-portada` que usa el resto de la portada: a
   22 pt un título de cuatro palabras no sostiene media hoja de foto. */
.portada__titulo {
  font-size: var(--fs-titular);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -0.015em;
  color: #fff;
  margin: 0;
  text-wrap: balance;
}

/* ------------------------------------------------------- el bloque blanco */

.portada__ficha {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 7mm;
  padding: 10mm 15mm;
  background: #fff;
}

/* Primera fila: el logo, un filete y la descripción de la empresa. El
   filete separa la marca del dato sin necesidad de una caja. */
.portada__marca {
  display: grid;
  grid-template-columns: auto 1.5pt minmax(0, 1fr);
  align-items: center;
  gap: 7mm;
}

.portada__logo { display: flex; align-items: center; }

.portada__marca .documento__logo {
  max-height: 18mm;
  max-width: 70mm;
}

/* Sin logo cargado no hay nada que separar, y un filete suelto contra el
   margen izquierdo se lee como un error.

   Se colapsa la retícula entera y no sólo el filete: esconder el filete
   con `display: none` lo saca del grid pero **no saca su columna**, así
   que el texto de la empresa se corría a la columna de 1,5 pt y se
   envolvía a un carácter por renglón. El bloque medía 477 px en vez de
   60, la portada se pasaba de largo y salía una página en blanco detrás
   de cada propuesta. Con una sola columna el texto ocupa todo el ancho,
   que es lo que corresponde cuando no hay logo al lado. */
.portada__marca:has(.portada__logo:empty) {
  grid-template-columns: minmax(0, 1fr);
}
.portada__marca:has(.portada__logo:empty) .portada__logo,
.portada__marca:has(.portada__logo:empty) .portada__filete { display: none; }

.portada__filete {
  align-self: stretch;
  min-height: 14mm;
  background: var(--azul-inst);
  print-color-adjust: exact;
  -webkit-print-color-adjust: exact;
}

.portada__empresa {
  font-size: var(--fs-aux);
  line-height: 1.45;
  color: var(--gris-claro);
}

.portada__empresa b, .portada__empresa strong { color: var(--gris-texto); }

/* Segunda fila: a quién va y hasta cuándo vale. Separadas por una línea
   fina, con las fechas alineadas a la derecha para que las dos columnas
   se lean como una ficha y no como dos párrafos sueltos. */
.portada__datos {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 10mm;
  align-items: start;
  padding-top: 6mm;
  border-top: 0.75pt solid var(--borde-ext);
}

.portada__datos > div:last-child { text-align: right; }

.portada__rotulo {
  font-size: var(--fs-caption);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--azul-inst);
  margin-bottom: 1.5mm;
}

.portada__valor {
  font-size: var(--fs-seccion);
  font-weight: 700;
  color: var(--azul-marino);
  line-height: 1.2;
}

.portada__nota {
  font-size: var(--fs-aux);
  color: var(--gris-claro);
  margin-top: 1.2mm;
}

@media print {
  /* En el papel, 173 mm de los 279,4 de la hoja: el 62 %. Va en
     milímetros y no en porcentaje porque el porcentaje se mide contra la
     altura del padre, y el padre tiene min-height y no height: el
     navegador no lo resuelve y la foto queda del alto de la imagen. */
  .portada__foto { height: 173mm; }
}

/* La imagen que trae {{logo}}. Alto acotado y ancho libre porque un logo
   es apaisado o cuadrado según quién lo diseñó, y forzarle un ancho fijo
   lo deformaría; limitando la altura entra bien en una cabecera angosta
   o crece sin invadir el resto de la portada. */
.documento__logo {
  display: block;
  max-height: 16mm;
  max-width: 60mm;
  width: auto;
  height: auto;
}

/* La portada la escribe el operador, así que su jerarquía también se
   define por etiqueta: un `<h1>` suyo, fuera de las clases de arriba,
   tiene que salir con cuerpo de portada igual. */
.hoja--caratula h1 {
  font-size: var(--fs-portada);
  font-weight: 700;
  color: var(--azul-marino);
  line-height: 1.15;
  margin: 0 0 2mm;
  padding: 0;
  border: none;
}

.hoja--caratula h2 {
  font-size: var(--fs-antetitulo);
  font-weight: 700;
  color: var(--azul-inst);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  margin: 0 0 1.5mm;
}

.hoja--caratula p {
  font-size: var(--fs-bajada);
  text-align: left;
  margin: 0 0 1.5mm;
}

/* Un `<h1>` con la clase del titular manda sobre la regla de etiqueta. */
.hoja--caratula h1.portada__titulo {
  font-size: var(--fs-titular);
  color: #fff;
  line-height: 1.08;
  margin: 0;
}

@media print {
  /* El salto lo pone `.hoja + .hoja`. Repetirlo acá con `page-break-after`
     sumaba una hoja en blanco entre la carátula y la cotización. */
  /* `100vh` —la página entera— y no los 92vh de antes: ese recorte era
     por miedo a que estirar hasta el borde sumara una página, y quedó
     probado que no. La carátula centrada en la página completa es lo que
     se buscaba desde el principio. */
  .hoja--caratula { min-height: 100vh; margin-bottom: 0; }
}

/* ------------------------------------------------- membrete de fábrica

   El que sale cuando no hay plantilla de cabecera cargada. */

.hoja__cabeza {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 8mm;
  padding-bottom: 3mm;
  border-bottom: 1.5pt solid var(--azul-inst);
}

.hoja__marca {
  font-size: var(--fs-subtitulo);
  font-weight: 700;
  color: var(--azul-marino);
}

.hoja__numero { text-align: right; }
.hoja__valor { font-size: var(--fs-subtitulo); font-weight: 700; color: var(--azul-marino); }
.hoja__sub { font-size: var(--fs-aux); color: var(--gris-claro); }

.hoja__rotulo {
  font-size: var(--fs-caption);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--azul-inst);
  margin-bottom: 1mm;
}

/* ------------------------------------------- datos de la cotización

   Cliente, validez y número de propuesta, uno al lado del otro sobre
   fondo celeste: es la ficha de la operación, y separarla del cuerpo
   evita que se lea como un párrafo más de la propuesta.

   La tercera columna es angosta a propósito: sólo lleva el número y la
   fecha, y darle el mismo ancho que al cliente dejaría un hueco. */

.hoja__datos {
  display: grid;
  grid-template-columns: 1.15fr 1fr 0.62fr;
  gap: 6mm;
  margin: 4mm 0;
  padding: 3mm 4mm;
  background: var(--celeste-suave);
  border: 0.75pt solid var(--borde-ext);
  print-color-adjust: exact;
  -webkit-print-color-adjust: exact;
}

.hoja__propuesta {
  font-size: 12pt;
  letter-spacing: 0.02em;
  color: var(--azul-inst);
}

/* Descripción y condiciones las escribe el operador en un textarea, sin
   saber HTML. `pre-line` hace que el Enter que apretó sea el salto que
   sale impreso: respeta los saltos escritos, junta los espacios de más y
   sigue acomodando cada párrafo al ancho de la hoja. */

.hoja__descripcion,
.hoja__parrafo {
  white-space: pre-line;
}

.hoja__descripcion {
  margin: 0 0 4mm;
  padding: 2.5mm 3.5mm;
  /* Verde y no celeste: arriba está el celeste de Cliente/Validez y abajo
     el celeste de las filas pares de la tabla. Con el mismo tono la
     descripción se perdía entre los dos; el verde la separa de un
     vistazo. */
  background: var(--verde-fondo);
  border-left: 1.5pt solid var(--verde-borde);
  print-color-adjust: exact;
  -webkit-print-color-adjust: exact;
}

/* --------------------------------------------------------------- tablas

   Se estilan por etiqueta dentro de `.hoja` y no sólo por `.hoja__tabla`:
   la cabecera y la garantía las escribe el operador, y una tabla que él
   ponga ahí tiene que salir con el mismo formato que la de precios. */

.hoja table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-td);
  line-height: var(--lh-tabla);
  margin: 0 0 3mm;
  border: 0.75pt solid var(--borde-ext);
}

.hoja th {
  font-size: var(--fs-th);
  font-weight: 700;
  color: #fff;
  background: var(--azul-inst);
  text-align: left;
  vertical-align: middle;
  text-transform: none;
  letter-spacing: 0;
  white-space: nowrap;
  padding: 1.6mm 2.3mm;
  border: 0.5pt solid var(--borde-int);
  print-color-adjust: exact;
  -webkit-print-color-adjust: exact;
}

.hoja td {
  padding: 1.6mm 2.3mm;
  vertical-align: middle;
  border: 0.5pt solid var(--borde-int);
  print-color-adjust: exact;
  -webkit-print-color-adjust: exact;
}

/* La cebra es sólo de la tabla de precios: en una tabla de maquetación
   —la que el operador usa para poner dos cosas a los costados de la
   cabecera— teñiría renglones sin motivo. */
.hoja__tabla { margin-bottom: 4mm; }

/* Las cabeceras de la tabla de precios van en versalitas, y las de las
   tres columnas de cifras centradas sobre su columna. El poco tracking
   es lo que hace legible una versalita a 10 pt; sin él las mayúsculas se
   amontonan. */
.hoja__tabla th {
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.hoja__tabla th.num, .hoja__tabla th.moneda { text-align: center; }
/* La cebra va por número de ítem y no por posición de fila: con los
   subtítulos de grupo intercalados, `nth-child` teñiría renglones
   corridos y el sombreado dejaría de alternar. */
.hoja__tabla tbody tr.par > td { background: var(--celeste-suave); }

/* El subtítulo de un grupo de equipos. No es otra cabecera de columnas:
   va en celeste —el color que el documento usa para estructura— con la
   tinta institucional, para que se lea como una división de la tabla y
   no como el encabezado repetido. */
.hoja__tabla tbody tr.grupo th {
  background: var(--celeste-suave);
  color: var(--azul-marino);
  font-size: var(--fs-caption);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 2mm 2.3mm 1.4mm;
  /* Un subtítulo al pie de una hoja no encabeza nada. La paginación ya lo
     evita al armar las hojas; esto es el cinturón para cuando el
     navegador corta por su cuenta. */
  break-after: avoid;
  page-break-after: avoid;
}

/* La capacidad adentro de un grupo de equipos. Divide al grupo, no abre
   uno nuevo: por eso va sin el fondo celeste del subtítulo de arriba,
   apenas un poco más chico y con la tinta plomiza de un dato secundario,
   como el detalle técnico de cada ítem —una fila menos, no otro título. */
.hoja__tabla tbody tr.subgrupo th {
  /* `.hoja th` pone fondo y letra blanca para la cabecera de columnas; acá
     se cancelan los dos, si no la tinta plomiza queda invisible. */
  background: #fff;
  color: var(--gris-claro);
  font-size: var(--fs-caption);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 1.6mm 2.3mm 1mm;
  border: none;
  border-bottom: 1px solid var(--borde-int);
  break-after: avoid;
  page-break-after: avoid;
}

.hoja__tabla .sub {
  display: block;
  font-size: var(--fs-caption);
  color: var(--gris-claro);
  margin-top: 0.8mm;
  line-height: 1.25;
}

.hoja__tabla td.num { text-align: center; font-weight: 700; color: var(--gris-claro); }
.hoja__tabla td.moneda {
  text-align: right;
  font-weight: 700;
  color: var(--azul-marino);
  white-space: nowrap;
}

/* ------------------------------------------------------------- totales */

.hoja__totales {
  margin-left: auto;
  width: 75mm;
  border: 0.75pt solid var(--borde-ext);
  print-color-adjust: exact;
  -webkit-print-color-adjust: exact;
}

.hoja__totales > div {
  display: flex;
  justify-content: space-between;
  gap: 4mm;
  padding: 1.5mm 3mm;
  border-bottom: 0.5pt solid var(--borde-int);
}

.hoja__total {
  border-bottom: none;
  background: var(--celeste-fondo);
  font-size: var(--fs-subtitulo);
  padding: 2.2mm 3mm !important;
  print-color-adjust: exact;
  -webkit-print-color-adjust: exact;
}

.hoja__total span, .hoja__total b { color: var(--azul-marino); font-weight: 700; }

/* La aclaración de la Inversión Total —«(impuesto incluido)»— va debajo
   y más chica: es contexto del número, no un segundo importe. La caja se
   ensancha un poco porque con centavos «Bs 15.865,00» ya no entra junto
   al rótulo en 75 mm. */
.hoja__totales { width: 82mm; }
.hoja__totales small {
  display: block;
  font-size: 0.82em;
  color: var(--tinta-suave);
  font-weight: 400;
}

/* ---------------------------------------------------------- condiciones

   En ámbar y no en celeste como el resto: es lo único de la hoja que
   compromete al cliente a algo —plazos, anticipo, vigencia—. Que se
   distinga de un vistazo del material informativo es el punto. */

.hoja__pie {
  margin-top: 5mm;
  padding: 2.5mm 3.5mm;
  background: var(--ambar-fondo);
  border-left: 1.5pt solid var(--ambar-borde);
  print-color-adjust: exact;
  -webkit-print-color-adjust: exact;
}

.hoja__pie .hoja__rotulo { color: #8A5A12; }
.hoja__pie p { margin: 0; }

/* ------------------------------------------------------- anexos del documento

   Marcas, galería y preguntas frecuentes. Al imprimir, el conjunto arranca
   en página nueva: son material de lectura, no parte de la cotización
   comercial, y meterlos a continuación de los totales haría que el cliente
   tenga que buscar dónde termina el precio.

   Pero entre ellos se dejan fluir. Ver la regla en @media print. */

.hoja--anexo { margin-top: 20px; }

/* En pantalla las hojas se ven una debajo de la otra, así que la segunda
   hoja del detalle necesita decir que viene de la anterior. */
.hoja__continua {
  font-size: var(--fs-aux);
  color: var(--gris-claro);
  text-align: left;
  margin: 3mm 0 0;
}

/* El título de un anexo es la «sección» de la propuesta: el escalón más
   alto de la jerarquía dentro del cuerpo. Va con `.hoja` adelante para
   ganarle al reseteo de títulos de arriba, que por llevar la etiqueta
   pesa más que una clase sola. */
.hoja .hoja__titulo {
  font-size: var(--fs-seccion);
  font-weight: 700;
  color: var(--azul-marino);
  line-height: 1.2;
  margin: 0 0 3.2mm;
  padding-bottom: 1.6mm;
  border-bottom: 1.5pt solid var(--azul-inst);
}

/* La garantía se enmarca en verde, que en este juego de colores es lo
   que respalda, y no en el ámbar de lo que condiciona. */
.hoja--garantia .hoja__cuerpo {
  padding: 4mm 5mm;
  background: var(--verde-fondo);
  border-left: 1.5pt solid var(--verde-borde);
  print-color-adjust: exact;
  -webkit-print-color-adjust: exact;
}

.hoja--garantia h2 {
  font-size: var(--fs-seccion);
  font-weight: 700;
  color: var(--azul-marino);
  margin: 0 0 3mm;
}

.hoja--garantia h3 {
  font-size: var(--fs-subsub);
  font-weight: 700;
  color: var(--azul-marino);
  margin: 3mm 0 1.2mm;
}

.hoja--garantia p:last-child { margin-bottom: 0; }
.hoja--garantia b { color: var(--azul-marino); }

/* --------------------------------------------------------------- viñetas

   Por etiqueta y no por clase: las listas las escribe el operador —en la
   descripción de una marca, en la garantía— y no va a acordarse de poner
   una clase. La clase se acepta igual, por si alguna vez la usa. */

.hoja ul, .hoja ul.vinetas { margin: 0 0 2.5mm; padding: 0; list-style: none; }

.hoja ul > li {
  position: relative;
  padding-left: 6mm;
  margin-bottom: 1.6mm;
  text-align: justify;
  break-inside: avoid;
}

.hoja ul > li::before {
  content: "";
  position: absolute;
  left: 2.2mm;
  top: 1.6mm;
  width: 1.5mm;
  height: 1.5mm;
  background: var(--azul-inst);
  print-color-adjust: exact;
  -webkit-print-color-adjust: exact;
}

.hoja ul ul { margin: 1.2mm 0 0; }
.hoja ul ul > li { padding-left: 5mm; }
.hoja ul ul > li::before {
  content: "\2013";
  background: none;
  width: auto;
  height: auto;
  left: 1mm;
  top: 0;
  color: var(--azul-inst);
}

/* ------------------------------------------------------------------ cita */

.hoja blockquote, .hoja .cita {
  font-size: var(--fs-cita);
  font-style: italic;
  color: var(--azul-marino);
  text-align: center;
  line-height: 1.3;
  margin: 5mm auto;
  max-width: 155mm;
}

/* ---------------------------------------------------------- fichas de marca */

.anexo-marca {
  display: grid;
  grid-template-columns: 34mm minmax(0, 1fr);
  gap: 5mm;
  align-items: start;
  padding: 4mm 0;
  border-bottom: 0.5pt solid var(--borde-int);
}

.anexo-marca:last-child { border-bottom: none; }
.anexo-marca__logo img { max-width: 100%; max-height: 18mm; object-fit: contain; }

.anexo-marca__texto h3 {
  font-size: var(--fs-subtitulo);
  font-weight: 700;
  color: var(--azul-inst);
  margin: 0 0 1.8mm;
}

.anexo-marca__texto p:last-child { margin-bottom: 0; }

/* Una foto metida en el HTML que escribe el operador nunca mide más que
   media hoja. La descripción de una marca se pega muchas veces desde una
   página web, con la foto al 100 % del ancho: la del stand de TOSOT, que es
   vertical (1024 × 1536), medía 22 cm de alto dentro de la columna de texto.
   Una foto no se parte, así que esa ficha no entraba en ninguna hoja y seis
   propuestas imprimían una página sin cabecera ni pie. `contain` conserva la
   proporción dentro del tope en vez de estirarla; el ancho que eligió el
   operador se respeta siempre que la foto no pase del tope. */
.anexo-marca__texto img,
.prop__parrafo img,
.prop__destacado img,
.prop__bajada img,
.hoja--garantia img {
  max-width: 100%;
  max-height: 110mm;
  object-fit: contain;
  object-position: left top;
}

/* Sin logo la ficha usa el ancho completo: una columna vacía de 34 mm
   dejaría el texto arrancando en el medio de la hoja sin razón. */
.anexo-marca:not(:has(.anexo-marca__logo)) { grid-template-columns: minmax(0, 1fr); }

/* Dos por fila y no las que entren: son fotos de trabajo terminado, y a
   tres por fila un equipo instalado en la pared se ve del tamaño de un
   sello. La foto es el argumento de venta; si no se distingue, sobra. */
.anexo-galeria {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 5mm;
}

.anexo-galeria figure { margin: 0; }

.anexo-galeria img {
  width: 100%;
  height: 62mm;
  object-fit: cover;
  border: 0.75pt solid var(--borde-ext);
  display: block;
}

/* En una pantalla angosta dos columnas dejan las fotos ilegibles: ahí sí
   conviene una sola. En papel el ancho es siempre el mismo, así que esta
   regla no afecta al PDF. */
@media screen and (max-width: 560px) {
  .anexo-galeria { grid-template-columns: minmax(0, 1fr); }
}

.anexo-galeria figcaption {
  font-size: var(--fs-caption);
  color: var(--gris-claro);
  margin-top: 1.2mm;
  line-height: 1.25;
}

/* ------------------------------------------------------ preguntas frecuentes */

.anexo-faq { margin-bottom: 4mm; }
.anexo-faq:last-child { margin-bottom: 0; }

.anexo-faq h3 {
  font-size: var(--fs-caption);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--azul-inst);
  margin: 0 0 2.5mm;
}

.anexo-faq__par { margin-bottom: 3mm; }

.anexo-faq__p {
  font-size: var(--fs-subsub);
  font-weight: 700;
  color: var(--azul-marino);
  margin-bottom: 1mm;
}

.anexo-faq__r { text-align: justify; }

/* -------------------------------------------- pantallas de contenido de venta */

.ficha-marca {
  display: grid;
  grid-template-columns: 200px minmax(0, 1fr);
  gap: 20px;
  align-items: start;
}

.ficha-marca__logo { display: flex; flex-direction: column; gap: 10px; }
.ficha-marca__logo img { max-width: 100%; max-height: 80px; object-fit: contain; align-self: flex-start; }

.ficha-marca__sinlogo {
  display: grid;
  place-items: center;
  height: 80px;
  border: 1px dashed var(--linea-fuerte);
  border-radius: var(--r);
  font-size: 11px;
  color: var(--tinta-suave);
}

.casilla {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--tinta-media);
  cursor: pointer;
}

.rejilla-imagenes {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 18px;
}

.tarjeta-imagen { margin: 0; display: flex; flex-direction: column; gap: 6px; }
.tarjeta-imagen--apagada { opacity: 0.5; }

.tarjeta-imagen img {
  width: 100%;
  height: 140px;
  object-fit: cover;
  border: 1px solid var(--linea);
  border-radius: var(--r);
  display: block;
}

.tarjeta-imagen figcaption { font-size: 11.5px; line-height: 1.45; }
.tarjeta-imagen figcaption .sub { display: block; font-size: 10.5px; color: var(--tinta-media); }

/* Un equipo que la lista trae y el catálogo no tiene. Se destaca porque es
   la única fila que, confirmada sin mirar, no hace nada. */
.tag--nuevo {
  background: var(--frio);
  color: #fff;
  border-color: var(--frio);
  letter-spacing: .06em;
}

.lista-decisiones { margin: 0; padding-left: 18px; color: var(--tinta-media); }
.lista-decisiones li { margin-bottom: 5px; }
.lista-decisiones li:last-child { margin-bottom: 0; }

/* La fórmula del precio, escrita con los porcentajes que están cargados.
   Monoespaciada porque son cuentas, no prosa. */
.formula {
  background: var(--plomo);
  border: 1px solid var(--linea);
  border-radius: 3px;
  padding: 12px 14px;
  font-family: var(--codigo, ui-monospace, "Cascadia Code", Consolas, monospace);
  font-size: 11.5px;
  line-height: 1.7;
  color: var(--tinta-media);
}

.formula b { color: var(--tinta); }
.formula .pista { font-family: inherit; }

/* Bloque al que se acaba de llegar por un enlace con ancla: un borde
   marcado, para no tener que buscar en una página de veinte fichas. */
.bloque--destacado { border-color: var(--frio); box-shadow: 0 0 0 3px var(--frio-claro); }

/* Edición en el lugar dentro de una fila de tabla. */
.fila-editar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.fila-editar input[type="text"], .fila-editar input:not([type]) { min-width: 160px; }

/* Selección de anexos: tres columnas de casillas, una por clase. */
.rejilla-anexos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 20px;
  align-items: start;
}

.anexo-opcion {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  padding: 5px 0;
  font-size: 12px;
  line-height: 1.35;
  cursor: pointer;
  border-bottom: 1px solid var(--linea);
}

.anexo-opcion:last-child { border-bottom: none; }
.anexo-opcion input { margin-top: 2px; flex: none; }
.anexo-opcion .sub { display: block; font-size: 10.5px; color: var(--tinta-media); margin-top: 2px; }
.anexo-opcion--foto img {
  width: 44px;
  height: 32px;
  object-fit: cover;
  border: 1px solid var(--linea);
  border-radius: 2px;
  flex: none;
}

@media screen and (max-width: 720px) {
  .ficha-marca, .anexo-marca { grid-template-columns: minmax(0, 1fr); }
}

/* La hoja del PDF. El mismo tamaño y márgenes que usa el navegador al
   imprimir, para que el archivo generado y lo que se ve en pantalla al
   dar Imprimir sean el mismo documento. */

/* ------------------------------------------- hoja de propuesta comercial */

/* Los bloques del motor de propuestas. La jerarquía es lo que separa una
   propuesta de una lista de párrafos: la etiqueta anuncia, el titular
   pesa, la bajada explica, y los tres destacados —argumento, beneficio,
   diferencial— salen del cuerpo del texto para que se lean incluso al
   hojear. Las medidas van en pt como el resto del documento. */

.hoja .prop__etiqueta {
  font-size: var(--fs-antetitulo);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--azul-inst);
  margin: 0 0 2mm;
}

.hoja .prop__titular {
  font-size: var(--fs-portada);
  font-weight: 700;
  line-height: 1.15;
  color: var(--azul-marino);
  margin: 0 0 3mm;
}

.hoja .prop__bajada {
  font-size: var(--fs-bajada);
  line-height: 1.4;
  color: var(--gris-texto);
  padding-bottom: 4mm;
  margin-bottom: 5mm;
  border-bottom: 1pt solid var(--borde-ext);
}

/* El rótulo de cada bloque en versalitas y chico: dice de qué habla el
   párrafo sin competir con el párrafo. Sin él, seis bloques seguidos son
   una pared de texto. */
.hoja .prop__rotulo {
  font-size: var(--fs-caption);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--azul-inst);
  margin-bottom: 1mm;
}

.hoja .prop__parrafo { margin-bottom: 4.5mm; }
.hoja .prop__parrafo p:last-child,
.hoja .prop__destacado p:last-child { margin-bottom: 0; }

/* El destacado no lleva color de fondo a propósito: la portada ya enseñó
   que una capa pintada de lado a lado tarda en salir en el PDF. Un filete
   grueso a la izquierda logra lo mismo y se dibuja solo. */
.hoja .prop__destacado {
  padding: 3mm 0 3mm 5mm;
  margin-bottom: 4.5mm;
  border-left: 2.5pt solid var(--azul-inst);
}

/* Cuando se ve en pantalla, la hoja está en px y no en mm: las mismas
   proporciones, escritas para el monitor. */
@media screen {
  .hoja .prop__bajada { padding-bottom: 12px; margin-bottom: 16px; }
  .hoja .prop__parrafo, .hoja .prop__destacado { margin-bottom: 14px; }
  .hoja .prop__destacado { padding: 8px 0 8px 15px; }
  .hoja .prop__etiqueta { margin-bottom: 6px; }
  .hoja .prop__titular { margin-bottom: 9px; }
}

/* --------------------------------- el segmento, en la pantalla de edición */

/* No es un campo: es el resultado de mirar al cliente. Se dibuja como un
   dato en reposo y no como una casilla, para que nadie intente escribirlo. */
.segmento {
  display: flex;
  align-items: baseline;
  gap: 8px;
  flex-wrap: wrap;
  padding: 6px 9px;
  background: var(--superficie-2);
  border: 1px solid var(--linea);
  border-radius: 2px;
  color: var(--tinta);
}

/* ------------------------------------------------------------- pestañas */

.pestanas {
  display: flex;
  gap: 4px;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--linea-fuerte);
}

.pestanas__uno {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 14px;
  font-size: 12px;
  color: var(--tinta-media);
  text-decoration: none;
  border: 1px solid transparent;
  border-bottom: none;
  border-radius: var(--r) var(--r) 0 0;
  margin-bottom: -1px;
}

.pestanas__uno:hover { color: var(--frio); }

.pestanas__uno--activa {
  background: var(--superficie);
  border-color: var(--linea-fuerte);
  color: var(--tinta);
  font-weight: 600;
}

.pestanas__cuenta {
  font-size: 10.5px;
  color: var(--tinta-suave);
  font-variant-numeric: tabular-nums;
}

@page {
  size: letter;
  /* Sin margen acá: los 10 mm de arriba y abajo y los 15 mm de los
     costados los pone `.hoja` como relleno, más abajo.

     La diferencia importa por la portada. Con el margen en @page, el
     navegador recorta todo lo que se salga del área útil —comprobado
     leyendo el PDF: el recorte empezaba a 10,05 mm del borde—, así que
     una foto a sangre era imposible. Con el margen en la hoja, el área
     pintable es el papel entero y la portada puede sacarse el relleno
     para que la foto llegue al filo.

     La otra salida —`@page portada { margin: 0 }`, una página con
     nombre— parecía la del manual y no sirve: cambia a cuánto equivale
     `100vh` en *todo* el documento, y `100vh` es exactamente lo que
     mantiene la cabecera y el pie en su lugar en el resto de las hojas.
     Se probó: las hojas normales pasaban a ocupar dos páginas. */
  margin: 0;
}

@media print {
  /* El armazón de ClimIA no sale en el papel: el PDF se genera
     imprimiendo la página, y lo único que tiene que quedar es la hoja. */
  .lateral, .lateral__velo, .lateral__plegar, .movil, .sin-imprimir, .aviso, .notas { display: none !important; }
  .app { display: block; }
  /* Y el lienzo vuelve a ser claro. Con `color-scheme: dark` en :root el
     navegador pinta el fondo de la página de gris oscuro antes que la hoja
     blanca; no se ve, pero el PDF del cliente no tiene por qué llevar una
     capa que no es suya. */
  :root { color-scheme: light; }
  /* Una fila partida entre dos hojas se lee mal y desalinea los precios. */
  tr, .hoja__totales, .hoja__pie { page-break-inside: avoid; }

  /*
   * Cabecera arriba, pie abajo, y sólo el cuerpo se mueve.
   *
   * La hoja se estira hasta el alto exacto de la página con `100vh`. Que
   * sea `vh` y no un número de píxeles calculado en JavaScript es lo que
   * hace que funcione: al imprimir, `100vh` es —por definición— el alto
   * del área imprimible que el propio navegador está usando, mientras que
   * cualquier medida tomada en pantalla es una estimación que puede
   * pasarse por uno o dos píxeles. Y pasarse por un píxel no se paga con
   * un píxel: la hoja no entra en la página, se parte, y sale una página
   * de más que la numeración no contaba. Con `100vh` no hay nada que
   * estimar. (Probado imprimiendo de verdad: `min-height: 100vh` da una
   * página por hoja, exacta.)
   *
   * Con la hoja del alto de la página, el pie pegado abajo con
   * `position: absolute` cae en el borde físico inferior y la cabecera,
   * que es lo primero del flujo, en el superior. Los dos quedan donde
   * corresponde sin depender del largo del contenido, que es lo único que
   * los movía antes.
   *
   * Que el cuerpo entre en el hueco que queda lo garantiza
   * `public/impresion.js`, que mide y pasa lo que sobra a una hoja nueva
   * —con copia de esta misma cabecera y de este mismo pie, para que cada
   * hoja conserve su formato—.
   */
  .hoja {
    min-height: 100vh;
    /* Éste es el margen de la propuesta: 10 mm arriba y abajo, 15 a los
       costados. Vive acá y no en @page para que la portada pueda
       renunciar a él. Medido sobre el PDF: la cabecera arranca a 10,05 mm
       del borde de arriba y el pie termina a 9,95 mm del de abajo. */
    padding: 10mm 15mm;
    padding-bottom: calc(10mm + var(--hoja-pie, 0px));
  }
  .hoja__plantilla--pie { left: 15mm; right: 15mm; bottom: 10mm; }

  /* La portada es la única hoja a sangre: la foto tiene que llegar al
     filo del papel, así que renuncia al relleno y cada bloque de adentro
     se pone el suyo. */
  .hoja--caratula { padding: 0; }

  /* Una hoja, una página. Antes se dejaba que dos anexos cortos
     compartieran página para no gastar papel; desde que cada hoja lleva su
     propia cabecera, su pie y su «2 de 6 páginas», compartir página haría
     que esa numeración mienta: dirían ser dos hojas y saldrían impresas en
     una. Vale más el papel que un documento que se contradice. */
  .hoja + .hoja { page-break-before: always; margin-top: 0; }
  .hoja--anexo { margin-top: 0; }

  /* Un título solo al pie de la hoja, con su contenido en la siguiente, es
     el precio de dejarlos fluir. Se evita. */
  .hoja__titulo { page-break-after: avoid; }
  /* La ficha de una marca **no** lleva `page-break-inside: avoid`, aunque
     una pregunta o una foto sí. Con descripciones largas —las de acá miden
     casi una hoja— pedirle al navegador que no la parta lo obliga a
     empujarla entera a la hoja siguiente y a dejar media hoja en blanco
     atrás. Se contaban dos páginas de más por cotización, y encima el
     lector veía el hueco. Cada marca ya arranca en su hoja; si su texto no
     entra, que siga en la de al lado es mejor que un salto en el medio. */
  .anexo-faq__par, .anexo-galeria figure { page-break-inside: avoid; }
  .anexo-faq { page-break-inside: auto; }
  thead { display: table-header-group; }
  body { background: #fff; }
  .contenido { padding: 0; max-width: none; }
  .hoja { border: none; border-radius: 0; max-width: none; }
  a { text-decoration: none; color: inherit; }

  /* El PDF se genera imprimiendo esta misma página, así que todo lo que se
     quite acá se pierde también en el archivo. Antes había dos reglas que
     borraban el encabezado azul y el rayado de la tabla «porque gastan
     tinta en papel»: el efecto real era que la cotización en pantalla
     tenía formato y el PDF que recibía el cliente salía en blanco y negro.
     La propuesta comercial es lo último que conviene despintar.

     `print-color-adjust: exact` es imprescindible: sin él el navegador
     descarta los fondos al imprimir y no alcanza con volver a declararlos. */
  .hoja, .hoja * { print-color-adjust: exact; -webkit-print-color-adjust: exact; }
}

.sube  { color: var(--calor);  font-weight: 600; }
.baja  { color: var(--frio);   font-weight: 600; }
.quieto{ color: var(--tinta-suave); }

/* --------------------------------------------------------------- avisos */

.aviso {
  display: flex;
  gap: 10px;
  padding: 11px 14px;
  border-radius: var(--r-boton);
  border: 1px solid;
  margin-bottom: 16px;
  font-family: var(--prosa);
}

.aviso b { font-weight: 700; }
.aviso--ok     { background: var(--ok-claro);     border-color: var(--ok-borde); color: var(--ok); }
.aviso--error  { background: var(--alerta-claro); border-color: var(--alerta-borde); color: var(--alerta); }
.aviso--atencion{ background: var(--calor-claro); border-color: var(--calor-borde); color: var(--calor); }
.aviso--info   { background: var(--frio-claro);   border-color: var(--frio-borde); color: var(--tinta); }

/* ------------------------------------------------------------ formularios */

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

.campo { display: flex; flex-direction: column; gap: 4px; min-width: 0; }

/* `hidden` tiene que ganarle al `display` de acá arriba. El navegador
   esconde con `[hidden] { display: none }`, que pierde por especificidad
   contra `.campo`: sin esta regla, los campos que el formulario de
   clientes esconde —razón social y NIT cuando el cliente es una persona—
   se quedan a la vista. */
.campo[hidden], .campos[hidden], .pista[hidden] { display: none; }
.campo--ancho { grid-column: 1 / -1; }

/* Dos campos por renglón, a mitades. Distinto de dejar que la retícula
   acomode sola: acá se quiere exactamente dos, aunque entren tres, porque
   los que se emparejan son pares —los dos textos de la cotización, las
   dos formas de agregar un ítem— y verlos del mismo ancho es lo que dice
   que son alternativas o equivalentes. */
.campos--dos { grid-template-columns: repeat(2, minmax(0, 1fr)); }

/* Tres columnas fijas y no auto-fit: en esta fila —razón social, NIT y
   tipo de contacto— los dos primeros desaparecen cuando el cliente es una
   persona, y con auto-fit el que queda se estiraba de lado a lado. Con
   las columnas fijas conserva su ancho y la fila se lee igual en los dos
   casos. */
.campos--fiscal { grid-template-columns: repeat(3, minmax(0, 1fr)); }

@media screen and (max-width: 720px) {
  .campos--fiscal { grid-template-columns: minmax(0, 1fr); }
}

/* Edición masiva (varios productos a la vez): cada campo se activa con su
   propia casilla y arranca apagado. Al revés de lo habitual —donde el
   campo ya trae un valor y se lo puede borrar— acá el silencio es la
   opción seria: sin marcar, ese dato de cada producto no se toca. */
.campo-lote__casilla { display: flex; align-items: center; gap: 6px; cursor: pointer; }

.campo--lote select:disabled,
.campo--lote textarea:disabled,
.campo--lote input:not([type="checkbox"]):disabled {
  opacity: 0.45;
  background: var(--superficie-2);
}

/* El precio y el botón de agregar: el precio se lleva el ancho de un
   campo normal y el botón sólo lo que necesita. */
.campos--agregar { grid-template-columns: 210px auto; justify-content: start; }
.campos--agregar .btn { align-self: start; }

@media screen and (max-width: 720px) {
  .campos--dos { grid-template-columns: minmax(0, 1fr); }
}

/* El bloque Cliente de la cotización: columnas un 40 % más angostas
   —126 px de mínimo en vez de 210— para que el nombre de la propuesta
   entre en el mismo renglón que empresa, contacto, teléfono y correo.
   Se puede porque los cuatro son datos cortos. El nombre de la propuesta
   sí es una frase, así que se queda con dos columnas. */
.campos--cliente { grid-template-columns: repeat(auto-fit, minmax(126px, 1fr)); }
.campos--cliente .campo--doble { grid-column: span 2; }
@media screen and (max-width: 900px) {
  .campos--cliente .campo--doble { grid-column: 1 / -1; }
}

/* Descripción comercial y estado en un solo renglón: la descripción se
   queda con el ancho que sobra y el estado con lo que necesita un select
   de tres valores. Se apilan cuando la ventana no da. */
.campos--desc { grid-template-columns: minmax(0, 1fr) 230px; }
@media screen and (max-width: 720px) { .campos--desc { grid-template-columns: minmax(0, 1fr); } }

/* Los marcadores disponibles, abajo del campo que los usa. */
.marcadores-desc { margin-top: 12px; }
.marcadores-desc__chips { display: flex; flex-wrap: wrap; gap: 5px; margin: 5px 0 8px; }

.chip {
  font-family: var(--mono);
  font-size: 10.5px;
  padding: 2px 7px;
  color: var(--frio);
  background: var(--frio-claro);
  border: 1px solid var(--frio-borde);
  border-radius: 2px;
  cursor: pointer;
}

.chip:hover { background: var(--frio); color: var(--climia-bg-950); border-color: var(--frio); }
.texto-resuelto { font-family: var(--prosa); color: var(--tinta); }

label, .campo > span:first-child {
  font-size: 9.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--tinta-suave);
}

.pista {
  font-size: 11px;
  color: var(--tinta-suave);
  font-family: var(--prosa);
  letter-spacing: 0;
  text-transform: none;
}

input, select, textarea {
  font: inherit;
  font-variant-numeric: tabular-nums;
  color: var(--tinta);
  background: var(--climia-bg-900);
  border: 1px solid var(--linea-fuerte);
  border-radius: var(--r);
  padding: 6px 9px;
  width: 100%;
  min-width: 0;
  transition: border-color 120ms ease, box-shadow 120ms ease;
}

input::placeholder, textarea::placeholder { color: var(--tinta-apagada); }
input:hover:not(:disabled):not(:focus), select:hover:not(:disabled):not(:focus), textarea:hover:not(:disabled):not(:focus) { border-color: var(--climia-line-600); }

textarea { font-family: var(--prosa); resize: vertical; min-height: 62px; }

/* El foco: borde cyan y un halo que no mueve nada de lugar. Es el único
   control que brilla, y sólo mientras se escribe en él. */
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--frio);
  box-shadow: 0 0 0 3px rgba(18, 200, 255, 0.14);
}

input:disabled, select:disabled, textarea:disabled,
input[readonly], textarea[readonly] { color: var(--tinta-suave); background: var(--superficie); cursor: default; }

/* Un campo con error dice que lo tiene con el borde y con el texto: el
   rojo solo no alcanza para quien no distingue colores. */
input[aria-invalid="true"], select[aria-invalid="true"], textarea[aria-invalid="true"] { border-color: var(--alerta); }

select option { background: var(--climia-surface-850); color: var(--tinta); }

input[type="checkbox"] { width: auto; }

/* Impuesto y Moneda: dos opciones que se excluyen entre sí, y un
   desplegable las hace parecer una lista larga cuando son sólo dos. El
   radio nativo con acento ámbar —el mismo tono de "atención" que ya usa
   el resto del documento— se lee de un vistazo sin abrir nada. */
.radios {
  display: flex;
  align-items: center;
  gap: 22px;
  padding-top: 5px;
  min-height: 30px;
}

.radio,
.opcion-check {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--prosa);
  font-size: 13px;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--tinta);
  cursor: pointer;
}

.radio input[type="radio"],
.opcion-check input[type="checkbox"] {
  width: 16px;
  height: 16px;
  accent-color: var(--ambar-borde);
  cursor: pointer;
}

.radio input:disabled,
.opcion-check input:disabled {
  cursor: default;
}

.opcion-check { padding-top: 5px; }

.linea-campos { display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap; }
.linea-campos .campo { flex: 1 1 150px; }

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

.acciones--pegadas { margin-top: 0; }

/* --------------------------------------------------------------- botones */

.btn {
  display: inline-block;
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.01em;
  padding: 6px 14px;
  border-radius: var(--r-boton);
  border: 1px solid var(--linea-fuerte);
  background: var(--superficie-2);
  color: var(--tinta);
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease, box-shadow 120ms ease;
}

.btn:hover { background: var(--superficie-3); border-color: var(--climia-line-600); text-decoration: none; }
.btn:disabled, .btn[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; }

/* La acción principal: degradé azul de marca, borde cyan y el único
   resplandor fijo de una pantalla. */
.btn--principal {
  background: var(--climia-gradient-accion);
  border-color: var(--frio);
  color: var(--sobre-accion);
  font-weight: 600;
  box-shadow: 0 0 16px rgba(18, 200, 255, 0.18);
}
.btn--principal:hover { background: linear-gradient(180deg, #129af0, #0a74bd); border-color: var(--climia-cyan-300); box-shadow: var(--climia-glow-primary); }

.btn--peligro { color: var(--alerta); border-color: var(--alerta-borde); }
.btn--peligro:hover { background: var(--alerta-claro); border-color: var(--alerta); }

.btn--chico { padding: 3px 8px; font-size: 11px; }

.enlace-sobrio { color: var(--tinta-media); }

/* Un formulario que se abre con un botón, en vez de ocupar la pantalla
   mientras no se lo usa. El <summary> es el botón. */
.desplegar > summary {
  list-style: none;
  cursor: pointer;
  display: inline-block;
  font: inherit;
  letter-spacing: 0.04em;
  padding: 6px 14px;
  border-radius: 2px;
  border: 1px solid var(--linea-fuerte);
  background: var(--superficie);
  color: var(--tinta);
}
.desplegar > summary::-webkit-details-marker { display: none; }
.desplegar > summary:hover { background: var(--superficie-2); border-color: var(--tinta-suave); }
.desplegar[open] > summary { background: var(--superficie-2); }
.desplegar__cuerpo { margin-top: 16px; }

/* Los saltos de línea de un guion son parte del guion. */
.texto-guion { white-space: pre-wrap; }

/* ------------------------------------------------------------- historial */

.barra-var {
  display: inline-block;
  height: 3px;
  vertical-align: middle;
  border-radius: 2px;
  min-width: 2px;
}
.barra-var--sube { background: var(--calor); }
.barra-var--baja { background: var(--frio); }

/* --------------------------------------------------- selector de columnas */

.ojo { position: relative; }

.ojo summary {
  list-style: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px;
  font-size: 11px;
  border: 1px solid var(--linea-fuerte);
  border-radius: 2px;
  background: var(--superficie);
  color: var(--tinta-media);
}

.ojo summary::-webkit-details-marker { display: none; }
.ojo summary:hover { border-color: var(--tinta-suave); color: var(--tinta); }
.ojo[open] summary { background: var(--superficie-2); color: var(--tinta); }

.ojo__menu {
  position: absolute;
  right: 0;
  top: calc(100% + 6px);
  z-index: 20;
  min-width: 210px;
  padding: 10px 12px;
  display: flex;
  flex-direction: column;
  gap: 7px;
  background: var(--superficie);
  border: 1px solid var(--linea-fuerte);
  border-radius: var(--r);
  box-shadow: 0 6px 18px var(--sombra);
}

.ojo__menu label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--tinta);
  cursor: pointer;
  white-space: nowrap;
}

.ojo__cabeza {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 8px;
  margin-bottom: 2px;
  border-bottom: 1px solid var(--linea);
}

.ojo__ayuda { font-size: 10.5px; color: var(--tinta-suave); }

/* Cada columna es una fila arrastrable: el tirador a la izquierda, la
   casilla de visibilidad y, para quien no quiera arrastrar, dos flechas.
   El arrastre es el camino rápido; las flechas son el que siempre está. */
.ojo__fila {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 1px 2px;
  border: 1px solid transparent;
  border-radius: 2px;
  background: var(--superficie);
}

.ojo__fila label { flex: 1; }

.ojo__tirador {
  cursor: grab;
  color: var(--tinta-suave);
  font-size: 11px;
  line-height: 1;
  padding: 3px 2px;
  user-select: none;
}

.ojo__fila:hover { background: var(--superficie-2); }
.ojo__fila--arrastrando { opacity: 0.4; }
.ojo__fila--destino { border-color: var(--frio); }

.ojo__mover {
  border: none;
  background: none;
  cursor: pointer;
  color: var(--tinta-suave);
  font-size: 10px;
  line-height: 1;
  padding: 3px 2px;
  font-family: var(--mono);
}

.ojo__mover:hover:not(:disabled) { color: var(--tinta); }
.ojo__mover:disabled { opacity: 0.25; cursor: default; }

/* ------------------------------------------------------ selección de filas */

th.sel, td.sel {
  width: 30px;
  padding-left: 12px;
  padding-right: 0;
  text-align: center;
}

td.sel { vertical-align: middle; }
tr.fila--elegida td { background: var(--frio-claro); }

/* Barra de acciones sobre la selección. Aparece recién cuando hay algo
   elegido: mientras no lo haya, no ocupa lugar ni promete nada. */
.barra-seleccion {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 8px 16px;
  background: var(--frio-claro);
  border-bottom: 1px solid var(--linea);
}

.barra-seleccion[hidden] { display: none; }
.barra-seleccion form { display: inline; }
.barra-seleccion__conteo { font-size: 12px; color: var(--tinta); }
.barra-seleccion .btn[aria-disabled="true"] { opacity: 0.4; cursor: default; }
.barra-seleccion .pista { margin-left: auto; }


/* ------------------------------------------------------------ clientes */

/* El permiso para escribirle. Tres estados y tres colores, porque la
   diferencia entre ellos decide si se manda un mensaje o no: verde es
   que sí, gris es que todavía no lo dio, rojo es que pidió que no. */
.tag--con_permiso  { color: var(--ok);     background: var(--ok-claro);     border-color: var(--ok-borde); }
.tag--sin_permiso  { color: var(--tinta-media); background: var(--superficie-2); border-color: var(--linea-fuerte); }
.tag--dado_de_baja { color: var(--alerta); background: var(--alerta-claro); border-color: var(--alerta-borde); }

/* Los datos del cliente, en pares rótulo/valor. Rejilla y no tabla: son
   pares sueltos, no filas comparables entre sí. */
.ficha {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px 20px;
  margin: 0;
}

.ficha dt {
  font-size: 9.5px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--tinta-suave);
}

.ficha dd { margin: 2px 0 0; color: var(--tinta); }

/* Cada persona es un bloque con su propio borde: en una empresa con
   cuatro contactos, una lista corrida no deja ver dónde termina uno y
   empieza el siguiente. */
.persona {
  padding: 12px 0;
  border-top: 1px solid var(--linea);
}

.persona:first-child { border-top: none; padding-top: 0; }

.persona__cabeza {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.persona__cabeza > div {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
}

.telefonos { list-style: none; margin: 8px 0 0; padding: 0; }

.telefonos li {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 3px 0;
  flex-wrap: wrap;
}

.telefonos__numero { font-variant-numeric: tabular-nums; color: var(--tinta); }

/* Editar un contacto es lo raro; verlo es lo común. Los formularios van
   plegados para que la ficha se lea de un vistazo y no como una pila de
   casillas. */
.persona__mas summary {
  list-style: none;
  cursor: pointer;
  display: inline-block;
  margin-top: 6px;
  font-size: 11px;
  color: var(--tinta-suave);
  border-bottom: 1px dashed var(--linea-fuerte);
}

.persona__mas summary::-webkit-details-marker { display: none; }
.persona__mas summary:hover { color: var(--frio); border-bottom-color: var(--frio); }

.persona__menu {
  margin-top: 10px;
  padding: 12px;
  background: var(--superficie-2);
  border: 1px solid var(--linea);
  border-radius: var(--r);
}

/* ------------------------------- el cliente, dentro de la cotización */

.cliente-elegido {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding: 10px 12px;
  background: var(--frio-claro);
  border: 1px solid var(--frio-borde);
  border-radius: var(--r);
}

.cliente-elegido__quien { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.cliente-elegido__nombre { font-weight: 600; color: var(--tinta); }

.buscador-cliente { position: relative; }

/* El botón de alta se queda del ancho de su texto. `.linea-campos .campo`
   reparte el sobrante entre todos, y con dos campos el botón se estiraba
   media pantalla y parecía otra casilla de texto. */
.buscador-cliente .linea-campos .campo:last-child { flex: 0 0 auto; }

/* Los resultados se superponen al formulario en vez de empujarlo: la
   cotización de abajo tiene datos sin guardar, y que el bloque entero
   salte mientras se escribe hace perder de vista lo que se estaba
   haciendo. */
.buscador-cliente__lista {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% + 4px);
  z-index: 20;
  max-height: 280px;
  overflow-y: auto;
  background: var(--superficie);
  border: 1px solid var(--linea-fuerte);
  border-radius: var(--r);
  box-shadow: 0 6px 18px var(--sombra);
}

.buscador-cliente__lista[hidden] { display: none; }

.buscador-cliente__item {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  width: 100%;
  padding: 7px 10px;
  border: none;
  border-bottom: 1px solid var(--linea);
  background: none;
  font: inherit;
  text-align: left;
  cursor: pointer;
  color: var(--tinta);
}

.buscador-cliente__item:last-child { border-bottom: none; }
.buscador-cliente__item:hover,
.buscador-cliente__item:focus { background: var(--frio-claro); outline: none; }
.buscador-cliente__dato { font-size: 11px; color: var(--tinta-suave); }
.buscador-cliente__vacio { padding: 10px; font-size: 12px; color: var(--tinta-suave); }

.filtros {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: flex-end;
  padding: 12px 16px;
  background: var(--plomo);
  border: 1px solid var(--linea-fuerte);
  border-radius: var(--r);
  margin-bottom: 12px;
}

/* La barra creció a ocho controles —nueve en Costos, que suma Proveedor— y
   antes cada uno se reservaba 168px fijos: WiFi terminaba solo en el
   renglón de abajo, y una barra de filtros partida en dos se lee como si
   fueran dos barras distintas. Ahora todos crecen y se encogen juntos
   sobre una base chica, así que entran en una línea y se reparten el
   sobrante de la pantalla en vez de dejarlo al final. Lo que se recorta es
   el rótulo, no el control: `.multi__valor` ya corta con puntos
   suspensivos y el menú desplegado conserva su ancho. */
.filtros .campo { flex: 1 1 118px; }

/* El buscador se lleva el doble del espacio sobrante: es el único donde se
   escribe, y los demás sólo tienen que mostrar lo elegido. */
.filtros .campo--buscar { flex: 2 1 160px; }

/* Los binarios no necesitan ni esa base: «Con WiFi» entra holgado en menos,
   y lo que se ahorra acá lo ganan los otros. */
.filtros .campo--angosto { flex: 0 1 104px; }

/* Filtro de varios valores.

   Un <details> con casillas adentro, y no un <select multiple>: el nativo
   exige ctrl+clic para sumar un segundo valor —quien no lo sabe reemplaza
   el que ya tenía elegido, que es exactamente el error que este control
   viene a evitar—, ocupa un alto fijo en la barra y no deja leer lo
   elegido sin desplegarlo. Acá el botón cerrado dice qué hay puesto. */

.multi { position: relative; }

/* Las medidas son las de `input, select` a propósito: los siete controles
   de la barra están alineados por su borde de abajo y uno más alto que el
   resto se nota enseguida. */
.multi summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
  padding: 6px 8px;
  background: var(--superficie);
  border: 1px solid var(--linea-fuerte);
  border-radius: 2px;
  color: var(--tinta);
}

.multi summary::-webkit-details-marker { display: none; }
.multi summary:hover { border-color: var(--tinta-suave); }
.multi[open] summary { border-color: var(--frio); }

.multi__valor { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* Un filtro puesto se tiene que distinguir de un vistazo entre cinco: con
   nada elegido el rótulo dice «Todas» en gris de reposo, y en cuanto hay
   algo marcado el control entero se tiñe. Sin esto, filtrar y no entender
   por qué falta un equipo es cuestión de tiempo. */
.multi:not(.multi--puesto) .multi__valor { color: var(--tinta-suave); }
/* El filete doble y no un fondo teñido: la barra de filtros ya es celeste,
   así que pintar el control de celeste claro lo hace desaparecer dentro de
   ella —justo al revés de lo que hace falta—. El borde reforzado sobre
   blanco se ve contra los otros seis. */
.multi--puesto summary {
  border-color: var(--frio);
  box-shadow: inset 0 0 0 1px var(--frio);
}
.multi--puesto .multi__valor { color: var(--tinta); font-weight: 600; }

.multi__flecha { flex: none; color: var(--tinta-suave); }
.multi[open] .multi__flecha { transform: rotate(180deg); }

.multi__menu {
  position: absolute;
  left: 0;
  top: calc(100% + 4px);
  z-index: 20;
  width: max-content;
  min-width: 100%;
  max-width: 300px;
  padding: 8px 10px;
  background: var(--superficie);
  border: 1px solid var(--linea-fuerte);
  border-radius: var(--r);
  box-shadow: 0 6px 18px var(--sombra);
}

.multi__cabeza {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  padding-bottom: 6px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--linea);
}

.multi__cuantas { font-size: 10.5px; color: var(--tinta-suave); }
.multi__ninguna:disabled { opacity: 0.35; cursor: default; }

/* Se desborda con barra y no crece: con veinte marcas el menú tapaba la
   tabla que se está filtrando. */
.multi__lista {
  display: flex;
  flex-direction: column;
  gap: 1px;
  max-height: 264px;
  overflow-y: auto;
}

.multi__lista label {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 3px 4px;
  border-radius: 2px;
  font-size: 12px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--tinta);
  cursor: pointer;
}

.multi__lista label:hover { background: var(--superficie-2); }
.multi__lista input[type="checkbox"] { flex: none; }

/* El `display: flex` de arriba le gana al `display: none` que el navegador
   le da a `[hidden]`, así que sin esta regla las opciones que el
   sub-filtrado descarta se marcan como ocultas y se siguen viendo. */
.multi__lista label[hidden] { display: none; }

/* ------------------------------------- columnas de un campo compuesto

   Las casillas de la pantalla de mapeo. Cada una muestra el encabezado
   de la columna y un valor de ejemplo: dos columnas llamadas "Modelo" no
   se distinguen por el nombre, y acá elegir mal significa darle al equipo
   un identificador equivocado para siempre. */
.col-lista {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 8px;
  border: 1px solid var(--linea);
  border-radius: 3px;
  background: var(--superficie-2);
}

.col-op {
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding: 5px 8px;
  border: 1px solid var(--linea);
  border-radius: 3px;
  background: var(--superficie);
  cursor: pointer;
  font-size: 12px;
  min-width: 0;
}

.col-op:hover { border-color: var(--frio); }

.col-op--puesta {
  border-color: var(--frio);
  background: var(--frio-claro);
}

.col-op input[type="checkbox"] { flex: none; }
.col-op__nombre { font-weight: 600; white-space: nowrap; }
.col-op__muestra {
  color: var(--tinta-suave);
  font-size: 10.5px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 150px;
}

/* La opción sigue marcada pero ningún equipo la cumple ya, cruzada con el
   resto de los filtros puestos —por ejemplo, Daher no vende esa marca—.
   No se esconde para que se pueda desmarcar, sólo se apaga. */
.multi__opcion--sin { opacity: 0.45; }

/* ---------------------------------------------------- orden de columnas

   Dos flechas por encabezado, de menor a mayor y de mayor a menor. Van
   blancas y tenues como el tirador de ancho de al lado, y se iluminan al
   pasar el mouse o cuando esa es la columna por la que está ordenada la
   tabla. */
.orden {
  display: inline-flex;
  flex-direction: column;
  gap: 1px;
  margin-left: 5px;
  vertical-align: -1px;
}

.orden-asc, .orden-desc {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  background: none;
  color: rgba(255, 255, 255, 0.4);
  cursor: pointer;
  line-height: 0;
}

.orden-asc:hover, .orden-desc:hover,
.orden-asc.orden--activa, .orden-desc.orden--activa {
  color: #fff;
}

/* El `screen and` de estos bloques —y de los otros de ancho— no sobra.
   Al imprimir en carta el ancho de página es de 816 px, así que
   `(max-width: 900px)` también da verdadero en el papel; como están
   escritos después del bloque @media print, le ganaban. El síntoma era
   difícil de rastrear: `.contenido` recuperaba sus 18 px de arriba y 48
   de abajo en el PDF, cada hoja quedaba 66 px más alta que la página, y
   salía el doble de páginas de las que decía la numeración. Cualquier
   regla de ancho que se agregue de acá en más va con `screen and`. */
@media screen and (max-width: 900px) {
  .contenido { padding: 18px 16px 48px; }
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}

/* Prospecto y cliente. Verde es el que ya compró: en un listado de
   cincuenta filas, la diferencia entre los dos es lo que se mira. */
.tag--cliente   { color: var(--ok); background: var(--ok-claro); border-color: var(--ok-borde); }
.tag--prospecto { color: var(--tinta-media); background: var(--superficie-2); border-color: var(--linea-fuerte); }

/* Estado de una conversación de WhatsApp. */
.tag--abierta            { color: var(--ok);          background: var(--ok-claro);    border-color: var(--ok-borde); }
.tag--esperando_cliente  { color: var(--calor);        background: var(--calor-claro); border-color: var(--calor-borde); }
.tag--cerrada            { color: var(--tinta-media);  background: var(--superficie-2); border-color: var(--linea-fuerte); }

/* Cada conversación es un bloque propio, igual que `.persona`: en un
   cliente con dos hilos —dos personas escribiendo por su cuenta— una
   lista corrida no deja ver dónde termina uno y empieza el otro. */
.conversacion {
  padding: 12px 0;
  border-top: 1px solid var(--linea);
}

.conversacion:first-child { border-top: none; padding-top: 0; }

.conversacion__cabeza {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}

.conversacion__cabeza > div {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
}

.mensajes { list-style: none; margin: 10px 0 0; padding: 0; }

/* Un mensaje entrante y uno saliente se distinguen por el borde, no por
   burbujas de colores: es un registro para revisar, no una app de chat. */
.mensaje {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 5px 0 5px 10px;
  border-left: 2px solid var(--linea-fuerte);
  font-size: 12.5px;
}

.mensaje--saliente { border-left-color: var(--frio); }

.mensaje__quien {
  flex: 0 0 auto;
  font-weight: 600;
  color: var(--tinta-suave);
  min-width: 64px;
}

.mensaje__texto { flex: 1 1 auto; color: var(--tinta); word-break: break-word; }

.mensaje__cuando {
  flex: 0 0 auto;
  color: var(--tinta-suave);
  font-size: 10.5px;
  white-space: nowrap;
}

/* El GPS y las referencias comparten renglón y son los dos de texto
   libre, así que el alto va parejo: uno más alto que el otro deja el
   renglón desprolijo sin razón. */
.campo #ubicacion_gps { min-height: 62px; }

/* --------------------------------------------------------------- acceso ---
   Quién está adentro, y la pantalla por la que se entra. */


.entrada {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 24px;
  background: var(--papel);
}

.entrada {
  background:
    radial-gradient(60% 50% at 50% 0%, rgba(18, 200, 255, 0.10), transparent 70%),
    var(--papel);
}

.entrada__caja {
  width: 100%;
  max-width: 360px;
  padding: 26px 26px 22px;
  background: var(--climia-gradient-panel);
  border: 1px solid var(--linea-fuerte);
  border-radius: var(--r-panel);
  box-shadow: 0 20px 50px var(--sombra), var(--climia-glow-soft);
}

.entrada__marca { margin-bottom: 20px; text-align: center; }
.entrada__logo { display: block; width: 220px; max-width: 100%; height: auto; margin: 0 auto 10px; border-radius: 8px; }

.entrada__rotulo {
  font-size: 9.5px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--tinta-suave);
}

.entrada .campo { margin-bottom: 14px; }
.entrada .campo input { width: 100%; }
.entrada__btn { width: 100%; justify-content: center; margin-top: 4px; }

.entrada__pie {
  margin: 18px 0 0;
  font-size: 11px;
  line-height: 1.5;
  color: var(--tinta-suave);
}

/* La clave recién generada: se muestra una sola vez, así que tiene que ser
   imposible no verla y fácil de copiar sin equivocarse un carácter. */
.bloque--clave { border-color: var(--frio); }

.clave-nueva {
  margin: 8px 0 12px;
  padding: 12px 14px;
  background: var(--frio-claro);
  border: 1px dashed var(--frio);
  font-family: var(--mono);
  font-size: 20px;
  letter-spacing: 0.08em;
  user-select: all;
}

/* La barra de guardado de la propuesta. El botón va más grande que el
   resto: es el único de la pantalla y cierra una edición larga, así que
   tiene que encontrarse sin buscarlo después de bajar tres bloques. */
.acciones--guardar {
  margin: 22px 0 8px;
  padding-top: 16px;
  border-top: 1px solid var(--linea);
  align-items: center;
}

.btn--guardar { padding: 9px 22px; font-size: 13px; }

/* «Marcar como enviada» y «Volver a borrador». Dejaron el azul principal
   —que ahora es el de guardar, la acción que se repite— por el ámbar de la
   paleta: cambiar el estado se hace una vez y congela la edición de la
   cotización, así que conviene que no se parezca al botón de al lado. */
.btn--estado {
  background: var(--calor-claro);
  border-color: var(--ambar-borde);
  color: var(--calor);
  font-weight: 600;
}

.btn--estado:hover { background: var(--calor-claro-fuerte); border-color: var(--calor); }

/* Ganar una propuesta es la buena noticia de la pantalla: verde, el mismo
   que la app ya usa para lo que está bien. «Perdida» queda como un botón
   común a propósito — no es un error ni un peligro, es un dato. */
.btn--ganada {
  border-color: var(--ok);
  color: var(--ok);
  font-weight: 600;
}
.btn--ganada:hover { background: var(--ok-claro); border-color: var(--ok); }

/* ------------------------------------------------------ fotos de equipo */

/* La foto de una unidad instalada y la de su placa. Se muestran chicas
   —son para reconocer el equipo de un vistazo, no para mirarlas— y el
   enlace lleva al archivo entero, que es donde se lee un número de serie
   borroso. `contain` y no `cover`: una placa recortada pierde justo el
   dato por el que se sacó la foto. */
.foto-equipo {
  display: block;
  max-width: 100%;
  max-height: 160px;
  object-fit: contain;
  border: 1px solid var(--linea);
  border-radius: var(--r);
  background: var(--superficie-2);
  margin-bottom: 6px;
}

/* --------------------------------------------- selección de técnicos */

/* Una fila por técnico, no una grilla de columnas. La versión anterior
   ponía el nombre y su radio de «responsable» juntos y repartidos en
   cuatro columnas, y se leía como un grupo de radios —«elegí uno»—
   cuando lo que se puede es marcarlos a todos. */
.lista-tecnicos { display: flex; flex-wrap: wrap; gap: 6px 18px; }
.lista-tecnicos--filas { flex-direction: column; gap: 0; }

.tecnico-fila {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px;
  padding: 7px 10px;
  border-bottom: 1px solid var(--linea);
  max-width: 34rem;
}
.tecnico-fila:last-child { border-bottom: none; }
.tecnico-fila:hover { background: var(--superficie-2); }

/* La vista previa de la tarjeta del aviso de servicio. El iframe rinde
   540 px fijos —el tamaño exacto que fotografía el navegador— y acá se
   escala para que entre en cualquier pantalla sin deformarse. */
.wa-tarjeta {
  width: 380px;
  max-width: 100%;
  aspect-ratio: 1;
  margin-bottom: 12px;
  border: 1px solid var(--linea);
  border-radius: 8px;
  overflow: hidden;
}
.wa-tarjeta iframe {
  width: 540px;
  height: 540px;
  border: 0;
  transform-origin: top left;
  /* 380 / 540. El número va escrito y no calculado porque el iframe rinde
     a 540 px sí o sí —es el tamaño que fotografía el navegador— y el marco
     de arriba está fijado en 380. */
  transform: scale(0.7037);
}

/* ---------------------------------------------------------------------
   Rastreo de técnicos (14-sep-2026): el mapa en vivo y los recorridos.
   El mapa ocupa el ancho del bloque y una altura fija: con altura según
   el contenido Leaflet no tiene dónde dibujar.
   --------------------------------------------------------------------- */
.mapa-campo { height: 520px; width: 100%; background: var(--superficie-2); }
.mapa-campo .leaflet-tooltip { font-family: var(--fuente); font-size: 12px; font-weight: 600; }

.avisos-zona { margin: 6px 0 0; padding-left: 18px; }
.avisos-zona li { margin: 4px 0; }

.recorrido-muestra {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  margin-right: 6px;
  vertical-align: -1px;
}

/* =====================================================================
   Propuestas — la pantalla de edición
   ---------------------------------------------------------------------
   Dos rediseños, el mismo mes. El del 16-sep-2026 hizo que la propuesta
   entrara en una pantalla: una tarjeta para el formulario con el rótulo
   a la izquierda, ayudas como `title`, una sola forma de agregar a la
   vez. El del 23-sep-2026 le puso la identidad de ClimIA sin tocar nada
   de eso:

   - barra superior con el número, el estado real del guardado y las
     acciones, con «Guardar» como única acción principal;
   - columna derecha con el contexto, el asistente (desactivado hasta que
     exista) y el resumen, donde el total es el dato más grande de la
     pantalla;
   - el buscador del catálogo en la cabecera de los ítems.

   Los colores son los roles de :root, nunca hex sueltos.
   ===================================================================== */

/* El aire es el del diseño —16 px de gutter, no los 28 de `.contenido`—
   así que la pantalla se sale del padding de su contenedor en vez de
   pedirle al layout que haga una excepción. */
.prop {
  margin: -22px -28px -64px;
  padding: 0 0 24px;
}

/* Con un aviso arriba ("Propuesta guardada") la pantalla ya no sube hasta el
   borde: si subiera, la barra fija le taparía el borde de abajo al aviso. */
.aviso + .prop { margin-top: 0; }

/* Cualquier cosa escondida con `hidden` dentro de la pantalla se esconde
   de verdad. Varias piezas de acá tienen `display: flex` o `grid`, y ese
   `display` le gana al `[hidden]` del navegador: sin esta regla, la
   columna de precio que no se imprime o un panel de anexos cerrado
   aparecían igual. */
.prop [hidden] { display: none !important; }

.prop-ico { flex: none; }

.oculto {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* ------------------------------------------------------ barra superior */

.prop__barra {
  display: flex;
  align-items: center;
  gap: 12px 16px;
  flex-wrap: wrap;
  padding: 10px 16px;
  min-height: 68px;
  /* Sin backdrop-filter: con el fondo animado detrás, el desenfoque se
     rehacía en cada cuadro, y la barra ya es casi opaca. */
  background: var(--barra-prop-fondo);
  border-bottom: 1px solid var(--linea);
  position: sticky;
  top: var(--alto-cabecera);
  z-index: 30;
}

.prop__identidad { display: flex; flex-direction: column; gap: 2px; min-width: 0; }

.prop__volver {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--tinta-suave);
}

.prop__volver:hover { color: var(--frio); text-decoration: none; }

.prop__titulo { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

.prop__num {
  font-size: 23px;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.1;
  color: var(--tinta);
}

.prop__titulo .tag { font-size: 10.5px; padding: 3px 9px; }

.prop__guardado {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--tinta-suave);
}

/* Cambios pendientes: ámbar y con texto. El color solo no alcanzaría. */
.prop__guardado--sucio { color: var(--calor); }
.prop__guardado--guardando { color: var(--frio); }

.prop__acciones { display: flex; align-items: center; gap: 8px; margin-left: auto; flex-wrap: wrap; }
.prop__acciones form { display: flex; }

.prop__acciones .btn {
  height: 36px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 0 13px;
  font-size: 13px;
}

.prop__acciones .btn--principal { padding: 0 22px; }

/* El botón del panel sólo existe cuando la columna derecha no se ve. */
.prop__riel-abrir { display: none !important; }

/* ------------------------------------------------------------ la rejilla */

.prop__cuerpo { padding: 14px 16px 0; }

.prop__rejilla {
  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--ancho-riel);
  gap: 14px;
  align-items: start;
}

.prop__editor { min-width: 0; }

/* -------------------------------------------------------- las tarjetas */

.prop-tarjeta {
  background: var(--climia-gradient-panel);
  border: 1px solid var(--linea);
  border-radius: var(--r-tarjeta);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.18);
}

.prop-tarjeta + .prop-tarjeta { margin-top: 12px; }

/* Una sección del formulario: rótulo con su ícono a la izquierda,
   contenido a la derecha. */
.prop-seccion {
  display: grid;
  grid-template-columns: 136px minmax(0, 1fr);
}

.prop-seccion + .prop-seccion { border-top: 1px solid var(--linea); }

.prop-seccion__rotulo {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 14px 12px 0 16px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--tinta);
}

.prop-seccion__rotulo .prop-ico { color: var(--frio); margin-top: 1px; }
.prop-seccion__cuerpo { padding: 11px 14px 12px 4px; min-width: 0; }

@media screen and (max-width: 860px) {
  .prop-seccion { grid-template-columns: minmax(0, 1fr); }
  .prop-seccion__rotulo { padding: 10px 14px 0; }
  .prop-seccion__cuerpo { padding: 8px 14px 12px; }
}

/* --------------------------------------------------- campos y rótulos */

.prop-rot {
  display: block;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--tinta-suave);
  margin-bottom: 5px;
}

/* La aclaración pegada al rótulo —«· encabezado del documento»— dice de
   qué parte del papel se está hablando sin gastar un renglón. */
.prop-rot small { font-size: 10.5px; font-weight: 400; letter-spacing: 0; text-transform: none; }
.prop-rot a { font-size: 11px; font-weight: 500; letter-spacing: 0; text-transform: none; margin-left: 6px; }

.prop-campo { min-width: 0; }

.prop input:not([type="checkbox"]):not([type="radio"]),
.prop select {
  height: 34px;
  padding: 0 10px;
  font-size: 13px;
}

.prop select { padding: 0 8px; }
.prop textarea { padding: 7px 10px; font-size: 13px; line-height: 1.45; min-height: 58px; }

.prop-fila { display: flex; align-items: flex-end; gap: 16px; flex-wrap: wrap; }
.prop-fila--cliente { gap: 10px; }
.prop-fila--cliente .btn { height: 34px; display: inline-flex; align-items: center; }
.prop-divisor { width: 1px; height: 34px; background: var(--linea); margin: 0 2px; }

.prop-columnas { display: grid; gap: 10px 12px; }
.prop-columnas--tipo { grid-template-columns: 230px minmax(0, 1fr); }
.prop-columnas--datos { grid-template-columns: repeat(4, minmax(0, 1fr)); margin-top: 10px; }
.prop-columnas--textos { grid-template-columns: repeat(2, minmax(0, 1fr)); }

@media screen and (max-width: 860px) {
  .prop-columnas--tipo,
  .prop-columnas--datos,
  .prop-columnas--textos { grid-template-columns: minmax(0, 1fr); }
}

/* Impuesto y moneda: dos opciones que se excluyen, dibujadas como un
   segmentado. Por dentro siguen siendo radios —el envío y el JavaScript
   que recalcula los totales leen input[name=impuesto]:checked—; lo que
   cambia es que el radio se esconde y lo que se ve es su etiqueta.

   Lo elegido se distingue sin el brillo: fondo azul lleno y letra blanca
   contra texto apagado sobre navy. */
.prop-segmentado {
  display: flex;
  height: 34px;
  padding: 2px;
  gap: 2px;
  border: 1px solid var(--linea-fuerte);
  border-radius: var(--r);
  background: var(--climia-bg-900);
}

.prop-segmentado label {
  display: flex;
  align-items: center;
  padding: 0 12px;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--tinta-suave);
  border-radius: 5px;
  cursor: pointer;
  white-space: nowrap;
  user-select: none;
}

.prop-segmentado input { position: absolute; opacity: 0; width: 1px; height: 1px; pointer-events: none; }
.prop-segmentado label:hover { color: var(--tinta); background: rgba(18, 200, 255, 0.06); }
.prop-segmentado label:has(input:checked) {
  background: var(--climia-gradient-accion);
  color: var(--sobre-accion);
  box-shadow: 0 0 0 1px var(--frio-borde), 0 0 12px rgba(18, 200, 255, 0.16);
}
.prop-segmentado label:has(input:focus-visible) { outline: 2px solid var(--frio); outline-offset: 1px; }
.prop-segmentado label:has(input:disabled) { cursor: default; opacity: 0.7; }

/* El segmento del cliente es un dato, no un control. Va en píldora para
   que no se lo confunda con un campo que se puede escribir. */
.prop-pill {
  display: flex;
  align-items: center;
  height: 34px;
  padding: 0 14px;
  background: var(--frio-claro);
  border: 1px solid var(--frio-borde);
  border-radius: 17px;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--frio);
  white-space: nowrap;
}

.prop-check {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 34px;
  font-size: 12.5px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--tinta-media);
  cursor: pointer;
}

.prop-check input { width: 16px; height: 16px; accent-color: var(--climia-cyan-400); cursor: pointer; }
.prop-nota { font-size: 12px; color: var(--tinta-suave); }

/* El cliente ya vinculado, en el renglón del buscador. */
.prop-cliente { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-height: 34px; }
.prop-cliente__nombre { font-size: 14px; font-weight: 600; color: var(--tinta); }
.prop-cliente__dato { font-size: 12px; color: var(--tinta-suave); }

/* ------------------------------------------------------------- ítems */

.prop-items__cabeza {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 11px 14px;
  border-bottom: 1px solid var(--linea);
}

.prop-items__titulo {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: 16px;
  font-weight: 600;
  color: var(--tinta);
}

.prop-items__titulo .prop-ico { color: var(--frio); }
.prop-items__resumen { font-size: 12px; color: var(--tinta-suave); }

.prop-items__cabeza .prop-agregar__buscador { flex: 1 1 280px; max-width: 460px; margin-left: 8px; }

.prop-items__alta {
  height: 34px;
  display: inline-flex !important;
  align-items: center;
  gap: 6px;
  padding: 0 12px !important;
  font-size: 12.5px !important;
  color: var(--frio) !important;
  border-color: var(--frio-borde) !important;
  background: rgba(18, 200, 255, 0.05) !important;
}

.prop-items__alta:hover { background: var(--frio-claro) !important; }

.prop-items__modo { margin-left: auto; font-size: 11.5px; color: var(--tinta-suave); }
.prop-items__modo b { color: var(--tinta-media); font-weight: 600; }
.prop-items__congelado { color: var(--tinta-apagada); }

@media screen and (max-width: 1599px) { .prop-items__congelado { display: none; } }

.prop-items__vacio { padding: 26px 14px; }

/* La tabla de ítems no usa el encabezado genérico: franja oscura con
   rótulos apagados, porque lo que tiene que resaltar son los importes.
   Los anchos van fijos, así la descripción se queda con lo que sobra y
   las columnas de plata no bailan al cambiar de moneda. El ancho mínimo
   es el que hace legible la fila: por debajo, la tabla se desplaza sola
   dentro de su marco y la página no. */
.prop-items .tabla-marco { overflow-x: auto; }
.prop-items table { table-layout: fixed; font-size: 13px; min-width: 760px; }

.prop-items th {
  height: 34px;
  padding: 0 8px;
  background: var(--cabecera);
  border-bottom: 1px solid var(--linea);
  color: var(--th-texto);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.08em;
}

.prop-items td {
  height: 58px;
  padding: 6px 8px;
  border-bottom: 1px solid var(--linea-tenue);
  vertical-align: middle;
}

.prop-items tbody tr:nth-child(even) td { background: var(--cebra); }
.prop-items tbody tr:hover td { background: var(--fila-mouse-items); }
.prop-items tbody tr:last-child td { border-bottom: 1px solid var(--linea); }

.prop-items__desc { display: flex; align-items: center; gap: 10px; min-width: 0; }
.prop-items__textos { flex: 1; min-width: 0; }

/* De dónde salió la línea: del catálogo (el equipo) o escrita a mano (la
   herramienta). Es un dato, y por eso lleva `title`. */
.prop-items__origen {
  display: grid;
  place-items: center;
  width: 46px;
  height: 36px;
  flex: none;
  border-radius: 7px;
  border: 1px solid var(--linea-fuerte);
}

.prop-items__origen--equipo { background: linear-gradient(145deg, #d9eef8, #7699aa); color: #0b3650; }
.prop-items__origen--libre { background: linear-gradient(145deg, #0d6094, #06345a); color: #4ae9ff; }

/* Descripción y detalle se editan en el lugar: sin borde hasta que el
   mouse pasa por encima. Una lista de ítems con dos cajas dibujadas por
   fila se lee como un formulario, no como una lista. */
.prop-items__texto {
  border-color: transparent !important;
  background: transparent !important;
  height: 25px !important;
  padding: 0 5px !important;
  font-size: 13.5px !important;
  font-weight: 600;
  color: var(--tinta);
  box-shadow: none !important;
}

.prop-items__texto--detalle {
  height: 21px !important;
  margin-top: 1px;
  font-size: 11.5px !important;
  font-weight: 400;
  color: var(--tinta-suave);
}

.prop-items__texto:hover { border-color: var(--linea-fuerte) !important; background: var(--climia-bg-900) !important; }
.prop-items__texto:focus { border-color: var(--frio) !important; background: var(--climia-bg-900) !important; }

/* Subir y bajar: estas dos flechas funcionan —las mueve el servidor—. */
.prop-items__mover { display: flex; flex-direction: column; gap: 2px; align-items: center; }

.prop-items__mover button {
  width: 20px;
  height: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  font-size: 9px;
  line-height: 1;
  color: var(--tinta-suave);
  background: none;
  border: 1px solid transparent;
  border-radius: 3px;
  cursor: pointer;
}

.prop-items__mover button:hover:not(:disabled) { color: var(--frio); background: var(--frio-claro); border-color: var(--frio-borde); }
.prop-items__mover button:disabled { opacity: 0.3; cursor: default; }

.prop-items__n { font-family: var(--mono); font-size: 11.5px; color: var(--tinta-suave); text-align: center; }

/* El paso de a uno: escribir un «2» en el campo de cantidad es más
   trabajo que apretar «+», y la cantidad casi siempre se mueve de a una. */
.prop-cant {
  display: flex;
  align-items: center;
  width: 96px;
  height: 32px;
  margin: 0 auto;
  border: 1px solid var(--linea-fuerte);
  border-radius: var(--r);
  background: var(--climia-bg-900);
  overflow: hidden;
}

.prop-cant button {
  width: 30px;
  height: 100%;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  font-size: 16px;
  line-height: 1;
  color: var(--frio);
  background: none;
  border: none;
  cursor: pointer;
  user-select: none;
}

.prop-cant button:hover { background: var(--frio-claro); }

.prop-cant input {
  height: 100% !important;
  border: none !important;
  border-left: 1px solid var(--linea) !important;
  border-right: 1px solid var(--linea) !important;
  border-radius: 0 !important;
  box-shadow: none !important;
  background: transparent !important;
  text-align: center;
  padding: 0 !important;
  font-family: var(--mono);
  font-size: 12.5px !important;
}

.prop-items__precio {
  height: 32px !important;
  width: 104px;
  text-align: right;
  font-family: var(--mono);
  font-size: 12.5px !important;
}

/* Las flechas del precio, al costado del campo. Se comportan como el
   control de un campo numérico —aparecen al enfocar o al pasar el mouse—
   pero el campo sigue siendo de texto: tiene que aceptar «4.236,1», y eso
   un `type="number"` lo borra sin avisar. Se esconden con `visibility`
   para que el hueco quede reservado y la columna no tiemble. */
.prop-precio {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 3px;
}

.prop-precio input { flex: 0 1 auto; min-width: 0; }
.prop-items .prop-precio input { width: 100px; }
.prop-agregar__precio .prop-precio input { width: 100%; }

.prop-precio__paso {
  display: flex;
  flex-direction: column;
  flex: none;
  width: 15px;
  visibility: hidden;
}

.prop-precio:hover .prop-precio__paso,
.prop-precio:focus-within .prop-precio__paso { visibility: visible; }

.prop-precio__paso button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 15px;
  height: 15px;
  padding: 0;
  font-size: 8px;
  line-height: 1;
  color: var(--tinta-suave);
  background: var(--superficie-2);
  border: 1px solid var(--linea-fuerte);
  cursor: pointer;
}

.prop-precio__paso button:first-child { border-radius: 3px 3px 0 0; border-bottom: none; }
.prop-precio__paso button:last-child { border-radius: 0 0 3px 3px; }
.prop-precio__paso button:hover { color: var(--frio); background: var(--frio-claro); }
.prop-agregar__precio .prop-precio__paso button { height: 17px; }

.prop-items__subtotal { text-align: right; font-family: var(--mono); font-size: 13px; font-weight: 600; color: var(--tinta); }

.prop-items__quitar {
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto;
  padding: 0;
  color: var(--tinta-suave);
  background: none;
  border: 1px solid transparent;
  border-radius: 7px;
  cursor: pointer;
}

.prop-items__quitar:hover { color: var(--alerta); background: var(--alerta-claro); border-color: var(--alerta-borde); }

/* El aviso de precio de lista pisado, bajo el campo de precio. */
.prop-items__lista { display: block; font-size: 10.5px; color: var(--calor); margin-top: 3px; text-align: right; padding-right: 18px; }

/* ------------------------------------------------------- agregar ítem */

.prop-agregar {
  padding: 11px 14px;
  background: var(--velo);
  border-bottom: 1px solid var(--linea);
}

/* Cerrado no ocupa nada: los disparadores están en la cabecera. */
.prop-agregar[data-actual="cerrado"] { display: none; }

.prop-agregar__fila { display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap; }
.prop-agregar__fila--cerrado { align-items: center; }
.prop-agregar__buscador { position: relative; }

.prop-agregar__buscador .prop-lupa {
  position: absolute;
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  color: var(--tinta-suave);
  pointer-events: none;
}

.prop-agregar__buscador input { padding: 0 10px 0 32px !important; }
.prop-agregar__libre { flex: 1 1 300px; max-width: 520px; }
.prop-agregar__precio { width: 126px; flex: none; }
.prop-agregar__precio input { text-align: right; font-family: var(--mono); }
.prop-agregar .btn { height: 34px; display: inline-flex; align-items: center; font-size: 12.5px; }

.prop-enlace {
  font: inherit;
  font-size: 12.5px;
  color: var(--tinta-suave);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}

.prop-enlace:hover { color: var(--frio); text-decoration: underline; }
.prop-agregar__cerrar { margin-left: auto; }

.prop-resultados {
  margin-top: 9px;
  border: 1px solid var(--linea);
  border-radius: 9px;
  max-height: 260px;
  overflow-y: auto;
  background: var(--superficie);
}

/* Cada resultado es un botón de envío con el id del producto adentro: la
   fila entera es el control. Sin JavaScript la lista no filtra, pero
   elegir sigue funcionando. */
.prop-resultado {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 120px 84px;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 9px 12px;
  text-align: left;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--linea);
  cursor: pointer;
  font: inherit;
  color: inherit;
}

.prop-resultado:last-child { border-bottom: none; }
.prop-resultado:nth-child(even) { background: var(--cebra); }
.prop-resultado:hover, .prop-resultado:focus-visible { background: var(--frio-claro); }
.prop-resultado__nombre { display: block; font-size: 13px; font-weight: 600; color: var(--tinta); }
.prop-resultado__meta { display: block; font-size: 11px; color: var(--tinta-suave); margin-top: 1px; }
.prop-resultado__precio { text-align: right; font-family: var(--mono); font-size: 13px; font-weight: 600; color: var(--tinta); }

.prop-resultado__accion {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 4px;
  height: 28px;
  font-size: 12px;
  font-weight: 600;
  color: var(--frio);
  border: 1px solid var(--frio-borde);
  border-radius: 7px;
}

.prop-resultado:hover .prop-resultado__accion { background: var(--frio); color: var(--climia-bg-950); }
.prop-resultados__vacio { padding: 16px 12px; font-size: 12.5px; color: var(--tinta-suave); text-align: center; }

/* ------------------------------------------------------------ totales */

.prop-totales {
  display: flex;
  align-items: baseline;
  justify-content: flex-end;
  gap: 26px;
  padding: 11px 16px;
  background: var(--velo);
  border-radius: 0 0 var(--r-tarjeta) var(--r-tarjeta);
  flex-wrap: wrap;
}

.prop-totales__caja { text-align: right; }
.prop-totales__rotulo { font-size: 10.5px; font-weight: 600; letter-spacing: 0.06em; color: var(--tinta-suave); text-transform: uppercase; }
.prop-totales__rotulo small { font-size: 10px; font-weight: 400; letter-spacing: 0; text-transform: none; }
.prop-totales__valor { display: block; font-family: var(--mono); font-size: 13.5px; color: var(--tinta-media); }
.prop-totales__caja--descuento .prop-totales__valor { color: var(--frio); }

.prop-totales__caja--total {
  padding: 4px 12px;
  border: 1px solid var(--frio-borde);
  border-radius: 9px;
  background: rgba(18, 200, 255, 0.06);
}

.prop-totales__caja--total .prop-totales__rotulo { color: var(--tinta); }
.prop-totales__caja--total .prop-totales__valor { font-size: 17px; font-weight: 700; color: var(--tinta); }

/* ------------------------------------------------------------- anexos */

.prop-anexos__cabeza { display: flex; align-items: center; gap: 10px; padding: 11px 14px; flex-wrap: wrap; }

.prop-anexos__modo {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.07em;
  border-radius: 5px;
  padding: 2px 7px;
  background: var(--ok-claro);
  border: 1px solid var(--ok-borde);
  color: var(--ok);
}

.prop-anexos__modo--manual { background: var(--calor-claro); border-color: var(--calor-borde); color: var(--calor); }
.prop-anexos__chips { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }

.prop-anexos__chip {
  display: flex;
  align-items: center;
  gap: 5px;
  height: 24px;
  padding: 0 10px;
  border-radius: 12px;
  font-size: 11.5px;
  font-weight: 600;
  background: var(--frio-claro);
  border: 1px solid var(--frio-borde);
  color: var(--frio);
}

.prop-anexos__chip--vacio { background: transparent; border-color: var(--linea); color: var(--tinta-suave); }
.prop-anexos__derecha { display: flex; align-items: center; gap: 10px; margin-left: auto; }
.prop-anexos__derecha .btn { height: 32px; display: inline-flex; align-items: center; padding: 0 14px; font-size: 12.5px; }

.prop-anexos__cuerpo { border-top: 1px solid var(--linea); }

/* Pestañas horizontales, como en la referencia: el subrayado cyan dice
   cuál está abierta, y la cuenta de cada una se ve sin abrirla. */
.prop-anexos__pestanas {
  display: flex;
  gap: 4px;
  padding: 0 12px;
  border-bottom: 1px solid var(--linea);
  overflow-x: auto;
}

.prop-anexos__pestana {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 42px;
  padding: 0 14px;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--tinta-suave);
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  white-space: nowrap;
}

.prop-anexos__pestana:hover { color: var(--tinta); }

.prop-anexos__pestana--activa {
  color: var(--tinta);
  border-bottom-color: var(--frio);
  background: linear-gradient(180deg, rgba(18, 200, 255, 0.08), transparent);
}

.prop-anexos__cuenta {
  min-width: 20px;
  text-align: center;
  font-size: 10.5px;
  font-weight: 700;
  border-radius: 10px;
  padding: 1px 6px;
  background: var(--frio-claro);
  color: var(--frio);
}

.prop-anexos__cuenta--vacia { background: var(--superficie-2); color: var(--tinta-suave); }
.prop-anexos__panel { padding: 10px 14px 14px; }
.prop-anexos__pista { font-size: 12px; color: var(--tinta-suave); margin: 0 0 10px; }

.prop-anexos__grilla {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
  gap: 10px;
}

/* Las imágenes van en tarjetas grandes: se eligen mirándolas. */
.prop-anexos__grilla--imagen { grid-template-columns: repeat(auto-fill, minmax(190px, 1fr)); }

.prop-opcion {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 56px;
  padding: 9px 10px;
  border: 1px solid var(--linea);
  border-radius: 10px;
  background: var(--superficie);
  cursor: pointer;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
  transition: border-color 120ms ease, background 120ms ease;
}

.prop-opcion:hover { border-color: var(--climia-line-600); }
.prop-opcion:has(input:checked) { border-color: var(--frio-borde); background: rgba(18, 200, 255, 0.07); }
.prop-opcion:has(input:focus-visible) { outline: 2px solid var(--frio); outline-offset: 2px; }
.prop-opcion input { width: 16px; height: 16px; flex: none; accent-color: var(--climia-cyan-400); cursor: pointer; }

.prop-opcion__miniatura {
  width: 46px;
  height: 34px;
  flex: none;
  border-radius: 6px;
  background: var(--superficie-3);
  object-fit: cover;
}

.prop-anexos__grilla--imagen .prop-opcion { flex-direction: column; align-items: stretch; padding: 0; overflow: hidden; }
.prop-anexos__grilla--imagen .prop-opcion input { position: absolute; top: 8px; left: 8px; z-index: 1; }
.prop-anexos__grilla--imagen .prop-opcion__miniatura { width: 100%; height: 96px; border-radius: 0; }
.prop-anexos__grilla--imagen .prop-opcion__texto { padding: 7px 10px 9px; }
.prop-anexos__grilla--imagen .prop-opcion__auto { position: absolute; top: 8px; right: 8px; }

.prop-opcion__texto { display: flex; flex-direction: column; min-width: 0; }
.prop-opcion__nombre { font-size: 12.5px; font-weight: 600; color: var(--tinta); }
.prop-opcion__meta { font-size: 11px; color: var(--tinta-suave); }

.prop-opcion__auto {
  margin-left: auto;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.07em;
  color: var(--ok);
  background: var(--velo-fuerte);
  border: 1px solid var(--ok-borde);
  border-radius: 4px;
  padding: 1px 5px;
}

/* La tarjeta que lleva a cargar más, al final de cada grilla. */
.prop-opcion--cargar {
  justify-content: center;
  flex-direction: column;
  gap: 6px;
  border-style: dashed;
  border-color: var(--frio-borde);
  background: rgba(0, 152, 226, 0.04);
  color: var(--frio);
  font-size: 12px;
  text-align: center;
}

.prop-opcion--cargar:hover { background: var(--frio-claro); text-decoration: none; }
.prop-anexos__grilla--imagen .prop-opcion--cargar { padding: 14px; min-height: 140px; }

/* ----------------------------------------------------------------- pie */

/* La nota del congelamiento y el borrado, en la misma línea y bien
   separados: eliminar la cotización es lo único irreversible de la
   pantalla y no tiene por qué estar cerca de lo que se aprieta todos los
   días. */
.prop-pie { display: flex; align-items: center; gap: 10px; margin-top: 12px; padding: 0 2px; flex-wrap: wrap; }
.prop-pie__nota { font-size: 11.5px; color: var(--tinta-suave); }
.prop-pie form { margin-left: auto; }

.prop-pie__borrar {
  font: inherit;
  font-size: 12px;
  color: var(--alerta);
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
}

.prop-pie__borrar:hover { text-decoration: underline; }

/* ------------------------------------------------------ columna derecha */

.prop__riel {
  position: sticky;
  top: calc(var(--alto-cabecera) + 82px);
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-height: calc(100vh - var(--alto-cabecera) - 94px);
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--linea-fuerte) transparent;
}

.prop__riel-cerrar { display: none; }

.riel-tarjeta {
  background: var(--climia-gradient-panel);
  border: 1px solid var(--linea);
  border-radius: var(--r-tarjeta);
  padding: 14px;
}

/* El banner es marca: el recorte se queda con el equipo y deja afuera el
   borde izquierdo del archivo, que trae restos de texto. */
.riel-banner {
  position: relative;
  height: 118px;
  flex: none;
  border: 1px solid var(--linea);
  border-radius: var(--r-tarjeta);
  overflow: hidden;
  background: var(--climia-bg-900);
}

.riel-banner img {
  position: absolute;
  right: 0;
  top: 0;
  height: 100%;
  width: auto;
  max-width: none;
  opacity: 0.9;
}

.riel-banner::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(3, 17, 31, 0.96) 0%, rgba(3, 17, 31, 0.7) 42%, transparent 75%);
}

.riel-banner__texto {
  position: absolute;
  left: 14px;
  top: 50%;
  transform: translateY(-50%);
  z-index: 1;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  line-height: 1.45;
  text-transform: uppercase;
  color: var(--tinta);
}

.riel-banner__texto b { font-weight: 700; color: var(--frio); }

/* El asistente. Visible pero apagado: todo lo que haría está listado y
   desactivado, con su rótulo. */
.riel-asistente { box-shadow: var(--climia-glow-soft); }

.riel-asistente__cabeza { display: flex; align-items: center; gap: 10px; }

.riel-asistente__robot {
  width: 56px;
  height: 72px;
  flex: none;
  object-fit: cover;
  object-position: 70% 30%;
  border-radius: 10px;
  border: 1px solid var(--linea);
}

.riel-asistente__antes { font-size: 11.5px; color: var(--tinta-media); }

.riel-asistente__nombre {
  margin: 0;
  font-size: 20px;
  font-weight: 800;
  letter-spacing: -0.01em;
  text-transform: none;
  color: var(--frio);
}

.riel-asistente__sub { font-size: 11px; color: var(--tinta-suave); line-height: 1.35; }

.riel-asistente__insignia {
  align-self: flex-start;
  margin-left: auto;
  font-size: 9px;
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--calor);
  background: var(--calor-claro);
  border: 1px solid var(--calor-borde);
  padding: 3px 6px;
  border-radius: 6px;
  white-space: nowrap;
}

.riel-asistente__acciones { list-style: none; margin: 12px 0 0; padding: 0; }

.riel-asistente__acciones button {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  min-height: 34px;
  padding: 0 2px;
  font: inherit;
  font-size: 12px;
  text-align: left;
  color: var(--tinta-suave);
  background: none;
  border: none;
  border-top: 1px solid var(--linea-tenue);
  cursor: not-allowed;
}

.riel-asistente__acciones button .prop-ico { color: var(--tinta-apagada); }
.riel-asistente__acciones small { margin-left: auto; font-size: 10px; color: var(--tinta-apagada); }

.riel-asistente__nota { margin: 8px 0 0; font-size: 11px; line-height: 1.45; color: var(--tinta-suave); }

.riel-asistente__pedir {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  width: 100%;
  height: 36px;
  margin-top: 10px;
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--tinta-suave);
  background: transparent;
  border: 1px dashed var(--linea-fuerte);
  border-radius: var(--r-boton);
  cursor: not-allowed;
}

/* El resumen: el total es el dato dominante de la pantalla. */
.riel-resumen__titulo {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 10px;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  color: var(--tinta);
}

.riel-resumen__titulo .prop-ico { color: var(--frio); }

.riel-resumen__filas { margin: 0; display: flex; flex-direction: column; gap: 5px; }
.riel-resumen__filas > div { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.riel-resumen__filas dt { font-size: 12.5px; color: var(--tinta-media); }
.riel-resumen__filas dt small { font-size: 10.5px; color: var(--tinta-suave); }
.riel-resumen__filas dd { margin: 0; font-family: var(--mono); font-size: 13px; font-weight: 600; color: var(--tinta); white-space: nowrap; }

.riel-resumen__total {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 12px;
  padding: 10px 12px;
  border: 1px solid var(--climia-cyan-400);
  border-radius: 10px;
  background: linear-gradient(90deg, rgba(8, 125, 232, 0.28), rgba(18, 200, 255, 0.08));
  box-shadow: var(--climia-glow-primary);
}

.riel-resumen__total span { font-size: 14px; font-weight: 700; color: var(--tinta); }
.riel-resumen__total b { font-family: var(--mono); font-size: 20px; font-weight: 700; color: var(--tinta); white-space: nowrap; }

.riel-resumen__aceptado { margin-top: 8px; font-size: 12.5px; color: var(--ok); }
.riel-resumen__aceptado b { font-family: var(--mono); }

.riel-resumen__cuenta {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-top: 10px;
  font-size: 12px;
  color: var(--frio);
}

.riel-resumen__guardar { width: 100%; height: 38px; margin-top: 12px; }
.riel-resumen__nota { margin-top: 6px; font-size: 11px; color: var(--tinta-suave); text-align: center; }

/* En ventanas bajas el banner cede su alto al resumen. */
@media screen and (max-height: 880px) { .riel-banner { display: none; } }

/* ------------------------------------------------- barra fija de abajo

   El total a la vista en ventanas angostas, donde la columna derecha no
   está. Con la columna visible esta barra sobra. */
.prop-guardar {
  position: sticky;
  bottom: 0;
  z-index: 25;
  display: none;
  align-items: center;
  gap: 14px;
  min-height: 58px;
  margin-top: 16px;
  padding: 0 16px;
  background: var(--pie-fondo);
  border-top: 1px solid var(--linea-fuerte);
  box-shadow: 0 -8px 24px var(--sombra);
}

.prop-guardar .btn { height: 38px; display: inline-flex; align-items: center; padding: 0 20px; }
.prop-guardar__nota { font-size: 12px; color: var(--tinta-suave); }
.prop-guardar__resumen { margin-left: auto; font-size: 12px; color: var(--tinta-suave); }
.prop-guardar__total { font-family: var(--mono); font-size: 18px; font-weight: 700; color: var(--tinta); }

/* ------------------------------------------------------- por ancho

   ≥ 1280: la composición completa, con la columna derecha fija.
   1024–1279: la columna pasa a panel, que se abre con «ClimIA» desde la
   barra; vuelve la barra fija de abajo con el total.
   < 1024: además la barra lateral de la app se esconde (ver el armazón). */
@media screen and (max-width: 1279px) {
  .prop__rejilla { grid-template-columns: minmax(0, 1fr); }
  .prop__riel-abrir { display: inline-flex !important; }
  .prop-guardar { display: flex; }

  .prop__riel {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    width: min(340px, 92vw);
    max-height: none;
    padding: 50px 14px 14px;
    background: var(--climia-bg-900);
    border-left: 1px solid var(--linea);
    box-shadow: -10px 0 40px var(--sombra);
    transform: translateX(104%);
    transition: transform 160ms ease;
    z-index: 75;
  }

  .riel-abierto .prop__riel { transform: none; }

  .prop__riel-cerrar {
    display: grid;
    place-items: center;
    position: absolute;
    top: 10px;
    right: 12px;
    width: 32px;
    height: 32px;
    font-size: 14px;
    color: var(--tinta-media);
    background: none;
    border: 1px solid var(--linea);
    border-radius: var(--r-boton);
    cursor: pointer;
  }

  .prop__riel-velo { position: fixed; inset: 0; z-index: 72; background: var(--climia-overlay); }
  .riel-banner { display: none; }
}

@media screen and (max-width: 900px) {
  .prop { margin: -18px -16px -48px; }
  .prop__num { font-size: 20px; }
  .prop-guardar__nota { display: none; }
}

@media screen and (max-width: 720px) {
  .prop__acciones { margin-left: 0; }
  .prop-items__cabeza .prop-agregar__buscador { margin-left: 0; flex-basis: 100%; max-width: none; }
  .prop-items__modo { margin-left: 0; }
}

/* ------------------------------------------------ listado de propuestas

   Los botones de cada fila en un renglón: Abrir, PDF, Duplicar y la «×».
   Los formularios van en línea —duplicar y eliminar son POST, y un
   <form> por defecto es un bloque que parte la fila en tres renglones—. */
.acciones-propuesta { justify-content: flex-end; flex-wrap: nowrap; gap: 6px; }
.acciones-propuesta form { display: flex; margin: 0; }

/* Eliminar es una «×» y no un botón con texto: es lo menos frecuente de
   la fila y lo único irreversible, así que ocupa lo mínimo y va al final,
   lejos de Abrir. Rojo sólo al pasar el mouse, para que una columna de
   cien filas no sea una columna de cien alarmas. */
.acciones-propuesta__borrar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  padding: 0;
  font: inherit;
  font-size: 16px;
  line-height: 1;
  color: var(--tinta-suave);
  background: none;
  border: 1px solid transparent;
  border-radius: 5px;
  cursor: pointer;
}

.acciones-propuesta__borrar:hover { color: var(--alerta); background: var(--alerta-claro); border-color: var(--alerta-borde); }
.acciones-propuesta__borrar--hueco { cursor: default; }
.acciones-propuesta__borrar--hueco:hover { background: none; border-color: transparent; }


/* =====================================================================
   Técnicos — tarjetas y ficha
   ---------------------------------------------------------------------
   La lista pasó de filas de formulario a tarjetas con la foto de cada
   uno (16-sep-2026). Es a quién se manda a la casa de un cliente: se
   reconoce por la cara antes que por el nombre, y la misma foto va a ir
   en el informe que recibe el cliente. Lo que se edita vive en la ficha,
   que reusa el esqueleto de la pantalla de propuestas (`.prop`).
   ===================================================================== */

.tec-grilla {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 12px;
}

.tec-tarjeta {
  display: flex;
  flex-direction: column;
  background: var(--superficie);
  border: 1px solid var(--linea-fuerte);
  border-radius: 5px;
  overflow: hidden;
  color: inherit;
  transition: border-color 120ms ease, box-shadow 120ms ease;
}

.tec-tarjeta:hover { border-color: var(--frio); box-shadow: 0 2px 10px var(--sombra); text-decoration: none; }

/* Un técnico dado de baja sigue figurando —hizo trabajos que tienen su
   nombre— pero atrás y apagado, para que no se lo mande a ningún lado. */
.tec-tarjeta--inactivo { opacity: 0.55; }
.tec-tarjeta--inactivo .tec-foto img { filter: grayscale(1); }

/* Cuadrada, como pidió el usuario: la foto manda. `object-fit: cover`
   recorta lo que sobre en vez de deformar la cara. */
.tec-foto {
  position: relative;
  aspect-ratio: 1 / 1;
  background: var(--frio-claro);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}

.tec-foto img { width: 100%; height: 100%; object-fit: cover; display: block; }

.tec-foto__iniciales {
  font-size: 54px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--tinta-suave);
}

.tec-foto__estado {
  position: absolute;
  top: 8px;
  left: 8px;
}

.tec-tarjeta__cuerpo { padding: 10px 12px 12px; display: flex; flex-direction: column; gap: 2px; flex: 1; }
.tec-tarjeta__nombre { font-size: 14.5px; font-weight: 700; color: var(--tinta); line-height: 1.25; }
.tec-tarjeta__cargo { font-size: 12.5px; color: var(--tinta-media); }
.tec-tarjeta__dato { font-size: 12px; color: var(--tinta-suave); }
.tec-tarjeta__dato b { font-weight: 600; color: var(--tinta-media); }

/* Lo que le falta para el informe al cliente, en ámbar: no es un error,
   es trabajo pendiente. */
.tec-tarjeta__falta {
  margin-top: 6px;
  align-self: flex-start;
  font-size: 11px;
  font-weight: 600;
  color: var(--calor);
  background: var(--calor-claro);
  border: 1px solid var(--calor-borde);
  border-radius: 3px;
  padding: 1px 6px;
}

.tec-tarjeta__pie {
  display: flex;
  gap: 1px;
  border-top: 1px solid var(--linea);
  background: var(--linea);
}

.tec-tarjeta__pie a {
  flex: 1;
  padding: 7px 8px;
  text-align: center;
  font-size: 12px;
  font-weight: 600;
  background: var(--superficie-2);
  color: var(--frio);
}

.tec-tarjeta__pie a:hover { background: var(--frio-claro); text-decoration: none; }

/* El alta, como una tarjeta más al final de la grilla: agregar a alguien
   es ocupar el próximo lugar, no ir a otra pantalla. */
.tec-nuevo {
  border-style: dashed;
  background: var(--superficie-2);
  padding: 12px;
  gap: 8px;
}

.tec-nuevo:hover { box-shadow: none; }
.tec-nuevo__titulo { font-size: 13px; font-weight: 700; color: var(--tinta); }
.tec-nuevo input { height: 30px; padding: 0 9px; font-size: 13px; border-radius: 3px; }

/* ------------------------------------------------------------ la ficha */

.ficha-tec__foto {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  width: 150px;
  flex: none;
}

.ficha-tec__marco {
  width: 150px;
  height: 150px;
  border-radius: 5px;
  border: 1px solid var(--linea-fuerte);
  background: var(--frio-claro);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}

.ficha-tec__marco img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ficha-tec__marco .tec-foto__iniciales { font-size: 46px; }

/* El input de archivo nativo es feo e ilegible; se esconde y lo reemplaza
   un botón que lo dispara. Sigue siendo el mismo control, con su foco. */
.ficha-tec__archivo { position: absolute; width: 1px; height: 1px; opacity: 0; }
.ficha-tec__archivo:focus-visible + .btn { outline: 2px solid var(--frio); outline-offset: 2px; }
.ficha-tec__foto .btn { height: 28px; display: inline-flex; align-items: center; font-size: 12px; border-radius: 3px; }
.ficha-tec__nota { font-size: 11px; color: var(--tinta-suave); text-align: center; }

.ficha-tec__identidad { display: flex; gap: 16px; align-items: flex-start; flex-wrap: wrap; }
.ficha-tec__identidad > .ficha-tec__campos { flex: 1 1 360px; min-width: 0; }

.ficha-grid { display: grid; gap: 10px; }
.ficha-grid + .ficha-grid { margin-top: 9px; }
.ficha-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.ficha-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.ficha-grid--ci { grid-template-columns: minmax(0, 1fr) 90px 150px; }
.ficha-grid--trabajo { grid-template-columns: 170px 170px minmax(0, 1fr) minmax(0, 1fr); }

@media screen and (max-width: 860px) {
  .ficha-grid--2, .ficha-grid--3, .ficha-grid--ci, .ficha-grid--trabajo { grid-template-columns: minmax(0, 1fr); }
}

/* Lo que va a ver el cliente, marcado: el operador tiene que saber qué
   campos salen en un papel ajeno antes de escribirlos. */
.ficha-tec__cliente {
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--frio);
  background: var(--frio-claro);
  border: 1px solid var(--frio-borde);
  border-radius: 3px;
  padding: 0 4px;
  margin-left: 4px;
  vertical-align: 1px;
}

/* El botón de la foto es un <label> —así dispara el input de archivo sin
   JavaScript— y hereda de la regla global de etiquetas las mayúsculas y
   el espaciado de un rótulo de campo. Acá tiene que verse como un botón. */
.ficha-tec__foto label.btn { text-transform: none; letter-spacing: 0.04em; color: var(--tinta); }

/* ------------------------------------------ Parámetros: diseño de la plataforma

   Dos tarjetas elegibles, cada una con una muestra en miniatura. Los
   colores de la muestra van fijos a propósito —y son la única excepción a
   la regla de pedir colores por rol—: la muestra del diseño claro tiene
   que verse clara aunque la pantalla esté en oscuro, y al revés. */
.disenos { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 320px)); gap: 14px; }

.diseno-opcion {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px;
  border: 1px solid var(--linea-fuerte);
  border-radius: var(--r-tarjeta);
  background: var(--superficie);
  cursor: pointer;
  font-size: 13px;
  letter-spacing: 0;
  text-transform: none;
  color: var(--tinta-media);
}

.diseno-opcion:hover { border-color: var(--frio-borde); }
.diseno-opcion:has(input:checked) { border-color: var(--frio); box-shadow: 0 0 0 1px var(--frio), var(--climia-glow-soft); }
.diseno-opcion:has(input:focus-visible) { outline: 2px solid var(--frio); outline-offset: 2px; }
.diseno-opcion input { position: absolute; top: 14px; right: 14px; width: 16px; height: 16px; accent-color: var(--frio); }
.diseno-opcion .tag { position: absolute; bottom: 12px; right: 12px; }
.diseno-opcion__texto { display: flex; flex-direction: column; gap: 2px; padding-right: 60px; }
.diseno-opcion__texto b { font-size: 14px; color: var(--tinta); }
.diseno-opcion__texto small { font-size: 12px; color: var(--tinta-suave); }

.diseno-muestra {
  display: flex;
  height: 110px;
  border-radius: 7px;
  overflow: hidden;
  border: 1px solid rgba(127, 163, 196, 0.4);
}

.diseno-muestra__lateral { display: flex; flex-direction: column; gap: 6px; width: 26%; padding: 10px 7px; }
.diseno-muestra__lateral i { display: block; height: 6px; border-radius: 3px; }
.diseno-muestra__cuerpo { flex: 1; display: flex; flex-direction: column; gap: 8px; padding: 8px; }
.diseno-muestra__barra { height: 12px; border-radius: 3px; }
.diseno-muestra__tarjeta { flex: 1; display: flex; flex-direction: column; gap: 6px; padding: 8px; border-radius: 5px; }
.diseno-muestra__tarjeta i { display: block; height: 6px; width: 70%; border-radius: 3px; }
.diseno-muestra__tarjeta b { display: block; margin-top: auto; align-self: flex-end; width: 34%; height: 12px; border-radius: 3px; }

.diseno-muestra--oscuro { background: #03111f; }
.diseno-muestra--oscuro .diseno-muestra__lateral { background: #06192b; border-right: 1px solid #123c5d; }
.diseno-muestra--oscuro .diseno-muestra__lateral i { background: #123c5d; }
.diseno-muestra--oscuro .diseno-muestra__lateral i:nth-child(2) { background: #12c8ff; box-shadow: 0 0 8px rgba(18, 200, 255, 0.5); }
.diseno-muestra--oscuro .diseno-muestra__barra { background: #071d31; border: 1px solid #123c5d; }
.diseno-muestra--oscuro .diseno-muestra__tarjeta { background: #0a243b; border: 1px solid #123c5d; }
.diseno-muestra--oscuro .diseno-muestra__tarjeta i { background: #78a8c7; opacity: 0.6; }
.diseno-muestra--oscuro .diseno-muestra__tarjeta b { background: #087de8; box-shadow: 0 0 8px rgba(18, 200, 255, 0.4); }

.diseno-muestra--claro { background: #E2EDF7; }
.diseno-muestra--claro .diseno-muestra__lateral { background: #0D3B66; }
.diseno-muestra--claro .diseno-muestra__lateral i { background: #1D5B94; }
.diseno-muestra--claro .diseno-muestra__lateral i:nth-child(2) { background: #BBD3E8; }
.diseno-muestra--claro .diseno-muestra__barra { background: #ffffff; border: 1px solid #B9CFE3; }
.diseno-muestra--claro .diseno-muestra__tarjeta { background: #ffffff; border: 1px solid #D2E1EE; }
.diseno-muestra--claro .diseno-muestra__tarjeta i { background: #B9CFE3; }
.diseno-muestra--claro .diseno-muestra__tarjeta b { background: #1B75BC; }

/* =====================================================================
   Fondo dinámico de ClimIA (23-sep-2026)
   ---------------------------------------------------------------------
   Detrás de toda la app, sólo en el diseño oscuro. Lo arma
   `partials/fondoClimia.eta` y lo anima `public/fondo/fondo-climia.js`.

   Tiene que percibirse y después olvidarse: todo es lento, chico y
   transparente, y el centro —donde van las tarjetas— queda más limpio.
   Sólo se anima `transform` y `opacity`, que los hace el compositor.

   Para bajar o subir todo de una vez: `--fondo-intensidad` (0 apaga las
   capas animadas, 1 es lo diseñado, más de 1 no se recomienda).
   ===================================================================== */

.fondo-climia {
  --fondo-intensidad: 1;
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
  background: var(--climia-bg-950);
}

/* Todo lo de la app va encima. Los paneles que se abren (el menú en
   angosto, la columna de la propuesta) están adentro de `.app`, así que
   también quedan por encima del fondo. */
.app { position: relative; z-index: 1; }

.fondo-climia__base {
  position: absolute;
  inset: 0;
  background: url("/fondo/climia-dynamic-base.webp") center / cover no-repeat;
}

.fc-defs { position: absolute; width: 0; height: 0; }

.fc-corriente,
.fondo-climia__nodos,
.fondo-climia__lienzo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

/* Las corrientes: tres trazos por esquina —un halo ancho, el cuerpo y una
   línea fina— con el degradé que se enciende en el medio. El desenfoque
   es de toda la capa, y como la capa sólo se traslada, se calcula una vez. */
.fc-corriente {
  opacity: var(--fondo-intensidad);
  filter: blur(1.2px);
  will-change: transform;
  animation: fc-mecer 22s ease-in-out infinite alternate;
}

.fc-corriente path { fill: none; stroke: url(#fc-aire); stroke-linecap: round; stroke-width: 3.2; opacity: 0.28; }
.fc-corriente .fc-ancha { stroke-width: 18; opacity: 0.09; }
.fc-corriente .fc-fina { stroke-width: 1.6; opacity: 0.2; }

/* Velocidades y sentidos distintos, y arranques corridos con un retraso
   negativo: cuatro corrientes al compás se verían como una sola animación. */
.fc-corriente--1 { animation-duration: 14s; animation-delay: -3s; }
.fc-corriente--2 { animation-duration: 11s; animation-delay: -8s; animation-direction: alternate-reverse; }
.fc-corriente--3 { animation-duration: 16s; animation-delay: -5s; }
.fc-corriente--4 { animation-duration: 10s; animation-delay: -9s; animation-direction: alternate-reverse; }
.fc-corriente--5 { animation-duration: 13s; animation-delay: -2s; opacity: calc(var(--fondo-intensidad) * 0.7); }
.fc-corriente--6 { animation-duration: 12s; animation-delay: -6s; animation-direction: alternate-reverse; opacity: calc(var(--fondo-intensidad) * 0.7); }

/* Un vaivén, no un giro: hasta ~80 px de lado y 24 de alto. */
@keyframes fc-mecer {
  0%   { transform: translate3d(-30px, 10px, 0); }
  35%  { transform: translate3d(6px, -14px, 0); }
  70%  { transform: translate3d(34px, 8px, 0); }
  100% { transform: translate3d(48px, -10px, 0); }
}

/* El barrido de aire: una franja inclinada y muy tenue que cruza de
   izquierda a derecha y descansa fuera de la pantalla antes de volver. */
.fondo-climia__barrido {
  position: absolute;
  top: -20%;
  bottom: -20%;
  left: 0;
  width: 38%;
  background: linear-gradient(90deg, rgba(18, 200, 255, 0) 0%, rgba(18, 200, 255, 0.05) 40%, rgba(120, 230, 255, 0.09) 50%, rgba(18, 200, 255, 0.05) 60%, rgba(18, 200, 255, 0) 100%);
  opacity: var(--fondo-intensidad);
  transform: translate3d(-120%, 0, 0) skewX(-18deg);
  will-change: transform;
  animation: fc-barrer 16s cubic-bezier(0.45, 0, 0.3, 1) infinite;
}

@keyframes fc-barrer {
  0%   { transform: translate3d(-120%, 0, 0) skewX(-18deg); }
  55%  { transform: translate3d(330%, 0, 0) skewX(-18deg); }
  100% { transform: translate3d(330%, 0, 0) skewX(-18deg); }
}

/* Los nodos laten: 0,30 → 0,80 de opacidad y 1 → 1,15 de tamaño. */
.fondo-climia__nodos { opacity: var(--fondo-intensidad); }

.fc-nodo {
  transform-box: fill-box;
  transform-origin: center;
  opacity: 0.3;
  animation: fc-latir 5s ease-in-out infinite;
}

@keyframes fc-latir {
  0%, 100% { opacity: 0.3; transform: scale(1); }
  50%      { opacity: 0.95; transform: scale(1.3); }
}

.fondo-climia__lienzo { opacity: var(--fondo-intensidad); }

/* El velo de legibilidad: el centro, donde va el contenido, queda un paso
   más oscuro y parejo; los bordes, donde vive el dibujo, apenas. */
.fondo-climia__velo {
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 62% 58% at 55% 48%, rgba(2, 11, 26, 0.55) 0%, rgba(2, 11, 26, 0.32) 55%, rgba(2, 11, 26, 0) 100%),
    radial-gradient(circle at 50% 45%, rgba(2, 11, 26, 0.15) 0%, rgba(2, 11, 26, 0.08) 45%, rgba(1, 8, 20, 0.2) 100%);
}

/* En teléfono se quedan la imagen, dos corrientes y el lienzo (que ya
   dibuja la mitad de partículas): menos capas moviéndose, menos batería. */
@media screen and (max-width: 767px) {
  .fc-corriente--2, .fc-corriente--3, .fc-corriente--5, .fc-corriente--6 { display: none; }
}

/* Quien pidió menos movimiento ve la imagen fija y nada más. */
@media (prefers-reduced-motion: reduce) {
  .fc-corriente, .fondo-climia__nodos, .fondo-climia__lienzo, .fondo-climia__barrido { display: none; }
}

@media print {
  .fondo-climia { display: none !important; }
}

/* La caja de entrada, por encima del fondo dinámico. */
.entrada__caja { position: relative; z-index: 1; }

/* Los títulos de página quedan sobre el dibujo del fondo, no sobre una
   tarjeta: una sombra casi invisible los separa de las líneas que pasan
   por detrás. */
/* Sólo en pantalla y nunca adentro de una hoja: al imprimir, Chrome
   convierte un texto con sombra en una imagen, y el título del comprobante
   salía en el PDF como un recuadro rasterizado. Lo detectó la comparación
   contra `main`. */
@media screen {
  .app .contenido h1:not(.hoja h1) { text-shadow: 0 1px 10px rgba(3, 17, 31, 0.95), 0 0 2px rgba(3, 17, 31, 0.9); }
}

/* Las tarjetas son de vidrio: dejan ver el fondo dinámico. Primero se las
   había hecho opacas para que ninguna línea del dibujo cruzara una tabla;
   el usuario pidió lo contrario —el fondo está para verse— y la opacidad
   quedó en lo justo para leer (ver `--panel-vidrio`). */
.bloque,
.prop-tarjeta,
.riel-tarjeta { background: var(--panel-vidrio); }
