@import url('tipos/archivo.css');

/* ==========================================================================================
   El sistema visual de la plataforma.

   Hasta ahora cada pantalla traía su propio <style> con sus tarjetas, sus chips y sus tablas:
   veintidós plantillas definiendo lo mismo de veintidós maneras. Eso no se nota mientras hay
   siete pantallas y se nota muchísimo cuando hay setenta, que es a donde vamos.

   Cómo está montado, y por qué:

   1. TOKENS. Todo lo visual sale de una variable. Cambiar el aire de la aplicación entera es
      cambiar cuatro números aquí, no repasar setenta archivos.
   2. El color de MARCA no está aquí: lo pone cada empresa y lo inyecta la plantilla base
      (`marca.tokens_css`), ya con el contraste calculado en nucleo/color.py.
   3. COMPONENTES con nombre en castellano, como el resto del código: `.tarjeta`, `.chip`,
      `.btn`, `.tabla`, `.vacio`. Una pantalla nueva se escribe combinándolos y no necesita
      CSS propio; si lo necesita, es que falta un componente aquí.
   4. Se lee de día en un taller y de noche en una oficina: hay modo oscuro, y no es un
      invento de la pantalla, es el mismo sistema con otros valores de los mismos tokens.
   ========================================================================================== */

:root {
  /* --- Tinta y superficies ------------------------------------------------------------- */
  /* El papel tiene cuerpo a propósito: con un fondo casi blanco, las tarjetas blancas, la
     franja blanca y el lateral blanco se fundían en una sola sábana y la pantalla se veía
     «demasiado clara», sin relieve. Un papel un punto más tostado y unas líneas que se ven
     devuelven la estructura sin oscurecer nada. Cifras medidas: el texto principal queda en
     13,6 sobre el papel y 16,7 sobre las tarjetas; el secundario, en 5,4 y 6,6. */
  --ink:        #151719;   /* texto principal */
  --ink2:       #4d5258;   /* texto secundario: 7,2 sobre el papel, se lee de verdad */
  /* Apagado, pero legible: lo llevan el «/» del buscador, la etiqueta «Ver» de los filtros
     y los textos de «no hay nada». Estaba en #70747b, que sobre el rayado de las tablas se
     quedaba en 4,27 —por debajo del 4,5 que este sistema promete—. Ahora: 5,5 sobre las
     tarjetas, 5,0 sobre el rayado y 4,5 sobre el papel. Sigue siendo el gris más flojo. */
  /* El gris más flojo. La referencia lo ponía en #858b93, que sobre el papel se queda
     en 3,4 y rompe el 4,5 que esta hoja promete por escrito. Este es el más claro de
     ese mismo tono que cumple: 4,59 sobre el papel, 4,76 sobre el rayado y 5,14 sobre
     las tarjetas. Con #6b7076 se quedaba en 4,46 y el guardián lo cazó por 0,04. */
  --ink3:       #696e74;
  --fondo:      #f3f2ef;   /* el papel: gris muy claro, sin el tostado de antes */
  --panel:      #ffffff;   /* las tarjetas encima del papel */
  --panel-2:    #f7f6f3;   /* rayado de tabla, cabeceras */
  --linea:      #dad8d3;
  --linea-2:    #b9b6ae;   /* separaciones que sí tienen que verse */

  /* --- El lateral. Va con el tema: claro de día, oscuro de noche -----------------------
     Fue oscuro también de día, para separar de un golpe «dónde estoy» de «lo que miro».
     Pero era el único trozo de la pantalla que no obedecía al interruptor, y el logo de cada
     empresa —hecho para papel blanco— se veía encima como una pegatina. De día es un gris
     cálido muy claro, distinto del blanco de la franja y de las tarjetas para que se lea
     como columna; de noche, un gris azulado (abajo). El «dónde estoy» lo sigue diciendo el
     bloque del color de la empresa en la sección puesta. */
  --lateral:        #1f2226;
  --lateral-2:      #2a2e33;   /* lo que se posa encima: la fila con el ratón */
  --lateral-txt:    #e9e7e2;
  --lateral-txt-2:  #9ea3aa;   /* lo secundario: 5,6 sobre el rail, se lee de verdad */
  --lateral-linea:  #343940;

  /* --- Estado. Cuatro y no más: cada uno significa una cosa y no se reutilizan.
       Los modificadores se llaman `es-ok`, `es-aviso`… y no `ok`, `aviso`: `.aviso` ya es el
       cartel de los mensajes, y un elemento con las dos clases se llevaba los dos aspectos. */
  /* El acento de la interfaz: naranja, y NO el color de la empresa. Son dos cosas
     distintas y antes eran una sola. El color del taller sigue mandando en lo suyo
     —el logo, el membrete de los documentos, lo que ve un cliente suyo— y la
     herramienta se queda en negro y naranja, que no compite con ninguna marca y se
     lee igual de bien en un taller rojo que en uno azul.
     `--acento-txt` es blanco: 4,7 sobre el naranja, medido. */
  --acento:     #d0620f;  --acento-suave:  #fbeadb;  --acento-txt: #ffffff;
  /* El mismo naranja tiene dos papeles y no puede ser el mismo tono en los dos. Como
     MANCHA —la raya de 3 px de la sección puesta, el relleno de un botón— #d0620f está
     bien. Como LETRA se queda en 3,45 sobre el papel: por debajo del 4,5 que esta hoja
     promete. Este es el mismo naranja oscurecido hasta cumplir: 5,12 sobre el papel y
     5,74 sobre las tarjetas. */
  --acento-legible: #a64c0c;

  --ok:         #2d7a4f;  --ok-suave:      #e6f2ea;
  --aviso:      #8a5a12;  --aviso-suave:   #fbf1e0;
  --grave:      #b2231b;  --grave-suave:   #fae4e1;
  --info:       #23557f;  --info-suave:    #e6eef6;

  /* --- Espacio. Escala de 4: dos elementos separados «un poco» lo están siempre igual --- */
  --e1: 4px;  --e2: 6px;  --e3: 8px;  --e4: 12px;
  --e5: 16px; --e6: 24px; --e7: 32px; --e8: 48px;

  /* --- Formas --------------------------------------------------------------------------- */
  --r:    10px;   /* la tarjeta */
  --r-s:  7px;    /* el control */
  --r-xs: 5px;
  --sombra:   0 1px 2px rgba(28, 30, 34, .06);
  --sombra-2: 0 4px 16px rgba(28, 30, 34, .10);

  /* --- Letra ---------------------------------------------------------------------------- */
  /* Archivo al 87,5 % de ancho: condensada sin llegar a estrecharse, con cifras de
     ancho fijo y una negrita que aguanta un titular de 40 px. Va AUTOALOJADA
     (`tipos/archivo.css`): esta aplicación promete no hablar con nadie y no puede
     pedirle la letra a Google cada vez que alguien abre una pantalla. */
  --tipo: "Archivo", system-ui, "Segoe UI", Roboto, sans-serif;
  --mono: ui-monospace, "Cascadia Mono", "Consolas", monospace;
  --t-xs: .72rem; --t-s: .8rem; --t-m: .88rem; --t-b: 1rem;
  --t-g: 1.15rem; --t-xg: 1.45rem; --t-xxg: 1.9rem;

  --transicion: .14s ease;
  color-scheme: light;
}

/* El mismo sistema, de noche. Se cambian los tokens, no los componentes.

   Va SOLO cuando alguien lo pide (`data-tema="oscuro"`), no cuando lo pide el sistema
   operativo. Un taller que abre la aplicación y se la encuentra en negro sin haber tocado
   nada cree que se ha roto algo, y con un cliente delante eso no se explica. Se enciende
   desde el pie del menú y se recuerda en ese navegador. */
:root[data-tema="oscuro"] {
    /* Los valores están medidos, no elegidos a ojo: el texto principal queda en 12,0 sobre
       el panel y el secundario en 7,4 —de día, sobre el papel, son 13,6 y 5,4—, así que de
       noche se lee igual de bien. No es negro: un fondo casi negro con tarjetas casi negras
       se veía «demasiado oscuro» y sin relieve; es un gris antracita con las tarjetas un
       punto más claras y las líneas visibles, que es lo que hace que se distingan. */
    /* --ink3 de noche: estaba en #9d9890, que sobre el rayado de tabla (--panel-2) daba
       4,05. Ahora 4,7 ahí, 5,6 sobre el panel y 6,6 sobre el fondo. */
    --ink: #f2f0ec; --ink2: #c2beb6; --ink3: #aaa59e;
    --fondo: #1f2124; --panel: #2b2e33; --panel-2: #353940;
    --linea: #474c54; --linea-2: #5f656e;
    --ok: #86d6ac;  --ok-suave: #22452f;
    --aviso: #eec27f; --aviso-suave: #45361a;
    --grave: #f0a9a3; --grave-suave: #47282a;
    --info: #9cc4ea;  --info-suave: #1f3650;
    --sombra: 0 1px 2px rgba(0, 0, 0, .4);
    --sombra-2: 0 4px 16px rgba(0, 0, 0, .5);
    /* El lateral de noche: 11,7 de contraste el texto principal, 5,5 el secundario. */
    --lateral: #272b31; --lateral-2: #323740;
    --lateral-txt: #e7e9ec; --lateral-txt-2: #9aa1ac; --lateral-linea: #3d434c;
    /* El color de la empresa, aclarado: el rojo o el azul marino corporativos no se leen
       sobre un panel casi negro. Lo calcula nucleo/color.py y lo inyecta la plantilla. */
    --marca-legible: var(--marca-legible-oscuro, #d9d6d0);
    /* El acento, de noche. La mancha se queda igual —sobre un fondo oscuro un naranja
       fuerte se ve mejor, no peor— y la letra se ACLARA en vez de oscurecerse: 6,36 sobre
       el fondo y 5,37 sobre las tarjetas. Con el de día se quedaba en 3,53 sobre las
       tarjetas. */
    --acento-suave: #3a2415;
    --acento-legible: #ec8a3f;
    color-scheme: dark;
  }


/* ---------- Base ------------------------------------------------------------------------ */
* { box-sizing: border-box; margin: 0; }

body {
  font-family: var(--tipo);
  font-size: var(--t-b);
  line-height: 1.5;
  background: var(--fondo);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
}

/* Foco visible SIEMPRE. Media plantilla usa el teclado con guantes de trabajo puestos, y un
   foco invisible es una pantalla que no se puede usar sin ratón.

   Con `--marca-legible` y NO con `--marca-accion`, que es lo que había. `--marca-accion` se
   calcula para que el TEXTO DE ENCIMA se lea —es el fondo de un botón—, y eso no dice nada
   de cómo se ve el propio color sobre la página. Medido con seis marcas plausibles, las seis
   dejaban el anillo por debajo del 3:1 que pide la norma para algo que no es texto, y de
   forma sistemática: las marcas oscuras desaparecían en tema oscuro y las claras en tema
   claro. El rojo de GSN se quedaba en 2,76 de noche. O sea que la mitad del tiempo, quien
   navega con el teclado no veía dónde estaba.

   `--marca-legible` ya se voltea con el tema (más abajo, en el bloque oscuro) porque se
   calcula contra el peor fondo de cada uno. Con las mismas seis marcas: ninguna baja de
   4,96, y sigue siendo el color del cliente. */
:focus-visible {
  outline: 2px solid var(--marca-legible, var(--ink));
  outline-offset: 2px;
  border-radius: var(--r-xs);
}

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

a { color: var(--marca-legible, var(--info)); }
h1 { font-size: var(--t-xg); line-height: 1.25; letter-spacing: -.01em; }
h2 { font-size: var(--t-g); line-height: 1.3; }
h3 { font-size: var(--t-b); line-height: 1.35; }
code, kbd, .mono { font-family: var(--mono); font-size: .92em; }

/* ---------- Estructura de página --------------------------------------------------------- */
.sub { color: var(--ink2); margin-bottom: var(--e6); max-width: 74ch; }
.pie { color: var(--ink2); font-size: var(--t-s); margin-top: var(--e6); max-width: 80ch; }

/* Cabecera de pantalla: título a la izquierda, acciones a la derecha, y en el móvil una
   debajo de otra sin que haya que pensarlo. */
.cabecera { display: flex; align-items: flex-start; gap: var(--e5); flex-wrap: wrap;
            margin-bottom: var(--e2); }
.cabecera .acciones { margin-left: auto; display: flex; gap: var(--e3); flex-wrap: wrap; }

/* ---------- Tarjeta ---------------------------------------------------------------------- */
.tarjeta {
  background: var(--panel);
  border: 1px solid var(--linea);
  border-radius: var(--r);
  padding: var(--e5) var(--e6);
  margin-bottom: var(--e5);
  box-shadow: var(--sombra);
}
.tarjeta > h3:first-child, .tarjeta > h2:first-child { margin-bottom: var(--e1); }
.tarjeta .sub { margin-bottom: var(--e4); }
.tarjeta.apagada { background: var(--panel-2); }
/* La tarjeta de fichar, teñida entera: verde si estás dentro, rojo si estás fuera. El estado
   se dice con palabras Y con color, que se lea desde lejos sin leer. La comparten «Mi
   jornada» y el perfil de la tablet: es la misma pantalla en dos marcos. */
.tarjeta.jornada-dentro { border-color: var(--ok); background: var(--ok-suave); }
.tarjeta.jornada-fuera { border-color: var(--grave); background: var(--grave-suave); }
/* Mi jornada (27/09/2026): el botón de fichar solo y, debajo, dónde se ficha. En el teléfono,
   a lo ancho: se pulsa de pie y con el pulgar. */
.tarjeta .fichar-aqui { margin-top: var(--e4); }
.tarjeta .donde-fichar { margin-top: var(--e4); }
@media (max-width: 780px) { .tarjeta .fichar-aqui .btn.grande { width: 100%; } }

/* ---------- Rejilla de métricas ---------------------------------------------------------- */
/* Los números que se miran de un vistazo al entrar. Auto-fit: caben los que quepan y no hay
   que decidir columnas por pantalla. */
/* Las cifras de cabecera, en UNA tarjeta con separadores y no en tres tarjetas sueltas.
   Sueltas se leían como tres cosas distintas; juntas se leen como lo que son: las tres caras
   del mismo número. Además ocupan menos alto, que en una pantalla con tabla debajo importa. */
/* Rejilla con un hueco de 1 px sobre el color de la línea: las separaciones salen solas y
   quedan bien pase lo que pase al reajustarse —tres arriba y dos abajo, o seis en fila—. Con
   bordes por elemento había que adivinar cuál es el último de cada fila, que es una cuenta
   que el navegador ya sabe hacer y nosotros no. */
.metricas { display: grid; gap: 1px; margin-bottom: var(--e5);
            grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
            background: var(--linea); border: 1px solid var(--linea);
            border-radius: var(--r); box-shadow: var(--sombra); overflow: hidden; }
.metrica { padding: var(--e4) var(--e5); background: var(--panel); }
.metrica .q { display: block; font-size: var(--t-xs); text-transform: uppercase;
              letter-spacing: .06em; color: var(--ink2); }
/* La cifra se encoge si es larga en vez de partirse: «19.128,89 €» en dos renglones no
   es una cifra, es un jeroglífico. */
.metrica .v { display: block; font-weight: 700; line-height: 1.15; margin-top: var(--e1);
              font-variant-numeric: tabular-nums;
              font-size: clamp(1.25rem, .9rem + 1.1vw, 1.9rem); }
/* Una cifra no se parte, pero una FRASE sí: «Dentro desde las 16:34» no es un número y
   con `nowrap` se salía de su celda y se cortaba en «Dentro desde las 16:». Se envuelve
   solo lo que lleva espacios; lo que no los lleva —«19.128,89 €»— sigue en un renglón
   porque no tiene por dónde partirse. */
.metrica .v { white-space: normal; overflow-wrap: break-word; }
.metrica .q { min-height: 2.2em; }
.metrica .n { display: block; font-size: var(--t-s); color: var(--ink2); }
.metrica.es-ok .v    { color: var(--ok); }
.metrica.es-aviso .v { color: var(--aviso); }
.metrica.es-grave .v { color: var(--grave); }
/* El color va en la CIFRA, no en el fondo del cuadro. Cuatro cuadros teñidos seguidos son un
   muro de color donde ya no destaca nada; con la cifra en su color y el cuadro en blanco, lo
   que está mal se sigue viendo desde la puerta y la pantalla respira.
   El único que conserva el fondo es lo grave, que es donde el bloque de color hace lo que
   promete: que no se pueda pasar por alto. */
.metrica.es-grave { background: var(--grave-suave); }
/* Una métrica sola no se estira a lo ancho de la pantalla: una cifra de dos dígitos en un
   cuadro de 1.100 px parece un error de maquetación, no un dato. */
/* Una métrica sola no se estira a lo ancho de la pantalla: una cifra de dos dígitos en un
   cuadro de 1.100 px parece un error de maquetación, no un dato. */
.metricas:has(> .metrica:only-child) { max-width: 340px; }

/* ---------- Tabla ------------------------------------------------------------------------ */
table { width: 100%; border-collapse: collapse; }
/* Sin mayúsculas desde el 27/09/2026: las mayúsculas espaciadas quedan solo para el
   antetítulo. Repetidas en cada cabecera de columna, cada unidad y cada epígrafe, eran lo que
   más pesaba de la pantalla sin decir nada. */
th { text-align: left; font-size: var(--t-s); color: var(--ink3); font-weight: 600;
     padding: var(--e2) var(--e3); }
td { padding: var(--e3); border-top: 1px solid var(--linea); vertical-align: top; }
tbody tr:hover td { background: var(--panel-2); }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Una fila que lleva a un sitio (`data-href`, ver filas.js): la mano al pasar y un rayado al
   posarse, para que se vea que toda ella es la puerta y no solo el nombre. */
tr[data-href] { cursor: pointer; }
tr[data-href]:hover > td { background: var(--panel-2); }
/* Un dato que se copia —el NIF, el IBAN— es él mismo el botón: se pulsa el valor y ya está,
   con el icono de copiar detrás como en cualquier programa, sin borde ni rótulo (Daniel,
   15/09/2026). Al copiarlo el icono se vuelve un visto verde un momento. */
.copiable { display: inline-flex; align-items: center; gap: 6px; padding: 0; border: 0;
            background: none; font: inherit; color: inherit; cursor: pointer;
            border-radius: var(--r-xs); }
.copiable:hover { color: var(--marca-legible); }
.copiable:focus-visible { outline: 2px solid var(--marca-borde); outline-offset: 2px; }
.copiable svg { width: 14px; height: 14px; fill: none; stroke: currentColor; stroke-width: 1.8;
                stroke-linecap: round; stroke-linejoin: round; color: var(--ink3); }
.copiable:hover svg { color: var(--marca-legible); }
.copiable .hecho { display: none; }
.copiable.copiado .hecho { display: block; color: var(--ok); }
.copiable.copiado .copia { display: none; }

/* El test del sistema en caliente: la barra de progreso bajo el titular y el estado de cada
   fila mientras se mira (pendiente, apagada; mirando, con su rayado; rota, en rojo). */
.medidor-test { height: 6px; border-radius: 3px; background: var(--linea-2); overflow: hidden;
                margin: var(--e3) 0 var(--e5); max-width: 480px; }
.medidor-test > i { display: block; height: 100%; background: var(--ok); border-radius: 3px;
                    transition: width .3s ease; }
tr.pendiente > td { color: var(--ink3); }
tr.mirando > td { background: var(--panel-2); }
tr.rota > td { background: var(--grave-suave); }
/* Una fecha nunca se parte: «29/08/202 / 6» en dos líneas no es una fecha. */
/* Un número de factura, un código de orden, una fecha o un importe son UNA unidad: no se
   parten en dos renglones. «2026-⏎1585» y «25/08/20⏎26» no son texto envuelto, son un dato
   roto, y encima cuesta más leerlo que si la columna fuera un poco más ancha. El texto de
   verdad —conceptos, nombres, notas— sí envuelve, que para eso es texto. */
.fecha, .num, .dato { white-space: nowrap; }
/* Las acciones de una fila van seguidas, no una debajo de otra: cada formulario es un bloque
   y, sin esto, dos botones de la misma fila salían en dos renglones. */
td.acciones { text-align: right; white-space: nowrap; width: 1%; }
td.acciones > form, td.acciones > a, td.acciones > button { display: inline-flex;
                                                            vertical-align: middle;
                                                            margin-left: var(--e1); }
/* El texto envuelve: una tabla no puede obligar a arrastrar la pantalla a los lados. */
/* El texto envuelve, pero por los espacios: `anywhere` partía «Construcciones» en
   «Construccio / nes», que es más difícil de leer que una columna un poco más ancha. Solo se
   parte una palabra cuando de verdad no cabe entera (una referencia larga, un correo). */
td, th { overflow-wrap: break-word; }
/* La tabla apretada: una línea por fila, para leer un libro entero de un vistazo —las facturas
   de «Todas» en tabla—. Las cifras y las fechas no envuelven y el nombre sí, pero con un mínimo;
   si no cabe, se desplaza la tabla dentro de `.tabla-ancha`, nunca la pantalla. La fila de
   subtotal separa los meses con un filete del color del texto, como la línea de suma de una
   hoja de cálculo. */
table.apretada td, table.apretada th { padding: var(--e1) var(--e2); }
table.apretada td { white-space: nowrap; }
table.apretada td.texto { white-space: normal; min-width: 14ch; }
table.apretada tr.subtotal th, table.apretada tr.subtotal td {
  padding-top: var(--e4); border-top: 2px solid var(--ink); font-weight: 700;
  text-transform: none; letter-spacing: 0; font-size: var(--t-s); color: var(--ink); }

/* ---------- Ficha de lista ---------------------------------------------------------------- */
/* Un elemento de una lista que pide una acción: la corrección que hay que aprobar, el
   presupuesto que espera respuesta. No es una fila de tabla porque lleva texto largo dentro
   —el motivo que escribió una persona— y una tabla con párrafos se lee fatal. */
.item { border: 1px solid var(--linea); border-radius: var(--r-s); background: var(--panel);
        padding: var(--e4) var(--e5); margin-bottom: var(--e3);
        display: flex; gap: var(--e5); flex-wrap: wrap; align-items: flex-start; }
.item .cuerpo { flex: 1 1 320px; min-width: 0; }
.item .acciones { display: flex; gap: var(--e2); flex-wrap: wrap; align-items: center; }
.item .meta { color: var(--ink2); font-size: var(--t-s); margin-top: var(--e1); }
.item.es-aviso { border-left: 3px solid var(--aviso); }
/* Lo que ya no está en marcha: se ve, pero no compite con lo vivo. */
.item.apagada { background: var(--panel-2); border-style: dashed; }
.item.apagada .cuerpo { color: var(--ink2); }

/* Lo que ha escrito una persona, citado tal cual. Se distingue de lo que dice el sistema. */
.cita { border-left: 3px solid var(--linea-2); padding-left: var(--e3); margin-top: var(--e2);
        color: var(--ink); }

/* ---------- Tabla de datos (clave / valor) ------------------------------------------------ */
/* Para una ficha: a la izquierda cómo se llama el dato, a la derecha lo que vale. No es una
   tabla de filas comparables, así que no lleva cabecera ni rayado. */
.datos td { vertical-align: top; }
.datos td:first-child { width: 230px; color: var(--ink2); }
.datos tbody tr:hover td { background: none; }
/* La misma pareja clave/valor sin tabla, para las fichas de cuatro campos: ahí una tabla es
   andamiaje de más. Lo usaban ya dos módulos **sin que existiera la regla**, así que la
   etiqueta y el valor salían pegados: «Anotada por—». Un nombre de clase que se usa y no
   está definido es peor que uno que no existe, porque parece que funciona. */
.datos:not(table) { display: grid; gap: var(--e3); }
.datos:not(table) > div { display: grid; grid-template-columns: 200px minmax(0, 1fr);
                          gap: var(--e4); align-items: baseline; }
/* La etiqueta parte por donde sea si hace falta. Su columna mide 200 px y hay rótulos que
   son una sola palabra larguísima sin sitio por donde cortar —«FECHAHORAHUSOGENREGISTRO», que
   es como se llama de verdad un campo de VeriFactu—: sin esto la palabra se salía de su
   columna y se montaba encima del valor. */
.datos:not(table) .et { color: var(--ink2); overflow-wrap: anywhere; }
@media (max-width: 620px) {
  .datos:not(table) > div { grid-template-columns: 1fr; gap: 0; }
}
.rompe { word-break: break-all; }

/* ---------- Chips ------------------------------------------------------------------------ */
.chip {
  display: inline-flex; align-items: center; gap: var(--e1);
  font-size: var(--t-xs); font-weight: 700; letter-spacing: .03em;
  border-radius: 999px; padding: 3px 10px; white-space: nowrap;
  background: var(--panel-2); color: var(--ink2); border: 1px solid var(--linea);
}
.chip.es-ok    { background: var(--ok-suave);    color: var(--ok);    border-color: transparent; }
.chip.es-aviso { background: var(--aviso-suave); color: var(--aviso); border-color: transparent; }
.chip.es-grave { background: var(--grave-suave); color: var(--grave); border-color: transparent; }
.chip.es-info  { background: var(--info-suave);  color: var(--info);  border-color: transparent; }
.chip.es-marca { background: var(--marca-suave); color: var(--marca-legible);
                 border-color: var(--marca-borde); }
.chip.es-plan  { border-style: dashed; }
.chips { display: flex; flex-wrap: wrap; gap: var(--e2); }
/* El tipo de una factura (`facturacion/_tipo.html`): «Certificación a origen» o «Rectificativa
   de F2026-034» no caben en la columna de quién a 390 px, y una chapa que no parte se montaba
   encima del concepto. Esta parte por sus palabras, como el texto que la rodea (28/09/2026). */
.chip.tipo-de-factura { white-space: normal; max-width: 100%; }

/* ---------- Botones ---------------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--e2);
  padding: 10px 18px; border-radius: var(--r-s);
  /* La acción principal es NEGRA, no del color de la empresa.

     Fue del color del cliente, con la idea de que la herramienta se sintiera suya. El
     problema es que la paleta de estado de esta casa ya tiene el color ocupado: `--grave`
     —rojo— significa «dinero parado» y «baja», y `--ok` —verde— significa «cuadra». Un
     cliente de marca roja acaba con el botón de «Anotar una solicitud» pintado del mismo
     tono que la alarma de una factura vencida, y uno de marca verde con el botón de borrar
     diciendo que todo va bien. Es exactamente lo que pasaba en GSN.

     La marca no se pierde: sigue en el logo del lateral, en el membrete de cada documento
     —que es lo que ve un cliente suyo— y en la sección puesta. La HERRAMIENTA se queda en
     negro y naranja, que es lo que ya decía el token `--acento` y el botón no cumplía. */
  border: 1px solid var(--ink);
  background: var(--ink); color: var(--panel);
  font: inherit; font-size: var(--t-m); font-weight: 600; text-decoration: none;
  cursor: pointer; transition: background var(--transicion), border-color var(--transicion);
  /* 40 px de alto mínimo: se toca con el dedo y con guantes. */
  min-height: 40px;
  /* El texto de una tabla envuelve; el de un botón, no. «Ver» partido en «Ve / r» en la
     última columna de una tabla estrecha no es una línea más: es una palabra rota. Un
     rótulo de botón es corto por definición, así que cabe entero o la columna se ensancha. */
  white-space: nowrap;
}
/* Al posarse, un punto más de tinta. No cambia de color: un botón que cambia de tono al
   pasar por encima parece que ya ha hecho algo. */
.btn:hover { background: var(--ink); filter: brightness(1.35); }
.btn:disabled, .btn[aria-disabled="true"] { opacity: .5; cursor: not-allowed; }
.btn.segundo { background: var(--panel); color: var(--ink); border-color: var(--linea-2); }
.btn.segundo:hover { background: var(--panel-2); border-color: var(--ink3); }
/* Lo que no tiene vuelta atrás: anular una orden, rechazar una factura, anular un registro.
   Va en CONTORNO con la palabra en rojo, no en rojo relleno.

   El rojo relleno estaba prohibido por escrito y con razón: en esta casa `--grave` significa
   «dinero parado» y «baja», así que un botón rojo entre dos negros no avisa de nada —solo
   grita— y además se confunde con una alarma. Y lo que de verdad protege de un clic sin
   vuelta no es el color: es que la acción PIDA MOTIVO y se pueda deshacer, que es lo que ya
   hacen todas. El color queda para decir de qué clase es la acción, que es lo que un color
   sabe hacer. */
.btn.peligro { background: var(--panel); color: var(--grave); border-color: var(--grave); }
.btn.peligro:hover { background: var(--grave-suave); color: var(--grave); filter: none; }
/* De noche `--grave` es un rosa claro: como LETRA sobre el panel oscuro se lee bien, que
   es justo lo que ahora es. Antes era el fondo y había que oscurecer el texto encima. */
.btn.suelto { background: transparent; color: var(--marca-legible, var(--info));
              border-color: transparent; padding-left: var(--e3); padding-right: var(--e3); }
.btn.suelto:hover { background: var(--panel-2); }
.btn.chico { padding: 6px 12px; font-size: var(--t-s); min-height: 32px; }
/* Con el dedo, 32 px no bastan. En un ratón sí —el puntero es un punto— y por eso el
   tamaño de siempre se queda para escritorio: engordar todas las filas de todas las
   listas para un problema que solo existe con el dedo sería pagar en las dos pantallas.

   `pointer: coarse` es el navegador diciendo «esto se toca», y es más fiel que el ancho:
   una tablet apaisada de 1024 es ancha y se toca igual. Medido en «Ver», «Rectificar» y
   «Cartel con el QR» de media aplicación: 33 px, cuando lo recomendado son 44.

   Se toca el ALTO y no el texto: la fila crece unos píxeles y la letra se queda como
   estaba, que es lo que hace que la lista siga cabiendo. */
@media (pointer: coarse) {
  .btn.chico { min-height: 44px; padding-top: 10px; padding-bottom: 10px; }
  /* Y el botón normal, que se quedaba en 43 por un píxel: el alto sale del texto más el
     relleno, así que basta con que alguien cambie el cuerpo de letra para que baje. Un
     mínimo explícito no depende de eso. */
  .btn { min-height: 44px; }
}
.btn.grande { padding: 14px 26px; font-size: var(--t-g); min-height: 52px; }
.btn.ancho { width: 100%; }

/* ---------- Formularios ------------------------------------------------------------------ */
/* El rótulo NOMBRA el campo y la ayuda lo EXPLICA: son dos cosas distintas y tienen que
   verse distintas. Los dos usaban `--t-s` y `--ink2`, o sea el mismo tamaño y el mismo
   color, así que el título y su explicación se leían como un solo bloque gris y había que
   adivinar dónde acababa uno. Se separan por peso y por tinta, no por tamaño: el alto del
   rótulo entra en la retícula de `.campos` y cambiarlo movería las 158 pantallas. */
label { display: block; font-size: var(--t-s); color: var(--ink); font-weight: 600;
        margin-bottom: var(--e1); }
/* `input:not([type])` está en la lista a propósito. Un `<input name="motivo" required>` sin
   `type` ES un campo de texto para el navegador, pero NINGUNA de estas reglas lo alcanzaba:
   salía con el ancho que el navegador le da por defecto —unos 175 px—, sin borde propio y
   sin la altura de los demás. Se veía en la conformidad de un parte de montaje, donde el
   campo «Nombre y cargo de quien lo da por bueno» cortaba su propio marcador de ayuda; y hay
   nueve campos así repartidos por la aplicación. Se arregla aquí y no campo a campo, que es
   lo que volvería a pasar con el décimo. */
/* Y `url`, `month`, `week` y `datetime-local` por el mismo motivo, aunque no los escriba
   ninguna plantilla: los pone Django solo. Un `URLField` sale como `type="url"`, y el campo
   «Sitio web» de los datos de la empresa se pintaba con el borde fino del navegador y 175 px
   de ancho, en medio de una rejilla de campos de 40 px de alto. Los cuatro son campos de
   texto para el navegador; que el tipo diga qué se teclea no cambia cómo se ve. */
input:not([type]),
input[type=text], input[type=email], input[type=number], input[type=date], input[type=time],
input[type=password], input[type=search], input[type=tel], input[type=url],
input[type=month], input[type=week], input[type=datetime-local], select, textarea {
  width: 100%; padding: 9px 11px; font: inherit; font-size: var(--t-m);
  color: var(--ink); background: var(--panel);
  border: 1px solid var(--linea-2); border-radius: var(--r-s);
  min-height: 40px;
}
/* El de archivo no lleva el marco de los demás —el navegador pinta su propio botón y
   forzarlo deja un cuadro vacío con un botón dentro—, pero sí tiene que caber. Trae un ancho
   propio de 253 px que no se encoge, y en la rejilla de «Traer datos» la celda mide 246 en
   una ventana de 800: el nombre del archivo se salía siete píxeles por la derecha. */
input[type=file] { max-width: 100%; }
input:disabled, select:disabled, textarea:disabled { background: var(--panel-2); color: var(--ink3); }
textarea { min-height: 72px; resize: vertical; }
/* Rejilla de campos. `align-items: start` y una altura mínima para la etiqueta: con
   etiquetas de una y de dos líneas mezcladas, los cuadros de texto quedaban a alturas
   distintas dentro de la misma fila y el formulario parecía roto. */
.campos { display: grid; gap: var(--e4);
          grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); align-items: start; }
.campos > div > label { min-height: 2.4em; display: flex; align-items: flex-end; }
/* Un campo de varias líneas ocupa dos huecos. Se escribe una frase en él —«qué ha quedado
   puesto hoy»— y en 190 px eso es una columna de cinco palabras: se teclea a ciegas. El
   `:has` va dentro de una consulta de anchura a propósito: por debajo de 700 px la rejilla se
   queda en una columna, y ahí un `span 2` crearía una segunda columna implícita y sacaría el
   formulario de la pantalla. Un navegador que no entienda `:has` descarta la regla entera y
   se queda como estaba, que es exactamente lo que se quiere. */
@media (min-width: 700px) { .campos > div:has(textarea) { grid-column: span 2; } }
.campos > div > .btn { margin-top: 2.4em; }
/* Una casilla no es un cuadro de texto: ni ocupa todo el ancho ni mide 40 px de alto.

   Marcada va NEGRA y no del color de la empresa. Es la misma decisión que el botón
   primario: el rojo de GSN se guarda para lo que es de GSN —el logotipo, la marca del
   documento— y no para lo que hace la aplicación. En una pantalla de editor con veinte
   casillas, veinte cuadros rojos hacían de la lista un semáforo. En tema oscuro `--ink` es
   claro y el navegador pone la marca en oscuro: sigue leyéndose. */
input[type=checkbox], input[type=radio] { width: 20px; height: 20px; min-height: 0;
                                          accent-color: var(--ink); }
.campos input[type=checkbox] { margin-top: var(--e2); }
/* Una casilla por opción, en fila y no en columna: los siete días que se trabaja del
   convenio ocupaban siete renglones. Se pide desde el widget:
   `CheckboxSelectMultiple(attrs={"class": "casillas-en-fila"})`, que Django pone en el
   contenedor. */
.casillas-en-fila { display: flex; flex-wrap: wrap; gap: var(--e2) var(--e4);
                    margin-top: var(--e2); }
.casillas-en-fila label { display: inline-flex; align-items: center; gap: var(--e1);
                          font-weight: normal; }
.campos .casillas-en-fila input[type=checkbox] { margin-top: 0; }
.ayuda { font-size: var(--t-s); color: var(--ink3); margin-top: var(--e1); }
.error { font-size: var(--t-s); color: var(--grave); margin-top: var(--e1); }

/* ---------- Avisos ----------------------------------------------------------------------- */
.aviso {
  background: var(--panel); border: 1px solid var(--linea);
  border-left: 4px solid var(--ink3); border-radius: var(--r);
  padding: var(--e4) var(--e5); margin-bottom: var(--e5);
}
.aviso.success { border-left-color: var(--ok); background: var(--ok-suave); }
.aviso.error   { border-left-color: var(--grave); background: var(--grave-suave); }
.aviso.warning { border-left-color: var(--aviso); background: var(--aviso-suave); }
.aviso.info    { border-left-color: var(--info); background: var(--info-suave); }

/* ---------- Estado vacío ------------------------------------------------------------------ */
/* Una lista vacía no puede decir solo «no hay nada»: tiene que decir qué es esto y qué se
   hace ahora. Es la primera pantalla que ve un cliente el día que empieza. */
.vacio { text-align: center; padding: var(--e7) var(--e5); color: var(--ink2); }
.vacio .q { display: block; font-size: var(--t-g); font-weight: 600; color: var(--ink);
            margin-bottom: var(--e2); }
.vacio .v { display: block; max-width: 52ch; margin: 0 auto var(--e5); }

/* Un código que hay que teclear o leer en voz alta: separado y grande. */
.codigo { font-size: var(--t-g); font-weight: 700; letter-spacing: .12em;
          background: var(--panel-2); border: 1px solid var(--linea);
          padding: var(--e2) var(--e4); border-radius: var(--r-s); }

/* Un formulario de una sola columna: cambiar la contraseña, un dato suelto. Ancho corto a
   propósito: un campo de 900 px de ancho para escribir seis letras se ve mal y se usa peor. */
.tarjeta.estrecha { max-width: 460px; }
.pila { display: flex; flex-direction: column; gap: var(--e4); }

/* ---------- Secciones plegables ----------------------------------------------------------- */
/* Una tarjeta que se abre bajo demanda. La línea de arriba —título, cuenta y, si la hay, la
   suma— es la primera lectura; la tabla, la lista o el formulario viven dentro y se abren con
   un clic. Van CERRADAS por defecto, siempre: es la regla de la casa (lectura simple, detalle
   bajo demanda). Lo que pide una acción —un borrador sin emitir, una factura sin cobrar— no
   se pliega: se pliega lo que ya está hecho, lo que se cambia una vez al año y lo que se
   consulta de tarde en tarde. Un `open` puesto a mano es una excepción, y se explica al lado.
   Uso: <details class="seccion"><summary>Cobradas <span class="chip">30</span>
        <span class="cifra">250.000 €</span></summary><div class="cuerpo">...</div></details> */
/* Sin caja desde el 27/09/2026: una línea con su regla debajo, como un renglón más. Con
   caja blanca, borde y sombra, cuatro pliegues seguidos parecían cuatro tarjetas y competían
   con lo que está abierto, que es lo que pide algo. */
details.seccion { background: transparent; border: 0; border-bottom: 1px solid var(--linea);
                  border-radius: 0; margin: 0; box-shadow: none; }
details.seccion > summary { list-style: none; cursor: pointer; display: flex; align-items: center;
                            gap: var(--e3); flex-wrap: wrap; padding: var(--e4) var(--e6);
                            font-weight: 600; font-size: var(--t-b); border-radius: var(--r); }
details.seccion > summary::-webkit-details-marker { display: none; }
details.seccion > summary::after { content: "▾"; margin-left: auto; color: var(--ink3);
                                   font-weight: 400; }
details.seccion[open] > summary::after { content: "▴"; }
details.seccion > summary:hover { background: var(--panel-2); }
details.seccion[open] > summary { border-bottom: 1px solid var(--linea);
                                  border-radius: var(--r) var(--r) 0 0; }
details.seccion > summary .cifra { font-weight: 700; }
details.seccion > summary .pista { font-weight: 400; color: var(--ink2); font-size: var(--t-m); }
details.seccion > .cuerpo { padding: var(--e4) var(--e6) var(--e5); }
details.seccion > .cuerpo > .sub { margin-bottom: var(--e4); }

/* El membrete de la empresa tal como sale impreso. */
.membrete { font-size: var(--t-m); line-height: 1.6; color: var(--ink2);
            border-left: 3px solid var(--linea-2); padding-left: var(--e4); }

/* ---------- Tarjeta de «crear algo» -------------------------------------------------------- */
/* El formulario de dar de alta va plegado. Se usa una vez al día y estaba empujando hacia
   abajo lo que se mira veinte veces: la lista. Abierto ocupa lo mismo que antes; cerrado,
   una línea. */
/* Crear algo: cerrado es un BOTÓN a la derecha; abierto, una tarjeta con el formulario.
   Antes era una franja de lado a lado que ocupaba una fila entera de la pantalla para decir
   «puedes crear una factura». La acción principal va donde se espera —arriba y a la
   derecha— y el formulario aparece cuando se pide. */
details.crear { margin-bottom: var(--e5); }
details.crear > summary { cursor: pointer; list-style: none; display: inline-flex;
                          align-items: center; gap: var(--e2);
                          padding: 9px var(--e5); border-radius: var(--r-s);
                          /* Negra, como `.btn`: cerrado ESTO es la acción principal de la
                             pantalla, así que tiene que ser el mismo botón y no un primo
                             suyo del color de la empresa. El porqué, en «Botones». */
                          border: 1px solid var(--ink);
                          background: var(--ink); color: var(--panel);
                          font-weight: 600; font-size: var(--t-m); min-height: 38px;
                          transition: background var(--transicion); }
details.crear > summary::-webkit-details-marker { display: none; }
details.crear > summary::before { content: "＋"; font-weight: 700; }
/* El mismo plegable, pero para EDITAR lo que ya existe: sin «+», que significa añadir. Un
   «+ Editar sus datos» promete otra ficha y lo que hace es abrir la que ya se está mirando. */
details.crear.editar > summary::before { content: none; }
details.crear > summary:hover { background: var(--ink); filter: brightness(1.35); }

/* Con DOS formas de dar de alta en la misma cabecera —«apuntar un precio» y «añadir un
   material», «anotar una entrega» y «anotar un reconocimiento»— solo la PRIMERA va en negro.
   Dos botones negros del mismo tamaño uno al lado del otro no son dos acciones principales:
   son ninguna, porque el ojo no sabe cuál mirar. La segunda se lee igual y se pulsa igual,
   pero no compite. Se hace por hermandad y no con una clase para que no haya que acordarse:
   la segunda que se escriba se apaga sola. */
.acciones details.crear ~ details.crear > summary,
.acciones-pantalla details.crear ~ details.crear > summary {
  background: transparent; color: var(--ink); border-color: var(--linea-2); }
.acciones details.crear ~ details.crear > summary:hover,
.acciones-pantalla details.crear ~ details.crear > summary:hover {
  background: var(--panel-2); filter: none; }
/* La pista solo cuando está abierto: en el botón sobra, y ahí dentro es donde hace falta. */
details.crear > summary .pista { display: none; }
details.crear:not([open]) { display: flex; justify-content: flex-end;
                            margin-bottom: var(--e4); }
/* Y el cuerpo se esconde a mano cuando está cerrado. Suena redundante —un `<details>` ya
   esconde lo suyo— pero el `display: flex` de la línea de arriba convierte ese cuerpo en un
   elemento de la fila: el navegador lo aplasta contra el borde derecho y sus campos, que
   tienen un ancho mínimo, se salen de la pantalla. En un móvil eso arrastraba la página
   entera de lado por un formulario que ni siquiera se veía. */
details.crear:not([open]) > .cuerpo-crear { display: none; }

/* Dos acciones seguidas van en la misma fila, no una debajo de otra. Cuando una se abre,
   ocupa el ancho entero y la otra se queda a su lado hasta que haya sitio. */
.acciones-pantalla { display: flex; flex-wrap: wrap; justify-content: flex-end;
                     gap: var(--e3); margin-bottom: var(--e4); }
.acciones-pantalla > details.crear { margin-bottom: 0; }
.acciones-pantalla > details.crear[open] { flex: 1 1 100%; }

/* ---------- Y cuando el alta se abre DENTRO de una cabecera -------------------------------
   Cerrado, `details.crear` es un botón y comparte la fila con el titular, que es lo que se
   quiere. Abierto se convierte en un formulario de cuatro o seis campos, y ahí seguía siendo
   un elemento más de esa misma fila: el titular se quedaba encogido a su ancho mínimo a la
   izquierda, el formulario ocupaba la derecha, y con `align-items: flex-end` el titular se
   hundía al fondo de la fila. Resultado: media pantalla en blanco arriba a la izquierda y un
   cuadro flotando arriba a la derecha, sin relación aparente con la pantalla que hay debajo.

   Pasaba en las diecisiete pantallas que abren un alta desde la cabecera —crear un borrador,
   preparar una entrega, anotar una solicitud…—, o sea que no era un fallo de una plantilla:
   era del componente. `.acciones-pantalla` ya lo tenía resuelto con `flex: 1 1 100%` y a la
   cabecera nunca se le llevó la regla.

   Abierto, el bloque baja a su propia fila y ocupa el ancho entero. El titular vuelve arriba,
   donde estaba, y el formulario se lee como lo que es: lo que se ha abierto debajo. */
.cabecera .acciones:has(> details.crear[open]) { flex: 1 1 100%; margin-left: 0;
                                                 align-items: stretch; }
.cabecera .acciones > details.crear[open] { width: 100%; margin-bottom: 0; }

details.crear[open] { display: block; background: var(--panel);
                      border: 1px solid var(--linea); border-radius: var(--r);
                      box-shadow: var(--sombra); }
details.crear[open] > summary { display: flex; width: 100%; border-radius: var(--r) var(--r) 0 0;
                                border: 0; border-bottom: 1px solid var(--linea);
                                background: var(--panel-2); color: var(--ink);
                                padding: var(--e4) var(--e6); }
details.crear[open] > summary::before { content: "−"; color: var(--marca-legible); }
details.crear[open] > summary:hover { background: var(--panel-2); }
details.crear[open] > summary .pista { display: inline; font-weight: 400; color: var(--ink2);
                                       font-size: var(--t-m); }
details.crear .cuerpo-crear { padding: var(--e5) var(--e6); }

/* ---------- Desplegable de opciones -------------------------------------------------------- */
/* Una sola cosa a la vista por fila; lo demás, al abrirlo. Diez filas con dos formularios
   cada una son un muro de botones, no una pantalla. */
/* Un «abrir» es un pliegue, no una alarma ni una acción principal: va en tinta secundaria y
   subrayado al posarse. Iba del color de la empresa —o sea, rojo en GSN—, y en una lista con
   siete filas eran siete rótulos rojos compitiendo con lo único que de verdad urge en la
   pantalla. La marca vive en el logo, en el membrete y en la sección puesta. */
summary.abrir { cursor: pointer; color: var(--ink2); font-size: var(--t-m);
                font-weight: 600; list-style: none; display: inline-block; }
summary.abrir:hover { color: var(--ink); text-decoration: underline;
                      text-underline-offset: 3px; }
summary.abrir::marker, summary.abrir::-webkit-details-marker { display: none; }
summary.abrir::after { content: " ▾"; color: var(--ink2); }
details[open] > summary.abrir::after { content: " ▴"; }
.opciones { display: flex; flex-direction: column; gap: var(--e3); margin-top: var(--e3);
            padding: var(--e3) var(--e4); border: 1px solid var(--linea);
            border-radius: var(--r-s); background: var(--panel-2); }
.opciones form { display: flex; gap: var(--e2); align-items: center; flex-wrap: wrap; }
/* `width: auto` en un `<select>` significa «lo que mida la opción más larga», y dentro de la
   columna de acciones de un renglón —que es estrecha y está pegada al borde derecho— eso se
   sale de la pantalla: con «Dirección · 42 permisos» el desplegable llegaba a 1.506 px en una
   ventana de 1.440 y la página arrastraba de lado, que en esta casa no se permite en
   escritorio. Se le pone tope y el texto largo se recorta en el propio control. */
.opciones select { width: auto; max-width: min(300px, 40vw); }

/* ---------- Formulario por pasos ----------------------------------------------------------- */
/* Un formulario largo que rellena alguien que no lo hace todos los días: numerado, con cada
   paso en su bloque. Se usa para pedir una corrección del registro. */
.paso { border: 1px solid var(--linea); border-radius: var(--r); background: var(--panel);
        padding: var(--e5) var(--e6); margin-bottom: var(--e4); }
.paso > h3 { display: flex; align-items: center; gap: var(--e3); margin-bottom: var(--e4); }
/* El número del paso va NEGRO, no del color de la empresa. Misma decisión que el botón
   primario y que las casillas: el rojo de GSN es de GSN —el logotipo, la marca del papel— y
   no de lo que hace la aplicación. Con cuatro pasos, cuatro círculos rojos competían con el
   único botón de la pantalla. */
.paso .n { display: inline-flex; width: 26px; height: 26px; border-radius: 50%; flex: none;
           background: var(--ink); color: var(--panel);
           align-items: center; justify-content: center; font-size: var(--t-s); font-weight: 700; }

/* ---------- El rastro de algo ----------------------------------------------------------- */
/* Por dónde ha pasado una cosa y quién firmó cada paso: una factura recibida, una remisión a
   la AEAT, un presupuesto con sus versiones. Se lee de arriba abajo, y de un vistazo se ve
   dónde está parado. No es el `.paso` de un formulario: aquí no se rellena nada, se cuenta
   lo que ya ha ocurrido. El punto lleno dice «hecho», el hueco «todavía no».
   El estado NUNCA va solo por el color: cada línea lleva su texto. */
ol.rastro, ul.rastro { list-style: none; margin: 0; padding: 0; }
.rastro li { position: relative; padding: 0 0 var(--e5) var(--e5);
             border-left: 2px solid var(--linea); }
.rastro li:last-child { border-left-color: transparent; padding-bottom: 0; }
.rastro li::before { content: ""; position: absolute; left: -7px; top: 3px; width: 12px;
                     height: 12px; border-radius: 50%; background: var(--panel);
                     border: 2px solid var(--linea-2); }
.rastro li.hecho::before { background: var(--ok); border-color: var(--ok); }
.rastro li.falla::before { background: var(--grave); border-color: var(--grave); }
.rastro .q { display: block; font-weight: 700; }
.rastro .m { display: block; color: var(--ink2); font-size: var(--t-s); }
/* Lo que sigue a un rastro sin epígrafe en medio —la frase que lo explica, el pliegue que
   apunta el paso que falta— pegaba con la última línea: la ficha de cobro de una factura. */
.rastro + p, .rastro + details { margin-top: var(--e5); }

/* Elegir una opción entre varias, con el área de toque entera: se rellena de pie y con prisa. */
ul.elige { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column;
           gap: var(--e2); }
ul.elige label { display: flex; align-items: center; gap: var(--e3); padding: var(--e4);
                 border: 1px solid var(--linea); border-radius: var(--r-s); cursor: pointer;
                 font-size: var(--t-b); color: var(--ink); }
ul.elige label:hover { border-color: var(--marca-borde); background: var(--panel-2); }
ul.elige input { transform: scale(1.25); }

/* El periodo del análisis: las dos fechas a la vista y, tras una raya, los atajos que las
   rellenan. Las fechas iban plegadas tras «otras fechas»; ahora mandan ellas y los atajos
   son lo que son (Daniel, 15/09/2026). Los campos van sin caja propia: son parte del mando,
   como los años de Facturas, y el valor se lee como un dato más de la línea. */
.filtros.periodo { gap: var(--e2); padding-right: var(--e2); }
.filtros.periodo input[type="date"] { width: auto; margin: 0; padding: 4px var(--e2);
                                      border: 1px solid transparent; background: transparent;
                                      font: inherit; font-size: var(--t-m); color: var(--ink);
                                      font-weight: 600; border-radius: var(--r-xs); }
.filtros.periodo input[type="date"]:hover,
.filtros.periodo input[type="date"]:focus { border-color: var(--linea-2); background: var(--panel); }
.filtros.periodo .a { color: var(--ink3); font-size: var(--t-s); }
.filtros.periodo .sep { width: 1px; height: 18px; background: var(--linea); margin: 0 var(--e2); }

/* Tarjetitas de un vistazo: los últimos días fichados, una obra, un día suelto. */
.minis { display: flex; gap: var(--e3); flex-wrap: wrap; }
.mini { border: 1px solid var(--linea); border-radius: var(--r-s); padding: var(--e3) var(--e4);
        font-size: var(--t-m); min-width: 132px; background: var(--panel); }
.mini .f { font-weight: 700; }
.mini .m { color: var(--ink2); }
/* La misma terna que en las métricas y en los vacíos —rótulo, cifra, aclaración—, para que
   una tarjetita y una métrica no se escriban de dos maneras distintas. */
.mini .q { display: block; font-size: var(--t-xs); text-transform: uppercase;
           letter-spacing: .05em; color: var(--ink2); }
.mini .v { display: block; font-weight: 700; font-size: var(--t-g); line-height: 1.2;
           font-variant-numeric: tabular-nums; white-space: nowrap; }
.mini .n { display: block; font-size: var(--t-s); color: var(--ink2); }
.mini.es-aviso { border-color: var(--aviso); background: var(--aviso-suave); }
.mini.es-aviso .v { color: var(--aviso); }
.mini.es-grave { border-color: var(--grave); background: var(--grave-suave); }
.mini.es-grave .v { color: var(--grave); }
.mini.es-ok { border-color: var(--ok); background: var(--ok-suave); }
.mini.es-ok .v { color: var(--ok); }

/* Los accesos del inicio, agrupados como en el menú. */
.grupo-accesos { margin-bottom: var(--e4); }
.grupo-accesos .et { font-size: var(--t-xs); font-weight: 700; letter-spacing: .07em;
                     text-transform: uppercase; color: var(--ink2); margin-bottom: var(--e2); }
/* Una métrica que lleva a algún sitio: se nota que se puede tocar. */
a.metrica:hover, a.item:hover { border-color: var(--marca-borde); box-shadow: var(--sombra-2); }

/* ---------- Utilidades justas ------------------------------------------------------------- */
.fila { display: flex; align-items: center; gap: var(--e3); flex-wrap: wrap; }
.fila.pegada { gap: var(--e2); }
.derecha { margin-left: auto; }
.apagado { color: var(--ink2); }
.num { font-variant-numeric: tabular-nums; }
.nada { color: var(--ink3); }
.oculto { display: none !important; }

/* ---------- Filtros ------------------------------------------------------------------------ */
/* Los mismos en todas las pantallas que filtran: un año, un estado, un periodo. */
/* ---------- Resumen de una línea ---------------------------------------------------------- */
/* Las cifras de contexto de una pantalla que es una LISTA. Antes iban en cuadros como los de
   un tablero, y ahí no pintaban nada: en una pantalla con treinta y cinco facturas debajo,
   tres cajas de cien píxeles para decir «hay 35 facturas» empujan la lista fuera de la vista
   para contar lo que la lista ya cuenta.
   Los cuadros se quedan donde la cifra ES la pantalla —cobros, el análisis, las nóminas—; en
   una lista, el dato va en una línea y la lista empieza arriba. */
.resumen { display: flex; flex-wrap: wrap; gap: var(--e6); margin-bottom: var(--e5);
           font-size: var(--t-m); color: var(--ink2); }
.resumen strong { font-weight: 700; color: var(--ink); font-size: var(--t-b);
                  font-variant-numeric: tabular-nums; margin-right: var(--e2); }
.resumen .es-aviso strong { color: var(--aviso); }
.resumen .es-grave strong { color: var(--grave); }
.resumen .es-ok strong    { color: var(--ok); }

/* ---------- Filtros: las pestañas de dentro de una pantalla ------------------------------ */
/* Un mando de segmentos: el grupo entero es una pieza y solo una opción está puesta. Antes
   eran píldoras sueltas y la puesta iba del color de la empresa —el mismo del botón de
   «Crear»—, así que un filtro parecía una acción y competía en peso con las pestañas de
   arriba. Un filtro no hace nada: cambia lo que se está mirando, y su sitio en la jerarquía
   está por debajo de las dos cosas.
   La pieza se ajusta a su contenido (`inline-flex`): una barra gris de lado a lado para tres
   palabras sería otra franja compitiendo por la atención. */
.filtros { display: inline-flex; gap: 2px; align-items: center; flex-wrap: wrap;
           background: var(--panel-2); border: 1px solid var(--linea);
           border-radius: var(--r-s); padding: 3px;
           margin-bottom: var(--e5); }
.filtros > .et:first-child { margin-left: var(--e3); }
.filtros .et { font-size: var(--t-s); color: var(--ink3); margin-right: var(--e2); }
.filtros a { font-size: var(--t-s); padding: 6px var(--e4); border-radius: var(--r-xs);
             text-decoration: none; color: var(--ink2); white-space: nowrap; }
.filtros a:hover { color: var(--ink); }
/* El puesto, en bloque oscuro como en `.segmentos`: era blanco con negrita sobre el gris
   del mando, y a un metro no se veía cuál estaba elegido (Daniel, 15/09/2026). Las dos
   piezas —filtros arriba, segmentos en la barra de la lista— dicen «este» de la misma forma. */
.filtros a.puesto { background: var(--ink); color: var(--panel); font-weight: 600; }
/* Los que además llevan un desplegable o una caja de buscar (documentos, nóminas). */
.filtros select, .filtros input { margin: 0 var(--e2); }
.filtros .btn { margin-left: var(--e2); }

/* ==========================================================================================
   EL LIBRO · la forma de una pantalla de lista

   Parte de trabajo, no tablero. La jerarquía la hacen la tipografía y las reglas, no las
   cajas: una pantalla contesta UNA pregunta, y la cifra que duele va a la izquierda y grande.

   De dónde salió: la lista de una pantalla vivía en una tabla dentro de una tarjeta, con una
   tira de tres o cuatro cuadros encima. Los cuadros contaban lo que la lista ya cuenta y
   empujaban la lista fuera de la vista; la tabla repartía el peso a partes iguales entre
   «quién», «qué», «cuándo» y «estado», así que para saber cuál de las treinta y cinco filas
   corre prisa había que leerlas todas. Aquí la fila se ordena por la cifra que la hace
   urgente, esa cifra se pinta a 30 px a la izquierda, y el titular la dice antes de que se
   mire nada: «Solicitudes: 2 esperan respuesta».

   Se llama renglón y no fila porque `.fila` ya es la utilidad de poner cosas en línea. Un
   renglón es lo que tiene un libro de cuentas, que es exactamente lo que es esta lista.
   ========================================================================================== */

/* ---------- La cabecera de la pantalla ---------------------------------------------------- */
/* El antetítulo dice dónde estás —«Ventas · Presupuesto»— para que el h1 no tenga que
   gastarse en repetir la sección y pueda gastarse en decir lo que pasa. */
.antetitulo { font-size: var(--t-s); font-weight: 600; letter-spacing: .06em;
              text-transform: uppercase; color: var(--ink3); }

/* El titular lleva el dato dentro, y el dato va en `<em>`. En naranja por defecto —lo que
   pide trabajo—, en `--grave` cuando es dinero parado o una baja, en `--ok` cuando la
   respuesta es que todo cuadra. El `<em>` no se pone en cursiva: aquí significa «esta es la
   cifra», y una cursiva en mitad de un titular de 40 px se lee como un tropiezo. */
h1 em { font-style: normal; color: var(--acento-legible); }
h1 em.es-grave { color: var(--grave); }
h1 em.es-ok    { color: var(--ok); }
h1 em.es-tinta { color: var(--ink); }

/* En una pantalla del libro el h1 es el titular de un parte, no el rótulo de un módulo: sube
   a 40 px y a 800. `clamp` porque en un portátil de 1280 un titular de dos líneas a 40 px se
   come la primera pantalla entera. */
/* Un punto más pequeño desde el 27/09/2026 (de 2,5 a 2,05 rem como mucho): sigue siendo lo
   más grande de la pantalla, y la cifra de dentro sigue mandando, pero deja de empujar la
   lista fuera de la primera pantalla. */
.cabecera h1 { font-size: clamp(1.6rem, 2.6vw, 2.05rem); font-weight: 800; letter-spacing: -.025em;
               line-height: 1.1; margin-top: var(--e1); }
/* Las acciones se alinean con la base del titular, no con su parte de arriba: un botón
   flotando a la altura del antetítulo parece de la franja de arriba y no de la pantalla. */
.cabecera.libro { align-items: flex-end; }
.cabecera.libro .acciones { align-items: flex-end; }
/* El pliegue de «crear» lleva margen de abajo para separarse de lo que sigue cuando va
   solo; en la cabecera, junto a un `.btn`, ese margen lo subía diez píxeles respecto al
   botón de al lado (Daniel, 15/09/2026: «PIN de la tablet» y «Dar acceso a alguien»). */
.cabecera .acciones > details.crear { margin-bottom: 0; }
/* Y el titular cede antes que la acción. Con un `h1` largo —«Paquete para la gestoría: 3
   clases de documento dentro»— el bloque del título se quedaba con todo el ancho y el botón
   se caía a la línea siguiente, quedando ENTRE el titular y su lede, que es donde nadie lo
   busca. Con `flex: 1 1 24rem` el titular parte en dos líneas dentro de su parte y la acción
   se queda arriba a la derecha, donde vive. `min-width: 0` para que una palabra larga no
   estire la caja por encima de su base. */
.cabecera.libro > div:first-child { flex: 1 1 24rem; min-width: 0; }
/* `0 1 auto` y con tope, no `0 0 auto`. Sin poder encoger, un bloque de acciones con DOS
   pliegues —«anotar una entrega» y «anotar un reconocimiento», en Prevención— se queda con su
   ancho natural, 548 px, y arrastra de lado una pantalla de 390. Con el tope, los dos botones
   se reparten en dos líneas, que es para lo que ya estaba puesto el `flex-wrap` de dentro. */
.cabecera.libro > .acciones { flex: 0 1 auto; max-width: 100%; }
/* Y en un teléfono, la acción ocupa la línea entera debajo del titular: es lo que ya hacen de
   hecho todas las pantallas de un solo botón, y con dos deja de haber medio botón por línea. */
@media (max-width: 620px) {
  .cabecera .acciones { margin-left: 0; }
  .cabecera.libro > .acciones { flex: 1 1 100%; }
  details.crear > summary { max-width: 100%; }
}
/* El lede: una o dos frases que digan qué hacer o qué significa. Nunca un párrafo. */
.cabecera + .sub, .cabecera .sub { margin-top: var(--e4); margin-bottom: 0; max-width: 60ch; }

/* ---------- La barra de la lista ---------------------------------------------------------- */
/* Filtro a la izquierda, orden declarado a la derecha, y una regla de 2 px debajo que es
   donde empieza el libro. El orden se ESCRIBE —«Ordenadas por días esperando»— porque una
   lista ordenada por algo que no se dice obliga a deducirlo comparando filas, y casi siempre
   se deduce mal. */
.barra-lista { margin-top: var(--e6); display: flex; align-items: center;
               justify-content: space-between; gap: var(--e5); flex-wrap: wrap;
               padding-bottom: var(--e3); border-bottom: 1px solid var(--linea-2); }
.orden { font-size: var(--t-s); color: var(--ink3); }
.orden b { color: var(--ink2); font-weight: 600; }
/* En la barra de la lista, las páginas van a la izquierda y en línea —«1–40 de 403», sus
   flechas— y el orden a la derecha como mando, sin el margen que llevan al pie. */
.barra-lista > .paginas { margin-top: 0; justify-content: flex-start; gap: var(--e4);
                          font-size: var(--t-s); }
/* A la derecha, otras formas de llevarse la misma lista —en tabla, en hoja de cálculo—,
   pequeñas: son de la lista y no de la pantalla. */
.barra-lista > .otras-formas { margin-left: auto; display: flex; gap: var(--e3); align-items: center;
                               font-size: var(--t-s); }
.otras-formas a { color: var(--ink2); }
.otras-formas a:hover { color: var(--ink); }
.otras-formas .sep { color: var(--ink3); }

/* Los filtros de una lista, plegados detrás de «Mostrar filtros» (Andrés, 19/09/2026). Con
   alguno puesto salen abiertos y el rótulo dice cuántos: una lista filtrada que no lo dice se
   lee como la entera. */
details.filtros-plegables { margin: var(--e3) 0 var(--e2); }
details.filtros-plegables > summary { list-style: none; cursor: pointer; display: inline-flex;
                                      align-items: center; gap: var(--e2); padding: 4px 0;
                                      font-size: var(--t-s); color: var(--ink2); }
details.filtros-plegables > summary::-webkit-details-marker { display: none; }
details.filtros-plegables > summary::after { content: "▾"; color: var(--ink3); }
details.filtros-plegables[open] > summary::after { content: "▴"; }
details.filtros-plegables > summary:hover { color: var(--ink); }
details.filtros-plegables > summary .al-cerrar,
details.filtros-plegables[open] > summary .al-abrir { display: none; }
details.filtros-plegables[open] > summary .al-cerrar { display: inline; }
details.filtros-plegables > .filtros { margin-top: var(--e2); }

/* El mando segmentado. Se distingue de `.filtros` en que la opción puesta va en negro sólido
   y lleva su recuento dentro: en el libro el filtro también informa —«Esperando 2»— y así la
   cuenta no necesita una tira de cuadros que la diga aparte. Sin caja alrededor: el grupo se
   lee como grupo por la proximidad, y una caja gris más es una franja más. */
.segmentos { display: flex; gap: 2px; flex-wrap: wrap; }
.segmentos a, .segmentos button { border: 0; background: transparent; padding: 6px var(--e4);
                                  border-radius: var(--r-s); font-weight: 600;
                                  font-size: var(--t-s); color: var(--ink2);
                                  text-decoration: none; white-space: nowrap; cursor: pointer; }
.segmentos a:hover, .segmentos button:hover { background: var(--panel-2); color: var(--ink); }
/* El puesto, en claro y con su borde desde el 27/09/2026: un solo bloque negro por
   pantalla, que es el botón principal. Negro, el segmento puesto era una segunda acción
   principal justo debajo del titular. */
.segmentos a.puesto, .segmentos button.puesto { background: var(--panel); color: var(--ink);
                                                outline: 1px solid var(--linea-2); outline-offset: -1px; }
/* El recuento dentro de la pastilla, más flojo que el rótulo: es el dato, no la etiqueta. */
.segmentos span { font-weight: 500; opacity: .7; margin-left: var(--e2); }

/* ---------- El renglón -------------------------------------------------------------------- */
/* [cifra 30/800] [quién] [qué] [cuándo] [importe] [acciones →]
   Separados por una regla de 1 px y nada más: sin tarjeta, sin fondo alterno, sin sombra.
   El renglón entero es un enlace al expediente, PERO además lleva su botón «Expediente»
   visible: un `onclick` de fila no se ve, no se puede abrir en otra pestaña y no existe para
   quien navega con el teclado. La regla de la casa es que el expediente siempre tenga una
   puerta que se vea. */
.renglon { display: grid; grid-template-columns: 120px 1.4fr 1.6fr 150px auto;
           gap: 0 var(--e5); align-items: center; padding: var(--e5) 0;
           border-bottom: 1px solid var(--linea); color: inherit; text-decoration: none; }
.renglon:hover { background: var(--panel-2); }
/* Un enlace DENTRO de un renglón es el texto del renglón, no un enlace suelto: hereda la
   tinta y solo se subraya al posarse. Si no, el nombre de cada fila sale del color de la
   empresa y subrayado, y una lista de treinta pasa a ser una lista de treinta enlaces
   gritando. Pasa cuando el renglón no puede ser un `<a>` entero porque su acción es un
   formulario —abrir un estudio, enviar un pedido—, que es la mitad de las pantallas. */
.renglon a { color: inherit; text-decoration: none; }
.renglon a:hover { text-decoration: underline; text-underline-offset: 3px; }

/* Y lo mismo dentro de una tabla de datos, por el mismo motivo. Un enlace en una celda es el
   texto de esa celda —el nombre del proveedor, el del material—, no una llamada a pulsar:
   ocho enlaces rojos en columna no son una lista de enlaces, son una columna gritando. Se
   quedan subrayados en gris para que se sepa que llevan a algún sitio, y el subrayado se
   enciende al pasar por encima. */
main table td a { color: inherit; text-decoration: underline; text-underline-offset: 3px;
                  text-decoration-color: var(--linea); }
main table td a:hover { text-decoration-color: currentColor; }
/* Las variantes de reparto. La rejilla se declara en la plantilla porque el número de datos
   es de la pantalla, no del sistema: un pedido lleva importe y una solicitud no. */
.renglon.con-dinero { grid-template-columns: 120px 1.5fr 1fr 130px 130px auto; }
.renglon.c4         { grid-template-columns: 120px 1.6fr 1fr auto; }
.renglon.c3         { grid-template-columns: 120px 1fr auto; }
.renglon.sin-cifra  { grid-template-columns: 1.6fr 1fr 150px auto; }
.renglon.apretado   { padding: var(--e4) 0; }
/* Lista con selección múltiple: la casilla va la PRIMERA, en columna propia. Metida dentro
   del nombre caía a la línea de arriba y el renglón se leía como si el nombre tuviera un
   sombrero. Al frente, las once casillas quedan en la misma vertical y se marcan de arriba
   abajo sin buscar ninguna. */
.renglon.con-casilla { grid-template-columns: 26px 120px 1.5fr 1.2fr auto; }
.renglon.con-casilla.cifra-ancha { grid-template-columns: 26px 190px 1.4fr 1.1fr auto; }
/* Y sin cifra ninguna: una lista de cosas que solo se marcan —de qué quiero que me avisen—
   no tiene número a la izquierda, y dejar su hueco vacío ponía 120 px de nada entre la
   casilla y lo que dice. */
.renglon.con-casilla.sin-cifra { grid-template-columns: 26px 1.6fr 1fr auto; }
.renglon .casilla { display: grid; place-items: center; }
.renglon .casilla input { width: 20px; height: 20px; }
/* Cuando la cifra de la izquierda NO es un contador corto de días, sino algo que lleva
   espacios: un importe («119.185,00 €») o un tiempo («41 h 20 min»). A 30 px no caben en 120,
   así que partían por el espacio —el € o el «min» caían solos a la línea siguiente— y el
   nombre de al lado se les montaba encima. Un importe partido en dos renglones deja de ser un
   importe, y una hora partida deja de ser una hora.
   Se ensancha la columna Y se encoge la letra, que es la misma pareja que ya usan las
   métricas: un número no se parte nunca, se hace más pequeño. */
.renglon.cifra-ancha { grid-template-columns: 190px 1.5fr 1.4fr auto; }
/* Y en el de tres columnas, lo mismo: una fecha en la columna de la cifra se salía por
   encima del nombre de al lado («Quién se la llevó», en Conservación de datos). */
.renglon.c3.cifra-ancha { grid-template-columns: 190px 1fr auto; }
.renglon.cifra-ancha .espera { font-size: var(--t-g); white-space: nowrap; }

/* La cifra que duele, con su unidad al lado, porque «17» sin «días» no significa nada.
   Hasta el 27/09/2026 iba a 30 px y la unidad debajo en mayúsculas: en una lista de siete
   filas eran siete cifras del tamaño del titular, y la pantalla tenía ocho cosas gritando en
   vez de una. Ahora la cifra grande es la del titular; aquí basta con el peso y el color. */
.renglon .espera { font-size: var(--t-g); font-weight: 700; letter-spacing: -.01em;
                   line-height: 1.25; font-variant-numeric: tabular-nums; }
.renglon .espera small { display: inline; font-size: var(--t-s); font-weight: 500;
                         color: var(--ink3); margin-left: var(--e1); }
/* Lo que no tiene cifra —«Sin pedir»— no se inventa un cero: se dice con palabras, más
   pequeño y en gris, y se va al final de la lista. Un 0 grande compite con un 17 grande.

   Va ANTES que los colores de estado y no después, que es donde estaba. Con la misma
   especificidad manda el último, así que este gris se comía el verde de todos los
   «espera sin es-ok»: «Llegó todo», «Aceptado», «Al día» y «Cobrada» salían en gris de texto
   apagado en diecinueve pantallas. El tamaño sí es de «sin cifra»; el color es del estado. */
.renglon .espera.sin { font-size: var(--t-b); font-weight: 600; color: var(--ink3);
                       letter-spacing: 0; }
/* Lo que ya está hecho —«Cobrada», «Aceptado», «Con cuenta»— se dice en gris y pequeño, y NO
   lleva el verde de `es-ok` a tamaño de cifra. Ocho «Cobrada» verdes y grandes en la ficha de
   un cliente tapaban las dos facturas vencidas que había entre ellas (27/09/2026). El color
   queda para lo que pide algo. */
.renglon .espera.hecho, .renglon .espera.hecho small { font-size: var(--t-m); font-weight: 500;
                                                        color: var(--ink3); letter-spacing: 0; }
.renglon .espera.es-aviso, .renglon .espera.es-aviso small { color: var(--acento-legible); }
.renglon .espera.es-grave, .renglon .espera.es-grave small { color: var(--grave); }
.renglon .espera.es-ok,    .renglon .espera.es-ok small    { color: var(--ok); }

/* Quién: el nombre pesa, y debajo lo que haga falta para reconocerlo (teléfono, NIF).

   Ojo con el combinador: estas reglas van a HIJO DIRECTO (`>`) y no a descendiente. Con
   `.renglon .quien span` la regla alcanzaba también al `<span class="chip">` de dentro de la
   segunda línea, lo volvía `display:block` con más especificidad que el propio `.chip`, y la
   etiqueta «todavía no es cliente» salía estirada a los 325 px de la columna: parecía un
   campo de formulario vacío. Se vio en la captura y no lo cazó ninguna medida.

   Y por eso mismo llevan `:not(.chip)`: una etiqueta puede ir SOLA en su hueco —la desviación
   de una orden de taller, el momento de una factura— y entonces sí es hija directa. Sin la
   exclusión, «+25,8 %» se estiraba a lo ancho de su columna y volvía a parecer un campo
   vacío. Un chip nunca es una segunda línea: es una pastilla, y se ajusta a lo que dice. */
/* Una palabra larga no saca la página de lado. Los hijos de una rejilla no encogen por debajo
   de su palabra más larga, y en un móvil de 390 px el concepto «CONSTRUCCIONES PARDIÑAS» o un
   número de obra pegado a un nombre empujaba la columna hasta 460: la lista de facturas de un
   taller de verdad se arrastraba de lado en cuanto había un cliente con el nombre en mayúsculas. */
.renglon .quien, .renglon .que { min-width: 0; overflow-wrap: anywhere; }
.renglon .quien > b { display: block; font-size: var(--t-g); font-weight: 700; line-height: 1.25; }
.renglon .quien > span:not(.chip) { display: block; font-size: var(--t-m); color: var(--ink2);
                         margin-top: 3px; }
/* Qué: la cosa, y debajo dónde. Peso 500 y no 700: en un renglón solo puede haber un nombre
   propio, y es el de quién. */
.renglon .que > b { display: block; font-size: var(--t-g); font-weight: 500; line-height: 1.3; }
.renglon .que > span:not(.chip) { display: block; font-size: var(--t-m); color: var(--ink3); margin-top: 3px; }
/* Cuándo: la fecha en la que se decide, y debajo de dónde viene. */
.renglon .cuando > b { display: block; font-size: var(--t-m); font-weight: 600; }
.renglon .cuando > span:not(.chip) { display: block; font-size: var(--t-s); color: var(--ink3);
                          margin-top: 3px; }
/* El dinero, a la derecha y alineado por la coma: una columna de importes que no cuadra por
   la derecha no se puede comparar de un vistazo, que es para lo único que está ahí. */
.renglon .dinero { text-align: right; font-size: var(--t-b); font-weight: 700;
                   font-variant-numeric: tabular-nums; }
.renglon .dinero > span:not(.chip) { display: block; font-size: var(--t-s); font-weight: 500;
                          color: var(--ink3); margin-top: 3px; }
.renglon .acciones { display: flex; gap: var(--e3); align-items: center;
                     justify-content: flex-end; margin-left: 0; }
/* La flecha del final. Es decoración con oficio: dice que el renglón lleva a algún sitio sin
   gastar una palabra, y por eso va en gris y detrás del botón que sí se puede pulsar. */
.renglon .va { color: var(--ink3); font-size: var(--t-xg); line-height: 1; }
/* La puerta al expediente, sin caja (27/09/2026). Sigue estando, se sigue viendo y se sigue
   pudiendo pulsar, abrir en otra pestaña y alcanzar con el teclado —que es el principio—, pero
   ya no es un botón con borde repetido en cada fila: en una lista de siete eran siete cajas
   iguales que no decían nada y tapaban la única acción de verdad de la fila («Cobrar», «Dar
   acceso»). La marca la ponen las plantillas: `class="btn segundo chico puerta"`. */
.btn.puerta, .btn.chico.puerta { background: transparent; border-color: transparent; color: var(--ink2);
                                 font-weight: 500; padding-left: var(--e2); padding-right: var(--e2);
                                 text-decoration: underline; text-decoration-color: var(--linea-2);
                                 text-underline-offset: 3px; }
.btn.puerta:hover { background: transparent; color: var(--ink); text-decoration-color: currentColor;
                    filter: none; }

/* Un formulario que no cabe en la fila cae DEBAJO de ella, a todo el ancho, y no dentro de
   la columna de acciones. La columna de acciones es estrecha y está pegada al borde derecho:
   un `<select>` de «Dirección · 42 permisos» metido ahí medía 287 px que empezaban en el
   1.219 de una ventana de 1.440, así que la página arrastraba de lado. Estrechar el control
   no arregla nada —el problema es dónde está—, y el sitio natural de un formulario que se
   abre bajo demanda es la línea siguiente, donde tiene el ancho entero.
   Va como hijo directo del renglón y ocupa todas las columnas. */
.renglon > details.bajo-la-fila { grid-column: 1 / -1; margin-top: var(--e3); }
/* La barra de una obra (27/09/2026): la fase en segmentos a la izquierda y, a la derecha,
   «Añadir» con las altas de los demás módulos, que salen con la obra ya puesta. */
.barra-obra .apagado { font-size: var(--t-s); }
.barra-obra .anadir { gap: var(--e4); font-size: var(--t-s); flex-wrap: wrap; }
.barra-obra .anadir a { color: var(--ink); font-weight: 600; text-underline-offset: 3px;
                        text-decoration-color: var(--linea-2); }
.barra-obra .anadir a:hover { text-decoration-color: currentColor; }
/* La acción de una fila que abre un formulario —«Dar acceso»—, a la vista como botón y con
   el formulario debajo, alineado a la derecha y por encima de las filas de abajo: abrirlo
   no mueve la lista (27/09/2026). En el teléfono, en su sitio y a lo ancho. */
.renglon .acciones details.en-la-fila { position: relative; }
.renglon .acciones details.en-la-fila > summary { list-style: none; }
.renglon .acciones details.en-la-fila > summary::-webkit-details-marker { display: none; }
.renglon .acciones details.en-la-fila > .opciones {
  position: absolute; right: 0; top: calc(100% + var(--e2)); z-index: 6; margin: 0;
  background: var(--panel); border: 1px solid var(--linea); border-radius: var(--r-s);
  box-shadow: var(--sombra-2); padding: var(--e4); min-width: 340px; }
@media (max-width: 780px) {
  .renglon .acciones details.en-la-fila > .opciones { position: static; min-width: 0;
                                                     margin-top: var(--e3); }
}
.renglon > details.bajo-la-fila > summary { font-size: var(--t-s); }

/* Los códigos internos —C2026-003, P2026-007— viven en la segunda línea y en gris. Delante
   no: nadie busca un presupuesto por su número hasta que ya lo ha encontrado por el cliente.

   Se llama `.referencia` y NO `.codigo` porque `.codigo` ya existe y significa otra cosa: el
   número que hay que teclear o leer en voz alta —el PIN de la tablet—, que va en una caja con
   borde y letra espaciada. Con ese nombre, cada «P2026-007» de la lista salía metido en un
   recuadro y parecía un campo de formulario vacío del ancho de la columna. */
.renglon .referencia { color: var(--ink3); font-variant-numeric: tabular-nums; }

/* La cabecera de una lista de renglones, y el corte de mes que la parte.

   El renglón nació sin rótulos y para casi todas las listas está bien: nadie necesita que le
   pongan «Cliente» encima del nombre del cliente. La excepción es la columna del dinero, que
   según la pestaña es una cifra u otra —lo que queda por cobrar, lo que entró—, y sin rótulo
   no hay forma de saber cuál. Por eso la cabecera es fina, gris y en versalita: rotula, no
   compite con las filas. Hereda la rejilla del renglón (`renglon con-dinero cabecera`), así
   que las columnas caen siempre donde las de abajo.

   El corte de mes es la costumbre que traen quienes vienen de una hoja de cálculo: filas y,
   al cambiar de mes, su suma. Va con línea arriba y el mes en versalita, para que se lea como
   una separación y no como una fila más. */
/* Y la columna de acciones con suelo fijo. Cada renglón es su propia rejilla, así que con la
   última columna en `auto` una fila con tres botones y otra con dos repartían distinto lo que
   sobraba: los conceptos de la lista de facturas no estaban en la misma vertical, y la
   cabecera —que no tiene botones— se iba cuarenta píxeles más a la derecha que todo lo demás.
   Con un mínimo, las filas normales caen todas igual; la que de verdad necesite más, crece. */
.renglon.con-dinero.acciones-fijas {
  grid-template-columns: 120px 1.5fr 1fr 130px 130px minmax(250px, auto); }
.renglon.cabecera { padding: 0 0 var(--e3); border-bottom: 1px solid var(--linea-2); }
.renglon.cabecera:hover { background: none; }
.renglon.cabecera > span { font-size: var(--t-s); font-weight: 600; color: var(--ink3); }
.renglon.cabecera > span.dinero { text-align: right; }

/* El rótulo que ordena (`nucleo/_ordena.html`). La cabecera es también el mando del orden
   (Andrés, 19/09/2026): se pulsa el rótulo y la columna que manda lleva su flecha, ▼ o ▲. Sin
   subrayado ni color de enlace, que la cabecera rotula y no compite con las filas; el que
   manda, en negro, y los demás dicen que se pueden pulsar al pasar por encima. */
.renglon.cabecera a.ordena, th a.ordena { color: inherit; text-decoration: none; }
.renglon.cabecera a.ordena:hover, th a.ordena:hover { color: var(--ink); text-decoration: underline;
                                                     text-underline-offset: 3px; }
a.ordena.puesta { color: var(--ink); }
a.ordena .flecha { margin-left: .3em; }
a.ordena:not(.puesta):hover::after { content: "↕"; margin-left: .3em; color: var(--ink3); }
/* Lo que ocupa el botón de las filas sin enseñarlo: en una rejilla con la última columna en
   `auto`, la cabecera sin botones repartía el sitio de otra forma y sus rótulos no caían
   encima de su columna. */
.renglon.cabecera .hueco { visibility: hidden; }

.corte-de-mes { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--e4);
                justify-content: space-between; padding: var(--e5) 0 var(--e3);
                border-bottom: 1px solid var(--linea); }
.corte-de-mes > b { font-size: var(--t-m); font-weight: 800; letter-spacing: .06em;
                    text-transform: uppercase; }
.corte-de-mes > span { font-size: var(--t-s); color: var(--ink2);
                       font-variant-numeric: tabular-nums; }

/* ---------- La petición: lo que espera un sí o un no ---------------------------------------- */
/* Una ausencia por decidir, una corrección del registro. No es un renglón: lleva dentro lo que
   ESCRIBIÓ una persona —«tengo médico el jueves»— y eso es justo lo que decide la respuesta,
   así que necesita sitio para citarlo entero y no cabe en una celda.

   A la izquierda la cifra que se mira primero al aprobar —cuántos días son, qué día es—; en el
   centro quién, de qué y lo que dijo; a la derecha la decisión. Sale de la pantalla de
   ausencias, que fue la primera en pasarse al libro, y ahora vive aquí para que la usen todas
   las que preguntan lo mismo. */
.peticion { display: grid; grid-template-columns: 110px 1fr auto; gap: 0 var(--e5);
            align-items: start; padding: var(--e5) 0; border-bottom: 1px solid var(--linea); }
.peticion .cifra { font-size: var(--t-xxg); font-weight: 800; letter-spacing: -.03em;
                   line-height: 1; font-variant-numeric: tabular-nums; }
.peticion .cifra small { display: block; font-size: var(--t-xs); font-weight: 600;
                         letter-spacing: .04em; text-transform: uppercase; color: var(--ink3);
                         margin-top: var(--e1); }
.peticion .quien { font-size: var(--t-g); font-weight: 700; }
.peticion .quien a { color: inherit; text-decoration: none; }
.peticion .quien a:hover { text-decoration: underline; text-underline-offset: 3px; }
/* La etiqueta de qué clase de petición es, pegada al nombre: vacaciones y baja no se deciden
   igual, y eso se sabe antes de leer nada más. */
.peticion .tipo { display: inline-block; font-size: var(--t-xs); font-weight: 700;
                  padding: 2px 7px; border-radius: var(--r-xs); margin-left: var(--e2);
                  vertical-align: 2px; background: var(--panel-2); color: var(--ink2); }
.peticion .tipo.es-vacaciones { background: var(--ink); color: var(--panel); }
.peticion .tipo.es-permiso    { background: var(--acento-suave); color: var(--acento-legible); }
.peticion .tipo.es-baja       { background: var(--grave-suave); color: var(--grave); }
.peticion .cuando { font-size: var(--t-m); color: var(--ink2); margin-top: 3px; }
/* Lo que escribió la persona, citado tal cual y con su raya: se distingue de lo que dice el
   sistema, y es lo que se lee antes de contestar. */
.peticion q { display: block; quotes: "«" "»"; margin-top: var(--e3); padding-left: var(--e3);
              border-left: 2px solid var(--linea); color: var(--ink); }
.peticion .meta { font-size: var(--t-s); color: var(--ink3); margin-top: var(--e3); }
.peticion .acciones { display: flex; gap: var(--e2); align-items: center; flex-wrap: wrap;
                      justify-content: flex-end; margin-left: 0; }
.peticion .acciones input[type="text"] { width: 200px; }
@media (max-width: 900px) {
  .peticion { grid-template-columns: 90px 1fr; }
  .peticion .acciones { grid-column: 2; justify-content: flex-start; margin-top: var(--e3); }
}

/* ---------- El epígrafe: el título de un bloque -------------------------------------------- */
/* Letra pequeña en mayúsculas con una regla de 2 px debajo. Separa sin pesar: un `<h2>` de
   los de antes competía con el titular de la pantalla, y una tarjeta alrededor lo habría
   convertido en otra caja. A la derecha, el recuento o la aclaración, en minúsculas: es
   dato, no rótulo. */
/* El rótulo a la izquierda y su explicación a la derecha, en la misma línea. Con
   `flex-wrap`, porque en una pantalla estrecha la explicación no cabe al lado y sin esto se
   salía por la derecha arrastrando la página entera: medido en la ficha de un proveedor, la
   línea «el precio de hoy · en verde, en lo que nadie lo mejora» llegaba a 450 px de un ancho
   de 390. Al envolver, la explicación cae debajo del rótulo, que es donde se lee igual. */
/* Desde el 27/09/2026 el epígrafe es un título de verdad —letra normal, tamaño de título—
   y lo separa el AIRE de arriba, no una raya negra de 2 px. Menos tinta (27/09/2026, propuesta «El hilo del encargo»): con seis apartados, seis rayas negras iguales y el ojo no sabía dónde acababa un grupo. La raya que queda es
   la fina de siempre, y la explicación va pegada al título, no al otro extremo de la línea,
   donde nadie la lee junto a lo que explica. */
.epigrafe { display: flex; align-items: baseline; justify-content: flex-start;
            flex-wrap: wrap; gap: 0 var(--e4); margin: var(--e8) 0 0;
            padding-bottom: var(--e3);
            border-bottom: 1px solid var(--linea); font-size: var(--t-g); font-weight: 700;
            letter-spacing: -.01em; }
.epigrafe span, .epigrafe .nota { font-weight: 500; letter-spacing: 0; text-transform: none;
                                  color: var(--ink3); font-size: var(--t-m);
                                  min-width: 0; overflow-wrap: anywhere; }

/* ---------- La segunda hoja --------------------------------------------------------------- */
/* Lo que se mira DESPUÉS de la lista: el reparto por obras, «qué hacer con esto». Dos
   columnas, sin caja, separadas por aire y no por bordes. */
.hoja { margin-top: var(--e8); display: grid; grid-template-columns: 1.1fr .9fr;
        gap: 0 var(--e8); align-items: start; }
.hoja.iguales { grid-template-columns: 1fr 1fr; }
/* Con una sola cosa que poner, una sola columna. Una hoja de dos con la mitad vacía se lee
   como si faltara algo, y el bloque bueno queda arrinconado contra el borde derecho. */
.hoja.una { grid-template-columns: 1fr; }
.hoja > div > .epigrafe:first-child { margin-top: 0; }

/* El renglón pequeño de la segunda hoja: nombre, contexto e importe. */
.renglon.menor { grid-template-columns: 1fr auto auto; gap: 0 var(--e6);
                 padding: var(--e4) 0; }
.renglon.menor b { font-size: var(--t-b); font-weight: 600; }
.renglon.menor .contexto { display: block; font-size: var(--t-s); color: var(--ink3);
                          margin-top: 2px; }
.renglon.menor .dinero { font-size: var(--t-g); font-weight: 800; letter-spacing: -.02em;
                         min-width: 110px; }
/* `minmax(0, 1fr)` y no `1fr`: un `1fr` no baja de su contenido mínimo, así que un nombre
   largo empuja el importe fuera de la pantalla en vez de partirse. Y en un móvil el importe
   suelta sus 110 px de ancho mínimo, que ahí son casi un tercio de la pantalla. */
.renglon.menor { grid-template-columns: minmax(0, 1fr) auto auto; }
@media (max-width: 620px) { .renglon.menor .dinero { min-width: 0; } }
/* La cifra del renglón pequeño también se tiñe: en la portada, un euro parado y una orden
   fuera de plazo duelen distinto, y el color lo dice antes de leer el rótulo. */
.renglon .dinero.es-grave { color: var(--grave); }
.renglon .dinero.es-aviso { color: var(--acento-legible); }
.renglon .dinero.es-ok    { color: var(--ok); }

/* La ficha del expediente: la misma pareja clave/valor de `.datos`, pero separada por la
   regla de 1 px del libro en vez de por aire. En un expediente hay ocho o diez datos
   seguidos y sin regla se leen como un párrafo en dos columnas; con ella, cada uno es una
   línea que se busca con el dedo. La etiqueta va en mayúsculas pequeñas: es un rótulo, no un
   dato, y así no compite con lo que vale. */
.datos.reglada { gap: 0; }
.datos.reglada > div { padding: var(--e4) 0; border-bottom: 1px solid var(--linea);
                       grid-template-columns: 150px minmax(0, 1fr); align-items: start; }
.datos.reglada .et { font-size: var(--t-s); font-weight: 600; text-transform: uppercase;
                     letter-spacing: .04em; color: var(--ink3); padding-top: 2px; }
.datos.reglada small { display: block; color: var(--ink3); font-size: var(--t-s); }

/* LA CIFRA DEL DOCUMENTO, al lado del titular. Sustituye a la tira de cuadros que encabezaba
   los expedientes —Base, IVA, Total, Válido hasta en un presupuesto; Llevada, Desviación,
   Entrega, Ahora mismo en una orden de taller—. Cuatro cuadros pesan lo mismo y solo se mira
   uno; aquí ese va en grande y el resto debajo, en una línea, como en el pie de una factura
   de papel.
   No siempre es dinero: en una orden son las horas llevadas, y en un cliente lo facturado. */
.cifra-cabecera { text-align: right; }
.cifra-cabecera .total { font-size: var(--t-xg); font-weight: 700; letter-spacing: -.02em;
                         line-height: 1; font-variant-numeric: tabular-nums; }
.cifra-cabecera .total.es-grave { color: var(--grave); }
.cifra-cabecera .total.es-aviso { color: var(--acento-legible); }
.cifra-cabecera .desglose { font-size: var(--t-s); color: var(--ink3); margin-top: var(--e2);
                            font-variant-numeric: tabular-nums; }
@media (max-width: 760px) { .cifra-cabecera { text-align: left; } }

/* La cifra dentro del lede. En una lista la cifra que duele va en el renglón, pero en un
   EXPEDIENTE no hay lista: la cosa es una sola y su cifra —«lleva 15 días esperando»— vive
   en la frase. Se marca igual que en el `h1`, con las mismas tres respuestas.
   Va apuntado a `.sub` y no suelto a `.es-aviso`: esos modificadores ya significan otra cosa
   en las métricas y en los chips —borde, fondo—, y una regla global de color se los llevaría
   por delante. */
.sub .es-aviso, .afirmacion .es-aviso, .cierre .es-aviso, main td .es-aviso { color: var(--acento-legible); }
.sub .es-grave, .afirmacion .es-grave, .cierre .es-grave, main td .es-grave { color: var(--grave); }
.sub .es-ok,    .afirmacion .es-ok,    .cierre .es-ok,    main td .es-ok    { color: var(--ok); }
/* La celda de una tabla, también: una variación de precio es «+12 %» o «−4 %», y el signo
   solo es legible de un vistazo si lleva su color. Iba escrito a mano con un `style=` dentro
   de la plantilla de la tarifa, que es la manera de que el día que cambie el token de rojo
   ese sitio se quede con el anterior.
   El cierre entra en la misma regla por el mismo motivo. Es la suma de la pantalla —«hay
   34.025,28, entran 5.497,90, salen 52.357,36, quedarían 4.214,94»— y ahí el signo del
   número es lo que lo hace legible de un vistazo: sin esto, la cifra que entra y la que sale
   salían las dos en tinta y había que leer el rótulo de debajo para saber cuál era cuál. */

/* La vuelta atrás, al pie del expediente. Es un enlace, no un botón: no hace nada, deshace
   el paso de haber entrado. Iba del color de la empresa —o sea, rojo en GSN— y a la altura
   de un botón, así que la salida pesaba lo mismo que la acción principal de la pantalla. */
.btn.suelto { color: var(--ink2); text-decoration: underline; text-underline-offset: 3px;
              font-weight: 500; padding-left: 0; }
.btn.suelto:hover { background: transparent; color: var(--ink); }

/* La frase que dice qué se hace, arriba de su explicación. En la columna derecha de un
   expediente hay una decisión por bloque, y esa decisión se lee en una línea: la explicación
   de debajo es para quien la necesite, no para quien ya sabe a qué venía. */
.afirmacion { font-size: var(--t-g); margin-bottom: var(--e3); }
.epigrafe + .afirmacion { margin-top: var(--e4); }
.afirmacion + .sub { margin-top: 0; }

/* ---------- El cierre de la pantalla ------------------------------------------------------- */
/* Ni la lista vacía ni el final de la lista dicen «no hay nada»: dicen qué hacer, y llevan la
   salida al lado. Un vacío que solo informa de su vacío deja a quien llega sin siguiente paso. */
.cierre { margin-top: var(--e7); padding: var(--e5) var(--e6); background: var(--panel);
          border: 1px solid var(--linea); border-radius: var(--r);
          display: flex; justify-content: space-between; align-items: center;
          gap: var(--e5); flex-wrap: wrap; }
/* A HIJO DIRECTO, no a descendiente. La misma lección que el `.chip` del renglón: `.cierre b`
   alcanzaba también a una negrita dentro de la explicación —«solo los módulos
   **encendidos**»— y la convertía en bloque, así que la palabra saltaba a su propia línea y
   partía la frase en tres. El `b` que manda aquí es el rótulo del cierre, que es hijo. */
.cierre > div > b { display: block; font-size: var(--t-b); }
.cierre > div > span { display: block; color: var(--ink2); font-size: var(--t-m);
                       margin-top: 2px; }

/* Una línea suelta dentro del libro: «Nada que enseñar en este filtro». Sin caja, con la
   misma regla de 1 px que los renglones, para que el ritmo de la lista no se rompa. */
.renglon-vacio { padding: var(--e5) 0; font-size: var(--t-m); color: var(--ink2);
                 border-bottom: 1px solid var(--linea); }
.renglon-vacio b { display: block; color: var(--ink); }

/* ---------- Respuesta al ancho ------------------------------------------------------------- */
/* Un renglón de cinco columnas en 1100 px deja la fecha en dos renglones y el importe pegado
   al botón. Antes de que eso pase, las tres últimas columnas se van a una segunda línea: se
   sigue leyendo de izquierda a derecha y no aparece scroll lateral, que en esta casa no se
   permite en escritorio.

   AQUÍ VAN TODAS LAS VARIANTES, una por una, y no vale con poner `.renglon` a secas. Una
   consulta de medios no sube la especificidad: `.renglon.cifra-ancha` son dos clases y
   `.renglon` una, así que la variante gana esté donde esté escrita y la pantalla se queda con
   sus cuatro columnas en 390 px. Se vio en el barrido: «Facturas por emitir», «Los días que
   se pasó» y «Precios de material» arrastraban la página entera de lado en un móvil, y la
   columna de la derecha caía a 502 px de un ancho de 390. Lo mismo con `.hoja.iguales`, que
   dejaba el escritorio en dos columnas de 178 px.

   Cada vez que se añada una variante de reparto arriba hay que añadirla aquí. No es una
   costumbre: hay un test que lo comprueba —`LaRejillaRespondeAlAnchoTest`— porque esto no
   falla en ningún sitio, solo se ve mirando la pantalla estrecha. */
@media (max-width: 1100px) {
  .renglon, .renglon.con-dinero, .renglon.con-dinero.acciones-fijas, .renglon.c4, .renglon.c3,
  .renglon.sin-cifra, .renglon.cifra-ancha, .renglon.c3.cifra-ancha, .renglon.con-casilla,
  .renglon.con-casilla.cifra-ancha, .renglon.con-casilla.sin-cifra {
    grid-template-columns: 100px 1fr 1fr; gap: var(--e3) var(--e5); }
  /* Y sin cabecera: aquí las filas ya no son columnas —la fecha, el importe y los botones se
     van a una segunda línea—, así que unos rótulos en fila serían rótulos de nada. */
  .renglon.cabecera { display: none; }
  /* Menos la que ordena: sin ella no habría con qué elegir el orden. Se queda como una línea
     de rótulos pulsables, sin los que no ordenan. */
  .renglon.cabecera.ordena-columnas { display: flex; flex-wrap: wrap; gap: var(--e2) var(--e5); }
  .renglon.cabecera.ordena-columnas > span:not(:has(a.ordena)) { display: none; }
  .renglon.con-casilla, .renglon.con-casilla.cifra-ancha, .renglon.con-casilla.sin-cifra {
    grid-template-columns: 26px 100px 1fr; }
  /* 100 px no dan para lo que va en esa primera columna, y aquí no se sale nada de la
     página: se pinta un texto ENCIMA del de al lado, que ninguna medida de scroll ve.
     «120.451,14 €» tapaba el nombre del cliente y «Administración» salía escrito sobre
     «Administración de Lunanorte» en Equipo y accesos. Una palabra sola no tiene por dónde
     partirse, así que se aplica la misma pareja de arriba: ensanchar la columna a 150 px
     —lo que pide el contenido medido, no lo que parezca— y encoger la letra de la variante
     sin cifra, que es la que lleva palabras y no números.

     Ancho fijo y no `max-content`: cada renglón es su propia rejilla, así que con
     `max-content` cada fila cogería un ancho distinto y los nombres de la lista dejarían de
     estar en la misma vertical. */
  .renglon, .renglon.con-dinero, .renglon.con-dinero.acciones-fijas, .renglon.c4, .renglon.c3,
  .renglon.cifra-ancha, .renglon.c3.cifra-ancha {
    grid-template-columns: 150px 1fr 1fr; }
  /* Cuatro columnas y no tres: con tres, el cuarto dato del renglón —`.que`, que no lleva
     ninguna de las clases que saltan de línea— caía en la columna de la casilla, 26 px, y
     «Se compensa con descanso» salía en cuatro renglones de una palabra. Se ve en «Horas de
     más», que es donde un renglón con casilla lleva además un estado escrito. */
  .renglon.con-casilla, .renglon.con-casilla.cifra-ancha {
    grid-template-columns: 26px 150px 1fr 1fr; }
  .renglon .espera.sin { font-size: var(--t-g); }
  /* Y la variante que NO tiene cifra: su primera columna es el nombre, no un número, así que
     los 100 px de la regla de arriba se lo comían. En el buscador —que se abre desde la barra
     de todas las pantallas— «P2026-023 · Construcciones del Norte, S.L.» salía en cuatro
     renglones dentro de 100 px con dos tercios de la fila en blanco al lado. */
  .renglon.sin-cifra { grid-template-columns: 1.6fr 1fr; }
  .renglon.con-casilla.sin-cifra { grid-template-columns: 26px 1.6fr 1fr; }
  .renglon .cuando, .renglon .acciones, .renglon .dinero { grid-column: 2 / -1; }
  .renglon .dinero { text-align: left; }
  /* El renglón pequeño se queda como está y por eso se nombra: `1fr auto auto` ya cabe en
     390 px —el nombre se encoge, el importe y la flecha ocupan lo suyo— y partirlo en tres
     líneas convierte una lista de ocho avisos en una pantalla de puro desplazamiento. Lo que
     sí hay que deshacer aquí es el salto de columna de la regla de al lado, que le mandaba el
     importe a una línea propia debajo del nombre. */
  .renglon.menor { grid-template-columns: 1fr auto auto; }
  .renglon.menor .dinero, .renglon.menor .acciones, .renglon.menor .cuando { grid-column: auto; }
  .hoja, .hoja.iguales, .hoja.una { grid-template-columns: 1fr; gap: var(--e7); }
}
@media (max-width: 760px) {
  /* Con TODAS las del bloque de 1100 px: `.con-dinero.acciones-fijas` (Emitidas) y
     `.c3.cifra-ancha` (el portal) faltaban aquí y se quedaban con las tres columnas de allí,
     el nombre y el concepto partidos letra a letra en noventa píxeles (28/09/2026). */
  .renglon, .renglon.con-dinero, .renglon.con-dinero.acciones-fijas, .renglon.c4, .renglon.c3,
  .renglon.sin-cifra, .renglon.cifra-ancha, .renglon.c3.cifra-ancha, .renglon.con-casilla,
  .renglon.con-casilla.cifra-ancha, .renglon.con-casilla.sin-cifra {
    grid-template-columns: 1fr; }
  /* La casilla, a la izquierda del todo y no centrada en su propia línea: en una lista de
     once cosas que marcar se marcan de arriba abajo, y para eso tienen que estar en la misma
     vertical. */
  .renglon .casilla { place-items: center start; }
  .renglon .cuando, .renglon .acciones, .renglon .dinero { grid-column: 1; }
  /* El renglón pequeño se queda como está y por eso se nombra: `1fr auto auto` ya cabe en
     390 px —el nombre se encoge, el importe y la flecha ocupan lo suyo— y partirlo en tres
     líneas convierte una lista de ocho avisos en una pantalla de puro desplazamiento. Lo que
     sí hay que deshacer aquí es el salto de columna de la regla de al lado, que le mandaba el
     importe a una línea propia debajo del nombre. */
  .renglon.menor { grid-template-columns: 1fr auto auto; }
  .renglon.menor .dinero, .renglon.menor .acciones, .renglon.menor .cuando { grid-column: auto; }
  .renglon .acciones { justify-content: flex-start; }
}

/* ---------- Una tabla ancha --------------------------------------------------------------- */
/* La tabla que no cabe se desplaza DENTRO de su envoltorio; la página, nunca. En escritorio
   no se desplaza ninguna —la regla de la casa es que el cuadro se vea entero— pero en un
   móvil una tabla de cinco columnas de dinero no cabe de ninguna manera, y la alternativa es
   partir cada celda en cuatro líneas hasta que la fila mida media pantalla.

   Se escribe `<div class="tabla-ancha"><table>…</table></div>` alrededor de la tabla. */
.tabla-ancha { overflow-x: auto; }

/* ---------- Paginación --------------------------------------------------------------------- */
.paginas { display: flex; gap: var(--e5); align-items: center; justify-content: center;
           margin-top: var(--e5); font-size: var(--t-m); color: var(--ink2); }

/* ---------- Impresión ---------------------------------------------------------------------- */
@media print {
  aside, .no-imprimir, .btn { display: none !important; }
  body { background: #fff; }
  main { padding: 0; max-width: none; }
  .tarjeta { border: 0; box-shadow: none; padding: 0; }
}

/* ==========================================================================================
   El armazón: menú lateral y cuerpo de la página.

   Estaba en la plantilla base, con el resto. Aquí sirve además para las pantallas que no
   heredan de ella (el kiosco de la tablet, los documentos imprimibles): usan los mismos
   tokens y no vuelven a inventarse el aire de la aplicación.
   ========================================================================================== */

/* El fondo del lateral se pinta también en el cuerpo: el `aside` se queda fijo y mide una
   pantalla de alto, así que en una página larga se veía el papel claro por debajo de él.
   Con esto la columna oscura llega hasta abajo sin que el menú tenga que estirarse. */
body.con-menu { display: flex; min-height: 100vh;
                background: linear-gradient(to right, var(--lateral) 232px,
                                            var(--fondo) 232px); }

aside {
  width: 232px; flex: none;
  background: var(--lateral); color: var(--lateral-txt);
  border-right: 1px solid var(--lateral-linea);
  padding: var(--e5) var(--e4);
  display: flex; flex-direction: column;
  /* Se queda quieto y se desplaza por dentro: el pie —quién eres, el modo oscuro, salir— no
     puede desaparecer en cuanto la pantalla tiene contenido. */
  position: sticky; top: 0; align-self: flex-start; height: 100vh;
}
aside nav { flex: 1; overflow-y: auto; min-height: 0; display: flex; flex-direction: column;
            gap: 2px; }

/* La versión, al fondo del lateral. `nav` se queda con el espacio sobrante (flex: 1), así
   que esto cae solo al fondo sin posicionar nada. Tabular para que no baile al cambiar. */
aside .pie-lateral { flex: none; padding: var(--e3) var(--e3) 0; color: var(--lateral-txt-2);
                     font-size: var(--t-xs); font-variant-numeric: tabular-nums; }

/* Ojo con el alcance: `marca` y `quien` son palabras que también usan la pantalla de entrada
   y la de la tablet para otra cosa. Estas reglas son las del menú lateral y solo suyas. */

/* La marca, arriba del todo. Con logo va el logo SOLO y a lo ancho de la columna: es la firma
   de la casa y ya dice el nombre; encajado en 32 px con el rótulo al lado no se reconocía.
   Sin logo, el cuadrado del color de la empresa y su nombre. Pinchar lleva a la ficha de la
   empresa (a quien puede editarla) o al inicio, y por eso se ilumina al pasar: es un sitio. */
aside .marca { display: flex; align-items: center; gap: var(--e3);
               margin-bottom: var(--e5); padding: var(--e3); border-radius: var(--r-s);
               text-decoration: none; color: inherit;
               transition: background var(--transicion); }
aside .marca:hover { background: var(--lateral-2); }
aside .marca .punto { width: 32px; height: 32px; border-radius: 8px; background: var(--marca);
                      flex: none; }
/* El logo llega como llega: casi siempre un PNG con su fondo blanco. De día ese blanco se
   funde con el lateral (`multiply` deja ver el fondo a través del blanco). De noche se
   invierte y se gira el tono: los trazos oscuros pasan a claros conservando su color —el
   rojo sigue siendo rojo, más claro—, el blanco del archivo pasa a negro y `screen` lo hace
   desaparecer contra el lateral. Un solo archivo sirve para los dos modos, sin pedirle a
   ningún cliente una versión oscura de su logo. */
/* El logo, dentro de una placa blanca. El lateral es oscuro, y un logo hecho para papel
   blanco encima de un gris casi negro se ve como una pegatina: es lo que hizo que este
   rail se probara oscuro una vez y se volviera claro. La placa lo resuelve sin pedirle a
   ningún cliente una versión de su logo para fondo oscuro. */
/* A lo ancho de la columna, como dice el comentario de arriba y como NO estaba: la regla
   ponía 44x44 px. Un logo apaisado —el de un taller suele serlo, 1,6:1 es lo normal— metido
   en un cuadrado de 44 se queda en unos 36x22 px reales, del tamaño de un icono del menú.
   Deja de ser la firma de la casa y pasa a ser una pegatina que nadie reconoce.

   La intención estaba escrita en el comentario de esta misma regla y en el de la plantilla,
   las dos veces con las mismas palabras: «el logo SOLO y a lo ancho de la columna». Solo
   faltaba que el código dijera lo mismo.

   El lateral mide 232 px con 12 de aire a cada lado, y la placa se come 8 más: quedan 192
   para el logo, que a 1,6:1 son 120 de alto. `max-height` corta ahí los logos cuadrados o
   verticales, que si no se comerían media columna. Y `max-width` es para el móvil, donde el
   lateral pasa a ocupar todo el ancho y sin tope el logo saldría gigante. */
aside .marca img.punto { width: 100%; max-width: 200px; height: auto; max-height: 96px;
                         flex: none; object-fit: contain;
                         background: #fff; border-radius: 8px; padding: var(--e3);
                         mix-blend-mode: normal; }
header img.punto { background: none; object-fit: contain; }
aside .marca strong { font-size: var(--t-b); line-height: 1.2; display: block;
                      color: var(--lateral-txt); }
aside .marca small { display: block; color: var(--lateral-txt-2); font-size: var(--t-xs); }

/* Una sección: icono y nombre. El icono NUNCA va solo —un menú de dibujos obliga a adivinar—
   y el nombre nunca va sin icono: a media distancia se reconoce antes la forma que la
   palabra, y a los dos días se pincha sin leer. */
aside nav a.seccion { display: flex; align-items: center; gap: var(--e3);
                      padding: 9px var(--e3); border-radius: var(--r-s);
                      color: var(--lateral-txt-2); text-decoration: none;
                      font-size: var(--t-m); font-weight: 500;
                      transition: background var(--transicion), color var(--transicion); }
aside nav a.seccion svg { width: 19px; height: 19px; flex: none; fill: none;
                          stroke: currentColor; stroke-width: 1.8; stroke-linecap: round;
                          stroke-linejoin: round; }
aside nav a.seccion:hover { background: rgba(255, 255, 255, .06); color: var(--lateral-txt); }
/* La sección puesta: un bloque claramente más claro que el rail y el icono del color del
   acento. Antes el bloque era el mismo que el del ratón encima (`--lateral-2`), así que al
   mover el ratón por el lateral había dos filas iguales y ninguna decía «estás aquí»; y
   llevaba una raya naranja a la izquierda, que Daniel quitó el 15/09/2026: con el bloque y
   el icono ya se ve, y la raya era un tercer aviso. Sigue sin ser un bloque del color de la
   empresa: el acento es de la herramienta, no del taller, y no compite con la marca. */
aside nav a.seccion.activa { background: rgba(255, 255, 255, .14); color: #fff;
                             font-weight: 600; }
aside nav a.seccion.activa svg { color: var(--acento); }
/* La ayuda es la última sección del lateral, pegada a Configuración y con su mismo aspecto
   (Daniel, 15/09/2026): no lleva nada propio. */

.tema { background: none; border: 0; padding: 0; font: inherit; color: inherit;
        text-decoration: underline; cursor: pointer; }

/* ---------- La franja de arriba ------------------------------------------------------------ */
/* De lado a lado y con su línea: se lee como el marco de la aplicación —dónde buscas, quién
   eres— y no compite con el contenido. Va pegada arriba: buscar es lo que más se hace y no
   puede quedarse atrás al bajar por una tabla de cuarenta filas. */
/* Va de lado a lado de lo que se ve —fuera del ancho de lectura, que es cosa de `.pantalla`—
   en tres columnas: quién eres, el buscador y las tres acciones. Las dos de los lados crecen
   igual, así que el buscador queda en el centro mientras hay sitio; y ninguna baja de lo que
   ocupa su contenido, así que nada se monta encima de nada.

   Antes el nombre y las acciones iban posados en absoluto, fuera de la fila, para no
   descentrar el buscador. En una pantalla ancha funcionaba; desde 1.180 px el buscador se
   ponía encima del botón de fichar —«Fichar entrad»—, y a 900 encima del nombre. Un elemento
   fuera de la fila no le quita sitio a nadie, y por eso tampoco se lo respeta nadie. Lo vio
   Andrés el 11/09/2026 encogiendo la ventana, y lo mide `tests_barra`. */
.barra { display: grid; align-items: center; gap: var(--e3) var(--e5);
         grid-template-columns: minmax(max-content, 1fr) minmax(16rem, 440px)
                                minmax(max-content, 1fr);
         background: var(--panel); border-bottom: 1px solid var(--linea);
         padding: var(--e4) var(--e7);
         position: sticky; top: 0; z-index: 20; }
.barra .buscador { grid-column: 2; width: 100%; }
/* Quién está dentro y con qué papel, siempre a la vista. El nombre lleva a la ficha de la
   persona cuando algún módulo encendido la aporta (gancho «nucleo.ficha_personal»). El papel
   va debajo, más pequeño: dice qué puede tocar quien está mirando, y antes vivía abajo a la
   izquierda, lejos de la persona a la que se refiere. */
/* La esquina de la izquierda son DOS cosas: quién eres y el botón de fichar. */
.barra .quien-soy { grid-column: 1; justify-self: start;
                    display: flex; align-items: center; gap: var(--e3); min-width: 0; }
.barra .yo { max-width: 15rem; color: var(--ink); line-height: 1.2; min-width: 0; }
.barra .yo a, .barra .yo > span { color: inherit; text-decoration: none; display: block; }
.barra .yo a:hover .yo-nombre { color: var(--marca-legible); text-decoration: underline; }
.barra .yo .yo-nombre { display: block; font-size: var(--t-m); font-weight: 600;
                        white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.barra .yo .yo-rol { display: block; font-size: var(--t-xs); font-weight: 400;
                     color: var(--ink2); white-space: nowrap; overflow: hidden;
                     text-overflow: ellipsis; }
/* Debajo del nombre, solo el papel. La línea «Sin fichar» / «Dentro desde las 08:12» que
   iba a su lado se quitó el 11/09/2026: decía lo mismo que el botón de fichar —que ya lleva
   el estado en su punto, hueco fuera y lleno dentro— y parecía otro botón. Era un enlace a
   «Mi jornada», y quien lo pulsaba para fichar veía que «no hacía nada». La hora de entrada
   va ahora en el título del botón y en lo que lee el lector de pantalla. */

/* Las tres acciones que no son de ninguna pantalla —tema, ayuda y salir—, agrupadas a la
   derecha y simétricas al nombre de la izquierda, con el buscador centrado entre las dos.
   Antes el tema y salir estaban plegados abajo a la izquierda: había que desplegar un bloque
   para apagar la luz. */
.barra .acciones { grid-column: 3; justify-self: end;
                   display: flex; align-items: center; gap: var(--e2); }
/* Cuando no caben las tres columnas en una fila, el buscador baja a la segunda, de lado a
   lado, y arriba se quedan quién eres —con su botón— y las acciones. La cuenta es con lo
   peor que puede traer la fila: un nombre de 10rem, el botón de fichar y los cuatro
   redondos de quien ve el panel del proveedor. Con eso, por encima de 1.100 px cabe. */
@media (max-width: 1280px) { .barra .yo { max-width: 10rem; } }
@media (max-width: 1100px) {
  .barra { grid-template-columns: minmax(0, 1fr) auto; }
  .barra .quien-soy { grid-column: 1; grid-row: 1; }
  .barra .acciones { grid-column: 2; grid-row: 1; }
  .barra .buscador { grid-column: 1 / -1; grid-row: 2; max-width: none; }
}
.barra .acciones .ayuda-boton,
.barra .acciones .boton-barra,
.barra .acciones .tema { width: 34px; height: 34px; padding: 0; border-radius: 50%;
                         display: inline-flex; align-items: center; justify-content: center;
                         color: var(--ink2); border: 1px solid var(--linea-2);
                         background: var(--panel); cursor: pointer; flex: none; }
.barra .acciones svg { width: 18px; height: 18px; fill: none; stroke: currentColor;
                       stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
.barra .acciones .ayuda-boton:hover,
.barra .acciones .boton-barra:hover,
.barra .acciones .tema:hover { color: var(--marca-legible); border-color: var(--marca-borde); }
/* En la barra el conmutador es solo icono: el rótulo lo sigue llevando donde haga falta. */
.barra .acciones .tema .tema-texto { position: absolute; width: 1px; height: 1px;
                                     overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.barra .acciones .tema .tema-icono { width: 18px; height: 18px; display: block; }
/* Y con el dedo, los tres redondos de la barra crecen. Mismo criterio que el botón
   pequeño: 34 px es un objetivo cómodo para un puntero y escaso para una yema. Se sube
   solo bajo `pointer: coarse`, así que en escritorio la barra no cambia de alto.

   Lo cazó `manage.py cabe` barriendo las 153 pantallas: era el único control de toda la
   aplicación que se quedaba corto una vez arreglados los `.btn.chico`. */
@media (pointer: coarse) {
  .barra .acciones .ayuda-boton,
  .barra .acciones .boton-barra,
  .barra .acciones .tema { width: 44px; height: 44px; }
}

/* ---------- Las pestañas de la sección ------------------------------------------------------ */
/* Lo primero del contenido, y a propósito: dicen dónde estás y qué más hay al lado sin abrir
   nada. La línea gris recorre el ancho entero —así son una barra y no cinco enlaces sueltos—
   y la activa se marca con un trazo del color de la empresa.
   Subrayado y no pastilla: una pestaña con forma de botón invita a pulsarla esperando que
   haga algo, y esto solo cambia de pantalla. */
/* Las pestañas continúan el blanco de la franja de arriba: buscar y moverse son la misma
   cosa —el marco— y se leen mejor como un solo bloque que como dos rayas sueltas. Debajo
   empieza el papel, y ahí ya está el contenido. */
.pestanas { display: flex; gap: var(--e2); background: var(--panel);
            border-bottom: 1px solid var(--linea);
            padding: var(--e3) calc(var(--e7) - var(--e4));
            overflow-x: auto; }

/* El título a la izquierda y la acción principal a su derecha, como se espera y sin tocar
   ni una plantilla. Se hace con `float`, que es justo para esto —saca el botón del flujo y
   deja que el título ocupe su sitio a la izquierda—; con rejilla había que adivinar en qué
   fila cae cada cosa, y bastaba una pantalla sin subtítulo para que el botón se subiera
   encima del título. Todo lo que viene después baja del todo (`clear`). */
/* Ancho de lectura, no de pantalla: una tabla de siete columnas necesita sitio, y un texto
   de 1.600 px de ancho no se lee. 1.360 es el punto en que caben las tablas del sistema sin
   que los párrafos se conviertan en renglones interminables. El tope va aquí, en el
   contenido, y no en `main`: las dos franjas de arriba (buscador y pestañas) tienen que ir
   de lado a lado de lo que se ve, si no el buscador queda centrado en una columna y no en la
   pantalla, y en un monitor ancho se nota. */
.pantalla { max-width: 1360px; padding: var(--e6) var(--e7) var(--e8); }
.pantalla > details.crear:not([open]) { float: right; margin: 0 0 var(--e4) var(--e5); }
.pantalla > *:not(h1):not(.sub):not(details.crear) { clear: both; }
/* Con cabecera propia (título + acciones a la derecha) el botón no flota: allí ya hay un
   sitio hecho para las acciones y se pisarían. */
.pantalla:has(> .cabecera) > details.crear:not([open]) { float: none; margin-left: 0; }
/* El segundo piso se marca con un TRAZO, no con un bloque.

   Tuvo bloque de color, para que las dos alturas de la navegación tuvieran la misma forma.
   La idea era buena y el resultado, no: con el bloque, una pestaña y el botón de acción
   principal eran el mismo rectángulo del color de la empresa a diez centímetros uno de otro,
   así que la pantalla ofrecía dos cosas idénticas de las que solo una hace algo. En GSN, que
   es roja, además coincidía con el color que en esta casa significa «dinero parado».

   La forma común entre los dos pisos se mantiene por donde importa —el mismo sitio, el mismo
   orden, el mismo rótulo—, y lo que los distingue es el nivel: bloque relleno arriba en el
   lateral, subrayado de 3 px aquí. Es la misma regla que ya usa el panel del proveedor.

   Sin icono: en el lateral el icono ayuda a encontrar una sección entre nueve de un vistazo;
   aquí son cuatro o cinco palabras en una línea que ya se lee entera, y el icono solo añade
   ruido delante de cada una. */
.pestanas a { display: inline-flex; align-items: center;
              padding: var(--e3) var(--e2) var(--e4); margin: 0 var(--e4) -1px 0;
              border-bottom: 3px solid transparent;
              color: var(--ink2); text-decoration: none; font-size: var(--t-m);
              font-weight: 600; white-space: nowrap; letter-spacing: -.005em;
              transition: color var(--transicion), border-color var(--transicion); }
.pestanas a:hover { color: var(--ink); border-bottom-color: var(--linea-2); }
.pestanas a.activa { color: var(--ink); border-bottom-color: var(--ink); }
/* Pestañas DE una pantalla (VeriFactu dentro de Facturas, el registro dentro del control
   horario): la misma forma que las de la sección —que no haya dos maneras de lo mismo—,
   pero dentro del contenido, sin comerse los márgenes ni el fondo de la franja de arriba. */
.pestanas.dentro { margin: 0 0 var(--e5); padding: 0 0 var(--e3); background: none; }

/* ---------- El buscador ------------------------------------------------------------------ */
/* Va arriba del contenido y con sitio para un nombre entero, un número de factura o una
   dirección; pero sin mandar en la franja. Llegó a 560 px con borde marcado y sombra, y
   era lo primero que se veía de cada pantalla (Daniel, 15/09/2026): ahora 440, el borde
   del color de las líneas y sin sombra hasta que se escribe en ella. */
.buscador { position: relative; flex: 1 1 auto; max-width: 440px; }
.buscador input { width: 100%; padding: 8px 36px 8px 36px; border-radius: var(--r-s);
                  border: 1px solid var(--linea); background: var(--panel-2);
                  font-size: var(--t-m); color: var(--ink); }
.buscador input:focus { background: var(--panel); box-shadow: var(--sombra); }
.buscador input::placeholder { color: var(--ink3); }
.buscador input:focus { outline: 2px solid var(--marca-borde); outline-offset: -1px; }
.buscador input::-webkit-search-cancel-button { cursor: pointer; }
/* La lupa, dibujada con dos formas: no hace falta una fuente de iconos para un círculo y una
   raya. */
.buscador .lupa { position: absolute; left: 12px; top: 50%; transform: translateY(-50%);
                  width: 16px; height: 16px; pointer-events: none; fill: none;
                  stroke: var(--ink3); stroke-width: 2; stroke-linecap: round; }
.buscador kbd { position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
                font: inherit; font-size: var(--t-xs); color: var(--ink3);
                border: 1px solid var(--linea-2); border-radius: 4px; padding: 0 5px;
                pointer-events: none; background: var(--panel-2); }
.buscador input:focus ~ kbd { display: none; }
.buscador .resultados { position: absolute; z-index: 30; left: 0; right: 0; top: 100%;
                        margin-top: 6px; background: var(--panel);
                        border: 1px solid var(--linea-2); border-radius: var(--r);
                        box-shadow: var(--sombra-2); max-height: 66vh; overflow-y: auto;
                        padding: var(--e3); }
.buscador .resultados .rotulo { font-size: var(--t-xs); text-transform: uppercase;
                                letter-spacing: .06em; color: var(--ink3); font-weight: 700;
                                padding: var(--e3) var(--e3) var(--e1); }
.buscador .resultados a { display: flex; align-items: baseline; gap: var(--e3);
                          padding: 8px var(--e3); border-radius: var(--r-xs);
                          text-decoration: none; color: var(--ink); }
.buscador .resultados a strong { font-size: var(--t-b); font-weight: 600; flex: none;
                                 max-width: 46%; overflow: hidden; text-overflow: ellipsis;
                                 white-space: nowrap; }
.buscador .resultados a span { font-size: var(--t-s); color: var(--ink2); overflow: hidden;
                               text-overflow: ellipsis; white-space: nowrap; }
.buscador .resultados a:hover, .buscador .resultados a.puesto { background: var(--marca-suave);
                                                                color: var(--marca-legible); }
.buscador .resultados a.puesto span { color: var(--marca-legible); }
.buscador .resultados .nada { padding: var(--e4); color: var(--ink2); font-size: var(--t-m); }
/* Lo último que has abierto lleva al lado solo qué es: el título, casi toda la anchura. */
.buscador .resultados a.abierta strong { max-width: 80%; }
/* Lo que se empieza desde la caja vacía: botones en una fila, no renglones. */
.buscador .resultados .crear { display: flex; flex-wrap: wrap; gap: var(--e2);
                               padding: var(--e1) var(--e3) var(--e3); }
.buscador .resultados .crear a { display: inline-flex; padding: 6px 12px; font-size: var(--t-s);
                                 font-weight: 600; border: 1px solid var(--linea-2);
                                 border-radius: 999px; }

main { flex: 1; min-width: 0; }

/* --- En el móvil -------------------------------------------------------------------------
   Media plataforma se usa de pie y con una mano: fichar en obra, mirar tus horas, pedir una
   corrección. Con el menú lateral fijo, el contenido se quedaba en un palmo de ancho. */
@media (max-width: 780px) {
  body.con-menu { flex-direction: column; background: var(--fondo); }
  /* El lateral pasa a ser una tira horizontal arriba: en el móvil una columna de 232 px se
     come media pantalla. Las secciones se deslizan a lo ancho y el icono ayuda a
     reconocerlas de un vistazo, que es justo para lo que está. */
  aside { width: 100%; border-right: 0; padding: var(--e3) var(--e4);
          position: static; height: auto;
          flex-direction: row; flex-wrap: wrap; align-items: center; }
  aside .marca { flex: 1 1 auto; margin-bottom: 0; padding: 0; }
  aside .marca img.punto { width: auto; max-height: 40px; }
  aside nav { order: 2; flex: 1 1 100%; flex-direction: row; gap: var(--e2);
              overflow-x: auto; padding: var(--e3) 0 var(--e1); }
  aside nav a.seccion { white-space: nowrap; padding: 7px var(--e4);
                        background: var(--lateral-2); }
  .barra { position: static; padding: var(--e3) var(--e5); gap: var(--e3); }
  .barra .yo { max-width: none; }
  .pantalla { padding: var(--e5) var(--e5) var(--e7); max-width: none; }
  .pestanas { gap: var(--e2); padding: var(--e3) var(--e3); }
  h1 { font-size: var(--t-g); }
  /* La tabla se lleva su propio desplazamiento dentro, para que la página no se mueva.

     Va a CUALQUIER tabla del contenido y no solo a la que está dentro de una tarjeta, que es
     como estaba escrito. Al pasar las pantallas al libro las tarjetas desaparecieron, y con
     ellas este desplazamiento: la previsión semana a semana —cinco columnas de dinero— pasó a
     arrastrar la página entera de lado en un móvil. Una tabla ancha se desplaza dentro de sí
     misma; la página, nunca. La de clave/valor se queda como está: no tiene columnas que se
     salgan y como bloque perdería su reparto. */
  main table:not(.datos) { display: block; overflow-x: auto; }
  /* Y con envoltorio, que es lo bueno y lo que se pone en las tablas anchas de verdad: el que
     se desplaza es el `div`, y la tabla de dentro se queda a su ANCHO NATURAL. Sin eso, la
     tabla se mete a la fuerza en los 390 px, la última columna se queda en cuarenta, su
     contenido se parte palabra a palabra y la fila crece hasta doscientos píxeles de alto por
     un texto que además está fuera de la pantalla. Medido en la previsión semana a semana.
     La regla lleva `main` delante solo para ganarle en especificidad a la de arriba. */
  main .tabla-ancha > table { display: table; width: max-content; min-width: 100%; }
}

/* ---------- Los filtros con campos, en una linea ------------------------------------------ */
/* `.filtros` nacio para una tira de enlaces —«Ano: 2026 · 2025 · todas»— y aguantaba un
   desplegable suelto. Con cuatro campos dentro (cliente, desde, hasta, hito) se rompia: en
   los formularios de verdad `label` es `display:block` y `select` es `width:100%`, asi que
   cada campo caia en su propia linea y la barra de filtros ocupaba media pantalla POR ENCIMA
   de la lista que venia a filtrar. Medido en /facturacion/borradores/: 330 px de filtros
   antes del primer renglon.

   Aqui se deshacen esas dos reglas, y solo dentro de la barra. Sin colores nuevos. */
.filtros label, .filtros .et { display: inline-block; margin: 0 var(--e2) 0 0;
                               white-space: nowrap; }
.filtros select, .filtros input { width: auto; min-height: 34px; padding: 5px 9px;
                                  font-size: var(--t-s); }
.filtros input[type=date] { max-width: 9.5rem; }
.filtros input.importe-del-filtro { max-width: 7rem; text-align: right; }
.filtros select { max-width: 15rem; }


/* ---------- El editor: varias filas que se editan a la vez -------------------------------- */
/* El quinto tipo de pantalla del libro (LIBRO.md). Es lo que hay debajo de un formset: las
   partidas de una plantilla, los datos que describen un tipo de trabajo, las líneas de una
   nómina. Iban en `<table class="formset">`, y una tabla de campos no es una tabla: no se
   compara nada en vertical, cada celda es un control, y la cabecera de la tabla acababa
   haciendo de rótulo de un formulario, que es un trabajo que no le toca.

   Aquí es una rejilla, con las columnas declaradas por la pantalla que la usa —cada editor
   tiene las suyas— y los rótulos una sola vez arriba, como en un parte de trabajo. La regla
   de 2 px bajo la cabecera y la de 1 px bajo cada fila son las mismas del renglón, así que
   el editor y la lista se leen con el mismo ritmo.

   Los campos van a 36 px de alto y sin el `max-width` de los formularios: en un formulario
   un campo largo se lee mejor estrecho, pero aquí la anchura la manda la columna. */
.editor { margin-top: var(--e5); }
.editor .cabeza { display: grid; gap: var(--e3); padding: 0 0 var(--e3);
                  font-size: var(--t-xs); font-weight: 700; text-transform: uppercase;
                  letter-spacing: .06em; color: var(--ink3);
                  border-bottom: 2px solid var(--ink); }
.editor .fila { display: grid; gap: var(--e3); padding: var(--e3) 0;
                border-bottom: 1px solid var(--linea); align-items: center; }
.editor .fila input, .editor .fila select, .editor .fila textarea {
  max-width: none; width: 100%; min-height: 36px; padding: 5px 9px;
  font-size: var(--t-s); box-sizing: border-box; }
.editor .fila textarea { min-height: 36px; }
/* Las casillas —«obliga», «compara», «quitar»— centradas en su columna y sin estirarse: un
   `input[type=checkbox]` con `width:100%` se convierte en una barra. */
.editor .fila input[type=checkbox] { width: 20px; height: 20px; min-height: 0;
                                     margin: 0 auto; display: block; }
.editor .fila .num input { text-align: right; }
.editor .error { grid-column: 1 / -1; color: var(--grave); font-size: var(--t-s);
                 padding-bottom: var(--e3); }
/* El rótulo de cada campo, para cuando la cabecera no está. En escritorio los rótulos van
   una vez arriba y este no se ve; en pantalla estrecha la cabecera desaparece y cada campo
   cae en su línea, y sin él quedaban tres casillas seguidas —«1,00», vacía, «3850,00»— sin
   decir cuál es la cantidad y cuál el precio. El `aria-label` lo dice a quien no ve la
   pantalla; esto se lo dice a quien sí la ve. Se usa envolviendo el control:
   `<label class="celda"><span class="rotulo">Cantidad</span>{{ campo }}</label>`. */
.editor .celda { display: block; }
.editor .celda > .rotulo { display: none; }

/* En pantalla estrecha la rejilla se deshace y cada campo pasa a su línea, con su rótulo
   delante: una fila de ocho campos en 390 px no existe. La cabecera desaparece —los rótulos
   los pone entonces cada campo— y por eso cada control lleva su `aria-label` puesto. */
@media (max-width: 900px) {
  .editor .cabeza { display: none; }
  .editor .celda > .rotulo { display: block; margin-bottom: var(--e1); font-size: var(--t-xs);
                             font-weight: 700; letter-spacing: .06em;
                             text-transform: uppercase; color: var(--ink3); }
  .editor .fila { grid-template-columns: 1fr !important; gap: var(--e2);
                  padding: var(--e4) 0; }
  .editor .fila input[type=checkbox] { margin: 0; }
}

/* ---------- El botón rápido de fichar ------------------------------------------------------
   Vive en la franja de arriba, o sea en las 153 pantallas, y hace de un clic lo que antes
   costaba dos pantallas de rodeo. Dice dos cosas a la vez y hacen falta las dos:

   · **El color dice en qué estado estás.** Verde cuando estás fuera —el botón te mete—, rojo
     cuando estás dentro —el botón te saca—. Es lo que se ve de reojo, sin leer, desde tres
     metros, que es como se mira una franja que está siempre ahí.
   · **El rótulo dice qué va a pasar al pulsarlo**, que no es lo mismo que el estado. Y es lo
     que se puede leer en voz alta y lo que distingue quien no separa el verde del rojo: el
     color NUNCA va solo.

   **El color va en el contorno y en el punto, no en el fondo**, y eso se decidió mirando la
   barra pintada. El primer intento fue macizo —verde y rojo llenos— con el argumento de que
   se ve desde tres metros; el argumento era prestado de OTRA superficie: a tres metros se
   mira la Pared, que tiene su propio botón y está fuera del libro a propósito. La barra de la
   aplicación se mira a distancia de lectura, y ahí el fondo de color no compra distancia:
   solo compra color. Y competía con dos cosas:

   · La barra sale en las 153 pantallas, así que un botón macizo es una SEGUNDA acción
     principal en todas ellas, contra la regla de una sola acción negra por pantalla.
   · El rojo de este producto significa dinero parado. Dos centímetros por encima de un
     «17.683 € sin cobrar», un rojo macizo que significa «estás dentro» le quita el filo al de
     abajo. Que el rojo quiera decir siempre lo mismo es un presupuesto que se gasta una vez.

   Lo que sí distingue los dos estados de un vistazo es el punto —hueco fuera, lleno dentro—,
   que además es la misma forma que en la tablet y que en la línea de estado de al lado. */
.barra .fichar-rapido { flex: none; }
.btn.fichar { min-height: 34px; padding: 6px 14px; font-size: var(--t-s); font-weight: 600;
              display: inline-flex; align-items: center; gap: 7px; white-space: nowrap;
              background: transparent; }
.btn.fichar::before { content: ""; width: 8px; height: 8px; border-radius: 50%; flex: none;
                      border: 2px solid currentColor; }
.btn.fichar.entrar { color: var(--ok); border-color: var(--ok); background: transparent; }
.btn.fichar.entrar:hover { background: var(--ok-suave); filter: none; }
.btn.fichar.salir { color: var(--grave); border-color: var(--grave); background: transparent; }
.btn.fichar.salir:hover { background: var(--grave-suave); filter: none; }
/* El punto, en la misma forma que en la tablet y que en la línea de estado: hueco cuando
   estás fuera, lleno cuando estás dentro. */
.btn.fichar.salir::before { background: currentColor; }
/* En pantalla estrecha la franja aprieta, y lo que cede es el hueco de alrededor: el rótulo
   se queda entero, porque es lo que se lee en voz alta y lo único que no puede faltar. */
@media (max-width: 820px) {
  .btn.fichar { padding: 6px 10px; }
}


/* =========================================================================================
   Las piezas de «El hilo del encargo» (27/09/2026)
   Cinco piezas que no existían: el camino del antetítulo, la línea de pasos del encargo, el
   índice pegado de un expediente largo, la barra fija de un editor y el marco del teléfono.
   ========================================================================================= */

/* ---------- El camino: el antetítulo de un expediente, con sus enlaces -------------------
   «Ventas › Presupuestos › P2026-007». Solo en los expedientes: en una lista el antetítulo es
   la sección y no hay a dónde subir. Hasta ahora la única vuelta era un «← Todas las obras»
   al pie de la página. */
.camino { display: flex; flex-wrap: wrap; align-items: baseline; gap: 0 var(--e2); }
.camino a { color: var(--ink2); text-decoration: none; border-bottom: 1px solid var(--linea-2); }
.camino a:hover { color: var(--ink); border-bottom-color: currentColor; }
.camino .sep { color: var(--ink3); font-weight: 400; }

/* ---------- La línea de pasos del encargo ------------------------------------------------
   Petición · presupuesto · obra · facturas · cobro, con el paso de ahora marcado. Es el
   recorrido entero aplanado: cinco pasos y nunca trece, dos líneas por paso, y color solo en
   el de ahora y en lo que pide algo. La pinta `nucleo/_hilo.html` con lo que contestan los
   módulos al gancho `nucleo.hilo`. */
.hilo { margin-top: var(--e6); }
.hilo ol { list-style: none; margin: 0; padding: 0; display: grid;
           grid-auto-flow: column; grid-auto-columns: minmax(0, 1fr); }
.hilo li { position: relative; margin: 0; padding: 20px var(--e4) 0 0; min-width: 0; }
.hilo li::before { content: ""; position: absolute; top: 5px; left: 14px; right: 0; height: 1px;
                   background: var(--linea-2); }
.hilo li:last-child::before { display: none; }
.hilo .punto { position: absolute; top: 0; left: 0; width: 11px; height: 11px; border-radius: 50%;
               box-sizing: border-box; background: var(--fondo); border: 1.5px solid var(--ink3); }
.hilo .fase { display: block; font-size: var(--t-s); color: var(--ink3); }
.hilo .valor { display: block; font-size: var(--t-m); font-weight: 600; color: var(--ink);
               margin-top: 1px; overflow-wrap: anywhere; }
.hilo a.valor { text-decoration: none; }
.hilo a.valor:hover { text-decoration: underline; text-underline-offset: 3px; }
.hilo .detalle { display: block; font-size: var(--t-s); color: var(--ink3); margin-top: 1px; }
.hilo li.es-hecho .punto { background: var(--ink3); }
.hilo li.es-luego .valor { color: var(--ink3); font-weight: 500; }
.hilo li.es-pide .punto { background: var(--acento); border-color: var(--acento); }
.hilo li.es-pide .valor, .hilo li.es-pide .detalle { color: var(--acento-legible); }
.hilo li.es-grave .punto { background: var(--grave); border-color: var(--grave); }
.hilo li.es-grave .valor, .hilo li.es-grave .detalle { color: var(--grave); }
.hilo li.aqui .punto { border: 3px solid var(--acento); background: var(--panel);
                       outline: 3px solid var(--acento-suave); }
.hilo li.aqui.es-grave .punto { border-color: var(--grave); outline-color: var(--grave-suave); }
.hilo li.aqui .fase { color: var(--ink); font-weight: 700; }
.hilo .todo { display: inline-block; margin-top: var(--e3); font-size: var(--t-s); color: var(--ink3); }
/* En el teléfono cinco pasos no caben en 390 px: se pliega en una línea —«Paso 3 de 5 ·
   Obra»— con cinco tramos de color, y al tocarla se despliega en vertical. */
.hilo-plegado { display: none; }
@media (max-width: 780px) {
  .hilo > ol, .hilo > .todo { display: none; }
  .hilo-plegado { display: block; border-top: 1px solid var(--linea-2);
                  border-bottom: 1px solid var(--linea); }
  .hilo-plegado > summary { display: grid; grid-template-columns: auto 1fr auto; gap: var(--e4);
                            align-items: center; padding: var(--e4) 0; cursor: pointer; list-style: none; }
  .hilo-plegado > summary::-webkit-details-marker { display: none; }
  .hilo-plegado > summary::after { content: "▾"; color: var(--ink3); }
  .hilo-plegado[open] > summary::after { content: "▴"; }
  .hilo-plegado .cual { font-weight: 700; font-size: var(--t-m); white-space: nowrap; }
  .hilo-plegado .cual small { display: block; font-size: var(--t-xs); font-weight: 600; color: var(--ink3); }
  .hilo-plegado .tramos { display: grid; grid-template-columns: repeat(5, 1fr); gap: 4px; }
  .hilo-plegado .tramos i { height: 6px; border-radius: 3px; background: var(--linea); }
  .hilo-plegado .tramos i.es-hecho { background: var(--ink3); }
  .hilo-plegado .tramos i.aqui { background: var(--acento); }
  .hilo-plegado .tramos i.es-pide { background: var(--acento-suave); outline: 1.5px solid var(--acento); outline-offset: -1.5px; }
  .hilo-plegado .tramos i.es-grave { background: var(--grave); }
  .hilo-plegado ol { list-style: none; margin: 0; padding: 0 0 var(--e4); }
  .hilo-plegado li { position: relative; margin: 0; padding: var(--e3) 0 var(--e3) 26px;
                     border-top: 1px solid var(--linea); }
  .hilo-plegado li .punto { position: absolute; left: 0; top: 14px; }
  .hilo-plegado li::before { display: none; }
  .hilo-plegado .todo { display: block; padding: 0 0 var(--e4) 26px; }
}

/* ---------- El índice de un expediente largo ----------------------------------------------
   La ficha de una persona medía 2.692 px en diez bloques sin forma de saltar. El índice se
   queda pegado arriba al bajar y enseña en naranja lo que pide algo. Lo rellena
   `static/nucleo/indice.js` con los epígrafes de la pantalla; sin guion, no sale. */
nav.indice { position: sticky; top: 0; z-index: 5; background: var(--fondo);
             display: flex; flex-wrap: wrap; gap: var(--e2) var(--e6); align-items: baseline;
             padding: var(--e4) 0 var(--e3); margin-top: var(--e5); border-bottom: 1px solid var(--linea);
             font-size: var(--t-m); }
nav.indice:empty { display: none; }
nav.indice a { color: var(--ink2); font-weight: 600; text-decoration: none; }
nav.indice a:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
nav.indice a small { font-weight: 500; color: var(--ink3); margin-left: var(--e1); font-size: var(--t-s); }
nav.indice a.pide, nav.indice a.pide small { color: var(--acento-legible); }

/* ---------- La barra de un editor ---------------------------------------------------------
   En el borrador de una factura, «Emitir» estaba arriba y era OTRO formulario, y «Guardar»,
   abajo: se podía emitir sin lo último que se había escrito. La barra va pegada al pie de la
   ventana mientras se edita, con las dos acciones juntas y un solo negro. */
.barra-fija { position: sticky; bottom: 0; z-index: 5; background: var(--fondo);
              border-top: 1px solid var(--linea-2); margin-top: var(--e6);
              padding: var(--e4) 0; display: flex; flex-wrap: wrap; gap: var(--e3);
              align-items: center; }
.barra-fija .estado { color: var(--ink2); font-size: var(--t-m); margin-right: auto; }

/* ---------- El marco en el teléfono -------------------------------------------------------
   Hasta el 27/09/2026 eran cuatro franjas antes del titular —la marca con las secciones
   deslizando de lado, el papel con fichar, tema y salir, el buscador y las pestañas— y el
   titular empezaba a 298 px de 844. Ahora arriba va una sola franja con la sección en la que
   estás, fichar y tus botones; abajo, una barra con Hoy, Mi trabajo, Buscar y Secciones, que
   abre la lista entera. */
.barra-movil, .secciones-cerrar { display: none; }
@media (max-width: 780px) {
  aside { position: relative; padding: var(--e3) var(--e4); flex-wrap: nowrap; }
  aside .marca { flex: 0 0 auto; }
  aside .marca img.punto { max-height: 30px; }
  aside .marca > span:not(.punto) { display: none; }
  aside nav { order: 0; flex: 1 1 auto; padding: 0; overflow: hidden; }
  aside nav a.seccion { display: none; background: transparent; padding: 0 var(--e3); }
  aside nav a.seccion.activa { display: flex; background: transparent; font-size: var(--t-g);
                               font-weight: 700; color: var(--lateral-txt); }
  aside nav a.seccion.activa svg { display: none; }
  aside .pie-lateral { display: none; }
  /* La franja de arriba se posa sobre la del lateral: fichar y los dos redondos a la derecha,
     sin el nombre (ya sale en tu ficha) ni el buscador (está en la barra de abajo). */
  .barra { position: absolute; top: 0; right: 0; background: transparent; border: 0;
           padding: var(--e3) var(--e4); display: flex; gap: var(--e2); align-items: center;
           width: auto; }
  .barra .yo, .barra .buscador { display: none; }
  .barra .quien-soy { display: flex; }
  body.con-menu { position: relative; padding-bottom: 72px; }
  /* Las secciones, en una hoja que se abre desde la barra de abajo. Sin guion: el enlace
     «Secciones» apunta a `#secciones`, y `:target` la enseña. */
  aside nav:target { position: fixed; inset: 0 0 64px 0; z-index: 40; overflow-y: auto;
                     background: var(--lateral); padding: var(--e5); display: flex;
                     flex-direction: column; gap: var(--e1); }
  aside nav:target a.seccion { display: flex; font-size: var(--t-b); padding: var(--e3) var(--e4); }
  aside nav:target a.seccion svg { display: block; }
  aside nav:target .secciones-cerrar { display: block; color: var(--lateral-txt-2);
                                       padding: var(--e4); text-align: right; }
  .barra-movil { display: grid; grid-template-columns: repeat(4, 1fr); position: fixed; left: 0;
                 right: 0; bottom: 0; z-index: 30; background: var(--panel);
                 border-top: 1px solid var(--linea-2);
                 padding: var(--e2) 0 calc(var(--e3) + env(safe-area-inset-bottom, 0px)); }
  .barra-movil a { display: flex; flex-direction: column; align-items: center; gap: 2px;
                   font-size: var(--t-xs); font-weight: 600; color: var(--ink2); text-decoration: none;
                   padding: var(--e2) 0; }
  .barra-movil svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.8;
                     stroke-linecap: round; stroke-linejoin: round; }
  .barra-movil a.activa { color: var(--ink); }
  .barra-movil a.activa svg { color: var(--acento); }
}

/* ---------- La pantalla del encargo: el dibujo de carriles --------------------------------
   `nucleo/recorrido.py` dibuja el SVG con estas clases, así que vale de día y de noche. En el
   teléfono no cabe y no se pinta: queda la lista «Paso a paso», que dice lo mismo. */
.rec-lienzo { margin-top: var(--e6); border: 1px solid var(--linea); border-radius: var(--r);
              background: var(--panel); overflow-x: auto; }
.rec-lienzo svg { display: block; width: 100%; min-width: 760px; height: auto; }
.rec-lienzo a:hover .rec-nombre { text-decoration: underline; }
.rec-carril { fill: var(--panel); }
.rec-carril.otro { fill: var(--panel-2); }
.rec-rotulo { fill: var(--ink2); font: 700 13px var(--tipo); }
.rec-linea { stroke: var(--ink3); stroke-width: 1.6; fill: none; }
.rec-punta { fill: var(--ink3); }
.rec-punto { stroke-width: 2.5; fill: var(--panel); stroke: var(--ink3); }
.rec-punto.es-hecho { fill: var(--ok); stroke: var(--ok); }
.rec-punto.es-normal { stroke: var(--acento); stroke-width: 4; }
.rec-punto.es-pide { fill: var(--acento-suave); stroke: var(--acento); }
.rec-punto.es-grave { fill: var(--grave-suave); stroke: var(--grave); }
.rec-punto.es-luego { stroke-dasharray: 3 3; stroke-width: 1.6; }
.rec-visto { fill: var(--panel); font: 800 10px var(--tipo); text-anchor: middle; }
.rec-nombre { fill: var(--ink); font: 700 12.5px var(--tipo); text-anchor: middle; }
.rec-texto { fill: var(--ink2); font: 600 11.5px var(--tipo); text-anchor: middle; }
.rec-texto.es-pide, .rec-texto.es-normal { fill: var(--acento-legible); }
.rec-texto.es-grave { fill: var(--grave); }
.rec-texto.es-hecho { fill: var(--ok); }
.rec-texto.es-luego { fill: var(--ink3); }
.rec-leyenda { display: flex; flex-wrap: wrap; gap: var(--e2) var(--e5); margin-top: var(--e3);
               font-size: var(--t-s); color: var(--ink2); }
.rec-leyenda span { display: inline-flex; align-items: center; gap: var(--e2); }
.rec-leyenda i { width: 12px; height: 12px; border-radius: 50%; display: inline-block;
                 border: 2px solid var(--ink3); box-sizing: border-box; }
.rec-leyenda i.es-hecho { background: var(--ok); border-color: var(--ok); }
.rec-leyenda i.es-normal { border: 3px solid var(--acento); }
.rec-leyenda i.es-pide { background: var(--acento-suave); border-color: var(--acento); }
.rec-leyenda i.es-grave { background: var(--grave-suave); border-color: var(--grave); }
.rec-leyenda i.es-luego { border: 1.5px dashed var(--ink3); }
@media (max-width: 780px) { .rec-lienzo, .rec-leyenda { display: none; } }
