/* Comparador de mayoristas — hoja de estilo única.

   Un solo tema, claro. TODOS los colores, radios, sombras y tipografías se
   declaran una vez en :root y no se vuelve a escribir un color suelto en el
   resto del fichero: cambiar la paleta es tocar este bloque y nada más.

   Los nombres largos (--bg, --ink, --accent…) son los de la paleta. Debajo
   quedan los nombres antiguos (--fondo, --texto, --acento…) apuntando a ellos:
   así las plantillas que todavía no se han reescrito siguen viéndose bien y no
   hay ni un día con la interfaz a medias. */

:root {
  /* La paleta es la de pcracing.pro, sacada de sus propias variables: papel
     crema, negro casi puro, rojo PC Racing para lo que se pulsa y franja negra
     para la navegación. */

  /* Fondos y papel */
  --bg: #FFFBF9;
  --surface: #FFFFFF;
  --surface-2: #FAF4F0;

  /* Tinta, de más oscura a más tenue */
  --ink: #010102;
  --ink-2: #2B2E35;
  --ink-3: #51555E;
  --ink-4: #676C77;

  /* Líneas */
  --line: #E6DEDA;
  --line-soft: #F0EAE6;

  /* Rojo PC Racing: lo que se puede pulsar y la sección abierta */
  --accent: #BC0009;
  --accent-strong: #960007;
  --accent-soft: #FCEBEA;

  /* Verde: la mejor compra y lo que está al día */
  --good: #006911;
  --good-strong: #004D0C;
  --good-soft: #E6F2E7;

  /* Ámbar: lo que hay que mirar, nunca un error */
  --warn: #8A4B00;
  --warn-text: #6E3C00;
  --warn-soft: #FCEFD9;
  --warn-bar: #D98A1C;

  /* Gris de relleno para chips sin significado */
  --neutral-soft: #F5EFEB;

  /* Lo que rompe algo (agotado, borrar). Granate y no el rojo de la marca:
     si fueran el mismo, un enlace y un «agotado» se leerían igual. */
  --danger: #8C1C2C;
  --danger-soft: #F7E9EB;

  /* La franja negra de la web (menú lateral) y lo que va encima de ella. */
  --oscuro: #08060A;
  --oscuro-2: #17151B;
  --oscuro-linea: #2A2730;
  --oscuro-texto: #ECE8E6;
  --oscuro-tenue: #92959C;
  --rojo-sobre-oscuro: #FF3434;
  --verde-sobre-oscuro: #3DBE5C;

  /* Forma: la web va de esquinas casi rectas. */
  --radio: 6px;         /* tarjetas */
  --radio-bloque: 4px;  /* bloques dentro de una tarjeta */
  --radio-s: 4px;       /* botones y campos */
  --radio-chip: 3px;    /* pastillas */
  --sombra: 0 1px 2px rgba(1, 1, 2, .05);
  --sombra-alta: 0 4px 14px rgba(1, 1, 2, .09);
  --foco: 0 0 0 3px var(--accent-soft);

  /* Tipografías de la web. Se sirven desde static/fuentes.css, sin pedirle
     nada a Google: la herramienta se ve igual sin internet. */
  --fuente: "Inter", -apple-system, "Segoe UI", Roboto, sans-serif;
  --fuente-titulo: "Rajdhani", "Inter", "Segoe UI", sans-serif;
  --fuente-mono: "JetBrains Mono", "Cascadia Code", Consolas, monospace;

  /* Flecha de los desplegables. Es el url() entero y no solo el color porque
     dentro de un url() no se sustituyen variables. Dibujada con el tono de
     --ink-4. */
  --flecha: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5 6 6.5l5-5' fill='none' stroke='%23676C77' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");

  /* --- Nombres antiguos, para no romper nada mientras se reescribe -------- */
  --fondo: var(--bg);
  --fondo-2: var(--neutral-soft);
  --panel: var(--surface);
  --panel-2: var(--surface-2);
  --borde: var(--line-soft);
  --borde-fuerte: var(--line);
  --texto: var(--ink);
  --suave: var(--ink-3);
  --tenue: var(--ink-4);
  --acento: var(--accent);
  --acento-2: var(--accent);
  --acento-suave: var(--accent-soft);
  --verde: var(--good);
  --verde-fondo: var(--good-soft);
  --verde-borde: #BCDCC0;
  --rojo: var(--danger);
  --rojo-fondo: var(--danger-soft);
  --ambar: var(--warn);
  --ambar-fondo: var(--warn-soft);
}

* { box-sizing: border-box; }

html { color-scheme: light; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 15px/1.55 var(--fuente);
  -webkit-font-smoothing: antialiased;
}

/* Cualquier cifra, en cualquier sitio, con las cifras del mismo ancho: es lo
   que permite comparar dos precios sin leerlos. */
.num, .precio, td.num, th.num, input[type=number],
.cifra, .valor, .dato, time, .mono { font-variant-numeric: tabular-nums; }

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

/* Lo que se copia y se pega: comandos, EAN, referencias. */
code, .mono {
  font-family: var(--fuente-mono);
  font-size: .92em;
  letter-spacing: -.01em;
}
/* Un comando no lleva espacios donde partirlo, y `.venv\Scripts\python.exe -m
   src.cli entrar` medía 480 px de una pieza: era lo que hacía la página más
   ancha que la pantalla y arrastraba con ella todo lo demás. Se desplaza él
   solo, sin partirse: un comando cortado a la mitad no se puede pegar. */
code {
  background: var(--neutral-soft); padding: 2px 7px; border-radius: 6px;
  display: inline-block; max-width: 100%; overflow-x: auto;
  vertical-align: bottom;
}

/* Iconos. Trazo, nunca relleno, y del color del texto que tienen al lado: así
   un icono dentro de un botón ámbar sale ámbar sin escribir un color más. */
.ico {
  flex: 0 0 auto; display: inline-block; vertical-align: -.18em;
  fill: none; stroke: currentColor; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
}

/* Lo que solo tiene que leer un lector de pantalla. */
.solo-lectores {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* --- Armazón: menú lateral fijo + contenido ------------------------------ */

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

/* Negro, como la franja de arriba de pcracing.pro, con la bandera a cuadros y
   el rojo de la marca en la sección abierta. */
.lateral {
  position: fixed; top: 0; left: 0; bottom: 0; width: 240px; z-index: 30;
  background: var(--oscuro); color: var(--oscuro-texto);
  border-right: 1px solid var(--oscuro-linea);
  display: flex; flex-direction: column; gap: 6px;
  padding: 22px 16px 16px;
  overflow-y: auto;
}
/* El hueco que deja el menú fijo. Va en un elemento aparte y no en un
   padding-left del main porque así el contenido sigue centrándose solo. */
.hueco-lateral { flex: 0 0 240px; }

/* La marca vale igual en el menú y en la pantalla de la contraseña, que no
   hereda de base.html. Por eso no va colgada de .lateral. */
.marca { display: flex; align-items: center; gap: 10px; color: var(--ink); }
.marca:hover { text-decoration: none; opacity: .85; }
/* La bandera a cuadros del logo: negro y rojo de la marca. */
.marca .bandera { flex: 0 0 auto; display: block; }
.marca .bandera .c1 { fill: var(--accent); }
.marca .bandera .c2 { fill: currentColor; }
.marca .texto { line-height: 1; }
.marca .nombre-marca {
  display: block; font-family: var(--fuente-titulo); font-weight: 700;
  font-style: italic; font-size: 22px; letter-spacing: -.01em; text-transform: uppercase;
}
.marca .nombre-marca b { color: var(--accent); font-weight: 700; }
.marca .texto .sub {
  display: block; margin-top: 4px;
  font-family: var(--fuente-mono); font-size: 9px; font-weight: 500; white-space: nowrap;
  letter-spacing: .06em; text-transform: uppercase; color: var(--ink-4);
}
.lateral .marca { padding: 0 8px 20px; color: var(--oscuro-texto); }
.lateral .marca .nombre-marca b { color: var(--rojo-sobre-oscuro); }
.lateral .marca .texto .sub { color: var(--oscuro-tenue); }

.lateral nav { display: flex; flex-direction: column; gap: 2px; }
.lateral nav a {
  display: flex; align-items: center; gap: 10px;
  min-height: 44px; padding: 0 12px; border-radius: var(--radio-s);
  color: var(--oscuro-tenue);
  font-family: var(--fuente-titulo); font-size: 15.5px; font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase;
  transition: background .12s, color .12s;
}
.lateral nav a:hover { background: var(--oscuro-2); color: var(--oscuro-texto); text-decoration: none; }
.lateral nav a.activo { background: var(--accent); color: var(--surface); }
.lateral nav a .etiq { flex: 1 1 auto; }

/* El atajo de teclado, escrito como se escribe una tecla. */
.atajo {
  font-family: var(--fuente-mono); font-size: 10.5px; font-weight: 500;
  color: var(--ink-4); background: var(--neutral-soft);
  border-radius: 5px; padding: 2px 5px; letter-spacing: 0;
}
.lateral nav a .atajo { background: var(--oscuro-2); color: var(--oscuro-tenue); text-transform: none; }
.lateral nav a.activo .atajo { background: var(--accent-strong); color: var(--surface); }

/* Contador al final de un enlace del menú. Solo se pinta cuando hay algo que
   contar: un "0" permanente es ruido. */
.contador {
  min-width: 20px; text-align: center; padding: 1px 6px;
  border-radius: var(--radio-chip); font-size: 11.5px; font-weight: 600;
  font-variant-numeric: tabular-nums;
  background: var(--neutral-soft); color: var(--ink-3);
}
.contador.bien { background: var(--good-soft); color: var(--good); }
.contador.ojo { background: var(--warn-soft); color: var(--warn-text); }

/* --- Tarjeta de frescura del menú --------------------------------------- */

.lateral .frescura {
  margin-top: auto;
  background: var(--oscuro-2); border: 1px solid var(--oscuro-linea);
  border-radius: var(--radio-bloque); padding: 13px 13px 12px;
  font-size: 12.5px; color: var(--oscuro-tenue);
}
.lateral .frescura .titulo {
  font-family: var(--fuente-mono); font-size: 10px; font-weight: 500; letter-spacing: .12em;
  text-transform: uppercase; color: var(--oscuro-tenue); margin-bottom: 7px;
}
.lateral .frescura .cuantos {
  font-family: var(--fuente-titulo); font-weight: 700; font-size: 18px;
  color: var(--oscuro-texto); margin-bottom: 9px;
}

/* Barra de tramos: un trozo por estado, del ancho de lo que representa. Se
   lee de un vistazo qué parte del catálogo está al día sin leer un número. */
.tramos {
  display: flex; gap: 2px; height: 6px; margin-bottom: 9px;
  border-radius: var(--radio-chip); overflow: hidden;
}
.tramos span { display: block; height: 100%; }
.tramos .aldia { background: var(--good); }
.tramos .viejo { background: var(--warn-bar); }
.tramos .fuera { background: var(--line); }
.lateral .tramos .aldia { background: var(--verde-sobre-oscuro); }
.lateral .tramos .fuera { background: var(--oscuro-linea); }

.lateral .frescura a {
  font-weight: 600; display: inline-flex; align-items: center; gap: 4px;
  color: var(--rojo-sobre-oscuro);
}

/* --- Quién está dentro --------------------------------------------------- */

.usuario {
  display: flex; align-items: center; gap: 10px;
  margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--oscuro-linea);
  min-width: 0;
}
.usuario .avatar {
  width: 32px; height: 32px; border-radius: var(--radio-s); flex: 0 0 auto;
  background: var(--accent); color: var(--surface);
  display: grid; place-items: center;
  font-family: var(--fuente-titulo); font-weight: 700; font-size: 16px; text-transform: uppercase;
}
.usuario .quien { min-width: 0; line-height: 1.3; }
.usuario .nombre {
  font-size: 13px; font-weight: 600; color: var(--oscuro-texto);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.usuario .correo {
  font-size: 11.5px; color: var(--oscuro-tenue);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* --- Contenido ----------------------------------------------------------- */

main.hoja {
  flex: 1 1 auto; min-width: 0;
  padding: 32px 48px 64px;
}
.contenedor { max-width: min(1180px, 100%); margin: 0 auto; }

/* Botón de menú para pantallas estrechas. Oculto mientras el menú lateral
   cabe: no hay nada que desplegar. */
.abrir-menu { display: none; }

/* --- Tipografía ---------------------------------------------------------- */

/* Como los titulares de pcracing.pro: Rajdhani, mayúsculas, cursiva. */
h1 {
  font-family: var(--fuente-titulo); font-size: 40px; font-weight: 700;
  font-style: italic; text-transform: uppercase;
  letter-spacing: -.01em; line-height: 1.02; margin: 0 0 10px;
}
/* La raya roja corta que la web pone encima de cada titular. Solo en el
   título suelto de la página: dentro de una fila (con icono al lado) sobra. */
.contenedor > h1::before {
  content: ""; display: block; width: 46px; height: 3px;
  background: var(--accent); margin-bottom: 14px;
}
h2 {
  font-family: var(--fuente-titulo); font-size: 19px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .03em; line-height: 1.2;
  margin: 34px 0 14px; display: flex; align-items: center; gap: 9px;
}
h3 { font-size: 15px; font-weight: 600; margin: 0; }

.subtitulo { color: var(--ink-3); font-size: 14.5px; margin: 0 0 26px; max-width: 74ch; }
.titulo-busqueda { margin-bottom: 12px; }

/* Pastilla de recuento. Vale en cualquier sitio, no solo pegada a un título:
   sobre los resultados dice de dónde sale lo que se está viendo. */
.cuenta {
  font-size: 12px; font-weight: 500; color: var(--ink-3);
  background: var(--neutral-soft); border: 1px solid transparent;
  padding: 3px 9px; border-radius: var(--radio-chip); white-space: nowrap;
}
/* Ámbar cuando hay algo que mirar, verde cuando el dato se acaba de traer. Un
   solo gris para las tres cosas dejaba el aviso al mismo nivel que la etiqueta
   de siempre. */
.cuenta.atencion { background: var(--warn-soft); color: var(--warn-text); }
.cuenta.viva { background: var(--good-soft); color: var(--good); }
.cuenta[title] { cursor: help; }

.pastillas {
  display: flex; gap: 8px; flex-wrap: wrap; align-items: center;
  margin: 0 0 20px;
}

/* --- Formularios --------------------------------------------------------- */

.buscador, .panel {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radio); box-shadow: var(--sombra);
}
.buscador { padding: 18px; }
.panel { padding: 20px; margin-bottom: 18px; }
/* `overflow: hidden` para que la tabla no se salga de las esquinas
   redondeadas, y `auto` en horizontal porque una tabla de siete columnas no
   cabe en un móvil: antes empujaba la página entera. Ahora se desplaza solo
   la tabla, dentro de su tarjeta. */
.panel.sin-relleno { padding: 0; overflow-x: auto; overflow-y: hidden; }

.fila { display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-end; }
.crece { flex: 1 1 260px; min-width: 210px; }

input[type=text], input[type=number], input[type=email], input[type=password],
input[type=time], input[type=search], select {
  width: 100%; padding: 11px 13px;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--radio-s);
  font: inherit; font-size: 14px; transition: border-color .12s, box-shadow .12s;
}
input::placeholder { color: var(--ink-4); }
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--accent); box-shadow: var(--foco);
}
/* Foco visible en todo lo que se puede recorrer con el tabulador, no solo en
   los campos: sin esto, moverse con el teclado es moverse a ciegas. */
a:focus-visible, button:focus-visible, summary:focus-visible,
input[type=checkbox]:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px;
}
/* El desplegable nativo traía su propia flecha, su propio alto y su propio
   fondo gris del sistema: al lado de la caja de texto se veía que eran de dos
   sitios distintos. Se apaga y se dibuja la flecha aquí, con lo que ya hereda
   el borde, el alto y el foco de los campos. */
select {
  appearance: none; -webkit-appearance: none;
  padding-right: 34px;
  background-image: var(--flecha);
  background-repeat: no-repeat;
  background-position: right 12px center;
  cursor: pointer;
}
label.campo { display: block; }
label.campo > span {
  display: block; font-size: 12px; font-weight: 600; letter-spacing: .01em;
  color: var(--ink-3); margin-bottom: 6px;
}
label.campo .pista { font-weight: 400; color: var(--ink-4); }
/* El mismo rótulo, pero suelto. Hace falta cuando el campo no se puede envolver
   en un <label>: un <label> se asocia al primer control que lleve dentro, y en
   el contador de unidades el primero es el botón de «menos». */
.rotulo {
  display: block; font-size: 12px; font-weight: 600; letter-spacing: .01em;
  color: var(--ink-3); margin-bottom: 6px;
}

button, .boton {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  min-height: 40px; padding: 10px 18px; border: 1px solid transparent;
  border-radius: var(--radio-s);
  background: var(--accent); color: var(--surface);
  font: inherit; font-family: var(--fuente-titulo); font-weight: 700; font-size: 15px;
  letter-spacing: .06em; text-transform: uppercase;
  cursor: pointer; white-space: nowrap; transition: background .12s, transform .06s;
}
button:hover, .boton:hover { background: var(--accent-strong); text-decoration: none; }
button:active { transform: translateY(1px); }
button.secundario, .boton.secundario {
  background: var(--surface); color: var(--ink); border-color: var(--line);
}
button.secundario:hover, .boton.secundario:hover { background: var(--surface-2); }
button.peligro {
  background: transparent; color: var(--danger); padding: 8px 12px; border-color: var(--line);
  min-height: 36px;
}
button.peligro:hover { background: var(--danger-soft); }
button.pequeno, .boton.pequeno { padding: 7px 12px; min-height: 34px; font-size: 14px; }
/* Un botón apagado tiene que PARECER apagado: si no, se pulsa, no pasa nada y
   se interpreta como que el programa está roto. El cursor lo remata. */
button:disabled,
button:disabled:hover {
  opacity: .45; cursor: not-allowed; transform: none;
  background: transparent; color: var(--ink-3);
}

.opciones {
  display: flex; gap: 18px; flex-wrap: wrap; align-items: center;
  margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line-soft);
  font-size: 13.5px; color: var(--ink-3);
}
.opciones label { display: flex; align-items: center; gap: 7px; cursor: pointer; }
.opciones input[type=checkbox] { accent-color: var(--accent); width: 16px; height: 16px; }
.opciones input[type=number] { width: 76px; padding: 7px 9px; }

/* Casilla con forma de pastilla. La casilla es una casilla de verdad, no un
   dibujo: se marca con el teclado y la lee un lector de pantalla. */
.chip-casilla {
  display: inline-flex; align-items: center; gap: 8px;
  min-height: 36px; padding: 0 13px; border-radius: var(--radio-chip);
  background: var(--surface); border: 1px solid var(--line);
  font-size: 13px; color: var(--ink-2); cursor: pointer;
  transition: background .12s, border-color .12s, color .12s;
}
.chip-casilla:hover { background: var(--surface-2); }
.chip-casilla input { accent-color: var(--accent); width: 15px; height: 15px; margin: 0; }
.chip-casilla:has(input:checked) {
  background: var(--accent-soft); border-color: transparent;
  color: var(--accent); font-weight: 600;
}

/* El campo principal de la búsqueda: 56 px de alto y la lupa dentro. Es lo
   primero que se hace al abrir el programa, así que tiene que ganar a todo lo
   demás de la tarjeta sin que haya que buscarlo.

   El borde va a 2 px SIEMPRE, gris de serie y azul al enfocar. Engordándolo
   solo en el foco, el campo crecía 2 px al pinchar y empujaba la fila entera. */
.busca-caja { position: relative; }
.busca-caja .ico {
  position: absolute; left: 17px; top: 50%; transform: translateY(-50%);
  color: var(--ink-4); pointer-events: none;
}
.busca-caja input[type=text] {
  min-height: 56px; padding-left: 47px; font-size: 15.5px;
  border-width: 2px;
}
.busca-caja input[type=text]:focus { border-color: var(--accent); }
/* El resto de la primera fila se pone a la misma altura: con el campo a 56 y
   el desplegable a 42 la fila parecía dos filas mal alineadas. */
.buscador .fila.principal { align-items: flex-end; gap: 10px; }
.buscador .fila.principal select,
.buscador .fila.principal .contar button,
.buscador .fila.principal .contar input { min-height: 56px; }
.buscador .fila.principal button[type=submit] {
  min-height: 56px; padding: 0 28px; font-size: 15px;
}

/* Segunda fila: a la izquierda lo que se enciende y se apaga, a la derecha lo
   que solo se ajusta o se informa. */
.ajustes {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line-soft);
}
.ajustes .derecha {
  margin-left: auto; display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
}
.ajustes .junto { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--ink-3); }
.ajustes .junto input[type=number] { width: 72px; padding: 8px 10px; min-height: 36px; }
/* Rótulo, no selector: la comparativa se ordena siempre por coste real y no
   hay otra forma de ordenarla. Con pinta de desplegable sería un mando que no
   manda nada. */
.ajustes .fijo {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 13px; color: var(--ink-4); cursor: help;
}

/* Contador de unidades: dos botones de 44 px y el número en medio. */
.contar { display: flex; align-items: stretch; }
.contar button {
  width: 44px; min-height: 44px; padding: 0;
  background: var(--surface); color: var(--ink); border: 1px solid var(--line);
  font-family: var(--fuente); font-size: 18px; letter-spacing: 0;
}
.contar button:first-child { border-radius: var(--radio-s) 0 0 var(--radio-s); }
.contar button:last-child { border-radius: 0 var(--radio-s) var(--radio-s) 0; }
.contar button:hover { background: var(--surface-2); }
.contar input {
  width: 62px; text-align: center; border-radius: 0;
  border-left: 0; border-right: 0; min-height: 44px;
}
/* Las flechitas del navegador sobran: ya hay dos botones de 44 px. */
.contar input::-webkit-outer-spin-button,
.contar input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.contar input { -moz-appearance: textfield; }

/* --- Plegables ----------------------------------------------------------- */

/* Un <summary> con pinta de botón. Permite desplegar un formulario ahí mismo
   sin JavaScript y sin mandar a otra página, que para editar cuatro campos
   sería dar un rodeo. */
details.editar > summary {
  display: inline-flex; align-items: center; gap: 6px;
  cursor: pointer; list-style: none; width: fit-content;
  min-height: 34px; padding: 6px 12px; border-radius: var(--radio-s);
  font-size: 13px; font-weight: 600;
  background: var(--surface); color: var(--ink);
  border: 1px solid var(--line);
}
details.editar > summary::-webkit-details-marker { display: none; }
details.editar > summary:hover { background: var(--surface-2); }
details.editar[open] > summary { border-color: var(--accent); color: var(--accent); }
details.editar .cuerpo {
  margin-top: 14px; padding: 16px; border-radius: var(--radio-bloque);
  background: var(--surface-2); border: 1px solid var(--line-soft);
}

/* El análisis del componente, plegado para no repetirlo en cada producto. */
details.analisis-plegado > summary,
details.mas-ofertas > summary {
  display: flex; align-items: center; gap: 7px;
  cursor: pointer; list-style: none; min-height: 44px; padding: 11px 20px;
  font-size: 13px; font-weight: 600;
  border-top: 1px solid var(--line-soft);
}
details.analisis-plegado > summary::-webkit-details-marker,
details.mas-ofertas > summary::-webkit-details-marker { display: none; }
details.analisis-plegado > summary { color: var(--ink-3); }
details.mas-ofertas > summary { color: var(--accent); }
details.analisis-plegado > summary:hover,
details.mas-ofertas > summary:hover { background: var(--surface-2); }
details.analisis-plegado > summary .ico,
details.mas-ofertas > summary .ico { transition: transform .15s; }
details[open] > summary .ico.giro { transform: rotate(90deg); }
details.analisis-plegado .analisis { border-top: 0; }

details.avanzado { margin-top: 16px; border-top: 1px solid var(--line-soft); padding-top: 14px; }
details.avanzado summary {
  cursor: pointer; font-size: 13.5px; font-weight: 600; color: var(--ink-3);
  list-style: none; display: flex; align-items: center; gap: 7px;
}
details.avanzado summary::-webkit-details-marker { display: none; }
details.avanzado summary .ico { transition: transform .15s; }
details.avanzado[open] summary .ico.giro { transform: rotate(90deg); }
details.avanzado summary:hover { color: var(--ink); }
details.avanzado .cuerpo { padding-top: 16px; }

/* --- Pantalla de espera -------------------------------------------------- */

.cargando {
  position: fixed; inset: 0; z-index: 100;
  display: grid; place-items: center;
  background: var(--bg); /* opaco: tapar del todo evita pulsar otra vez */
}
/* Imprescindible y fácil de olvidar: el `display:grid` de arriba le gana al
   `display:none` que el navegador aplica a [hidden], así que sin esta línea la
   pantalla de espera sale en TODAS las páginas y tapa la app entera. */
.cargando[hidden] { display: none; }
.cargando .caja { text-align: center; max-width: 460px; padding: 0 24px; }
.cargando h2 {
  margin: 22px 0 8px; border: 0; padding: 0; display: block;
  font-family: var(--fuente-titulo); font-size: 21px; font-weight: 700;
}
.cargando p { color: var(--ink-3); margin: 0; font-size: 14px; }
.cargando .reloj {
  margin-top: 20px; font-family: var(--fuente-titulo);
  font-size: 32px; font-weight: 700; color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.cargando .paciencia { margin-top: 14px; color: var(--ink-4); font-size: 13px; min-height: 20px; }
/* :not([hidden]) porque un display propio anularia el hidden y el boton
   saldria tambien al enviar un correo, donde cancelar no para nada. */
.cargando .cancelar:not([hidden]) {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  margin-top: 22px; font-size: 12.5px; color: var(--ink-4);
}
.cargando .rueda {
  width: 46px; height: 46px; margin: 0 auto; border-radius: 50%;
  border: 4px solid var(--line); border-top-color: var(--accent);
  animation: girar .8s linear infinite;
}
@keyframes girar { to { transform: rotate(360deg); } }
/* Quien tenga desactivadas las animaciones ve un punto que late, no un giro. */
@media (prefers-reduced-motion: reduce) {
  .cargando .rueda { animation: latir 1.4s ease-in-out infinite; }
  @keyframes latir { 50% { opacity: .35; } }
}

/* --- Tarjeta de producto ------------------------------------------------- */

.producto {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radio); margin-bottom: 16px; overflow: hidden;
  box-shadow: var(--sombra); transition: box-shadow .15s;
}
.producto:hover { box-shadow: var(--sombra-alta); }
.producto .cabeza {
  padding: 18px 20px 15px; border-bottom: 1px solid var(--line-soft);
  display: flex; gap: 18px; align-items: flex-start;
}
/* `min-width: 0` no es decorativo: sin él, un título largo sin espacios no
   deja encogerse a la columna y empuja la gráfica fuera de la tarjeta. */
.producto .titular { flex: 1 1 auto; min-width: 0; }
.producto h3 { margin: 8px 0 9px; font-size: 19px; font-weight: 600; line-height: 1.35; }
.producto .acciones-producto { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 12px; }
/* Cerrados son dos botones uno al lado del otro; el que se abre se lleva la
   fila entera. Sin esto el formulario nacía dentro de media columna y los
   campos salían apilados de uno en uno. */
.producto .acciones-producto > details[open] { flex: 1 1 100%; }

/* --- Tendencia de precio (mini-gráfica) ---------------------------------- */

/* La base guarda miles de cambios de precio que no se veían en ninguna
   pantalla. Aquí van como una línea diminuta al lado del título: acompaña, no
   compite con la tabla de precios, que es lo que se viene a mirar. */
.tendencia {
  flex: 0 0 auto; text-align: right; cursor: help;
  display: flex; flex-direction: column; align-items: flex-end; gap: 4px;
}
.chispa {
  display: block; overflow: visible;
  background: var(--surface-2); border: 1px solid var(--line-soft);
  border-radius: var(--radio-s); padding: 4px 6px; box-sizing: content-box;
}
.chispa polyline {
  fill: none; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
  stroke: var(--ink-4);
}
/* El color dice el sentido antes de leer el número. Subir es malo: esto es
   precio de compra, no cotización. */
.tendencia.sube .chispa polyline { stroke: var(--danger); }
.tendencia.baja .chispa polyline { stroke: var(--good); }
.tendencia .dato {
  font-size: 11.5px; font-weight: 600; color: var(--ink-4);
  font-variant-numeric: tabular-nums;
}
.tendencia.sube .dato { color: var(--danger); }
.tendencia.baja .dato { color: var(--good); }
.tendencia .minimo {
  font-size: 10px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase;
  color: var(--good); background: var(--good-soft);
  border-radius: var(--radio-chip); padding: 2px 8px;
}

/* --- Etiquetas ----------------------------------------------------------- */

.etiquetas { display: flex; gap: 7px; flex-wrap: wrap; align-items: center; }
.etiqueta {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11.5px; font-weight: 500;
  padding: 3px 9px; border-radius: var(--radio-chip);
  background: var(--neutral-soft); color: var(--ink-3);
  border: 1px solid transparent;
}
/* El EAN es un número que se copia y se pega en la web del mayorista: va en
   monoespaciada para poder leerlo cifra a cifra. */
.etiqueta.ean { font-family: var(--fuente-mono); font-size: 11px; letter-spacing: -.01em; }
.etiqueta.ok { background: var(--good-soft); color: var(--good); font-weight: 600; }
.etiqueta.duda { background: var(--warn-soft); color: var(--warn-text); }
.etiqueta.usado { background: var(--danger-soft); color: var(--danger); }
/* Nota del análisis («A tener en cuenta»). Iba en el color de marca, que en
   este tema es rojo: «viene con frecuencias de fábrica algo más altas» se leía
   como una avería. Es información, así que va en neutro. */
.etiqueta.nota { background: var(--neutral-soft); color: var(--ink-3); }
/* Etiqueta que además es un enlace: se distingue de las informativas porque se
   puede pulsar, y si no se nota nadie la pulsa. */
.etiqueta.enlace { text-decoration: none; cursor: pointer; }
.etiqueta.enlace:hover { background: var(--accent-soft); color: var(--accent); }

/* --- Tablas -------------------------------------------------------------- */

table { width: 100%; border-collapse: collapse; }

/* Cada producto lleva su tabla, y el navegador le daba a cada una el ancho que
   le pedía su contenido: en una lista de doce tarjetas, las columnas bailaban
   de una a otra y "coste real" nunca caía en el mismo sitio. Con el ancho
   fijado se leen como una sola tabla.

   Los anchos van por `.comparativa` y no por `.producto table`: Informes y
   Avisos también pintan una tabla dentro de una tarjeta `.producto`, y con
   estos anchos les aplastaba la primera columna a 44 px dejando el nombre del
   componente invisible. */
.comparativa { table-layout: fixed; min-width: 760px; }
.comparativa th:nth-child(1), .comparativa td:nth-child(1) { width: 40px; }
.comparativa th:nth-child(3), .comparativa td:nth-child(3) { width: 104px; }
.comparativa th:nth-child(4), .comparativa td:nth-child(4) { width: 84px; }
.comparativa th:nth-child(5), .comparativa td:nth-child(5) { width: 108px; }
.comparativa th:nth-child(6), .comparativa td:nth-child(6) { width: 90px; }
.comparativa th:nth-child(7), .comparativa td:nth-child(7) { width: 76px; }
.comparativa th:nth-child(8), .comparativa td:nth-child(8) { width: 80px; }
.comparativa th:nth-child(9), .comparativa td:nth-child(9) { width: 112px; }
/* Nueve columnas no caben en una pantalla estrecha. Se desplaza la tabla
   dentro de su tarjeta, no la página entera: si se va la página, el precio se
   sale por un lado y el nombre del proveedor por el otro. */
.tabla-scroll { overflow-x: auto; }
/* El nombre del proveedor es lo único que puede quedarse sin sitio, así que es
   lo único que se parte en dos líneas en vez de desbordar. */
.comparativa td:nth-child(2) { overflow-wrap: anywhere; }
/* La cabecera se repite en cada tarjeta de producto, y buscando "rtx 5060 ti"
   salen doce. Con fondo propio eran doce bandas grises que pesaban más que los
   precios; sin él, siguen leyéndose y dejan de llamar la atención. */
thead th {
  text-align: left; font-size: 10.5px; font-weight: 600; letter-spacing: .06em;
  text-transform: uppercase; color: var(--ink-4);
  padding: 10px 20px; border-bottom: 1px solid var(--line-soft);
}
thead th[title] { cursor: help; }
tbody td { padding: 13px 20px; border-bottom: 1px solid var(--line-soft); font-size: 14px; }
tbody tr:last-child td { border-bottom: 0; }
tbody tr.mejor { background: var(--good-soft); }
tbody tr.mejor td:first-child { box-shadow: inset 3px 0 0 var(--good); }
/* Oferta descartada: se sigue viendo, apagada y con el motivo al lado. No se
   esconde, porque entonces no se sabe por qué no sale ese proveedor. */
tbody tr.apagada { color: var(--ink-4); background: var(--surface-2); }
tbody tr.apagada .precio, tbody tr.apagada .proveedor { font-weight: 500; color: var(--ink-4); }
td.num, th.num { text-align: right; white-space: nowrap; }
td.orden { color: var(--ink-4); width: 38px; font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums; }
.precio { font-weight: 600; font-size: 14.5px; }
.proveedor { font-weight: 600; }
.agotado { color: var(--danger); font-size: 11.5px; font-weight: 600; }
.motivo { display: block; margin-top: 2px; font-size: 11.5px; color: var(--ink-4); }
/* NOX: su precio de tarifa no es el pactado. Ambar como los demas avisos, y
   pegado al nombre del proveedor para que no se lea el precio sin verlo. */
.nota-precio { display: block; margin-top: 3px; font-size: 11.5px; line-height: 1.35;
               color: var(--warn-text); font-weight: 600; }

/* Distribuidor real detrás de un agregador (ITscope). Va en su propia línea y
   más tenue: es quien pone el precio, pero el proveedor sigue siendo la vía. */
.vendedor {
  display: block; margin-top: 2px;
  font-size: 11.5px; font-weight: 400; color: var(--ink-4);
}
/* Precio de un proveedor que no entró en la última sincronización. En ámbar y
   con la fecha dentro: al lado de un precio de hoy y con la misma pinta, uno de
   hace tres semanas es lo que hace elegir mal. */
.caducado {
  display: inline-flex; align-items: center; gap: 4px; margin-top: 3px; cursor: help;
  font-size: 10.5px; font-weight: 600;
  color: var(--warn-text); background: var(--warn-soft);
  border-radius: var(--radio-chip); padding: 2px 8px;
}
/* Lo contrario: dato traído hoy. El punto verde se ve antes que la hora. */
.fresco {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12px; color: var(--ink-3); font-variant-numeric: tabular-nums;
}
/* Dato que el proveedor no da. Se marca con "?" o con "sin datos" en vez de
   con un guion para que no se lea como un cero: portes desconocidos no son
   portes gratis. El subrayado de puntos avisa de que hay explicación encima. */
.sin-dato {
  color: var(--ink-4); cursor: help; border-bottom: 1px dotted var(--ink-4);
  font-size: 12px; font-weight: 500;
}
/* Lo contrario: portes que sí se conocen y salen a cero porque el pedido llega
   al mínimo de envío gratuito. Antes los dos casos eran el mismo guion. */
.gratis { color: var(--good); font-size: 12px; font-weight: 600; cursor: help; }
/* Distinto de .sin-dato: aquí el dato existe y se puede rellenar, solo que
   nadie lo ha metido. Por eso va en ámbar y no en gris. */
.pendiente { color: var(--warn-text); cursor: help; font-size: 12px; font-weight: 500; }
/* Fechas en columna: con cifras de ancho fijo se comparan de un vistazo, que
   es justo para lo que está esa columna. */
td.fecha, td.atrasado { font-variant-numeric: tabular-nums; }
td.fecha { color: var(--ink-3); }
td.atrasado { color: var(--warn-text); }

/* La línea editable de un informe: el nombre del componente necesita sitio
   para verse entero, y los dos botones tienen que ir juntos en una línea. Las
   dos cosas sumaban un ancho mínimo de 620 px que desbordaba la pantalla en
   móvil; el mínimo se suelta en la media query de abajo. */
td.linea-nombre { min-width: 190px; }
td.acciones { white-space: nowrap; }

/* Fila que separa un grupo dentro de una tabla ("Necesitan atención · 3"). */
tbody tr.grupo td {
  background: var(--surface-2); padding: 9px 20px;
  font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-4); border-bottom: 1px solid var(--line-soft);
}
tbody tr.grupo.ojo td { color: var(--warn-text); background: var(--warn-soft); }

/* --- Pie de tarjeta ------------------------------------------------------ */

.veredicto {
  padding: 16px 20px; background: var(--good-soft);
  border-top: 1px solid var(--line-soft);
}
.veredicto .titulo {
  font-size: 10.5px; font-weight: 600; letter-spacing: .07em;
  text-transform: uppercase; color: var(--good); display: block; margin-bottom: 6px;
}
.veredicto .coste {
  font-family: var(--fuente-titulo); font-size: 32px; font-weight: 700;
  color: var(--good-strong); letter-spacing: -.02em; line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
/* El veredicto subió al principio de la tarjeta, justo debajo de la cabecera,
   que ya trae su propia línea: con las dos salía una raya de 2px. */
.producto .cabeza + .veredicto { border-top: 0; }
.veredicto .coste + b { margin-left: 8px; }
.veredicto b { color: var(--good-strong); font-size: 15px; }
.veredicto .pero { display: block; color: var(--ink-3); font-size: 13px; margin-top: 6px; }
/* Dentro del recuadro verde de "mejor compra", una salvedad que puede cambiar
   la decisión no puede ir del mismo gris que las demás: se pierde. */
.veredicto .pero.ojo { color: var(--warn-text); font-weight: 600; }
.veredicto .ir {
  display: inline-flex; align-items: center; gap: 6px; margin-top: 10px;
  min-height: 40px; padding: 9px 16px; border-radius: var(--radio-s);
  background: var(--good); color: var(--surface); font-weight: 600; font-size: 14px;
}
.veredicto .ir:hover { background: var(--good-strong); text-decoration: none; }

.analisis {
  padding: 14px 20px; background: var(--surface-2);
  border-top: 1px solid var(--line-soft); font-size: 13.5px; color: var(--ink-3);
}
.analisis .que { color: var(--ink); font-weight: 600; }
.analisis ul { margin: 8px 0 0; padding-left: 19px; }
.analisis li { margin: 4px 0; }
.mas { padding: 11px 20px; font-size: 12.5px; color: var(--ink-4); border-top: 1px solid var(--line-soft); }

/* Rótulo de la tabla de ofertas, dentro de la tarjeta del producto. */
.rotulo-tabla {
  display: flex; align-items: baseline; gap: 8px;
  margin: 0; padding: 14px 20px 0;
  font-size: 12px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; color: var(--ink-4);
}
/* Diferencia contra la oferta más barata. En rojo no: no es un error, es
   cuánto más cuesta. Y la más barata lleva un guion, no un "+0,00 €", que
   invita a compararlo consigo mismo. */
td.diferencia { color: var(--ink-3); font-variant-numeric: tabular-nums; }
/* La fila descartada pierde el número de posición: si sigue teniendo el 3, se
   lee como la tercera mejor opción cuando en realidad no es ninguna. */
td.orden.fuera { color: transparent; }

/* --- Pantalla de la contraseña ------------------------------------------- */
/* Solo se ve al entrar desde otro equipo de la red. Centrada y estrecha: no hay
   nada más que hacer en esta página que escribir una línea. */

.acceso {
  min-height: 100vh; display: flex; align-items: center; justify-content: center;
  padding: 24px; background: var(--bg);
}
.acceso .panel { width: 100%; max-width: 390px; padding: 28px; margin: 0; }
.acceso .marca { margin-bottom: 18px; }
.acceso .subtitulo { margin-bottom: 20px; font-size: 14px; }
.acceso form { display: flex; flex-direction: column; gap: 14px; }
.acceso button { width: 100%; }

/* --- Bloques informativos ------------------------------------------------ */

.aviso {
  display: flex; align-items: flex-start; gap: 9px;
  padding: 12px 15px; border-radius: var(--radio-bloque); font-size: 13.5px;
  margin-bottom: 16px; background: var(--warn-soft); color: var(--warn-text);
  line-height: 1.5;
}
.aviso .ico { margin-top: 2px; }
.aviso.ok { background: var(--good-soft); color: var(--good); }
.aviso.malo { background: var(--danger-soft); color: var(--danger); }
.aviso.info { background: var(--accent-soft); color: var(--accent); }
.aviso.neutro { background: var(--neutral-soft); color: var(--ink-3); }
/* Un enlace azul dentro de una caja ámbar parecía pegado de otra página. Toma
   el color del aviso y se distingue por el subrayado, que además es lo que
   hace evidente que el aviso se puede resolver desde ahí mismo. */
.aviso a { color: inherit; font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
.aviso a:hover { opacity: .75; }
/* Subida del CSV de NOX en la portada: el formulario va debajo del texto. */
.carga-nox form { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 8px; }
.carga-nox input[type=file] { font: inherit; font-size: 13px; color: var(--ink-2); max-width: 100%; }
details.aviso { display: block; }
details.aviso summary { cursor: pointer; }
/* Dos avisos finos, uno al lado del otro, en vez de dos bandas apiladas. */
.avisos-par { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 16px; }
.avisos-par .aviso { flex: 1 1 300px; margin-bottom: 0; }

.vacio {
  padding: 56px 24px; text-align: center; color: var(--ink-4);
  background: var(--surface); border: 1px dashed var(--line);
  border-radius: var(--radio);
}
.vacio strong { color: var(--ink); display: block; margin-bottom: 6px; font-size: 15px; }

.rejilla { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 14px; }
.ficha {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radio); padding: 16px; box-shadow: var(--sombra);
}
.ficha .nombre { font-weight: 600; margin-bottom: 4px; }
.ficha .detalle { font-size: 13.5px; color: var(--ink-3); line-height: 1.5; }
.ficha.mal { border-left: 3px solid var(--danger); }
.ficha.bien { border-left: 3px solid var(--good); }

/* Cifra grande con su rótulo debajo. Los dos hijos van en `display:block`
   porque casi siempre son `<span>`: en línea, el rótulo se pegaba al lado del
   número en la misma fila y el `margin-top` no hacía nada. */
.metrica { text-align: left; }
.metrica .cifra {
  display: block;
  font-family: var(--fuente-titulo); font-size: 32px; font-weight: 700;
  letter-spacing: -.02em; line-height: 1.1; font-variant-numeric: tabular-nums;
}
.metrica .etiq { display: block; font-size: 12.5px; color: var(--ink-3); margin-top: 3px; }

.punto { display: inline-block; width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto; }
.punto.verde { background: var(--good); }
.punto.rojo { background: var(--danger); }
.punto.ambar { background: var(--warn-bar); }
.punto.gris { background: var(--line); }
.detalle { font-size: 13.5px; color: var(--ink-3); }
/* Punto de color + texto (la leyenda de la barra de frescura). En línea normal
   el punto se apoya en la base de la letra y queda colgando; centrado a mano
   con flex se lee como una sola cosa. */
.leyenda {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 13.5px; color: var(--ink-3);
}

/* --- Tarjetas de cifras -------------------------------------------------- */

/* Se ve de un golpe que hay datos dentro y de cuándo son. Cada una lleva al
   sitio donde se puede comprobar, porque una cifra que no se puede verificar
   no vale nada. */
.cifras {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 12px; margin: 22px 0 6px;
}
.cifra-tarjeta {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radio); padding: 16px 18px; box-shadow: var(--sombra);
  display: flex; flex-direction: column; gap: 3px;
  color: var(--ink); transition: border-color .12s, box-shadow .12s;
}
a.cifra-tarjeta:hover {
  text-decoration: none; border-color: var(--ink-4); box-shadow: var(--sombra-alta);
}
.cifra-tarjeta .valor {
  font-family: var(--fuente-titulo); font-size: 28px; font-weight: 700;
  letter-spacing: -.02em; line-height: 1.15; font-variant-numeric: tabular-nums;
}
.cifra-tarjeta .etiq { font-size: 12.5px; color: var(--ink-3); line-height: 1.35; }
.cifra-tarjeta.atencion { border-color: var(--warn-bar); }
.cifra-tarjeta.atencion .valor { color: var(--warn-text); }
.cifras-nota {
  margin: 10px 0 0; font-size: 12.5px; color: var(--ink-3); line-height: 1.5;
  max-width: 82ch;
}
.cifras-nota a { color: var(--warn-text); font-weight: 600; white-space: nowrap; }

/* --- Dos columnas (lista + panel lateral de la pantalla) ----------------- */

.dos-columnas { display: grid; grid-template-columns: 1fr 360px; gap: 20px; align-items: start; }
.dos-columnas.estrecha { grid-template-columns: 1fr 340px; }

/* --- Destinatarios ------------------------------------------------------- */

/* Un correo es una sola palabra y el navegador no la parte: con los dos botones
   al lado, la fila medía 43 px más que la pantalla en un móvil estrecho y
   arrastraba la página entera. Plegando la fila y dejando que el correo se
   parta solo cuando no queda sitio, cabe. */
.destinatario {
  display: flex; align-items: center; gap: 11px; flex-wrap: wrap;
  padding: 9px 0; border-bottom: 1px solid var(--line-soft);
}
.destinatario .quien { flex: 1; min-width: 12ch; overflow-wrap: anywhere; }

/* --- Barra de progreso hacia un objetivo --------------------------------- */

.progreso {
  height: 6px; border-radius: var(--radio-chip); background: var(--neutral-soft);
  overflow: hidden; margin: 8px 0 0;
}
.progreso span { display: block; height: 100%; background: var(--accent); }
.progreso.cerca span { background: var(--good); }

/* --- Bloque de comando copiable ------------------------------------------ */

.comando {
  display: flex; align-items: center; gap: 10px;
  background: var(--warn-soft); border-radius: var(--radio-bloque);
  padding: 12px 14px; margin-top: 12px;
}
.comando code {
  flex: 1 1 auto; background: transparent; padding: 0;
  color: var(--warn-text); font-size: 12.5px;
}
/* El mismo bloque cuando no hay nada que arreglar: el comando sigue a mano,
   pero en gris. En ámbar permanente se acaba mirando como parte del decorado y
   el día que de verdad hay una sesión caducada ya no avisa de nada. */
.comando.neutro { background: var(--neutral-soft); }
.comando.neutro code { color: var(--ink-2); }

/* --- Sincronizar ahora (Proveedores) --------------------------------------- */

.sinc { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line-soft); }
.sinc[hidden] { display: none; }
.sinc .detalle { margin: 6px 0 0; }
.sinc-cabecera { display: flex; align-items: center; gap: 10px; }
.rueda-mini {
  width: 16px; height: 16px; border-radius: 50%; flex: 0 0 auto;
  border: 2px solid var(--line); border-top-color: var(--accent);
  animation: girar .8s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
  .rueda-mini { animation: latir 1.4s ease-in-out infinite; }
}
.sinc-lista {
  list-style: none; margin: 12px 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 8px 18px;
}
.sinc-lista li { display: flex; align-items: baseline; flex-wrap: wrap; gap: 2px 8px; min-width: 0; }
.sinc-lista .etiqueta { flex: 0 0 auto; min-width: 84px; justify-content: center; }
.sinc-lista .quien { font-weight: 600; white-space: nowrap; }
.sinc-lista .detalle { margin: 0; min-width: 0; overflow-wrap: anywhere; }
.sinc-mas { margin-top: 10px; font-size: 13px; }
.sinc-mas summary { cursor: pointer; color: var(--ink-3); }
.sinc-mas ul { margin: 6px 0 0; padding-left: 18px; color: var(--ink-3); }
.sinc-mas li { margin-top: 3px; overflow-wrap: anywhere; }

/* La columna «Acción» de Proveedores: el estado y el botón de sincronizar
   en la misma línea, y uno debajo del otro si no caben. */
.accion-fila { display: flex; align-items: center; gap: 8px 12px; flex-wrap: wrap; }
.accion-fila form { margin-left: auto; }

/* --- Menos de 1024: el lateral pasa a ser una cabecera ------------------- */

@media (max-width: 1023px) {
  .armazon { display: block; }
  .hueco-lateral { display: none; }

  .lateral {
    position: sticky; top: 0; left: auto; bottom: auto; width: auto;
    border-right: 0; border-bottom: 3px solid var(--accent);
    padding: 10px 16px;
    /* Cerrado de serie: en una pantalla estrecha, el menú entero por delante
       del contenido obliga a hacer scroll para llegar a lo que se venía a
       hacer. */
    display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 0;
  }
  .lateral .marca { padding: 0; }
  .abrir-menu {
    display: inline-flex; width: 44px; height: 44px; padding: 0;
    background: var(--oscuro-2); color: var(--oscuro-texto); border: 1px solid var(--oscuro-linea);
  }
  .abrir-menu:hover { background: var(--oscuro-linea); }
  /* Todo lo que no es la marca ni el botón se apila debajo, a lo ancho, y solo
     cuando se ha pulsado el botón. */
  .lateral nav, .lateral .frescura, .lateral .usuario { display: none; }
  .lateral.abierto nav,
  .lateral.abierto .frescura,
  .lateral.abierto .usuario { display: flex; grid-column: 1 / -1; margin-top: 10px; }
  .lateral.abierto nav { flex-direction: column; }
  .lateral.abierto .frescura { display: block; margin-top: 12px; }

  main.hoja { padding: 24px 20px 48px; }
  /* Dos columnas no caben: se apilan, y el panel lateral queda debajo. */
  .dos-columnas, .dos-columnas.estrecha { grid-template-columns: 1fr; }
}

@media (max-width: 760px) {
  h1 { font-size: 26px; }
  main.hoja { padding: 20px 14px 40px; }
  /* Las tablas de Proveedores, Avisos e Informes se aprietan y pierden la
     cabecera: sus columnas son texto y se entienden solas. La comparativa no:
     tiene ancho mínimo y se desplaza dentro de su tarjeta, así que conserva
     cabecera y número de orden. Sin la cabecera quedaban cinco columnas de
     números seguidos sin saber cuál era el precio y cuál el coste real. */
  table:not(.comparativa) thead { display: none; }
  tbody td { padding: 11px 15px; }
  /* En móvil cada oferta es una ficha y no una fila de nueve columnas: con la
     tabla desplazable solo se veían proveedor y precio, y el coste real, el
     stock y la entrega quedaban fuera de la pantalla. Arriba va lo que decide
     (proveedor y coste real) y debajo el resto, cada dato con su nombre
     (data-etiq en resultados.html), porque aquí no hay cabecera.
       fila 1: nº · proveedor ·········· coste real
       fila 2:      precio s/IVA · portes · diferencia
       fila 3:      stock · entrega · datos                                   */
  .comparativa { min-width: 0; }
  .comparativa, .comparativa tbody { display: block; }
  .comparativa thead { display: none; }
  .comparativa tbody tr {
    display: grid; grid-template-columns: 26px repeat(3, minmax(0, 1fr));
    column-gap: 10px; row-gap: 8px; padding: 12px 14px;
    border-bottom: 1px solid var(--line-soft);
  }
  .comparativa tbody tr:last-child { border-bottom: 0; }
  .comparativa tbody tr.mejor { box-shadow: inset 3px 0 0 var(--good); }
  .comparativa tbody tr.mejor td:first-child { box-shadow: none; }
  .comparativa tr > td:nth-child(n) {
    width: auto; padding: 0; border: 0; text-align: left; white-space: normal;
  }
  .comparativa tr > td:nth-child(1) { grid-area: 1 / 1; }
  .comparativa tr > td:nth-child(2) { grid-area: 1 / 2 / 2 / 4; font-size: 15px; }
  .comparativa tr > td:nth-child(5) { grid-area: 1 / 4; text-align: right; font-size: 16px; }
  .comparativa tr > td:nth-child(3) { grid-area: 2 / 2; }
  .comparativa tr > td:nth-child(4) { grid-area: 2 / 3; }
  .comparativa tr > td:nth-child(6) { grid-area: 2 / 4; }
  .comparativa tr > td:nth-child(7) { grid-area: 3 / 2; }
  .comparativa tr > td:nth-child(8) { grid-area: 3 / 3; }
  .comparativa tr > td:nth-child(9) { grid-area: 3 / 4; }
  .comparativa td[data-etiq]::before {
    content: attr(data-etiq); display: block; margin-bottom: 1px;
    font-size: 10px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
    color: var(--ink-4);
  }
  /* El resto de ofertas va dentro de su tarjeta, y el desplazamiento lateral
     ya no hace falta. */
  .producto .tabla-scroll { overflow-x: visible; }
  /* Con la tarjeta estrecha, la gráfica al lado del título deja el título en
     una columna de dos palabras. Se pasa debajo, en su propia línea. */
  .producto .cabeza { flex-wrap: wrap; gap: 10px; }
  .tendencia { flex-direction: row; align-items: center; gap: 8px; }
  /* En pantalla estrecha manda que quepa: el nombre se acorta y los botones se
     apilan antes que sacar la tarjeta fuera de la pantalla. */
  td.linea-nombre { min-width: 0; }
  td.acciones { white-space: normal; }
}

/* Al imprimir o guardar en PDF una comparativa, el menú no pinta nada. */
@media print {
  .lateral, .hueco-lateral, .cargando { display: none !important; }
  main.hoja { padding: 0; }
  .producto { break-inside: avoid; box-shadow: none; }
}

/* --- Componentes: catálogo por categorías con filtros ------------------- */

.cat-rejilla {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
  gap: 14px; margin-bottom: 22px;
}
.cat-tarjeta {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radio); box-shadow: var(--sombra);
  display: flex; flex-direction: column; transition: box-shadow .15s, border-color .15s;
}
.cat-tarjeta:hover { box-shadow: var(--sombra-alta); border-color: var(--accent-soft); }
.cat-cabeza {
  display: grid; grid-template-columns: auto 1fr auto; grid-template-rows: auto auto;
  column-gap: 14px; align-items: center; padding: 18px 18px 14px; color: var(--ink);
}
.cat-cabeza:hover { text-decoration: none; }
.cat-cabeza .cat-icono { grid-row: 1 / 3; }
.cat-icono {
  width: 48px; height: 48px; border-radius: var(--radio-bloque); flex: 0 0 auto;
  background: var(--accent-soft); color: var(--accent);
  display: grid; place-items: center;
}
.cat-nombre { font-family: var(--fuente-titulo); font-weight: 700; font-size: 17px; letter-spacing: -.01em; }
.cat-cuenta { grid-column: 2; font-size: 12.5px; color: var(--ink-4); font-variant-numeric: tabular-nums; }
.cat-ir { grid-column: 3; grid-row: 1 / 3; color: var(--ink-4); transition: transform .15s, color .15s; }
.cat-tarjeta:hover .cat-ir { color: var(--accent); transform: translateX(3px); }
.cat-atajos {
  display: flex; gap: 6px; flex-wrap: wrap;
  padding: 12px 18px 16px; border-top: 1px solid var(--line-soft); margin-top: auto;
}
.nota-pie { font-size: 13px; color: var(--ink-4); max-width: 80ch; }

/* Migas y cabecera de la categoría */
.migas { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--ink-4); margin-bottom: 10px; }
.migas span { color: var(--ink-3); }
.comp-titulo { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-bottom: 14px; }
.comp-titulo h1 { margin: 0; }
.comp-titulo .cat-icono { width: 44px; height: 44px; }

/* En pantalla ancha las nueve caben en dos filas: con una sola fila y scroll,
   la categoría activa (la última, Monitores) quedaba cortada a la derecha y
   no se veía dónde estabas. En móvil sí va en una fila deslizable, y
   componentes_categoria.html la desplaza para que la activa quede a la vista. */
.comp-categorias {
  display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px;
}
@media (max-width: 760px) {
  .comp-categorias { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 4px; scrollbar-width: thin; }
}
.comp-categorias a {
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  padding: 7px 12px; border-radius: var(--radio-chip); font-size: 13px; font-weight: 500;
  color: var(--ink-3); background: var(--surface); border: 1px solid var(--line);
}
.comp-categorias a:hover { text-decoration: none; color: var(--ink); background: var(--surface-2); }
.comp-categorias a.activa { background: var(--ink); color: var(--surface); border-color: var(--ink); }

.comp-atajos { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin-bottom: 18px; }
.rotulo-atajos {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12px; font-weight: 600; color: var(--ink-4); margin-right: 4px;
}
.portada-componentes { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin: 14px 0 4px; }

/* Dos columnas: filtros a la izquierda, fijos al bajar; productos a la derecha. */
.comp-disposicion { display: grid; grid-template-columns: 264px minmax(0, 1fr); gap: 22px; align-items: start; }

.comp-filtros {
  position: sticky; top: 16px; max-height: calc(100vh - 32px); overflow-y: auto;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radio); box-shadow: var(--sombra); padding: 4px 16px 16px;
  scrollbar-width: thin;
}
.comp-filtros > summary {
  list-style: none; cursor: default; display: flex; align-items: center; gap: 8px;
  font-weight: 600; font-size: 14px; padding: 12px 0 8px;
}
.comp-filtros > summary::-webkit-details-marker { display: none; }

.faceta { border: 0; margin: 0; padding: 14px 0; border-top: 1px solid var(--line-soft); min-width: 0; }
.faceta-nombre {
  display: flex; align-items: center; gap: 6px; padding: 0;
  font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-4); margin-bottom: 8px;
}
.faceta-nombre .ayuda { cursor: help; display: inline-flex; }
.faceta-valores { display: flex; flex-direction: column; gap: 1px; }
.faceta-valor {
  display: flex; align-items: center; gap: 9px; cursor: pointer;
  padding: 5px 7px; margin: 0 -7px; border-radius: 8px; font-size: 13.5px; color: var(--ink-2);
}
.faceta-valor:hover { background: var(--surface-2); }
.faceta-valor input { accent-color: var(--accent); width: 16px; height: 16px; margin: 0; flex: 0 0 auto; }
.faceta-valor .texto { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.faceta-valor .n { font-size: 11.5px; color: var(--ink-4); font-variant-numeric: tabular-nums; }
.faceta-valor:has(input:checked) { color: var(--accent); font-weight: 600; }
.faceta-valor:has(input:checked) .n { color: var(--accent); }
.faceta-valor.vacio { color: var(--ink-4); }
.faceta-valor.extra { display: none; }
.faceta.abierta .faceta-valor.extra { display: flex; }
/* Mientras se escribe en la caja de un filtro, manda la caja. */
.faceta.buscando .faceta-valor.coincide { display: flex; }
.faceta.buscando .faceta-valor.no-coincide { display: none; }
.faceta.buscando .ver-mas { display: none; }
.faceta input.faceta-busca { padding: 7px 10px; font-size: 13px; margin-bottom: 6px; }
button.ver-mas {
  background: none; color: var(--accent); border: 0; padding: 4px 0 0; min-height: 0;
  font-family: var(--fuente); letter-spacing: 0; text-transform: none;
  font-size: 12.5px; font-weight: 600; cursor: pointer;
}
button.ver-mas:hover { background: none; text-decoration: underline; }
.sin-dato-faceta { font-size: 11.5px; color: var(--ink-4); margin-top: 6px; cursor: help; }
.precio-tramo { display: flex; align-items: center; gap: 6px; }
.precio-tramo input[type=number] { padding: 8px 9px; font-size: 13px; min-width: 0; }
.precio-tramo button { flex: 0 0 auto; padding: 0 10px; }
.comp-filtros .limpiar { display: block; margin-top: 10px; font-size: 13px; font-weight: 600; }
.comp-filtros .aplicar { width: 100%; margin-top: 12px; }

/* Barra de arriba de los resultados */
.comp-barra { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; margin-bottom: 12px; }
.comp-barra .busca-caja { min-width: 220px; }
.comp-orden select { min-width: 210px; }
.comp-activos { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; margin-bottom: 12px; }
.filtro-activo {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 8px 5px 11px; border-radius: var(--radio-chip); font-size: 12.5px; font-weight: 600;
  background: var(--accent-soft); color: var(--accent);
}
.filtro-activo .que { font-weight: 400; }
.filtro-activo:hover { text-decoration: none; background: var(--accent); color: var(--surface); }
.comp-activos .limpiar { font-size: 12.5px; margin-left: 4px; }
.comp-rango { font-size: 12.5px; color: var(--ink-4); margin: 0 0 10px; font-variant-numeric: tabular-nums; }

/* Tarjeta de producto del catálogo: datos a la izquierda, compra a la derecha. */
.comp-producto {
  display: grid; grid-template-columns: minmax(0, 1fr) 210px;
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radio); box-shadow: var(--sombra); margin-bottom: 12px;
  overflow: hidden; transition: box-shadow .15s;
}
.comp-producto:hover { box-shadow: var(--sombra-alta); }
.comp-info { padding: 16px 18px 14px; min-width: 0; }
.comp-marca { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--ink-3); }
.comp-marca b { text-transform: uppercase; letter-spacing: .05em; font-size: 11.5px; color: var(--ink-2); }
.comp-producto h3 { font-size: 15.5px; line-height: 1.4; margin: 6px 0 10px; overflow-wrap: anywhere; }
.comp-ids { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 10px; font-size: 11.5px; color: var(--ink-4); }
.comp-compra {
  padding: 16px 18px; border-left: 1px solid var(--line-soft); background: var(--surface-2);
  display: flex; flex-direction: column; gap: 4px; justify-content: center;
}
.comp-precio { font-family: var(--fuente-titulo); font-size: 24px; font-weight: 700; letter-spacing: -.02em; line-height: 1.1; }
.comp-donde { font-size: 13px; color: var(--ink-3); }
.comp-stock { display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--good); font-weight: 500; }
.comp-prov { font-size: 12px; color: var(--ink-4); margin-top: 4px; }
.comp-ahorro { display: block; color: var(--good); font-weight: 600; cursor: help; }
.comp-producto.agotado-todo .comp-precio { color: var(--ink-4); }

/* Estrella y campana de la tarjeta. Discretas hasta que se usan: marcadas,
   la estrella se rellena en ámbar y la campana en el rojo de la marca con el
   precio objetivo al lado, para leerlo sin abrir nada. */
.comp-acciones { display: flex; justify-content: flex-end; gap: 4px; margin: -8px -10px 2px 0; }
.icono-btn {
  display: inline-flex; align-items: center; gap: 4px;
  min-height: 30px; min-width: 30px; padding: 0 6px; justify-content: center;
  background: transparent; border: 1px solid transparent; border-radius: var(--radio-s);
  color: var(--ink-4); font-size: 12px; font-weight: 600; cursor: pointer; box-shadow: none;
}
.icono-btn:hover { background: var(--surface); border-color: var(--line); color: var(--ink-2); }
.icono-btn:focus-visible { outline: none; box-shadow: var(--foco); }
.icono-btn:disabled { opacity: .6; cursor: wait; }
.icono-btn.fav.activo { color: var(--warn-bar); }
.icono-btn.fav.activo .ico { fill: currentColor; }
.icono-btn.campana.activo { color: var(--accent); background: var(--accent-soft); }
.icono-btn .objetivo:empty { display: none; }

.aviso-rapido {
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--radio-bloque);
  padding: 10px; margin-bottom: 8px; font-size: 12.5px; color: var(--ink-2);
}
.aviso-rapido[hidden] { display: none; }
.aviso-rapido label { display: block; font-weight: 600; }
.aviso-rapido .entrada-eur { display: flex; align-items: center; gap: 6px; margin-top: 6px; font-weight: 400; }
.aviso-rapido input { width: 100%; min-width: 0; min-height: 32px; padding: 4px 8px; }
.aviso-rapido .botones { display: flex; gap: 6px; margin-top: 8px; }
.aviso-rapido .botones [hidden] { display: none; }
.aviso-rapido .nota { margin-top: 6px; color: var(--good); }
.aviso-rapido .nota:empty { display: none; }
.aviso-rapido .nota.malo { color: var(--danger); }

/* Favoritos en la página de Avisos */
.favorito-fila .titulo a { color: var(--ink); text-decoration: none; }
.favorito-fila .titulo a:hover { color: var(--accent); text-decoration: underline; }
.favorito-fila .antes { color: var(--ink-4); font-size: 12px; }
.favorito-fila .baja { color: var(--good); font-weight: 600; }
.favorito-fila .sube { color: var(--danger); font-weight: 600; }

/* Página de Favoritos: una tarjeta por favorito, con la compra a la derecha y
   los parecidos más baratos debajo. */
.fav-resumen { margin: 0 0 16px; color: var(--ink-3); font-size: 13.5px; }
.fav-resumen b { color: var(--ink); }
.fav-resumen .baja, .fav-resumen .baja b { color: var(--good); }
.fav-tarjeta {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radio); box-shadow: var(--sombra); margin-bottom: 14px; overflow: hidden;
  transition: opacity .15s;
}
.fav-tarjeta.quitado { opacity: .45; }
.fav-cabeza { display: grid; grid-template-columns: minmax(0, 1fr) 250px; }
.fav-info { padding: 16px 18px 14px; min-width: 0; }
.fav-info h3 { font-size: 15.5px; line-height: 1.4; margin: 6px 0 8px; overflow-wrap: anywhere; }
.fav-info h3 a { color: var(--ink); }
.fav-info h3 a:hover { color: var(--accent); }
.fav-guardado { font-size: 12px; color: var(--ink-4); }
.fav-compra {
  padding: 16px 18px; border-left: 1px solid var(--line-soft); background: var(--surface-2);
  display: flex; flex-direction: column; gap: 4px;
}
.fav-tarjeta.apagada .comp-precio { color: var(--ink-4); }
.fav-cambio { display: flex; align-items: center; gap: 4px; font-size: 12.5px; font-weight: 600; }
.fav-cambio.baja { color: var(--good); }
.fav-cambio.sube { color: var(--danger); }
.fav-cambio.igual { color: var(--ink-4); font-weight: 500; }
.fav-comprar {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px; margin-top: 8px;
  min-height: 38px; padding: 8px 14px; border-radius: var(--radio-s);
  background: var(--good); color: var(--surface); font-weight: 600; font-size: 13.5px;
}
.fav-comprar:hover { background: var(--good-strong); color: var(--surface); text-decoration: none; }
.fav-comprar.pequeno { min-height: 30px; padding: 4px 10px; margin-top: 0; font-size: 12.5px; white-space: nowrap; }

.fav-similares { border-top: 1px solid var(--line-soft); padding: 10px 18px 12px; }
.fav-sim-titulo { font-size: 13px; font-weight: 600; color: var(--ink-2); display: flex; flex-wrap: wrap; gap: 8px; align-items: baseline; }
.fav-criterio { font-weight: 500; color: var(--ink-4); font-size: 12px; }
.fav-similares ul { list-style: none; margin: 6px 0 0; padding: 0; }
.fav-similares li {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto auto;
  align-items: center; gap: 10px; padding: 6px 0; border-top: 1px dashed var(--line-soft); font-size: 13px;
}
.fav-similares li:first-child { border-top: 0; }
.fav-similares li .comp-acciones { margin: 0; }
.fav-sim-nombre { color: var(--ink); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fav-sim-nombre:hover { color: var(--accent); }
.fav-similares .precio { font-weight: 700; }
.fav-similares .baja { color: var(--good); font-weight: 600; font-size: 12.5px; }
.fav-otras { font-size: 12.5px; font-weight: 600; }
.fav-sim-vacio { font-size: 12.5px; color: var(--ink-4); display: flex; gap: 6px; align-items: center; }

@media (max-width: 720px) {
  .fav-cabeza { grid-template-columns: 1fr; }
  .fav-compra { border-left: 0; border-top: 1px solid var(--line-soft); }
  .fav-similares li { grid-template-columns: auto minmax(0, 1fr) auto; }
  .fav-similares li .fav-comprar, .fav-similares li > .sin-dato { grid-column: 2 / -1; justify-self: start; }
}

.comp-ofertas { grid-column: 1 / -1; border-top: 1px solid var(--line-soft); }
.comp-ofertas > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: 6px;
  padding: 9px 18px; font-size: 13px; font-weight: 600; color: var(--accent);
}
.comp-ofertas > summary::-webkit-details-marker { display: none; }
.comp-ofertas > summary:hover { background: var(--surface-2); }
.comp-ofertas[open] > summary .ico { transform: rotate(180deg); }
.comp-tabla { min-width: 640px; }
.comp-tabla td, .comp-tabla th { padding-left: 18px; padding-right: 18px; }
.comp-tabla tbody td { padding-top: 10px; padding-bottom: 10px; font-size: 13.5px; }
.comp-vivo {
  display: flex; gap: 10px; flex-wrap: wrap; align-items: center; justify-content: space-between;
  padding: 10px 18px 12px; font-size: 12.5px; color: var(--ink-4); border-top: 1px solid var(--line-soft);
}
.comp-vivo a { display: inline-flex; align-items: center; gap: 5px; font-weight: 600; }

.paginas { display: flex; gap: 4px; flex-wrap: wrap; justify-content: center; margin: 22px 0 6px; }
.paginas a, .paginas span {
  min-width: 38px; height: 38px; padding: 0 11px; border-radius: var(--radio-s);
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 13.5px; font-weight: 500; font-variant-numeric: tabular-nums;
}
.paginas a { background: var(--surface); border: 1px solid var(--line); color: var(--ink-2); }
.paginas a:hover { text-decoration: none; background: var(--surface-2); }
.paginas .actual { background: var(--ink); color: var(--surface); font-weight: 600; }
.paginas .hueco { color: var(--ink-4); min-width: 20px; padding: 0; }

@media (max-width: 1023px) {
  /* minmax(0, …) y no 1fr a secas: con 1fr la columna crece hasta el ancho
     mínimo de la tabla de ofertas y la página entera se desplaza de lado. */
  .comp-disposicion { grid-template-columns: minmax(0, 1fr); }
  .comp-filtros { position: static; max-height: none; }
  .comp-filtros > summary { cursor: pointer; padding: 12px 0; }
  .comp-filtros:not([open]) { padding-bottom: 4px; }
}
@media (max-width: 760px) {
  .comp-producto { grid-template-columns: minmax(0, 1fr); }
  .comp-compra { border-left: 0; border-top: 1px solid var(--line-soft); }
  .comp-orden, .comp-orden select { width: 100%; min-width: 0; }
  table.comp-tabla thead { display: table-header-group; }
}

/* --- Informes: lista a la izquierda, el elegido a la derecha -------------- */
/* Antes todos los informes iban apilados con sus formularios sueltos, y la
   hora y los días se cambiaban en un plegable al final de cada tarjeta. Ahora
   se elige uno en la lista y se ve entero, en tres bloques numerados. */

.inf-marco {
  display: grid; grid-template-columns: 280px minmax(0, 1fr);
  gap: 18px; align-items: start;
}
.inf-lista {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radio); box-shadow: var(--sombra); overflow: hidden;
  position: sticky; top: 16px;
}
.inf-lista-cabeza {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 12px 14px 12px 16px; border-bottom: 1px solid var(--line-soft);
  font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-4);
}
.inf-item {
  display: flex; flex-direction: column; gap: 4px;
  padding: 12px 16px; border-bottom: 1px solid var(--line-soft);
  color: var(--ink); text-decoration: none;
}
.inf-item:last-child { border-bottom: 0; }
.inf-item:hover { background: var(--surface-2); text-decoration: none; }
.inf-item.elegido { background: var(--accent-soft); box-shadow: inset 3px 0 0 var(--accent); }
.inf-item strong { font-size: 14px; font-weight: 600; line-height: 1.3; }
.inf-item-cuando { font-size: 12.5px; color: var(--ink-3); }
.inf-item-estado {
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
  font-size: 12px; color: var(--ink-4);
}

.inf-detalle { min-width: 0; }
.inf-titulo { margin: 0 0 10px; }
.inf-cabecera { display: flex; gap: 18px; align-items: flex-start; flex-wrap: wrap; }
.inf-cabecera-texto { flex: 1 1 300px; min-width: 0; }
.inf-datos { display: flex; gap: 8px 28px; flex-wrap: wrap; margin: 14px 0 0; }
.inf-datos dt {
  font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--ink-4); margin-bottom: 3px;
}
.inf-datos dd { margin: 0; font-size: 14px; color: var(--ink); }
.inf-botones { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.inf-botones form { display: inline; margin: 0; }

.inf-seccion {
  display: flex; align-items: center; gap: 10px;
  font-size: 15px; font-weight: 600; margin: 0 0 16px;
}
.inf-num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent);
  font-size: 12.5px; font-weight: 700;
}

.inf-dias { margin-top: 16px; }
.inf-dias-fila { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.inf-atajos { display: inline-flex; gap: 6px; flex-wrap: wrap; margin-left: 8px; }
.inf-pie {
  display: flex; gap: 14px; align-items: center;
  margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line-soft);
}

.inf-tabla input[type=text], .inf-tabla select { padding: 7px 10px; font-size: 13px; }
.inf-tabla select { padding-right: 30px; }
.inf-tabla tr.inf-nueva td { background: var(--surface-2); }
.inf-nota { margin: 0; padding: 12px 20px 16px; border-top: 1px solid var(--line-soft); }
.inf-correos { display: flex; gap: 8px; flex-wrap: wrap; margin-bottom: 14px; }
.inf-correos form { display: inline; margin: 0; }

@media (max-width: 1023px) {
  .inf-marco { grid-template-columns: minmax(0, 1fr); }
  .inf-lista { position: static; }
}
@media (max-width: 760px) {
  /* Cada componente, en su propia ficha: nombre, categoría y botones uno bajo
     otro. En fila no cabían y la tabla empujaba la página de lado. */
  .inf-tabla, .inf-tabla tbody, .inf-tabla tr, .inf-tabla td { display: block; width: 100%; }
  .inf-tabla tr { padding: 10px 15px; border-bottom: 1px solid var(--line-soft); }
  .inf-tabla tbody td { padding: 4px 0; border: 0; text-align: left; }
  .inf-tabla td:empty { display: none; }
  td.linea-nombre { min-width: 0; }
  .inf-atajos { margin-left: 0; }
}
