/* ═══════════════════════════════════════════════════════════════════════════
   comun/estilos/tokens.css — los colores, las formas y las medidas. Nada más.

   ⚠ ESTE FICHERO NO SE EDITA A MANO. Lo escribe
   diseno/direcciones/generar_tokens.py, que DERIVA cada color de un matiz y lo
   BUSCA hasta que pasa el contraste que le toca. Si hay que cambiar un color, se
   cambia allí y se vuelve a generar. Retocado a mano, el primer valor que se
   quede corto no lo dice nadie.

   Aquí no entra ni un selector de componente: eso vive en componentes.css.
   Ningún componente escribe un color a mano; todos piden una variable.

   ── La dirección, decidida por Fabio el 14/08/2026 ──────────────────────────

   «Rejilla Suiza · con protagonismo», elegida entre seis maquetas de la misma
   pantalla (diseno/direcciones/). Lo que la define, y no se toca:

     · Papel y tinta. CERO SOMBRAS: la elevación no existe, existe la rejilla.
     · La jerarquía la hace el GROSOR del filete, no el color:
         1px SEPARA una fila de la siguiente
         2px AGRUPA (cierra la cabecera de una tabla, subraya un rótulo)
         3px CIERRA bloque (abre una sección, marca el apartado activo)
     · Radio de 2px en todo: casi cuadrado, con una pequeña redondez.
     · Una sola voz tipográfica, Archivo, en dos pesos. El 700 se reserva para
       los títulos y para LO QUE SE PULSA: el peso también informa.
     · El color entra en CINCO sitios y en ninguno más: el botón principal, los
       enlaces, el anillo de foco, el apartado activo del menú y las etiquetas
       de módulo. Fuera de ahí, papel y tinta.

   Lo que se descartó, y por qué, está en diseno/direcciones/CRITICA.md.

   ── Las dos capas, y por qué están separadas ────────────────────────────────

   :root                  la FORMA. Radios, grosores, espaciado, tipografía y
                          densidad. No cambia ni por tema ni por cliente.

   [data-paleta="x"]                        el COLOR, en tema claro.
   [data-tema="oscuro"][data-paleta="x"]    el mismo juego, en oscuro.

   El color va aparte porque **cada cliente tiene su matiz**: el portal de una
   empresa sale en sus colores corporativos. Lo que NO cambia por cliente es la
   intensidad —en cuántos sitios entra el color—, que es de SmartDesk.

   Los ocho matices de aquí son EXACTAMENTE los ocho de comun/paletas.php. Si
   las dos listas dejaran de coincidir, un cliente se quedaría sin colores y no
   se notaría hasta verlo en producción.

   Cada matiz declara el juego ENTERO y ninguno hereda de otro: una variable que
   faltara se pintaría con el color del matiz anterior.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── tipografías ──────────────────────────────────────────────────────────
   Servidas desde nuestro servidor, no desde el CDN de Google: el CDN manda la
   IP del visitante a un tercero (RGPD) y una CSP seria no debería tener que
   abrir fonts.gstatic.com.

   Archivo es la voz de la casa desde S3.5. JetBrains Mono se queda para UN solo
   trabajo: los datos que se comparan letra a letra —subdominios, NIF, nombres
   de base de datos—, donde distinguir un 0 de una O no es estética.

   Se piden por ?tipo= porque comun/ queda fuera de los docroots; quien los
   entrega es comun/estilos/servir_estilos.php.
   ─────────────────────────────────────────────────────────────────────────── */
@font-face{font-family:'Archivo';font-style:normal;font-weight:400;font-display:swap;
           src:url('estilos.php?tipo=archivo-400') format('woff2')}
@font-face{font-family:'Archivo';font-style:normal;font-weight:700;font-display:swap;
           src:url('estilos.php?tipo=archivo-700') format('woff2')}
@font-face{font-family:'JetBrains Mono';font-style:normal;font-weight:500;font-display:swap;
           src:url('estilos.php?tipo=jetbrains-mono-500') format('woff2')}

/* ── la forma: ni el tema ni el cliente la tocan ─────────────────────────── */
:root{
  /* familias */
  --f-texto: 'Archivo', 'Helvetica Neue', Arial, sans-serif;
  --f-dato:  'JetBrains Mono', ui-monospace, monospace;

  /* Pesos que existen de verdad en los ficheros. Pedir uno que no está hace que
     el navegador lo finja engordando el trazo, y se nota. */
  --p-normal: 400;
  --p-fuerte: 700;   /* títulos y TODO lo que se pulsa */
  --p-dato:   500;

  /* radio: casi cuadrado, con una pequeña redondez */
  --r: 2px;

  /* los tres grosores de filete, que son la jerarquía */
  --f-separa: 1px;
  --f-agrupa: 2px;
  --f-cierra: 3px;

  /* espaciado: escala de 4, sin valores sueltos */
  --e1: 4px;  --e2: 8px;  --e3: 12px; --e4: 16px;
  --e5: 20px; --e6: 24px; --e7: 32px; --e8: 44px;

  /* tamaños de letra */
  --t-cuerpo: 14px;
  --t-apoyo:  12px;
  --t-micro:  11px;
  --t-titulo: 26px;

  /* densidad */
  --alto-fila: 56px;
  --ancho-lateral: 236px;
  --ancho-lateral-plegado: 60px;   /* el menú en modo solo iconos (S5.1) */

  /* ── movimiento (S5.1) ──────────────────────────────────────────────────
     Cinco sitios de SmartDesk se mueven: el panel de la obligación, la ficha
     que sube desde abajo en el móvil, la barra de marcado múltiple, el menú
     lateral al plegarse y la cabecera del móvil. Los cinco usan ESTAS dos
     duraciones y ESTA curva, y no las suyas: cinco velocidades distintas en la
     misma pantalla se leen como cinco programas distintos.

     La curva sale rápida y frena al final —lo que se mueve parece que llega,
     no que arranca—, y no rebota: el rebote es simpático la primera vez y
     cansa a las cincuenta, que es las que Carmen va a abrir la ficha en una
     mañana.

     El respeto a `prefers-reduced-motion` NO está aquí: está en una sola regla
     al final de componentes.css que anula todas las transiciones. Si estuviera
     aquí habría que acordarse en cada componente. */
  --mov-rapido: 120ms;   /* lo que solo cambia de color o de opacidad */
  --mov-normal: 200ms;   /* lo que se desplaza o cambia de tamaño */
  --curva: cubic-bezier(.2, .7, .3, 1);
}

/* El navegador necesita saber de qué color es el lienzo para pintar lo que no
   controlamos: barras de desplazamiento, autorrelleno y controles nativos. */
:root{ color-scheme: light }
[data-tema="oscuro"]{ color-scheme: dark }


/* ═══ EL COLOR · un bloque por matiz ═════════════════════════════════════
   Los mismos ocho de comun/paletas.php. El matiz lo elige quien da de alta
   al cliente; la intensidad es de SmartDesk y es la misma en los ocho.
   ═══════════════════════════════════════════════════════════════════════ */

/* ── azul — el azul de SmartProcess ── */
[data-paleta="azul"]{
  /* el papel y la tinta */
  --papel:           #FFFFFF;  /* fondo de la página, de la tarjeta y de cada fila */
  --superficie:      #F4F6F9;  /* bloque apoyado: barra lateral, cabecera de tabla, fila apagada */
  --filete:          #DDE0E9;  /* el filete de 1px que SEPARA una fila de la siguiente */
  --filete-fuerte:   #0B0C0F;  /* trazo de los controles: campo, botón secundario, botón de icono */
  --tinta:           #121930;  /* texto principal, y los filetes de 2px y 3px que agrupan y cierran */
  --tinta-2:         #090B11;  /* texto de apoyo, rótulo de columna y ayuda del campo */
  --marcador:        #8994B8;  /* la sugerencia del campo vacío; el único texto que va a 3:1 y no a 4.5:1 */

  /* el color de marca */
  --acc:             #456BE8;  /* relleno del botón principal */
  --acc-texto:       #FFFFFF;  /* la etiqueta que va encima de ese relleno */
  --acc-hover:       #214EE4;  /* ese relleno con el ratón encima */
  --enlace:          #3C64E7;  /* los enlaces dentro del contenido */
  --enlace-hover:    #030717;  /* el enlace con el ratón encima */
  --foco:            #456BE8;  /* el anillo de foco (2px, siempre separado 2px del control) */
  --activo-fondo:    #E4E9FC;  /* fondo del apartado del menú en el que estás */
  --activo-texto:    #030717;  /* su texto */
  --activo-filete:   #456BE8;  /* su listón de 3px a la izquierda */
  --cab-filete:      #456BE8;  /* el filete de 2px que cierra la cabecera de la tabla */
  --chip-fondo:      #EDF1FD;  /* fondo de las etiquetas de módulo y de rol */
  --chip-texto:      #030717;  /* su texto */
  --chip-filete:     #C6D0F1;  /* su contorno */
  --fila-hover:      #E8EDFC;  /* la fila de la tabla con el ratón encima */
  --resalte:         #456BE8;  /* lo que hay que mirar primero: listón de la fila que pide atención */
  --resalte-suave:   #E4E9FC;  /* el mismo resalte de fondo, para teñir sin gritar */
  --resalte-texto:   #FFFFFF;  /* la tinta que se escribe encima del resalte */

  /* lo que pasa */
  --exito:           #1B7F4B;  /* correcto */
  --exito-fondo:     #EFF6F1;  /* su fondo */
  --exito-relleno:   #46996E;  /* la MANCHA de correcto: barras del cuadro de mando (3:1, no 4.5) */
  --aviso:           #8A5A00;  /* atención */
  --aviso-fondo:     #FBF4E6;  /* su fondo */
  --aviso-relleno:   #BC8420;  /* la MANCHA de atención: barras del cuadro de mando (3:1, no 4.5) */
  --error:           #B3261E;  /* fallo */
  --error-fondo:     #FCEFEE;  /* su fondo */
  --error-relleno:   #C9463C;  /* la MANCHA de fuera de plazo: barras del cuadro de mando (3:1, no 4.5) */
  --info:            #1F5FA8;  /* información */
  --info-fondo:      #EDF3FB;  /* su fondo */
}

[data-tema="oscuro"][data-paleta="azul"]{
  /* el papel y la tinta */
  --papel:           #0A0D17;  /* fondo de la página, de la tarjeta y de cada fila */
  --superficie:      #121726;  /* bloque apoyado: barra lateral, cabecera de tabla, fila apagada */
  --filete:          #252C44;  /* el filete de 1px que SEPARA una fila de la siguiente */
  --filete-fuerte:   #616984;  /* trazo de los controles: campo, botón secundario, botón de icono */
  --tinta:           #F0F1F8;  /* texto principal, y los filetes de 2px y 3px que agrupan y cierran */
  --tinta-2:         #7986AF;  /* texto de apoyo, rótulo de columna y ayuda del campo */
  --marcador:        #505D86;  /* la sugerencia del campo vacío; el único texto que va a 3:1 y no a 4.5:1 */

  /* el color de marca */
  --acc:             #5C7DEB;  /* relleno del botón principal */
  --acc-texto:       #0A0D17;  /* la etiqueta que va encima de ese relleno */
  --acc-hover:       #849EF0;  /* ese relleno con el ratón encima */
  --enlace:          #6E8BED;  /* los enlaces dentro del contenido */
  --enlace-hover:    #5C7DEB;  /* el enlace con el ratón encima */
  --foco:            #5C7DEB;  /* el anillo de foco (2px, siempre separado 2px del control) */
  --activo-fondo:    #131E41;  /* fondo del apartado del menú en el que estás */
  --activo-texto:    #6081EB;  /* su texto */
  --activo-filete:   #5C7DEB;  /* su listón de 3px a la izquierda */
  --cab-filete:      #5C7DEB;  /* el filete de 2px que cierra la cabecera de la tabla */
  --chip-fondo:      #111934;  /* fondo de las etiquetas de módulo y de rol */
  --chip-texto:      #5C7DEB;  /* su texto */
  --chip-filete:     #28345D;  /* su contorno */
  --fila-hover:      #141D3B;  /* la fila de la tabla con el ratón encima */
  --resalte:         #5C7DEB;  /* lo que hay que mirar primero: listón de la fila que pide atención */
  --resalte-suave:   #131E41;  /* el mismo resalte de fondo, para teñir sin gritar */
  --resalte-texto:   #0A0D17;  /* la tinta que se escribe encima del resalte */

  /* lo que pasa */
  --exito:           #4FBF83;  /* correcto */
  --exito-fondo:     #13251C;  /* su fondo */
  --exito-relleno:   #35895D;  /* la MANCHA de correcto: barras del cuadro de mando (3:1, no 4.5) */
  --aviso:           #D9A441;  /* atención */
  --aviso-fondo:     #2A2010;  /* su fondo */
  --aviso-relleno:   #8F6A22;  /* la MANCHA de atención: barras del cuadro de mando (3:1, no 4.5) */
  --error:           #EF7A72;  /* fallo */
  --error-fondo:     #2C1614;  /* su fondo */
  --error-relleno:   #A2453E;  /* la MANCHA de fuera de plazo: barras del cuadro de mando (3:1, no 4.5) */
  --info:            #6FA8E8;  /* información */
  --info-fondo:      #12202F;  /* su fondo */
}

/* ── morado — el morado de SmartProcess; es el de la casa ── */
[data-paleta="morado"]{
  /* el papel y la tinta */
  --papel:           #FFFFFF;  /* fondo de la página, de la tarjeta y de cada fila */
  --superficie:      #F5F4F9;  /* bloque apoyado: barra lateral, cabecera de tabla, fila apagada */
  --filete:          #DFDDE9;  /* el filete de 1px que SEPARA una fila de la siguiente */
  --filete-fuerte:   #0B0B0F;  /* trazo de los controles: campo, botón secundario, botón de icono */
  --tinta:           #171230;  /* texto principal, y los filetes de 2px y 3px que agrupan y cierran */
  --tinta-2:         #0A0911;  /* texto de apoyo, rótulo de columna y ayuda del campo */
  --marcador:        #978FBC;  /* la sugerencia del campo vacío; el único texto que va a 3:1 y no a 4.5:1 */

  /* el color de marca */
  --acc:             #755DEF;  /* relleno del botón principal */
  --acc-texto:       #FFFFFF;  /* la etiqueta que va encima de ese relleno */
  --acc-hover:       #593CEC;  /* ese relleno con el ratón encima */
  --enlace:          #6D53EE;  /* los enlaces dentro del contenido */
  --enlace-hover:    #060217;  /* el enlace con el ratón encima */
  --foco:            #755DEF;  /* el anillo de foco (2px, siempre separado 2px del control) */
  --activo-fondo:    #E7E3FC;  /* fondo del apartado del menú en el que estás */
  --activo-texto:    #060217;  /* su texto */
  --activo-filete:   #755DEF;  /* su listón de 3px a la izquierda */
  --cab-filete:      #755DEF;  /* el filete de 2px que cierra la cabecera de la tabla */
  --chip-fondo:      #EFECFD;  /* fondo de las etiquetas de módulo y de rol */
  --chip-texto:      #060217;  /* su texto */
  --chip-filete:     #CDC6F1;  /* su contorno */
  --fila-hover:      #EBE8FC;  /* la fila de la tabla con el ratón encima */
  --resalte:         #755DEF;  /* lo que hay que mirar primero: listón de la fila que pide atención */
  --resalte-suave:   #E7E3FC;  /* el mismo resalte de fondo, para teñir sin gritar */
  --resalte-texto:   #FFFFFF;  /* la tinta que se escribe encima del resalte */

  /* lo que pasa */
  --exito:           #1B7F4B;  /* correcto */
  --exito-fondo:     #EFF6F1;  /* su fondo */
  --exito-relleno:   #46996E;  /* la MANCHA de correcto: barras del cuadro de mando (3:1, no 4.5) */
  --aviso:           #8A5A00;  /* atención */
  --aviso-fondo:     #FBF4E6;  /* su fondo */
  --aviso-relleno:   #BC8420;  /* la MANCHA de atención: barras del cuadro de mando (3:1, no 4.5) */
  --error:           #B3261E;  /* fallo */
  --error-fondo:     #FCEFEE;  /* su fondo */
  --error-relleno:   #C9463C;  /* la MANCHA de fuera de plazo: barras del cuadro de mando (3:1, no 4.5) */
  --info:            #1F5FA8;  /* información */
  --info-fondo:      #EDF3FB;  /* su fondo */
}

[data-tema="oscuro"][data-paleta="morado"]{
  /* el papel y la tinta */
  --papel:           #0C0A17;  /* fondo de la página, de la tarjeta y de cada fila */
  --superficie:      #161226;  /* bloque apoyado: barra lateral, cabecera de tabla, fila apagada */
  --filete:          #2A2544;  /* el filete de 1px que SEPARA una fila de la siguiente */
  --filete-fuerte:   #696387;  /* trazo de los controles: campo, botón secundario, botón de icono */
  --tinta:           #F1F0F8;  /* texto principal, y los filetes de 2px y 3px que agrupan y cierran */
  --tinta-2:         #857CB1;  /* texto de apoyo, rótulo de columna y ayuda del campo */
  --marcador:        #60568F;  /* la sugerencia del campo vacío; el único texto que va a 3:1 y no a 4.5:1 */

  /* el color de marca */
  --acc:             #856FF1;  /* relleno del botón principal */
  --acc-texto:       #0C0A17;  /* la etiqueta que va encima de ese relleno */
  --acc-hover:       #A494F4;  /* ese relleno con el ratón encima */
  --enlace:          #917DF2;  /* los enlaces dentro del contenido */
  --enlace-hover:    #816AF0;  /* el enlace con el ratón encima */
  --foco:            #856FF1;  /* el anillo de foco (2px, siempre separado 2px del control) */
  --activo-fondo:    #1B1341;  /* fondo del apartado del menú en el que estás */
  --activo-texto:    #856FF1;  /* su texto */
  --activo-filete:   #856FF1;  /* su listón de 3px a la izquierda */
  --cab-filete:      #856FF1;  /* el filete de 2px que cierra la cabecera de la tabla */
  --chip-fondo:      #171134;  /* fondo de las etiquetas de módulo y de rol */
  --chip-texto:      #816AF0;  /* su texto */
  --chip-filete:     #31285D;  /* su contorno */
  --fila-hover:      #1A143B;  /* la fila de la tabla con el ratón encima */
  --resalte:         #856FF1;  /* lo que hay que mirar primero: listón de la fila que pide atención */
  --resalte-suave:   #1B1341;  /* el mismo resalte de fondo, para teñir sin gritar */
  --resalte-texto:   #0C0A17;  /* la tinta que se escribe encima del resalte */

  /* lo que pasa */
  --exito:           #4FBF83;  /* correcto */
  --exito-fondo:     #13251C;  /* su fondo */
  --exito-relleno:   #35895D;  /* la MANCHA de correcto: barras del cuadro de mando (3:1, no 4.5) */
  --aviso:           #D9A441;  /* atención */
  --aviso-fondo:     #2A2010;  /* su fondo */
  --aviso-relleno:   #8F6A22;  /* la MANCHA de atención: barras del cuadro de mando (3:1, no 4.5) */
  --error:           #EF7A72;  /* fallo */
  --error-fondo:     #2C1614;  /* su fondo */
  --error-relleno:   #A2453E;  /* la MANCHA de fuera de plazo: barras del cuadro de mando (3:1, no 4.5) */
  --info:            #6FA8E8;  /* información */
  --info-fondo:      #12202F;  /* su fondo */
}

/* ── marino — más serio y apagado que el azul de la casa ── */
[data-paleta="marino"]{
  /* el papel y la tinta */
  --papel:           #FFFFFF;  /* fondo de la página, de la tarjeta y de cada fila */
  --superficie:      #F4F7F9;  /* bloque apoyado: barra lateral, cabecera de tabla, fila apagada */
  --filete:          #DDE2E9;  /* el filete de 1px que SEPARA una fila de la siguiente */
  --filete-fuerte:   #0B0C0F;  /* trazo de los controles: campo, botón secundario, botón de icono */
  --tinta:           #121F30;  /* texto principal, y los filetes de 2px y 3px que agrupan y cierran */
  --tinta-2:         #090C11;  /* texto de apoyo, rótulo de columna y ayuda del campo */
  --marcador:        #8096B2;  /* la sugerencia del campo vacío; el único texto que va a 3:1 y no a 4.5:1 */

  /* el color de marca */
  --acc:             #3976C6;  /* relleno del botón principal */
  --acc-texto:       #FFFFFF;  /* la etiqueta que va encima de ese relleno */
  --acc-hover:       #2F61A2;  /* ese relleno con el ratón encima */
  --enlace:          #366FBA;  /* los enlaces dentro del contenido */
  --enlace-hover:    #060C14;  /* el enlace con el ratón encima */
  --foco:            #3976C6;  /* el anillo de foco (2px, siempre separado 2px del control) */
  --activo-fondo:    #E7EFF8;  /* fondo del apartado del menú en el que estás */
  --activo-texto:    #060C14;  /* su texto */
  --activo-filete:   #3976C6;  /* su listón de 3px a la izquierda */
  --cab-filete:      #3976C6;  /* el filete de 2px que cierra la cabecera de la tabla */
  --chip-fondo:      #EFF4FA;  /* fondo de las etiquetas de módulo y de rol */
  --chip-texto:      #060C14;  /* su texto */
  --chip-filete:     #C8D9EF;  /* su contorno */
  --fila-hover:      #EBF1F9;  /* la fila de la tabla con el ratón encima */
  --resalte:         #3976C6;  /* lo que hay que mirar primero: listón de la fila que pide atención */
  --resalte-suave:   #E7EFF8;  /* el mismo resalte de fondo, para teñir sin gritar */
  --resalte-texto:   #FFFFFF;  /* la tinta que se escribe encima del resalte */

  /* lo que pasa */
  --exito:           #1B7F4B;  /* correcto */
  --exito-fondo:     #EFF6F1;  /* su fondo */
  --exito-relleno:   #46996E;  /* la MANCHA de correcto: barras del cuadro de mando (3:1, no 4.5) */
  --aviso:           #8A5A00;  /* atención */
  --aviso-fondo:     #FBF4E6;  /* su fondo */
  --aviso-relleno:   #BC8420;  /* la MANCHA de atención: barras del cuadro de mando (3:1, no 4.5) */
  --error:           #B3261E;  /* fallo */
  --error-fondo:     #FCEFEE;  /* su fondo */
  --error-relleno:   #C9463C;  /* la MANCHA de fuera de plazo: barras del cuadro de mando (3:1, no 4.5) */
  --info:            #1F5FA8;  /* información */
  --info-fondo:      #EDF3FB;  /* su fondo */
}

[data-tema="oscuro"][data-paleta="marino"]{
  /* el papel y la tinta */
  --papel:           #0A1017;  /* fondo de la página, de la tarjeta y de cada fila */
  --superficie:      #121B26;  /* bloque apoyado: barra lateral, cabecera de tabla, fila apagada */
  --filete:          #253244;  /* el filete de 1px que SEPARA una fila de la siguiente */
  --filete-fuerte:   #617084;  /* trazo de los controles: campo, botón secundario, botón de icono */
  --tinta:           #F0F3F8;  /* texto principal, y los filetes de 2px y 3px que agrupan y cierran */
  --tinta-2:         #768EAD;  /* texto de apoyo, rótulo de columna y ayuda del campo */
  --marcador:        #4D6380;  /* la sugerencia del campo vacío; el único texto que va a 3:1 y no a 4.5:1 */

  /* el color de marca */
  --acc:             #5187CD;  /* relleno del botón principal */
  --acc-texto:       #0A1017;  /* la etiqueta que va encima de ese relleno */
  --acc-hover:       #7DA5D9;  /* ese relleno con el ratón encima */
  --enlace:          #6594D2;  /* los enlaces dentro del contenido */
  --enlace-hover:    #5589CE;  /* el enlace con el ratón encima */
  --foco:            #5187CD;  /* el anillo de foco (2px, siempre separado 2px del control) */
  --activo-fondo:    #132741;  /* fondo del apartado del menú en el que estás */
  --activo-texto:    #5D8FD0;  /* su texto */
  --activo-filete:   #5187CD;  /* su listón de 3px a la izquierda */
  --cab-filete:      #5187CD;  /* el filete de 2px que cierra la cabecera de la tabla */
  --chip-fondo:      #112034;  /* fondo de las etiquetas de módulo y de rol */
  --chip-texto:      #5589CE;  /* su texto */
  --chip-filete:     #283F5D;  /* su contorno */
  --fila-hover:      #14253B;  /* la fila de la tabla con el ratón encima */
  --resalte:         #5187CD;  /* lo que hay que mirar primero: listón de la fila que pide atención */
  --resalte-suave:   #132741;  /* el mismo resalte de fondo, para teñir sin gritar */
  --resalte-texto:   #0A1017;  /* la tinta que se escribe encima del resalte */

  /* lo que pasa */
  --exito:           #4FBF83;  /* correcto */
  --exito-fondo:     #13251C;  /* su fondo */
  --exito-relleno:   #35895D;  /* la MANCHA de correcto: barras del cuadro de mando (3:1, no 4.5) */
  --aviso:           #D9A441;  /* atención */
  --aviso-fondo:     #2A2010;  /* su fondo */
  --aviso-relleno:   #8F6A22;  /* la MANCHA de atención: barras del cuadro de mando (3:1, no 4.5) */
  --error:           #EF7A72;  /* fallo */
  --error-fondo:     #2C1614;  /* su fondo */
  --error-relleno:   #A2453E;  /* la MANCHA de fuera de plazo: barras del cuadro de mando (3:1, no 4.5) */
  --info:            #6FA8E8;  /* información */
  --info-fondo:      #12202F;  /* su fondo */
}

/* ── teal — entre el azul y el verde ── */
[data-paleta="teal"]{
  /* el papel y la tinta */
  --papel:           #FFFFFF;  /* fondo de la página, de la tarjeta y de cada fila */
  --superficie:      #F4F9F9;  /* bloque apoyado: barra lateral, cabecera de tabla, fila apagada */
  --filete:          #DDE8E9;  /* el filete de 1px que SEPARA una fila de la siguiente */
  --filete-fuerte:   #0B0E0F;  /* trazo de los controles: campo, botón secundario, botón de icono */
  --tinta:           #122D30;  /* texto principal, y los filetes de 2px y 3px que agrupan y cierran */
  --tinta-2:         #091011;  /* texto de apoyo, rótulo de columna y ayuda del campo */
  --marcador:        #669DA3;  /* la sugerencia del campo vacío; el único texto que va a 3:1 y no a 4.5:1 */

  /* el color de marca */
  --acc:             #17818C;  /* relleno del botón principal */
  --acc-texto:       #FFFFFF;  /* la etiqueta que va encima de ese relleno */
  --acc-hover:       #136872;  /* ese relleno con el ratón encima */
  --enlace:          #157984;  /* los enlaces dentro del contenido */
  --enlace-hover:    #041416;  /* el enlace con el ratón encima */
  --foco:            #17818C;  /* el anillo de foco (2px, siempre separado 2px del control) */
  --activo-fondo:    #E5F9FB;  /* fondo del apartado del menú en el que estás */
  --activo-texto:    #041416;  /* su texto */
  --activo-filete:   #17818C;  /* su listón de 3px a la izquierda */
  --cab-filete:      #17818C;  /* el filete de 2px que cierra la cabecera de la tabla */
  --chip-fondo:      #EDFBFC;  /* fondo de las etiquetas de módulo y de rol */
  --chip-texto:      #041416;  /* su texto */
  --chip-filete:     #C6ECF1;  /* su contorno */
  --fila-hover:      #E9FAFB;  /* la fila de la tabla con el ratón encima */
  --resalte:         #17818C;  /* lo que hay que mirar primero: listón de la fila que pide atención */
  --resalte-suave:   #E5F9FB;  /* el mismo resalte de fondo, para teñir sin gritar */
  --resalte-texto:   #FFFFFF;  /* la tinta que se escribe encima del resalte */

  /* lo que pasa */
  --exito:           #1B7F4B;  /* correcto */
  --exito-fondo:     #EFF6F1;  /* su fondo */
  --exito-relleno:   #46996E;  /* la MANCHA de correcto: barras del cuadro de mando (3:1, no 4.5) */
  --aviso:           #8A5A00;  /* atención */
  --aviso-fondo:     #FBF4E6;  /* su fondo */
  --aviso-relleno:   #BC8420;  /* la MANCHA de atención: barras del cuadro de mando (3:1, no 4.5) */
  --error:           #B3261E;  /* fallo */
  --error-fondo:     #FCEFEE;  /* su fondo */
  --error-relleno:   #C9463C;  /* la MANCHA de fuera de plazo: barras del cuadro de mando (3:1, no 4.5) */
  --info:            #1F5FA8;  /* información */
  --info-fondo:      #EDF3FB;  /* su fondo */
}

[data-tema="oscuro"][data-paleta="teal"]{
  /* el papel y la tinta */
  --papel:           #0A1617;  /* fondo de la página, de la tarjeta y de cada fila */
  --superficie:      #122426;  /* bloque apoyado: barra lateral, cabecera de tabla, fila apagada */
  --filete:          #254144;  /* el filete de 1px que SEPARA una fila de la siguiente */
  --filete-fuerte:   #618184;  /* trazo de los controles: campo, botón secundario, botón de icono */
  --tinta:           #F0F7F8;  /* texto principal, y los filetes de 2px y 3px que agrupan y cierran */
  --tinta-2:         #70A3A9;  /* texto de apoyo, rótulo de columna y ayuda del campo */
  --marcador:        #41686C;  /* la sugerencia del campo vacío; el único texto que va a 3:1 y no a 4.5:1 */

  /* el color de marca */
  --acc:             #1A95A2;  /* relleno del botón principal */
  --acc-texto:       #0A1617;  /* la etiqueta que va encima de ese relleno */
  --acc-hover:       #21B9CA;  /* ese relleno con el ratón encima */
  --enlace:          #1EA9B8;  /* los enlaces dentro del contenido */
  --enlace-hover:    #1DA1AF;  /* el enlace con el ratón encima */
  --foco:            #1A95A2;  /* el anillo de foco (2px, siempre separado 2px del control) */
  --activo-fondo:    #133D41;  /* fondo del apartado del menú en el que estás */
  --activo-texto:    #1FB1C1;  /* su texto */
  --activo-filete:   #1A95A2;  /* su listón de 3px a la izquierda */
  --cab-filete:      #1A95A2;  /* el filete de 2px que cierra la cabecera de la tabla */
  --chip-fondo:      #113034;  /* fondo de las etiquetas de módulo y de rol */
  --chip-texto:      #1DA1AF;  /* su texto */
  --chip-filete:     #28585D;  /* su contorno */
  --fila-hover:      #14373B;  /* la fila de la tabla con el ratón encima */
  --resalte:         #1A95A2;  /* lo que hay que mirar primero: listón de la fila que pide atención */
  --resalte-suave:   #133D41;  /* el mismo resalte de fondo, para teñir sin gritar */
  --resalte-texto:   #0A1617;  /* la tinta que se escribe encima del resalte */

  /* lo que pasa */
  --exito:           #4FBF83;  /* correcto */
  --exito-fondo:     #13251C;  /* su fondo */
  --exito-relleno:   #35895D;  /* la MANCHA de correcto: barras del cuadro de mando (3:1, no 4.5) */
  --aviso:           #D9A441;  /* atención */
  --aviso-fondo:     #2A2010;  /* su fondo */
  --aviso-relleno:   #8F6A22;  /* la MANCHA de atención: barras del cuadro de mando (3:1, no 4.5) */
  --error:           #EF7A72;  /* fallo */
  --error-fondo:     #2C1614;  /* su fondo */
  --error-relleno:   #A2453E;  /* la MANCHA de fuera de plazo: barras del cuadro de mando (3:1, no 4.5) */
  --info:            #6FA8E8;  /* información */
  --info-fondo:      #12202F;  /* su fondo */
}

/* ── verde — verde de bosque, nada de verde de aviso ── */
[data-paleta="verde"]{
  /* el papel y la tinta */
  --papel:           #FFFFFF;  /* fondo de la página, de la tarjeta y de cada fila */
  --superficie:      #F4F9F7;  /* bloque apoyado: barra lateral, cabecera de tabla, fila apagada */
  --filete:          #DDE9E3;  /* el filete de 1px que SEPARA una fila de la siguiente */
  --filete-fuerte:   #0B0F0D;  /* trazo de los controles: campo, botón secundario, botón de icono */
  --tinta:           #123021;  /* texto principal, y los filetes de 2px y 3px que agrupan y cierran */
  --tinta-2:         #09110D;  /* texto de apoyo, rótulo de columna y ayuda del campo */
  --marcador:        #63A182;  /* la sugerencia del campo vacío; el único texto que va a 3:1 y no a 4.5:1 */

  /* el color de marca */
  --acc:             #1F8452;  /* relleno del botón principal */
  --acc-texto:       #FFFFFF;  /* la etiqueta que va encima de ese relleno */
  --acc-hover:       #196B42;  /* ese relleno con el ratón encima */
  --enlace:          #1E804F;  /* los enlaces dentro del contenido */
  --enlace-hover:    #05150D;  /* el enlace con el ratón encima */
  --foco:            #1F8452;  /* el anillo de foco (2px, siempre separado 2px del control) */
  --activo-fondo:    #E6F9F0;  /* fondo del apartado del menú en el que estás */
  --activo-texto:    #05150D;  /* su texto */
  --activo-filete:   #1F8452;  /* su listón de 3px a la izquierda */
  --cab-filete:      #1F8452;  /* el filete de 2px que cierra la cabecera de la tabla */
  --chip-fondo:      #EEFBF5;  /* fondo de las etiquetas de módulo y de rol */
  --chip-texto:      #05150D;  /* su texto */
  --chip-filete:     #C6F1DB;  /* su contorno */
  --fila-hover:      #EAFAF2;  /* la fila de la tabla con el ratón encima */
  --resalte:         #1F8452;  /* lo que hay que mirar primero: listón de la fila que pide atención */
  --resalte-suave:   #E6F9F0;  /* el mismo resalte de fondo, para teñir sin gritar */
  --resalte-texto:   #FFFFFF;  /* la tinta que se escribe encima del resalte */

  /* lo que pasa */
  --exito:           #1B7F4B;  /* correcto */
  --exito-fondo:     #EFF6F1;  /* su fondo */
  --exito-relleno:   #46996E;  /* la MANCHA de correcto: barras del cuadro de mando (3:1, no 4.5) */
  --aviso:           #8A5A00;  /* atención */
  --aviso-fondo:     #FBF4E6;  /* su fondo */
  --aviso-relleno:   #BC8420;  /* la MANCHA de atención: barras del cuadro de mando (3:1, no 4.5) */
  --error:           #B3261E;  /* fallo */
  --error-fondo:     #FCEFEE;  /* su fondo */
  --error-relleno:   #C9463C;  /* la MANCHA de fuera de plazo: barras del cuadro de mando (3:1, no 4.5) */
  --info:            #1F5FA8;  /* información */
  --info-fondo:      #EDF3FB;  /* su fondo */
}

[data-tema="oscuro"][data-paleta="verde"]{
  /* el papel y la tinta */
  --papel:           #0A1711;  /* fondo de la página, de la tarjeta y de cada fila */
  --superficie:      #12261C;  /* bloque apoyado: barra lateral, cabecera de tabla, fila apagada */
  --filete:          #254434;  /* el filete de 1px que SEPARA una fila de la siguiente */
  --filete-fuerte:   #638775;  /* trazo de los controles: campo, botón secundario, botón de icono */
  --tinta:           #F0F8F4;  /* texto principal, y los filetes de 2px y 3px que agrupan y cierran */
  --tinta-2:         #70A98C;  /* texto de apoyo, rótulo de columna y ayuda del campo */
  --marcador:        #416C57;  /* la sugerencia del campo vacío; el único texto que va a 3:1 y no a 4.5:1 */

  /* el color de marca */
  --acc:             #24995E;  /* relleno del botón principal */
  --acc-texto:       #0A1711;  /* la etiqueta que va encima de ese relleno */
  --acc-hover:       #2DBE75;  /* ese relleno con el ratón encima */
  --enlace:          #29AE6B;  /* los enlaces dentro del contenido */
  --enlace-hover:    #28A969;  /* el enlace con el ratón encima */
  --foco:            #24995E;  /* el anillo de foco (2px, siempre separado 2px del control) */
  --activo-fondo:    #13412A;  /* fondo del apartado del menú en el que estás */
  --activo-texto:    #2CBA73;  /* su texto */
  --activo-filete:   #24995E;  /* su listón de 3px a la izquierda */
  --cab-filete:      #24995E;  /* el filete de 2px que cierra la cabecera de la tabla */
  --chip-fondo:      #113422;  /* fondo de las etiquetas de módulo y de rol */
  --chip-texto:      #28A969;  /* su texto */
  --chip-filete:     #285D42;  /* su contorno */
  --fila-hover:      #143B28;  /* la fila de la tabla con el ratón encima */
  --resalte:         #24995E;  /* lo que hay que mirar primero: listón de la fila que pide atención */
  --resalte-suave:   #13412A;  /* el mismo resalte de fondo, para teñir sin gritar */
  --resalte-texto:   #0A1711;  /* la tinta que se escribe encima del resalte */

  /* lo que pasa */
  --exito:           #4FBF83;  /* correcto */
  --exito-fondo:     #13251C;  /* su fondo */
  --exito-relleno:   #35895D;  /* la MANCHA de correcto: barras del cuadro de mando (3:1, no 4.5) */
  --aviso:           #D9A441;  /* atención */
  --aviso-fondo:     #2A2010;  /* su fondo */
  --aviso-relleno:   #8F6A22;  /* la MANCHA de atención: barras del cuadro de mando (3:1, no 4.5) */
  --error:           #EF7A72;  /* fallo */
  --error-fondo:     #2C1614;  /* su fondo */
  --error-relleno:   #A2453E;  /* la MANCHA de fuera de plazo: barras del cuadro de mando (3:1, no 4.5) */
  --info:            #6FA8E8;  /* información */
  --info-fondo:      #12202F;  /* su fondo */
}

/* ── granate — rojo oscuro con autoridad ── */
[data-paleta="granate"]{
  /* el papel y la tinta */
  --papel:           #FFFFFF;  /* fondo de la página, de la tarjeta y de cada fila */
  --superficie:      #F9F4F5;  /* bloque apoyado: barra lateral, cabecera de tabla, fila apagada */
  --filete:          #E9DDDF;  /* el filete de 1px que SEPARA una fila de la siguiente */
  --filete-fuerte:   #0F0B0B;  /* trazo de los controles: campo, botón secundario, botón de icono */
  --tinta:           #301218;  /* texto principal, y los filetes de 2px y 3px que agrupan y cierran */
  --tinta-2:         #11090A;  /* texto de apoyo, rótulo de columna y ayuda del campo */
  --marcador:        #B68690;  /* la sugerencia del campo vacío; el único texto que va a 3:1 y no a 4.5:1 */

  /* el color de marca */
  --acc:             #CA4963;  /* relleno del botón principal */
  --acc-texto:       #FFFFFF;  /* la etiqueta que va encima de ese relleno */
  --acc-hover:       #AE324B;  /* ese relleno con el ratón encima */
  --enlace:          #C63955;  /* los enlaces dentro del contenido */
  --enlace-hover:    #140609;  /* el enlace con el ratón encima */
  --foco:            #CA4963;  /* el anillo de foco (2px, siempre separado 2px del control) */
  --activo-fondo:    #F8E7EB;  /* fondo del apartado del menú en el que estás */
  --activo-texto:    #140609;  /* su texto */
  --activo-filete:   #CA4963;  /* su listón de 3px a la izquierda */
  --cab-filete:      #CA4963;  /* el filete de 2px que cierra la cabecera de la tabla */
  --chip-fondo:      #FAEFF1;  /* fondo de las etiquetas de módulo y de rol */
  --chip-texto:      #140609;  /* su texto */
  --chip-filete:     #EFC8D0;  /* su contorno */
  --fila-hover:      #F9EBEE;  /* la fila de la tabla con el ratón encima */
  --resalte:         #CA4963;  /* lo que hay que mirar primero: listón de la fila que pide atención */
  --resalte-suave:   #F8E7EB;  /* el mismo resalte de fondo, para teñir sin gritar */
  --resalte-texto:   #FFFFFF;  /* la tinta que se escribe encima del resalte */

  /* lo que pasa */
  --exito:           #1B7F4B;  /* correcto */
  --exito-fondo:     #EFF6F1;  /* su fondo */
  --exito-relleno:   #46996E;  /* la MANCHA de correcto: barras del cuadro de mando (3:1, no 4.5) */
  --aviso:           #8A5A00;  /* atención */
  --aviso-fondo:     #FBF4E6;  /* su fondo */
  --aviso-relleno:   #BC8420;  /* la MANCHA de atención: barras del cuadro de mando (3:1, no 4.5) */
  --error:           #B3261E;  /* fallo */
  --error-fondo:     #FCEFEE;  /* su fondo */
  --error-relleno:   #C9463C;  /* la MANCHA de fuera de plazo: barras del cuadro de mando (3:1, no 4.5) */
  --info:            #1F5FA8;  /* información */
  --info-fondo:      #EDF3FB;  /* su fondo */
}

[data-tema="oscuro"][data-paleta="granate"]{
  /* el papel y la tinta */
  --papel:           #170A0D;  /* fondo de la página, de la tarjeta y de cada fila */
  --superficie:      #261216;  /* bloque apoyado: barra lateral, cabecera de tabla, fila apagada */
  --filete:          #44252B;  /* el filete de 1px que SEPARA una fila de la siguiente */
  --filete-fuerte:   #87636A;  /* trazo de los controles: campo, botón secundario, botón de icono */
  --tinta:           #F8F0F1;  /* texto principal, y los filetes de 2px y 3px que agrupan y cierran */
  --tinta-2:         #AF7984;  /* texto de apoyo, rótulo de columna y ayuda del campo */
  --marcador:        #86505B;  /* la sugerencia del campo vacío; el único texto que va a 3:1 y no a 4.5:1 */

  /* el color de marca */
  --acc:             #D05D74;  /* relleno del botón principal */
  --acc-texto:       #170A0D;  /* la etiqueta que va encima de ese relleno */
  --acc-hover:       #DE8C9D;  /* ese relleno con el ratón encima */
  --enlace:          #D67185;  /* los enlaces dentro del contenido */
  --enlace-hover:    #D16177;  /* el enlace con el ratón encima */
  --foco:            #D05D74;  /* el anillo de foco (2px, siempre separado 2px del control) */
  --activo-fondo:    #41131C;  /* fondo del apartado del menú en el que estás */
  --activo-texto:    #D3697E;  /* su texto */
  --activo-filete:   #D05D74;  /* su listón de 3px a la izquierda */
  --cab-filete:      #D05D74;  /* el filete de 2px que cierra la cabecera de la tabla */
  --chip-fondo:      #341118;  /* fondo de las etiquetas de módulo y de rol */
  --chip-texto:      #D16177;  /* su texto */
  --chip-filete:     #5D2832;  /* su contorno */
  --fila-hover:      #3B141C;  /* la fila de la tabla con el ratón encima */
  --resalte:         #D05D74;  /* lo que hay que mirar primero: listón de la fila que pide atención */
  --resalte-suave:   #41131C;  /* el mismo resalte de fondo, para teñir sin gritar */
  --resalte-texto:   #170A0D;  /* la tinta que se escribe encima del resalte */

  /* lo que pasa */
  --exito:           #4FBF83;  /* correcto */
  --exito-fondo:     #13251C;  /* su fondo */
  --exito-relleno:   #35895D;  /* la MANCHA de correcto: barras del cuadro de mando (3:1, no 4.5) */
  --aviso:           #D9A441;  /* atención */
  --aviso-fondo:     #2A2010;  /* su fondo */
  --aviso-relleno:   #8F6A22;  /* la MANCHA de atención: barras del cuadro de mando (3:1, no 4.5) */
  --error:           #EF7A72;  /* fallo */
  --error-fondo:     #2C1614;  /* su fondo */
  --error-relleno:   #A2453E;  /* la MANCHA de fuera de plazo: barras del cuadro de mando (3:1, no 4.5) */
  --info:            #6FA8E8;  /* información */
  --info-fondo:      #12202F;  /* su fondo */
}

/* ── naranja — cálido y visible; el más llamativo ── */
[data-paleta="naranja"]{
  /* el papel y la tinta */
  --papel:           #FFFFFF;  /* fondo de la página, de la tarjeta y de cada fila */
  --superficie:      #F9F6F4;  /* bloque apoyado: barra lateral, cabecera de tabla, fila apagada */
  --filete:          #E9E2DD;  /* el filete de 1px que SEPARA una fila de la siguiente */
  --filete-fuerte:   #0F0C0B;  /* trazo de los controles: campo, botón secundario, botón de icono */
  --tinta:           #301E12;  /* texto principal, y los filetes de 2px y 3px que agrupan y cierran */
  --tinta-2:         #110C09;  /* texto de apoyo, rótulo de columna y ayuda del campo */
  --marcador:        #AD8C76;  /* la sugerencia del campo vacío; el único texto que va a 3:1 y no a 4.5:1 */

  /* el color de marca */
  --acc:             #BA5817;  /* relleno del botón principal */
  --acc-texto:       #FFFFFF;  /* la etiqueta que va encima de ese relleno */
  --acc-hover:       #9A4913;  /* ese relleno con el ratón encima */
  --enlace:          #B15416;  /* los enlaces dentro del contenido */
  --enlace-hover:    #170B03;  /* el enlace con el ratón encima */
  --foco:            #BA5817;  /* el anillo de foco (2px, siempre separado 2px del control) */
  --activo-fondo:    #FCEDE4;  /* fondo del apartado del menú en el que estás */
  --activo-texto:    #170B03;  /* su texto */
  --activo-filete:   #BA5817;  /* su listón de 3px a la izquierda */
  --cab-filete:      #BA5817;  /* el filete de 2px que cierra la cabecera de la tabla */
  --chip-fondo:      #FDF3ED;  /* fondo de las etiquetas de módulo y de rol */
  --chip-texto:      #170B03;  /* su texto */
  --chip-filete:     #F1D7C6;  /* su contorno */
  --fila-hover:      #FCF0E8;  /* la fila de la tabla con el ratón encima */
  --resalte:         #BA5817;  /* lo que hay que mirar primero: listón de la fila que pide atención */
  --resalte-suave:   #FCEDE4;  /* el mismo resalte de fondo, para teñir sin gritar */
  --resalte-texto:   #FFFFFF;  /* la tinta que se escribe encima del resalte */

  /* lo que pasa */
  --exito:           #1B7F4B;  /* correcto */
  --exito-fondo:     #EFF6F1;  /* su fondo */
  --exito-relleno:   #46996E;  /* la MANCHA de correcto: barras del cuadro de mando (3:1, no 4.5) */
  --aviso:           #8A5A00;  /* atención */
  --aviso-fondo:     #FBF4E6;  /* su fondo */
  --aviso-relleno:   #BC8420;  /* la MANCHA de atención: barras del cuadro de mando (3:1, no 4.5) */
  --error:           #B3261E;  /* fallo */
  --error-fondo:     #FCEFEE;  /* su fondo */
  --error-relleno:   #C9463C;  /* la MANCHA de fuera de plazo: barras del cuadro de mando (3:1, no 4.5) */
  --info:            #1F5FA8;  /* información */
  --info-fondo:      #EDF3FB;  /* su fondo */
}

[data-tema="oscuro"][data-paleta="naranja"]{
  /* el papel y la tinta */
  --papel:           #170F0A;  /* fondo de la página, de la tarjeta y de cada fila */
  --superficie:      #261A12;  /* bloque apoyado: barra lateral, cabecera de tabla, fila apagada */
  --filete:          #443125;  /* el filete de 1px que SEPARA una fila de la siguiente */
  --filete-fuerte:   #846F61;  /* trazo de los controles: campo, botón secundario, botón de icono */
  --tinta:           #F8F3F0;  /* texto principal, y los filetes de 2px y 3px que agrupan y cierran */
  --tinta-2:         #AB8973;  /* texto de apoyo, rótulo de columna y ayuda del campo */
  --marcador:        #795C49;  /* la sugerencia del campo vacío; el único texto que va a 3:1 y no a 4.5:1 */

  /* el color de marca */
  --acc:             #D5651A;  /* relleno del botón principal */
  --acc-texto:       #170F0A;  /* la etiqueta que va encima de ese relleno */
  --acc-hover:       #E98C4E;  /* ese relleno con el ratón encima */
  --enlace:          #E5742A;  /* los enlaces dentro del contenido */
  --enlace-hover:    #DE691B;  /* el enlace con el ratón encima */
  --foco:            #D5651A;  /* el anillo de foco (2px, siempre separado 2px del control) */
  --activo-fondo:    #412513;  /* fondo del apartado del menú en el que estás */
  --activo-texto:    #E5742A;  /* su texto */
  --activo-filete:   #D5651A;  /* su listón de 3px a la izquierda */
  --cab-filete:      #D5651A;  /* el filete de 2px que cierra la cabecera de la tabla */
  --chip-fondo:      #341F11;  /* fondo de las etiquetas de módulo y de rol */
  --chip-texto:      #DE691B;  /* su texto */
  --chip-filete:     #5D3D28;  /* su contorno */
  --fila-hover:      #3B2414;  /* la fila de la tabla con el ratón encima */
  --resalte:         #D5651A;  /* lo que hay que mirar primero: listón de la fila que pide atención */
  --resalte-suave:   #412513;  /* el mismo resalte de fondo, para teñir sin gritar */
  --resalte-texto:   #170F0A;  /* la tinta que se escribe encima del resalte */

  /* lo que pasa */
  --exito:           #4FBF83;  /* correcto */
  --exito-fondo:     #13251C;  /* su fondo */
  --exito-relleno:   #35895D;  /* la MANCHA de correcto: barras del cuadro de mando (3:1, no 4.5) */
  --aviso:           #D9A441;  /* atención */
  --aviso-fondo:     #2A2010;  /* su fondo */
  --aviso-relleno:   #8F6A22;  /* la MANCHA de atención: barras del cuadro de mando (3:1, no 4.5) */
  --error:           #EF7A72;  /* fallo */
  --error-fondo:     #2C1614;  /* su fondo */
  --error-relleno:   #A2453E;  /* la MANCHA de fuera de plazo: barras del cuadro de mando (3:1, no 4.5) */
  --info:            #6FA8E8;  /* información */
  --info-fondo:      #12202F;  /* su fondo */
}

/* ── grafito — sin color de marca: solo tinta y grises ── */
[data-paleta="grafito"]{
  /* el papel y la tinta */
  --papel:           #FFFFFF;  /* fondo de la página, de la tarjeta y de cada fila */
  --superficie:      #FAFAF8;  /* bloque apoyado: barra lateral, cabecera de tabla, fila apagada */
  --filete:          #E2E2DE;  /* el filete de 1px que SEPARA una fila de la siguiente */
  --filete-fuerte:   #0D0D0D;  /* trazo de los controles: campo, botón secundario, botón de icono */
  --tinta:           #111111;  /* texto principal, y los filetes de 2px y 3px que agrupan y cierran */
  --tinta-2:         #0D0D0D;  /* texto de apoyo, rótulo de columna y ayuda del campo */
  --marcador:        #949494;  /* la sugerencia del campo vacío; el único texto que va a 3:1 y no a 4.5:1 */

  /* el color de marca */
  --acc:             #757575;  /* relleno del botón principal */
  --acc-texto:       #FFFFFF;  /* la etiqueta que va encima de ese relleno */
  --acc-hover:       #5E5E5E;  /* ese relleno con el ratón encima */
  --enlace:          #707070;  /* los enlaces dentro del contenido */
  --enlace-hover:    #0D0D0D;  /* el enlace con el ratón encima */
  --foco:            #757575;  /* el anillo de foco (2px, siempre separado 2px del control) */
  --activo-fondo:    #F1F1EF;  /* fondo del apartado del menú en el que estás */
  --activo-texto:    #0D0D0D;  /* su texto */
  --activo-filete:   #757575;  /* su listón de 3px a la izquierda */
  --cab-filete:      #757575;  /* el filete de 2px que cierra la cabecera de la tabla */
  --chip-fondo:      #F6F6F4;  /* fondo de las etiquetas de módulo y de rol */
  --chip-texto:      #0D0D0D;  /* su texto */
  --chip-filete:     #DCDCD7;  /* su contorno */
  --fila-hover:      #F3F3F1;  /* la fila de la tabla con el ratón encima */
  --resalte:         #757575;  /* lo que hay que mirar primero: listón de la fila que pide atención */
  --resalte-suave:   #F1F1EF;  /* el mismo resalte de fondo, para teñir sin gritar */
  --resalte-texto:   #FFFFFF;  /* la tinta que se escribe encima del resalte */

  /* lo que pasa */
  --exito:           #1B7F4B;  /* correcto */
  --exito-fondo:     #EFF6F1;  /* su fondo */
  --exito-relleno:   #46996E;  /* la MANCHA de correcto: barras del cuadro de mando (3:1, no 4.5) */
  --aviso:           #8A5A00;  /* atención */
  --aviso-fondo:     #FBF4E6;  /* su fondo */
  --aviso-relleno:   #BC8420;  /* la MANCHA de atención: barras del cuadro de mando (3:1, no 4.5) */
  --error:           #B3261E;  /* fallo */
  --error-fondo:     #FCEFEE;  /* su fondo */
  --error-relleno:   #C9463C;  /* la MANCHA de fuera de plazo: barras del cuadro de mando (3:1, no 4.5) */
  --info:            #1F5FA8;  /* información */
  --info-fondo:      #EDF3FB;  /* su fondo */
}

[data-tema="oscuro"][data-paleta="grafito"]{
  /* el papel y la tinta */
  --papel:           #0E0E0D;  /* fondo de la página, de la tarjeta y de cada fila */
  --superficie:      #171715;  /* bloque apoyado: barra lateral, cabecera de tabla, fila apagada */
  --filete:          #2A2A27;  /* el filete de 1px que SEPARA una fila de la siguiente */
  --filete-fuerte:   #696969;  /* trazo de los controles: campo, botón secundario, botón de icono */
  --tinta:           #F2F2F0;  /* texto principal, y los filetes de 2px y 3px que agrupan y cierran */
  --tinta-2:         #878787;  /* texto de apoyo, rótulo de columna y ayuda del campo */
  --marcador:        #616161;  /* la sugerencia del campo vacío; el único texto que va a 3:1 y no a 4.5:1 */

  /* el color de marca */
  --acc:             #828282;  /* relleno del botón principal */
  --acc-texto:       #0E0E0D;  /* la etiqueta que va encima de ese relleno */
  --acc-hover:       #A3A3A3;  /* ese relleno con el ratón encima */
  --enlace:          #8F8F8F;  /* los enlaces dentro del contenido */
  --enlace-hover:    #858585;  /* el enlace con el ratón encima */
  --foco:            #828282;  /* el anillo de foco (2px, siempre separado 2px del control) */
  --activo-fondo:    #232320;  /* fondo del apartado del menú en el que estás */
  --activo-texto:    #8A8A8A;  /* su texto */
  --activo-filete:   #828282;  /* su listón de 3px a la izquierda */
  --cab-filete:      #828282;  /* el filete de 2px que cierra la cabecera de la tabla */
  --chip-fondo:      #1C1C1A;  /* fondo de las etiquetas de módulo y de rol */
  --chip-texto:      #858585;  /* su texto */
  --chip-filete:     #333330;  /* su contorno */
  --fila-hover:      #1F1F1C;  /* la fila de la tabla con el ratón encima */
  --resalte:         #828282;  /* lo que hay que mirar primero: listón de la fila que pide atención */
  --resalte-suave:   #232320;  /* el mismo resalte de fondo, para teñir sin gritar */
  --resalte-texto:   #0E0E0D;  /* la tinta que se escribe encima del resalte */

  /* lo que pasa */
  --exito:           #4FBF83;  /* correcto */
  --exito-fondo:     #13251C;  /* su fondo */
  --exito-relleno:   #35895D;  /* la MANCHA de correcto: barras del cuadro de mando (3:1, no 4.5) */
  --aviso:           #D9A441;  /* atención */
  --aviso-fondo:     #2A2010;  /* su fondo */
  --aviso-relleno:   #8F6A22;  /* la MANCHA de atención: barras del cuadro de mando (3:1, no 4.5) */
  --error:           #EF7A72;  /* fallo */
  --error-fondo:     #2C1614;  /* su fondo */
  --error-relleno:   #A2453E;  /* la MANCHA de fuera de plazo: barras del cuadro de mando (3:1, no 4.5) */
  --info:            #6FA8E8;  /* información */
  --info-fondo:      #12202F;  /* su fondo */
}

/* Red de seguridad: si llegara un matiz que no existe —o ninguno—, el sitio
   no se queda sin colores; hereda el de la casa. paleta_valida() ya lo
   impide en PHP, y esto es el segundo cierre.

   El :not([data-paleta]) es imprescindible: :root es una pseudo-CLASE y
   pesa lo mismo que [data-paleta="x"], así que sin él este bloque empata
   con los ocho matices y, por ir el último, los gana. */
:root:not([data-paleta]){
  /* el papel y la tinta */
  --papel:           #FFFFFF;  /* fondo de la página, de la tarjeta y de cada fila */
  --superficie:      #F5F4F9;  /* bloque apoyado: barra lateral, cabecera de tabla, fila apagada */
  --filete:          #DFDDE9;  /* el filete de 1px que SEPARA una fila de la siguiente */
  --filete-fuerte:   #0B0B0F;  /* trazo de los controles: campo, botón secundario, botón de icono */
  --tinta:           #171230;  /* texto principal, y los filetes de 2px y 3px que agrupan y cierran */
  --tinta-2:         #0A0911;  /* texto de apoyo, rótulo de columna y ayuda del campo */
  --marcador:        #978FBC;  /* la sugerencia del campo vacío; el único texto que va a 3:1 y no a 4.5:1 */

  /* el color de marca */
  --acc:             #755DEF;  /* relleno del botón principal */
  --acc-texto:       #FFFFFF;  /* la etiqueta que va encima de ese relleno */
  --acc-hover:       #593CEC;  /* ese relleno con el ratón encima */
  --enlace:          #6D53EE;  /* los enlaces dentro del contenido */
  --enlace-hover:    #060217;  /* el enlace con el ratón encima */
  --foco:            #755DEF;  /* el anillo de foco (2px, siempre separado 2px del control) */
  --activo-fondo:    #E7E3FC;  /* fondo del apartado del menú en el que estás */
  --activo-texto:    #060217;  /* su texto */
  --activo-filete:   #755DEF;  /* su listón de 3px a la izquierda */
  --cab-filete:      #755DEF;  /* el filete de 2px que cierra la cabecera de la tabla */
  --chip-fondo:      #EFECFD;  /* fondo de las etiquetas de módulo y de rol */
  --chip-texto:      #060217;  /* su texto */
  --chip-filete:     #CDC6F1;  /* su contorno */
  --fila-hover:      #EBE8FC;  /* la fila de la tabla con el ratón encima */
  --resalte:         #755DEF;  /* lo que hay que mirar primero: listón de la fila que pide atención */
  --resalte-suave:   #E7E3FC;  /* el mismo resalte de fondo, para teñir sin gritar */
  --resalte-texto:   #FFFFFF;  /* la tinta que se escribe encima del resalte */

  /* lo que pasa */
  --exito:           #1B7F4B;  /* correcto */
  --exito-fondo:     #EFF6F1;  /* su fondo */
  --exito-relleno:   #46996E;  /* la MANCHA de correcto: barras del cuadro de mando (3:1, no 4.5) */
  --aviso:           #8A5A00;  /* atención */
  --aviso-fondo:     #FBF4E6;  /* su fondo */
  --aviso-relleno:   #BC8420;  /* la MANCHA de atención: barras del cuadro de mando (3:1, no 4.5) */
  --error:           #B3261E;  /* fallo */
  --error-fondo:     #FCEFEE;  /* su fondo */
  --error-relleno:   #C9463C;  /* la MANCHA de fuera de plazo: barras del cuadro de mando (3:1, no 4.5) */
  --info:            #1F5FA8;  /* información */
  --info-fondo:      #EDF3FB;  /* su fondo */
}

:root[data-tema="oscuro"]:not([data-paleta]){
  /* el papel y la tinta */
  --papel:           #0C0A17;  /* fondo de la página, de la tarjeta y de cada fila */
  --superficie:      #161226;  /* bloque apoyado: barra lateral, cabecera de tabla, fila apagada */
  --filete:          #2A2544;  /* el filete de 1px que SEPARA una fila de la siguiente */
  --filete-fuerte:   #696387;  /* trazo de los controles: campo, botón secundario, botón de icono */
  --tinta:           #F1F0F8;  /* texto principal, y los filetes de 2px y 3px que agrupan y cierran */
  --tinta-2:         #857CB1;  /* texto de apoyo, rótulo de columna y ayuda del campo */
  --marcador:        #60568F;  /* la sugerencia del campo vacío; el único texto que va a 3:1 y no a 4.5:1 */

  /* el color de marca */
  --acc:             #856FF1;  /* relleno del botón principal */
  --acc-texto:       #0C0A17;  /* la etiqueta que va encima de ese relleno */
  --acc-hover:       #A494F4;  /* ese relleno con el ratón encima */
  --enlace:          #917DF2;  /* los enlaces dentro del contenido */
  --enlace-hover:    #816AF0;  /* el enlace con el ratón encima */
  --foco:            #856FF1;  /* el anillo de foco (2px, siempre separado 2px del control) */
  --activo-fondo:    #1B1341;  /* fondo del apartado del menú en el que estás */
  --activo-texto:    #856FF1;  /* su texto */
  --activo-filete:   #856FF1;  /* su listón de 3px a la izquierda */
  --cab-filete:      #856FF1;  /* el filete de 2px que cierra la cabecera de la tabla */
  --chip-fondo:      #171134;  /* fondo de las etiquetas de módulo y de rol */
  --chip-texto:      #816AF0;  /* su texto */
  --chip-filete:     #31285D;  /* su contorno */
  --fila-hover:      #1A143B;  /* la fila de la tabla con el ratón encima */
  --resalte:         #856FF1;  /* lo que hay que mirar primero: listón de la fila que pide atención */
  --resalte-suave:   #1B1341;  /* el mismo resalte de fondo, para teñir sin gritar */
  --resalte-texto:   #0C0A17;  /* la tinta que se escribe encima del resalte */

  /* lo que pasa */
  --exito:           #4FBF83;  /* correcto */
  --exito-fondo:     #13251C;  /* su fondo */
  --exito-relleno:   #35895D;  /* la MANCHA de correcto: barras del cuadro de mando (3:1, no 4.5) */
  --aviso:           #D9A441;  /* atención */
  --aviso-fondo:     #2A2010;  /* su fondo */
  --aviso-relleno:   #8F6A22;  /* la MANCHA de atención: barras del cuadro de mando (3:1, no 4.5) */
  --error:           #EF7A72;  /* fallo */
  --error-fondo:     #2C1614;  /* su fondo */
  --error-relleno:   #A2453E;  /* la MANCHA de fuera de plazo: barras del cuadro de mando (3:1, no 4.5) */
  --info:            #6FA8E8;  /* información */
  --info-fondo:      #12202F;  /* su fondo */
}

/* ═══════════════════════════════════════════════════════════════════════════
   comun/estilos/componentes.css — las piezas de las que se hacen las páginas.

   Regla que gobierna este fichero entero: aquí NO se escribe ni un color, ni un
   radio, ni una medida de espaciado a mano. Todo sale de tokens.css con var().
   Si algo necesita un valor que no existe como token, se añade el token; no se
   escribe el valor aquí. Es lo que permite que cada cliente tenga su portal en
   su color sin abrir este fichero.

   ── La dirección (S3.5, elegida por Fabio el 14/08/2026) ────────────────────

   «Rejilla Suiza · morado con protagonismo». Tres cosas la definen, y las tres
   están implementadas aquí:

     1. CERO SOMBRAS. No hay elevación; hay rejilla. Lo que en otros sistemas
        se separa con una sombra, aquí se separa con un filete.
     2. La jerarquía la hace el GROSOR del filete, no el color:
          --f-separa (1px)  separa una fila de la siguiente
          --f-agrupa (2px)  agrupa: cierra la cabecera de una tabla, subraya
                            el rótulo de una tarjeta
          --f-cierra (3px)  cierra bloque: abre una sección, marca el apartado
                            del menú en el que estás
     3. El peso también informa: --p-fuerte (700) es para los títulos y para
        LO QUE SE PULSA. Si algo está en negrita y no es un título, se pulsa.

   El color entra en cinco sitios y en ninguno más: el botón principal, los
   enlaces, el anillo de foco, el apartado activo del menú y las etiquetas de
   módulo. Fuera de ahí, papel y tinta.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── base ────────────────────────────────────────────────────────────────── */
*{ margin:0; padding:0; box-sizing:border-box }

html{ -webkit-text-size-adjust:100% }

body{
  min-height:100dvh;
  font-family:var(--f-texto);
  font-weight:var(--p-normal);
  font-size:var(--t-cuerpo);
  line-height:1.45;
  color:var(--tinta);
  background:var(--papel);
  -webkit-font-smoothing:antialiased;
}

a{ color:var(--enlace); text-decoration:none }
a:hover{ color:var(--enlace-hover); text-decoration:underline }

/* ── el tamaño POR DEFECTO de un icono (S8.1, 21/08/2026) ──────────────────
   `icono()` escupe `<svg viewBox="0 0 24 24">` sin `width` ni `height`, así que
   quien no le pone una regla CSS no obtiene «un icono pequeño»: obtiene un SVG
   que se estira hasta llenar a su padre, con relleno negro y sin trazo. En S8
   `.zona-fichero` se quedó sin regla y el dibujo de subir salió a **875×875 px**
   —medido—, dejando el campo de subir una factura ocupando la pantalla entera.
   Y las filas del Catálogo salían con un cuadrado negro por icono, por lo mismo.

   Esto es el suelo, y por eso va aquí arriba y no junto a una pieza: la docena
   de reglas `.loquesea svg{…}` de más abajo siguen mandando —empatan en peso y
   ganan por orden, o pesan más—, pero la pantalla que se olvide de escribir la
   suya ya no puede reventar. Un fallo que solo se ve mirando no puede depender
   de acordarse. */
svg[aria-hidden="true"]{
  flex:none; width:16px; height:16px;
  stroke:currentColor; stroke-width:1.7; fill:none;
  stroke-linecap:round; stroke-linejoin:round;
}

/* Foco visible en TODO lo enfocable, y SEPARADO del control. La separación no
   es estética: pegado a un botón de color, el anillo se mide contra ese color y
   puede quedarse en 1,2:1. Separado, se mide contra el papel de detrás. */
:where(a,button,input,select,textarea,summary,[tabindex]):focus-visible{
  outline:var(--f-agrupa) solid var(--foco); outline-offset:2px;
}

/* Salto al contenido: invisible hasta que se llega con el tabulador. */
.saltar{
  position:absolute; left:var(--e4); top:calc(var(--e4) * -4); z-index:10;
  padding:var(--e2) var(--e4); border-radius:var(--r);
  background:var(--acc); color:var(--acc-texto); font-weight:var(--p-fuerte);
  transition:top .15s ease;
}
.saltar:focus{ top:var(--e4); text-decoration:none }

/* Texto que se lee pero no se ve. Para los controles que enseñan un icono y
   necesitan una palabra que un lector de pantalla pueda decir. No se usa
   display:none: eso también lo esconde del lector. */
.solo-lectores{
  position:absolute; width:1px; height:1px; overflow:hidden;
  clip-path:inset(50%); white-space:nowrap;
}
/* ── y el ancla que hace que ese `absolute` no se escape ──────────────────
   Este es el fallo más caro del sistema y ya se había pagado TRES veces por
   separado —la rejilla del mes, la matriz de la ficha y ahora las cuatro
   pantallas de tabla—, así que se arregla de una vez y en un solo sitio.

   Qué pasa: `.solo-lectores` es `position:absolute`, y un absoluto sin ancestro
   posicionado se ancla al primero que lo esté. En SmartDesk ese es SIEMPRE el
   `.marco`, que es `position:relative` para el menú plegado. Su posición
   estática, en cambio, cae donde esté el botón que lo contiene: en la fila 200
   de Empresas, a 11.380 px del principio. Resultado medido: el DOCUMENTO se
   hacía 11.381 px de alto y la página entera se desplazaba, además de la tabla.
   Dos barras sobre la misma pantalla, que es justo lo que quitó `$pantallaFija`.

   `:has(> …)` dice «el que lleve uno dentro es su ancla». Una línea, y ya no hay
   que acordarse de poner `position:relative` cada vez que se escribe un botón
   con icono. Medido en Empresas: documento de 11.381 px a 800, los mismos que
   la ventana, y la tabla sigue desplazándose por dentro. */
:has(> .solo-lectores),
/* El mismo recorte de tres líneas se usa en otros tres sitios, y cada uno
   necesita su ancla por lo mismo. Se listan aquí y no junto a cada pieza para
   que se vean los cuatro de un vistazo el día que aparezca un quinto. */
.segmentos,                 /* el radio de verdad del conmutador de tema. Este
                               era el que quedaba: al fondo de una barra lateral
                               de 684 px, empujaba el documento a 651 en una
                               ventana de 560. Medido: 91 px de página fantasma */
.pestanas a,                /* el nombre de la pestaña, recortado en el móvil */
.mes-del-anio .falta-mes    /* «sin presentar», recortado por debajo de 560 px */
{ position:relative }

/* ── el bloque ────────────────────────────────────────────────────────────
   La pieza de la que está hecho todo: papel con un filete alrededor. Antes de
   S3.5 esto era `.cristal` y llevaba desenfoque; el cristal se fue con la
   dirección vieja, pero el nombre de la clase se cambió también, porque una
   clase que se llama cristal y no es cristal miente a quien lee el HTML. */
.bloque{
  background:var(--papel);
  border:var(--f-separa) solid var(--filete);
  border-radius:var(--r);
}
.tarjeta{ padding:var(--e5) var(--e6) }
/* El mismo relleno, igual por los cuatro lados. Existe porque en S8 esto se
   escribió tres veces como `style="padding:var(--e5)"` y la CSP lo tiró: el
   atributo `style` no se aplica en SmartDesk (trampa nº 32). Si hace falta
   relleno, es una clase. */
.acolchado{ padding:var(--e5) }

/* ── disposición ──────────────────────────────────────────────────────────
   El armazón mide EXACTAMENTE la ventana y no más: `height:100dvh` y ni una
   barra de desplazamiento en la página. Quien puede desplazarse es cada
   columna por dentro, y solo si su contenido no cabe.

   Nada de `max-width` centrado: esto es una herramienta de trabajo. El menú va
   pegado a la izquierda y el contenido se lleva todo el ancho que haya. Lo que
   sí necesita medida de lectura son los párrafos largos, y esos la piden ellos.

   La regla se invierte en móvil (corte de 900px): allí la barra deja de ser
   columna, se convierte en menú de arriba y la página vuelve a desplazarse
   entera, que es lo que espera un dedo. */
.marco{
  display:grid; grid-template-columns:var(--ancho-lateral) minmax(0,1fr);
  gap:var(--e4); padding:var(--e4);
  height:100dvh; align-items:stretch;
  /* El ancla del menú plegado, que al desplegarse se sale de su columna y flota
     por encima del contenido. Sin esto se anclaría al documento. */
  position:relative;
}
/* La columna de la derecha envuelve el contenido Y el pie: se desplazan juntos
   y solo ellos. `min-height:0` es imprescindible — sin él, un hijo de un grid
   se niega a encoger por debajo de su contenido y el desbordamiento se escapa
   al cuerpo, que es justo lo que se quiere evitar. */
.columna{
  display:flex; flex-direction:column; min-height:0; min-width:0;
  overflow-y:auto; overscroll-behavior:contain;
  /* El hueco de la barra de desplazamiento se reserva SIEMPRE, se use o no.
     Sin esto, una pantalla que se desplaza mide 15 px menos de ancho que una
     que no, y al cambiar de pestaña dentro del mismo módulo todo el contenido
     —la cinta de pestañas incluida— salta de lado. Medido en Pedidos: la
     columna daba 1.141 px en Ajustes y 1.156 en la lista. */
  scrollbar-gutter:stable;
}
/* Cada uno en SU columna, dicho a mano y no dejado a la colocación automática.
   Cuesta dos líneas y evita un fallo que ya se pagó una vez: con el menú
   plegado, `.lateral` es `position:absolute` y sale del flujo, así que la
   rejilla se encontraba un solo hijo y lo metía en la primera pista —el
   contenido entero aplastado en 60 px—. Fijadas las dos, da igual si una está
   en el flujo o no. */
.marco > .lateral{ grid-column:1 }
.marco > .columna{ grid-column:2 }
/* Las pantallas de acceso son de una sola columna y no llevan menú: allí la
   columna vuelve a la primera pista. Lo mismo hace el móvil, más abajo. */
.marco-acceso > .columna{ grid-column:1 }
.contenido{ display:flex; flex-direction:column; gap:var(--e4); min-width:0; flex:1 0 auto }

/* ── pantalla fija: la que mide exactamente la ventana (S5.1, 2ª ronda) ────
   La columna deja de desplazarse y el que se desplaza es UN solo trozo de
   dentro. Lo pide `$pantallaFija = true` en la pantalla (ver cabecera.php).

   Cómo se reparte el alto, que es lo único que hay que entender:

     .columna.fija        no se desplaza NUNCA          overflow:hidden
       .contenido         reparte lo que hay            flex:1, min-height:0
         …cabecera, pestañas, barra, filtros…           flex:none  (miden lo suyo)
         .crece                                         flex:1, min-height:0
           …y dentro, quien lleva el overflow:auto
       .pie                                             flex:none

   `min-height:0` en los dos sitios no es adorno y es el error clásico de esta
   maqueta: un hijo de flex se niega por defecto a encoger por debajo de su
   contenido, así que sin él la tabla empuja hacia abajo, la columna crece más
   que la ventana y vuelve el desplazamiento que se quería quitar.

   `.crece` la pone la pantalla en el trozo que tiene que estirarse. Solo puede
   haber uno: dos elementos peleándose por el hueco que sobra es como se acaba
   con una tabla de 40 px. */
.columna.fija{ overflow:hidden }
.columna.fija .contenido{ flex:1 1 auto; min-height:0; overflow:hidden; gap:var(--e3) }
.columna.fija .contenido > *{ flex:none }
.columna.fija .contenido > .crece{ flex:1 1 auto; min-height:0; display:flex;
                                   flex-direction:column; gap:var(--e3) }
/* El pie se queda, pero más fino: en una pantalla que no se desplaza, cada
   píxel que se lleva el pie se lo quita a la tabla. */
.columna.fija .pie{ flex:none; padding:var(--e2) var(--e2) 0 }
/* El `.crece` que además se desplaza por dentro. Lo usan las cuatro pantallas
   que son UNA tabla: Empresas, Obligaciones, Grupos y Equipo. En el mes no se
   pone aquí porque allí el que desplaza está más adentro —la tabla o el panel—,
   y el `.crece` solo reparte. */
.columna.fija .contenido > .crece.desborda{ overflow:auto; overscroll-behavior:contain }
/* ── y lo de dentro NO encoge, desborda ────────────────────────────────────
   `.crece` es una columna flex, así que sus hijos son elementos flex. Un hijo
   flex que lleve `overflow:hidden` —y la lista de Grupos lo lleva— tiene tamaño
   mínimo automático CERO, así que en vez de desbordar el marco y sacar su barra,
   **encoge y se recorta**. Efecto exacto, y es la queja de Fabio: la tabla no se
   ve entera y no hay ninguna barra con la que llegar al final. Medido en Grupos
   con quince grupos: el marco decía `scrollHeight` 479 sobre `clientHeight` 479
   —«aquí cabe todo»— con más de novecientos píxeles de filas escondidas.

   Con `flex:0 0 auto` cada hijo mide lo suyo, el marco desborda y aparece la
   barra. Vale para los cuatro: las otras tres pantallas se salvaban de casualidad
   porque su `.tabla` no lleva `overflow`. */
.columna.fija .contenido > .crece.desborda > *{ flex:0 0 auto }

/* ── títulos ─────────────────────────────────────────────────────────────── */
.titulo-pagina{
  font-weight:var(--p-fuerte); font-size:var(--t-titulo); letter-spacing:-.015em;
}
/* La cabecera de pantalla: SOLO el título, y siempre del mismo alto (S5.1 §1.7).
   Hasta ahora llevaba también los botones de la pantalla, y ahí estaba el
   problema que contó Fabio: cada pantalla tiene un número distinto de botones,
   en una ventana estrecha se le iban a una segunda línea, y la cabecera crecía
   y encogía al cambiar de pestaña. Cambiar de pestaña no puede mover el sitio
   donde está todo lo demás.

   Los botones se han repartido por su pantalla, cada uno donde se usa: junto al
   buscador en Empresas, bajo las pestañas en Catálogo, en la fila del mes en el
   Cuadro de mando. El filete de 3px sigue siendo el que ABRE la sección. */
.cabecera-pagina{
  display:flex; align-items:center; gap:var(--e3); flex-wrap:nowrap;
  min-height:44px; padding-bottom:var(--e3);
  border-bottom:var(--f-cierra) solid var(--tinta);
}
.cabecera-pagina .titulo-pagina{
  min-width:0;
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
/* En pantalla estrecha, la cabecera SÍ envuelve. El alto fijo de arriba existe
   para que cambiar de pestaña no mueva de sitio todo lo demás, y eso es un
   problema de escritorio; en el móvil lo que pasaba era otra cosa: con un botón
   al lado, «Pasadas del cron» se cortaba en «Pasadas del…» a 375 px. Un título
   recortado con puntos suspensivos no dice en qué pantalla estás, que es lo
   único para lo que sirve. Se vio mirando la pantalla en el móvil (S10). */
@media (max-width: 700px){
  .cabecera-pagina{ flex-wrap:wrap }
  .cabecera-pagina .titulo-pagina{ white-space:normal; overflow:visible }
}
/* El subdominio va pegado al nombre y el resto —pastillas y botones— se va a la
   derecha. Desde S8.1 las DOS pestañas de la ficha de un cliente comparten esta
   cabecera (`comun/plantilla/piezas_cliente.php`); antes cada una tenía la suya
   y al cambiar de pestaña el título cambiaba de tamaño y de sitio. */
.cabecera-pagina .nif-ficha{ font-family:var(--f-dato); font-size:var(--t-apoyo);
                             color:var(--tinta-2); flex:none }
.cabecera-pagina .nif-ficha ~ *{ flex:none }
.cabecera-pagina .nif-ficha + *{ margin-left:auto }
/* Fila de acciones de la pantalla, debajo de la cabecera o de las pestañas.
   Todo a la misma altura y alineado a la izquierda, que es lo que pidió Fabio
   para el móvil y no estorba en escritorio. */
.acciones-pantalla{
  display:flex; align-items:center; gap:var(--e2); flex-wrap:wrap;
}
.acciones-pantalla .a-la-derecha{ margin-left:auto }
/* «Todos a la misma altura» (§2.2), y hay que decirlo: el conmutador de
   Rejilla/Lista se construye con `.segmentos`, que se mide por el alto de su
   etiqueta y salía 5 px más bajo que los botones de al lado. Puestos en fila,
   cinco píxeles de desnivel se ven perfectamente. */
.acciones-pantalla .segmentos{ min-height:40px; align-items:stretch }
.acciones-pantalla .segmentos a,
.acciones-pantalla .segmentos label{ display:inline-flex; align-items:center }

/* Rótulo de sección: dentro de una tarjeta, y con el filete de 2px que AGRUPA
   lo que viene debajo. */
.grupo{
  font-size:var(--t-micro); font-weight:var(--p-fuerte); letter-spacing:.07em;
  text-transform:uppercase; color:var(--tinta-2);
  padding-bottom:var(--e3); border-bottom:var(--f-agrupa) solid var(--tinta);
}

/* ── barra lateral ───────────────────────────────────────────────────────── */
.lateral{
  display:flex; flex-direction:column; gap:2px;
  /* Los lados van a --e2 y no a --e4 por culpa del menú plegado: la banda mide
     60 px y con 16 px a cada lado le quedaban 26 px por dentro, donde no cabe
     una fila de 36 con un icono de 16 que empieza en el 13. El icono se salía
     de su propio fondo por la derecha, y eso es lo que se veía como «el fondo
     azul del apartado activo llega hasta la mitad». Con 8 px caben los 36.
     De paso, el menú fijo gana 16 px de texto. */
  padding:var(--e4) var(--e2);
  background:var(--superficie);
  border:var(--f-separa) solid var(--filete);
  border-radius:var(--r);
  /* Ocupa su columna entera y no se mueve. Si la ventana es tan baja que el
     menú no cabe, se desplaza ÉL por dentro; la página sigue quieta. */
  min-height:0; overflow-y:auto; overscroll-behavior:contain;
}
.lateral .marca{
  display:flex; align-items:center; gap:var(--e2);
  padding:var(--e1) var(--e2) var(--e5);
  font-weight:var(--p-fuerte); font-size:18px; letter-spacing:-.015em;
}
.lateral .marca a{ color:var(--tinta) }
.lateral .marca a:hover{ text-decoration:none; opacity:.8 }
/* El cuadradito de la marca: en esta dirección no hay logotipo de color, hay un
   sólido de tinta. Es lo más barato que se puede reconocer a un metro. */
.lateral .marca em{ font-style:normal; color:var(--acc) }

/* En escritorio este envoltorio no existe: `display:contents` lo borra del
   cálculo y deja `nav` y `.abajo` como hijos directos de la columna, que es lo
   que hace falta para que el `margin-top:auto` de `.abajo` siga empujando. Solo
   se materializa en el móvil, para poder animar la apertura del menú. */
.plegable-movil, .plegable-movil > .dentro{ display:contents }

.lateral nav{ display:flex; flex-direction:column; gap:2px }
/* ⚠ `>` y no un descendiente cualquiera. Hasta el 19/08 esto era `.lateral nav
   span` a secas, y ese selector cazaba TAMBIÉN al `<span class="texto-menu">`
   que envuelve el texto dentro de cada entrada desde S5.1. Es decir: el texto
   se llevaba otra vez el `padding:8px 10px`, el `min-height:36px` y el filete
   de 3 px de su propia entrada. Medido en el navegador, un selector de más
   salía por tres sitios que parecían tres fallos distintos:
     · cada fila medía 52 px en vez de 36, y 72 las de dos palabras;
     · al texto le quedaban 23 px menos, así que «Obligaciones fiscales» y
       «Mi cuenta» se partían en DOS LÍNEAS —y al plegar y desplegar el menú,
       volvían a una y el bloque entero daba un salto—;
     · la barra medía 225 px por dentro de sus 219, que es la franja de
       desplazamiento horizontal que se veía debajo del menú fijo. */
.lateral nav > a,
.lateral nav > span{
  display:flex; align-items:center; gap:10px;
  padding:8px 10px; border-radius:var(--r);
  font-size:var(--t-cuerpo); font-weight:var(--p-fuerte); color:var(--tinta-2);
  min-height:36px;
  border-left:var(--f-cierra) solid transparent;
}
.lateral nav > a:hover{ background:var(--fila-hover); color:var(--tinta); text-decoration:none }
/* El apartado en el que estás: fondo, texto y listón de 3px. Tres señales, no
   solo el color — quien no distingue el morado sigue viendo el listón. */
.lateral nav > a[aria-current="page"]{
  background:var(--activo-fondo); color:var(--activo-texto);
  border-left-color:var(--activo-filete);
}
/* Entrada sin destino todavía. Apagada y no enfocable: un enlace que no lleva a
   ningún sitio es peor que una entrada honestamente apagada. Ya no lleva la
   palabra «pronto» al lado (19/08): con cuatro entradas apagadas era un menú
   lleno de promesas; con una, el color apagado ya lo dice solo.

   Va con --marcador y no con --tinta-2, y eso hay que explicarlo porque parece
   lo contrario de lo que toca. Medido en el navegador: en los temas CLAROS
   `--tinta-2` (#090B11) es más oscuro que `--tinta` (#121930), así que la
   entrada apagada salía a 18,17:1 contra el papel — exactamente el mismo negro
   que una entrada viva. Mientras llevaba la palabra «pronto» al lado daba igual;
   sin ella, la única diferencia era el grosor de la letra, y eso no se ve.

   `--marcador` es el único tono pensado para ir a 3:1 y no a 4,5:1 —el texto de
   sugerencia de un campo vacío—, y esto es justo ese caso: una entrada INACTIVA,
   que es lo que la WCAG 1.4.3 deja expresamente fuera del mínimo de contraste.
   Medido con el arreglo puesto, sobre el fondo de la barra (--superficie, que
   no es el papel para el que se calculó el tono): 2,77:1 en claro y 2,76:1 en
   oscuro, contra los 18,17:1 y 4,97:1 de las entradas vivas. Se lee, y se ve
   que está apagada — que es lo que había que conseguir sin la palabra.

   ⚠ Lo de `--tinta-2` no es cosa de esta regla: pasa en las CATORCE paletas
   claras y afecta a todo el «texto de apoyo» del sitio, que sale negro en vez
   de gris. Eso se arregla en el generador (diseno/direcciones/generar_tokens.py)
   y en su fase, no aquí a mano: tokens.css no se edita. */
.lateral nav > .pronto{ color:var(--marcador); font-weight:var(--p-normal); cursor:default }
/* El nombre de un módulo lo pone el catálogo y puede ser tan largo como quiera:
   antes de partirse en dos líneas —que es lo que descuadra la barra— se recorta
   con puntos suspensivos. El `title` de la entrada lo dice entero. */
.texto-menu{ min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.lateral svg{ flex:none; width:16px; height:16px; stroke:currentColor;
              stroke-width:1.7; fill:none; stroke-linecap:round; stroke-linejoin:round }

.lateral .abajo{
  margin-top:auto; padding-top:var(--e4);
  border-top:var(--f-separa) solid var(--filete);
  display:flex; flex-direction:column; gap:var(--e3);
}
/* ── tu nombre, que es la puerta de Mi cuenta (19/08) ──────────────────────
   Facturas y Mi cuenta salieron del menú y entraron aquí: se llega a ellas
   pulsando tu nombre, abajo del todo, que es donde lo busca cualquiera por
   costumbre de otras aplicaciones. Por eso `.yo` se dibuja como una entrada más
   del menú —mismo icono, mismo hueco, mismo fondo al pasar el ratón—: si va a
   comportarse como una entrada, tiene que parecerlo.

   Mientras la pantalla no exista (F2) el HTML pone un <div> en vez de un <a>:
   se ve igual, pero ni se ilumina ni se puede pulsar ni se enfoca con el
   tabulador. Un sitio que se ilumina y no lleva a ningún lado se pulsa una vez
   y ya no se vuelve a probar. */
.quien{ display:flex; flex-direction:column; gap:var(--e2) }
.yo{
  display:flex; align-items:center; gap:10px; min-width:0; min-height:36px;
  padding:8px 10px; border-radius:var(--r);
  border-left:var(--f-cierra) solid transparent;
  color:var(--tinta);
}
a.yo:hover{ background:var(--fila-hover); text-decoration:none }
a.yo[aria-current="page"]{
  background:var(--activo-fondo); color:var(--activo-texto);
  border-left-color:var(--activo-filete);
}
/* Mientras es un <div> —o sea, mientras la pantalla no existe— el dibujo va del
   mismo gris que las entradas apagadas del menú. Hace falta desde que el icono
   se ve también con la barra plegada: a plena tinta sería el único icono del pie
   que promete llevar a algún sitio y no lleva. Tu NOMBRE no se apaga: eso no es
   un control, es quién eres. */
div.yo{ color:var(--marcador); cursor:default }
.yo-texto{ display:flex; flex-direction:column; min-width:0 }
.quien .nombre{ font-weight:var(--p-fuerte); font-size:var(--t-cuerpo); color:var(--tinta) }
.quien .de-donde{ color:var(--tinta-2); font-size:var(--t-apoyo) }
/* Un nombre largo o una razón social entera no ensanchan la barra: se recortan,
   igual que el nombre de un módulo. */
.quien .nombre, .quien .de-donde{
  display:block; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}

/* ── Salir, dibujado como una entrada más del menú (20/08) ─────────────────
   Estaba dentro de `.quien` y era un `.boton fantasma ancho`. Salió de ahí
   porque con el menú plegado `.quien` se desvanece entero y el botón se iba con
   él: no había forma de cerrar sesión sin desplegar la barra. Y de paso deja de
   parecer un ajuste de tu ficha, que es lo que era puesto ahí dentro.

   Se dibuja igual que un enlace del menú —mismo hueco, mismo icono, mismo
   fondo al pasar el ratón— porque va a comportarse como uno. En rojo solo al
   pasar por encima: es la única acción del menú que se deshace volviendo a
   entrar, y anunciarla en rojo todo el rato sería gritar. */
.lateral .salir button{
  display:flex; align-items:center; gap:10px; width:100%;
  padding:8px 10px; border-radius:var(--r);
  border:0; border-left:var(--f-cierra) solid transparent;
  background:transparent; color:var(--tinta-2);
  font-family:var(--f-texto); font-size:var(--t-cuerpo); text-align:left;
  cursor:pointer; min-height:36px;
}
.lateral .salir button:hover{ background:var(--error-fondo); color:var(--error) }
.lateral .salir button:focus-visible{ outline:2px solid var(--acc); outline-offset:2px }

/* botón que abre el menú en móvil; en escritorio no existe */
.abrir-menu{ display:none }

/* ── el menú plegado: solo iconos, y se despliega al pasar el ratón (S5.1) ──
   Cómo funciona, que tiene una decisión dentro:

   La COLUMNA de la rejilla se queda en 60 px pase lo que pase, y lo que crece al
   pasar el ratón es el menú, que se sale de su columna y flota por encima del
   contenido. Si creciera la columna, las 24 columnas de la rejilla de enero se
   recolocarían enteras cada vez que el ratón roza el menú de camino a otro
   sitio, y eso marea. Aquí el contenido no se entera de nada.

   `:focus-within` va junto a `:hover` y no es un extra: sin él, quien navega con
   el tabulador entra en un menú que sigue encogido y no puede leer dónde está.

   El texto se desvanece con `opacity` y no con `display:none` — el nombre
   accesible del enlace ES ese texto (ver lateral.php). */
[data-menu="plegado"] .marco{
  grid-template-columns:var(--ancho-lateral-plegado) minmax(0,1fr);
}
/* ⚠ `left:0` y no `left:var(--e4)`, y arriba y abajo justo al revés. No es una
   incoherencia, es cómo se coloca un absoluto dentro de una REJILLA:

   `.marco > .lateral{ grid-column:1 }` le da a la barra una posición de rejilla
   definida, y entonces su bloque contenedor deja de ser el marco entero y pasa
   a ser SU CELDA (CSS Grid §9.2) — pero solo en el eje que está definido. El
   horizontal lo está: la celda empieza donde acaba el relleno del marco. El
   vertical no, así que ahí el bloque contenedor sigue siendo el marco de borde
   a borde y `top`/`bottom` sí tienen que valer --e4.

   Con `left:var(--e4)` la barra se sumaba dos veces el relleno: se pintaba 16 px
   más a la derecha, se comía entero el hueco que la separa del contenido y se le
   pegaba encima. Medido: banda de 32 a 92 px y contenido empezando en 92. */
[data-menu="plegado"] .lateral{
  position:absolute; left:0; top:var(--e4); bottom:var(--e4);
  width:var(--ancho-lateral-plegado); z-index:30;
  overflow-x:hidden;
  transition:width var(--mov-normal) var(--curva);
}
[data-menu="plegado"] .lateral:hover,
[data-menu="plegado"] .lateral:focus-within{ width:var(--ancho-lateral) }

/* Lo que se desvanece es el TEXTO de tu nombre, no el bloque entero (20/08).
   Hasta aquí se iba `.quien` completo, y eso dejaba 54 px de nada en mitad del
   pie de la barra plegada: la única entrada del menú sin icono a la vista era
   justamente la puerta de Mi cuenta. Ahora se queda su dibujo, como el resto, y
   solo se van las dos líneas de texto. */
[data-menu="plegado"] .texto-menu,
[data-menu="plegado"] .marca-larga,
[data-menu="plegado"] .yo-texto,
[data-menu="plegado"] .chincheta{
  opacity:0; transition:opacity var(--mov-rapido) var(--curva);
}
[data-menu="plegado"] .lateral:hover .texto-menu,
[data-menu="plegado"] .lateral:hover .marca-larga,
[data-menu="plegado"] .lateral:hover .yo-texto,
[data-menu="plegado"] .lateral:hover .chincheta,
[data-menu="plegado"] .lateral:focus-within .texto-menu,
[data-menu="plegado"] .lateral:focus-within .marca-larga,
[data-menu="plegado"] .lateral:focus-within .yo-texto,
[data-menu="plegado"] .lateral:focus-within .chincheta{ opacity:1 }

/* ── el tema con el menú plegado: el icono del que está puesto (20/08) ─────
   Antes `.control-tema` se desvanecía entero, así que en 60 px el pie de la
   barra se quedaba con dos iconos de administración sueltos en medio y nada
   más — «se ve raro que estén ahí en el medio solos», dijo Fabio.

   Ahora se queda UNA cosa: el icono del tema que está elegido. Y se hace sin
   JavaScript, con `input:checked + label`: el conmutador ya son tres radios de
   verdad, así que el navegador sabe cuál está marcado sin que nadie se lo
   cuente. Al desplegar la barra vuelven los tres y el rótulo.

   El rótulo «Tema» sí se desvanece: es una palabra, y en la barra plegada no
   hay sitio para palabras. */
[data-menu="plegado"] .control-tema > .grupo{
  opacity:0; transition:opacity var(--mov-rapido) var(--curva);
}
[data-menu="plegado"] .lateral:hover .control-tema > .grupo,
[data-menu="plegado"] .lateral:focus-within .control-tema > .grupo{ opacity:1 }

[data-menu="plegado"] .segmentos{ border-color:transparent; background:transparent }
[data-menu="plegado"] .segmentos label{ display:none }
[data-menu="plegado"] .segmentos input:checked + label{ display:flex }
[data-menu="plegado"] .lateral:hover .segmentos,
[data-menu="plegado"] .lateral:focus-within .segmentos{
  border-color:var(--filete); background:var(--superficie);
}
[data-menu="plegado"] .lateral:hover .segmentos label,
[data-menu="plegado"] .lateral:focus-within .segmentos label{ display:flex }

/* El rótulo corto de la marca solo existe cuando el menú está plegado y quieto. */
.marca-corta{ display:none }
[data-menu="plegado"] .marca-corta{ display:inline }
[data-menu="plegado"] .marca-larga{ position:absolute }
[data-menu="plegado"] .lateral:hover .marca-corta,
[data-menu="plegado"] .lateral:focus-within .marca-corta{ display:none }
[data-menu="plegado"] .lateral:hover .marca-larga,
[data-menu="plegado"] .lateral:focus-within .marca-larga{ position:static }
/* ── el menú plegado en reposo: el icono, centrado de verdad ────────────────
   Esto es lo que pedía ser: hasta el 19/08 la regla era `padding-right:0` con
   un comentario que decía «así el icono se centra en los 60 px». No se centraba
   —quedaba a 13 px del borde izquierdo de una fila de 26— porque el texto, aun
   desvanecido, SIGUE ocupando su sitio: un `opacity:0` no quita nada del
   cálculo. Centrar sin más habría empujado el icono fuera de la banda.

   Así que se hacen tres cosas, y las tres son la misma idea:

   1. El texto sale del flujo con `position:absolute`, exactamente como ya hacía
      el rótulo largo de la marca dos reglas más arriba. Sigue en el árbol —el
      nombre accesible del enlace ES ese texto— pero ya no mide.
   2. La fila se iguala por los lados: sin relleno a la izquierda y con uno a la
      derecha del grosor del filete, que es lo que compensa los 3 px que el
      filete del apartado activo le come al centro. Medido: icono de 38 a 54 en
      una banda de 16 a 76; centro del icono 46, centro de la banda 46.
   3. La marca hace lo mismo con la chincheta, que en reposo no se ve pero
      seguía empujando el rótulo con su `margin-left:auto`.

   Y el icono cae en el MISMO sitio esté plegada o desplegada la barra (3 px de
   filete + 10 de relleno = los mismos 13), así que al pasar el ratón no salta:
   solo aparece el texto a su lado.

   Va dentro de un `@media` de escritorio, y no reseteado abajo en el bloque de
   móvil como sus vecinas, porque en el teléfono el `position:absolute` del
   punto 1 dejaría el menú desplegable sin texto. Una regla que hay que acordarse
   de apagar en otro sitio es una regla que un día no se apaga. */
@media (min-width: 901px){
  [data-menu="plegado"] .lateral:not(:hover):not(:focus-within) .texto-menu,
  [data-menu="plegado"] .lateral:not(:hover):not(:focus-within) .chincheta{
    position:absolute;
  }
  [data-menu="plegado"] .lateral:not(:hover):not(:focus-within) nav > a,
  [data-menu="plegado"] .lateral:not(:hover):not(:focus-within) nav > span{
    justify-content:center; padding-left:0; padding-right:var(--f-cierra);
  }
  /* Las dos líneas del texto de tu nombre salen del flujo por lo mismo que el
     texto de una entrada: si no, la fila mide 54 px en vez de 36 y rompe el
     ritmo de la columna justo donde se junta con las demás. */
  [data-menu="plegado"] .lateral:not(:hover):not(:focus-within) .yo-texto{ position:absolute }

  /* ── los rótulos de grupo, sin su filete negro (20/08) ──────────────────
     `.grupo` cierra su sección con 2 px de `--tinta`, que es lo correcto cuando
     encima hay una palabra: es el subrayado de «ADMINISTRACIÓN». Con la barra
     plegada la palabra no está —se va con el resto del texto— y lo que quedaba
     era un trazo casi negro cruzando la banda a media altura, sin nada que
     subrayar. Del color del filete separa igual y no grita: son los mismos
     14 px de alto, así que al desplegar no se mueve nada. */
  [data-menu="plegado"] .lateral:not(:hover):not(:focus-within) .grupo{
    border-bottom-color:var(--filete);
  }

  /* ── el tema, una fila más de la columna ────────────────────────────────
     Con la barra plegada solo se ve el icono del tema puesto (regla de más
     arriba), pero seguía dibujándose como lo que es desplegada: una etiqueta
     dentro de un conmutador, con su relleno de 12 px y el fondo del elegido.
     Medido: el icono caía en 55 con la banda centrada en 46, y el recuadro
     azul lo hacía parecer el apartado en el que estás, que es lo que dice ese
     fondo en todo el resto del menú.

     Aquí no es un apartado, es un ajuste. Así que en reposo se comporta como
     una fila: ancho completo, 36 px de alto, icono al centro y sin recuadro.
     Al pasar el ratón vuelven los tres y el elegido recupera su fondo. */
  [data-menu="plegado"] .lateral:not(:hover):not(:focus-within) .segmentos{ padding:0 }
  [data-menu="plegado"] .lateral:not(:hover):not(:focus-within) .segmentos label{
    /* 34 y no 36: los 2 px que faltan los pone el filete del conmutador, que
       sigue midiendo aunque en reposo sea transparente. Así la fila del tema
       mide exactamente lo mismo que las once de arriba. */
    width:100%; justify-content:center; padding:0; min-height:34px;
    background:transparent; box-shadow:none;
    color:var(--tinta-2); font-weight:var(--p-normal);
  }
  [data-menu="plegado"] .lateral:not(:hover):not(:focus-within) .marca{
    justify-content:center; padding-left:0; padding-right:0;
  }
}

/* La chincheta. Es lo único del menú que decide entre los dos modos, así que
   cuando está echada se ve echada: fondo del apartado activo y el dibujo
   girado, que es como se dibuja una chincheta clavada. */
.chincheta{
  display:inline-flex; align-items:center; justify-content:center; flex:none;
  width:28px; height:28px; margin-left:auto;
  border:var(--f-separa) solid transparent; border-radius:var(--r);
  background:transparent; color:var(--tinta-2); cursor:pointer;
}
.chincheta:hover{ color:var(--tinta); border-color:var(--filete-fuerte) }
.chincheta svg{ width:15px; height:15px; stroke:currentColor; stroke-width:1.7;
                fill:none; stroke-linecap:round; stroke-linejoin:round;
                transition:transform var(--mov-rapido) var(--curva) }
.chincheta[aria-pressed="true"]{
  background:var(--activo-fondo); color:var(--activo-texto);
  border-color:var(--activo-filete);
}
.chincheta[aria-pressed="false"] svg{ transform:rotate(-40deg) }

/* ── botones ─────────────────────────────────────────────────────────────── */
.boton{
  display:inline-flex; align-items:center; justify-content:center; gap:var(--e2);
  padding:9px var(--e4); min-height:38px;
  border:var(--f-separa) solid transparent; border-radius:var(--r);
  background:var(--acc); color:var(--acc-texto);
  font-family:var(--f-texto); font-size:var(--t-cuerpo); font-weight:var(--p-fuerte);
  cursor:pointer;
}
.boton:hover{ background:var(--acc-hover); color:var(--acc-texto); text-decoration:none }
.boton svg{ flex:none; width:16px; height:16px; stroke:currentColor; stroke-width:1.7;
            fill:none; stroke-linecap:round; stroke-linejoin:round }
.boton.fantasma{
  background:transparent; color:var(--tinta); border-color:var(--filete-fuerte);
}
.boton.fantasma:hover{ background:var(--fila-hover); color:var(--tinta) }
.boton.ancho{ width:100% }
.boton.chico{ padding:5px var(--e3); min-height:30px; font-size:var(--t-apoyo) }
.boton.peligro{
  background:transparent; color:var(--error); border-color:var(--error);
}
.boton.peligro:hover{ background:var(--error); color:var(--papel) }
.boton[disabled]{ opacity:.5; cursor:not-allowed }

/* ── botón de icono ───────────────────────────────────────────────────────
   Un botón sin texto visible. La palabra SIGUE en el HTML, dentro de un
   .solo-lectores, y además va en `title` para quien pasa el ratón y no
   reconoce el dibujo: un icono aislado lo acierta menos de la mitad de la
   gente, y ese porcentaje no mejora porque nosotros lo tengamos claro.

   32×32 en escritorio, donde el puntero es preciso; en móvil sube a 44, que es
   donde manda el dedo. */
.boton.icono{
  width:32px; height:32px; min-height:32px; padding:0;
  background:transparent; color:var(--tinta-2); border-color:transparent;
}
.boton.icono:hover{ background:transparent; color:var(--tinta); border-color:var(--filete-fuerte) }
.boton.icono.peligro{ color:var(--error); border-color:transparent }
.boton.icono.peligro:hover{ background:var(--error); color:var(--papel) }

/* ── campos ──────────────────────────────────────────────────────────────── */
.campo{ display:flex; flex-direction:column; gap:6px }
.campo label{ font-size:var(--t-apoyo); font-weight:var(--p-fuerte) }
.campo input, .campo select, .campo textarea,
.dato-fila .con-campo input, .dato-fila .con-campo select{
  width:100%; padding:9px var(--e3); min-height:38px;
  border:var(--f-separa) solid var(--filete-fuerte); border-radius:var(--r);
  background:var(--papel); color:var(--tinta);
  font-family:var(--f-texto); font-size:var(--t-cuerpo);
}
/* El marcador tiene su propio token y NO usa `tinta-2` (S5.1). Con `tinta-2` —que
   en el tema claro sale casi negra— la sugerencia se leía igual de fuerte que lo
   que la persona había escrito, y había que mirar dos veces para saber si el
   campo estaba relleno. Se puede bajar a 3:1 porque el marcador nunca es la
   única pista: en este sistema todo campo lleva su <label> visible encima. */
.campo input::placeholder,
.campo textarea::placeholder{ color:var(--marcador); opacity:1 }
.campo .ayuda{ font-size:var(--t-apoyo); color:var(--tinta-2) }
/* La ayuda que va DENTRO de la etiqueta —que es la convención de la casa, y
   desde S8.1 la única forma admitida (ver más abajo)— hereda el peso 700 de la
   etiqueta y se lee como si fuera parte del rótulo: «Clave no se cambia» en
   negrita entera. El peso normal es lo que las separa. */
.campo label .ayuda{ font-weight:var(--p-normal) }

/* ── el desplegable largo que se busca, en vez de desplegarse (S11 · 3.4b) ──
   La otra mitad de la pieza que vive en `comun/plantilla/guiones.php`: el
   <select> se esconde y en su sitio quedan esta caja y su lista de tres.

   Van aquí, entre las reglas de `.campo`, y no sueltas al final del fichero,
   porque la caja ES un campo más: hereda de `.campo input` de aquí arriba el
   ancho, los 38 px y el filete, y lo único suyo es lo que se añade debajo. Sin
   JavaScript no llega a existir ninguna de las dos —las crea el guion—, así que
   estas reglas no esconden ni enseñan nada por su cuenta.

   La caja es un `type="search"` y WebKit le pone lo suyo: el redondeo de iOS,
   que se salta los 2 px de `--r` de la casa, y una cruz de borrar que en Firefox
   no existe. Se le quitan los dos: un mando que sólo sale en la mitad de los
   navegadores descuadra el campo y no se puede explicar en el manual. */
.busca-elige{ appearance:none; -webkit-appearance:none }
.busca-elige::-webkit-search-cancel-button{ appearance:none; -webkit-appearance:none }

/* El buscador que obliga a elegir. La lista nace pegada al campo y no flota:
   flotando se sale por la derecha en 375 px, que es lo que ya pasó con el menú
   de tres puntos. En ESCRITORIO sí flota — ver la regla de más abajo. */
.sugerencias{ list-style:none; margin:var(--e1) 0 0; padding:0;
              border:var(--f-separa) solid var(--filete); border-radius:var(--r) }
.sugerencias[hidden]{ display:none }
.sugerencias li + li{ border-top:var(--f-separa) solid var(--filete) }
.sugerencias button{ display:flex; gap:var(--e2); align-items:baseline;
                     width:100%; min-height:38px; padding:var(--e2) var(--e3);
                     background:none; border:0; border-radius:0; cursor:pointer;
                     font:inherit; color:var(--tinta); text-align:left }
.sugerencias button:hover,
.sugerencias button:focus-visible{ background:var(--superficie) }
.campo.sin-elegir input{ border-color:var(--error) }
.campo.sin-elegir .ayuda{ color:var(--error) }

/* ── y el catálogo de conceptos, que se despliega ENTERO y en columnas ─────
   La corrección de Fabio del 28/08: «un desplegable de verdad, que permita ver
   todos los valores disponibles, y que muestre algunos datos como si fuera una
   tabla». La lista es la misma `.sugerencias` del buscador de cliente —mismo
   marco, mismos filetes de 1 px, misma altura de fila— y lo único que añade
   `.con-datos` es el reparto en columnas de lo que va dentro de cada botón.

   El nombre se lleva el hueco (`flex:1`) y lo demás queda pegado a la derecha
   en su orden. Es rejilla suiza: las columnas se alinean solas porque todas las
   filas llevan las mismas piezas, y no hace falta declarar anchos.

   Un tope de alto y su barra propia: veinte conceptos son 760 px, y una lista
   más larga que la ventana tapa el formulario que se está rellenando. Seis
   filas y media es lo que cabe sobre el teclado de un móvil. */
.sugerencias.con-datos{ max-height:260px; overflow-y:auto; overscroll-behavior:contain }
.sugerencias.con-datos button{ flex-wrap:wrap; align-items:center; gap:var(--e1) var(--e2) }
.sugerencias.con-datos .titulo{ flex:1 1 12ch; min-width:0; font-weight:var(--p-fuerte);
                                overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
/* Las tres columnas de datos llevan ANCHO FIJO, y ahí está lo que las hace
   tabla: con el ancho natural, cada celda empezaba donde acababa la de al lado
   y el borde izquierdo de la columna quedaba en escalera —medido: la familia
   arrancaba en 1.094, 1.104, 1.110 y 1.125 px en cuatro filas seguidas—. Las
   medidas salen del dato más largo de cada una: «Certificados» (12), «por
   trabajo» (11) y «120 min» (7). Lo que se pase se recorta con puntos
   suspensivos, que es preferible a que la fila se parta en dos. */
.sugerencias.con-datos .apagado{ font-size:var(--t-apoyo); color:var(--tinta-2);
                                 overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.sugerencias.con-datos .columna-familia{ flex:0 0 12ch }
.sugerencias.con-datos .columna-cobra{   flex:0 0 11ch }
.sugerencias.con-datos .columna-minutos{ flex:0 0 7ch;  text-align:right }
.sugerencias.con-datos .columna-tipo{    flex:0 0 15ch }
.sugerencias.con-datos .etiqueta{ flex:none }


/* ── …y en ESCRITORIO la lista flota, no empuja (Fabio, 29/08) ────────────
   «Me gusta cómo se muestran los conceptos al enfocar el input, pero que se
   muestren por encima del resto de campos, no que mueva todo el contenido del
   formulario, es incómodo.» Tenía razón y se mide: la lista del catálogo son
   260 px que se metían EN EL FLUJO, así que al pulsar el campo bajaban de golpe
   las cuatro filas de «Más detalles» y los dos botones. Se abría para mirar el
   catálogo y lo que se movía era todo lo demás.

   Las dos listas del alta —el cliente y el catálogo— y no solo una: es el mismo
   componente con el mismo defecto en la misma fila del mismo formulario, y
   arreglar una dejaría la de al lado empujando.

   `left:0; right:0` y no un ancho: así la lista mide exactamente lo que su
   campo y NO PUEDE salirse por la derecha, que es lo que pasó con el menú de
   tres puntos y lo que dejó escrita la regla de arriba. Y `background` propio,
   porque hasta hoy no lo necesitaba —estaba en el flujo, sobre el papel— y
   flotando dejaría ver los campos de debajo a través.

   ⚠ Solo por encima de 900 px, que es el corte de la casa. En el teléfono la
   lista se queda en el flujo a propósito: flotando taparía los campos de abajo
   justo cuando el teclado se come media pantalla, y la página no se podría
   desplazar para leerla. El móvil se mira aparte y después, que es el orden que
   puso Fabio.

   ⚠ Y esto cuenta con que el campo esté en la MITAD DE ARRIBA de su panel: el
   `.dentro` de un `.desplegable` lleva `overflow:hidden` para poder animar el
   despliegue, así que una lista que se saliera por abajo del panel se vería
   cortada. Los dos buscadores están en la primera fila del alta y los 260 px de
   tope caben de sobra; una lista nueva más abajo tendría que mirarlo. */
@media (min-width: 901px){
  .campo[data-elige],
  .campo[data-elige-concepto]{ position:relative }
  .campo[data-elige] > .sugerencias,
  .campo[data-elige-concepto] > .sugerencias{
    position:absolute; top:100%; left:0; right:0; z-index:3;
    margin-top:2px; background:var(--papel);
  }
}

/* El pie del buscador nace vacío y se llena sólo cuando hay algo que decir. Un
   <p> vacío no mide nada, pero el `gap` del campo lo cuenta igual: son 6 px de
   más bajo el cliente que ninguno de los otros campos tiene. Medido a 375 px:
   67,4 px de alto contra los 61,4 de los demás. */
.campo .ayuda:empty{ display:none }

/* ── el campo con la etiqueta AL LADO, no encima (S8.1, 2ª vuelta) ─────────
   Lo pidió Fabio para las dos fechas del mantenimiento: «Mantenimiento gratuito
   hasta» y «Estuvo activo hasta» son rótulos largos sobre campos estrechos, así
   que se partían en tres líneas y la fila del mantenimiento medía el triple que
   las de arriba. Con la etiqueta al lado, la fila vuelve a medir lo que mide un
   campo.

   Se usa donde el rótulo es largo y el dato corto —una fecha, un porcentaje—, y
   no en general: con la etiqueta encima caben rótulos largos sin comerse el
   ancho, que es lo que quiere un formulario de doce campos. */
/* El peso hace falta: `.caja-subir .linea > .campo.corto` pesa (0,3,0) y le
   ganaba a un `.campo.en-linea` a secas, así que el campo se quedaba en 130 px
   con la etiqueta al lado — y salía peor que apilado, que es como lo vi. */
.caja-subir .linea > .campo.en-linea,
.desplegable .ficha .linea > .campo.en-linea,
.campo.en-linea{ flex-direction:row; align-items:center; gap:var(--e2);
                 flex:0 1 auto; white-space:nowrap }
.campo.en-linea > label{ flex:none }
.campo.en-linea > input,
.campo.en-linea > select{ flex:none; width:auto; min-width:0 }

/* ── aire alrededor de la zona de subir (S8.1, 2ª vuelta) ──────────────────
   Iba pegada al campo de arriba y al botón de abajo. En un formulario denso, la
   única pieza con filete propio necesita separarse de lo que la rodea para
   leerse como una pieza. */
.caja-subir > .zona-fichero{ margin:var(--e3) 0 }
/* Las casillas y los redondeles NO son campos de escribir: la regla de arriba
   les daba ancho completo y 38 px de alto. */
.campo input[type="checkbox"],
.campo input[type="radio"]{
  width:auto; min-height:0; padding:0; accent-color:var(--acc);
}

/* Un bloque por fila: cada campo a ancho completo. Sigue siendo la regla en el
   PORTAL y en las pantallas de acceso, que es donde está el cliente y donde un
   formulario se rellena una vez. */
/* El hueco entre campos apilados, a --e5 y no a --e4 (Fabio, 28/08: «los títulos
   de los campos están demasiado pegados a los inputs de arriba»). No es gusto,
   es una proporción: la etiqueta va a 6 px de SU campo y estaba a 16 del campo
   de ARRIBA, o sea 2,7 veces — demasiado cerca para que se lea a qué pertenece.
   Con 20 px son 3,3 veces, que ya separa los dos bloques de un vistazo.

   Y la altura que cuesta se recupera de sobra en el mismo movimiento: los
   campos que caben juntos van en `.linea`, así que hay menos filas. */
.formulario{ display:flex; flex-direction:column; gap:var(--e5) }

/* La excepción, y solo en el panel (S3.5, decisión de Fabio): es una
   herramienta nuestra, con formularios que se rellenan a diario y que a una
   columna obligan a bajar tres pantallas para dar de alta un cliente. */
.formulario.denso{
  display:grid; grid-template-columns:repeat(2, minmax(0,1fr)); gap:var(--e4);
}
.formulario.denso .completo{ grid-column:1 / -1 }

/* Una casilla con su texto al lado, del tamaño que tiene una casilla en
   cualquier sitio. La etiqueta ES el texto de al lado; no lleva otra encima. */
/* El `margin-top:3px` de la casilla es para cuando el texto de al lado tiene DOS
   líneas —el título y su ayuda debajo—: ahí la casilla tiene que alinearse con
   la primera línea y no con el centro del párrafo.
   `.casilla.centrada` es para cuando el texto es una línea sola, que es el caso
   de «Ver también las inactivas»: ahí ese mismo margen bajaba la casilla 3 px y
   el texto parecía subido. Es exactamente lo que contó Fabio en §1.8. */
.casilla{ display:flex; align-items:flex-start; gap:var(--e2) }
.casilla input{ flex:none; width:15px; height:15px; margin-top:3px; accent-color:var(--acc) }
.casilla.centrada{ align-items:center }
.casilla.centrada input{ margin-top:0 }
.casilla .texto{ font-size:13px; color:var(--tinta) }
.casilla .texto .ayuda{ display:block; font-size:var(--t-apoyo); color:var(--tinta-2) }

/* ── tabla de opciones ────────────────────────────────────────────────────
   Una fila por módulo con su descripción, y una columna por estado. Sustituye a
   los desplegables sueltos: con cuatro módulos eran cuatro desplegables que
   había que abrir uno a uno para saber qué tenía contratado un cliente.

   Son redondeles nativos con `name` compartido por módulo: el navegador ya sabe
   que de los cuatro solo puede haber uno, el teclado se mueve con las flechas y
   el lector de pantalla lo anuncia sin ayuda. Cada uno lleva su `aria-label` con
   el módulo Y el estado, porque la cabecera de columna se ve pero no se oye. */
.opciones{ display:flex; flex-direction:column; gap:var(--e1) }
.opciones > *{
  display:grid; grid-template-columns:minmax(180px,1fr) repeat(4, 86px);
  gap:var(--e3); align-items:center;
}
.opciones .cabecera-op{
  padding:0 var(--e3) var(--e1);
  font-size:var(--t-micro); font-weight:var(--p-fuerte); letter-spacing:.06em;
  text-transform:uppercase; color:var(--tinta-2);
}
.opciones .cabecera-op span:not(:first-child){ text-align:center }
.opciones .fila-op{
  padding:var(--e2) var(--e3);
  border:var(--f-separa) solid var(--filete); border-radius:var(--r);
}
.opciones .fila-op:hover{ background:var(--fila-hover) }
.opciones .que{ display:flex; flex-direction:column; gap:1px; min-width:0 }
.opciones .que strong{ font-size:13px; font-weight:var(--p-fuerte) }
.opciones .que .ayuda{ font-size:var(--t-micro); color:var(--tinta-2) }
/* El objetivo de pulsación es la celda entera, no el redondel de 15 px. */
.opciones .op{ display:grid; place-items:center; min-height:34px; border-radius:var(--r); cursor:pointer }
.opciones .op:hover{ background:var(--chip-fondo) }
.opciones .op input{ width:15px; height:15px; accent-color:var(--acc); cursor:pointer }
/* El rótulo de dentro de la celda solo existe en móvil, donde la cabecera de
   columna desaparece y un redondel suelto no diría qué significa. */
.opciones .op .rotulo-op{ display:none }

/* ── segmentos (el conmutador de tema es uno) ────────────────────────────
   Se construye con radios de verdad, no con botones: así el teclado y el lector
   de pantalla lo entienden solos como «un grupo, tres opciones, una elegida». */
.segmentos{
  display:inline-flex; gap:2px; padding:2px;
  border:var(--f-separa) solid var(--filete); border-radius:var(--r);
  background:var(--papel);
}
.segmentos.ancho{ display:flex; width:100% }
.segmentos.ancho label{ flex:1; justify-content:center; min-height:32px }
/* Sin relleno lateral propio (20/08). Lo llevaba —`0 var(--e2)`— y era lo único
   de la barra que no empezaba donde empiezan las demás filas: el conmutador y su
   rótulo salían 8 px metidos hacia dentro, y con el menú plegado eso mandaba el
   icono del tema 9 px a la derecha del centro de la banda. Los huecos los pone
   la fila, no el bloque.

   Y el hueco entre el rótulo «TEMA» y el conmutador va a 2 px, que es el que
   deja `nav` entre «ADMINISTRACIÓN» y su primera entrada. Eran 8 y 2 para la
   misma relación —un rótulo de grupo y lo primero que hay debajo— dibujada dos
   veces distinto. */
.control-tema{ display:flex; flex-direction:column; gap:2px; padding:0 }
/* El radio de verdad no se ve, pero SIGUE estando: se recorta, no se apaga con
   opacity:0. La diferencia importa — con opacity:0 hay lectores de pantalla que
   lo dan por invisible y dejan de anunciarlo, y el control se vuelve inoperable
   justo para quien más lo necesita. */
.segmentos input{
  position:absolute; width:1px; height:1px; overflow:hidden;
  clip-path:inset(50%); white-space:nowrap;
}
.segmentos label{
  display:inline-flex; align-items:center; gap:var(--e2);
  padding:6px var(--e3); border-radius:var(--r);
  font-size:var(--t-apoyo); color:var(--tinta-2); cursor:pointer; user-select:none;
}
.segmentos label:hover{ background:var(--fila-hover) }
/* La opción elegida se tiene que VER. Hasta S3.5 se pintaba con un blanco al
   92 % encima de un blanco al 55 %: guardaba —se comprobó contra la base— pero
   no lo decía, que a efectos de quien mira es lo mismo. */
.segmentos input:checked + label{
  background:var(--activo-fondo); color:var(--activo-texto); font-weight:var(--p-fuerte);
  box-shadow:inset 0 0 0 1px var(--activo-filete);
}
.segmentos input:focus-visible + label{ outline:var(--f-agrupa) solid var(--foco); outline-offset:2px }
/* pointer-events:none — el icono no recibe la pulsación, la recibe la etiqueta.
   Sin esto, un clic que cae encima del dibujo puede quedarse en el SVG y no
   llegar a marcar el radio. */
.segmentos label svg{ width:14px; height:14px; stroke:currentColor; stroke-width:1.7;
                      fill:none; stroke-linecap:round; stroke-linejoin:round;
                      pointer-events:none }

/* ── datos, etiquetas y estados ──────────────────────────────────────────── */
/* Los datos que se comparan letra a letra: subdominio, NIF, nombre de base de
   datos. Van en monoespaciada porque ahí distinguir un 0 de una O no es
   estética; es el único sitio donde SmartDesk usa una segunda tipografía. */
.modelo{
  font-family:var(--f-dato); font-weight:var(--p-dato); font-size:var(--t-apoyo);
}
.etiqueta{
  display:inline-flex; align-items:center; gap:var(--e1);
  padding:2px 6px; border-radius:var(--r);
  background:var(--chip-fondo); color:var(--chip-texto);
  border:var(--f-separa) solid var(--chip-filete);
  font-size:var(--t-micro); font-weight:var(--p-fuerte);
  white-space:nowrap;
}
.etiqueta.apagada{ color:var(--tinta-2); background:transparent;
                   border-color:var(--filete); font-weight:var(--p-normal) }
.etiqueta.acento{ background:var(--activo-fondo); color:var(--activo-texto);
                  border-color:var(--activo-filete) }

/* El color NUNCA lleva solo la información: el punto va siempre con su palabra. */
.estado{
  display:inline-flex; align-items:center; gap:6px;
  padding:3px var(--e2); border-radius:var(--r);
  font-size:var(--t-micro); font-weight:var(--p-fuerte);
}
.estado::before{ content:''; width:6px; height:6px; background:currentColor }
.estado.pendiente{ color:var(--aviso);  background:var(--aviso-fondo) }
.estado.entregada{ color:var(--exito);  background:var(--exito-fondo) }
.estado.problema{  color:var(--error);  background:var(--error-fondo) }

/* ── tabla de tarjetas ────────────────────────────────────────────────────
   Término medio a propósito entre las dos cosas que se hacen normalmente:

   · Una TABLA de verdad alinea las columnas y se lee de un vistazo, pero es un
     bloque macizo en el que ninguna fila se distingue de la de al lado.
   · Una lista de TARJETAS distingue cada elemento, pero cada tarjeta coloca sus
     datos donde le cabe y el ojo ya no puede comparar dos filas.

   Aquí la cabecera es una tarjeta y cada fila es otra, pero TODAS comparten la
   misma rejilla de columnas, declarada una sola vez en `--cols`. Se compara como
   en una tabla y se distingue como en una lista.

   `--cols` la pone el modificador de cada pantalla, no un style= en el HTML: la
   CSP prohíbe los estilos en línea y, además, tener las columnas de las dos
   pantallas juntas aquí es lo que impide que una se quede desalineada cuando se
   toque la otra.

   Una fila NO es un enlace y no se pulsa entera: pulsar una fila y no saber a
   dónde va es de las cosas que más se odian de un panel. Se pulsan sus botones. */
.tabla{ display:flex; flex-direction:column }
.tabla > *{
  display:grid; grid-template-columns:var(--cols);
  gap:var(--e4); align-items:center;
  padding:0 var(--e4);
}
.tabla-cabecera{
  min-height:34px;
  background:var(--superficie);
  border:var(--f-separa) solid var(--filete);
  border-bottom:var(--f-agrupa) solid var(--cab-filete);
  border-radius:var(--r) var(--r) 0 0;
  font-size:var(--t-micro); font-weight:var(--p-fuerte); letter-spacing:.07em;
  text-transform:uppercase; color:var(--tinta-2);
}
/* Pegada arriba mientras se desplaza la tabla (§4ª tanda). Solo dentro del
   marco que desplaza: en el cuadro de mando, donde la tabla va en una columna
   que se desplaza entera, pegarla la dejaría flotando sobre otra cosa.
   Lo pegajoso puede ser este elemento porque `.tabla` es una columna flex y él
   es un hijo directo, así que se pega mientras su tabla esté a la vista.
   Sin `z-index` propio: los paneles de las filas valen 20 y tienen que seguir
   pintándose por encima. */
.crece.desborda .tabla-cabecera{ position:sticky; top:0; z-index:2 }
.tabla-cabecera .fin{ text-align:right }
/* Los rótulos de la cabecera pueden encoger por debajo de su palabra (20/08).
   Sin esto, un rótulo más ancho que su columna NO la deja encoger —un elemento
   de rejilla no baja de su contenido mínimo— y la cabecera se sale por la
   derecha arrastrando una barra de desplazamiento horizontal que no es de
   nadie: medido en Equipo, «ACCIONES» sobre una columna de 44 px sacaba 3 px, y
   eso era todo el «scroll horizontal» de la pantalla. Las FILAS ya lo tenían
   (`.celda{min-width:0}`); la cabecera no, porque sus hijos son `<span>`
   pelados. */
.tabla-cabecera > *{ min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.tabla-fila{
  min-height:var(--alto-fila);
  background:var(--papel);
  border:var(--f-separa) solid var(--filete);
  border-top:0;
}
.tabla-fila:last-child{ border-radius:0 0 var(--r) var(--r) }
/* Con las fichas intercaladas, el último hijo de la tabla ya no es una fila sino
   la ficha de la última, así que el selector de arriba no casa con nada y la
   tabla termina en pico. Con guion se tapaba solo (`.ultima-visible`), pero el
   sin-JavaScript es justo lo que estas pantallas sostienen. `.con-fichas` lo
   pone la pantalla que las pinta, para que esto no se aplique donde no toca. */
.tabla.con-fichas > .tabla-fila:nth-last-child(2){ border-radius:0 0 var(--r) var(--r) }
.tabla-fila:hover{ background:var(--fila-hover) }
/* La fila apagada: un cliente o una persona dados de baja. Se ven, pero no
   compiten con los activos. Nunca se esconden: lo que no se ve, no se arregla.
   Se distingue por DOS cosas y ninguna es el color: el fondo y el listón. */
.tabla-fila.inactiva{
  background:var(--superficie);
  border-left:var(--f-cierra) solid var(--filete-fuerte);
}
/* Una fila apagada también responde al ratón. Sin esta línea no lo hacía:
   `.tabla-fila.inactiva` y `.tabla-fila:hover` pesan lo mismo y ganaba la de
   abajo, así que las inactivas eran las únicas filas muertas de la tabla. No se
   notaba mientras el hover era casi blanco; con el hover del matiz, sí. */
.tabla-fila.inactiva:hover{ background:var(--fila-hover) }

/* ── la fila que se acaba de tocar, unos segundos ─────────────────────────
   Fabio, 28/08: «que no se muestre a la derecha de la fila, hace que se
   descoloque todo el contenido de la fila. Me gustaría más que se pusiera
   durante unos segundos de algún color que se relacione con la acción realizada
   (verde completado, azul reabierto), y que la información de lo que ha pasado
   se muestre justo encima de la tabla».

   Lo que sustituye: una `<span class="aviso-guardado">` que iba DENTRO de la
   celda de acciones y corría los botones de sitio justo en la fila que se
   acababa de tocar.

   La `transition` va en la fila y no en las clases: es lo que hace que quitar
   la clase —lo hace el guion a los tres segundos— devuelva el color con un
   desvanecido y no con un corte. Y el color va SIEMPRE con el texto de encima
   de la tabla: un color solo no lleva nunca la información.

   `.recien-abierta` es el azul del hover, y es la respuesta al «al abrir un
   pedido, ponle de color de fondo el azul del hover durante unos segundos». No
   sale del servidor: la pone el guion cuando una ficha se despliega, así que
   vale igual para la que viene pintada y para la que se trae por detrás. */
.tabla-fila{ transition:background-color var(--mov-normal) var(--curva) }
.tabla-fila.recien-abierta,
.tabla-fila.tocada-abierta{ background:var(--fila-hover) }
.tabla-fila.tocada-hecha{   background:var(--exito-fondo) }
.tabla-fila.tocada-nueva{   background:var(--exito-fondo) }
.tabla-fila.tocada-espera{  background:var(--aviso-fondo) }
.tabla-fila.tocada-fuera{   background:var(--superficie) }

.celda{ min-width:0 }
.celda .rotulo{ display:none }        /* solo aparece en móvil */
.celda-principal{ display:flex; flex-direction:column; gap:1px; min-width:0 }
.celda-principal .titulo{ font-weight:var(--p-fuerte); color:var(--tinta);
                          overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.celda-principal .bajo{ font-family:var(--f-dato); font-size:var(--t-micro); color:var(--tinta-2);
                        overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.celda-etiquetas{ display:flex; flex-wrap:wrap; gap:var(--e1) }
.celda-acciones{ display:flex; gap:var(--e1); justify-content:flex-end; align-items:center }
/* Cada acción es su propio <form method="post">: nada que cambie datos viaja en
   un GET (CONVENCIONES §4.3). */
.celda-acciones form{ display:flex }

/* ── menú de desbordamiento (el botón de tres puntos) ─────────────────────
   Se hace con <details>, no con un div y JavaScript. Motivo: <details> abre y
   cierra ÉL SOLO, con teclado incluido, aunque el guion no cargue. El guion de
   pie.php solo añade los remates que el elemento no trae: cerrar al pulsar
   fuera, cerrar con Escape, no dejar dos abiertos a la vez, y abrir hacia
   arriba cuando abajo no queda sitio.

   Aquí dentro van las acciones que no caben en la fila y las que no conviene
   tener a un clic de distancia: cambiar el rol, bloquear, desactivar. */
.menu{ position:relative }
.menu > summary{ list-style:none; cursor:pointer }
.menu > summary::-webkit-details-marker{ display:none }
.menu > summary::marker{ content:'' }
.menu[open] > summary{ color:var(--tinta); border-color:var(--filete-fuerte) }
.menu.arriba .panel{ top:auto; bottom:calc(100% + var(--e1)) }
.menu .panel{
  position:absolute; right:0; top:calc(100% + var(--e1)); z-index:20;
  min-width:230px; padding:var(--e2);
  display:flex; flex-direction:column; gap:2px;
  background:var(--papel);
  /* 2px y no 1: el panel flota sobre el contenido y, sin sombras, el único que
     puede despegarlo del papel de debajo es su propio filete. */
  border:var(--f-agrupa) solid var(--tinta);
  border-radius:var(--r);
}
/* ── y se despliega, no aparece de golpe (4ª tanda) ───────────────────────
   Es una ANIMACIÓN y no una transición, y eso no es un capricho de sintaxis:
   `<details>` no esconde su contenido con `display:none` sino apagando su
   renderizado, así que cuando el panel existe para el navegador ya está en su
   estado final y no hay dos valores entre los que transicionar. Una animación
   sí arranca sola en cuanto el elemento se pinta por primera vez.

   Sale del borde de su mando —de arriba si abre hacia abajo, de abajo si abre
   hacia arriba—, que es lo que hace que se lea como «esto ha salido de aquí» y
   no como «esto ha aparecido». `prefers-reduced-motion` la deja en nada con la
   regla general del final del fichero. */
@keyframes desplegar-panel{
  from{ opacity:0; transform:translateY(-6px) scaleY(.97) }
  to  { opacity:1; transform:none }
}
@keyframes desplegar-panel-arriba{
  from{ opacity:0; transform:translateY(6px) scaleY(.97) }
  to  { opacity:1; transform:none }
}
.menu[open] > .panel{
  transform-origin:top center;
  animation:desplegar-panel var(--mov-normal) var(--curva);
}
.menu.arriba[open] > .panel{
  transform-origin:bottom center;
  animation-name:desplegar-panel-arriba;
}

/* Dentro del panel los botones vuelven a llevar su palabra: aquí hay sitio, y
   son justo las acciones que más caro cuesta equivocarse. */
.menu .panel .boton{
  width:100%; justify-content:flex-start; min-height:36px;
  padding:var(--e2) var(--e3); font-size:13px;
  background:transparent; color:var(--tinta); border-color:transparent;
}
.menu .panel .boton:hover{ background:var(--fila-hover) }
.menu .panel .boton.peligro{ color:var(--error); border-color:transparent }
.menu .panel .boton.peligro:hover{ background:var(--error); color:var(--papel) }
.menu .panel form{ display:block }
.menu .panel .separador{ height:var(--f-separa); background:var(--filete); margin:var(--e1) 0 }
/* La explicación de por qué algo NO se puede hacer, dentro del menú de tres
   puntos. Era un `style=` en el HTML y la CSP se lo comía (trampa nº 32), así
   que el texto salía a tamaño de párrafo y pegado al borde. */
.menu .panel .nota-menu{ padding:var(--e2) var(--e3); font-size:var(--t-micro);
                         max-width:260px }
.menu .panel .grupo{
  padding:var(--e2) var(--e3) var(--e1);
  border-bottom:0;
}
.menu .panel select{
  width:100%; min-height:36px; padding:var(--e2) var(--e3);
  border:var(--f-separa) solid var(--filete-fuerte); border-radius:var(--r);
  background:var(--papel); color:var(--tinta);
  font-family:var(--f-texto); font-size:13px; margin-bottom:var(--e2);
}

/* ── columnas de cada pantalla ────────────────────────────────────────────
   Una línea por tabla, y aquí juntas a propósito: si viven separadas, se
   desalinean la primera vez que alguien toque una sola. */
.tabla.clientes{ --cols: minmax(200px,2.2fr) minmax(150px,1.5fr) minmax(170px,1.4fr) 108px 88px }
.tabla.usuarios{ --cols: minmax(190px,2fr) minmax(130px,1.2fr) 118px 104px minmax(150px,1.3fr) 116px }
.tabla.gente-del-cliente{ --cols: minmax(190px,2.2fr) 118px 104px minmax(140px,1fr) 48px }
.tabla.pendientes{ --cols: 34px minmax(190px,2.2fr) minmax(150px,1.4fr) minmax(110px,1fr) 116px 172px }
.tabla.catalogo{ --cols: 60px minmax(210px,2.4fr) 112px 104px 140px }
.tabla.empresas{ --cols: minmax(200px,2.4fr) minmax(150px,1.4fr) minmax(120px,1fr) 104px 128px }
/* SIETE columnas, no seis: persona · entra · papel · obligaciones · empresas ·
   estado · acciones. Con seis, la séptima celda de cada fila se caía a una
   SEGUNDA fila de la rejilla, y eso explicaba de golpe las tres cosas que se
   veían mal en la pantalla: filas del doble de alto, el icono de acciones
   suelto debajo y en el centro, y la palabra «ACCIONES» descolgada bajo
   «PERSONA» en la cabecera. Al añadir una columna a una tabla hay que venir
   aquí; si no, la rejilla no avisa, se limita a envolver. */
.tabla.equipo{ --cols: minmax(170px,2fr) 104px 88px 120px 76px 92px 40px }
/* Y con el hueco de columna más corto que el resto de tablas. No es capricho:
   son SIETE columnas —la que más tiene el sitio— y con `--e4` sumaban 96 px solo
   de aire. La tabla pedía 882 px de mínimo y en un portátil de 1100 con el menú
   desplegado quedan unos 830, así que salía una barra horizontal dentro del
   marco. Con estas medidas el mínimo baja a 794 y cabe. */
.tabla.equipo > *{ gap:var(--e3) }

/* ── Pedidos ──────────────────────────────────────────────────────────────
   Dos declaraciones, no una columna que se apaga: quien no puede ver el
   precio no recibe la columna en el SELECT (comun/pedidos.php,
   pedidos_visibles), así que aquí solo hay que saber cuántas hay. Si se
   hiciera con `display:none`, el importe habría viajado al HTML y estaría a
   un «ver código fuente» de distancia.

   Los mínimos son los medidos, no los deseados: por debajo de ~1.290 px de
   ventana la de ocho columnas se comía la de acciones. */
.tabla.pedidos{
  --cols: 108px minmax(150px,1.4fr) minmax(160px,1.6fr) minmax(110px,1fr) 104px 72px 96px;
}
.tabla.pedidos.con-precio{
  --cols: 108px minmax(140px,1.3fr) minmax(150px,1.5fr) minmax(100px,1fr) 104px 72px 96px 96px;
}

/* Pedidos · el catálogo de conceptos (S11 · 4.5). SEIS columnas y en este
   orden: 1 orden · 2 concepto · 3 precio · 4 tipo · 5 estado · 6 acciones. La
   familia va bajo el nombre y los minutos bajo el precio: con columnas propias
   eran ocho, la tabla pedía más de 900 px de mínimo y salía una barra
   horizontal dentro del marco en cualquier portátil con el menú desplegado. La
   lección de `.tabla.equipo`, veinte líneas más arriba: al añadir una columna a
   una tabla hay que venir AQUÍ, o la celda de más se cae a una segunda fila de
   la rejilla y nadie avisa.

   Aquí NO hay variante «con precio» como en `.tabla.pedidos` de aquí encima: al
   catálogo solo entra quien administra el módulo, y quien pone los precios los
   ve por definición.

   Que la fila emita seis celdas y no siete lo vigila
   `herramientas/comprobar_pedidos.php` (sección B4), que cuenta los valores de
   este `--cols` contra los rótulos y las celdas de `conceptos.php`. */
.tabla.conceptos{ --cols: 60px minmax(190px,2.4fr) 100px 110px 96px 132px }

/* …y las columnas que puede NO haber (S11 · 29/08). El catálogo se le abre
   ahora a todo el equipo en solo lectura, y con dos columnas que dependen de
   quién mira: el precio (`ve_precio`) y las acciones (`administra`).

   Cada combinación lleva su `--cols` ESCRITO, y no un cálculo: una columna que
   se deja de pintar sin quitarla de aquí no deja un hueco, corre todas las de
   su derecha una posición —el chip del tipo aparecería bajo el rótulo
   «Precio»— y no da ningún error. Solo se ve mirando la pantalla. */
.tabla.conceptos.sin-dinero{ --cols: 60px minmax(190px,2.4fr) 110px 96px 132px }
.tabla.conceptos.solo-mirar{ --cols: 60px minmax(190px,2.4fr) 100px 110px 96px }
.tabla.conceptos.sin-dinero.solo-mirar{ --cols: 60px minmax(190px,2.4fr) 110px 96px }

/* Pedidos · el cierre de mes (S11 · 5.4). SEIS columnas y en este orden:
   1 ref. · 2 concepto · 3 uds. · 4 precio · 5 importe · 6 acciones.

   Aquí NO hay variante «con precio» como en `.tabla.pedidos` de arriba, y no es
   un olvido: a esta pantalla solo entra quien ve el precio —lo corta
   `pedidos_cierre_por_cliente()`, que sin `ve_precio` devuelve la lista vacía—,
   así que la columna del importe está SIEMPRE o no hay pantalla.

   La de acciones son 40 px, como en `.tabla.equipo`: es un solo botón de icono.
   Y la del concepto se lleva todo lo que sobra, que es lo único que se lee
   entero.

   Que la fila emita seis celdas y no siete lo vigila
   `herramientas/comprobar_pedidos.php` (sección B5), que cuenta los valores de
   este `--cols` contra los rótulos y las celdas de `cierre.php`: si no cuadran
   NO da ningún error, la celda de más se cae a una segunda fila de la rejilla y
   la tabla sale torcida. */
/* OCHO columnas desde el 28/08: «de quién» y «cerrado» las pidió Fabio, y el
   concepto cede el sitio (de 2,6fr a 2fr y de 200 a 160 px de mínimo). Las dos
   nuevas van a ancho fijo porque su contenido lo es: un nombre de pila recortado
   y una fecha de diez caracteres. */
.tabla.cierre-lineas{ --cols: 106px minmax(160px,2fr) 116px 92px 56px 84px 92px 40px }

/* El mando de editar lleva ancla (`?editar=<id>#pedido-<id>`) porque abrir una
   ficha es una carga de página: sin ella se aterriza arriba del todo y la ficha
   se queda tres pantallas más abajo. El ancla sola no basta: la cabecera de la
   tabla va pegada arriba (`position:sticky; top:0`) y se comería los primeros
   34 px de la fila justo cuando el navegador salta. Los 42 son esos 34 más un
   hueco; en el teléfono manda otro número, y está en su `@media`. */
.tabla.pedidos .tabla-fila{ scroll-margin-top: 42px }

/* Anulado NO es un fallo: es una decisión normal. En rojo, una lista con tres
   anulados parece una lista rota. Va en `--marcador`, que es el único gris
   calibrado a 3:1 en los dos temas. Y CON fondo: la base `.estado{}` no pone
   ninguno, y los otros tres chips (pendiente, entregada, problema, arriba)
   siempre emparejan color+fondo; sin `--chip-fondo` este saldría transparente
   y, al lado de los demás, no parecería un chip. */
.estado.anulado::before{ background: var(--marcador) }
.estado.anulado{ color: var(--tinta); background: var(--chip-fondo) }
.tabla-fila.es-anulado .celda-principal .titulo{ text-decoration: line-through }

/* Propuesto: hoy no se ve en ningún listado —comun/pedidos.php excluye
   `p.estado <> 'propuesto'` en pedidos_visibles y compañía—, pero la clase ya
   la emite pedidos_chip_de_estado() (comun/plantilla/piezas_pedidos.php) y el
   día que la fase del buzón encienda los propuestos tiene que salir con su
   color, no en blanco y sin fondo. */
.estado.propuesto{ color: var(--info); background: var(--info-fondo) }

/* Un pedido silenciado (anulación pedida, o pospuesto) no está anulado y no
   puede parecerlo: se distingue con un listón, que es la señal que la casa ya
   usa para «esto no es como los demás». */
.tabla-fila.silenciado{ border-left: var(--f-cierra) solid var(--marcador) }

/* Un concepto sin tarifa todavía se marca en la propia lista, no solo en el
   cierre de mes. Es el riesgo nº2 del diseño: si el día 1 la propuesta sale
   llena de «sin precio», Vanesa ve cuarenta precios que poner a mano y se
   vuelve al Excel. Verlo aquí, mientras se escribe el catálogo, es lo que hace
   que no llegue a pasar.

   Es el mismo listón que `.tabla-fila.silenciado` de aquí arriba —la señal que
   la casa ya usa para «esto no es como los demás»—, en `--aviso`. Y el texto
   «sin precio» va además en su celda: un color solo nunca lleva la
   información. */
.tabla.conceptos .tabla-fila.sin-precio{ border-left:var(--f-cierra) solid var(--aviso) }

/* ── lista simple ─────────────────────────────────────────────────────────
   Filas apiladas dentro de UN bloque, sin columnas alineadas. Es para las listas
   cuyas filas no son comparables entre sí —las migraciones aplicadas, los
   módulos que un cliente tiene contratados—, donde alinear columnas no ayudaría
   a nadie. Cuando las filas SÍ se comparan, lo que toca es la tabla de arriba. */
.lista{ overflow:hidden }
.lista .fila{
  display:flex; align-items:center; gap:var(--e4);
  padding:var(--e3) var(--e5);
  border-top:var(--f-separa) solid var(--filete);
}
.lista .fila:first-child{ border-top:0 }
/* Y la primera fila DESPUÉS del rótulo tampoco lleva la suya: el rótulo ya trae
   su propio filete abajo, y las dos juntas se ven como una raya doble. */
.lista .cabecera + .fila{ border-top:0 }
.lista .fila:hover{ background:var(--fila-hover) }
.lista .cabecera{
  padding:var(--e3) var(--e5);
  background:var(--superficie);
  border-bottom:var(--f-agrupa) solid var(--cab-filete);
  font-size:var(--t-micro); font-weight:var(--p-fuerte); letter-spacing:.07em;
  text-transform:uppercase; color:var(--tinta-2);
}
.fila .principal{ display:flex; flex-direction:column; gap:2px; min-width:0; flex:1 1 220px }
.fila .principal .titulo{ font-weight:var(--p-fuerte); color:var(--tinta) }
.fila .principal .bajo{ font-size:var(--t-apoyo); color:var(--tinta-2) }
.fila .etiquetas{ display:flex; flex-wrap:wrap; gap:var(--e1) }
.fila .acciones{ display:flex; flex-wrap:wrap; gap:var(--e2); margin-left:auto }
.fila .acciones form{ display:inline }

/* ── barra de filtros ───────────────────────────────────────────────────────
   Los filtros son un <form method="get">: se pueden compartir por enlace, el
   botón «atrás» hace lo que se espera y funcionan sin JavaScript. Por eso esta
   fila SÍ lleva varios controles: es una barra de búsqueda, no un formulario de
   escribir datos (esos van a un campo por fila). */
.filtros{ display:flex; flex-wrap:wrap; gap:var(--e3); align-items:flex-end }
.filtros .campo{ flex:1 1 180px; min-width:0 }
.filtros .campo.ancho{ flex:2 1 260px }
.filtros .acciones{ display:flex; gap:var(--e2) }

/* ── tarjeta héroe y tarjetas menores (portal) ───────────────────────────── */
.heroe{ padding:var(--e7) var(--e6) }
.heroe h2{ font-weight:var(--p-fuerte); font-size:var(--t-titulo); letter-spacing:-.015em }
.heroe p{ margin-top:var(--e2); color:var(--tinta-2); max-width:62ch }
.heroe .cifra{ font-weight:var(--p-fuerte); font-size:56px; letter-spacing:-.02em; line-height:1 }
.heroe .cifra .unidad{ font-size:var(--t-cuerpo); color:var(--tinta-2); margin-left:var(--e2) }

.fila-mini{ display:grid; grid-template-columns:repeat(3,1fr); gap:var(--e4) }
.mini{ padding:var(--e5) }
.mini .icono{
  width:36px; height:36px; border-radius:var(--r);
  display:grid; place-items:center; margin-bottom:var(--e3);
  background:var(--chip-fondo); color:var(--chip-texto);
  border:var(--f-separa) solid var(--chip-filete);
}
.mini .icono svg{ width:18px; height:18px; stroke:currentColor; stroke-width:1.7;
                  fill:none; stroke-linecap:round; stroke-linejoin:round }
.mini h3{ font-size:var(--t-cuerpo); font-weight:var(--p-fuerte) }
.mini p{ margin-top:var(--e1); font-size:var(--t-apoyo); color:var(--tinta-2) }

/* ── aviso de tarea ─────────────────────────────────────────────────────────
   Para lo que la pantalla NO puede hacer sola y alguien tiene que ir a hacer a
   mano (crear el subdominio en cPanel). Se distingue del error a propósito:
   esto no es un fallo, es una tarea pendiente. Lleva el listón de resalte, que
   es el color de «mira esto primero». */
.aviso-tarea{
  border-left:var(--f-cierra) solid var(--resalte);
  padding:var(--e4) var(--e5); background:var(--resalte-suave);
}
.aviso-tarea h3{ font-size:13px; font-weight:var(--p-fuerte); color:var(--tinta) }
.aviso-tarea ol{ margin:var(--e3) 0 0 var(--e5); display:flex; flex-direction:column; gap:var(--e2) }
.aviso-tarea li{ font-size:var(--t-apoyo); color:var(--tinta-2) }

/* ── vacío ──────────────────────────────────────────────────────────────────
   Una lista sin nada dentro lo dice. Una tabla vacía sin explicación se lee como
   «esto está roto». */
.vacio{ padding:var(--e7) var(--e6); text-align:center; color:var(--tinta-2) }
.vacio p{ font-size:var(--t-apoyo); max-width:46ch; margin:var(--e2) auto 0 }

/* ── ayudas de maquetación ─────────────────────────────────────────────────
   Media docena y ni una más. Existen para que ninguna página tenga que escribir
   un style="…" suelto: eso rompería la regla de «ningún valor a mano en un
   componente» y, de paso, obligaría a abrirle la mano a la CSP (un style en
   línea es indistinguible de uno inyectado por un atacante). */
.estrecho{ max-width:420px }
.apagado{ color:var(--tinta-2); font-size:var(--t-apoyo) }
.detalle{ color:var(--tinta-2); font-size:var(--t-apoyo); font-family:var(--f-dato);
          white-space:pre-wrap }
.a-la-derecha{ margin-left:auto }
.separado{ margin-top:var(--e5) }
.separado-poco{ margin-top:var(--e2) }

/* ═══════════════════════════════════════════════════════════════════════════
   DOS PATRONES QUE SE REPITEN (S5.1)

   Tres pantallas pedían lo mismo —la ficha se despliega bajo su fila y avisa al
   guardar— y otras tres pedían buscar en vivo. Escribirlo seis veces habría
   dejado seis versiones que se van separando; está escrito una vez aquí y una
   vez en comun/plantilla/guiones.php.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── la ficha que se despliega bajo su fila ───────────────────────────────
   ── POR QUÉ YA NO ES EL TRUCO DE `0fr → 1fr` (S8.1, 2ª vuelta) ───────────
   Hasta S8.1 esto era una rejilla de una fila que pasaba de `0fr` a `1fr`, con
   la transición sobre `grid-template-rows`. **Funcionaba**, y conviene dejarlo
   dicho porque al medirlo pareció que no: en una pestaña que el navegador tiene
   en segundo plano el reloj de las animaciones está PARADO —
   `document.timeline.currentTime` clavado en 0— así que la transición no avanza
   nunca y el panel se mide a cero para siempre. Es la trampa nº 4 otra vez, y
   esta vez mordió en Chrome de verdad, no en el panel de la sesión. Con
   `transition:none` el mismo panel medía sus 462 px.

   Se cambia por otro motivo, y es uno solo: **un `<details>` no se puede animar
   con CSS**. No tiene estado intermedio — el navegador lo enseña y ya está—, y
   media docena de paneles de «añadir» de S8 son `<details>`. Con dos mecanismos
   distintos en la misma pantalla, uno se deslizaba y el otro daba un salto, que
   es lo que pidió arreglar Fabio.

   Así que ahora hay UNO: el estado abierto es `height:auto` en el `.dentro`
   —que no depende de nada de fuera y funciona SIN JavaScript, que es lo que
   sostiene estas pantallas— y la animación la hace el guion midiendo el alto
   real (`comun/plantilla/guiones.php`). Tampoco hay número mágico: el número se
   mide en vez de inventarse.

   Funciona sin JavaScript, y no de adorno: la ficha abierta es la que el
   servidor pinta con `?editar=<id>`, así que sin guion se abre navegando —una
   recarga— y con guion se abre en el sitio. Las demás fichas van en el HTML ya
   pintadas y cerradas, que es lo que permite abrirlas al instante.

   `visibility:hidden` mientras está cerrada NO es redundante con el recorte: sin
   ella los campos de una ficha cerrada siguen estando en el orden del tabulador,
   y quien navega con teclado se cae dentro de un formulario que no ve. Se
   retrasa al final del cierre para que la ficha no desaparezca de golpe. */
.desplegable{
  display:grid; grid-template-rows:auto;
  visibility:hidden;
  transition:visibility 0s linear var(--mov-normal);
}
.desplegable > .dentro{ overflow:hidden; min-height:0; height:0 }
.desplegable.abierta{
  visibility:visible;
  transition:visibility 0s;
}
.desplegable.abierta > .dentro{ height:auto }
/* Dentro de una .tabla, cada hijo hereda las columnas de la rejilla; la ficha
   ocupa el ancho entero y no una columna.
   `align-items:stretch` NO es de adorno y costó un repaso encontrarlo: `.tabla >
   *` pone `align-items:center`, y eso cae también sobre la ficha. Centrado, el
   `.dentro` conserva su alto de contenido en vez de estirarse a la pista de
   `0fr` — que es justo lo que hace funcionar el recorte—, así que al abrir y al
   cerrar la ficha aparecía a su alto completo montada sobre las filas de arriba
   y de abajo durante los 200 ms de la transición. Medido: el padre a 0 de alto y
   el `.dentro` a 340. Dentro de `.lista` no pasaba, porque allí no hay rejilla. */
.tabla > .desplegable{ grid-template-columns:1fr; gap:0; padding:0;
                       align-items:stretch }
/* El relleno y la separación suben de `--e4`/`--e3` a `--e5`/`--e4` (S8.1, 2ª
   vuelta). Fabio: «falta un poco de márgenes entre todos los elementos, está
   como muy pegado; los campos de nueva aplicación están mejor separados». Tenía
   razón y se veía comparando las dos: el panel de alta va dentro de una
   `.tarjeta`, que ya trae su relleno, y la ficha de una fila no. */
.desplegable .ficha{
  border:var(--f-separa) solid var(--filete); border-top:0;
  border-left:var(--f-cierra) solid var(--activo-filete);
  background:var(--superficie);
  padding:var(--e5);
  /* Mismo hueco que `.formulario`, y por lo mismo (Fabio, 28/08): con --e4 la
     etiqueta quedaba a 16 px del campo de arriba y a 6 del suyo, o sea 2,7
     veces, y no se leía a cuál pertenecía. Esta regla pesa (0,2,0) y le ganaba
     a `.formulario`, así que sin tocarla el alta de Pedidos —que es una
     `.ficha` dentro de un `.desplegable`— se quedaba con los 16 de antes
     mientras el resto del portal ya iba a 20. */
  display:flex; flex-direction:column; gap:var(--e5);
}
/* Condensado, que es lo que pidió Fabio: la casilla comparte fila con su
   aclaración y las acciones se van al final de la misma línea. */
.desplegable .ficha .linea{
  display:flex; flex-wrap:wrap; align-items:flex-end; gap:var(--e4);
}
.desplegable .ficha .linea > .campo{ flex:1 1 200px; min-width:0 }
.desplegable .ficha .linea > .campo.corto{ flex:0 0 110px }
/* ── una fila donde TODOS los campos son cortos (Fabio, 29/08) ────────────
   «Que los cuatro inputs de la segunda fila ocupen todo el ancho, cada uno su
   porcentaje correspondiente.» Los `.corto` están clavados a 110 px y no
   crecen —que es lo que hace falta cuando comparten fila con un campo largo,
   para que «Unidades» no se lleve el mismo hueco que «Fecha del trabajo»—,
   pero en una fila donde son los CUATRO, esos 440 px dejaban medio formulario
   en blanco: medido en la ficha de un concepto a 1.280, 500 px vacíos a la
   derecha de «Clave».

   `flex:1 1 0` y no un porcentaje escrito: con la base a cero, el reparto lo
   hace el `flex-grow` y sale el mismo cuarto para cada uno sea cual sea el
   ancho de la ventana. Un `width:25%` habría que corregirlo a mano en cuanto
   cambie el hueco entre campos, y en 375 px no se doblaría.

   Se pide con una clase y no se cambia `.corto` en general: la regla de
   arriba es la buena para las filas mixtas, que son casi todas. */
.desplegable .ficha .linea.repartida > .campo.corto{ flex:1 1 0 }
/* ── y una casilla que ocupa su propia fila ───────────────────────────────
   «Que los checkbox tengan cada uno una fila, y ocupen todo el ancho.» Iban a
   `flex:1 1 220px`, así que las tres de un concepto salían en columnas de un
   tercio y cada explicación se partía en cinco líneas — tres párrafos cortos
   uno al lado del otro que hay que leer de arriba abajo tres veces.

   `.completo` ya era la clase que se emitía para esto: existía en
   `.formulario.denso .completo{ grid-column:1 / -1 }` —el alta, que es una
   rejilla— y en una `.linea`, que es flex, no hacía absolutamente nada. Era
   una clase inventada a medias: escrita en el HTML de los dos formularios y
   viva solo en uno. */
.desplegable .ficha .linea > .casilla.completo{ flex:1 1 100% }
/* La línea alinea por abajo, así que lo único que centra de verdad la casilla
   —y los botones— contra el campo de al lado es darles el MISMO alto que tiene
   el `<input>`. Medido antes: el campo centraba en 507 y la casilla en 518,
   once píxeles por debajo. Es el mismo arreglo que la casilla de la barra de
   filtros, y por el mismo motivo. */
.desplegable .ficha .linea > .casilla{ flex:1 1 220px; align-items:center;
                                       min-height:38px }
.desplegable .ficha .acciones{ display:flex; align-items:center; gap:var(--e1);
                               min-height:38px; margin-left:auto }

/* ── el panel de ALTA, desplegable como el de filtros (4ª tanda) ──────────
   «Nueva obligación», «Nuevo grupo» y «Nueva persona» eran lo único del módulo
   que aparecía de golpe: se navegaba a `?nueva=1`, la página se recargaba y el
   formulario estaba ahí. Ahora usan la misma maquinaria que la ficha de una
   fila —el `0fr → 1fr` de `.desplegable`— y por eso se despliegan igual.

   Sigue funcionando sin JavaScript, y eso es lo que decide la forma: el panel
   está SIEMPRE en el HTML y nace cerrado, y el servidor le pone `.abierta`
   cuando la dirección trae `?nueva=1`. Sin guion se navega y sale abierto; con
   guion, el guion se queda con el clic y lo abre en el sitio.

   Dos cosas que no son de adorno:

   · El tope de alto. El alta de una persona son cinco campos con sus
     aclaraciones y en una ventana baja no cabe entera. Sin tope, empuja a la
     tabla hasta dejarla en nada y el formulario tampoco se ve completo: se
     pierden los dos. Con tope, el que se desplaza es él.
   · El margen negativo mientras está cerrado. `.contenido` separa a sus hijos
     con `gap`, y un hijo de alto cero SIGUE contando como hijo: cerrado, el
     panel metía una separación de más entre el buscador y la tabla, siempre.
     El margen la cancela, y se anima con el resto para que no dé un salto. */
.desplegable.alta{
  margin-top:calc(-1 * var(--e3));
  transition:margin-top var(--mov-normal) var(--curva),
             visibility 0s linear var(--mov-normal);
}
.desplegable.alta.abierta{
  margin-top:0;
  transition:margin-top var(--mov-normal) var(--curva), visibility 0s;
}
/* ── quién cede el alto cuando la ventana es baja ─────────────────────────
   Medido en una ventana de 560 px con el alta de una persona abierta: el panel
   se quedaba con los 269 px que pedía y **la tabla bajaba a CERO**. No es que
   estorbara: es que desaparecía, y sin barra propia, así que no había forma de
   saber que seguía ahí. Un panel de alta no puede borrar la pantalla sobre la
   que se está trabajando.

   Así que el que cede es el panel, y la tabla tiene un suelo:

   · el panel puede encoger (`flex:0 1 auto`) y no pasa de la mitad de la
     ventana; lo que no quepa se desplaza DENTRO de él;
   · la tabla nunca baja de 96 px, que es una fila y su barra: lo justo para
     que se vea que sigue estando y se pueda llegar a ella.

   El desplazamiento va en `.dentro` y no en la tarjeta, y esto sí importa:
   `.dentro` es quien recorta para que funcione el `0fr → 1fr`, así que si la
   barra la llevara la tarjeta, al encoger el panel la tarjeta se cortaría por
   fuera de su propia barra y habría trozo de formulario inalcanzable. */
.columna.fija .contenido > .desplegable.alta{ flex:0 1 auto; min-height:0 }
/* La barra propia del panel SOLO tiene sentido en una pantalla fija, que es
   donde hay un tope de alto que respetar. En una pantalla que se desplaza
   entera no hay nada que recortar y el panel no necesita barra: la pone la
   página. El `.columna.fija` de delante es lo que lo limita a donde hace falta. */
.columna.fija .desplegable.alta.abierta > .dentro{ overflow:hidden auto;
                                                   overscroll-behavior:contain }

/* ── quién cede el alto: MANDA EL PANEL ────────────────────────────────────
   Decidido por Fabio con la pantalla delante: «que ocupara casi toda la
   pantalla si es necesario, aunque se oculte la tabla hasta contraer el
   recuadro». En un portátil el panel se quedaba en 150 px y no se veía ni el
   primer campo.

   Lo hacen dos declaraciones y ninguna es un número mágico:

   · el panel es `flex:0 1 auto`, así que se lleva EXACTAMENTE lo que mide su
     formulario, ni más ni menos, y solo encoge si no cabe;
   · con un panel abierto, la tabla pasa a `flex:1 1 0%`: base cero. Deja de
     pedir sitio y se queda solo con lo que sobre — que puede ser nada.

   Así el panel se ve entero siempre que quepa, la tabla vuelve sola al cerrar y
   nadie tiene que adivinar un reparto. Y **no lleva `min-height`** a propósito:
   un mínimo que no cupiera se saldría de `.contenido`, que recorta, y dejaría
   un trozo de formulario al que no se puede llegar ni con la barra. */
.columna.fija .contenido > .crece.desborda{ flex:1 1 auto; min-height:0 }
.columna.fija .contenido:has(> .desplegable.alta.abierta) > .crece.desborda{
  flex:1 1 0%; min-height:0;
}
/* Y la nota AL PIE de la tabla se va con la tabla. No es por rascar píxeles —son
   47 con su separación—: esas notas explican la tabla («borrar un grupo no borra
   sus empresas», «el orden de esta lista es el orden de las columnas»), y una
   explicación de algo que no está en pantalla es ruido. Vuelve al cerrar.

   ⚠ El `> .crece ~` no es adorno, y su falta costó la queja de Fabio del 28/08:
   sin él la regla decía «cualquier `p.apagado` hijo de `.contenido`», y en
   Conceptos hay DOS —la nota del pie y el aviso que va ENCIMA de la tabla, el
   que lleva la cuenta de conceptos activos sin precio—. Abrir «Nuevo concepto»
   borraba también el de arriba, que no estorba a nadie y es justo el que hay
   que leer mientras se rellena el formulario. Ahora solo se van las notas que
   están DESPUÉS de la tabla, que son las que la explican. */
.columna.fija .contenido:has(> .desplegable.alta.abierta) > .crece ~ p.apagado{ display:none }
/* El rótulo del panel se queda a la vista mientras se baja por el formulario:
   con el tope de arriba, en una ventana corta se pierde de vista enseguida y
   entonces no se sabe si se está creando o editando. */
.desplegable.alta .tarjeta > .grupo{
  position:sticky; top:0; z-index:1;
  background:var(--papel); padding-top:var(--e1);
}

/* ── el aviso de que se ha guardado ───────────────────────────────────────
   Va pegado a la fila que se acaba de guardar y no en lo alto de la pantalla:
   en una lista de treinta y seis modelos, un «Guardado» arriba del todo obliga
   a subir para leerlo y no dice CUÁL se guardó.

   Se desvanece solo a los cuatro segundos, y si el guion no cargara se queda
   puesto hasta la siguiente navegación. Un aviso de más no rompe nada; uno que
   no aparece, sí. */
.aviso-guardado{
  display:inline-flex; align-items:center; gap:6px;
  padding:3px var(--e2); border-radius:var(--r);
  font-size:var(--t-micro); font-weight:var(--p-fuerte);
  color:var(--exito); background:var(--exito-fondo);
  transition:opacity var(--mov-normal) var(--curva);
}
.aviso-guardado::before{ content:''; width:6px; height:6px; background:currentColor }
.aviso-guardado.yendose{ opacity:0 }
/* Y entra igual de suave que se va (Fabio, 28/08: «que al aparecer y desaparecer
   se haga con una transición suave, que no sea brusco»). Irse ya se animaba —lo
   hace `.yendose` con su `transition`—, pero aparecer era un corte: el aviso
   estaba puesto en el HTML desde el primer fotograma. Una animación y no una
   transición, porque no hay dos estados entre los que pasar: el elemento nace
   ya en su sitio. Los 4 px son los mismos que baja el aviso del cierre. */
@keyframes aviso-entra{ from{ opacity:0; transform:translateY(-4px) } to{ opacity:1; transform:none } }
.aviso-guardado{ animation:aviso-entra var(--mov-normal) var(--curva) }
/* El aviso vive SIEMPRE en el HTML —es el sitio donde el guion escribe cuando la
   acción se hace sin recargar— y cuando no hay nada que decir no ocupa. Un
   `<p>` vacío mide 0 de alto pero el `gap` del contenido lo cuenta igual: serían
   20 px de hueco encima de la tabla que nadie entiende. */
.aviso-guardado.vacio{ display:none }

/* ── el cuadro que pregunta antes de hacer algo (S11 · 28/08) ─────────────
   El primero de la casa, y nace de la corrección de Fabio: «que se muestre un
   modal que diga que esa tarea tiene x minutos predeterminados de duración,
   ¿quiere apuntar estos minutos o modificarlos?».

   Es un `<dialog>` de verdad y no un `<div>` con posición: el navegador le da
   gratis el foco atrapado dentro, el Escape que cierra, la capa de encima de
   todo y el `aria-modal`. Escribir eso a mano son doscientas líneas y tres
   fallos de accesibilidad.

   Lo de la casa que hay que ponerle, porque el navegador trae lo suyo:
   cero sombra, radio de 2 px y el filete de 3 px que CIERRA un bloque. El
   `padding:0` del `<dialog>` de fábrica se sustituye por el relleno de una
   tarjeta, y el `border:solid` que le pone Chrome, por el nuestro.

   `max-width:min(420px, calc(100vw - 2 * var(--e4)))`: en 375 px un cuadro de
   ancho fijo se sale por los dos lados. Y `max-height` con su desplazamiento
   propio, porque con el teclado del teléfono abierto la ventana se queda en la
   mitad de alto. */
/* ⚠ `margin:auto` Y NO ES ADORNO (Fabio, 29/08: «el modal se pone en la esquina
   de arriba a la izquierda»). Un `<dialog>` abierto con `showModal()` se centra
   solo porque la hoja del navegador le pone `margin:auto` con `inset:0`… y la
   reinicialización de este fichero —`*{ margin:0 }`, línea 32— se lo quita a
   TODO, incluido él. Con los cuatro márgenes a cero y los cuatro `inset` a cero,
   el cuadro se va a la esquina de arriba a la izquierda. No da ningún error y no
   se ve midiendo: se ve mirando. Medido antes: x=0, y=0 en una ventana de
   1280×720. */
.cuadro{
  width:100%; max-width:min(420px, calc(100vw - 2 * var(--e4)));
  max-height:calc(100dvh - 2 * var(--e4)); overflow:auto;
  margin:auto;
  padding:var(--e5);
  border:var(--f-cierra) solid var(--tinta); border-radius:var(--r);
  background:var(--papel); color:var(--tinta);
}
/* El velo. `--tinta` con alpha y no un negro suelto: en oscuro el negro sobre
   negro no separa nada, y el token ya cambia con el tema. */
.cuadro::backdrop{ background:rgb(0 0 0 / .45) }
/* Los tres botones caben en una línea en escritorio y se apilan en el teléfono.
   `.acciones-panel` ya hace eso; lo único suyo es que «Cancelar» se va al final
   y no compite con los dos que sí hacen algo. */
.cuadro .acciones-panel{ margin-top:var(--e2) }
.cuadro .frase{ margin:0 }

/* ── el importe calculado, AL LADO del campo y no debajo (29/08, 2ª pasada) ─
   Fabio: «cuando se carga precio por trabajo, se desalinea el input». Y no era
   el campo: era la fila.

   `.linea` alinea por ABAJO, y eso es lo que hace que dos campos con etiquetas
   de distinto alto tengan el `<input>` a la misma altura — que es el caso
   normal, porque en esta casa la ayuda va DENTRO de la etiqueta y cada una mide
   lo que mide. En cuanto un campo crece por DEBAJO de su input, su caja baja y
   su input sube: medido, 17 px por encima del de al lado en cuanto aparecía el
   total.

   La salida no es cambiar la alineación de la fila —con `flex-start` se
   desalinean los inputs cuando las etiquetas miden distinto, que es lo
   corriente—, sino que la caja del campo vuelva a TERMINAR en su input. Así que
   el total se pone en la misma línea, a la derecha.

   Y de paso condensa, que es lo que pidió Fabio para todo el módulo: una línea
   menos y el importe pegado al número del que sale. */
.con-total{ display:flex; flex-wrap:wrap; align-items:center; gap:var(--e2); min-width:0 }
/* El `130px` de base es el suelo del campo: por debajo, «14.990,00» no cabe.
   Y `flex-wrap` para el caso extremo —999 unidades a 14.990— en el que el
   total mide 186 px y no queda sitio para los dos en 375: ahí baja a su
   propia línea. Eso hace crecer la caja por debajo del input, que es justo lo
   que descuadraba la fila… pero por debajo de 900 px cada campo ya va en su
   propia fila, así que no hay nada con lo que descuadrarse. */
.con-total > input{ flex:1 1 130px; min-width:0 }
.con-total > .ayuda{ flex:0 1 auto; white-space:nowrap;
                     overflow:hidden; text-overflow:ellipsis }

/* ── un campo apagado se tiene que VER apagado (29/08, 2ª pasada) ───────────
   Fabio: «haz más evidente que está desactivado cuando no tiene el checkbox
   marcado». Un `<input disabled>` sin regla propia sale con el mismo papel y el
   mismo filete que uno vivo: en esta casa los campos no tienen relleve, así que
   lo único que lo distinguía era que no aceptaba el cursor.

   Tres señales y ninguna es solo el color: el papel pasa a `--superficie` (el
   mismo gris de una fila apagada), el filete se afina a `--filete` y el cursor
   lo dice al pasar por encima. El marcador se apaga con él, para que un «30»
   fantasma no parezca un valor puesto.

   ⚠ La ETIQUETA no se apaga. Un control desactivado está exento de la regla de
   contraste (WCAG 1.4.3), pero su rótulo no: es lo que explica por qué no se
   puede escribir, y es justo lo que hay que poder leer. Ya se pagó una vez con
   `.apagado-del-todo` al .45, que dejaba el texto en 2,9:1. */
.campo input:disabled,
.campo select:disabled,
.campo textarea:disabled{
  background:var(--superficie); color:var(--tinta-2);
  border-color:var(--filete); cursor:not-allowed;
}
.campo input:disabled::placeholder{ opacity:.55 }

/* ── el mando de «¿cuánto te llevó?»: los atajos y el recuadro (29/08) ────
   Fabio: «diferencia entre sí los recuadros que seleccionan el tiempo, y añade
   un recuadro en el que se pueda poner el tiempo manualmente». Son dos mandos
   para una sola respuesta, y lo que los junta en una fila es esto.

   Los atajos se llevan el hueco que sobre y el recuadro se queda en lo suyo:
   caben cinco o seis atajos y un número de tres cifras. En 375 px `flex-wrap`
   los baja solos a dos filas, que es la regla de la casa para el teléfono.

   `align-items:flex-end` porque el recuadro lleva su rótulo encima y los atajos
   no: alineados por arriba, la fila de atajos quedaba flotando trece píxeles por
   encima de la caja de al lado. Es el mismo arreglo que la casilla de la barra
   de filtros. */
.minutos-pedido{ border:0; padding:0; margin:0 }
.minutos-pedido > legend{ font-size:var(--t-apoyo); font-weight:var(--p-fuerte);
                          padding:0 }
.minutos-pedido > legend .ayuda{ font-weight:var(--p-normal) }
/* ⚠ `flex-direction:row` ESCRITO, y no heredado. Este bloque lleva también la
   clase `.campo`, y `.campo` es `display:flex; flex-direction:column`: sin esta
   línea el fieldset se maquetaba en COLUMNA y el `flex-basis` de los atajos —que
   en una fila es el ancho— se leía como ALTO. Medido: los cuatro atajos salían
   de 294 px de alto cada uno y el cuadro entero medía 688 px en una ventana de
   720. No daba ningún error: solo se veía mirando. */
.minutos-pedido{ display:flex; flex-direction:row; flex-wrap:wrap;
                 align-items:flex-end; gap:var(--e2) }
/* ⚠ El `<legend>` de un fieldset NO es un hijo flex: el navegador lo saca del
   flujo y lo pinta encima del borde, así que ni el `gap` del fieldset ni un
   `flex:1 0 100%` le hacen nada — lo probé, y el `flex` era una línea muerta.
   Lo único que separa el rótulo de los atajos es su propio margen, y va a los
   6 px que `.campo` deja entre una etiqueta y su control. Sin esto medía 29,
   que es la etiqueta más suelta de todo el formulario. */
.minutos-pedido > legend{ margin-bottom:6px }
/* `0 1` y no `1 1`: los atajos NO se estiran a todo lo que sobre. Medido en la
   ficha de un pedido a 1.280 px, con `1 1` cada recuadro de tiempo salía de 205
   px de ancho para decir «30 min» — que es justo el «hay muchos huecos» que
   Fabio escribió del formulario. Con el tope se quedan en unos 75 y el recuadro
   de «Otro» viene detrás, no pegado al otro extremo de la fila. Por debajo de
   460 px encogen, que es lo que hace falta en el teléfono. */
.minutos-pedido > .segmentos{ flex:0 1 460px; min-width:0 }
.minutos-pedido > .otro-tiempo{ flex:0 0 92px }
/* El rótulo «Otro» va en el mismo tamaño que los atajos de al lado y no en el
   de una etiqueta de campo: si no, la fila tiene dos escalas de texto para
   decir lo mismo. */
.minutos-pedido > .otro-tiempo > label{ font-weight:var(--p-normal); color:var(--tinta-2) }

/* ── buscar en vivo ───────────────────────────────────────────────────────
   La barra sigue siendo un <form method="get"> con su botón, y así funciona sin
   JavaScript. Lo que hace el guion es quitar el botón —cuando filtra al
   escribir, un botón «Filtrar» que ya no hace falta enseña a desconfiar de los
   botones— y esconder las filas que no casan.

   `.sin-resultados` lo enseña el guion cuando el filtro deja la lista vacía: una
   tabla que se queda en blanco sin decir nada se lee como «esto está roto». */
.filtrando .sin-resultados{ display:block }
.sin-resultados{ display:none }
/* «Quitar filtros» cuando no hay ninguno puesto. Se queda a la vista, apagado,
   en vez de desaparecer: un botón que aparece y desaparece hace que la fila de
   acciones baile cada vez que se teclea una letra. El guion le quita además el
   tabulador y le pone `aria-disabled`, que es lo que sí oye un lector de
   pantalla — en un <a>, `disabled` no existe y no lo oye nadie. */
.apagado-del-todo{ opacity:.45; pointer-events:none }
/* …y una SECCIÓN entera apagada no puede ir al .45 de ese botón. Está medido en
   la pantalla de Ajustes de Pedidos (el hueco del buzón con IA, tarea 4.6b): a
   .45 el cuerpo del texto se queda en 2,9:1 en el tema claro y 4,1:1 en el
   oscuro, y un texto normal necesita 4,5:1. Un botón apagado está exento de esa
   regla —WCAG 1.4.3 no mide los controles desactivados—; un párrafo que hay que
   LEER en una videollamada, no: la sección existe justamente para que se lea
   dónde va a vivir lo que todavía no está hecho.

   Con .70 quedan 6,5:1 y 8,6:1 y se sigue viendo apagada al lado de las
   tarjetas vecinas. El selector lleva `section` a propósito para que esto no
   toque el «Quitar filtros», que es un <a> y sigue en .45. */
section.apagado-del-todo{ opacity:.7 }
/* Al filtrar en cliente, la última fila visible es la que tiene que redondear la
   esquina; si no, el redondeo se queda en una fila escondida y la tabla termina
   en pico. */
.tabla-fila[hidden]{ display:none }
/* La gemela para la lista simple, que FALTABA y por eso el buscador de Grupos
   no escondía ni una fila: el guion pone `fila.hidden = true`, pero
   `.lista .fila{ display:flex }` es una regla de autor y gana SIEMPRE al
   `[hidden]{display:none}` de la hoja del navegador. Encima el recuento salía 0
   y se encendía el cartel de «no hay ninguno» ENCIMA de la lista entera. */
.lista .fila[hidden]{ display:none }
/* Y la ficha desplegable de una fila escondida se esconde con ella. Cerrada mide
   cero y da igual, pero una ABIERTA se quedaba flotando pegada debajo de otra
   fila, como si fuera de esa. */
.desplegable[hidden]{ display:none }
/* Y la misma familia otra vez, esta vez en un botón (S11 · 7.3). `.boton` pone
   `display:inline-flex`, y CUALQUIER regla de autor le gana al
   `[hidden]{display:none}` de la hoja del navegador: `boton.hidden = true` no
   escondía nada.
   No es teórico: el guion del selector de ejercicio esconde el «Ir» cuando hay
   JavaScript —porque entonces cambiar el desplegable ya envía solo—, y llevaba
   desde S5.1 sin conseguirlo. Medido: `hidden` a `true`, `display` a `flex` y
   44×44 px en pantalla, en las dos pantallas de Obligaciones. Un botón de más
   en una fila que en el teléfono no da para tres cosas. */
.boton[hidden]{ display:none }
.tabla-fila.ultima-visible{ border-radius:0 0 var(--r) var(--r) }

/* ── pie ──────────────────────────────────────────────────────────────────
   Va DENTRO de la columna de contenido, no colgando del cuerpo: si colgara del
   cuerpo volvería a sumar alto por debajo del armazón y devolvería la barra de
   desplazamiento que .marco quita a propósito. */
.pie{ padding:var(--e5) var(--e2) 0; font-size:var(--t-micro); color:var(--tinta-2);
      text-align:center }

/* ── pantallas de acceso (entrar, olvide-clave, restablecer) ──────────────
   Sin menú lateral: ahí fuera todavía no eres nadie, y un menú que no lleva a
   ningún sitio solo estorba. Una tarjeta en medio, del ancho de un formulario y
   ni un píxel más. Los campos siguen siendo uno por fila. */
.marco-acceso{
  display:grid; justify-items:center; align-content:center;
  grid-template-columns:1fr;
  height:100dvh; padding:var(--e6);
}
/* La columna manda aquí también, y es la que se desplaza si la tarjeta no cabe
   (pantalla baja, o el navegador con el zoom subido). Con `place-items:center` a
   secas, lo que sobra se corta por ARRIBA y el título queda inalcanzable. */
.marco-acceso .columna{ width:min(420px,100%); max-height:100% }
.marco-acceso .contenido{ flex:0 0 auto }
.acceso{ padding:var(--e7) var(--e6); display:flex; flex-direction:column; gap:var(--e4) }
.acceso h1{ font-weight:var(--p-fuerte); font-size:var(--t-titulo); letter-spacing:-.015em }
.acceso .marca-acceso{ font-weight:var(--p-fuerte); font-size:18px; letter-spacing:-.015em;
                       color:var(--tinta-2) }
.acceso .marca-acceso em{ font-style:normal; color:var(--acc) }
.acceso .para-quien{ color:var(--tinta-2); margin-top:calc(var(--e3) * -1) }
.acceso .enlace-olvido{ text-align:center; font-size:var(--t-apoyo) }
.acceso .enlace-olvido a{ color:var(--tinta-2) }

/* ═══════════════════════════════════════════════════════════════════════════
   MÓDULO DE OBLIGACIONES (S5)

   Todo lo de aquí abajo es del módulo del mes. Sigue las mismas reglas que el
   resto del fichero —ni un color a mano, cero sombras, el grosor del filete hace
   la jerarquía— y se queda junto porque es una unidad: el día que el módulo se
   toque, se toca este bloque entero y no catorce sitios sueltos.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── pestañas del módulo ─────────────────────────────────────────────────── */
.pestanas{ display:flex; flex-wrap:wrap; gap:var(--e4);
           border-bottom:var(--f-separa) solid var(--filete) }
/* ── y la cinta no se mueve al cambiar de pantalla del módulo ──────────────
   `.columna.fija` aprieta el `gap` de `.contenido` a --e3 para ganar sitio
   para la tabla, y las pantallas que se desplazan van a --e4. Consecuencia:
   dentro del MISMO módulo la cinta de pestañas cae 4 px más abajo en unas que
   en otras —medido en Pedidos: 80,7 px en la lista y en Conceptos, 84,7 en
   Cierre y en Ajustes—, así que al pulsar una pestaña la página da un salto
   que se lee como que se ha movido sola.

   Se iguala por ABAJO, a la medida de la pantalla fija, y no al revés: esos
   4 px se le quitaron a propósito a la cabecera para dárselos a la tabla, y
   devolvérselos aquí sería deshacer aquello por la puerta de atrás.

   El `:has(+ .pestanas)` lo limita a las cabeceras que llevan cinta debajo:
   una pantalla suelta —Empresas, Facturas— no tiene con qué desalinearse y no
   se le toca nada. */
.contenido > .cabecera-pagina:has(+ .pestanas){
  margin-bottom:calc(var(--e3) - var(--e4));
}
.columna.fija .contenido > .cabecera-pagina:has(+ .pestanas){ margin-bottom:0 }
.pestanas a{ padding:var(--e2) 0; font-size:var(--t-cuerpo); font-weight:var(--p-fuerte);
             color:var(--tinta-2); border-bottom:var(--f-cierra) solid transparent;
             margin-bottom:calc(var(--f-separa) * -1) }
.pestanas a:hover{ color:var(--tinta); text-decoration:none }
.pestanas a[aria-current="page"]{ color:var(--tinta); border-bottom-color:var(--tinta) }
/* En escritorio manda la palabra y el icono sobra: la pantalla que aprobó Fabio
   en S3.5 llevaba texto y nada más. El dibujo está en el HTML para el móvil, y
   aquí simplemente no se enseña. */
.pestanas a svg{ display:none }

/* ── la barra del mes: elegir, ver cuánto hay y decidir cómo se mira ───────
   Una sola fila con las tres cosas de esta pantalla. Antes eran dos —el
   ejercicio y un `.titulo-mes` con un «Enero de 2026» en 20 px— y decían el mes
   dos veces, porque el desplegable ya lo dice. Juntarlas devolvió 52 px de alto
   a la tabla, y en una pantalla que no se desplaza eso es fila y media más de
   trabajo a la vista. */
.barra-mes{ display:flex; align-items:center; gap:var(--e3); flex-wrap:wrap }

/* ── la caja de filtros, con los botones dentro (2ª ronda de S5.1) ─────────
   Una sola caja de lado a lado. El sumario ocupa la izquierda de la primera
   línea, los botones la derecha, y el panel de filtros baja por DEBAJO de los
   dos, a todo el ancho. Antes la caja envolvía solo al <details> y los botones
   iban en una franja aparte a su derecha: el recuadro se quedaba corto y esa
   franja se comía ancho para nada.

   El <details> se queda con su <summary> y nada más; el panel es HERMANO suyo y
   lo enseña `[open] ~ .panel-filtros`. Se probó con `display:contents` en el
   <details> para poder dejar el panel dentro, y no funciona: el navegador mete
   su propia ranura interna entre el <details> y sus hijos, y es esa la que ocupa
   la columna. Medido: el panel se quedaba en 747 px de 1.156. */
.barra-filtros{
  display:grid; grid-template-columns:minmax(0,1fr) auto;
  grid-template-areas:"sumario acciones"
                      "panel   panel";
  align-items:center;
}
.barra-filtros > .filtros-plegables{ grid-column:1; grid-row:1; min-width:0 }
.barra-filtros > .panel-filtros{ grid-column:1 / -1; grid-row:2 }
/* Los botones, apretados: en esta fila no son la acción principal —lo es la
   tabla de abajo— y cada píxel que se llevan se lo quitan a ella. */
.barra-filtros > .acciones-pantalla{
  grid-column:2; grid-row:1;
  display:flex; gap:var(--e1); align-items:center;
  padding:0 var(--e2) 0 0;
}
.barra-filtros > .acciones-pantalla .boton{ min-height:26px; padding:3px var(--e2) }
.barra-filtros > .acciones-pantalla .boton svg{ width:14px; height:14px }

/* El despliegue, animado. Mismo mecanismo que la ficha desplegable y el menú del
   móvil: una rejilla de una fila que va de 0fr a 1fr, que SÍ se puede animar
   hasta la altura real del contenido.
   `visibility` se retrasa al final del cierre para que los campos de un panel
   cerrado no sigan en el orden del tabulador. */
.panel-filtros{
  display:grid; grid-template-rows:0fr; visibility:hidden;
  border-top:0 solid var(--filete);
  transition:grid-template-rows var(--mov-normal) var(--curva),
             border-top-width var(--mov-normal) var(--curva),
             visibility 0s linear var(--mov-normal);
}
.panel-filtros > .dentro{ overflow:hidden; min-height:0 }
.filtros-plegables[open] ~ .panel-filtros{
  grid-template-rows:1fr; visibility:visible;
  border-top-width:var(--f-separa);
  transition:grid-template-rows var(--mov-normal) var(--curva),
             border-top-width var(--mov-normal) var(--curva), visibility 0s;
}
.barra-mes .cuentas-mes{ display:flex; align-items:center; gap:var(--e2);
                         flex-wrap:wrap; margin:0 }

.titulo-mes{ display:flex; align-items:center; gap:var(--e3); flex-wrap:wrap }
.titulo-mes h2{ font-size:20px; font-weight:var(--p-fuerte); letter-spacing:-.015em }
.titulo-mes .a-la-derecha{ display:flex; align-items:center; gap:var(--e2) }

/* ── la fila del ejercicio, encima de la cinta de meses (S5.1 §2.1) ────────
   El desplegable y su botón en la MISMA fila. Antes vivían en la cabecera de
   pantalla, donde el «Ir» se caía a una segunda línea en cuanto el título era
   largo: son una sola cosa —elegir año— y se les trata como tal. */
.fila-ejercicio{
  display:flex; align-items:center; gap:var(--e2); flex-wrap:nowrap;
}
.fila-ejercicio label{
  font-size:var(--t-micro); font-weight:var(--p-fuerte); letter-spacing:.07em;
  text-transform:uppercase; color:var(--tinta-2);
}
/* Un rótulo y su desplegable son UNA cosa, y así viajan por la fila (S11 · 7.3).
   Sueltos, en cuanto la fila se dobla —y en el teléfono se dobla siempre— el
   navegador parte por donde le cabe: medido a 375 px en el cierre de mes, la
   etiqueta «Mes» se quedaba en x=336, pegada al borde derecho, con su
   desplegable ya en la línea de abajo. Un rótulo apuntando a nada.

   En el escritorio no cambia nada: la caja no pinta nada y reparte el mismo
   hueco entre el rótulo y el campo que repartía la fila. */
.fila-ejercicio .par-campo{
  display:flex; align-items:center; gap:var(--e2); min-width:0;
}
.fila-ejercicio select{
  width:auto; min-width:90px; padding:5px var(--e3); min-height:30px;
  border:var(--f-separa) solid var(--filete-fuerte); border-radius:var(--r);
  background:var(--papel); color:var(--tinta);
  font-family:var(--f-texto); font-size:var(--t-apoyo);
}

/* Un botón que se queda pulsado: filtra y sigue filtrando hasta que se vuelve a
   pulsar. Lleva `aria-pressed` en el HTML, que es lo que lo dice de verdad; esto
   es solo que además se vea. */
.boton.pulsado,
.boton.fantasma.pulsado{
  background:var(--activo-fondo); color:var(--activo-texto);
  border-color:var(--activo-filete);
}

/* ── barra de filtros del módulo ─────────────────────────────────────────
   Un <details> de verdad: abre y cierra sin JavaScript. Desde S5.1 (2ª ronda)
   se pliega TAMBIÉN en escritorio —antes solo en el móvil— porque desplegada se
   comía 87 px de alto, y en una pantalla que ya no se desplaza esos 87 px se los
   quita a la tabla todos los días para una barra que se toca una vez al día.

   Nace abierta solo si hay algún filtro puesto. Esa regla no es nueva y no se
   toca: esconder un filtro que sí está filtrando es como alguien se pasa media
   mañana sin entender por qué le faltan empresas. */
.filtros-plegables > summary{
  display:flex; align-items:center; gap:var(--e2);
  padding:var(--e1) var(--e3); min-height:26px; cursor:pointer;
  font-size:var(--t-apoyo); font-weight:var(--p-fuerte);
  list-style:none;
}
.filtros-plegables > summary::-webkit-details-marker{ display:none }
.filtros-plegables > summary::marker{ content:'' }
.filtros-plegables > summary:hover{ background:var(--fila-hover) }
/* El filete que separa el sumario del panel lo pone ahora el propio panel al
   abrirse (y se anima con él): puesto en el sumario aparecía de golpe. */
/* La flecha: es lo único que dice de un vistazo que esto se abre. Gira 90° al
   abrir, que es el gesto que todo el mundo ya conoce. */
.filtros-plegables .flecha,
.cierre-cliente > summary .flecha{ display:inline-flex; flex:none;
                            transition:transform var(--mov-rapido) var(--curva) }
.filtros-plegables .flecha svg,
.cierre-cliente > summary .flecha svg{ width:14px; height:14px; stroke:currentColor;
                                stroke-width:2; fill:none; stroke-linecap:round;
                                stroke-linejoin:round }
.filtros-plegables[open] .flecha,
.cierre-cliente[open] > summary .flecha{ transform:rotate(90deg) }
.filtros-mes{ display:flex; flex-wrap:wrap; gap:var(--e3); align-items:flex-end;
              padding:var(--e3) }
.filtros-mes .campo{ flex:1 1 150px; min-width:0 }
.filtros-mes .campo.ancho{ flex:2 1 220px }
/* La casilla comparte fila con el buscador y los botones, y la fila alinea por
   abajo (`align-items:flex-end`), así que lo único que la centra de verdad es
   darle el MISMO alto que tienen ellos: bajando a 40 px de caja, su contenido
   cae exactamente en el centro de los otros. Con el relleno de antes se quedaba
   tres píxeles por debajo — poco, pero en una fila de cuatro cosas se ve.
   Medido: centro de la casilla 189 contra 186 del buscador y de los botones;
   ahora los tres en 186. */
.filtros-mes .casilla{ align-items:center; min-height:40px; padding-bottom:0 }
.filtros-mes .acciones{ display:flex; gap:var(--e2); padding-bottom:0 }

/* ── leyenda de estados ──────────────────────────────────────────────────── */
.fila-leyenda{ display:flex; align-items:center; gap:var(--e4); flex-wrap:wrap }
.fila-leyenda .apagado{ font-size:var(--t-micro) }
.leyenda{ display:flex; flex-wrap:wrap; gap:var(--e4);
          font-size:var(--t-micro); color:var(--tinta-2) }
.clave-estado{ display:inline-flex; align-items:center; gap:6px }
.clave-estado i{ width:12px; height:12px; border:var(--f-separa) solid var(--filete) }
.clave-estado.entregada i{ background:var(--exito-fondo); border-color:var(--exito) }
.clave-estado.pendiente i{ background:var(--aviso-fondo); border-color:var(--aviso) }
.clave-estado.no-obligado i{ background:var(--superficie); border-color:var(--filete-fuerte) }
.clave-estado.vacia i{ background:var(--papel) }
.clave-estado b{ font-family:var(--f-dato); font-weight:var(--p-dato); color:var(--tinta) }

/* ══════════════════════════════════════════════════════════════════════════
   EL CÓDIGO DE COLOR DE LOS GRÁFICOS (4ª tanda de S5.1)

   Cuatro categorías, cuatro colores, y los MISMOS en los cuatro gráficos del
   cuadro de mando. Están escritos una sola vez aquí abajo y de aquí los toman
   la leyenda, las barras apiladas, las columnas del año y los rótulos de los
   KPI. Antes cada gráfico se pintaba por su cuenta y por eso no coincidían: en
   «el año mes a mes» lo pendiente era el hueco sin rellenar, en «el reparto del
   año» también, y las no obligadas no aparecían en ninguno de los dos.

   Los tonos son los `-relleno`, que van a 3:1 contra el papel, y no los de
   TEXTO, que van a 4.5:1 y como mancha salen opacos («un color incómodo de
   mirar»). `--error-relleno` es nuevo de esta tanda y lo genera el mismo script
   que los otros dos, midiendo el contraste en los ocho matices y las dos luces.

   La leyenda usa el par fondo+filete y las barras el relleno macizo: en un
   cuadradito de 12 px un macizo pesa demasiado al lado del texto, y en una
   barra de 14 px un fondo claro no se ve. Es la misma pareja de tonos.
   ══════════════════════════════════════════════════════════════════════════ */
/* La leyenda de los GRÁFICOS lleva el relleno macizo, el mismo de la barra que
   explica, y no el fondo claro de la celda. Es la diferencia entre una leyenda
   que se compara de un vistazo y una que hay que interpretar: en oscuro, el
   `-fondo` es casi el papel y un cuadradito así no se parece a nada de lo que
   hay en el gráfico. La leyenda del MES se queda como está —allí lo que explica
   son las celdas, y las celdas sí llevan fondo claro con filete—. */
.leyenda.tramos .clave-estado i{ border-color:transparent }
.leyenda.tramos .clave-estado.a-tiempo i,       .clave-color.a-tiempo      { background:var(--exito-relleno) }
.leyenda.tramos .clave-estado.fuera-de-plazo i, .clave-color.fuera-de-plazo{ background:var(--error-relleno) }
.leyenda.tramos .clave-estado.pendiente i,      .clave-color.pendiente     { background:var(--aviso-relleno) }
/* En un cuadradito de 12px la trama de 6px de paso no se vería —cabrían dos
   rayas—, así que aquí va a la mitad de paso. Es el mismo gris y la misma
   inclinación: lo que se reconoce es la trama, no su medida exacta. */
.leyenda.tramos .clave-estado.no-obligado i,    .clave-color.no-obligado{
  background-color:var(--superficie); border-color:var(--marcador);
  background-image:repeating-linear-gradient(-45deg,
      transparent 0 2.6px, var(--marcador) 2.6px 3px);
}

/* El cuadradito del rótulo de un KPI: el mismo de la leyenda, para que la cifra
   de arriba y la barra de abajo se lean como lo mismo. */
.clave-color{
  display:inline-block; width:10px; height:10px; flex:none;
  margin-right:6px; vertical-align:baseline;
  border:var(--f-separa) solid transparent;
}

/* ── la rejilla del mes ──────────────────────────────────────────────────
   Es una <table> de verdad, y no la .tabla de tarjetas de arriba, por dos
   motivos que no son estéticos: aquí SÍ hay cabecera de columna que un lector de
   pantalla tiene que anunciar en cada celda, y hacen falta dos ejes pegados —la
   cabecera arriba y la empresa a la izquierda— que con divs cuesta el triple y
   se rompe al primer cambio.

   Enero tiene 24 columnas y no caben a lo ancho; por eso la primera columna y la
   cabecera se quedan clavadas. Es la decisión de S5: se asume el desplazamiento
   a cambio de no tocar la forma de trabajar. */
/* Hasta S5.1 esto llevaba `max-height:62vh`, y ese número era el problema: en
   una ventana de 900 px daba una tabla de 558 y dejaba 167 px de contenido por
   debajo, así que había que mover DOS barras para llegar al final. Ahora no
   tiene alto propio: se estira hasta donde llegue la ventana y se desplaza por
   dentro, a lo alto y a lo ancho. */
.rejilla-marco{ overflow:auto; overscroll-behavior:contain;
                flex:1 1 auto; min-height:0;
                border:var(--f-separa) solid var(--filete); border-radius:var(--r);
                background:var(--papel) }
.rejilla{ border-collapse:separate; border-spacing:0; width:max-content; min-width:100% }
.rejilla th, .rejilla td{ padding:0; text-align:left; vertical-align:middle;
                          border-bottom:var(--f-separa) solid var(--filete);
                          border-right:var(--f-separa) solid var(--filete);
  /* `position:relative` en cada celda, y no es adorno: dentro va un
     `.solo-lectores`, que es `position:absolute`. Sin un ancestro posicionado,
     ese texto se ancla al documento entero y su posición estática cae donde
     esté la celda —en la columna 24 son 1.700 px—, así que la PÁGINA se hacía
     1.700 px de ancha y aparecía una barra horizontal que el armazón quita a
     propósito. Anclado a su celda, se queda dentro del marco que sí desplaza.
     Las dos reglas de abajo lo pisan con `sticky`, que también sirve de ancla. */
                          position:relative }

.rejilla thead th{ position:sticky; top:0; z-index:3;
                   background:var(--superficie); color:var(--tinta-2);
                   border-bottom:var(--f-agrupa) solid var(--cab-filete);
                   padding:var(--e2) var(--e3);
                   font-size:var(--t-micro); font-weight:var(--p-fuerte);
                   letter-spacing:.07em; text-transform:uppercase; white-space:nowrap }
.rejilla th.columna-obligacion{ width:88px; min-width:88px; max-width:88px;
                                text-align:center; padding:var(--e2) var(--e1) }
.rejilla th.columna-obligacion .modelo{ display:block; font-size:var(--t-apoyo);
                                        color:var(--tinta); text-transform:none;
                                        letter-spacing:0;
                                        overflow:hidden; text-overflow:ellipsis }

/* El ancho lo manda una variable para poder cambiarlo desde el tirador (§2.7).
   El SUELO son 190 px y no es un número al azar: es lo que mide el NIF más largo
   en monoespaciada con su relleno, y Fabio pidió «un mínimo razonable: que
   siempre se vea el NIF». Por debajo de ahí el dato que identifica a la empresa
   se corta, y entonces la columna deja de servir para lo que está. */
.rejilla{ --ancho-empresa: 280px }
.rejilla .columna-empresa{ position:sticky; left:0; z-index:2;
                           width:var(--ancho-empresa);
                           min-width:var(--ancho-empresa);
                           max-width:var(--ancho-empresa);
                           background:var(--papel); padding:var(--e2) var(--e3);
                           border-right:var(--f-agrupa) solid var(--filete);
                           font-weight:var(--p-normal) }
.rejilla thead .columna-empresa{ z-index:4; background:var(--superficie);
                                 position:sticky; left:0 }
/* El tirador: una franja de 7 px pegada al borde derecho de la cabecera de la
   columna. Se ve al pasar el ratón por la cabecera y cuando tiene el foco; el
   resto del tiempo no está, porque es un mando que se usa una vez al mes y no
   tiene por qué competir con los datos. */
.tirador{
  position:absolute; top:0; right:-3px; bottom:0; z-index:5;
  width:7px; padding:0; border:0; background:transparent;
  cursor:col-resize;
}
.tirador::after{
  content:''; position:absolute; top:0; bottom:0; left:3px;
  width:1px; background:transparent;
  transition:background var(--mov-rapido) var(--curva);
}
.rejilla thead .columna-empresa:hover .tirador::after,
.tirador:hover::after,
.tirador:focus-visible::after{ background:var(--acc) }
.tirador:focus-visible{ outline:var(--f-agrupa) solid var(--foco); outline-offset:-1px }
/* Mientras se arrastra, el cursor manda en toda la página y no se selecciona
   texto por el camino. */
.redimensionando{ cursor:col-resize; user-select:none }

.rejilla tbody tr:hover td,
.rejilla tbody tr:hover .columna-empresa{ background:var(--fila-hover) }
.rejilla .empresa-inactiva .columna-empresa{ background:var(--superficie);
                                             border-left:var(--f-cierra) solid var(--filete-fuerte) }

/* La cabecera de responsable: la fila con fondo que ya tienen en el Excel.
   Lo pegajoso es el HIJO, no el <th>: una celda con colspan mide lo que la tabla
   entera, así que `sticky` sobre ella no pega nada y el nombre se iría a la
   izquierda en cuanto se desplace a lo ancho. */
.rejilla .fila-responsable th{ background:var(--superficie);
                               border-top:var(--f-agrupa) solid var(--tinta);
                               padding:0; font-size:var(--t-apoyo); text-align:left }
.rejilla .pegado{ position:sticky; left:0; z-index:2;
                  display:flex; align-items:center; gap:var(--e2);
                  width:max-content; max-width:100%; padding:var(--e2) var(--e3) }
.rejilla .fila-responsable .quien-lleva{ font-weight:var(--p-fuerte); color:var(--tinta) }
.rejilla .fila-responsable .cuantas{ color:var(--tinta-2); font-size:var(--t-micro) }
.rejilla .fila-grupo-empresas th{ background:var(--papel); padding:0; text-align:left;
                                  border-left:var(--f-cierra) solid var(--activo-filete) }
.rejilla .fila-grupo-empresas .pegado{ padding:var(--e1) var(--e3) }

/* ── el desplegable de orden de una cabecera (§2.5) ───────────────────────
   Es el mismo `<details class="menu">` del botón de tres puntos, y por eso
   hereda su panel, su «cerrar al pulsar fuera» y su Escape. Lo que cambia aquí
   es que el mando NO es un botón aparte: el mando ES la cabecera. Así ordenar
   se pide donde se mira, sin gastar ni un píxel de una fila que ya va justa.

   El panel se abre hacia la IZQUIERDA (`right:0`) porque una columna de modelo
   mide 88 px y el panel 230: abriéndolo hacia la derecha, el de la última
   columna se saldría del marco, que tiene `overflow:auto` y lo recortaría. */
.menu.ordenar{ display:block }
.menu.ordenar > summary{
  display:flex; align-items:center; gap:4px;
  color:inherit; font:inherit; letter-spacing:inherit; text-transform:inherit;
}
.tabla-cabecera .menu.ordenar > summary{ min-height:34px }
.rejilla th.columna-obligacion .menu.ordenar > summary{ justify-content:center }
.menu.ordenar > summary:hover{ color:var(--tinta) }
.menu.ordenar > summary:hover .marca-orden{ color:var(--tinta) }
/* El chevrón vive siempre en el hueco, puesto o no, para que la cabecera no dé
   un salto de 12 px la primera vez que se pasa el ratón por encima. Apagado
   cuando no ordena esta columna; con la tinta entera cuando sí. */
.menu.ordenar .marca-orden{ display:inline-flex; flex:none; color:transparent;
                          transition:color var(--mov-rapido) var(--curva) }
.menu.ordenar .marca-orden svg{ width:12px; height:12px; stroke:currentColor;
                              stroke-width:2.4; fill:none;
                              stroke-linecap:round; stroke-linejoin:round }
.menu.ordenar .marca-orden.puesta{ color:var(--acc) }
.menu.ordenar[open] .marca-orden{ color:var(--tinta) }
.menu.ordenar.ordenando > summary .rotulo-orden{ color:var(--tinta) }
.menu.ordenar .panel{ right:0; left:auto; top:100%; min-width:250px;
                    text-transform:none; letter-spacing:0 }
/* ── y el panel abierto se pone por encima de TODO lo demás (4ª tanda) ────
   El panel vale `z-index:20`, pero ese 20 no se mide contra la página: se mide
   dentro de la cabecera que lo contiene, que es `sticky` CON `z-index` y por eso
   crea contexto de apilado propio. Así que el panel del 111 valía lo que valga
   su `<th>` —3—, y la cabecera de EMPRESA vale 4 y se le pintaba encima: el menú
   salía cortado por detrás de la primera columna, que es la foto que mandó
   Fabio. Se sube la cabecera QUE TIENE EL MENÚ ABIERTO por encima de las demás,
   y solo mientras lo tiene abierto. */
.rejilla thead th:has(.menu.ordenar[open]),
.rejilla thead .columna-empresa:has(.menu.ordenar[open]){ z-index:9 }
/* Lo mismo en la lista, donde la que se pega arriba es la cabecera entera. */
.tabla-cabecera:has(.menu.ordenar[open]){ z-index:9 }
/* Y en la columna de la empresa, que es la primera y la más ancha, hacia la
   derecha: hacia la izquierda se saldría del marco por el otro lado. */
.rejilla .columna-empresa .menu.ordenar .panel{ right:auto; left:0 }
/* En la lista, las dos primeras columnas de datos abren hacia la derecha y las
   demás hacia la izquierda: en los dos casos, hacia dentro de la tabla. */
.tabla-cabecera > span:nth-child(2) .menu.ordenar .panel,
.tabla-cabecera > span:nth-child(3) .menu.ordenar .panel{ right:auto; left:0 }
.menu.ordenar .panel .boton{ font-size:12px; min-height:32px }
/* El panel hereda de `.rejilla thead th` el `white-space:nowrap`, y con él una
   opción larga se sale de su caja en vez de partirse. */
.menu.ordenar .panel .boton{ white-space:normal; text-align:left }

/* La celda: un botón, porque se pulsa. Y lleva SIEMPRE su palabra o su fecha:
   el color no puede llevar solo la información. */
.celda-obligacion{ padding:0 }
.celda-estado{ display:flex; align-items:center; justify-content:center; gap:5px;
               width:100%; min-height:38px; padding:var(--e1) 6px;
               border:0; border-radius:0; background:transparent; cursor:pointer;
               font-family:var(--f-texto); font-size:var(--t-micro);
               font-weight:var(--p-fuerte); color:var(--tinta-2); white-space:nowrap }
.celda-estado i{ width:6px; height:6px; background:currentColor; flex:none }
.celda-estado.entregada{ background:var(--exito-fondo); color:var(--exito) }
.celda-estado.pendiente{ background:var(--aviso-fondo); color:var(--aviso) }
.celda-estado.no-obligado{ background:var(--superficie); color:var(--tinta-2);
                           font-weight:var(--p-normal) }
.celda-estado.no-obligado i{ background:transparent;
                             box-shadow:inset 0 0 0 1px var(--filete-fuerte) }
.celda-estado:hover{ box-shadow:inset 0 0 0 2px var(--tinta); text-decoration:none }
/* La celda cuya ficha está abierta (§rejilla 3). Se marca con un filo GRUESO de
   la tinta, no con un color de fondo: el fondo ya lo usa el estado —verde,
   ámbar, gris— y pisarlo sería perder el dato para ganar la señal. Y como el
   filo es interior, la celda no cambia de tamaño ni mueve la rejilla. */
.celda-estado.abierta{ box-shadow:inset 0 0 0 3px var(--tinta) }
.celda-estado.abierta:hover{ box-shadow:inset 0 0 0 3px var(--tinta) }
/* Esa empresa no presenta ese modelo este mes: ni botón, ni color, ni ruido. */
.celda-vacia{ display:block; min-height:38px }

/* El conmutador de forma se hace con ENLACES, no con radios como el de tema:
   cambiar de vista es navegar, y navegar es un enlace (la dirección se comparte
   y el botón «atrás» funciona). Se le da el mismo aspecto que a los segmentos. */
.segmentos a{
  display:inline-flex; align-items:center; gap:var(--e2);
  padding:6px var(--e3); border-radius:var(--r);
  font-size:var(--t-apoyo); font-weight:var(--p-fuerte);
  color:var(--tinta-2); user-select:none;
}
.segmentos a:hover{ background:var(--fila-hover); color:var(--tinta); text-decoration:none }
.segmentos a[aria-current="page"]{
  background:var(--activo-fondo); color:var(--activo-texto);
  box-shadow:inset 0 0 0 1px var(--activo-filete);
}
.segmentos a svg{ width:14px; height:14px; stroke:currentColor; stroke-width:1.7;
                  fill:none; stroke-linecap:round; stroke-linejoin:round }

/* ── la ficha de una obligación, al lado de la rejilla ─────────────────────
   El hueco de la ficha está SIEMPRE en la página, midiendo cero (S5.1 §2.6).
   Hasta ahora el panel solo existía cuando el servidor lo pintaba, así que
   pulsar una casilla era recargar la pantalla entera: se perdía el sitio de la
   rejilla y, en enero, el desplazamiento horizontal de 24 columnas.

   Se anima la PISTA de la rejilla, de 0 a 380 px, y las dos medidas son
   longitudes a propósito: mezclando `0fr` con `380px` el navegador no sabe
   interpolar y el panel aparecería de golpe. */
.con-panel{ display:grid; grid-template-columns:minmax(0,1fr) 0px; gap:0;
            align-items:stretch;
            /* Se estira hasta donde llegue el hueco de la pantalla fija, y sus
               dos columnas miden lo mismo: eso es lo que hace que el panel de la
               ficha acabe EXACTAMENTE donde acaba la tabla, que es lo que pidió
               Fabio. `min-height:0` otra vez, o la rejilla se niega a encoger. */
            flex:1 1 auto; min-height:0;
            transition:grid-template-columns var(--mov-normal) var(--curva),
                       gap var(--mov-normal) var(--curva) }
.con-panel.con-ficha{ grid-template-columns:minmax(0,1fr) 380px; gap:var(--e4) }
/* `overflow:hidden` mientras está cerrada, para que la ficha se recorte según
   crece el hueco en vez de asomar por encima de la rejilla. Abierta pasa a
   desplazarse por dentro: es el SEGUNDO —y último— desplazamiento de la
   pantalla, y acaba justo donde acaba la tabla. */
.hueco-ficha{ min-width:0; min-height:0; overflow:hidden }
.con-panel.con-ficha .hueco-ficha{ overflow-y:auto; overflow-x:hidden;
                                   overscroll-behavior:contain }

/* ── la misma ficha, superpuesta (la lista, y todo el móvil) ───────────────
   En la lista las columnas son anchas: partir la pantalla en dos para hacerle
   sitio al panel dejaba la tabla ilegible. Así que aquí entra POR LA DERECHA y
   se pone encima (§2.8). En el móvil, más abajo, sube desde abajo (§2.b.5).

   `visibility` se retrasa hasta el final del cierre por lo mismo que en la ficha
   desplegable: sin ella, los campos de un panel cerrado siguen en el orden del
   tabulador y quien navega con teclado se cae dentro de algo que no ve. */
.hueco-ficha.superpuesta{
  position:fixed; top:0; right:0; bottom:0; z-index:50;
  width:min(420px, 100%);
  overflow-y:auto; overscroll-behavior:contain;
  background:var(--papel);
  border-left:var(--f-cierra) solid var(--tinta);
  transform:translateX(100%); visibility:hidden;
  transition:transform var(--mov-normal) var(--curva),
             visibility 0s linear var(--mov-normal);
}
.hueco-ficha.superpuesta.con-ficha{
  transform:none; visibility:visible;
  transition:transform var(--mov-normal) var(--curva), visibility 0s;
}
.hueco-ficha.superpuesta .panel-obligacion{ border:0; border-radius:0; min-height:100% }

/* El velo de detrás. Existe para dos cosas: que se vea que lo de debajo está
   esperando, y tener dónde pulsar para cerrar. Lo pone y lo quita el guion. */
.velo-ficha{
  position:fixed; inset:0; z-index:49;
  background:var(--tinta); opacity:0;
  transition:opacity var(--mov-normal) var(--curva);
}
.velo-ficha.puesto{ opacity:.35 }

/* ── los dos banners del marcado múltiple (§2.9) ───────────────────────────
   El de informar se ve de partida; el de actuar aparece cuando hay algo
   marcado, desplegándose de arriba abajo con el mismo truco de la rejilla de
   0fr a 1fr que usa la ficha desplegable.

   Sin JavaScript se ven los dos y todo funciona: se pierde el aparecer, no la
   función. Por eso el estado de partida del HTML es «los dos puestos» y es el
   guion el que esconde uno. */
.aviso-lote{
  display:flex; align-items:center; gap:var(--e2);
  padding:var(--e2) var(--e4);
  border:var(--f-separa) solid var(--filete); border-radius:var(--r);
  font-size:var(--t-apoyo); color:var(--tinta-2);
}
.aviso-lote svg{ flex:none; width:16px; height:16px; stroke:currentColor;
                 stroke-width:1.7; fill:none }
.js .aviso-lote[hidden]{ display:none }
.js .barra-lote{
  display:grid; grid-template-rows:0fr;
  padding:0; border-width:0; visibility:hidden;
  transition:grid-template-rows var(--mov-normal) var(--curva),
             padding var(--mov-normal) var(--curva),
             visibility 0s linear var(--mov-normal);
}
.js .barra-lote > .dentro{ overflow:hidden; min-height:0 }
.js .barra-lote.hay-marcadas{
  grid-template-rows:1fr; visibility:visible;
  padding:var(--e3) var(--e4); border-width:var(--f-separa);
  border-left-width:var(--f-cierra);
  transition:grid-template-rows var(--mov-normal) var(--curva),
             padding var(--mov-normal) var(--curva), visibility 0s;
}
.lado-rejilla{ display:flex; flex-direction:column; gap:var(--e3);
               min-width:0; min-height:0 }
.panel-obligacion{ display:flex; flex-direction:column; gap:var(--e4); padding:var(--e5) }
.panel-cabeza{ display:flex; align-items:flex-start; gap:var(--e3) }
.panel-cabeza > div{ margin-right:auto; min-width:0 }
.panel-cabeza h2{ font-size:18px; font-weight:var(--p-fuerte); letter-spacing:-.015em }
.panel-cabeza .grupo{ border-bottom:0; padding-bottom:2px }
.panel-estado{ display:flex; align-items:center; gap:var(--e3); flex-wrap:wrap;
               padding-bottom:var(--e3);
               border-bottom:var(--f-agrupa) solid var(--tinta) }
.datos-panel{ display:grid; grid-template-columns:auto minmax(0,1fr);
              gap:var(--e2) var(--e3); font-size:var(--t-apoyo) }
.datos-panel dt{ color:var(--tinta-2) }
.datos-panel dd{ min-width:0; overflow-wrap:anywhere }
.fecha-con-hoy{ display:flex; gap:var(--e2) }
.fecha-con-hoy input{ flex:1 1 auto; min-width:0 }
.acciones-panel{ display:flex; gap:var(--e2); flex-wrap:wrap }
.acciones-panel form{ flex:1 1 140px; display:flex }
.acciones-panel .boton{ width:100% }
.panel-historial{ padding-top:var(--e3); border-top:var(--f-separa) solid var(--filete) }
.panel-historial ul{ list-style:none; display:flex; flex-direction:column; gap:var(--e2);
                     margin:var(--e2) 0 0; font-size:var(--t-apoyo) }

/* ── el reparto de alto de la vista lista ─────────────────────────────────
   Mismo reparto que la rejilla: los dos banners miden lo suyo y la tabla se
   lleva lo que queda, desplazándose por dentro. Así la lista tiene UN
   desplazamiento —el suyo— y no el de la página entera.

   `.lista-marco` es la que lleva el `overflow`, y no la propia `.tabla`: la
   tabla es una pila de tarjetas con `border-radius` en la última, y ponerle a
   ella el desplazamiento le recorta las esquinas. */
.columna.fija .lista-crece{ display:flex; flex-direction:column; gap:var(--e3);
                            flex:1 1 auto; min-height:0 }
.columna.fija .lista-crece > *{ flex:none }
.columna.fija .lista-marco{ flex:1 1 auto; min-height:0;
                            overflow:auto; overscroll-behavior:contain }

/* ── la barra de marcado múltiple (solo en la lista) ─────────────────────── */
/* ── la barra del marcado múltiple, fina y en una línea (§lista 4) ─────────
   Fabio la vio y dijo que se veía fea: el recuento caía abajo, el rótulo «Fecha
   de entrega» quedaba encima del campo, y con dos alturas distintas la barra se
   leía en zigzag.

   Ahora es una sola línea, todo centrado en el mismo eje, y se lee como una
   frase: «3 elegidas · Fecha 18/08/2026 · Presentar · No obligadas». El rótulo
   va AL LADO del campo y no encima, que es la diferencia entera. */
.barra-lote{ padding:var(--e2) var(--e3);
             border:var(--f-separa) solid var(--filete); border-radius:var(--r);
             border-left:var(--f-cierra) solid var(--resalte);
             border-style:solid; background:var(--resalte-suave) }
.barra-lote .dentro{ display:flex; align-items:center; gap:var(--e3); flex-wrap:wrap }
.barra-lote .cuantas{ font-weight:var(--p-fuerte); font-size:var(--t-apoyo) }
/* El campo de fecha con su rótulo al lado. No usa `.campo`, que apila por
   diseño: aquí apilar es justo lo que sobraba. */
.barra-lote .fecha-lote{ display:inline-flex; align-items:center; gap:var(--e2);
                         margin-left:auto }
.barra-lote .fecha-lote > span{ font-size:var(--t-micro); font-weight:var(--p-fuerte);
                                letter-spacing:.06em; text-transform:uppercase;
                                color:var(--tinta-2) }
.barra-lote .fecha-lote input{
  width:auto; min-height:30px; padding:4px var(--e2);
  border:var(--f-separa) solid var(--filete-fuerte); border-radius:var(--r);
  background:var(--papel); color:var(--tinta);
  font-family:var(--f-texto); font-size:var(--t-apoyo);
}
.campo.compacto{ flex:0 0 auto }
.campo.compacto select, .campo.compacto input{ width:auto; min-width:140px }

/* El aviso suelto de «ya está hecho», cuando no hay panel donde meterlo.
   Sustituye a la tarjeta entera que había antes: cuatro palabras no necesitan
   filete, relleno de 20 px y una fila y media de la tabla. */
.aviso-guardado.suelto{ align-self:flex-start }

/* ── el botón de la fila que dice EN QUÉ estado está (§lista 2) ────────────
   Tres caras según el estado, y al pasar el ratón por una ya hecha ofrece
   deshacer. La palabra de deshacer está en el HTML y no la escribe el guion:
   así también la ve quien llega con el tabulador. */
.marcar-entregada{ position:relative }
.marcar-entregada .al-pasar{ display:none }
.marcar-entregada.estado-entregada,
.marcar-entregada.estado-no_obligado{
  background:transparent; border-color:var(--filete-fuerte); color:var(--tinta-2);
}
.marcar-entregada.estado-entregada{ color:var(--exito); border-color:var(--exito) }
.marcar-entregada.estado-entregada:hover,
.marcar-entregada.estado-no_obligado:hover{
  background:var(--fila-hover); color:var(--tinta); border-color:var(--filete-fuerte);
}
/* Al pasar el ratón —o al recibir el foco— la palabra cambia a «Deshacer». */
.marcar-entregada.estado-entregada:hover .palabra,
.marcar-entregada.estado-no_obligado:hover .palabra,
.marcar-entregada.estado-entregada:focus-visible .palabra,
.marcar-entregada.estado-no_obligado:focus-visible .palabra{ display:none }
.marcar-entregada.estado-entregada:hover .al-pasar,
.marcar-entregada.estado-no_obligado:hover .al-pasar,
.marcar-entregada.estado-entregada:focus-visible .al-pasar,
.marcar-entregada.estado-no_obligado:focus-visible .al-pasar{ display:inline }

/* El mismo botón de dos caras, en Pedidos (S11 · 3.4). Aquí el estado no viaja
   en una clase `estado-…`: la fila entera ya la lleva (`.tabla-fila.es-abierto`)
   y el botón sólo se pinta cuando hay algo que ofrecer, así que la regla es la
   general y no una lista de estados.

   Sin esto se veían LAS DOS palabras a la vez —«Abierto Marcar hecho» en el
   mismo botón—, que es lo que salió al mirar la pantalla a 375 px: el HTML de
   `index.php` traía `.palabra` y `.al-pasar` y ninguna hoja de estilos sabía
   nada de la clase `.marcar`. Ni un error, ni un aviso: sólo un botón que dice
   dos cosas contrarias. */
.boton.marcar{ position:relative }
.boton.marcar .al-pasar{ display:none }
.boton.marcar:hover .palabra,
.boton.marcar:focus-visible .palabra{ display:none }
.boton.marcar:hover .al-pasar,
.boton.marcar:focus-visible .al-pasar{ display:inline }

/* ── la ficha de una empresa (§4.b) ───────────────────────────────────────
   El nombre de la empresa va DEBAJO de las pestañas y no en la cabecera de la
   página: arriba tiene que quedar siempre el menú en el que estás. Y «Volver»
   a su derecha, que es donde se busca cuando ya has terminado. */
.titulo-ficha{ display:flex; align-items:baseline; gap:var(--e3); flex-wrap:wrap;
               margin-top:var(--e4) }
.titulo-ficha h2{ font-family:var(--f-titulo); font-size:20px;
                  font-weight:var(--p-fuerte); letter-spacing:-.01em; margin:0 }
.titulo-ficha .nif-ficha{ font-family:var(--f-dato); font-size:var(--t-apoyo);
                          color:var(--tinta-2) }
/* `align-self:center` porque el resto de la fila se alinea por la línea base del
   título y un botón alineado por su base queda tres píxeles bajo. */
.titulo-ficha .a-la-derecha{ align-self:center }

/* Las tres filas de §4.b.5: dos campos por fila, y apilados en el móvil. Es la
   única pantalla del sistema con dos por fila, y es porque los pares que pidió
   Fabio se leen juntos (NIF y nombre son «quién es»). */
.filas-ficha{ display:flex; flex-direction:column; gap:var(--e4) }
.fila-ficha{ display:grid; grid-template-columns:1fr 1fr; gap:var(--e4);
             align-items:start }
.fila-ficha > *{ min-width:0 }

/* Responsables y estado: casillas de verdad, no un `<select multiple>`. El marco
   se desplaza por dentro cuando el equipo crece, para que la ficha no se estire
   sin fin, y con doce personas ni aparece la barra. */
.lista-casillas{ border:0; padding:0; margin:0 }
.lista-casillas > legend{ padding:0; font-size:var(--t-apoyo);
                          font-weight:var(--p-fuerte); color:var(--tinta) }
.casillas-marco{ display:flex; flex-direction:column; gap:var(--e2);
                 max-height:190px; overflow-y:auto;
                 margin-top:6px; padding:var(--e3);
                 border:var(--f-separa) solid var(--filete-fuerte);
                 border-radius:var(--r); background:var(--papel) }
.casillas-marco .casilla{ cursor:pointer }
.casillas-marco .casilla:hover .texto{ color:var(--tinta) }
.lista-casillas .ayuda{ margin-top:6px; font-size:var(--t-apoyo); color:var(--tinta-2) }
/* El mismo armazón, pero con un `.segmentos` dentro en vez de las casillas: son
   los cuatro chips de tiempo de la ficha de un pedido (S11 · 3.5).

   El margen NO es de adorno y se vio midiendo: un `<legend>` no es hijo de la
   caja flexible —el navegador lo saca de la pila para dibujarlo sobre el borde
   del `<fieldset>`—, así que el `gap:6px` de `.campo` no le llega y el rótulo
   «¿Cuánto te llevó?» quedaba pegado a los chips, a 0 px, contra los 6 de
   cualquier otro campo del mismo formulario. Es exactamente el mismo margen que
   ya lleva `.casillas-marco` aquí arriba, y por lo mismo. */
.lista-casillas > .segmentos{ margin-top:6px }

/* ── Pedidos · ajustes del módulo (S11 · 4.6) ─────────────────────────────
   Las casillas de «quién ve el precio» van una al lado de otra y no una por
   fila: son DOS, y son la misma decisión partida en dos mitades. Apiladas se
   leen como dos ajustes distintos.

   Cada casilla es una caja de verdad y no una casilla suelta: el objetivo
   táctil pasa de los 15 px del cuadradito a toda la caja, que es lo que pide el
   móvil, y de paso hay sitio para la frase que explica a quién afecta marcarla.
   Un permiso que se marca sin leer se desmarca sin leer.

   El filete es `--filete-fuerte` y no `--filete`, y no lleva `background`: la
   caja vive dentro de un `.bloque`, que YA es `--papel`, así que repetir el
   fondo no pinta nada y el filete flojo casi no se distingue sobre blanco. Es
   lo mismo que hace `.casillas-marco` aquí arriba, y por lo mismo.

   Lo que NO lleva, a propósito: un `display:flex` para el `.texto`.
   `.casilla .texto .ayuda` ya es `display:block`, así que el rótulo y su
   explicación se apilan solos; con un `gap` propio ésta sería la única casilla
   del portal separada de otra manera. */
.roles-precio{ display:grid; gap:var(--e3);
               grid-template-columns:repeat(auto-fit, minmax(250px,1fr)) }
.roles-precio > .casilla{ padding:var(--e3); min-height:44px;
                          border:var(--f-separa) solid var(--filete-fuerte);
                          border-radius:var(--r) }

/* Quién lo ve HOY, con nombres. En línea y envolviendo: con once personas, una
   por fila son once líneas para decir algo que se lee de un vistazo. El icono
   de cada nombre no necesita medida propia — se la da el suelo de
   `svg[aria-hidden="true"]` de arriba del todo del fichero.

   ⚠ A quien NO ve el precio se le pone `class="apagado"`, que ya existe y hace
   exactamente esto (`--tinta-2` y `--t-apoyo`). No se inventa una clase nueva
   para eso. El precio de reusarla es que esta regla NO puede declarar `color`:
   pesa 0-1-1 contra el 0-1-0 de `.apagado` y se lo comería sin dar ningún
   error, dejando a los que no lo ven del mismo color que a los que sí. Lo
   vigila `herramientas/comprobar_pedidos.php` (sección B4). */
.quien-lo-ve{ display:flex; flex-wrap:wrap; gap:var(--e2);
              margin:0; padding:0; list-style:none }
.quien-lo-ve > li{ display:flex; align-items:center; gap:6px;
                   font-size:var(--t-apoyo) }

/* Los dos avisos de la matriz, juntos y antes de ella (§4.b.8). */
.avisos-matriz{ display:flex; flex-direction:column; gap:var(--e2) }
.avisos-matriz p{ font-size:var(--t-apoyo) }
/* La muestra del verde dentro de la frase: el aviso dice «los meses en verde» y
   sin enseñar cuál es el verde hay que ir a buscarlo. */
.pastilla-verde{ display:inline-block; padding:0 6px; border-radius:var(--r);
                 background:var(--exito-fondo); color:var(--exito);
                 font-weight:var(--p-fuerte) }

/* El botón de guardar, pegado abajo (§4.b.9). Con 36 obligaciones × 12 meses, el
   botón queda a mil píxeles de donde se está trabajando y salirse sin guardar
   deja de ser un descuido raro para ser lo normal. Ocupa lo mínimo de alto, que
   es la otra mitad de lo que pidió Fabio. */
.guardar-pegado{
  position:sticky; bottom:0; z-index:6;
  align-items:center; margin-top:var(--e4);
  padding:var(--e2) var(--e3);
  background:var(--superficie);
  border:var(--f-separa) solid var(--filete);
  border-top:var(--f-agrupa) solid var(--tinta);
  border-radius:0 0 var(--r) var(--r);
}
/* `width:auto` pisando a `.acciones-panel .boton{width:100%}`: heredándolo, el
   botón ocupaba la fila entera, la nota se iba a la línea de abajo y la barra
   medía 80 px de alto. Pegada a la parte baja de la pantalla, eso son 80 px
   menos de matriz para siempre. Con los dos en la misma línea, 50. */
.guardar-pegado .boton{ width:auto; min-height:34px }
.guardar-pegado .nota-guardar{ font-size:var(--t-apoyo) }

/* ── Pedidos · el cierre de mes (S11 · 5.5) ───────────────────────────────
   Un cliente por bloque, con su total a la derecha del rótulo. Se pliega con
   <details> y no con guion: abre y cierra él solo, con teclado incluido y sin
   una línea de JavaScript — que es lo que sostiene todas las pantallas de este
   módulo.

   El sumario es la tapa de la tarjeta: cuando está cerrado se redondea entero,
   y cuando está abierto solo por arriba, porque debajo va la tabla. Sin la
   primera regla, un cliente plegado termina en pico y parece que le falta algo. */
.cierre-cliente{ margin-top:var(--e3) }
.cierre-cliente > summary{
  display:flex; align-items:center; gap:var(--e3);
  padding:var(--e3) var(--e4); min-height:48px; cursor:pointer;
  background:var(--superficie);
  border:var(--f-separa) solid var(--filete);
  border-bottom:var(--f-agrupa) solid var(--cab-filete);
  border-radius:var(--r) var(--r) 0 0;
  font-weight:var(--p-fuerte);
  list-style:none;
}
.cierre-cliente:not([open]) > summary{
  border-radius:var(--r);
  border-bottom:var(--f-separa) solid var(--filete);
}
.cierre-cliente > summary::-webkit-details-marker{ display:none }
.cierre-cliente > summary::marker{ content:'' }
.cierre-cliente > summary:hover{ background:var(--fila-hover) }
/* El nombre del cliente se recorta ANTES de empujar al total. «ACTIVOS SIERRA
   SAN MIGUEL SL» en 375 px se lleva la fila entera, y el importe —que es lo que
   se ha venido a mirar— se salía del sumario por la derecha. */
.cierre-cliente > summary .empresa{
  min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
.cierre-cliente > summary .total{
  margin-left:auto; flex:none;
  font-family:var(--f-dato); font-size:16px; font-weight:var(--p-fuerte);
  font-variant-numeric:tabular-nums;
}
/* La cabecera de la tabla de dentro no vuelve a redondear ni a poner filete
   arriba: el que cierra por arriba es el sumario del cliente. Las FILAS no
   necesitan nada — `.tabla-fila` ya nace con `border-top:0`. */
.cierre-cliente .tabla-cabecera{ border-radius:0; border-top:0 }

/* La línea que no puede entrar todavía. NO se esconde: lo que no se ve, no se
   arregla, y una línea sin precio escondida es exactamente el trabajo que no se
   factura este mes ni ningún otro.

   Es el MISMO listón —y el mismo color— que `.tabla.conceptos .tabla-fila.sin-precio`
   del bloque de columnas: la señal de la casa para «esto no es como los demás».
   Va scoped a `.tabla.cierre-lineas` y no suelto, porque `.tabla-fila.sin-precio`
   a pelo pintaría también las filas del catálogo con otro tono. */
.tabla.cierre-lineas .tabla-fila.sin-precio{ border-left:var(--f-cierra) solid var(--aviso) }
/* Lo arrastrado de meses anteriores se distingue por el fondo, no por el color
   del texto: no es un problema, es un dato. Y lleva además su etiqueta con el
   mes, porque un color solo nunca lleva la información. */
.tabla.cierre-lineas .tabla-fila.arrastrada{ background:var(--superficie) }

/* El total del mes, cerrando la lista. El filete grueso de arriba es el mismo
   gesto que `.guardar-pegado`: aquí se acaba de sumar. */
.total-mes{
  display:flex; align-items:baseline; gap:var(--e3); flex-wrap:wrap;
  margin-top:var(--e4);
  padding:var(--e4) var(--e5);
  background:var(--papel);
  border:var(--f-separa) solid var(--filete);
  border-top:var(--f-cierra) solid var(--tinta);
  border-radius:var(--r);
}
.total-mes .cifra{
  font-family:var(--f-dato); font-size:26px; font-weight:var(--p-fuerte);
  font-variant-numeric:tabular-nums; letter-spacing:-.02em; line-height:1.1;
}
.total-mes .acciones{ margin-left:auto; display:flex; gap:var(--e2); flex-wrap:wrap }

/* ── la matriz de obligación × mes de la ficha de empresa ─────────────────
   Sustituye al «elige el modelo en una lista y luego marca sus meses en otro
   panel» del Excel, que es donde se equivocan: si te saltas el paso intermedio,
   los meses se guardan en el modelo que no era. Aquí la casilla del mes está en
   la fila de su modelo y no hay paso intermedio que saltarse. */
.matriz{ display:flex; flex-direction:column; gap:2px }
.matriz .cabecera-matriz,
.matriz .fila-matriz{ display:grid;
  grid-template-columns:minmax(180px,1fr) repeat(12, 38px) 44px;
  gap:var(--e1); align-items:center }
/* La cabecera de los meses, pegada arriba (§4.b.7). Se pega al VIEWPORT y no a
   un marco con desplazamiento propio: la ficha es una página que se desplaza
   entera, y meterle una segunda zona de desplazamiento dentro es justo lo que
   §4.1 vino a quitar. El `top` es 0 porque en escritorio la página no tiene
   cabecera fija encima; en el móvil sí, y allí se ajusta más abajo. */
.matriz .cabecera-matriz{ position:sticky; top:0; z-index:5;
                          padding:var(--e2) var(--e3);
                          background:var(--superficie);
                          border-bottom:var(--f-agrupa) solid var(--cab-filete);
                          font-size:var(--t-micro); font-weight:var(--p-fuerte);
                          letter-spacing:.06em; text-transform:uppercase;
                          color:var(--tinta-2) }
.matriz .cabecera-matriz span:not(:first-child){ text-align:center }
.matriz .fila-matriz{ padding:var(--e1) var(--e3);
                      border:var(--f-separa) solid var(--filete); border-radius:var(--r) }
.matriz .fila-matriz:hover{ background:var(--fila-hover) }
.matriz .que{ display:flex; flex-direction:column; gap:1px; min-width:0 }
.matriz .que strong{ font-size:13px; font-weight:var(--p-fuerte) }
.matriz .que .ayuda{ font-size:var(--t-micro); color:var(--tinta-2) }
/* `position:relative` y no es adorno: es la misma trampa que ya se pagó en la
   rejilla del mes. Dentro de cada casilla va un `.solo-lectores`, que es
   `position:absolute`; sin un ancestro posicionado se ancla al `.marco` y su
   posición estática cae donde esté la casilla —la de diciembre, a 756 px—, así
   que la PÁGINA se hacía 712 px de ancha en un teléfono de 375 y aparecía una
   barra horizontal. Anclado a su casilla, se queda dentro del marco de la
   matriz, que sí desplaza. Medido: 712 → 375. */
.matriz .mes{ position:relative;
              display:grid; place-items:center; min-height:34px;
              border-radius:var(--r); cursor:pointer }
.matriz .mes:hover{ background:var(--chip-fondo) }
.matriz .mes input{ width:15px; height:15px; accent-color:var(--acc); cursor:pointer }
/* Un mes con la obligación YA entregada no se desmarca sin querer: la casilla
   sigue funcionando, pero se ve que ahí hay algo hecho. */
.matriz .mes.hecho{ background:var(--exito-fondo) }
.matriz .mes.hecho input{ accent-color:var(--exito) }

/* ── catálogo y equipo ───────────────────────────────────────────────────── */
.orden{ font-family:var(--f-dato); font-weight:var(--p-dato); font-size:var(--t-apoyo);
        color:var(--tinta-2) }
/* En Clientes y en Usuarios la sublínea de .celda-principal es un NIF o un
   subdominio y va en monoespaciada. En el catálogo es prosa, y la monoespaciada
   estaría diciendo «esto se compara letra a letra», que es mentira. */

/* ── dos campos que son una pareja (S9.1, 22/08) ──────────────────────────
   `.linea` alinea por ABAJO, y eso está bien cuando lo que comparte fila es un
   campo con una casilla o con un botón: así se centran contra el `<input>`.
   Con dos campos y uno de ellos con su `.ayuda` debajo, alinear por abajo
   empuja al otro hacia abajo y las dos etiquetas quedan a distinta altura — que
   es justo lo que se ve en la captura del 22/08.

   Alineando por arriba, las etiquetas cuadran, los campos cuadran, y la ayuda
   cuelga de quien la tiene. */
.desplegable .ficha .linea.pareja{ align-items:flex-start }
/* …y la casilla NO se estira a todo lo que sobre (Fabio, 29/08: «está algo
   descuadrado y hay muchos huecos»). `.desplegable .ficha .linea > .casilla` es
   `flex:1 1 220px`, así que en el alta la casilla de «Ya está hecho» crecía
   hasta 1.100 px y empujaba el campo del tiempo al otro extremo de la fila: los
   dos mandos que hay que usar SEGUIDOS quedaban a media pantalla el uno del
   otro. Con el tope, el texto de la casilla sigue teniendo sitio de sobra —tres
   líneas de aclaración caben en 620— y el tiempo viene detrás, que es donde se
   va a buscar. Por debajo de ese ancho encoge y en 375 px se dobla sola. */
.desplegable .ficha .linea.pareja > .casilla{ flex:0 1 520px }
/* …y lo que sobra se lo lleva el campo de al lado (2ª pasada del 29/08). El
   bloque del tiempo era un `.corto` de 110 px: la etiqueta y su explicación se
   partían en CUATRO líneas, el campo caía 76 px por debajo de la casilla y
   quedaban 176 px vacíos a la derecha de la fila. Con 520 para la casilla, al
   tiempo le quedan 386 y el rótulo entero cabe en una línea. */
.desplegable .ficha .linea.pareja > .campo{ flex:1 1 auto }

/* ── los botones del formulario de un aviso ───────────────────────────────
   `.acciones-panel .boton{ width:100% }` está pensado para los paneles de
   acciones que llevan cada botón dentro de su propio `<form>` (la baja de una
   persona, por ejemplo), donde el botón tiene que llenar su hueco. En un
   Guardar/Cancelar normal eso los convierte en dos barras apiladas.

   Equipo ya lo resuelve así para el suyo (`.formulario.persona`), y este es el
   mismo caso con otro nombre. Se afina por formulario y no se toca la regla
   general: hay paneles que SÍ quieren el botón entero. */
.formulario.aviso .acciones-panel{ padding-top:var(--e2); flex-wrap:nowrap }
.formulario.aviso .acciones-panel .boton{ width:auto }

/* La sublínea de un aviso es su texto, no un dato: en la tabla salía en la
   fuente de datos, que es la de los NIF y los importes. Misma excepción que ya
   tienen Catálogo, Equipo y Actividad. */
.tabla.catalogo .celda-principal .bajo,
.tabla.conceptos .celda-principal .bajo,
.tabla.equipo .celda-principal .bajo,
.tabla.actividad .celda-principal .bajo,
.tabla.avisos-panel .celda-principal .bajo,
.tabla.avisos-panel .celda .bajo{ font-family:var(--f-texto); font-size:var(--t-apoyo) }

/* ── la pantalla de Equipo del portal (S5.5) ──────────────────────────────
   Aquí manda una idea: las filas son DOS LÍNEAS y nada más. Con doce personas,
   cada línea de más son doce líneas de más y la tabla deja de leerse de un
   vistazo. El nombre con el que se le conoce dentro del módulo no va bajo el
   nombre de la cuenta —serían tres líneas— sino en su propia columna, que es
   donde se busca. */
.tabla.equipo .tabla-fila{ min-height:48px }
.tabla.equipo .celda-principal{ gap:0 }
.tabla.equipo .celda-modulo{ display:flex; flex-direction:column; gap:1px; min-width:0 }
.tabla.equipo .celda-modulo .bajo{
  font-size:var(--t-micro); color:var(--tinta-2);
  overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
}
/* La columna de acciones es de 44 px y lleva un solo botón: sin esto, el `gap`
   de la rejilla lo separaba del borde y quedaba flotando. */
.tabla.equipo .celda-acciones{ justify-content:flex-end }

/* ── el aviso de la cabecera ──────────────────────────────────────────────
   Lo que está a medias se dice UNA vez y arriba, no fila a fila. Y se dice con
   un aviso de verdad: antes era una `.tarjeta` con un `.estado` suelto dentro,
   así que heredaba el relleno de tarjeta (24/32 px) y el aviso quedaba nadando
   con márgenes que no eran los de nadie.

   Se distingue por el listón de la izquierda y por el fondo, no por un color de
   texto: es la misma gramática que `.tabla-fila.inactiva` y que `.kpi.mirar-esto`. */
.aviso-cabecera{
  display:flex; align-items:flex-start; gap:var(--e3);
  padding:var(--e3) var(--e4);
  border:var(--f-separa) solid var(--aviso);
  border-left:var(--f-cierra) solid var(--aviso);
  border-radius:var(--r);
  background:var(--aviso-fondo);
}
.aviso-cabecera svg{ flex:none; width:18px; height:18px; margin-top:1px;
                     stroke:var(--aviso); stroke-width:1.8; fill:none }
.aviso-cabecera .texto{ display:flex; flex-direction:column; gap:2px; min-width:0 }
.aviso-cabecera .titulo{ font-size:13px; font-weight:var(--p-fuerte); color:var(--tinta) }
.aviso-cabecera p{ font-size:var(--t-apoyo); color:var(--tinta-2) }
.aviso-cabecera strong{ color:var(--tinta); font-weight:var(--p-fuerte) }

/* ── el formulario de una persona ─────────────────────────────────────────
   UNA COLUMNA, y con tope de ancho.

   Estaba con `.formulario.denso`, que son dos columnas… y `.denso` es la
   excepción del PANEL, no del portal (ver su comentario más arriba). En una
   pantalla de 1400 px eso dejaba la columna izquierda vacía enfrente de cuatro
   casillas, campos de 700 px de ancho para escribir un correo, y los grupos
   descolgados unos de otros. El tope de 560 px es el que hace que un campo mida
   lo que mide lo que se escribe dentro.

   Es además la regla que ya fijó Fabio para todo el proyecto: cada input a
   ancho completo, nunca dos por fila. */
.formulario.persona{ display:flex; flex-direction:column; gap:var(--e4) }
.formulario.persona .grupo-campos{ width:100% }
/* Aire entre el filete del rótulo («Nueva persona») y el primer campo: sin él
   las etiquetas nacen tocando la raya (Fabio, 20/08).
   Va en el rótulo y NO como `margin-top` del primer hijo del formulario, que
   fue lo primero que probé y no separaba nada: el `<form>` no tiene ni borde ni
   relleno, así que ese margen SE COLAPSA hacia fuera y sale del formulario en
   vez de empujar dentro de él. Medido: hueco de 0 px con `margin-top:8px`
   puesto y aplicándose. */
.formulario.persona{ padding-top:var(--e2) }
/* Los campos que comparten fila. Se reparten a partes iguales y no bajan de
   180 px: por debajo de eso un correo deja de leerse entero y más vale que la
   línea se parta sola. Fabio lo pidió el 20/08 —«nombre y correo en la misma
   línea», «papel y correo de obligaciones en la misma línea»—, que corrige lo
   que yo había puesto a una columna el día anterior. */
.formulario.persona .linea{
  display:flex; flex-wrap:wrap; align-items:flex-end; gap:var(--e4);
}
.formulario.persona .linea > .campo{ flex:1 1 180px; min-width:0 }
/* Los grupos del formulario: un rótulo con su filete y lo suyo debajo. Sustituye
   a los `<p class="grupo">` sueltos, que traían su propio borde y se veían como
   rayas sin nada que separar. */
.formulario.persona .grupo-campos{
  display:flex; flex-direction:column; gap:var(--e3);
  padding-top:var(--e3);
  border-top:var(--f-agrupa) solid var(--filete);
}
.formulario.persona .grupo-campos > .titulo-grupo{
  font-size:var(--t-micro); font-weight:var(--p-fuerte); letter-spacing:.07em;
  text-transform:uppercase; color:var(--tinta-2);
}
/* Las casillas de los módulos, apiladas y con su propio objetivo de pulsación.
   Nada de marco con desplazamiento: son tres o cuatro y caben. */
.formulario.persona .modulos{ display:flex; flex-direction:column; gap:2px }
/* En línea: son dos o tres módulos y apilados gastaban tres renglones para
   decir dos palabras. Con `wrap`, en una ventana estrecha vuelven a apilarse
   solos. */
.formulario.persona .modulos.en-linea{ flex-direction:row; flex-wrap:wrap; gap:var(--e2) }
.formulario.persona .modulos .casilla{
  align-items:center; padding:var(--e2) var(--e3);
  border:var(--f-separa) solid var(--filete); border-radius:var(--r);
  cursor:pointer;
}
.formulario.persona .modulos .casilla:hover{ background:var(--fila-hover) }
.formulario.persona .modulos .casilla input{ margin-top:0 }
/* Los botones, en su fila y del ancho de lo que dicen. `.acciones-panel` los
   estira a partes iguales —está pensado para los tres botones de la ficha de un
   cliente— y aquí eso daba un «Crear e invitar» de 1200 px. */
.formulario.persona .acciones-panel{ padding-top:var(--e2); flex-wrap:nowrap }
.formulario.persona .acciones-panel .boton{ width:auto }
.formulario.persona .acciones-panel form{ flex:0 0 auto }

/* El bloque de un módulo aparece SOLO si su casilla está marcada. Se despliega
   con la misma rejilla de 0fr → 1fr que las fichas, para que no dé un salto.

   Sin JavaScript se ve SIEMPRE, y eso es lo correcto: el bloque sigue estando
   en el formulario y se sigue pudiendo rellenar. Lo que se pierde es el
   aparecer, no la función — igual que en `.aviso-lote`. Por eso el estado de
   partida del HTML es «visible» y es `.js` quien lo esconde. */
.js .formulario.persona .grupo-modulo{
  display:grid; grid-template-rows:0fr;
  padding-top:0; border-top-width:0; gap:0;
  visibility:hidden;
  transition:grid-template-rows var(--mov-normal) var(--curva),
             padding-top var(--mov-normal) var(--curva),
             visibility 0s linear var(--mov-normal);
}
.js .formulario.persona .grupo-modulo > .dentro{ overflow:hidden; min-height:0;
                                                 display:flex; flex-direction:column; gap:var(--e3) }
.js .formulario.persona .grupo-modulo.abierta{
  grid-template-rows:1fr;
  padding-top:var(--e3); border-top-width:var(--f-agrupa);
  visibility:visible;
  transition:grid-template-rows var(--mov-normal) var(--curva),
             padding-top var(--mov-normal) var(--curva),
             visibility 0s;
}

/* ── cuadro de mando ─────────────────────────────────────────────────────── */
/* La pista mínima es 210 y no 160, y el `min(100%, …)` es lo que impide que en
   una pantalla estrecha la rejilla pida más de lo que hay (S8.1).

   Venía de S8 y se vio mirando el móvil: con 160 px de mínimo, en 375 px caben
   dos columnas de 168, y dentro de cada una la cifra —34 px, monoespaciada y con
   cifras de ancho fijo— mide 177. Resultado: «16.350,00 €» se salía de su propia
   tarjeta y arrastraba 19 px de desplazamiento horizontal a toda la página. Con
   210, en el móvil cae a una columna y la cifra entra; en el escritorio siguen
   siendo las tres de siempre. */
.kpis{ display:grid; gap:var(--e4);
       grid-template-columns:repeat(auto-fit, minmax(min(100%, 210px), 1fr)) }
.kpi{ padding:var(--e4) var(--e5) }
.kpi .grupo{ border-bottom:0; padding-bottom:var(--e2) }
.kpi .cifra{ font-size:34px; font-weight:var(--p-fuerte); letter-spacing:-.02em; line-height:1 }
.kpi.mirar-esto{ border-left:var(--f-cierra) solid var(--resalte);
                 background:var(--resalte-suave) }
.barras{ display:flex; flex-direction:column; gap:var(--e3) }
.barra-fila{ display:grid; grid-template-columns:minmax(120px,180px) minmax(0,1fr) 84px;
             gap:var(--e3); align-items:center; font-size:var(--t-apoyo) }
.barra{ display:flex; height:14px; border:var(--f-separa) solid var(--filete);
        border-radius:var(--r); overflow:hidden }
.barra i{ display:block; height:100% }
/* Los rellenos, no los tonos de TEXTO (§3.2). La barra se pintaba con `--exito`
   y `--aviso`, que están buscados para 4.5:1 porque son para leer encima del
   papel; usados como mancha salían opacos y pesados —«un color incómodo de
   mirar», dijo Fabio—. `--exito-relleno` y `--aviso-relleno` van a 3:1, que es
   el umbral de los elementos de interfaz, y existen en los dos temas: el
   generador los mide en los ocho matices y las dos luces. */
.barra .hecho{ background:var(--exito-relleno) }
.barra .falta{ background:var(--aviso-relleno) }
/* Los cuatro tramos, macizos. Un solo sitio: el mismo relleno lo usan la barra
   horizontal de las dos cargas y la columna vertical del año. */
.barra .a-tiempo,       .columna-mes .a-tiempo      { background:var(--exito-relleno) }
.barra .fuera-de-plazo, .columna-mes .fuera-de-plazo{ background:var(--error-relleno) }
.barra .pendiente,      .columna-mes .pendiente     { background:var(--aviso-relleno) }
/* Las no obligadas son la única de las cuatro que NO es una mancha de color, y
   es correcto que no lo sea: no son trabajo, son trabajo que no existe. Pero
   tampoco pueden ser el hueco vacío, que es lo que eran antes y por eso no se
   distinguían de «lo que falta por hacer». Se dicen con un rayado, que se ve sin
   competir con las tres que sí cuentan. */
/* El rayado: **fino y gris**, no un trazo macizo. La primera versión llevaba
   1px cada 4px en `--filete-fuerte`, y Fabio la cazó — «la línea gorda del patrón
   las hace destacar mucho»—. Tenía razón por partida doble:

   · era gruesa (1px cada 4 es casi un tercio de la superficie rayada), y
   · **`--filete-fuerte` en tema claro es #0B0C0F, o sea negro**: 18:1 contra la
     superficie. Es el trazo de los CONTROLES, buscado para que un campo vacío se
     vea; usado como trama pinta rayas negras.

   Y destacar es justo lo que esta categoría NO tiene que hacer: están para poder
   verlas, no para llamar la atención sobre trabajo que no existe.

   Ahora es 0,75px cada 6px en `--marcador`, que es **el único gris del sistema
   calibrado a 3:1 en los dos temas** —es el de la sugerencia de un campo vacío,
   el «visible pero callado» de la casa— y lo mide el generador en los ocho
   matices. Medido: 2,77 en claro y 2,76 en oscuro, contra los 18,07 y 3,28 de
   antes. Esa asimetría era el problema: en oscuro casi no se veía y en claro
   gritaba. */
.trama-no-obligado,
.barra .no-obligado, .columna-mes .no-obligado{
  background-color:var(--superficie);
  background-image:repeating-linear-gradient(-45deg,
      transparent 0 5.25px, var(--marcador) 5.25px 6px);
}
/* La apilada: cuatro tramos que TIENEN que caber en la barra. Los anchos salen
   de las clases de cinco en cinco, y un tramo que existe pero que redondeado da
   cero se pinta al 5 % para que no desaparezca — así que la suma puede pasarse
   de 100. `flex-shrink` los ajusta a la barra en vez de dejar que el último se
   salga; `min-width` evita que uno de 5 % se quede en nada. */
.barra.apilada{ background:var(--superficie) }
.barra.apilada i{ flex:0 1 auto; min-width:3px }
.cifra-barra{ font-family:var(--f-dato); font-size:var(--t-micro); text-align:right;
              color:var(--tinta-2) }
/* La barra del reparto anual es una sola mancha sobre su pista, no dos tramos
   pegados: ahí lo que se compara entre personas es cuánto llevan hecho de LO
   SUYO, y para eso las dos barras tienen que empezar en el mismo sitio. */
.barra.ancha{ background:var(--superficie) }
.barra.ancha .hecho{ transition:width var(--mov-normal) var(--curva) }

/* ── el año, mes a mes (§3.3) ─────────────────────────────────────────────
   Doce columnas, una por mes, y ni una línea de JavaScript: las alturas son
   clases de cinco en cinco (ver `.alto-*` más abajo). Cada mes es un enlace a
   su mes, porque el gráfico está para entrar a arreglar lo que enseña. */
/* `stretch` y no `end`: los meses que llevan la línea de «N sin presentar» miden
   15 px más, y alineando por abajo las barras de esos meses subían 15 px sobre
   las de los demás. Doce barras que no arrancan del mismo suelo no se pueden
   comparar, que es para lo único que está el gráfico. Estirados, la pila de
   110 px es lo primero de cada columna y todas empiezan en la misma raya. */
.anio-mes-a-mes{ display:grid; grid-template-columns:repeat(12, 1fr); gap:var(--e1);
                 align-items:stretch }
/* `min-width:0` NO es de adorno: un hijo de rejilla mide por defecto lo que mida
   su contenido más ancho, así que «13 sin presentar» —46 px sin partir— ensancha
   su pista de 1fr, las doce dejan de caber y la PÁGINA entera se desplaza a lo
   ancho. Medido en 375 px: el documento se iba a 569. */
.mes-del-anio{ display:flex; flex-direction:column; align-items:center; gap:var(--e1);
               min-width:0; padding:var(--e1) 2px; border-radius:var(--r);
               color:var(--tinta-2); text-decoration:none }
.mes-del-anio:hover{ background:var(--fila-hover); color:var(--tinta); text-decoration:none }
/* La pila es lo que da la altura común: sin ella cada columna mediría lo suyo y
   no habría contra qué comparar. */
.mes-del-anio .pila{ display:flex; align-items:flex-end; justify-content:center;
                     width:100%; height:110px }
/* `column-reverse` es lo que deja apilar desde ABAJO escribiendo los tramos en
   el mismo orden que en la barra horizontal (4ª tanda). Sin él habría que
   escribirlos al revés aquí para que se vieran igual, y así es como se acaba
   teniendo dos gráficos que se contradicen el día que alguien toca uno solo.
   `overflow:hidden` con `flex-shrink` en los tramos: la suma puede pasarse de
   100 por el mínimo del 5 %, y se ajustan en vez de salirse por arriba. */
.mes-del-anio .columna-mes{ display:flex; flex-direction:column-reverse;
                            width:100%; max-width:36px; min-height:2px;
                            overflow:hidden;
                            background:var(--superficie);
                            border:var(--f-separa) solid var(--filete);
                            border-radius:var(--r) var(--r) 0 0;
                            transition:height var(--mov-normal) var(--curva) }
.mes-del-anio .columna-mes i{ display:block; width:100%; flex:0 1 auto; min-height:2px;
                              transition:height var(--mov-normal) var(--curva) }
/* El tramo de arriba se come lo que sobre. Los porcentajes van de cinco en
   cinco y con un mínimo del 5 %, así que casi nunca suman 100 exacto: medido en
   enero, los cuatro daban 107 de 110 y quedaba una franja de 3 px del fondo de
   la columna asomando por arriba, que se lee como un quinto tramo que no
   existe. Creciendo el último, la columna siempre está llena. */
.mes-del-anio .columna-mes i:last-child{ flex-grow:1 }
.mes-del-anio .rotulo-mes{ font-size:var(--t-micro); font-weight:var(--p-fuerte);
                           letter-spacing:.04em; text-transform:uppercase }
.mes-del-anio .cifra-mes{ font-family:var(--f-dato); font-size:var(--t-micro);
                          color:var(--tinta-2) }
/* Lo que falta de un mes que ya pasó. Va en dos líneas y centrado porque en una
   columna de 1/12 no cabe de otra manera, y se queda: es la única señal de que
   hay que volver a un mes cerrado. */
.mes-del-anio .falta-mes{ font-size:10px; line-height:1.15; text-align:center;
                          font-weight:var(--p-fuerte); color:var(--aviso) }
/* El mes que se está mirando y el de hoy, dichos de dos maneras distintas: uno
   con el fondo y otro con un filete debajo. Con el mismo recurso para los dos no
   se sabría cuál es cuál cuando coinciden, que es casi siempre. */
.mes-del-anio.es-el-mirado{ background:var(--activo-fondo); color:var(--tinta) }
.mes-del-anio.es-el-mirado .columna-mes{ border-color:var(--activo-filete) }
.mes-del-anio.es-hoy .rotulo-mes{ box-shadow:0 2px 0 var(--acc) }

/* ── la rejilla de «qué modelos lleva cada uno» (4ª tanda) ────────────────
   Reaprovecha `.rejilla` y `.rejilla-marco` de la pantalla del mes: los dos ejes
   pegados —la cabecera arriba y la persona a la izquierda— ya están resueltos
   ahí, y resolverlos otra vez con otro nombre sería tener el mismo problema en
   dos sitios. Lo único suyo son los anchos y el tinte de la casilla.

   El tinte va con el color de MARCA y no con los cuatro del código de estado, y
   está dicho también en la pantalla: aquí no se cuenta cómo va el trabajo sino
   de qué está hecho. Casillas verdes o ámbar se leerían como presentadas o
   pendientes y dirían algo que no es. */
/* `dvh` y no `vh`: la misma lección de la rejilla del mes (S5.1) — en el móvil,
   `vh` mide contra la ventana con la barra de direcciones escondida y el
   recorte no coincide con lo que de verdad se ve. */
.reparto-modelos{ max-height:min(46dvh, 420px) }
/* La versión del TELÉFONO de este mismo reparto: una fila por persona con sus
   modelos ordenados de más a menos. En escritorio no existe —la rejilla dice
   más— y por eso nace escondida; el bloque móvil la enseña y esconde la
   rejilla. `.solo-escritorio`/`.solo-estrecho` reparten los dos párrafos que
   explican cada forma: el de la rejilla habla de casillas y tintes, y sobre
   la lista mentiría. */
.reparto-movil{ display:none }
.solo-estrecho{ display:none }
/* El aviso de «en el teléfono, solo la lista». Nace escondido porque en el
   ordenador la rejilla es la buena y ahí no hay nada que avisar; lo enseña el
   bloque del móvil, y solo cuando la pantalla llega en forma de rejilla. */
.aviso-solo-lista{ display:none; padding:var(--e4);
                   border:var(--f-separa) solid var(--filete);
                   border-left:var(--f-cierra) solid var(--resalte);
                   border-radius:var(--r); background:var(--resalte-suave) }
.aviso-solo-lista .boton{ margin-top:var(--e3) }
.persona-reparto .quien{ display:flex; align-items:baseline; gap:var(--e2); flex-wrap:wrap }
.persona-reparto .sus-modelos{ display:flex; flex-wrap:wrap; gap:4px; margin-top:4px }
.chip-modelo{ padding:1px 6px; border-radius:var(--r);
              background:var(--chip-fondo); color:var(--chip-texto);
              border:var(--f-separa) solid var(--chip-filete);
              font-family:var(--f-dato); font-size:12px; white-space:nowrap }
.chip-modelo b{ font-weight:var(--p-fuerte) }
.rejilla.modelos-persona{ --ancho-empresa: 190px }
.rejilla.modelos-persona th.columna-obligacion{ width:58px; min-width:58px; max-width:58px }
.rejilla.modelos-persona .columna-empresa{ font-weight:var(--p-normal) }
.rejilla.modelos-persona .columna-empresa .titulo{ display:block; font-weight:var(--p-fuerte);
                                                   font-size:13px;
                                                   overflow:hidden; text-overflow:ellipsis;
                                                   white-space:nowrap }
.rejilla.modelos-persona .columna-empresa .bajo{ display:block; font-size:var(--t-micro);
                                                 color:var(--tinta-2); font-weight:var(--p-normal) }
.rejilla.modelos-persona .columna-total{ position:sticky; right:0; z-index:2;
                                         width:58px; min-width:58px;
                                         padding:var(--e1) var(--e2); text-align:center;
                                         border-left:var(--f-agrupa) solid var(--filete);
                                         font-family:var(--f-dato); font-size:var(--t-micro);
                                         font-weight:var(--p-fuerte); color:var(--tinta) }
/* El fondo solo en la CABECERA. La columna de totales de las filas lleva su
   propio tinte —la escala de la rejilla, medida entre personas— y un fondo aquí
   lo taparía: `.rejilla.modelos-persona .columna-total` pesa (0,3,0) y
   `.celda-reparto.tinte-40` pesa (0,2,0), así que ganaba el gris. */
.rejilla.modelos-persona thead .columna-total{ z-index:4; background:var(--superficie) }
/* Pegada a la derecha y sin fondo propio, la columna de totales dejaría ver las
   casillas pasar por debajo al desplazar a lo ancho. El tinte la tapa cuando lo
   tiene; cuando vale cero, este papel. */
.rejilla.modelos-persona tbody .columna-total{ background:var(--papel) }
.celda-reparto{ padding:var(--e1) var(--e2); text-align:center;
                font-family:var(--f-dato); font-size:var(--t-micro); color:var(--tinta) }
.celda-reparto.sin-nada{ color:var(--marcador) }
/* Cinco escalones y no veinte: el tinte solo tiene que decir «esta pesa más que
   aquella», y para eso cinco pasos se distinguen y veinte no. El número exacto
   va escrito dentro de la casilla, que es de donde se lee el dato. */
.rejilla.modelos-persona tbody .columna-total.tinte-0,
.rejilla.modelos-persona tbody .columna-total.tinte-5,
.rejilla.modelos-persona tbody .columna-total.tinte-10,
.rejilla.modelos-persona tbody .columna-total.tinte-15{ background:color-mix(in srgb, var(--acc) 5%, var(--papel)) }
.rejilla.modelos-persona tbody .columna-total.tinte-20,
.rejilla.modelos-persona tbody .columna-total.tinte-25,
.rejilla.modelos-persona tbody .columna-total.tinte-30,
.rejilla.modelos-persona tbody .columna-total.tinte-35{ background:color-mix(in srgb, var(--acc) 10%, var(--papel)) }
.rejilla.modelos-persona tbody .columna-total.tinte-40,
.rejilla.modelos-persona tbody .columna-total.tinte-45,
.rejilla.modelos-persona tbody .columna-total.tinte-50,
.rejilla.modelos-persona tbody .columna-total.tinte-55{ background:color-mix(in srgb, var(--acc) 16%, var(--papel)) }
.rejilla.modelos-persona tbody .columna-total.tinte-60,
.rejilla.modelos-persona tbody .columna-total.tinte-65,
.rejilla.modelos-persona tbody .columna-total.tinte-70,
.rejilla.modelos-persona tbody .columna-total.tinte-75{ background:color-mix(in srgb, var(--acc) 24%, var(--papel)) }
.rejilla.modelos-persona tbody .columna-total.tinte-80,
.rejilla.modelos-persona tbody .columna-total.tinte-85,
.rejilla.modelos-persona tbody .columna-total.tinte-90,
.rejilla.modelos-persona tbody .columna-total.tinte-95,
.rejilla.modelos-persona tbody .columna-total.tinte-100{ background:color-mix(in srgb, var(--acc) 34%, var(--papel)) }

.celda-reparto.tinte-0,  .celda-reparto.tinte-5,  .celda-reparto.tinte-10,
.celda-reparto.tinte-15{ background:color-mix(in srgb, var(--acc) 5%, var(--papel)) }
.celda-reparto.tinte-20, .celda-reparto.tinte-25, .celda-reparto.tinte-30,
.celda-reparto.tinte-35{ background:color-mix(in srgb, var(--acc) 10%, var(--papel)) }
.celda-reparto.tinte-40, .celda-reparto.tinte-45, .celda-reparto.tinte-50,
.celda-reparto.tinte-55{ background:color-mix(in srgb, var(--acc) 16%, var(--papel)) }
.celda-reparto.tinte-60, .celda-reparto.tinte-65, .celda-reparto.tinte-70,
.celda-reparto.tinte-75{ background:color-mix(in srgb, var(--acc) 24%, var(--papel)) }
.celda-reparto.tinte-80, .celda-reparto.tinte-85, .celda-reparto.tinte-90,
.celda-reparto.tinte-95, .celda-reparto.tinte-100{
  background:color-mix(in srgb, var(--acc) 34%, var(--papel));
  font-weight:var(--p-fuerte);
}

/* ── alturas y anchos de cinco en cinco ───────────────────────────────────
   La CSP prohíbe los estilos en línea, así que una barra no puede llevar su
   `style="height:73%"`. La otra salida es que se lo ponga el guion —lo hace la
   carga por responsable, que es de antes—, y entonces sin JavaScript no hay
   gráfico. Esto es la tercera: veintiuna clases escritas una vez. En una barra
   de 110 px, un paso de 5 % son 5,5 px; y el número exacto va siempre escrito
   al lado, que es de donde se lee el dato de verdad. */
.alto-0{ height:0 }       .ancho-0{ width:0 }
.alto-5{ height:5% }      .ancho-5{ width:5% }
.alto-10{ height:10% }    .ancho-10{ width:10% }
.alto-15{ height:15% }    .ancho-15{ width:15% }
.alto-20{ height:20% }    .ancho-20{ width:20% }
.alto-25{ height:25% }    .ancho-25{ width:25% }
.alto-30{ height:30% }    .ancho-30{ width:30% }
.alto-35{ height:35% }    .ancho-35{ width:35% }
.alto-40{ height:40% }    .ancho-40{ width:40% }
.alto-45{ height:45% }    .ancho-45{ width:45% }
.alto-50{ height:50% }    .ancho-50{ width:50% }
.alto-55{ height:55% }    .ancho-55{ width:55% }
.alto-60{ height:60% }    .ancho-60{ width:60% }
.alto-65{ height:65% }    .ancho-65{ width:65% }
.alto-70{ height:70% }    .ancho-70{ width:70% }
.alto-75{ height:75% }    .ancho-75{ width:75% }
.alto-80{ height:80% }    .ancho-80{ width:80% }
.alto-85{ height:85% }    .ancho-85{ width:85% }
.alto-90{ height:90% }    .ancho-90{ width:90% }
.alto-95{ height:95% }    .ancho-95{ width:95% }
.alto-100{ height:100% }  .ancho-100{ width:100% }

/* ═══════════════════════════════════════════════════════════════════════════
   S8 · APLICACIONES, MANUALES Y FACTURAS
   Sale entero de diseno/wireframes-s8.html, con las decisiones de Fabio del
   21/08 ya dentro. Ni un color ni una medida a mano: todo por var().
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── anchos de las tablas nuevas ──────────────────────────────────────────
   Todas juntas, como las de arriba: separadas, se desalinean la primera vez que
   alguien toque una sola. */
.tabla.apps-cliente   { --cols: minmax(210px,2.4fr) minmax(150px,1.4fr) minmax(130px,1.1fr) 116px 92px }
/* Ocho columnas desde S8.1: se fue «Vence» y entraron base, IVA y total. Las
   tres de dinero miden lo mismo para que se puedan comparar de un vistazo. */
.tabla.facturas-cli   { --cols: 100px 92px minmax(160px,1.8fr) 100px 92px 108px 100px 48px }
/* Ocho columnas desde S8.1 (2ª vuelta): base, IVA y total separados, como en la
   lista del cliente. Las tres de dinero miden lo mismo para poder compararlas. */
.tabla.facturas-panel { --cols: 96px minmax(130px,1.2fr) minmax(150px,1.5fr) 96px 88px 104px 100px 84px }
.tabla.manuales-app   { --cols: minmax(200px,2.4fr) 80px 112px minmax(110px,1fr) 84px }
.tabla.enlaces-app    { --cols: minmax(180px,1.6fr) minmax(220px,2.2fr) 84px }
/* «Mantenimiento o servicio» no cabe en 118 px: en S8 la etiqueta se salía por
   encima de la columna de al lado y se leía «Mantenimiento o servicioSolo
   CAFyC». La columna crece y las etiquetas envuelven dentro de ella. */
.tabla.catalogo-apps  { --cols: 44px minmax(200px,2.2fr) minmax(140px,1.2fr) minmax(130px,1.2fr) 84px 84px }
.tabla.recurrencias   { --cols: minmax(190px,2fr) minmax(130px,1.2fr) 104px 116px 128px 84px }

/* ── la rejilla de tarjetas de aplicación (portal) ────────────────────────
   `auto-fill` y no `auto-fit`: con una sola aplicación, `auto-fit` estiraría esa
   tarjeta a lo ancho de la pantalla.

   `grid-auto-rows:1fr` es lo que hace que la tarjeta que se queda sola en la
   última fila mida lo mismo que las de arriba. Es la mitad de «bien
   armonizada», que fue la condición que puso Fabio el 21/08 al elegir esta
   forma; la otra mitad son las alturas mínimas de más abajo. */
.rejilla-apps{ display:grid; gap:var(--e4); grid-auto-rows:1fr;
               grid-template-columns:repeat(auto-fill, minmax(300px,1fr)) }
.tarjeta-app{ display:flex; flex-direction:column; gap:var(--e3); padding:var(--e5) }
.tarjeta-app > .cabeza{ display:flex; align-items:flex-start; gap:var(--e3) }
.tarjeta-app .cabeza > .texto{ min-width:0; flex:1 1 auto }
.tarjeta-app .icono{ width:36px; height:36px; flex:none; border-radius:var(--r);
                     display:grid; place-items:center;
                     background:var(--chip-fondo); color:var(--chip-texto);
                     border:var(--f-separa) solid var(--chip-filete) }
.tarjeta-app .icono svg{ width:18px; height:18px; stroke:currentColor; stroke-width:1.7;
                         fill:none; stroke-linecap:round; stroke-linejoin:round }
.tarjeta-app h3{ font-size:15px; font-weight:var(--p-fuerte); letter-spacing:-.01em }
/* La línea de «dónde vive», con su marca delante: la flecha que sale del cuadro
   para lo que se abre fuera y el cuadrado de SmartDesk para lo de aquí dentro.
   Va ANTES del texto porque la marca se mira primero. */
.tarjeta-app .donde{ font-size:var(--t-micro); color:var(--tinta-2); font-family:var(--f-dato);
                     display:flex; align-items:center; gap:5px; min-width:0 }
.tarjeta-app .donde span{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.tarjeta-app .donde svg{ flex:none; width:12px; height:12px; stroke:currentColor;
                         stroke-width:1.9; fill:none; stroke-linecap:round; stroke-linejoin:round }
/* Dos líneas reservadas aunque la descripción ocupe una: sin esto, la línea de
   recuentos de cada tarjeta queda a una altura distinta y la rejilla deja de
   leerse por columnas. */
.tarjeta-app .que-hace{ font-size:var(--t-apoyo); color:var(--tinta-2); flex:1 1 auto;
                        min-height:36px }

/* ── por qué estas dos filas tienen alto FIJO y no envuelven (S8.1) ────────
   «Todas las tarjetas iguales de verdad», que fue el encargo. En S8 los
   recuentos y el mantenimiento compartían una sola fila que envolvía: la
   tarjeta que tenía cobertura se comía dos líneas y la que no, una, así que los
   botones de abajo quedaban a alturas distintas y la rejilla dejaba de leerse
   por columnas. Ahora son dos filas separadas, cada una de UNA línea y con su
   alto puesto:

   · `.cuentas`   — manuales y enlaces, siempre los dos, siempre en una línea.
   · `.cobertura` — el mantenimiento, y cuando no hay se escribe «Sin
     mantenimiento» en vez de dejar el hueco. El hueco vacío también mide, pero
     una tarjeta con un blanco donde otra tiene un dato parece rota. */
.tarjeta-app .cuentas,
.tarjeta-app .cobertura{ display:flex; flex-wrap:nowrap; gap:var(--e3);
                         align-items:center; min-width:0;
                         font-size:var(--t-micro); color:var(--tinta-2) }
.tarjeta-app .cuentas{ height:34px; padding-top:var(--e3);
                       border-top:var(--f-separa) solid var(--filete) }
.tarjeta-app .cobertura{ height:22px }
.tarjeta-app .cobertura > *{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap }
.tarjeta-app .cuentas b{ font-family:var(--f-dato); color:var(--tinta); font-weight:var(--p-fuerte) }

/* Dos columnas iguales y `nowrap` en el texto: en S8 los botones eran
   `flex:1 1 auto` y «Abrir SmartAudit» no cabía, así que esa tarjeta —y solo
   esa— pasaba a dos filas de botón a todo lo ancho. La rejilla se rompía por un
   nombre largo. Ahora el reparto no depende del texto. */
.tarjeta-app .acciones{ display:grid; grid-template-columns:1fr 1fr; gap:var(--e2) }
.tarjeta-app .acciones .boton{ justify-content:center; min-width:0;
                               white-space:nowrap; overflow:hidden }

/* ── el camino del pago: 70 % · 30 % · mantenimiento ──────────────────────
   La pieza del sprint. Un cliente no pregunta «cuántas facturas tengo»:
   pregunta «por dónde va esto y qué me queda por pagar».

   El paso entero NO se pinta de color: en Rejilla Suiza el color es tinta, no
   mancha. Lo que dice el estado es la pastilla; el paso en el que estamos lleva
   el filete de cierre y el fondo de resalte, que es el mismo recurso que ya usa
   `.kpi.mirar-esto`. */
.camino{ display:flex; flex-wrap:wrap;
         border:var(--f-separa) solid var(--filete); border-radius:var(--r);
         background:var(--papel) }
.camino .paso{ flex:1 1 190px; min-width:0; padding:var(--e3) var(--e4);
               border-right:var(--f-separa) solid var(--filete);
               border-left:var(--f-cierra) solid transparent;
               display:flex; flex-direction:column; gap:6px }
.camino .paso:last-child{ border-right:0 }
.camino .paso.ahora{ border-left-color:var(--resalte); background:var(--resalte-suave) }
.camino .paso .que{ font-size:var(--t-micro); font-weight:var(--p-fuerte);
                    letter-spacing:.07em; text-transform:uppercase; color:var(--tinta-2) }
.camino .paso .cuanto{ font-family:var(--f-dato); font-size:19px; font-weight:var(--p-fuerte);
                       letter-spacing:-.01em }
.camino .paso .quien{ font-size:var(--t-micro); color:var(--tinta-2) }
.camino .paso.previsto .cuanto{ color:var(--tinta-2) }

/* ── el bloque de UNA aplicación en el panel (S8.1) ───────────────────────
   Dos encargos de Fabio en uno, y los dos salieron de mirar la pantalla:

   1. «Falta margen a la izquierda del contenido.» No era de esta pantalla ni
      del armazón: el relleno venía de un `style="padding:var(--e5)"` en el HTML
      y **la CSP se lo come**. `style-src 'self'` no lleva `'unsafe-inline'`, así
      que el navegador deja el atributo puesto y no aplica ni una declaración
      (medido: `style.length === 0`, `padding-left` computado 0). En SmartDesk el
      atributo `style` NO EXISTE; el relleno tiene que ser una clase, y esta lo
      es. Ver la trampa nº 32 de CLAUDE.md.

   2. «Cuatro bloques iguales seguidos y cuesta ver dónde acaba uno.» El color
      entra por donde ya lo tiene permitido la Rejilla Suiza —el filete de
      cierre y el icono—, no como mancha: 3px de acento a la izquierda del
      bloque entero (que es lo que la gramática de la casa llama «cierra
      bloque») y la cabecera sobre superficie, separada con el filete de agrupar.
      Ni una sombra, ni un fondo de color. */
.bloque-app{ padding:0; overflow:hidden;
             border-left:var(--f-cierra) solid var(--acc) }
.bloque-app > .cabeza-app{ background:var(--superficie);
                           border-bottom:var(--f-agrupa) solid var(--filete) }
.bloque-app > .cabeza-app .icono{ background:var(--activo-fondo); color:var(--activo-texto);
                                  border-color:var(--activo-filete) }
/* Todo lo que va debajo de la cabecera comparte el mismo margen. Es una regla y
   no un relleno en el bloque porque la cabecera va a sangre: si el relleno lo
   llevara el bloque, la cabecera no podría llegar a los bordes y el filete de
   agrupar se quedaría flotando con un hueco a cada lado. */
.bloque-app > :not(.cabeza-app){ margin-left:var(--e5); margin-right:var(--e5) }
.bloque-app > :last-child{ margin-bottom:var(--e5) }
/* Una aplicación de baja o en pausa no se pinta con el acento: el filete de
   cierre dice «esta está viva», y ponérselo a todas lo vacía de significado. */
.bloque-app.dormida{ border-left-color:var(--filete-fuerte) }
.bloque-app.dormida > .cabeza-app .icono{ background:var(--chip-fondo);
                                          color:var(--chip-texto);
                                          border-color:var(--chip-filete) }

/* ── la cabecera de la ficha de una aplicación ───────────────────────────── */
.cabeza-app{ display:flex; align-items:flex-start; gap:var(--e4); flex-wrap:wrap;
             padding:var(--e5) }
.cabeza-app .icono{ width:44px; height:44px; flex:none; border-radius:var(--r);
                    display:grid; place-items:center;
                    background:var(--chip-fondo); color:var(--chip-texto);
                    border:var(--f-separa) solid var(--chip-filete) }
.cabeza-app .icono svg{ width:22px; height:22px; stroke:currentColor; stroke-width:1.7;
                        fill:none; stroke-linecap:round; stroke-linejoin:round }
.cabeza-app .texto{ flex:1 1 320px; min-width:0; display:flex; flex-direction:column; gap:6px }
.cabeza-app h2{ font-size:22px; font-weight:var(--p-fuerte); letter-spacing:-.015em }
.cabeza-app .bajo{ font-size:var(--t-apoyo); color:var(--tinta-2) }
.cabeza-app .acciones{ display:flex; gap:var(--e2); align-items:center; flex-wrap:wrap }

/* ── elegir el dibujo de una aplicación (S8.1) ─────────────────────────────
   Era un `<select>` con ocho nombres escritos —«obligaciones», «facturacion»—,
   y elegir un DIBUJO leyendo una palabra es adivinar. Ahora es una rejilla de
   radios que enseña el dibujo; el radio de verdad sigue debajo, invisible pero
   presente, así que funciona con el teclado y sin JavaScript. */
.rejilla-iconos{ display:grid; gap:var(--e2);
                 grid-template-columns:repeat(auto-fill, minmax(78px,1fr)) }
.rejilla-iconos label{ display:flex; flex-direction:column; align-items:center;
                       gap:4px; padding:var(--e2) 4px; cursor:pointer;
                       border:var(--f-separa) solid var(--filete);
                       border-radius:var(--r); background:var(--papel);
                       font-size:var(--t-micro); color:var(--tinta-2);
                       text-align:center; min-width:0 }
.rejilla-iconos label span{ max-width:100%; overflow:hidden;
                            text-overflow:ellipsis; white-space:nowrap }
.rejilla-iconos label svg{ width:22px; height:22px; color:var(--tinta) }
.rejilla-iconos label:hover{ background:var(--fila-hover) }
.rejilla-iconos input{ position:absolute; width:1px; height:1px; opacity:0 }
.rejilla-iconos input:checked + svg,
.rejilla-iconos input:checked ~ span{ color:var(--activo-texto) }
.rejilla-iconos label:has(input:checked){ background:var(--activo-fondo);
                                          border-color:var(--activo-filete);
                                          border-left-width:var(--f-cierra) }
.rejilla-iconos label:has(input:focus-visible){ outline:var(--f-agrupa) solid var(--foco);
                                                outline-offset:2px }
/* ── el logo mide LO MISMO que el dibujo al que sustituye ──────────────────
   Un logo y un icono son la misma cosa en la pantalla: el dibujo de una
   aplicación. Si el logo mide 36 y el icono 16, la fila del catálogo baila y se
   nota a la primera —lo cazó Fabio con la captura—.

   Así que el tamaño NO lo trae el logo: lo hereda del sitio donde está, igual
   que el `<svg>`. `1em` con el `font-size` del contenedor puesto por su regla
   (`.tabla .celda`, `.tarjeta-app .icono`…) hace que los dos midan lo mismo sin
   tener que repetir la medida en dos sitios y acordarse de las dos. */
.logo-app{ width:16px; height:16px; object-fit:contain; flex:none;
           border-radius:2px; background:transparent }
/* Y donde el icono es grande, el logo también: se escriben juntos para que no
   se puedan separar. */
.tarjeta-app .icono .logo-app{ width:18px; height:18px }
.cabeza-app .icono .logo-app{ width:22px; height:22px }
/* En el formulario del catálogo sí se enseña grande, porque ahí el logo ES el
   asunto: se está mirando cuál se ha subido. */
.zona-fichero .logo-app{ width:32px; height:32px; border-radius:var(--r);
                         border:var(--f-separa) solid var(--filete) }

/* ── la liquidación del mantenimiento al cancelar (S8.1) ───────────────────
   No es un aviso ni un total: es una CUENTA, y se enseña entera —periodo, días
   usados, días que sobran y el importe— porque el número solo no se puede
   comprobar y esto acaba en una factura de verdad. */
.liquidacion{ display:flex; flex-wrap:wrap; gap:var(--e4); align-items:baseline;
              padding:var(--e3) var(--e4); border-radius:var(--r);
              border:var(--f-separa) solid var(--filete);
              border-left:var(--f-cierra) solid var(--resalte);
              background:var(--resalte-suave); font-size:var(--t-apoyo) }
.liquidacion .cuenta{ color:var(--tinta-2); font-family:var(--f-dato);
                      font-size:var(--t-micro) }
.liquidacion .cifra{ font-family:var(--f-dato); font-weight:var(--p-fuerte);
                     font-size:19px; letter-spacing:-.01em }

/* ── rótulo de sección dentro de una ficha ───────────────────────────────── */
.rotulo-seccion{ display:flex; align-items:center; gap:var(--e3); flex-wrap:wrap;
                 padding-bottom:var(--e2); border-bottom:var(--f-agrupa) solid var(--tinta) }
.rotulo-seccion h3{ font-size:var(--t-micro); font-weight:var(--p-fuerte);
                    letter-spacing:.07em; text-transform:uppercase; color:var(--tinta-2) }
.rotulo-seccion .cuantos{ font-size:var(--t-micro); color:var(--tinta-2);
                          font-family:var(--f-dato) }
.rotulo-seccion .a-la-derecha{ margin-left:auto; display:flex; gap:var(--e2) }
/* Una sección de la ficha: rótulo, contenido y aire entre los dos. Se repite en
   Manuales, Accesos y Facturas, así que se escribe una vez. */
.seccion-ficha{ padding:var(--e5); display:flex; flex-direction:column; gap:var(--e3) }

/* Las tres tarjetas del Inicio, que desde S8 son enlaces de verdad. Un enlace
   que ocupa una tarjeta entera no puede pintarse como un enlace de texto: sería
   una tarjeta azul y subrayada. Se comporta como una fila de lista — se ilumina
   al pasar por encima — que es lo que ya enseña que algo se pulsa. */
a.mini{ color:var(--tinta); text-decoration:none; display:block }
a.mini:hover{ background:var(--fila-hover); text-decoration:none }
a.mini:hover h3{ text-decoration:underline; text-underline-offset:3px }

/* ── «añadir algo», que es un <details> con pinta de botón ────────────────
   <details> y no un div con JavaScript, por lo mismo que el menú de tres
   puntos: abre y cierra él solo, con teclado, aunque el guion no cargue. Lo
   único que hay que hacer es quitarle el triangulito, que en un botón sobra. */
details.anadir{ display:flex; flex-direction:column; gap:var(--e3) }
details.anadir > summary{ list-style:none; cursor:pointer; align-self:flex-start }
details.anadir > summary::-webkit-details-marker{ display:none }
details.anadir > summary::marker{ content:'' }
details.anadir[open] > summary{ border-color:var(--filete-fuerte); color:var(--tinta) }

/* ── el formulario de subida del panel ───────────────────────────────────── */
.caja-subir{ padding:var(--e4) var(--e5); background:var(--superficie);
             border:var(--f-separa) solid var(--filete); border-radius:var(--r);
             display:flex; flex-direction:column; gap:var(--e3) }
.caja-subir .linea{ display:flex; gap:var(--e3); flex-wrap:wrap; align-items:flex-end }
.caja-subir .linea > .campo{ flex:1 1 150px; min-width:0 }
.caja-subir .linea > .campo.corto{ flex:0 1 130px }
.caja-subir .linea > .campo.ancho{ flex:2 1 260px }
.caja-subir .linea > .a-la-derecha{ margin-left:auto; display:flex; gap:var(--e2) }

/* ── el campo de subir un fichero (rehecho en S8.1) ───────────────────────
   Antes ocupaba media pantalla y encima insinuaba un arrastrar-y-soltar que no
   existía: dos fallos que ninguna comprobación automática ve y que saltan a la
   vista en la primera captura. Ahora:

   · Es UNA FILA, del alto de un campo normal. Nada de una caja de 40 px de
     relleno con un dibujo enorme dentro.
   · El filete es continuo, no discontinuo. El discontinuo es la señal universal
     de «suéltalo aquí», y prometerla en reposo es prometer algo que no pasa.
     Solo aparece —y solo mientras dura— cuando de verdad hay un fichero encima,
     con `.soltando`, que pone el guion. Y ahora sí funciona: `guiones.php` coge
     lo que se suelta y se lo mete al `<input type="file">`. */
.zona-fichero{ display:flex; align-items:center; gap:var(--e3); flex-wrap:wrap;
               padding:var(--e2) var(--e3);
               border:var(--f-separa) solid var(--filete);
               border-radius:var(--r); background:var(--papel);
               font-size:var(--t-apoyo); color:var(--tinta-2) }
.zona-fichero > label{ flex:none; font-weight:var(--p-fuerte); color:var(--tinta);
                       font-size:var(--t-apoyo) }
/* El `width:100%` NO es redundante con el `flex`, y sin él la pantalla se sale
   por la derecha en el móvil: un `<input type="file">` de Chrome trae su propio
   ancho mínimo —el botón «Seleccionar archivo» más «Ningún archivo
   seleccionado»— y ese mínimo **no lo baja `min-width:0`**, porque no es un
   mínimo de flex sino el tamaño intrínseco del control. Medido en 375 px: la
   zona pedía 305 px de mínimo y el documento se iba a 401. Con un ancho en
   porcentaje, el mínimo se calcula contra el contenedor y baja a 60. */
.zona-fichero input[type="file"]{ font:inherit; font-size:var(--t-apoyo);
                                  color:var(--tinta);
                                  flex:1 1 200px; width:100%;
                                  min-width:0; max-width:320px }
.zona-fichero.soltando{ border:var(--f-agrupa) dashed var(--acc);
                        background:var(--resalte-suave); color:var(--tinta) }
/* Un campo pequeño puede compartir la fila con el de subir —la versión del
   fichero va pegada al fichero, no tres líneas más abajo—, y ahí sí manda la
   etiqueta de arriba, no la de al lado. */
.zona-fichero .campo{ flex:0 1 150px; margin-left:auto }
.zona-fichero .campo label{ font-weight:var(--p-normal); color:var(--tinta-2) }

/* Un dato que se ENSEÑA donde iría un campo, porque no se edita: «Aquí dentro,
   en SmartDesk» en el sitio del enlace de un módulo. Mide lo mismo que un
   `<input>` para que la fila siga cuadrando. */
.valor-fijo{ display:flex; align-items:center; gap:var(--e2); min-height:38px;
             font-size:var(--t-apoyo); color:var(--tinta-2) }

/* ── dinero ──────────────────────────────────────────────────────────────
   Monoespaciada y con cifras de ancho fijo: una columna de importes que no está
   alineada por la coma no se puede sumar de un vistazo, y sumar de un vistazo
   es todo lo que se hace con ella. */
.dinero{ font-family:var(--f-dato); font-weight:var(--p-fuerte);
         font-variant-numeric:tabular-nums }
.tabla .celda.dinero{ justify-self:end; text-align:right }

/* ── S8 en el móvil ──────────────────────────────────────────────────────
   Va en su propio bloque y no dentro del @media grande de abajo: así lo de este
   sprint se lee junto. Lo que hace falta es poco, porque las tablas de tarjetas
   ya se apilan solas con la regla general y las tarjetas de aplicación son una
   rejilla que se queda en una columna.

   Lo único que hay que deshacer es la alineación a la derecha del dinero:
   apilada, una cifra pegada al borde derecho queda lejísimos de su rótulo. */
@media (max-width: 900px){
  .tabla .celda.dinero{ justify-self:start; text-align:left }
  .camino .paso{ flex:1 1 100%; border-right:0;
                 border-bottom:var(--f-separa) solid var(--filete) }
  .camino .paso:last-child{ border-bottom:0 }
  .caja-subir .linea > .a-la-derecha{ margin-left:0; width:100%; flex-wrap:wrap }
  .caja-subir .linea > .a-la-derecha .boton{ flex:1 1 auto; justify-content:center }
}

/* ── móvil ───────────────────────────────────────────────────────────────
   Corte en 900px. La sidebar NO desaparece: se convierte en menú superior
   desplegable. Ocultarla sin sustituto dejaría el sitio sin navegación, que es
   exactamente lo que no puede pasar. */
@media (max-width: 900px){
  /* Aquí se invierte la regla del armazón: la barra deja de ser una columna
     fija y pasa a ser el menú de arriba, así que la página vuelve a
     desplazarse entera. Un dedo espera eso; dos zonas de desplazamiento
     independientes en una pantalla de 375 px son una trampa. */
  .marco{ grid-template-columns:1fr; gap:var(--e3); padding:var(--e3);
          height:auto; min-height:100dvh }
  /* Una sola pista: las dos piezas se apilan en ella, una debajo de la otra. */
  .marco > .lateral, .marco > .columna{ grid-column:1 }

  /* ── la pantalla fija NO existe en el móvil ─────────────────────────────
     Aquí manda la regla del sistema de diseño: en el teléfono la página vuelve
     a desplazarse entera, que es lo que espera un dedo. Encajar una tabla en
     una ventana de 640 px de alto deja seis filas y dos barras que pelean.

     Y hay que desactivarla ENTERA y con la misma fuerza, no con `.columna` a
     secas: `.columna` pesa (0,1,0) y `.columna.fija` pesa (0,2,0), así que la
     regla corta PIERDE y el móvil se quedaba con `overflow:hidden` — la
     pantalla recortada y sin barra por la que bajar. Lo cazó un repaso, no la
     vista: en el navegador parecía que iba bien porque la tabla cabía. */
  .columna,
  .columna.fija{ overflow:visible }
  .columna.fija .contenido{ flex:1 0 auto; min-height:auto; overflow:visible;
                            gap:var(--e3) }
  .columna.fija .contenido > .crece,
  .columna.fija .lista-crece{ flex:1 0 auto; min-height:auto }
  .columna.fija .lista-marco,
  .columna.fija .contenido > .crece.desborda{ flex:1 0 auto; min-height:auto;
                                              overflow:visible }
  /* La rejilla NO va con `overflow:visible` como sus hermanos: soltarle los
     dos ejes hacía que sus 24 columnas (1.072 px medidos) ensancharan el
     DOCUMENTO y la página entera se fuera de lado — «el scroll está
     bugueado» del teléfono. El eje que el móvil libera es el VERTICAL (la
     página desplaza); el horizontal se queda dentro, como en `.matriz`. Al
     no tener tope de alto, el marco crece con la tabla y no atrapa el gesto
     vertical. */
  .columna.fija .rejilla-marco{ flex:1 0 auto; min-height:auto;
                                max-height:none; overflow-x:auto }
  .columna.fija .pie{ padding:var(--e5) var(--e2) 0 }

  /* ── el panel de alta en el móvil: que la página se desplace (20/08) ────
     En escritorio el panel tiene barra propia y `overscroll-behavior:contain`,
     que impide que al llegar a su final el gesto siga arrastrando la página de
     detrás. Eso está bien en un panel con tope de alto.

     En el móvil no hay tope: la pantalla deja de ser fija y quien se desplaza
     es la página entera. Y ahí ese `contain` era una trampa — el `.dentro`
     seguía siendo un contenedor con `overflow:auto` cuyo contenido cabía
     JUSTO, así que no tenía nada que desplazar… y aun así se quedaba con el
     gesto sin pasárselo a nadie. Medido: formulario de 679 px dentro de un
     hueco de 679, el botón «Cancelar» a 1090 en una ventana de 812, y el dedo
     sobre el formulario sin mover nada. La pantalla parecía bloqueada.

     Aquí el panel no desplaza nada: desborda y lo desplaza la página. */
  .columna.fija .desplegable.alta.abierta > .dentro{ overflow:visible; overscroll-behavior:auto }
  .columna.fija .contenido > .desplegable.alta{ flex:1 0 auto; min-height:auto }
  .columna.fija .contenido:has(> .desplegable.alta.abierta) > .crece.desborda{
    flex:1 0 auto; min-height:auto;
  }
  /* Y la nota al pie de la tabla vuelve: en escritorio se esconde para dejarle
     sitio al panel, pero aquí no compiten — van uno detrás del otro. */
  .columna.fija .contenido:has(> .desplegable.alta.abierta) > p.apagado{ display:block }

  /* ── la cabecera del móvil (S5.1 §1.6) ────────────────────────────────
     Más fina, pegada arriba, y se esconde al bajar y vuelve al subir. Lo de
     esconderse no es un adorno: en 375 px, una cabecera fija de 60 px se come
     una fila y media de la lista del mes, y la lista del mes es para lo que se
     abre el teléfono.

     `transform` y no `top`: mover con transform lo hace el compositor y no
     obliga al navegador a recalcular la posición de todo lo de debajo en cada
     fotograma del desplazamiento. La clase `.escondida` la pone el guion. */
  .lateral{
    overflow:visible; padding:var(--e2) var(--e3);
    position:sticky; top:0; z-index:40;
    transition:transform var(--mov-normal) var(--curva);
  }
  .lateral.escondida{ transform:translateY(calc(-100% - var(--e3))) }
  /* Con el menú abierto no se esconde nunca: se iría de la pantalla justo
     mientras alguien lo está usando. Y si abierto mide más que la pantalla
     (apaisado, teléfonos bajos), se desplaza ÉL: está pegado con sticky, así
     que lo que asome por debajo del borde no se alcanza de ninguna otra
     forma. */
  .lateral.abierta{ transform:none; max-height:100dvh; overflow-y:auto }
  .lateral .marca{ display:flex; align-items:center; padding-bottom:0 }
  .abrir-menu{
    display:inline-flex; align-items:center; justify-content:center;
    margin-left:auto; width:44px; height:44px;      /* objetivo táctil */
    border:var(--f-separa) solid var(--filete-fuerte); border-radius:var(--r);
    background:transparent; color:var(--tinta); cursor:pointer;
  }
  .abrir-menu svg{ width:20px; height:20px; stroke:currentColor; stroke-width:1.7; fill:none }

  /* ── el menú de móvil se abre con transición (S5.1 §1.4) ──────────────
     El mismo mecanismo que la ficha desplegable: una rejilla de una fila que va
     de 0fr a 1fr. Se anima hasta la altura real del menú sin inventarse un
     `max-height`, que es el número que siempre se queda corto el día que entra
     una sección nueva.

     Aquí sí se materializa el envoltorio que en escritorio era `display:contents`
     (ver lateral.php). */
  .plegable-movil{
    display:grid;
    transition:grid-template-rows var(--mov-normal) var(--curva),
               visibility 0s linear var(--mov-normal);
  }
  /* El cierre, SOLO si hay guion que pueda abrirlo. Sin JavaScript no corre
     el manejador de la hamburguesa, y con el 0fr sin esta guarda el teléfono
     se quedaba sin ninguna navegación: menú cerrado y nada que lo abra.
     `.js` la pone el guion de cabecera.php antes de cargar este CSS. */
  .js .plegable-movil{ grid-template-rows:0fr; visibility:hidden }
  .plegable-movil > .dentro{
    display:flex; flex-direction:column; gap:var(--e3);
    overflow:hidden; min-height:0;
  }
  .lateral.abierta .plegable-movil{
    grid-template-rows:1fr; visibility:visible;
    transition:grid-template-rows var(--mov-normal) var(--curva), visibility 0s;
  }
  .lateral nav{ margin-top:var(--e3) }
  /* `>` por lo mismo que arriba: sin él, los 44 px del objetivo táctil se los
     llevaba TAMBIÉN el texto de dentro, y cada entrada del menú del teléfono
     medía 60 px en vez de 44. Cuatro entradas, 64 px de más. */
  /* Salir y tu nombre entran en la misma cuenta: son dos cosas que se pulsan
     con el dedo, y se quedaban en 36 px porque no cuelgan de un `nav`. */
  .lateral nav > a, .lateral nav > span,
  .lateral .yo, .lateral .salir button{ min-height:44px }
  .segmentos.ancho label{ min-height:44px }
  /* El menú plegado es cosa del escritorio: en el móvil la barra ya es un menú
     desplegable de arriba y no hay columna que encoger. */
  [data-menu="plegado"] .marco{ grid-template-columns:1fr }
  [data-menu="plegado"] .lateral{ position:sticky; left:auto; top:0; bottom:auto; width:auto }
  [data-menu="plegado"] .texto-menu,
  [data-menu="plegado"] .marca-larga,
  [data-menu="plegado"] .yo-texto,
  [data-menu="plegado"] .control-tema > .grupo{ opacity:1 }
  /* Y el conmutador de tema entero, no solo el elegido: la regla que deja UN
     icono es del escritorio, pero está escrita fuera de su `@media` (va con el
     estado del menú, no con el ancho). En el teléfono la barra plegada no
     existe —es un menú desplegable de arriba—, así que dejar ahí una sola
     opción esconde las otras dos sin que nada las devuelva. */
  [data-menu="plegado"] .segmentos label{ display:flex }
  [data-menu="plegado"] .marca-corta{ display:none }
  [data-menu="plegado"] .marca-larga{ position:static }
  .chincheta{ display:none }

  .fila-mini{ grid-template-columns:1fr }
  .heroe{ padding:var(--e6) var(--e5) }
  .heroe .cifra{ font-size:44px }
  .tarjeta{ padding:var(--e4) var(--e5) }
  .filtros .campo{ flex:1 1 100% }
  /* …salvo la barra que lo pida (S11 · 7.3). Fabio, para el móvil: «condensa al
     máximo» y «mete el mayor número de elementos posible en la misma línea,
     para no tener que hacer scroll». En Pedidos la barra de filtros se llevaba
     298 px —casi la pantalla y media que hay hasta el primer pedido— por poner
     tres campos de uno en uno, y el propio `.filtros` de arriba ya dice por qué
     puede ir de otra manera: es una barra de búsqueda, no un formulario de
     escribir datos. La regla de «un bloque por fila» (§7.1) se queda para los
     formularios, que es de lo que habla.

     Va con clase y no a todo `.filtros` porque esa clase la llevan siete
     pantallas más —Facturas, Catálogo, Usuarios, Actividad, Pasadas— y ninguna
     se ha mirado a 375 px todavía. Cuando se miren, se les quita la clase de
     encima o se les pone; lo que no vale es cambiárselas a ciegas.

     `a-solas` es para el campo que NO quiere compañía: el buscador, cuyo rótulo
     lleva la ayuda al lado («Por referencia, cliente, NIF o concepto») y a media
     anchura se parte en tres líneas — que es exactamente lo contrario de lo que
     se venía a hacer. */
  .filtros.apretada .campo{ flex:1 1 140px }
  .filtros.apretada .campo.a-solas{ flex:1 1 100% }
  /* Y lo que un desplegable a media anchura no puede evitar: que un nombre
     largo no quepa. Con el corte a hueso —«ALMACENES JARDINES CASTELLANO»— la
     caja parece rota; con puntos suspensivos se lee como lo que es, un nombre
     que sigue. Se puede hacer aquí y no en el catálogo de conceptos, donde el
     mismo corte SÍ era un fallo: allí se está EDITANDO y hay que saber qué pone;
     aquí es un filtro, la lista de debajo enseña el resultado y el nombre
     entero está a un toque. Un `<select>` a 309 px tampoco lo arreglaría: esa
     razón social pide 330. */
  .filtros.apretada select{ text-overflow:ellipsis }

  /* ── la fila de los cuatro campos cortos, que en el teléfono NO cabe ──────
     `.repartida` reparte la fila a partes iguales con `flex:1 1 0`, y esa base
     a CERO es justo lo que impide que la fila se doble: los cuatro se quedan en
     la misma línea sea cual sea el ancho, encogiendo hasta donde haga falta. En
     el escritorio es lo que se buscaba —cuatro cuartos limpios en vez de 500 px
     vacíos a la derecha de «Clave»—; a 375 px son cuatro cajas de 78 px, y lo
     que se ve es «por», «Fac», «30» y «certifi». Los CUATRO valores cortados,
     en la pantalla donde se están editando.

     Es exactamente lo que avisó Fabio al poner el orden: cada arreglo de
     escritorio mueve la misma maqueta que luego hay que doblar en 375. Aquí
     vuelve la base de 140 px, que es lo que dobla la fila en dos parejas.

     Y no se toca la regla del escritorio: `.repartida` sigue con `flex:1 1 0`
     donde tiene sentido. Condensar es repartir mejor el ancho, no encoger los
     mandos hasta que no se lean. */
  /* ── y los formularios del módulo, emparejados también (S11 · 7.3) ────────
     `.linea > .campo` pide 200 px antes de doblar, y el hueco útil de un
     desplegable a 375 px son 307: dos campos de 200 no caben nunca, así que en
     el teléfono TODOS caían de uno en uno. Es la maqueta cómoda de escribir y
     la que deja el alta en tres pantallas de scroll. Con 140 px de base se
     emparejan los que caben, que es lo que pidió Fabio.

     Lo que se queda su fila entera —y la regla se explica sola— es el campo que
     lleva EXPLICACIÓN en su rótulo: a media anchura, «En blanco = todavía sin
     tarifa. Bloquea el cierre del mes hasta que se ponga» pasa de dos líneas a
     cinco, y lo que se ahorra a lo alto emparejando se paga con creces. Un
     campo nuevo entra solo en la regla que le toque según lo que lleve dentro,
     sin que haya que acordarse de ponerle una clase.

     Y también se queda entero el campo que lleva un DESPLEGABLE: lo que hay
     dentro sale de la base y puede medir lo que sea. A media anchura, «De quién
     es» enseñaba «ANGEL CABA…» — y en este equipo hay dos Ángeles, así que
     cortado por ahí no dice de quién es el pedido. Lo que sí se empareja es un
     campo de fecha o de cifras: eso mide siempre lo mismo y se sabe de antemano.

     Y los dos buscadores del alta, aparte: cliente y catálogo despliegan su
     lista de sugerencias justo debajo del campo, y a media anchura no se lee ni
     un nombre de empresa. */
  .desplegable .ficha .linea > .campo{ flex:1 1 140px }
  .desplegable .ficha .linea > .campo:has(label .ayuda),
  .desplegable .ficha .linea > .campo:has(textarea),
  .desplegable .ficha .linea > .campo:has(select),
  .desplegable .ficha .linea > .campo[data-elige],
  .desplegable .ficha .linea > .campo[data-elige-concepto]{ flex:1 1 100% }

  .desplegable .ficha .linea.repartida > .campo.corto{ flex:1 1 140px }
  /* …y dentro de la segunda pareja, el reparto tampoco es mitad y mitad: un
     campo de cinco dígitos al lado de uno de sesenta caracteres. Con la mitad
     para cada uno, «certificado_digital» pedía 124 px y tenía 122 — y las
     claves llegan a 22 caracteres en el catálogo de hoy. */
  .desplegable .ficha .linea.repartida > .campo.corto.de-cifras{ flex:0 0 96px }
  .formulario.denso{ grid-template-columns:1fr }
  .lista .fila{ padding:var(--e3) var(--e4); flex-wrap:wrap }
  .fila .acciones{ margin-left:0; width:100% }
  /* …salvo la lista que lo pida (S11 · 7.3). En los dos recuadros del Inicio
     —el de Obligaciones y el de Pedidos— cada fila son tres cosas: el nombre,
     un chip y un «Ver». Con el nombre pidiendo 220 px de base y las acciones a
     lo ancho, las TRES caían una debajo de otra: 144-183 px por fila, y seis
     filas entre los dos recuadros. El nombre se queda su línea —es lo largo— y
     el chip y el botón comparten la de abajo. Medido: de 183 a 106.

     Con clase, y no a todo `.lista`: esa clase la llevan además Grupos, el
     cuadro de mando y dos pantallas del panel, y ninguna se ha mirado a 375 px. */
  .lista.apretada .fila .principal{ flex:1 1 100% }
  .lista.apretada .fila .acciones{ margin-left:auto; width:auto }

  /* La tabla de opciones apila el módulo encima de sus cuatro estados. */
  .opciones > *{ grid-template-columns:repeat(4, 1fr); gap:var(--e2) }
  .opciones .que{ grid-column:1 / -1 }
  .opciones .cabecera-op{ display:none }
  .opciones .op{ min-height:44px; border:var(--f-separa) solid var(--filete) }
  .opciones .op .rotulo-op{ display:block; font-size:10px; color:var(--tinta-2) }

  /* La tabla de tarjetas deja de ser tabla. En 375 px no hay sitio para cinco
     columnas, y encogerlas hasta que quepan es como se consigue una pantalla
     que no se puede leer ni usar. Cada tarjeta se apila y CADA CELDA SACA SU
     RÓTULO: sin cabecera de columna, un «3» suelto no significa nada. */
  .tabla-cabecera{ display:none }
  .tabla{ gap:var(--e2) }
  .tabla > .tabla-fila{
    grid-template-columns:1fr; gap:var(--e2);
    padding:var(--e4); border-top:var(--f-separa) solid var(--filete);
    border-radius:var(--r);
  }
  .celda .rotulo{
    display:block; font-size:10px; letter-spacing:.06em; text-transform:uppercase;
    color:var(--tinta-2); margin-bottom:2px;
  }
  .celda-acciones{ justify-content:flex-start; flex-wrap:wrap; gap:var(--e2);
                   padding-top:var(--e2); border-top:var(--f-separa) solid var(--filete) }
  /* En el dedo, 32 px no basta: 44 es el objetivo táctil. */
  .boton.icono{ width:44px; height:44px; min-height:44px }

  /* ── Equipo en el móvil: la tarjeta, condensada (20/08) ─────────────────
     Con el apilado de arriba cada persona ocupaba SIETE bloques —uno por
     columna, cada uno con su rótulo encima— y una fila se comía media
     pantalla. Fabio: «cada fila ocupa mucho y está muy desordenada».

     Aquí la fila deja de ser una columna y pasa a ser una tarjeta de dos
     partes: arriba el nombre con su botón a la derecha, y debajo todo lo
     demás en línea, envolviendo. Se lee de un vistazo y ocupa un tercio.

     Los rótulos siguen estando —sin cabecera de columna, un «8» suelto no
     significa nada—, pero van DELANTE y en pequeño, no encima: encima cada
     dato gastaba dos líneas en vez de una. */
  .tabla.equipo > .tabla-fila{
    display:flex; flex-wrap:wrap; align-items:center;
    gap:var(--e2) var(--e3);
    padding:var(--e3) var(--e4);
  }
  /* El nombre se lleva la PRIMERA LÍNEA ENTERA menos el hueco del botón, y el
     botón se queda a su derecha. La base se calcula en vez de dejarla en `auto`
     a propósito: con `auto` el nombre medía lo que mide un nombre —140 px— y el
     primer dato se colaba a su lado, así que el botón acababa suelto en la
     tercera línea. Al llenar la línea, todo lo demás envuelve junto y debajo. */
  .tabla.equipo .celda-principal{
    flex:1 1 calc(100% - 44px - var(--e3)); min-width:0; order:1;
  }
  .tabla.equipo .celda-acciones{
    flex:0 0 44px; order:2;
    padding-top:0; border-top:0;
  }
  /* Y el resto, en línea y detrás de esos dos. El `:not()` NO es adorno: la
     celda del nombre es `class="celda celda-principal"`, así que esta regla
     también le casaba, pesaba lo mismo que la suya (0,2,1) y por ir después le
     ganaba — el nombre acababa con `flex:0 0 auto` y `order:3`, o sea medía lo
     que mide un nombre, dejaba sitio al primer dato a su lado y mandaba el
     botón a la tercera línea. Dos reglas que empatan las decide el orden, y ese
     es un sitio malísimo donde esconder una decisión. */
  .tabla.equipo .celda:not(.celda-principal):not(.celda-acciones){
    flex:0 0 auto; order:3;
  }
  .tabla.equipo .celda .rotulo{
    display:inline; margin:0 4px 0 0; font-size:9px;
  }
  /* La celda que no tiene nada que decir desaparece aquí, y solo aquí: en la
     rejilla de escritorio tiene que seguir ocupando su columna. */
  .tabla.equipo .celda.sin-dato{ display:none }
  /* El dato pegado a su rótulo, no debajo. */
  .tabla.equipo .celda-modulo{ flex-direction:row; align-items:center; gap:4px }
  .tabla.equipo .celda-modulo .bajo{ font-size:9px }

  /* En móvil el menú deja de flotar y se DESPLIEGA dentro de la fila, empujando
     lo de abajo. Flotando se salía por la derecha: el botón está pegado a la
     izquierda y el panel mide 230 px, así que en 375 px se iba fuera de la
     pantalla. Desplegado ocupa el ancho de la fila y no tapa nada. */
  .menu{ position:static }
  .menu[open]{ flex:1 1 100% }
  .menu .panel{ position:static; width:100%; min-width:0; margin-top:var(--e2) }
  .menu .panel .boton{ min-height:44px }

  /* ── el módulo de Obligaciones en el móvil ───────────────────────────── */

  /* Los botones, en su PROPIA fila y pegados a la izquierda (§2.b.2). En el
     teléfono, compartir línea con el nombre del mes los dejaba en dos alturas
     distintas y medio salidos. */
  /* En el móvil se apilan en una sola columna: sumario, botones y panel. Las
     filas se dicen a mano, igual que en escritorio: mezclar nombres de área
     aquí y líneas explícitas allí es como se acaba con un panel de ancho cero
     que nadie sabe de dónde sale. */
  .barra-filtros{ grid-template-columns:minmax(0,1fr) }
  .barra-filtros > .filtros-plegables{ grid-column:1; grid-row:1 }
  .barra-filtros > .acciones-pantalla{ grid-column:1; grid-row:2;
                                       width:100%; padding:0 var(--e3) var(--e2);
                                       flex-wrap:wrap }
  .barra-filtros > .panel-filtros{ grid-column:1; grid-row:3 }
  .barra-filtros > .acciones-pantalla .boton{ min-height:44px; padding:6px var(--e3) }
  .filtros-plegables > summary{ min-height:44px; padding:var(--e2) var(--e3);
                                font-size:var(--t-cuerpo) }
  .titulo-mes,
  .barra-mes{ align-items:flex-start; flex-direction:column; gap:var(--e2) }
  .titulo-mes .a-la-derecha,
  .barra-mes .a-la-derecha{ margin-left:0; width:100%; flex-wrap:wrap }
  .acciones-pantalla{ width:100% }
  /* Los dos desplegables a lo ancho: en 375 px, «Enero · 713 · 13 sin
     presentar» no cabe en media fila. */
  .fila-ejercicio{ width:100%; flex-wrap:wrap }
  /* Lo que se dobla es el PAR, no el rótulo por un lado y el campo por otro.
     Base escrita y NO `auto`: la base automática de un `<select>` es la de su
     opción más larga, y la del mes en Obligaciones es «Enero · 713 · 13 sin
     presentar» — 220 px que mandaban cada par a su propia línea.

     Y el suelo de 84 px en el desplegable, que es lo que impide que la fila se
     apriete de más: con 75 el año enseñaba «202», un número de cuatro cifras
     cortado a tres. Son esos cuatro dígitos más la flecha y el relleno,
     medidos. Con ese suelo la fila mínima son 339 px de los 351 que hay. */
  .fila-ejercicio .par-campo{ flex:1 1 150px }
  .fila-ejercicio select{ flex:1 1 84px; min-width:84px }
  /* Y el «Ir», que con la fila en una sola línea se quedaba en 34 px de ancho:
     alto sí tenía 44, pero un objetivo táctil lo son las dos medidas. */
  .fila-ejercicio button{ min-width:44px }

  /* El sumario ya es visible en los dos tamaños; aquí solo sube al objetivo
     táctil de 44 px. */
  .filtros-plegables > summary{ padding:var(--e3) var(--e4); min-height:44px }
  .filtros-plegables .filtros-mes{ padding-top:var(--e3) }

  /* ── la ficha, de abajo arriba y encima de todo (§2.b.5) ──────────────
     En el teléfono no hay sitio para un panel al lado ni para uno que entra por
     la derecha: ocupa lo que necesita, subiendo desde abajo, que es de donde
     vienen las fichas en cualquier aplicación de móvil.

     `max-height:90dvh` y no 100: el borde de arriba tiene que dejar ver que
     debajo hay algo, o parece que has cambiado de pantalla. */
  .con-panel{ grid-template-columns:1fr; gap:0 }
  .con-panel.con-ficha{ grid-template-columns:1fr; gap:0 }
  .hueco-ficha,
  .hueco-ficha.superpuesta{
    position:fixed; left:0; right:0; bottom:0; top:auto;
    width:auto; max-height:90dvh; z-index:50;
    overflow-y:auto; overscroll-behavior:contain;
    background:var(--papel);
    border:0; border-top:var(--f-cierra) solid var(--tinta);
    transform:translateY(100%); visibility:hidden;
    transition:transform var(--mov-normal) var(--curva),
               visibility 0s linear var(--mov-normal);
  }
  .hueco-ficha.con-ficha,
  .hueco-ficha.superpuesta.con-ficha{
    transform:none; visibility:visible;
    transition:transform var(--mov-normal) var(--curva), visibility 0s;
  }
  .panel-obligacion{ padding:var(--e4) }
  .rejilla .columna-empresa{ width:200px; min-width:200px }

  /* ── en el teléfono NO existe la rejilla (24/08, §2.b.1) ───────────────
     Decisión de Fabio con la pantalla delante: «solo se debe poder ver la
     vista de lista; no tiene sentido que puedan ver la de rejilla porque se
     ve horrible». Así que aquí no hay conmutador que enseñar — no es que se
     esconda un mando útil, es que solo hay una forma.

     Dos cosas que costó ver, y las dos son de la misma familia:

     · el selector de antes era `.titulo-mes #conmutador-vista`, y el
       conmutador **no cuelga de `.titulo-mes`**: vive en
       `.barra-mes > .acciones-pantalla`. O sea que esa regla no casaba con
       nada y el conmutador SE VEÍA en el teléfono, aunque el CSS llevara
       meses diciendo que estaba escondido. Un selector que no casa es una
       regla que no existe, y se lee igual que una que funciona. Aquí basta
       el id: es único en la página.
     · esconder un mando solo vale cuando hay otra salida. El guion fuerza la
       lista SIEMPRE, y si no hay JavaScript la rejilla se esconde (regla de
       aquí abajo) y sale un aviso con su enlace. */
  #conmutador-vista{ display:none }

  /* Y sin JavaScript, que es cuando el guion no puede llevarnos a la lista:
     la rejilla no se enseña rota, se enseña el aviso que lleva a la lista.
     El `data-vista` lo escribe `index.php` en el mismo contenedor que el
     filtro en vivo reemplaza por dentro, así que sobrevive a filtrar. */
  #resultado-mes[data-vista="rejilla"] > *{ display:none }
  #resultado-mes[data-vista="rejilla"] > .aviso-solo-lista{ display:block }

  /* ── las pestañas, con icono en vez de texto (§2.b.3) ─────────────────
     Seis apartados en 375 px no caben escritos y se iban a tres líneas. El
     texto NO se quita del HTML: se recorta con la misma técnica que
     `.solo-lectores`, así que el nombre sigue oyéndose y el `title` lo enseña
     al mantener pulsado. Un icono aislado lo acierta menos de la mitad de la
     gente; sin la palabra debajo, al menos que la oiga quien la necesite. */
  .pestanas{ gap:var(--e2); justify-content:space-between }
  .pestanas a{ display:flex; align-items:center; justify-content:center;
               min-width:44px; min-height:44px; padding:var(--e2) }
  .pestanas a .texto-pestana{
    position:absolute; width:1px; height:1px; overflow:hidden;
    clip-path:inset(50%); white-space:nowrap;
  }
  .pestanas a svg{ display:block; width:20px; height:20px; stroke:currentColor;
                   stroke-width:1.7; fill:none; stroke-linecap:round;
                   stroke-linejoin:round }

  /* Las dos columnas de la ficha se apilan: la regla de la casa es un campo por
     fila, y las parejas de §4.b.5 son una excepción que solo tiene sentido
     cuando hay ancho para las dos. */
  .fila-ficha{ grid-template-columns:1fr }
  .titulo-ficha{ gap:var(--e2) }
  .titulo-ficha .a-la-derecha{ margin-left:0 }
  /* Y el botón de guardar se pega al fondo de la VENTANA, que en el móvil es
     quien desplaza: la columna ya no tiene desplazamiento propio. */
  .guardar-pegado{ border-radius:var(--r) }

  /* La matriz de meses no cabe en 375 px con doce columnas de 38: se desplaza
     ella sola, con el nombre del modelo clavado a la izquierda. */
  .matriz{ overflow-x:auto }
  .matriz .cabecera-matriz, .matriz .fila-matriz{ width:max-content; min-width:100% }
  .matriz .que{ position:sticky; left:0; background:var(--papel) }

  /* ── la fila de la lista en el móvil, rediseñada (§móvil 3) ────────────
     Fabio: «no se entiende bien el modelo y no destaca lo suficiente; condénsalo
     un poco más si puedes».

     Lo que fallaba, y no era el tamaño de la letra: el modelo y el chip de
     estado compartían la MISMA área de la rejilla. El chip lleva color, punto y
     fondo; el modelo era gris monoespaciado del mismo tamaño. Puestos en el
     mismo sitio, el estado se comía al modelo, y si el texto crecía se
     superponían en vez de empujarse. Encima el modelo sale como «111» pelado,
     sin la palabra «Modelo» delante, así que si además no destaca no se lee como
     un dato: se lee como ruido.

     Ahora cada uno tiene SU columna y el modelo se pinta como una etiqueta —el
     mismo tratamiento que las demás etiquetas del sitio—, que es lo que le da
     peso sin tener que agrandarlo:

         [✓]  NOMBRE DE LA EMPRESA        [111]   [botón] [ficha]
              B12345678                 Pendiente

     Y se condensa: 1 px entre líneas, la fila baja de 60 px a 56. */
  .tabla.pendientes{ gap:0 }
  .tabla.pendientes > .tabla-fila{
    display:grid;
    grid-template-columns:22px minmax(0,1fr) auto auto;
    grid-template-areas:"elegir titulo modelo acciones"
                        "elegir nif    estado acciones";
    gap:1px var(--e2); align-items:center;
    /* 4 px arriba y abajo, no 8: el suelo de la fila lo pone el objetivo táctil
       de 44 px de los botones, así que todo lo que se le quite al relleno son
       filas de más a la vista. Con 4 la fila mide 52 y caben nueve en un
       teléfono; con 8 medía 61 y cabían siete. */
    padding:var(--e1) var(--e3); min-height:0;
    border-radius:0; border-top:0;
    border-bottom:var(--f-separa) solid var(--filete);
  }
  .tabla.pendientes > .tabla-fila:first-of-type{ border-top:var(--f-separa) solid var(--filete) }
  .tabla.pendientes .celda .rotulo{ display:none }
  .tabla.pendientes .celda-elegir{ grid-area:elegir }
  /* `display:contents` deja que el nombre y el NIF se coloquen como dos piezas
     distintas de la rejilla: es lo que permite las dos líneas sin anidar más. */
  .tabla.pendientes .celda-empresa{ display:contents }
  .tabla.pendientes .celda-empresa .titulo{ grid-area:titulo; font-size:13px;
                                            overflow:hidden; text-overflow:ellipsis;
                                            white-space:nowrap }
  .tabla.pendientes .celda-empresa .bajo{ grid-area:nif; justify-self:start;
                                          font-size:10px }

  /* El modelo, en su columna y con cuerpo de etiqueta. */
  .tabla.pendientes .celda-obligacion-lista{ grid-area:modelo; justify-self:end;
                                             display:flex; align-items:center }
  .tabla.pendientes .celda-obligacion-lista .que-es{ display:none }
  .tabla.pendientes .celda-obligacion-lista .modelo{
    padding:1px 6px; border-radius:var(--r);
    background:var(--chip-fondo); color:var(--chip-texto);
    border:var(--f-separa) solid var(--chip-filete);
    font-weight:var(--p-fuerte); font-size:12px;
  }

  /* El estado, debajo del modelo y en la misma columna: se leen en vertical, uno
     encima del otro, en vez de pelearse por el mismo sitio. */
  .tabla.pendientes .celda-estado-lista{ grid-area:estado; justify-self:end }
  .tabla.pendientes .celda-estado-lista .estado{ padding:1px 5px; font-size:10px }

  /* El responsable no entra: en el móvil se mira lo de uno. */
  .tabla.pendientes .celda-responsables{ display:none }

  /* Los dos botones —marcar y abrir la ficha—, uno al lado del otro y a 44 px,
     que es lo que pide el dedo (§2.b.4: «dejarlo como icono y añadir el de ver
     la ficha»). Ocupan las dos líneas de la fila, así que no la hacen más alta. */
  .tabla.pendientes .celda-acciones{ grid-area:acciones; padding:0; border:0;
                                     display:flex; gap:2px; justify-content:flex-end }
  .tabla.pendientes .marcar-entregada{ width:44px; height:44px; min-height:44px;
                                       padding:0; justify-content:center }
  /* Solo el dibujo: la palabra y la fecha no caben, y el `title` y el
     `.solo-lectores` siguen diciéndolo entero. */
  .tabla.pendientes .marcar-entregada .palabra,
  .tabla.pendientes .marcar-entregada .al-pasar{ display:none }
  .tabla.pendientes .marcar-entregada.estado-entregada:hover .palabra,
  .tabla.pendientes .marcar-entregada.estado-no_obligado:hover .palabra{ display:none }

  /* La fila de un pedido apilada de la forma genérica mide 372 px: un pedido
     por pantalla, que es exactamente la queja de Fabio del 20/08 con el cuadro
     de mando. Se condensa con rejilla propia, igual que se hizo con `.tabla.equipo`.

     Las celdas que aquí no aparecen (responsable, días, precio) siguen en el
     HTML y salen con su rótulo debajo: se condensa lo que se lee de un vistazo,
     no se esconde información. */
  .tabla.pedidos .tabla-fila{
    display: grid;
    /* TRES columnas y CUATRO líneas, y CADA celda con su sitio escrito: aquí
       ya no se autocoloca nada (S11 · 7.3). Es lo que quita las dos líneas que
       sobraban —el rótulo «Abierto» sin dato y el precio con el suyo— y deja la
       fila en 265-285 px → los que se midan abajo.

       Que estén las OCHO nombradas no es celo: mientras tres se autocolocaban,
       una celda nueva caía en una fila implícita detrás de los botones y no lo
       cazaba nada (pasó en la 3.4 con el nombre del cliente). Con la lista
       completa, la celda que se añada mañana y no se apunte aquí **se ve al
       primer vistazo**, porque cae en una quinta línea vacía.

       Y hay DOS repartos porque el precio es la única celda que puede no
       existir: quien no ve el dinero no recibe esa celda —no se esconde, no
       viaja— y su hueco tiene que cerrarlo el cliente. El interruptor es la
       clase `con-precio` que ya lleva la tabla. */
    grid-template-columns: minmax(0,1fr) auto auto;
    grid-template-areas:
      "ref      dias     estado"
      "titulo   titulo   titulo"
      "cliente  cliente  cliente"
      "datos    acciones acciones";
    gap: var(--e1) var(--e2);
    align-items: start;
    /* En el teléfono lo que va pegado arriba no es la cabecera de la tabla —que
       aquí no se pinta— sino la barra de `.lateral`, que mide 68 px. Sin esto,
       el salto del ancla deja la referencia y el chip de estado —la primera
       línea de la rejilla de aquí arriba— debajo de la barra. */
    scroll-margin-top: 76px;
  }
  /* La gemela de `.tabla-fila[hidden]` (§1470) para esta rejilla propia, y no es
     adorno: la regla de aquí arriba pesa (0,3,0) y le gana a la guarda general,
     que pesa (0,2,0). Sin esta línea, en el teléfono `fila.hidden = true` no
     escondía NADA: buscar en vivo dejaba las once filas puestas, filtrar hasta
     cero encendía el cartel de «no hay ningún pedido con eso» ENCIMA de la lista
     entera, y —como `.desplegable[hidden]` sí funciona— la ficha abierta se iba
     dejando su fila ahí, que es la misma mentira del revés.

     Es LA MISMA avería que ya se pagó en Grupos con `.lista .fila` (el comentario
     está junto a la guarda general), entrando por la puerta de la rejilla
     condensada del móvil. Por eso va pegada a la regla que la causa: quien
     cambie el `display` de la fila tiene la contra a la vista. */
  .tabla.pedidos .tabla-fila[hidden]{ display: none }
  .tabla.pedidos.con-precio .tabla-fila{
    grid-template-areas:
      "ref      dias     estado"
      "titulo   titulo   titulo"
      "cliente  cliente  precio"
      "datos    acciones acciones";
  }
  .tabla.pedidos .celda-referencia{ grid-area: ref }
  /* Los días suben a la primera línea, pegados al chip de estado: son los dos
     datos que dicen si un pedido corre prisa, y juntos se leen de una pasada.
     Abajo ocupaban una celda entera de la rejilla para una palabra («17 días»)
     y, en los que no están abiertos, para NADA. */
  .tabla.pedidos .celda-dias      { grid-area: dias; justify-self: end;
                                    align-self: center }
  /* El chip de estado NO se pulsa en Pedidos —es un `<div>` con una etiqueta
     dentro, no el `<a>` de la rejilla de Obligaciones—, así que el suelo táctil
     de 44 px que le pone la sección de aquí abajo no protege nada y le sumaba
     24 px a la primera línea de cada fila. La regla táctil se queda donde está
     para quien sí la necesita. */
  .tabla.pedidos .celda-estado    { grid-area: estado; justify-self: end;
                                    min-height: 0 }
  .tabla.pedidos .celda-principal { grid-area: titulo }
  .tabla.pedidos .celda-datos     { grid-area: datos; display:flex;
                                    flex-wrap:wrap; gap:var(--e2); min-width:0;
                                    align-self: center }
  /* El nombre del cliente, a lo ancho: es el dato más largo de la fila y el que
     más se busca. A media anchura se partía en tres líneas. Cede el hueco del
     precio —y solo ése— cuando hay precio que enseñar. */
  .tabla.pedidos .celda-cliente   { grid-area: cliente }
  .tabla.pedidos .celda-precio    { grid-area: precio; justify-self: end }
  /* Los botones. Hasta la 7.3 esta celda NO llevaba área: «Cliente», «Abierto»
     y «Precio» no tenían clase propia, se autocolocaban, y con `acciones` en un
     área nombrada la rejilla las mandaba a filas implícitas DETRÁS de ella — el
     nombre del cliente salía debajo de los botones, y parecía de otra fila. Se
     tapó entonces sacando `acciones` del área y mandándola la última con
     `order`. Ahora las ocho celdas tienen clase y área, no se autocoloca nada, y
     ni el `order` ni el `1 / -1` hacen falta. Lo que sí hace falta es quitarles el
     filete de arriba que les pone la regla general del móvil: allí la celda de
     acciones se lleva la fila entera y ese filete es la raya que cierra la
     tarjeta; aquí comparte línea con el nombre y quedaba un trozo de raya
     suelto sobre los botones, que se lee como un error de maqueta. */
  .tabla.pedidos .celda-acciones  { grid-area: acciones; justify-self: end;
                                    align-self: center;
                                    border-top: 0; padding-top: 0; margin-top: 0 }

  /* ── y el botón de dos caras, en el teléfono, enseña LA DE DETRÁS ────────
     El botón dice en qué estado está el pedido y al pasar el ratón ofrece lo
     contrario. **En un teléfono no se pasa el ratón por encima de nada**: la
     cara que se ofrece no aparece jamás, así que quedaba un botón azul que
     pone «Abierto» y nadie puede saber que lo que hace es marcarlo como hecho.
     Y encima repite lo que el chip de al lado ya dice.

     Aquí se da la vuelta a la regla: el estado lo cuenta el chip de la primera
     línea —que para eso ha subido ahí— y el botón cuenta lo que va a pasar si
     lo pulsas, que es lo único que no se puede adivinar. El `title` y el
     `.solo-lectores` del enlace siguen diciéndolo entero para quien no ve. */
  .tabla.pedidos .boton.marcar .palabra{ display:none }
  .tabla.pedidos .boton.marcar .al-pasar{ display:inline }

  /* ── el catálogo de conceptos, condensado igual (S11 · 7.3) ──────────────
     Apilada de la forma genérica, la tarjeta de un concepto medía 320 px: seis
     celdas, y CUATRO de ellas gastaban una línea entera en un rótulo para
     enseñar debajo un número de un dígito o un chip que se lee solo. Veinte
     conceptos eran 7.348 px, nueve pantallas de teléfono para una lista que en
     el ordenador cabe entera.

     Aquí no se usan áreas como en Pedidos: esta tabla tiene CUATRO repartos de
     columnas según quién mire —`sin-dinero` y `solo-mirar`, y las dos a la
     vez—, y cuatro plantillas de áreas serían cuatro sitios que mantener. Con
     flex y `flex-wrap` el reparto sale solo: cada celda pide lo suyo, y la que
     falte no deja hueco. */
  .tabla.conceptos .tabla-fila{
    display:flex; flex-wrap:wrap; align-items:center;
    gap:var(--e2) var(--e3);
  }
  /* ⚠ La gemela del `[hidden]`, por lo mismo que en Pedidos: la regla de aquí
     arriba pesa (0,3,0) y le gana a la guarda general `.tabla-fila[hidden]`,
     que pesa (0,2,0). Sin esta línea, el buscador en vivo de esta pantalla
     —`data-busca` en cada fila— dejaría las veinte puestas. Va pegada a la
     regla que la causa, para que quien cambie el `display` la tenga a la vista. */
  .tabla.conceptos .tabla-fila[hidden]{ display:none }
  /* Primera línea: el número de orden y, al lado, el nombre con su familia,
     cómo se cobra y sus minutos debajo. */
  .tabla.conceptos .celda-orden{ flex:0 0 auto; align-self:flex-start;
                                 padding-top:2px }
  /* 240 px de base no es un gusto: es lo que hace que el nombre comparta línea
     con el número de orden Y que los tres chips no quepan detrás y bajen solos.
     Con menos base, los chips se colaban en la primera línea y al nombre le
     quedaban 35 px. */
  .tabla.conceptos .celda-principal{ flex:1 1 240px; min-width:0 }
  /* Segunda línea: los tres chips juntos. Se leen solos —«sin precio»,
     «Facturable», «se ofrece»— y con rótulo encima se llevaban tres líneas. */
  .tabla.conceptos .celda-tarifa,
  .tabla.conceptos .celda-tipo,
  .tabla.conceptos .celda-oferta{ flex:0 0 auto }
  /* Y los cuatro botones de icono, a lo suyo: mandan a su propia línea porque
     entre los tres chips y ellos no hay sitio, y ahí es donde se buscan. */
  .tabla.conceptos .celda-acciones{ flex:1 1 100%; justify-content:flex-start }
  .tabla.conceptos .celda-orden .rotulo,
  .tabla.conceptos .celda-tarifa .rotulo,
  .tabla.conceptos .celda-tipo .rotulo,
  .tabla.conceptos .celda-oferta .rotulo{ display:none }

  /* ── y en una tarjeta, un nombre largo se DOBLA, no se corta ─────────────
     `.celda-principal .titulo` lleva `white-space:nowrap` + `text-overflow`
     porque en el escritorio es una columna de una tabla y ahí eso es lo
     correcto: la columna manda y el nombre entero está en el `title`. En el
     teléfono la fila ya no es una tabla, es una tarjeta, y ahí el corte es lo
     mismo que pasaba en la ficha de un concepto: «Renovación de certificado…»
     es el dato principal de la tarjeta y sale a medias. Debajo hay sitio de
     sobra; lo que no hay es ancho.

     Va a las tres tablas de Pedidos y no a todas: las demás pantallas del
     portal usan `.celda-principal` igual y no se han mirado a 375 px. */
  .tabla.pedidos .celda-principal .titulo,
  .tabla.conceptos .celda-principal .titulo,
  .tabla.cierre-lineas .celda-principal .titulo,
  .tabla.pedidos .celda-principal .bajo,
  .tabla.conceptos .celda-principal .bajo,
  .tabla.cierre-lineas .celda-principal .bajo{
    white-space:normal; overflow:visible; text-overflow:clip;
  }

  /* En la fila condensada casi ningún rótulo se gana su línea (S11 · 7.3, con
     la pantalla delante y las dos directrices de Fabio para el móvil:
     condensar, y meter en la misma línea todo lo que quepa).

     Se callan los que el dato explica solo:
      · Ref., Estado y Concepto — se leían solos ya desde la 3.4;
      · Cliente — va justo debajo del título y en una línea suya: una razón
        social no se confunde con nada;
      · Abierto — el dato es «17 días», que lo dice entero; y en los pedidos
        que NO están abiertos `pedidos_dias_abierto()` devuelve cadena vacía,
        así que ese rótulo salía SOLO, sin nada detrás (cinco de los ocho de la
        lista de pruebas);
      · Precio — el dato es «45,00 €» o el chip «Sin precio»;
      · De quién — un nombre de PERSONA, justo debajo de una razón social y con
        la cabecera de columna del escritorio diciéndolo. Se calla también
        porque es el que decide el alto de la fila: con el rótulo puesto, «De
        quién VANESA SERRANO» no cabía en la columna del pie y se partía en
        TRES líneas — 65 px por dos palabras, medidos.

     Sigue siendo UNA sola regla —varios selectores en el mismo bloque—, así que
     no hay dos pesos que empaten y no hay decisión escondida en el orden del
     fichero, que era lo que el `:not()` que había aquí venía a evitar. */
  .tabla.pedidos .celda-referencia .rotulo,
  .tabla.pedidos .celda-estado .rotulo,
  .tabla.pedidos .celda-cliente .rotulo,
  .tabla.pedidos .celda-datos .rotulo,
  .tabla.pedidos .celda-dias .rotulo,
  .tabla.pedidos .celda-precio .rotulo,
  .tabla.pedidos .celda-principal .rotulo{ display: none }

  /* ── lo que quedaba por debajo del dedo (24/08) ─────────────────────────
     Una pasada de auditoría móvil midió los objetivos táctiles de todo el
     sitio y estos son los que quedaban por debajo de los 44 px de la norma
     (SISTEMA-DISENO §9). Se suben aquí JUNTOS, para que la próxima pasada
     tenga un solo sitio que mirar. */
  .boton{ min-height:44px }
  .boton.chico{ min-height:44px }
  /* Este hace falta aparte: su regla base pesa (0,3,1) y le ganaba al bump
     genérico de `.menu .panel .boton` de más arriba. */
  .menu.ordenar .panel .boton{ min-height:44px }
  /* Y los 16 px, que a estos dos tampoco les llegaban: `.fila-ejercicio select`
     pesa (0,1,1) y les pone `--t-apoyo` = 12. Medido a 375 px en el cierre de
     mes: los dos desplegables del año y del mes, a 12. */
  .fila-ejercicio select{ min-height:44px; font-size:16px }
  .barra-lote .fecha-lote input{ min-height:44px }
  .celda-estado{ min-height:44px }
  /* El «Más detalles» del alta de Pedidos (S11 · 3.4). Un <summary> pelado mide
     20 px de alto: es el mando que abre los seis campos opcionales del alta y
     era el objetivo táctil más pequeño de la pantalla. Y `cursor:pointer`
     porque los otros tres <summary> de la casa —el menú de tres puntos, los
     filtros plegables y `details.anadir`— ya lo llevan; sin él, el único mando
     del formulario que no parece pulsable es justo éste. */
  .mas-detalles > summary{ min-height:44px; cursor:pointer;
                           padding-block:var(--e2) }
  /* Cada sugerencia del buscador de cliente (S11 · 3.4b). Se eligen con el
     pulgar y encima del teclado abierto: 38 px ahí es un botón que se falla. */
  .sugerencias button{ min-height:44px }

  /* ── y las columnas del catálogo de conceptos, aquí NO ──────────────────
     Los anchos fijos son lo que alinea las columnas en el escritorio, y en el
     teléfono son un desastre medido: 12ch + 11ch + 7ch + 15ch más los huecos y
     el relleno son 377,9 px de mínimo, no caben en los 351 de la columna y,
     como no pueden encoger, **empujaban la página entera a desbordar de lado**
     —375 de ventana contra 391 de contenido—. Y el desborde no lo sacaba la
     lista: lo sacaba el formulario del alta, que es donde nadie lo habría
     buscado.

     Aquí el nombre se lleva una línea entera y los datos se ponen debajo con su
     ancho natural. Se pierde la rejilla y no importa: en 375 px cuatro columnas
     de datos no se leen como tabla ni aunque cuadren.

     Y el nombre PARTE LÍNEA en vez de recortarse. Dos cosas en una declaración,
     y las dos hacen falta: en el escritorio se recorta con puntos suspensivos
     porque la fila mide 38 px y ahí manda la rejilla, pero en un teléfono un
     «Baja de un cliente y entrega de docum…» no dice cuál de los dos trabajos
     de baja es. Además el `nowrap` del escritorio era justo lo que desbordaba:
     un nombre que no puede partirse tiene el ancho de su texto como MÍNIMO, y
     ese mínimo subía por la lista hasta el formulario del alta. */
  .sugerencias.con-datos .titulo{ flex:1 1 100%; white-space:normal }
  .sugerencias.con-datos .columna-familia,
  .sugerencias.con-datos .columna-cobra,
  .sugerencias.con-datos .columna-minutos,
  .sugerencias.con-datos .columna-tipo{ flex:0 1 auto }
  .sugerencias.con-datos .columna-minutos{ text-align:left }
  .matriz .cabecera-matriz,
  .matriz .fila-matriz{ grid-template-columns:minmax(180px,1fr) repeat(12, 44px) 44px }
  .matriz .mes{ min-height:44px }

  /* Los campos de escribir, a 16 px: por debajo de eso, Safari en iOS hace
     zoom él solo al enfocar y la pantalla se queda descuadrada hasta que se
     pellizca de vuelta. 16 es el umbral documentado, no un gusto. La regla es
     GENERAL a propósito —no una lista de clases—: la primera versión listaba
     `.campo input` y compañía, y Mi cuenta se quedó fuera porque sus campos
     van en `.con-campo`. Un campo nuevo entra solo.

     ⚠ Y de los tres, DOS no llegaban (S11 · 7.3, medido a 375 px en la barra de
     filtros de Pedidos: los dos desplegables salían a 14 px). El `input` sí
     llega porque sus tres `:not([type=…])` lo suben a (0,3,1); un `select` o un
     `textarea` pelados pesan (0,0,1) y **pierden contra `.campo select`**, que
     es (0,1,1) y los pone a `--t-cuerpo` = 14. O sea que la regla casaba, se
     leía bien y no hacía nada en los dos sitios donde más se nota: un
     desplegable y un cuadro de texto son justo lo que se toca con el pulgar.

     Por eso aquí van también los selectores CON su clase: mismo peso que la
     regla base, y este bloque va después. Que siga yendo después lo vigila
     `herramientas/comprobar_pedidos.php`, porque un empate lo decide el orden
     del fichero y eso se rompe moviendo un bloque, sin tocar ni una regla. */
  .campo input, .campo select, .campo textarea,
  .dato-fila .con-campo input, .dato-fila .con-campo select,
  input:not([type=checkbox]):not([type=radio]):not([type=range]),
  select, textarea{ font-size:16px }

  /* El tirador de redimensionar la columna de empresa vive del ratón (solo
     asoma con :hover) y mide 7 px: en una pantalla táctil ni se ve ni se
     acierta. La rejilla ya se desplaza entera; fuera. */
  .tirador{ display:none }

  /* ── el cuadro de mando, recompuesto para el teléfono (24/08) ────────────
     Fabio lo miró en el suyo: «no se ve nada bien, los gráficos carecen de
     sentido». Tenía razón tres veces, y las tres eran de geometría:
     · los KPI salían uno debajo de otro a tarjeta entera — cinco pantallas
       de cifras antes del primer gráfico;
     · las barras de carga median ~35 px flotando en mitad de la fila: la
       pista de la rejilla de escritorio (nombre 120-180 px + cifra 84) se
       comía el ancho y la barra no comparaba nada;
     · el año eran doce columnas de 24 px con la cifra a 9 px debajo.
     El escritorio no se toca; aquí cada pieza se recompone a lo ancho. */

  /* Los KPI, de dos en dos; el total, a fila entera. La cifra baja de 34 a
     28 px porque en 160 px de tarjeta 34 se come el rótulo. */
  .kpis{ grid-template-columns:repeat(2, minmax(0,1fr)); gap:var(--e2) }
  .kpis .kpi:first-child{ grid-column:1 / -1 }
  /* Y con CUATRO, el último también: si no, la tercera fila se queda con una
     tarjeta a media anchura y medio hueco al lado, que se lee como que falta
     algo. Solo se aplica cuando el cuarto ES el último —el cuadro de mando de
     Obligaciones tiene cinco y ahí la cuenta ya sale— así que no hay que
     acordarse de nada al escribir la pantalla siguiente.
     Medido en el cierre de mes a 375 px. */
  .kpis .kpi:nth-child(4):last-child{ grid-column:1 / -1 }
  .kpi{ padding:var(--e3) var(--e4) }
  .kpi .cifra{ font-size:28px }

  /* Las barras de carga y del reparto: el nombre y la cifra en la primera
     línea, y la barra DEBAJO y a todo lo ancho. En fila de tres columnas la
     barra quedaba en ~35 px; así vuelve a ser una barra. */
  .barra-fila{ grid-template-columns:minmax(0,1fr) auto; gap:2px var(--e3);
               grid-template-areas:"quien cifra" "barra barra" }
  .barra-fila > span:first-child{ grid-area:quien }
  .barra-fila .barra{ grid-area:barra; height:16px }
  .barra-fila .cifra-barra{ grid-area:cifra }

  /* ── el año, en FILAS y no en columnas ──────────────────────────────────
     Doce columnas de 24 px no dicen nada; doce filas de 44 sí. La pieza es
     LA MISMA que en escritorio —los mismos tramos, las mismas clases
     `alto-N` que escribe el PHP—, solo que aquí `alto-N` se lee como ANCHO:
     la barra de cada mes mide su total contra el mes más cargado, y dentro
     van los cuatro tramos de siempre. La fila entera sigue siendo el enlace
     a su mes. */
  .anio-mes-a-mes{ display:flex; flex-direction:column; gap:2px }
  .mes-del-anio{ display:grid;
                 grid-template-columns:38px minmax(0,1fr) auto;
                 grid-template-areas:"rotulo pila cifra" "hueco falta falta";
                 align-items:center; gap:2px var(--e3);
                 min-height:44px; padding:var(--e1) var(--e2) }
  .mes-del-anio .rotulo-mes{ grid-area:rotulo; text-align:left }
  .mes-del-anio .pila{ grid-area:pila; height:16px; width:100%;
                       align-items:stretch; justify-content:flex-start;
                       background:var(--superficie); border-radius:var(--r) }
  .mes-del-anio .columna-mes{ flex-direction:row; max-width:none; height:100%;
                              min-height:0; border-radius:var(--r) }
  .mes-del-anio .columna-mes i{ min-height:0; min-width:2px; height:100% }
  .mes-del-anio .cifra-mes{ grid-area:cifra; font-size:var(--t-apoyo) }
  .mes-del-anio .falta-mes{ grid-area:falta; text-align:left }
  /* `alto-N` como anchura, SOLO dentro de este gráfico y solo en el teléfono.
     Pisa tanto la columna del mes como sus tramos; la altura la devuelve a
     100 % la pareja de reglas de arriba, que pesa más. */
  .anio-mes-a-mes .alto-0{ width:0 }
  .anio-mes-a-mes .alto-5{ width:5% }    .anio-mes-a-mes .alto-10{ width:10% }
  .anio-mes-a-mes .alto-15{ width:15% }  .anio-mes-a-mes .alto-20{ width:20% }
  .anio-mes-a-mes .alto-25{ width:25% }  .anio-mes-a-mes .alto-30{ width:30% }
  .anio-mes-a-mes .alto-35{ width:35% }  .anio-mes-a-mes .alto-40{ width:40% }
  .anio-mes-a-mes .alto-45{ width:45% }  .anio-mes-a-mes .alto-50{ width:50% }
  .anio-mes-a-mes .alto-55{ width:55% }  .anio-mes-a-mes .alto-60{ width:60% }
  .anio-mes-a-mes .alto-65{ width:65% }  .anio-mes-a-mes .alto-70{ width:70% }
  .anio-mes-a-mes .alto-75{ width:75% }  .anio-mes-a-mes .alto-80{ width:80% }
  .anio-mes-a-mes .alto-85{ width:85% }  .anio-mes-a-mes .alto-90{ width:90% }
  .anio-mes-a-mes .alto-95{ width:95% }  .anio-mes-a-mes .alto-100{ width:100% }

  /* ── qué modelos lleva cada uno: la tabla se va, entra la lista ──────────
     La rejilla mide 2.172 px: en un marco de 350 se ve un 16 % de cada
     pasada y la cabecera de modelos queda siempre fuera. En el teléfono la
     misma pregunta —«de qué está hecho el trabajo de cada uno»— la contesta
     mejor una fila por persona con sus modelos ordenados de más a menos. */
  .reparto-modelos{ display:none }
  .reparto-movil{ display:flex; flex-direction:column; gap:var(--e3) }
  .solo-escritorio{ display:none }
  .solo-estrecho{ display:block }
}

/* ── movimiento ──────────────────────────────────────────────────────────── */
/* Aquí vivió el corte de 560 px, que existía solo para encoger las DOCE
   columnas del gráfico del año. Desde el 24/08 en el teléfono el año son
   FILAS (ver el bloque de 900), así que las columnas estrechas ya no ocurren
   y aquellas reglas —que además escondían «sin presentar» a quien no usa
   lector de pantalla— pisaban a las nuevas por venir después en el fichero. */

/* ── los dos desplegables de la ficha de un pedido, con transición (29/08) ─
   Fabio: «los desplegables de otras acciones y qué le ha pasado a este pedido
   tienen que tener una animación suave de despliegue». Los demás desplegables
   del módulo —la ficha de una fila, el panel de alta— ya la tienen: son un
   `.desplegable` con la transición sobre `grid-template-rows`. Estos dos son
   `<details>` de verdad, y un `<details>` no se puede animar a mano sin
   convertirlo en un `<div>` con guion, que es cambiar un mando que el navegador
   ya sabe abrir con el teclado y anunciar a un lector de pantalla.

   Lo que sí se puede es animar `::details-content`, que es lo que el navegador
   pone alrededor de lo que hay dentro. Hacen falta dos cosas:

     · `interpolate-size: allow-keywords`, sin lo cual `auto` no interpola y la
       transición no hace nada (no falla: no se ve);
     · `content-visibility` con `allow-discrete`, para que lo de dentro siga
       estando durante los 200 ms de la salida — sin eso desaparece en el
       primer fotograma y solo se anima el cierre del hueco, que se ve peor que
       no animar nada.

   Todo dentro de un `@supports`: donde no exista `::details-content`, el
   `<details>` abre de golpe, que es exactamente lo que hacía hasta hoy. Y la
   duración es `--mov-normal`, la misma que el resto de lo que cambia de tamaño;
   `prefers-reduced-motion` la deja en nada con la regla de aquí abajo. */
@supports (interpolate-size: allow-keywords) and (selector(::details-content)){
  .mas-detalles{ interpolate-size:allow-keywords }
  .mas-detalles::details-content{
    block-size:0; overflow:clip;
    transition:block-size var(--mov-normal) var(--curva),
               content-visibility var(--mov-normal) allow-discrete;
  }
  .mas-detalles[open]::details-content{ block-size:auto }
}

@media (prefers-reduced-motion: reduce){
  *{ animation-duration:.01ms !important; transition-duration:.01ms !important }
}

/* ═══════════════════════════════════════════════════════════════════════════
   S9 · las dos portadas, Mi cuenta y Actividad
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── el recuadro de un módulo («widget») ──────────────────────────────────
   La única pieza nueva de S9. Todo lo demás de esas pantallas son piezas que ya
   existían (.bloque, .lista, .kpi, .tabla, .estado).

   `auto-fill` y no `auto-fit`, por lo mismo que la rejilla de aplicaciones de
   S8: con un solo recuadro, `auto-fit` lo estira a lo ancho de la pantalla y un
   cliente con un módulo vería una tarjeta de 1.100 px que no se parece a nada
   del resto del sitio. */
.widgets{ display:grid; gap:var(--e4); align-items:start;
          grid-template-columns:repeat(auto-fill, minmax(330px,1fr)) }
.widget{ padding:var(--e5); display:flex; flex-direction:column; gap:var(--e3) }
.widget > .cabeza{ display:flex; align-items:center; gap:var(--e2);
                   padding-bottom:var(--e2);
                   border-bottom:var(--f-agrupa) solid var(--tinta) }
.widget > .cabeza > .icono{ width:26px; height:26px; flex:none; border-radius:var(--r);
                            display:grid; place-items:center;
                            background:var(--chip-fondo); color:var(--chip-texto);
                            border:var(--f-separa) solid var(--chip-filete) }
.widget > .cabeza > .icono svg{ width:15px; height:15px; stroke:currentColor; stroke-width:1.7;
                                fill:none; stroke-linecap:round; stroke-linejoin:round }
.widget > .cabeza h3{ font-size:15px; font-weight:var(--p-fuerte); letter-spacing:-.01em }
.widget > .cabeza .cuando{ font-size:var(--t-micro); color:var(--tinta-2);
                           text-transform:uppercase; letter-spacing:.06em }
.widget > .cabeza .ver{ margin-left:auto; font-size:var(--t-apoyo); white-space:nowrap }

/* Las cifras van con la MISMA clave de color que el cuadro de mando del módulo
   (S5.1): un «pendiente» que aquí fuera de otro color obligaría a aprenderse
   dos leyendas para el mismo dato. */
.cifras{ display:flex; flex-wrap:wrap; gap:var(--e5) }
.cifras > div{ min-width:66px }
.cifras .n{ font-family:var(--f-dato); font-size:28px; font-weight:var(--p-fuerte);
            line-height:1; letter-spacing:-.02em; font-variant-numeric:tabular-nums }
.cifras .q{ margin-top:4px; font-size:var(--t-micro); color:var(--tinta-2);
            text-transform:uppercase; letter-spacing:.06em; display:flex; align-items:center }
.cifras .n.ojo{ color:var(--error) }

/* La frase del pie: lo que hay que hacer, en llano. Es lo que convierte cuatro
   números en algo que se entiende sin mirarlos. */
.frase{ font-size:var(--t-apoyo); color:var(--tinta-2) }
.frase b{ color:var(--tinta); font-weight:var(--p-fuerte) }
.widget .acciones{ display:flex; flex-wrap:wrap; gap:var(--e2); margin-top:auto }
.widget .acciones .boton.ancho{ flex:1 1 100% }
.widget .barra{ width:100% }
/* La lista que algunos módulos meten dentro de su recuadro: un .bloque dentro
   de otro .bloque. Solo hace falta despegarla un poco; el filete ya separa. */
.widget .lista{ margin-top:var(--e1) }

/* El recuadro que pide mirada. Mismo tratamiento que `.kpi.mirar-esto`: filete
   grueso a la izquierda y fondo de resalte, nunca un color de estado de fondo
   entero — eso grita, y a la tercera visita se ignora. */
/* El recuadro de un módulo va SIEMPRE sobre el azul de resalte (Fabio,
   29/08/2026). El azul lo pone `.de-modulo` y no `.mirar-esto` a propósito: son
   dos cosas distintas y antes iban juntas. Con las dos pegadas, Obligaciones
   salía teñida y Pedidos no —porque ese día no tenía nada atascado—, y la
   portada cambiaba de forma según el día sin que nadie hubiera cambiado nada.
   Ahora el azul dice «esto es un módulo tuyo» (verdad siempre) y el filete de la
   izquierda sigue diciendo «hoy mira esto» (verdad a ratos). */
.widget.de-modulo{ background:var(--resalte-suave) }
.widget.mirar-esto{ border-left:var(--f-cierra) solid var(--resalte);
                    background:var(--resalte-suave) }

/* ── el Inicio en dos columnas ────────────────────────────────────────────
   Lo de trabajar delante, lo de consultar al lado. */
.carril{ display:grid; gap:var(--e4); align-items:start;
         grid-template-columns:minmax(0,2.1fr) minmax(300px,1fr) }
.carril > div{ display:flex; flex-direction:column; gap:var(--e4); min-width:0 }

/* ── el saludo ───────────────────────────────────────────────────────────── */
.saludo{ display:flex; align-items:baseline; gap:var(--e3); flex-wrap:wrap }
.saludo h1{ font-size:var(--t-titulo); font-weight:var(--p-fuerte); letter-spacing:-.015em }
.saludo .fecha{ font-size:var(--t-apoyo); color:var(--tinta-2) }

/* ── el aviso nuestro («el viernes hay mantenimiento») ───────────────────── */
.aviso-casa{ display:flex; gap:var(--e3); align-items:flex-start;
             padding:var(--e3) var(--e5);
             border-left:var(--f-cierra) solid var(--info) }
.aviso-casa > .icono svg{ width:18px; height:18px; stroke:var(--info); stroke-width:1.7;
                          fill:none; stroke-linecap:round; stroke-linejoin:round;
                          margin-top:2px }
.aviso-casa h4{ font-size:var(--t-cuerpo); font-weight:var(--p-fuerte) }
.aviso-casa p{ margin-top:2px; font-size:var(--t-apoyo); color:var(--tinta-2) }
.aviso-casa .cerrar{ margin-left:auto }
.aviso-casa.atencion{ border-left-color:var(--aviso) }
.aviso-casa.atencion > .icono svg{ stroke:var(--aviso) }

/* ── la bandeja de «hay que tocar esto» ──────────────────────────────────── */
.bandeja .fila .de-donde{ font-size:var(--t-micro); color:var(--tinta-2);
                          text-transform:uppercase; letter-spacing:.06em }
.bandeja .fila .cuando{ font-size:var(--t-apoyo); color:var(--tinta-2); white-space:nowrap }
.bandeja .fila .punto{ width:8px; height:8px; flex:none; border-radius:50%;
                       background:var(--aviso-relleno) }
.bandeja .fila .punto.urge{ background:var(--error-relleno) }
.bandeja .fila .punto.tranquilo{ background:var(--exito-relleno) }

/* ── los contadores-filtro de Actividad ──────────────────────────────────
   Son el resumen Y el filtro. Dos piezas que dicen lo mismo —un resumen arriba
   y una barra de filtros debajo— es la manera más rápida de que la segunda se
   quede sin actualizar. */
.contadores{ display:flex; flex-wrap:wrap; gap:var(--e2) }
.contadores a{ display:inline-flex; align-items:center; gap:var(--e2);
               padding:6px var(--e3); border-radius:var(--r);
               border:var(--f-separa) solid var(--filete);
               background:var(--papel); color:var(--tinta-2);
               font-size:var(--t-apoyo); text-decoration:none }
.contadores a:hover{ border-color:var(--filete-fuerte); color:var(--tinta) }
.contadores a b{ font-family:var(--f-dato); font-weight:var(--p-fuerte); color:var(--tinta) }
.contadores a[aria-current="true"]{ background:var(--activo-fondo); color:var(--activo-texto);
                                    border-color:var(--activo-filete) }
.contadores a[aria-current="true"] b{ color:var(--activo-texto) }

/* ── Mi cuenta ───────────────────────────────────────────────────────────── */
.dato-fila{ display:flex; align-items:center; gap:var(--e4); padding:var(--e3) 0;
            border-top:var(--f-separa) solid var(--filete); flex-wrap:wrap }
.dato-fila:first-of-type{ border-top:0 }
.dato-fila .que{ width:190px; flex:none; font-size:var(--t-apoyo); color:var(--tinta-2) }
.dato-fila .valor{ font-weight:var(--p-fuerte); min-width:0; overflow-wrap:anywhere }
.dato-fila .acciones{ margin-left:auto; display:flex; gap:var(--e2) }

/* Los pasos del segundo factor. Numerados de verdad (<ol>): el orden no es
   decoración, es lo que impide guardar los códigos de rescate antes de
   comprobar que el de la aplicación funciona. */
.pasos-2fa{ display:grid; gap:var(--e4); grid-template-columns:repeat(auto-fit,minmax(260px,1fr));
            counter-reset:paso; margin:0; padding:0 }
.pasos-2fa > li{ list-style:none; padding:var(--e5); background:var(--papel);
                 border:var(--f-separa) solid var(--filete) }
.pasos-2fa > li::before{ counter-increment:paso; content:counter(paso);
                         display:grid; place-items:center; width:24px; height:24px;
                         border-radius:var(--r); background:var(--tinta); color:var(--papel);
                         font-family:var(--f-dato); font-size:var(--t-micro);
                         font-weight:var(--p-fuerte) }
.pasos-2fa h4{ margin-top:var(--e3); font-size:var(--t-cuerpo); font-weight:var(--p-fuerte) }
.pasos-2fa p{ margin-top:var(--e2); font-size:var(--t-apoyo); color:var(--tinta-2) }
.clave-2fa{ margin-top:var(--e3); padding:var(--e2) var(--e3); display:inline-block;
            font-family:var(--f-dato); font-size:15px; letter-spacing:.08em;
            background:var(--superficie); border:var(--f-separa) solid var(--filete);
            overflow-wrap:anywhere }
.codigos-rescate{ margin-top:var(--e3); display:grid; grid-template-columns:1fr 1fr;
                  gap:var(--e2); font-family:var(--f-dato); font-size:var(--t-apoyo) }
.codigos-rescate span{ padding:4px var(--e2); background:var(--superficie);
                       border:var(--f-separa) solid var(--filete); text-align:center }
.codigos-rescate span.gastado{ color:var(--tinta-2); text-decoration:line-through }

/* ── anchos de las tablas nuevas ──────────────────────────────────────────
   Una línea por tabla y todas juntas, igual que las de arriba: separadas, se
   desalinean la primera vez que alguien toque una sola. */
.tabla.actividad     { --cols: 138px minmax(150px,1.4fr) minmax(130px,1.1fr) minmax(180px,2fr) 116px }
.tabla.actividad-cli { --cols: 138px minmax(150px,1.4fr) minmax(130px,1.1fr) minmax(180px,2fr) }
.tabla.sesiones      { --cols: minmax(180px,1.8fr) minmax(130px,1.2fr) 132px 108px }
.tabla.panel-clientes{ --cols: minmax(160px,1.6fr) 84px 84px 108px 124px 92px }
.tabla.avisos-panel  { --cols: minmax(200px,2.4fr) minmax(120px,1.1fr) 132px minmax(120px,1fr) 92px }

/* ── el corte de las portadas ────────────────────────────────────────────
   Por debajo de 900 px el carril cae debajo de la columna y todo pasa a una
   sola, que es lo que ya hacen las demás rejillas del sitio. */
@media (max-width: 900px){
  .carril{ grid-template-columns:minmax(0,1fr) }
  .widgets{ grid-template-columns:minmax(0,1fr) }
  .dato-fila .que{ width:auto; flex:1 1 100% }
  .dato-fila .acciones{ margin-left:0 }
  /* Los dos enlaces que más se tocan en estas pantallas medían 17 y 28 px
     de alto: el «Ver …» de la cabecera de un recuadro y los contadores-filtro
     de Actividad. Al dedo, 44 (24/08). */
  .widget > .cabeza .ver{ display:inline-flex; align-items:center; min-height:44px }
  .contadores a{ min-height:44px }
}

/* El aviso de guardado, en su versión de error. Mismo tamaño y mismo sitio que
   el de «guardado»: si el error saliera más grande o en otro lado, la pantalla
   daría un salto justo cuando alguien acaba de equivocarse. */
.aviso-guardado.problema{ color:var(--error); background:var(--error-fondo) }

/* La fila de Mi cuenta que lleva un campo dentro. `.crece` no vale aquí: en
   este sistema esa clase es del armazón de viewport fijo y significa otra cosa
   (§ el armazón). */
.dato-fila .con-campo{ flex:1 1 240px; max-width:420px }
.dato-fila .con-campo input{ width:100% }
.dato-fila .frase{ display:block; margin-top:2px }

/* ── el KPI que además es un enlace (S9, 22/08) ───────────────────────────
   Cada cifra de la portada del panel lleva a su lista ya filtrada. Mismo trato
   que `a.mini` en el portal: el bloque entero es la zona de pulsar, y lo que se
   subraya al pasar por encima es el rótulo, no la cifra — subrayar un número
   grande lo hace parecer tachado. */
a.kpi{ color:inherit; text-decoration:none; display:block }
a.kpi:hover{ background:var(--fila-hover) }
a.kpi.mirar-esto:hover{ background:var(--resalte-suave) }
a.kpi:hover .grupo{ text-decoration:underline; text-underline-offset:3px }

/* Lo que dijo la última pasada de la noche, al lado de su hora. Va en la fuente
   de datos y pequeño: es una frase que escribe un cron, no una etiqueta. */
.cuenta-pasada{ display:block; margin-top:2px; font-family:var(--f-dato);
                font-size:var(--t-micro); color:var(--tinta-2) }

/* ── los accesos directos a las aplicaciones (S9, 22/08) ──────────────────
   Un botón por aplicación en marcha, dentro del recuadro del carril. Con esto,
   abrir SmartAudit deja de ser «Inicio → Aplicaciones → buscarla → Abrir».

   Rejilla que se dobla sola y NO un carrusel: un carrusel esconde la mitad de
   lo que tiene y obliga a pulsar una flecha para saber qué hay. Con cuatro o
   cinco aplicaciones eso es esconder para no ocupar dos filas. */
.accesos-apps{ display:grid; gap:var(--e2);
               grid-template-columns:repeat(auto-fill, minmax(88px, 1fr)) }
.acceso-app{ position:relative; display:flex; flex-direction:column; align-items:center;
             gap:6px; padding:var(--e3) 6px; text-align:center;
             border:var(--f-separa) solid var(--filete); border-radius:var(--r);
             background:var(--papel); color:var(--tinta); text-decoration:none }
.acceso-app:hover{ background:var(--fila-hover); border-color:var(--filete-fuerte);
                   text-decoration:none }
.acceso-app:hover .nombre{ color:var(--tinta) }
.acceso-app > .icono{ width:32px; height:32px; display:grid; place-items:center;
                      border-radius:var(--r); background:var(--chip-fondo);
                      color:var(--chip-texto);
                      border:var(--f-separa) solid var(--chip-filete) }
.acceso-app > .icono svg{ width:17px; height:17px; stroke:currentColor; stroke-width:1.7;
                          fill:none; stroke-linecap:round; stroke-linejoin:round }
.acceso-app > .icono .logo-app{ width:20px; height:20px }
/* El nombre, a dos líneas como mucho. Cortado a una, «Obligaciones fiscales» y
   «Obligaciones mercantiles» serían el mismo botón. */
.acceso-app .nombre{ font-size:var(--t-micro); line-height:1.25; color:var(--tinta-2);
                     display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
                     overflow:hidden; overflow-wrap:anywhere }
/* La marca de «se abre fuera» o «se descarga», en la esquina. Pequeña a
   propósito: dice qué va a pasar al pulsar sin competir con el dibujo. */
.acceso-app .fuera{ position:absolute; top:4px; right:4px; line-height:0 }
.acceso-app .fuera svg{ width:11px; height:11px; stroke:var(--tinta-2); stroke-width:2;
                        fill:none; stroke-linecap:round; stroke-linejoin:round }
.acceso-app.mas > .icono{ font-family:var(--f-dato); font-weight:var(--p-fuerte);
                          font-size:13px; background:var(--superficie);
                          color:var(--tinta-2) }

/* ── la fila de una sesión abierta (S9, 22/08) ────────────────────────────
   La marca «esta» va al lado del dispositivo, no debajo y no de lado a lado.
   `.celda-principal` apila en columna porque está pensada para un nombre con su
   sublínea; aquí lo que hay es un nombre y una etiqueta. */
.tabla.sesiones .celda-principal{ flex-direction:row; align-items:center; gap:var(--e2);
                                  flex-wrap:wrap }
.tabla.sesiones .celda-principal .etiqueta{ flex:none }


/* ═══════════════════════════════════════════════════════════════════════════
   LAS PASADAS DEL CRON (S10, 22/08/2026)

   La pantalla contesta «¿va bien?» antes que «¿qué pasó?», y de ahí salen las
   dos piezas nuevas: la tira de días y el gráfico de tiempos. Todo lo demás
   —.bloque, .tabla, .estado, .contadores, .desplegable— ya existía.
   ═══════════════════════════════════════════════════════════════════════════ */

/* El ancho de la tabla, en una línea y junto a los demás de arriba. */
.tabla.pasadas{ --cols: 116px minmax(130px,1.2fr) 112px minmax(180px,2.2fr) 76px 30px }

/* ── la cabecera de estado de cada tarea ────────────────────────────────────
   SIN `align-items:start`, y es lo que pidió Fabio el 22/08: «iguala los
   tamaños de las tarjetas, aunque una necesite más espacio que la otra». Con
   `start` cada una medía lo suyo y la fila quedaba con dos cajas de altos
   distintos —una con aviso de silencio y otra sin él— que se leen como dos
   cosas de importancia distinta cuando no lo son. El `stretch` que trae la
   rejilla por defecto las iguala solo, y de paso hace que abrir el «paso a
   paso» de una empuje a las dos a la vez.

   La consecuencia: el hueco sobrante cae DENTRO de la tarjeta corta. Por eso el
   «paso a paso» lleva `margin-top:auto` y se queda pegado abajo en todas, a la
   misma altura, en vez de dejar el aire debajo de él. */
.estados-cron{ display:grid; gap:var(--e4);
               grid-template-columns:repeat(auto-fill, minmax(420px,1fr)) }
.estado-cron{ padding:var(--e5); display:flex; flex-direction:column; gap:var(--e3) }
.estado-cron > .cabeza{ display:flex; align-items:center; gap:var(--e2);
                        padding-bottom:var(--e2);
                        border-bottom:var(--f-agrupa) solid var(--tinta) }
.estado-cron > .cabeza h3{ font-size:var(--t-cuerpo); font-weight:var(--p-fuerte) }
.estado-cron > .cabeza .horario{ margin-left:auto; font-family:var(--f-dato);
                                 font-size:var(--t-micro); color:var(--tinta-2) }
.estado-cron .veredicto-cron{ display:flex; align-items:baseline; gap:var(--e3);
                              flex-wrap:wrap }
.estado-cron .veredicto-cron .cifra{ font-size:26px; font-weight:var(--p-fuerte);
                                     letter-spacing:-.02em; line-height:1.1 }
/* Un filete de 3px a la izquierda cuando algo pide mirada. La misma gramática
   que `.kpi.mirar-esto` y que el recuadro de módulo de S9: el resalte es el
   GROSOR del filete, no un fondo de color. */
.estado-cron.mirar-esto{ border-left:var(--f-cierra) solid var(--resalte) }

/* Los titulares: «2 de 2 · copias de seguridad». Lo que se lee sin desplegar
   nada, y lo que Fabio pidió que se viera de un vistazo. En rejilla y no en
   línea seguida para que la segunda cifra caiga siempre en el mismo sitio: una
   fila que se reordena según lo que quepa hay que leerla en vez de mirarla. */
.titulares-cron{ display:grid; gap:var(--e2) var(--e4);
                 grid-template-columns:repeat(auto-fit, minmax(210px,1fr)) }
.titulares-cron > div{ display:flex; align-items:baseline; gap:var(--e2); min-width:0 }
/* El chip NO se parte. Se vio mirando: con SharePoint sin configurar, «sin
   configurar» caía en dos líneas y arrastraba al rótulo, y la fila de titulares
   —que existe para leerse de un vistazo— pasaba a tener tres alturas distintas.
   El que puede envolver es el rótulo, que es texto corrido. */
.titulares-cron .estado{ flex:none; white-space:nowrap }
.titulares-cron .que{ font-size:var(--t-apoyo); color:var(--tinta-2); min-width:0 }

/* El mando de «qué hace, paso a paso». `margin-top:auto` lo pega abajo: es lo
   que hace que en dos tarjetas de contenido distinto el botón caiga a la misma
   altura. El PANEL no está aquí dentro — ver `.pasos-de-la-tarea`. */
.estado-cron > .pasos-cron{ margin-top:auto; padding-top:var(--e3);
                            border-top:var(--f-separa) solid var(--filete) }

/* El panel, debajo de la rejilla y a todo lo ancho. Usa `.desplegable` (S8.1),
   que ya trae la animación y el guion que lo abre y lo cierra.

   A lo ancho y no dentro de la tarjeta por dos cosas que se vieron mirando la
   pantalla: dentro estiraba la fila y dejaba a la tarjeta de al lado con medio
   palmo de hueco vacío, y aquí la lista cabe en columnas y ocupa un tercio. Con
   ocho tareas sigue siendo UN panel, no ocho. */
/* Cerrado, el envoltorio mide cero pero sigue cobrando su hueco del `gap` de la
   columna, y entre las tarjetas y la leyenda quedaba un aire que nadie ha
   puesto. Se anula con un margen negativo del tamaño de ese hueco.

   ⚠️ Y NO con `display:none`, que fue lo primero que se probó: el guion que
   abre el panel mide el contenido para animarlo, y un contenido oculto mide
   CERO — el panel se abría a 0 px de alto y no se veía nada. No daba ningún
   error: la clase `.abierta` se ponía, el HTML era correcto y la animación
   corría de cero a cero. Se cazó midiendo el alto después de pulsar.

   `:has` y no una clase puesta por el guion, para que valga igual con el panel
   abierto desde el servidor (`?pasos=…`) y sin JavaScript. */
.paneles-pasos{ display:grid; gap:0 }
.paneles-pasos:not(:has(.abierta)){ margin-top:calc(var(--e4) * -1) }
.pasos-de-la-tarea > .dentro > .ficha{ padding:var(--e5) }
.cabeza-pasos{ display:flex; align-items:baseline; gap:var(--e3); flex-wrap:wrap;
               padding-bottom:var(--e3); margin-bottom:var(--e4);
               border-bottom:var(--f-agrupa) solid var(--tinta) }
.cabeza-pasos h3{ font-size:var(--t-cuerpo); font-weight:var(--p-fuerte) }
.cabeza-pasos .apagado{ font-family:var(--f-dato); font-size:var(--t-micro) }
.cabeza-pasos > a{ margin-left:auto; align-self:center }

/* En columnas cuando hay sitio, y en una sola cuando no. Un paso NUNCA se parte
   entre dos columnas (`break-inside`): media explicación al pie de una columna
   y la otra media arriba de la siguiente se lee como dos pasos distintos. */
.lista-pasos{ counter-reset:paso; margin:0; padding:0;
              columns:3 300px; column-gap:var(--e6) }
.lista-pasos > li{ break-inside:avoid; margin-bottom:var(--e3) }
/* Numerados de verdad (`<ol>`) porque el ORDEN es parte de lo que se explica:
   que «mirar si hay hueco» sea el paso 1 es lo único que hace que ese vigilante
   sirva de algo. La numeración se pinta a mano para que el número quede en una
   pastilla y no en el margen, donde se pierde. */
.lista-pasos > li{ list-style:none; display:grid; gap:2px var(--e3);
                   grid-template-columns:22px minmax(0,1fr) }
.lista-pasos > li::before{ counter-increment:paso; content:counter(paso);
                           grid-row:span 2; display:grid; place-items:center;
                           width:22px; height:22px; border-radius:var(--r);
                           background:var(--tinta); color:var(--papel);
                           font-family:var(--f-dato); font-size:var(--t-micro);
                           font-weight:var(--p-fuerte) }
.lista-pasos > li b{ font-size:var(--t-apoyo); font-weight:var(--p-fuerte);
                     align-self:center }
.lista-pasos > li span{ font-size:var(--t-apoyo); color:var(--tinta-2) }

/* La tarjeta encogida: la de una tarea que va bien cuando hay muchas. NO se
   esconde nada que sea urgente —el resultado, los titulares y la tira siguen—,
   solo se va el gráfico de tiempos, que se puede mirar más tarde. */
.estado-cron.compacta{ padding:var(--e4) var(--e5) }

/* ── la tira de días ───────────────────────────────────────────────────────
   Un cuadradito por día, el más viejo a la izquierda. Es la ÚNICA pieza de la
   pantalla que enseña una ausencia: dos noches que no corrieron son dos filas
   que no están en la tabla, y lo que no está no se mira.

   Son seis estados y no dos, porque «no hay fila» no significa lo mismo en los
   dos cron: el de avisos no corre los sábados, así que un sábado en blanco es el
   calendario y no una avería. Pintarlos igual serían ocho falsas alarmas al mes,
   y a la tercera se deja de mirar la tira entera. */
.tira-noches{ display:flex; flex-wrap:wrap; gap:3px }
.tira-noches i{ width:11px; height:22px; flex:none; border-radius:1px;
                background:var(--filete); border:1px solid transparent }
.tira-noches i.ok        { background:var(--exito-relleno) }
.tira-noches i.aviso     { background:var(--aviso-relleno) }
.tira-noches i.mal       { background:var(--error-relleno) }
.tira-noches i.abierta   { background:var(--aviso-relleno); border-color:var(--tinta) }
/* El borde va en `--marcador`, y esto se midió en los dos temas antes de
   elegirlo. Con `--filete` el cuadradito da 1,35:1 en oscuro —invisible—, y en
   la tira de los avisos son 13 de 30: un «no le tocaba» que no se ve deja la
   tira con huecos aparentes donde no los hay, justo lo contrario de lo que esta
   pieza existe para contar. Con `--filete-fuerte` pasa lo opuesto en claro:
   19,6:1, un borde casi negro que grita más que los verdes.

   `--marcador` da 3,01:1 en claro y 3,01:1 en oscuro —el umbral de los
   elementos de interfaz, clavado en los dos—, que es lo más callado que se
   puede ver. Comprobado con `getComputedStyle` en las dos luces. */
.tira-noches i.no-tocaba { background:var(--superficie); border-color:var(--marcador) }
/* El hueco NO se pinta de un color: se pinta vacío y rayado, porque no es un
   resultado — es la ausencia de uno. Un rojo liso diría «corrió y falló». */
.tira-noches i.hueco{ background:repeating-linear-gradient(135deg,
                        var(--error-relleno) 0 2px, transparent 2px 5px);
                      border-color:var(--error-relleno) }
.tira-noches i.hoy{ outline:2px solid var(--tinta); outline-offset:1px }

/* La leyenda usa `.clave-color`, que ya existe (cuadro de mando, S5.1). */
.leyenda.noches .clave-color.ok        { background:var(--exito-relleno) }
.leyenda.noches .clave-color.aviso     { background:var(--aviso-relleno) }
.leyenda.noches .clave-color.mal       { background:var(--error-relleno) }
.leyenda.noches .clave-color.abierta   { background:var(--aviso-relleno);
                                         border:1px solid var(--tinta) }
.leyenda.noches .clave-color.no-tocaba { background:var(--superficie);
                                         border:1px solid var(--marcador) }
.leyenda.noches .clave-color.hueco{ background:repeating-linear-gradient(135deg,
                                      var(--error-relleno) 0 2px, transparent 2px 5px);
                                    border:1px solid var(--error-relleno) }

/* ── cuánto tardó: barras en SVG, y no en CSS ─────────────────────────────
   ⚠️ No es una preferencia de estilo. La altura de cada barra es un dato
   distinto por barra, y la CSP manda `style-src 'self'` sin 'unsafe-inline'
   (comun/plantilla/cabecera.php): un `style="height:…"` se queda escrito en el
   HTML y NO se aplica, sin avisar. En un SVG, `height` e `y` son atributos de
   geometría y no pasan por CSS.

   ⚠️ Y por eso los `rect` NO llevan `class="barra"`: `.barra` ya existe más
   arriba en este mismo fichero —la barra apilada del cuadro de mando— con
   `height:14px` dentro, y en SVG el CSS le gana al atributo. Con esa clase,
   TODAS las barras salían de 14px sin un solo error. Se estilan por su sitio.

   Sin banda de fondo: una caja gris con las barras dentro convierte el hueco de
   arriba en la parte que más se ve. Lo que hay es una raya de base y la media. */
.tiempos{ width:100%; height:56px; display:block; color:var(--acc) }
.tiempos rect{ fill:currentColor }
.tiempos rect.pico{ fill:var(--error-relleno) }
.tiempos rect.suelo{ fill:var(--filete) }
.tiempos line{ stroke:var(--tinta-2); stroke-width:1; stroke-dasharray:3 3; fill:none }
.tiempos-pie{ display:flex; justify-content:space-between; gap:var(--e2);
              font-family:var(--f-dato); font-size:var(--t-micro); color:var(--tinta-2) }

/* ── el detalle de una pasada, desplegado bajo su fila ───────────────────── */
.parte-pasada{ display:grid; gap:var(--e4);
               grid-template-columns:minmax(0,1fr) minmax(0,1.05fr) }
.parte-pasada h4{ font-size:var(--t-micro); font-weight:var(--p-fuerte);
                  text-transform:uppercase; letter-spacing:.07em; color:var(--tinta-2) }
.cifras-pasada{ margin-top:var(--e2); display:grid; gap:0 var(--e4);
                grid-template-columns:repeat(auto-fill, minmax(150px,1fr)) }
.cifras-pasada > div{ display:flex; align-items:baseline; gap:var(--e2);
                      padding:5px 0; border-top:var(--f-separa) solid var(--filete);
                      min-width:0 }
.cifras-pasada b{ font-family:var(--f-dato); font-weight:var(--p-fuerte);
                  font-size:var(--t-cuerpo); flex:none }
.cifras-pasada b.entregada{ color:var(--exito) }
.cifras-pasada b.pendiente{ color:var(--aviso) }
.cifras-pasada b.problema { color:var(--error) }
.cifras-pasada span{ font-size:var(--t-apoyo); color:var(--tinta-2); min-width:0 }
.parte-pasada .frase{ margin-top:var(--e3) }

/* El error, entero. `pre-wrap` y no `pre`: un mensaje de PDO de 400 caracteres
   en una sola línea saca una barra de desplazamiento a la pantalla entera, que
   es la trampa que ya costó los cuatro scrolls de S5.1. */
.error-pasada{ margin-top:var(--e2); padding:var(--e3); background:var(--error-fondo);
               border:var(--f-separa) solid var(--error); border-radius:var(--r);
               font-family:var(--f-dato); font-size:var(--t-micro); color:var(--error);
               white-space:pre-wrap; overflow-wrap:anywhere;
               max-height:190px; overflow:auto }
.sin-error{ margin-top:var(--e2); padding:var(--e3); background:var(--superficie);
            border:var(--f-separa) solid var(--filete); border-radius:var(--r);
            font-size:var(--t-apoyo); color:var(--tinta-2) }

@media (max-width: 900px){
  .parte-pasada{ grid-template-columns:minmax(0,1fr) }
  .estados-cron{ grid-template-columns:minmax(0,1fr) }
}

