  .addrow { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
  /* Los dos botones de la primera columna: **corregir** y **quitar**.
     Son controles pequeños dentro de una celda, no botones de formulario, y sin
     esta regla heredan el `button` de arriba —azul, 11×20 px de relleno— y
     empujan el nombre a la línea siguiente. Pasó: al quitar los chips se llevó
     por delante este bloque, que estaba entre medias. Hay un test. */
  /* El nombre ocupa lo que necesite y los botones se quedan a su derecha, a la
     misma altura. Sueltos en el flujo del texto caían debajo del nombre en
     cuanto la columna se estrechaba. */
  /* El selector de supermercados y el código postal, en la misma línea. La
     página de búsqueda ya lo hacía; esta nunca recibió la regla, así que cada
     `<details>` —que es `display: block`— se quedaba en su propio renglón.
     `#cp` es solo un envoltorio: con `display: contents` el desplegable de
     dentro es el que se coloca, y no el `<span>`. */
  #shops { display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
           margin-top: 12px; }
  #cp { display: contents; }
  body[data-seccion="carros"] #vaciar, body[data-seccion="carros"] #descargas { display: none !important; }
  body[data-seccion="carros"] #compartirlista { display: none !important; }
  /* «Guardar lista» y su rótulo («Lista sin guardar») tampoco: guardar es de la lista y de la compra. */
  body[data-seccion="carros"] #guardar, body[data-seccion="carros"] #listaactual { display: none !important; }
  /* **La forma la dicta la fila, no de dónde venga el botón.**
     «Guardar lista» y «Vaciar lista» son `.chip-btn`, que en la fila de añadir
     se pinta azul y sólido porque allí es la acción principal. Aquí están
     entre pastillas —Supermercados, el código postal, Descargar— y ese azul
     los convertía en dos manchas de 39 px en mitad de una fila de controles de
     31. Se les da el mismo aspecto que al `<summary>` de al lado. */
  #shops > button {
    padding: 5px 12px; border-radius: 999px; font-size: 12.5px;
    border: 1px solid var(--line); background: var(--card);
    /* Sin peso propio: el `<summary>` de al lado hereda el de la página, así
       que ponerles negrita los dejaba distintos otra vez, ahora por el texto. */
    color: var(--text); font-weight: inherit; cursor: pointer;
  }
  #shops > button:hover { border-color: var(--muted); }
  /* **La altura de esta fila se dice en `base.html`**, con el mismo peso para
     todos. Es la misma pelea que la fila de añadir —un `<button>` usa
     `line-height: normal` y la tipografía del sistema, y un `<summary>` hereda
     las de la página, así que con el mismo relleno salen distintos: medido, 26
     contra 31— y está ahí arriba porque **la fila es de tres páginas**: aquí,
     «Buscar» y «Ofertas». Escrita solo aquí, la misma pastilla medía 31 en la
     lista y 36 en las otras dos. Y «Descargar» lleva `.chip-btn` en su
     `<summary>`: sin el peso igualado saldría en negrita mientras
     «Supermercados» no, que es igualar la caja y dejar el texto distinto. */

  .trm { display: flex; align-items: center; gap: 2px; }
  .trm .nm { flex: 1; min-width: 0; }
  .accfila { flex: none; white-space: nowrap; }
  .editterm {
    background: none; border: 0; color: var(--muted); cursor: pointer;
    font-size: 12px; line-height: 1; padding: 2px 4px; margin-left: 4px;
    border-radius: 5px; vertical-align: middle;
    opacity: 0; transition: opacity .12s;
  }
  tr.item:hover .editterm, .editterm:focus { opacity: 1; }
  .editterm:hover { color: var(--accent); background: var(--bg); }
  /* Quitar no es corregir: en rojo, como todo lo que destruye algo. */
  .editterm.quitar:hover { color: var(--err); background: var(--bg); }
  /* Si la fila no ha encontrado nada, el lápiz se ve sin pasar por encima: es
     justo lo que hay que hacer ahí. */
  tr.sinnada .editterm { opacity: 1; }
  /* **Los filtros de una línea se ven siempre que estén puestos**: un tope
     olvidado esconde productos sin que se note, y la marca en la propia fila
     es lo que lo delata. En el azul de los controles, con su número. */
  .editterm.filtroslinea.activo { opacity: 1; color: var(--accent); font-weight: 700; }
  .cell.filtrado { font-size: 11.5px; color: var(--muted); font-style: italic; }
  #cajonfiltros .filtroslinea .fayuda,
  #cajonfiltros .filtroslinea .fresumen { margin: 0; font-size: 13px; color: var(--muted); }
  #cajonfiltros .filtroslinea .fresumen { color: var(--text); font-weight: 600; }
  td input.editnm {
    font: inherit; padding: 0 2px; min-width: 60px;
    border: 0; border-bottom: 1px solid var(--accent);
    background: transparent; color: var(--text); outline: none;
  }
  .hint { color: var(--muted); font-size: 13px; margin-top: 10px; }

  .scroller { overflow-x: auto; }
  /* El aviso de «envase ×10»: ámbar, como lo que hay que mirar dos veces. */
  .grande { display: block; font-size: 10.5px; font-weight: 700; color: var(--aviso);
    white-space: nowrap; cursor: help; }
  /* **Una sombra en el borde mientras quede tabla por ver.** Con veintidós
     tiendas la tabla se corta a la derecha («Supermercados M…») y nada decía
     que se podía desplazar. La pone el JavaScript (`.mas-dcha`) mirando el
     desplazamiento, y va en un envoltorio porque dentro del propio `.scroller`
     se iría con lo que se desplaza. No hay sombra a la izquierda: la primera
     columna es fija y ya tapa lo que queda atrás. */
  .tablawrap { position: relative; }
  .tablawrap::after {
    content: ""; position: absolute; top: 0; right: 0; bottom: 0; width: 28px;
    pointer-events: none; opacity: 0; transition: opacity .15s;
    background: linear-gradient(to left, rgba(0, 0, 0, .14), rgba(0, 0, 0, 0));
  }
  .tablawrap.mas-dcha::after { opacity: 1; }
  table { border-collapse: collapse; width: 100%; font-size: 13.5px; }
  th, td { padding: 9px 10px; text-align: left; border-bottom: 1px solid var(--line); }
  th { font-size: 12.5px; font-weight: 700; color: var(--muted); white-space: nowrap; }
  td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
  tr.item > td:first-child {
    font-weight: 600; min-width: 190px;
    /* Con el aviso de "no encontrado" dentro, sin tope la columna se comía la
       tabla. */
    max-width: 280px;
  }
  tr.item:hover { background: var(--chip); }
  .cell { cursor: pointer; }
  .cell.na { color: var(--muted); }
  .cell.pick { color: var(--accent); font-weight: 700; }
  /* Decidido por ti que no lo llevas, distinto de que la tienda no lo tenga. */
  .cell.descartado { color: var(--muted); font-style: italic; font-size: 11.5px; }
  /* Precio traído de la lista guardada, no de una búsqueda de ahora. */
  .cell.viejo { opacity: .65; font-style: italic; cursor: help; }
  /* Cuánto ha cambiado la cesta guardada. */
  #cambios {
    margin-bottom: 10px; padding: 10px 12px; border-radius: 8px;
    background: var(--card); border: 1px solid var(--line); font-size: 12.5px;
  }
  #cambios h4 { margin: 0 0 6px; font-size: 12.5px; color: var(--muted); font-weight: 600; }
  .cambiofila { display: flex; align-items: baseline; gap: 8px; padding: 2px 0; flex-wrap: wrap; }
  .cambiofila .tienda-nm { min-width: 130px; font-weight: 600; }
  .cambiofila .pares { color: var(--muted); }
  .delta { font-weight: 700; white-space: nowrap; }
  .delta.sube { color: var(--err); }
  .delta.baja { color: var(--best); }
  .delta.igual { color: var(--muted); font-weight: 400; }
  .cellnums .delta, .compralinea .delta { font-size: 11px; }
  .cambiofila .resto { color: var(--muted); font-size: 11.5px; }
  #avisoviejo {
    margin-bottom: 10px; padding: 9px 12px; border-radius: 8px;
    background: var(--card); border: 1px dashed var(--line);
    color: var(--muted); font-size: 12.5px;
  }
  .cheapest { color: var(--best); font-weight: 700; }
  tr.total td { border-top: 2px solid var(--line); border-bottom: 0; font-weight: 700; padding-top: 12px; }
  tr.total td:first-child { font-size: 13px; font-weight: 700; }
  /* El total de la compra, **debajo de la tabla y no dentro** (ver el hueco en
     el HTML). Se queda quieto aunque la tabla se desplace a lo ancho, que es
     justo lo que hay que poder leer sin arrastrar nada. */
  #totaltabla {
    border-top: 1px dashed var(--line); padding-top: 10px; margin-top: 2px;
    display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  }
  #totaltabla .rot { font-weight: 700; font-size: 13px; }
  #totaltabla b { font-size: 19px; color: var(--best); }
  #totaltabla .det { flex: 1 1 100%; font-size: 12px; color: var(--muted); }
  #mercapanel {
    margin-top: 14px; padding: 14px 16px; border-radius: 12px;
    background: var(--card); border: 1px solid var(--line); font-size: 13.5px;
  }
  #mercapanel h3 { margin: 0 0 6px; font-size: 15px; }
  #mercapanel ol { margin: 10px 0; padding-left: 20px; }
  #mercapanel li { margin-bottom: 8px; }
  #mercapanel .nota { color: var(--muted); font-size: 12px; margin: 8px 0 12px; }
  /* El botón de la extensión manda sobre el panel cuando está: es el camino
     corto, y los marcadores quedan debajo como alternativa. */
  #extzona { margin: 10px 0 14px; }
  #extllenar.primario { background: var(--accent, #1a73e8); color: var(--sobre-accent, #fff);
    border-color: transparent; font-weight: 600; padding: 8px 14px; }
  #extllenar.primario[disabled] { opacity: .6; cursor: progress; }
  #extestado { margin: 6px 0 0; }
  /* Una línea por tienda: con diecinueve pegadas en un párrafo no se
     distinguía cuál había entrado, que es lo único que se mira. */
  .extresultado { margin-top: 6px; display: flex; flex-direction: column; gap: 2px; }
  .extfila { display: flex; gap: 8px; align-items: baseline; font-size: 12.5px; }
  .extfila b { flex: 0 0 auto; }
  .extfila span { color: var(--muted); }
  .extfila.bien b { color: var(--ok); }
  .extfila.mal b { color: var(--err); }
  #extinstalar { margin: 10px 0 14px; }
  #extinstalar summary { cursor: pointer; font-weight: 600; }
  #extinstalar ol { margin: 8px 0; padding-left: 20px; }
  #extinstalar li { margin-bottom: 6px; }
  /* El campo de respaldo al copiar: si el navegador no deja tocar el
     portapapeles, el texto se enseña aquí ya seleccionado. */
  .pegamarcador { font-size: 12px; width: 100%; margin-top: 4px; padding: 4px 6px;
    border: 1px solid var(--line); border-radius: 6px; background: var(--card);
    color: var(--muted); }
  /* El marcador se **arrastra** y el de abrir se **pulsa**: el cursor tiene que
     decir cuál es cuál, que si no el de «abrir» parece otro que arrastrar. */
  #mercalet2, .mercafila a.marcador { display: inline-block; text-decoration: none;
    cursor: grab; }
  .mercafila a.abrir { display: inline-block; text-decoration: none;
    cursor: pointer; background: var(--chip); color: var(--text);
    border: 1px solid var(--line); }
  .mercafila { display: flex; align-items: center; gap: 10px; padding: 7px 0;
    border-bottom: 1px solid var(--line); flex-wrap: wrap; }
  /* El camino corto de verdad: un botón que llena el carro sin instalar nada.
     Se rellena como el de la extensión porque es lo mismo para quien mira —lo
     que cambia por dentro no es asunto suyo— y va delante de todo lo demás. */
  .mercafila a.directo, .mercafila button.directo {
    display: inline-block; text-decoration: none; cursor: pointer;
    background: var(--accent); color: var(--sobre-accent); border: 1px solid transparent;
    font-weight: 600; }
  .mercafila button.directo[disabled] { opacity: .6; cursor: progress; }
  /* La lista guiada: una línea por producto, con su casilla y su enlace. Es lo
     único que vale en las once tiendas que no dejan llenar el carro desde
     fuera, y en un móvil es lo que de verdad se usa. */
  .guiada { width: 100%; margin: 2px 0 6px; }
  .guiada > summary { cursor: pointer; font-size: 12.5px; color: var(--accent); }
  .plegamarcador > summary { color: var(--muted); }
  .guiada ol { list-style: none; margin: 6px 0 0; padding: 0; }
  .guiada li { display: flex; align-items: center; gap: 8px; padding: 5px 0;
    border-top: 1px solid var(--line); }
  .guiada li input { flex: none; width: 18px; height: 18px; }
  .guiada li a { flex: 1; min-width: 0; font-size: 13px; color: var(--text);
    text-decoration: none; }
  .guiada li a:hover { color: var(--accent); text-decoration: underline; }
  .guiada li.metido a { text-decoration: line-through; color: var(--muted); }
  .guiada li .uds { flex: none; font-size: 12px; color: var(--muted); }
  .guiada .cuenta { font-size: 12px; color: var(--muted); margin: 6px 0 0; }
  .mercafila .qué { flex: 1; min-width: 0; font-size: 12.5px; color: var(--muted); }
  /* Cada tienda cuenta lo suyo en su propia fila: con cinco, el resultado de
     las cinco pegado en una línea no se lee. */
  .mercafila .dice:not(:empty) { flex-basis: 100%; color: var(--accent); }
  .mercafila b { font-size: 13px; color: var(--text); }
  /* **En el móvil, el nombre y el botón en una línea y la nota debajo.** La
     nota iba en la misma fila que el botón, así que en una pantalla de 390 px
     se quedaba en una columna estrecha: «2 productos · tarda un rato: los añade
     de uno en uno» ocupaba seis líneas. */
  @media screen and (max-width: 720px) {
    .mercafila > b { flex: 1 1 auto; }
    .mercafila > .qué:not(.dice) { flex: 1 1 100%; }
  }
  .cover { display: block; font-size: 11px; font-weight: 400; color: var(--muted); }
  .cover.miss { color: var(--err); }
  .cover.multi { color: var(--accent); font-weight: 700; cursor: help; }
  .win { display: block; font-size: 11px; font-weight: 700; color: var(--best); }
  tr.detail td { background: var(--bg); padding: 0; }
  /* Los anchos los fija `alinearDetalles` copiándolos de la cabecera. */
  .detail-inner { display: grid; align-items: start; }
  .detail-cell { padding: 8px 10px; min-width: 0; }
  .sinopts { color: var(--muted); font-size: 12px; }
  /* Selector de producto: un <select> no admite imágenes en sus opciones, así
     que se construye a mano para poder mostrar la foto de cada uno. */
  .prodpick { flex: 1; min-width: 0; }
  .prodpick { min-width: 0; }
  .prodpick > summary {
    width: 100%; border-radius: 8px; padding: 4px 8px; gap: 6px;
    font-size: 12px; justify-content: flex-start;
  }
  .prodpick > summary .caret { margin-left: auto; color: var(--muted); }
  .prodpick .lbl {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1;
  }
  /* `fixed`, no `absolute`: la tabla tiene scroll horizontal y un panel
     absoluto se vería recortado por él, pero dentro de la celda queda de ~150 px
     e ilegible. Lo coloca `colocarPanel()`. */
  .prodpick .ddpanel {
    position: fixed; top: 0; left: 0; width: max-content;
    /* `min()` es de Chrome 79 y el WebView de la app puede ser anterior:
       la declaración entera se ignoraría. `width` + `max-width` hace lo
       mismo en todos. */
    min-width: 360px; max-width: 92vw; width: 560px; max-height: 60vh;
  }
  .prodpick .ddrow .tx { white-space: normal; overflow: visible; }
  .prodpick .ddrow { gap: 10px; font-size: 12.5px; align-items: center; }
  .prodpick .ddrow.sel { background: var(--chip); font-weight: 700; }
  .prodpick .pr { font-variant-numeric: tabular-nums; font-weight: 700; white-space: nowrap; }
  .prodpick .tx { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .prodpick .up { color: var(--muted); font-size: 11px; margin-left: auto; white-space: nowrap; }
  .prodpick .ddrow input[type=checkbox] { accent-color: var(--accent); cursor: pointer; margin: 0; }
  /* Los dos modos de una tienda —automático y no llevar nada— no son productos,
     son acciones. Con la misma pinta de fila que los productos no se leían como
     pulsables: parecían un producto más de la lista. Van como botones de ancho
     completo, y el activo se rellena para que se vea cuál está puesto. */
  .prodpick .ddacc {
    display: flex; align-items: center; gap: 8px; width: 100%;
    padding: 7px 9px; margin-bottom: 4px; font: inherit; font-size: 12.5px;
    text-align: left; cursor: pointer;
    border: 1px solid var(--line); border-radius: 8px;
    background: var(--card); color: var(--text);
  }
  .prodpick .ddacc:hover { border-color: var(--muted); background: var(--chip); }
  .prodpick .ddacc .ic { line-height: 1; }
  .prodpick .ddacc .et { flex: 1; min-width: 0; }
  .prodpick .ddacc .sub {
    font-size: 11px; color: var(--muted); white-space: nowrap; font-weight: 400;
  }
  .prodpick .ddacc.on { font-weight: 700; border-color: var(--accent); background: var(--chip); }
  /* Descartar una tienda se marca en rojo, no en el azul de "elegido": no es una
     elección de producto, es dejar esa tienda sin nada. */
  .prodpick .ddnada.on { border-color: var(--err); color: var(--err); }
  .prodpick .ddnada.on .sub { color: var(--err); }
  /* "Solo de aquí" es lo contrario: se queda con esta tienda, así que va en el
     verde de "esta es la buena" y no en el rojo de descartar. */
  .prodpick .ddsolo.on { border-color: var(--best); color: var(--best); }
  .prodpick .ddsolo.on .sub { color: var(--best); }
  .prodpick .cant {
    width: 52px; font: inherit; font-size: 12px; padding: 2px 4px; text-align: right;
    border: 1px solid var(--line); border-radius: 6px;
    background: var(--bg); color: var(--text);
  }
  /* El nombre del supermercado se repite sobre el selector: la fila de detalle
     puede quedar lejos de la cabecera al hacer scroll horizontal. */
  .prodpick-shop {
    display: block; font-size: 11.5px; font-weight: 700;
    color: var(--muted); margin-bottom: 4px;
  }
  .spinwrap { display: inline-flex; align-items: center; gap: 6px; color: var(--muted); font-size: 12px; }
  #progress { color: var(--muted); font-size: 13px; margin-bottom: 12px; }
  #avisos { margin-bottom: 12px; display: grid; gap: 4px; }
  .aviso {
    color: var(--err); font-size: 13px; padding: 7px 10px; border-radius: 8px;
    border: 1px solid var(--err); background: var(--card);
  }
  td.failed { color: var(--err); cursor: help; font-weight: 700; }
  /* Miniaturas: la tabla ya hace scroll horizontal, así que caben sin romperla. */
  .cellbox { display: flex; align-items: center; gap: 8px; justify-content: flex-end; }
  .thumb {
    width: 34px; height: 34px; flex: none; object-fit: contain;
    background: var(--card); border: 1px solid var(--line); border-radius: 5px;
  }
  .thumb.vacia {
    display: grid; place-items: center; font-size: 8px; line-height: 1;
    color: var(--muted); text-align: center;
  }
  .thumb.vacia.conlogo { background: var(--chip); border-color: transparent; }
  .thumb.vacia img { width: 84%; height: 84%; object-fit: contain; opacity: .5;
    filter: grayscale(.4); mix-blend-mode: multiply; border-radius: 3px; }
  @media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .thumb.vacia img { mix-blend-mode: normal; }
  }
  :root[data-theme="dark"] .thumb.vacia img { mix-blend-mode: normal; }
  .cellnums { display: flex; flex-direction: column; align-items: flex-end; }
  .pickrow .thumb { width: 28px; height: 28px; }
  #empty { color: var(--muted); padding: 32px 0; text-align: center; }
  #empty .ejemplos { display: flex; flex-wrap: wrap; gap: 6px; justify-content: center;
    margin: 12px auto; max-width: 30rem; }
  #empty .ejemplo { padding: 6px 13px; border-radius: 999px; font-size: 13px;
    font-weight: 600; background: var(--card); color: var(--text);
    border: 1px solid var(--line); cursor: pointer; }
  #empty .ejemplo:hover { border-color: var(--accent); color: var(--accent); }
  #empty .ejemplo.todos { color: var(--accent); }
  /* **`.chip-btn` vive en `base.html`.** Estaba aquí y la usa también el panel
     del código postal, que es de las tres páginas: fuera de la lista su botón
     salía sin estilar. */
  label.foto { padding: 11px 18px; font-size: 15px; border-radius: 8px; cursor: pointer; }
  /* Revisión del OCR: nada entra en la lista sin pasar por aquí. */
  .amanofila { display: flex; align-items: center; gap: 8px; margin: 8px 0; }
  .amanofila label { width: 8.5rem; font-size: 13.5px; color: var(--muted); }
  .amanofila input { flex: 1; min-width: 0; height: 34px; padding: 0 10px;
    border: 1px solid var(--line); border-radius: 8px; background: var(--card);
    color: var(--text); font-size: 14px; }
  .amanofila input:focus { outline: none; border-color: var(--accent); }
  /* Lo apuntado a mano se distingue de lo que dice una tienda. No es un
     adorno: un precio que has escrito tú y uno que se ha leído de su web no
     valen lo mismo, y la tabla no puede dar a entender que sí. */
  .mio { font-style: italic; }
  .mio .amano { font-style: normal; font-size: 10.5px; color: var(--muted);
    border: 1px solid var(--line); border-radius: 999px; padding: 0 5px;
    margin-left: 4px; }
  #guardarpanel, #amanopanel {
    background: var(--card); border: 1px solid var(--accent); border-radius: 12px;
    padding: 16px 18px; margin-bottom: 16px;
  }
  #guardarpanel h2, #amanopanel h2 { margin: 0 0 4px; font-size: 16px; }
  #guardarpanel .sub, #amanopanel .sub {
    margin: 0 0 12px; color: var(--muted); font-size: 13px;
  }
  #guardaropciones { display: grid; gap: 2px; margin-bottom: 14px; }
  .gopcion {
    display: flex; align-items: center; gap: 10px; padding: 7px 8px;
    border-radius: 8px; cursor: pointer;
  }
  .gopcion:hover { background: var(--bg); }
  .gopcion input[type=radio] { accent-color: var(--accent); cursor: pointer; }
  .gopcion .meta { font-size: 11.5px; color: var(--muted); }
  .gopcion input[type=text] {
    flex: 1; min-width: 0; padding: 6px 9px; font-size: 14px;
    border: 1px solid var(--line); border-radius: 7px;
    background: var(--bg); color: var(--text);
  }
  #guardarpanel .acciones, #amanopanel .acciones { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
  #guardarpanel .cancelar { background: none; border: 1px solid var(--line); color: var(--muted); }
  /* Lupa: la foto de la lista es diminuta y muchos productos solo se
     distinguen por el envase. Al posarse encima se ve en grande. */
  #lupa {
    position: fixed; z-index: 40; width: 260px; padding: 12px;
    background: var(--card); border: 1px solid var(--line); border-radius: 12px;
    box-shadow: 0 10px 34px rgba(0,0,0,.22); pointer-events: none;
  }
  /* **Clavada sí se deja tocar, siguiendo al ratón no.** `pointer-events: none`
     está para que la foto no se coma el `mouseover` de lo que tiene debajo
     —se cerraría sola en cuanto se colocara encima—; pero cuando se ha clavado
     con un toque es lo contrario: hay que poder tocarla para quitarla. */
  #lupa.clavada { pointer-events: auto; cursor: zoom-out; }
  /* La ✕ recibe el dedo **aunque la lupa no**: un hijo puede volver a
     activarlos, y así el panel sigue sin comerse el `mouseover` de lo que tapa.
     28 px, que es lo mínimo con lo que se acierta. */
  #lupa .cerrarlupa {
    position: absolute; top: 6px; right: 6px; z-index: 1;
    width: 28px; height: 28px; padding: 0; pointer-events: auto;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 15px; line-height: 1;
    background: var(--chip); color: var(--text);
    border: 1px solid var(--line); border-radius: 8px;
  }
  #lupa .cerrarlupa:hover { border-color: var(--muted); }
  #lupa .foto {
    width: 100%; height: 200px; display: grid; place-items: center;
    background: var(--bg); border-radius: 8px; margin-bottom: 10px;
  }
  /* El tope va en píxeles, no en `%`: dentro de una rejilla con `place-items:
     center` el porcentaje no resuelve contra la caja, y la imagen salía 234 px
     de alto en un hueco de 200 metiéndose en el nombre de debajo. */
  #lupa .foto img { max-width: 100%; max-height: 200px; object-fit: contain; }
  #lupa .foto .sinfoto { color: var(--muted); font-size: 12px; }
  #lupa .nm { font-size: 13px; line-height: 1.35; }
  #lupa .datos {
    display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
    margin-top: 8px; font-variant-numeric: tabular-nums;
  }
  #lupa .pr { font-size: 19px; font-weight: 700; }
  #lupa .ud { font-size: 11.5px; color: var(--muted); }
  #lupa .tienda {
    font-size: 11px; color: var(--muted); margin-left: auto;
    font-weight: 700;
  }
  .compralinea.mirando { background: var(--chip); }

  /* Elegir entre comparar cestas enteras y repartir la compra. */
  /* Las opciones de un desplegable, **una debajo de otra**: son cosas
     distintas, no variantes de la misma, y en fila se leen como una sola. */
  .ddpanel.columna { display: flex; flex-direction: column; gap: 6px;
    padding: 8px; min-width: 12rem; }
  .ddpanel.columna > * { width: 100%; text-align: left; }
  /* **Del mismo alto que los botones de su fila.** Es un `<summary>`, no un
     `<button>`, así que no hereda nada: sin esto quedaba un dedo más bajo que
     «Vaciar lista» y la fila se veía desalineada. */
  #otrasformas > summary {
    /* **Mismo alto exacto que «Vaciar lista» y «Buscar precios».** Es un
       `<summary>`, no un `<button>`: no hereda nada, y además lleva borde de
       1 px que los botones no tienen. Por eso el relleno es menor y la altura
       de línea va escrita — con el `padding` de los botones quedaba 11 px más
       alto y la fila se veía descuadrada. */
    /* **El mismo alto que los botones de su fila**, y hay que escribirlo dos
       veces porque los botones también cambian de tamaño en móvil. Estirarlo
       con `align-items: stretch` funcionaba en escritorio y no en móvil: allí
       el desplegable ocupa la fila entera (`.dd { flex: 1 1 100% }`), así que
       un `height: 100%` no tiene contra qué resolver y se encogía.

       El relleno vertical va **1 px por debajo** del de los botones porque
       esto lleva borde y ellos no. */
    padding: 0 20px; font-size: 15px; font-weight: 600; cursor: pointer;
    box-sizing: border-box; border-radius: 8px; background: var(--card);
    color: var(--text); border: 1px solid var(--line); list-style: none;
    display: inline-flex; align-items: center; line-height: normal;
  }
  /* **La altura se escribe, y para los dos.** Perseguirla con `padding` no
     converge: un `<button>` usa `line-height: normal` **y la tipografía del
     sistema**, y un `<summary>` hereda las de la página, así que con el mismo
     relleno salen alturas distintas — y distintas en cada tamaño de pantalla.
     Diciéndola una vez para ambos, la fila queda alineada y se acabó. */
  .addrow > button, #otrasformas > summary { height: 42px; }
  .addrow .mas { display: none; }
  /* **Parar se ve distinto, y no por adorno.** Es el mismo botón que buscar,
     así que sin cambiar de color se pulsaría creyendo que se vuelve a buscar —
     que es justo lo contrario—. Rojo como «no lo llevo» del selector: no es un
     error, es una decisión tuya que quita algo. */
  #run.cortar { background: var(--err); border-color: var(--err); }
  /* **Lo de dentro del desplegable, sin recuadro**, igual que en el menú: son
     opciones de una lista, y la pastilla que llevan por venir de una fila de
     la página solo mete ruido dentro de un panel. El que sí lo lleva es el
     `<summary>`, que es lo que hay que ver pulsable. */
  #otrasformas .ddpanel > * {
    border: 0; background: none; border-radius: 6px; padding: 9px 8px;
    color: var(--text); font-weight: 600; font-size: 14px;
  }
  #otrasformas .ddpanel > *:hover { background: var(--bg); color: var(--accent); }
  #otrasformas > summary::-webkit-details-marker { display: none; }
  #otrasformas > summary:hover { border-color: var(--accent); color: var(--accent); }
  #modos { display: flex; gap: 6px; margin-bottom: 12px; flex-wrap: wrap; }
  #modos button[aria-pressed="true"] {
    border-color: var(--accent); color: var(--accent); font-weight: 700;
  }
  .compralinea .mover {
    font: inherit; font-size: 11.5px; padding: 3px 6px; max-width: 210px;
    border: 1px solid var(--line); border-radius: 6px;
    background: var(--bg); color: var(--muted);
  }
  .compralinea .mover:hover { border-color: var(--accent); color: var(--text); }
  /* Cierre de la compra: el total, al final, que es donde se busca. */
  #totalfinal {
    margin-top: 14px; padding: 14px 16px; border-radius: 12px;
    background: var(--card); border: 2px solid var(--accent);
  }
  #totalfinal .cifra {
    display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap;
  }
  #totalfinal .cifra b { font-size: 24px; margin-left: auto; }
  #totalfinal .rotulo { font-size: 14px; font-weight: 700; }
  #totalfinal .desglose {
    margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--line);
    font-size: 12.5px; color: var(--muted);
  }
  #resumenreparto {
    margin-bottom: 12px; padding: 10px 12px; border-radius: 8px;
    background: var(--card); border: 1px solid var(--line); font-size: 12.5px;
  }
  #resumenreparto b { font-size: 15px; }
  #resumenreparto .frente { color: var(--muted); }
  /* Empate al precio más bajo: la elección automática sería un volado. */
  #resumenreparto .empate {
    margin-top: 6px; padding-top: 6px; border-top: 1px solid var(--line);
    color: var(--accent); font-weight: 600;
  }
  .compralinea.empatada { background: color-mix(in srgb, var(--accent) 7%, transparent); }
  .empatemarca {
    display: block; font-size: 11px; font-weight: 700; color: var(--accent);
  }
  /* La compra por supermercado: lo que te llevas a la tienda. */
  #compra { display: grid; gap: 14px; margin-bottom: 16px; }
  .tienda {
    background: var(--card); border: 1px solid var(--line); border-radius: 12px;
    padding: 14px 16px;
  }
  .tienda.gana { border-color: var(--best); }
  .tienda.incompleta { opacity: .72; }
  .tienda > h3 {
    margin: 0 0 10px; font-size: 15px;
    display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  }
  .tienda .tot { margin-left: auto; font-size: 17px; font-weight: 700; }
  .tienda .marca {
    font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 999px;
    background: var(--bg); color: var(--best); border: 1px solid var(--best);
  }
  .tienda .marca.mal { color: var(--err); border-color: var(--err); }
  /* «Sin buscar» no es un fallo ni una falta: es que no se sabe todavía, y en
     rojo se leería como lo segundo. */
  .tienda .marca.sinbuscar { color: var(--muted); border-color: var(--line); }
  .compralinea {
    display: flex; align-items: center; gap: 10px;
    padding: 7px 0; border-top: 1px solid var(--line);
  }
  .compralinea .nom { flex: 1; min-width: 0; font-size: 13.5px; }
  .compralinea .term { display: block; font-size: 11px; color: var(--muted); }
  .compralinea .prec { font-weight: 700; white-space: nowrap; text-align: right; }
  .compralinea .prec .cover { font-weight: 400; }
  .enlacecomp { padding: 8px 10px 10px; border-bottom: 1px solid var(--line); }
  .enlacecomp input {
    width: 100%; padding: 6px 8px; font-size: 12px; margin-bottom: 4px;
    border: 1px solid var(--accent); border-radius: 6px;
    background: var(--bg); color: var(--text);
  }
  .enlacecomp span { font-size: 11.5px; color: var(--muted); line-height: 1.4; }
  #bajadas {
    margin: 0 0 10px; padding: 10px 12px; border-radius: 10px;
    background: color-mix(in srgb, var(--down) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--down) 35%, transparent);
    font-size: 13.5px;
  }
  #bajadas b { color: var(--down); }
  #bajadas ul { margin: 6px 0 0; padding-left: 18px; }
  #bajadas li { margin: 2px 0; }
  .oferta { display: inline-flex; align-items: baseline; gap: 4px; font-size: 10.5px; }
  .oferta s { color: var(--muted); }
  .oferta b { color: var(--down); font-weight: 700; }
  .compralinea .cant {
    display: inline-block; margin-left: 8px; padding: 1px 7px;
    border-radius: 999px; font-size: 11px; font-weight: 700;
    background: var(--chip); color: var(--accent);
  }
  .compralinea.falta .nom { color: var(--err); font-style: italic; }
  .compralinea.sinbuscar .nom { color: var(--muted); }
  .compralinea.viejo { opacity: .65; font-style: italic; }
  /* La casilla de ir cogiendo: lo mismo que el HTML descargable, pero aquí. */
  .compralinea .coger {
    width: 21px; height: 21px; flex: none; margin: 0; cursor: pointer;
    accent-color: var(--accent);
  }
  .compralinea.cogido .nom, .compralinea.cogido .prec {
    text-decoration: line-through; color: var(--muted);
  }
  .compralinea.cogido .thumb { opacity: .45; }
  #cogidos {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    margin: 0 0 10px; font-size: 13px; color: var(--muted);
  }
  #cogidos .barra {
    flex: 1; min-width: 90px; height: 6px; border-radius: 999px;
    background: var(--line); overflow: hidden;
  }
  #cogidos .barra i { display: block; height: 100%; background: var(--ok); }
  #cogidos b { color: var(--text); font-variant-numeric: tabular-nums; }
  /* Para llevarla al súper: en papel sobra todo lo demás. */
  /* --- móvil ------------------------------------------------------------
     La tabla es producto x supermercado: con nueve tiendas no cabe de ninguna
     manera, así que se mantiene el scroll horizontal y **se fija la primera
     columna**. Sin eso, al desplazarte se pierde de vista qué producto es cada
     fila y los precios dejan de significar nada. */
  /* ---------------------------------------------------------------- *
   * La vista de fichas: **una tarjeta por producto, con su cuadrícula de
   * supermercados**, que es lo que sustituye a la tabla en un móvil.
   *
   * Va apagada aquí y se enciende dentro del `@media`, igual que el plegado
   * de los controles: en un ordenador la tabla cabe y comparar veintidós
   * columnas de un vistazo es justo lo que sabe hacer.
   *
   * **Y el apagado va ANTES del `@media`, no después.** Las dos reglas tienen
   * la misma especificidad, así que manda la última que se escriba: puesta
   * debajo, ganaba también en un móvil y las fichas no se veían — se pintaban
   * enteras, con sus precios dentro, y `display` decía `none`. Medido en un
   * iframe de 390 px, que es como se vio.
   * ---------------------------------------------------------------- */
  #fichas { display: none; }

  @media (max-width: 720px) {
    /* Cerrados comparten línea; **abierto ocupa la fila entera**, que es lo que
       necesita su panel para leerse: en móvil no flota, empuja el contenido, y
       a media anchura no se lee. */
    #shops .dd { flex: 0 1 auto; }
    #shops .dd[open] { flex: 1 1 100%; }
    .addrow { gap: 6px; }
    .addrow button, .addrow label.foto { flex: 1 1 auto; }
    /* **Dos líneas y no cuatro, con una sola acción destacada.** Eran tres
       botones a lo ancho —«Añadir», «➕ Añadir de otra forma» y «Buscar
       precios»—, dos de ellos azules y del mismo peso: unos 270 px antes de la
       primera ficha y sin que se viera cuál es el paso principal. Ahora
       «Añadir» es un «＋» pegado al campo, como el «Buscar» de la página de
       búsqueda; «Añadir de otra forma» se lee como lo que es —una opción de
       vez en cuando— y «Buscar precios» es el único botón destacado.

       El campo pide **todo menos el «＋»** (`calc`) y no `flex: 1 1 0`: con
       base cero los cuatro cabrían en la misma línea aplastando el campo. */
    .addrow > #item { flex: 1 1 calc(100% - 50px); min-width: 0; }
    .addrow > button[type=submit] { flex: 0 0 44px; padding: 0; font-size: 22px; }
    .addrow > button[type=submit] .mas { display: inline; }
    .addrow > button[type=submit] .txt { display: none; }
    .addrow > #otrasformas { flex: 1 1 auto; }
    .addrow > #otrasformas > summary {
      border: 0; background: none; padding: 0 4px; color: var(--accent);
      justify-content: flex-start;
    }
    .addrow > #otrasformas[open] { flex: 1 1 100%; }
    .addrow > #run { flex: 0 0 auto; padding: 0 20px; }
    /* Y la misma altura para los dos en esta anchura. Le gana a
       `.dd > summary` por llevar id. */
    .addrow > button, #otrasformas > summary { height: 38px; }
    #otrasformas > summary { font-size: 14.5px; }

    table { font-size: 13px; }
    th, td { padding: 8px 8px; }
    tr.item > td:first-child { min-width: 132px; max-width: 190px; }

    thead th:first-child,
    tr.item > td:first-child,
    tr.total td:first-child,
    /* El hueco del término en la fila de detalle, para que los selectores no
       se metan debajo de la columna fija. */
    .detail-inner > div:first-child {
      position: sticky; left: 0; z-index: 2;
      background: var(--bg); box-shadow: 1px 0 0 var(--line);
    }
    tr.item:hover > td:first-child { background: var(--chip); }
    /* El lápiz no puede depender de pasar el ratón por encima. */
    /* **Y se pueden pulsar con el dedo.** Se ven siempre porque en táctil no
       hay `hover`, pero medidos en un móvil salían **20×16 el lápiz y 15×16 la
       ✕**: se ven y no se aciertan. Van a 24×24, que es el mínimo con el que
       se puede contar, y **solo aquí** — en un ordenador hay puntero y
       agrandarlos sería robarle sitio al nombre del producto, que en esta
       columna es lo que hay que leer. El relleno se queda pequeño y quien da
       el tamaño es el `min-*`, así que el icono no crece: crece su zona. */
    .editterm {
      opacity: 1; min-width: 24px; min-height: 24px;
      display: inline-flex; align-items: center; justify-content: center;
      padding: 2px;
    }

    /* El selector de producto pedía 360 px de ancho mínimo: en un móvil eso es
       más que la pantalla, y `min-width` gana a `max-width`. */
    .prodpick .ddpanel { min-width: 0; width: 560px;
                         max-width: calc(100vw - 20px); }
    .prodpick .ddrow .tx { white-space: normal; }

    #compraacciones { display: flex; flex-wrap: wrap; gap: 6px; }
    .tienda { padding: 12px; }
    .tienda > h3 { font-size: 14px; }
    .tienda .tot { font-size: 16px; }
    /* **En móvil la línea se envuelve y el selector de tienda baja a su propia
       fila.** Entre la casilla, la foto, el nombre, el selector y el precio no
       caben 390 px: el nombre se quedaba en una columna de unos 60 px y
       «Agua mineral grande Aguadoy» salía en cinco renglones. Con el selector
       abajo, el nombre recupera la fila entera. */
    .compralinea { gap: 8px; flex-wrap: wrap; }
    /* **Base cero, no `auto`.** Con `auto` el nombre pide todo su ancho de una
       línea y, como la fila se envuelve (por el selector de tienda de la
       repartida), un nombre largo —«Tomate frito Dia Vegecampo 3 x 390 g»—
       mandaba el precio solo a la línea de abajo, pegado a la izquierda. Con
       base cero el nombre se parte en dos líneas y el precio se queda a la
       derecha, que es donde se busca. */
    .compralinea .nom { font-size: 13px; flex: 1 1 0; }
    .compralinea .prec { flex: 0 0 auto; }
    .compralinea .mover { order: 5; flex: 1 1 100%; max-width: none; }
    .compralinea .coger { width: 24px; height: 24px; }
    .cambiofila .tienda-nm { min-width: 0; }
    .gopcion { flex-wrap: wrap; }
    .gopcion input[type=text] { flex: 1 1 100%; }

    /* --- la cuadrícula de fichas ------------------------------------- */
    #fichas { display: block; }

    /* **El carril lo desplaza el navegador, no nosotros.** `scroll-snap` deja
       cada ficha centrada al soltar, con la inercia y el rebote del sistema.
       La barra se esconde: aquí se arrastra con el dedo. */
    .fichapista {
      display: flex;
      overflow-x: auto; overflow-y: hidden;
      scroll-snap-type: x mandatory;
      -webkit-overflow-scrolling: touch;
      scrollbar-width: none;
      /* **Aquí NO va `touch-action`, y ponerlo fue el primer intento fallido.**
         Se escribió `pan-y` copiando el asa de reordenar tiendas, y dice lo
         contrario de lo que hace falta: `touch-action` declara qué gestos
         atiende **este** elemento, así que `pan-y` le entrega el vertical y le
         quita el horizontal — el dedo pasaba por encima y la ficha no se movía
         (medido con eventos táctiles de verdad: tres arrastres, `scrollLeft`
         en 0 las tres veces). Con el valor por defecto, `auto`, el navegador
         reparte solo: el gesto horizontal lo atiende este carril, que es lo
         único que se desplaza en horizontal, y el vertical se lo queda la
         página. */
    }
    .fichapista::-webkit-scrollbar { display: none; }

    .ficha {
      flex: 0 0 100%; width: 100%; min-width: 0;
      scroll-snap-align: center;
      /* **Un producto por gesto.** Sin esto, un arrastre rápido se salta dos o
         tres fichas —medido con un dedo sintético: de la 1 a la 4 de una vez—
         y lo que se pidió es que apareciera *el siguiente* producto. Es de
         Chrome 75, un pelo por encima del suelo de estas plantillas (74); se
         usa a sabiendas, como el `gap` de flexbox, porque **lo que se pierde
         donde no exista es que un impulso fuerte pase de largo**, no la
         función: el carril se desplaza y se ancla igual. */
      scroll-snap-stop: always;
      box-sizing: border-box; padding: 0 1px 2px;
    }

    .fichatit { display: flex; align-items: baseline; gap: 6px; padding: 2px 2px 8px; }
    .fichatit .nm {
      flex: 1 1 auto; min-width: 0;
      font-size: 17px; font-weight: 700; line-height: 1.25;
      overflow-wrap: anywhere;
    }
    .ficha.sinnada .fichatit .nm { color: var(--err); }
    .fichatit .pista { flex: 1 1 100%; }

    /* La cuadrícula: **se envuelve hacia abajo**, que es lo pedido. A 390 px
       salen tres columnas; en una pantalla más ancha, las que quepan. */
    .fichared {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
      gap: 6px;
    }

    .fichacell {
      display: flex; flex-direction: column; gap: 2px;
      border: 1px solid var(--line); border-radius: 10px;
      padding: 6px 6px 7px; background: var(--card);
      min-height: 86px; cursor: pointer;
      overflow: hidden;
    }
    .fichacell .fichashop {
      font-size: 11px; color: var(--muted); font-weight: 600;
      white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    }
    /* Dentro del cuadradito el precio va debajo de la foto y a la izquierda:
       la celda de la tabla lo alinea a la derecha porque allí es una columna
       numérica, y aquí no hay columna con la que alinearse. */
    .fichacell .cellbox { justify-content: flex-start; gap: 6px; }
    .fichacell .cellnums { align-items: flex-start; }
    .fichacell.cheapest { border-color: var(--best); }
    .fichacell.na { color: var(--muted); justify-content: flex-start; }
    .fichacell.failed { border-color: var(--err); }
    .fichacell .fichavacia { font-size: 15px; }

    /* El selector ocupa el cuadradito entero cuando se abre. */
    .fichacell .prodpick { width: 100%; }
    .fichacell .prodpick > summary { padding: 2px 0; border: 0; background: none;
                                     min-height: 0; }
    .fichacell .prodpick .lbl { white-space: normal; }

    .fichanav {
      display: flex; align-items: center; justify-content: center; gap: 10px;
      padding: 8px 0 2px;
    }
    .fichaflecha {
      width: 40px; height: 34px; padding: 0; font-size: 19px; line-height: 1;
      background: var(--chip); color: var(--text); border: 1px solid var(--line);
      border-radius: 8px;
    }
    .fichaflecha[disabled] { opacity: .35; }
    /* El rótulo **es** el botón de «ir a»: mismo sitio, mismo tamaño, con su ▾
       para que se vea que se abre. */
    .fichapos { font-size: 12.5px; color: var(--muted); min-width: 92px;
                justify-content: center; }
    /* **Cerrado mide lo que mide, que es lo que lo deja en el centro.**
       `base.html` da `flex: 1 1 100%` a todo `.dd` en móvil —una regla de la
       fila de los supermercados, donde el desplegable ocupa el renglón para
       que su panel se lea— y aquí eso empujaba el rótulo al borde izquierdo y
       la flecha «›» al derecho. Medido en 390 px: el `<details>` salía de
       283 px para un rótulo de 92.

       **Abierto sí ocupa la fila**, porque el panel empuja en vez de flotar y
       a 92 px no se leería; es el mismo par que ya usa `#shops .dd[open]`. Y
       entonces el `<summary>` se estira para que el rótulo no salte a la
       izquierda al pulsarlo — es `inline-flex`, así que sin el `width: 100%`
       llenaría el `<details>` y no lo que hay dentro, la misma pelea que
       «➕ Añadir de otra forma». */
    #fichair { position: static; flex: 0 0 auto; }
    #fichair[open] { flex: 1 1 100%; }
    #fichair[open] > .fichapos { width: 100%; box-sizing: border-box; }
    /* Era texto suelto: sin algo que lo diga, nadie lo pulsa. */
    #fichapos::after { content: " ▾"; color: var(--muted); }
    /* El panel empuja, no flota: es lo que ya hacen todos los desplegables en
       esta anchura, y aquí además va pegado al borde inferior de la ficha. */
    #fichalista {
      max-height: 52vh; left: 0; right: 0; width: auto; min-width: 0;
    }
    #fichalista .ddrow .meta { margin-left: auto; font-size: 11.5px;
                               color: var(--muted); }
    #fichalista .ddrow.sel { background: var(--chip); font-weight: 700; }
    .fichabuscar {
      width: 100%; box-sizing: border-box; margin: 2px 0 6px;
      padding: 9px 11px; font-size: 15px;
      border: 1px solid var(--line); border-radius: 8px;
      background: var(--bg); color: var(--text);
    }
    #fichalista .ddvacio { padding: 8px; color: var(--muted); font-size: 12.5px; }

    /* La ficha de los totales, que es la última del carril. */
    .fichacell.fichatot { cursor: default; }
    .fichacell.fichatot b { font-size: 15px; }
  }

  @media (max-width: 400px) {
    .thumb { width: 30px; height: 30px; }
    tr.item > td:first-child { min-width: 118px; font-size: 12.5px; }
    .cellnums .delta { display: none; }   /* no cabe; sigue en la vista de compra */
  }

  /* Encabezado que solo existe en papel: al imprimir varias listas hay que
     saber cuál es cada una. No lleva `hidden`, que `[hidden]` es `!important` y
     ganaría también en la hoja de impresión. */
  #cabecerapapel { display: none; }

  /* **La hoja de impresión de la lista, y lleva marca a propósito.** En esta
     página hay ya **tres** `@media print`: este, el de `base.html` —que
     esconde el aviso de lo que se guarda— y el de la lista que se descarga en
     HTML, que viaja dentro de una cadena de JavaScript. Partir por el primero
     o por el último no vale, y ha fallado las dos veces; los tests parten por
     esta marca, que no depende de cuántos haya. */
  @media print { /* hoja de la lista */
    /* `#totaltabla` iba **dentro** de `.scroller`, así que se ocultaba con
       ella sin nombrarlo. Fuera, hay que decirlo. */
    header, #shops, form, #progress, #avisos, .scroller, #totaltabla, .pie,
    #empty, #revision, #guardarpanel, #dictado, #compraacciones, #modos,
    /* El menú de secciones **y su fondo**: si el menú quedó abierto al
       imprimir, ese velo oscuro se lleva la hoja entera. */
    #menu, #menufondo, #menubtn { display: none !important; }
    /* El selector de tienda de cada línea no se pulsa en papel. */
    .compralinea .mover { display: none !important; }
    /* `.thumb` a secas no basta: el hueco "sin foto" es `.thumb.vacia`, dos
       clases, y ganaba por especificidad. */
    .thumb, .thumb.vacia { display: none !important; }

    #lupa { display: none !important; }
    #totalfinal { break-inside: avoid; border-color: #000; }
    #cabecerapapel { display: block; margin-bottom: 12px; }
    #cabecerapapel b { font-size: 17px; }
    #cabecerapapel span { color: #444; font-size: 12px; }

    /* Una lista de la compra en papel se usa con un boli: sin casilla que
       tachar, hay que ir buscando por dónde ibas. No la llevan las líneas que
       no se compran ("no lo tiene", "sin consultar").

       **Es la casilla de verdad, dibujada como una caja**, y ya no un
       `::before`. Desde que se puede ir tachando en la propia página hay un
       `<input>` en cada línea, y el pseudoelemento pintaba una segunda casilla
       al lado. Lo que sí se deshace al imprimir es el tachado: en papel se
       tacha con el boli, y una línea ya tachada no se puede volver a usar. */
    .compralinea .coger {
      -webkit-appearance: none; appearance: none;
      width: 11px; height: 11px; border: 1px solid #444; border-radius: 2px;
      margin-right: 4px;
    }
    .compralinea.cogido .nom, .compralinea.cogido .prec {
      text-decoration: none; color: inherit;
    }
    .compralinea.cogido .thumb { opacity: 1; }
    #cogidos { display: none !important; }
    /* El aviso de precios viejos **no** se oculta: llevar al súper precios de
       otro día sin decirlo sería peor que no llevar nada. */
    #avisoviejo { border: 1px solid #999; color: #000; }
    #compra { display: block; }
    .tienda { break-inside: avoid; border-color: #999; margin-bottom: 12px; }
    .thumb { display: none; }
  }
  #listaactual { font-size: 12.5px; color: var(--muted); }
  #listaactual b { color: var(--text); }
  /* Sin guardar no es un error —una lista de cinco cosas para el súper de hoy
     no tiene por qué guardarse—, así que va en el ámbar de los avisos y no en
     el rojo. */
  #listaactual.singuardar { color: var(--aviso); }
  .listarow { display: flex; align-items: center; gap: 8px; }
  .listarow .nm { flex: 1; cursor: pointer; }
  .listarow .meta { font-size: 11px; color: var(--muted); }
  .listarow .del {
    background: none; border: 0; color: var(--muted); cursor: pointer;
    font-size: 15px; padding: 2px 6px; border-radius: 50%;
  }
  .listarow .del:hover { color: var(--err); background: var(--bg); }
  .ddvacio { padding: 8px 10px; color: var(--muted); font-size: 12.5px; }
  /* Producto guardado que ya no aparece en los resultados de su tienda. */
  .cell.ido { color: var(--err); }
  .ido-marca {
    display: block; font-size: 10px; font-weight: 700; color: var(--err);
  }

/* El 📊 de una línea es un enlace: sin subrayado, como sus botones vecinos. */
.editterm.guardado { text-decoration: none; }
