/* Sistema tipográfico oficial "Clara y cálida". Las fuentes viven dentro de la aplicación:
   recepción no pierde legibilidad si se corta Internet y ninguna pantalla depende de un CDN.

   En WOFF2 y no en TTF, que es como estaban hasta el 03-08. El mismo archivo pesa entre un 60 %
   y un 74 % menos —2,1 MB de tipografías quedaron en 744 KB— porque WOFF2 trae la compresión
   Brotli adentro, y los ejes variables sobreviven intactos. El formato es de 2018 y no hay
   navegador en uso que no lo entienda, así que no queda un TTF de respaldo: sería peso muerto
   en el repositorio y una segunda copia que mantener sincronizada.

   Por venir ya comprimidos, estos archivos quedan fuera de `server.compression`: volver a
   comprimirlos gasta CPU del servidor para no ahorrar un byte. */
@font-face {
    font-family: "Nunito Sans";
    src: url("/fonts/nunito-sans-variable-abc455272596a9f52975ebdc73338d1c.woff2") format("woff2");
    font-style: normal;
    font-weight: 200 1000;
    font-stretch: 75% 125%;
    font-display: swap;
}

@font-face {
    font-family: "Nunito Sans";
    src: url("/fonts/nunito-sans-italic-variable-034231bc8baa7bdae0bf1aa829d88693.woff2") format("woff2");
    font-style: italic;
    font-weight: 200 1000;
    font-stretch: 75% 125%;
    font-display: swap;
}

@font-face {
    font-family: "Source Sans 3";
    src: url("/fonts/source-sans-3-variable-61db60cc19bc3d38ccc670fda4139fa4.woff2") format("woff2");
    font-style: normal;
    font-weight: 200 900;
    font-display: swap;
}

@font-face {
    font-family: "Source Sans 3";
    src: url("/fonts/source-sans-3-italic-variable-4419d63052fc56006f68d8aa299aa52d.woff2") format("woff2");
    font-style: italic;
    font-weight: 200 900;
    font-display: swap;
}

:root {
    /* Paleta oficial "Menta amable". Ver docs/identidad-visual.md. */
    color-scheme: light;
    --turquesa: #2aae91;
    --turquesa-profundo: #16745f;
    --sobre-turquesa: #102f2b;
    --rojo: #d95663;
    --rojo-profundo: #9d2f3e;
    --texto: #244643;
    --texto-tenue: #58716d;
    --fondo: #f7fbf5;
    --superficie: #ffffff;
    --barra: #ffffff;
    --campo: #ffffff;
    --menta-suave: #e1f2e8;
    --rojo-suave: #fceced;
    /* Ámbar de "revisar": lo que hay que mirar pero no es urgencia. Nació con la caja cerrada
       con diferencia —un faltante que el admin tiene que pescar entre las cuadradas verdes, y que
       el gris de "anulado" escondía—. Va entre el verde de "en orden" y el rojo de "ahora". Ver
       `.etiqueta.revisar`. */
    --ambar-suave: #fbeccb;
    --ambar-profundo: #8a5a12;
    --borde: #caddd8;
    --blanco: #ffffff;

    /* Tinta sobre papel. **No se redefinen en Grafito clínico, y eso es justamente el punto**: el
       membrete de una hoja se dibuja sobre blanco en los dos temas porque es lo único de la
       aplicación cuyo destino es la impresora. Ver `.hoja .membrete`. */
    --tinta-papel: #244643;
    --tinta-papel-tenue: #58716d;

    --fuente-marca: "Nunito Sans", system-ui, sans-serif;
    --fuente-interfaz: "Source Sans 3", system-ui, sans-serif;

    /* Tintas del símbolo. Van aparte de los tokens de interfaz a propósito: el logo no
       sigue al color de un botón, sigue a la marca. Ver "Uso en la aplicación" en
       docs/identidad-visual.md. */
    --marca-turquesa: #2aae91;
    --marca-tinta: #244643;
    --marca-rojo: #d95663;

    --sombra: 0 1px 2px rgba(36, 70, 67, 0.06);
}

/* "Grafito clínico": modo oscuro oficial. Puede forzarse con data-tema="oscuro". */
:root[data-tema="oscuro"] {
    color-scheme: dark;
    --turquesa: #55cbb2;
    --turquesa-profundo: #70dbc3;
    --sobre-turquesa: #102e29;
    --rojo: #f2737d;
    --rojo-profundo: #ff9ba4;
    --texto: #f1f6f4;
    --texto-tenue: #b4c3bf;
    --fondo: #171c1c;
    --superficie: #222b2a;
    --barra: #1b2322;
    --campo: #1b2423;
    --menta-suave: #293b37;
    --rojo-suave: #3a2529;
    --ambar-suave: #3a3120;
    --ambar-profundo: #f2c879;
    --borde: #3a4947;

    --marca-turquesa: #55cbb2;
    --marca-tinta: #f1f6f4;
    --marca-rojo: #f2737d;

    --sombra: none;
}

@media (prefers-color-scheme: dark) {
    :root:not([data-tema="claro"]) {
        color-scheme: dark;
        --turquesa: #55cbb2;
        --turquesa-profundo: #70dbc3;
        --sobre-turquesa: #102e29;
        --rojo: #f2737d;
        --rojo-profundo: #ff9ba4;
        --texto: #f1f6f4;
        --texto-tenue: #b4c3bf;
        --fondo: #171c1c;
        --superficie: #222b2a;
        --barra: #1b2322;
        --campo: #1b2423;
        --menta-suave: #293b37;
        --rojo-suave: #3a2529;
        --ambar-suave: #3a3120;
        --ambar-profundo: #f2c879;
        --borde: #3a4947;

        --marca-turquesa: #55cbb2;
        --marca-tinta: #f1f6f4;
        --marca-rojo: #f2737d;

        --sombra: none;
    }
}

* { box-sizing: border-box; }

body {
    margin: 0;
    font-family: var(--fuente-interfaz);
    font-optical-sizing: auto;
    color: var(--texto);
    background: var(--fondo);
    line-height: 1.5;
}

main {
    max-width: 48rem;
    margin: 0 auto;
    padding: 2rem 1.25rem;
}

h1,
h2,
h3 {
    font-family: var(--fuente-marca);
}

h1 {
    color: var(--turquesa-profundo);
    margin-bottom: 0.25rem;
}

section {
    margin-top: 2rem;
    padding: 1.25rem;
    background: var(--superficie);
    border-radius: 0.5rem;
    border: 1px solid var(--borde);
    box-shadow: var(--sombra);
}

/* El margen propio del h2 se suma al padding de la sección y deja más aire arriba que a los
   lados. Se nota sobre todo cuando hay varias secciones seguidas, que es casi siempre. */
section > :first-child {
    margin-top: 0;
}

section > :last-child {
    margin-bottom: 0;
}

main.angosto {
    max-width: 24rem;
}

/* Los enlaces del contenido: sin esto quedan en el azul del navegador, que no es de la
   paleta y sobre Grafito clínico casi no se lee. */
a {
    color: var(--turquesa-profundo);
}

/* Un foco visible es lo que permite operar la pantalla con el teclado, y recepción cobra
   con las dos manos ocupadas. El anillo se dibuja separado del borde del campo para que
   se note también sobre los inputs. */
:focus-visible {
    outline: 2px solid var(--turquesa);
    outline-offset: 2px;
    border-radius: 0.2rem;
}

/* Nace fuera de la pantalla y baja al recibir el foco: quien navega con teclado lo
   encuentra en el primer tabulador, y quien usa el mouse no lo ve nunca. */
.saltar {
    position: absolute;
    top: -3rem;
    left: 0.75rem;
    z-index: 20;
    padding: 0.5rem 0.9rem;
    border-radius: 0 0 0.3rem 0.3rem;
    background: var(--turquesa);
    color: var(--sobre-turquesa);
    text-decoration: none;
    transition: top 0.12s ease;
}

.saltar:focus {
    top: 0;
}

/* El <main> recibe el foco al saltar, pero es un contenedor: dibujarle el anillo alrededor
   de toda la pantalla no señala nada. */
main:focus-visible {
    outline: none;
}

.barra {
    position: sticky;
    top: 0;
    z-index: 10;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    padding: 0.6rem 1.25rem;
    background: var(--barra);
    border-bottom: 1px solid var(--borde);
    font-size: 0.9rem;
}

/* El símbolo y el nombre son un solo enlace al inicio. Nunito Sans compone el nombre como
   logotipo tipográfico mientras se definen las composiciones horizontal y vertical. */
.marca {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-family: var(--fuente-marca);
    font-weight: 700;
    letter-spacing: 0.01em;
}

.marca svg {
    width: 1.75rem;
    height: 1.75rem;
    flex: none;
}

.barra .grupo {
    display: flex;
    align-items: center;
    gap: 1rem;
}

/* La luz de estado del servicio. Es un punto y no una etiqueta: la etiqueta pesa lo mismo que el
   nombre de la clínica y estaría encendida todo el día para decir que no pasa nada, que es como se
   aprende a no mirar justo lo que hay que mirar el día que se pone roja.

   **Es un punto y nada más que un punto desde el 02-09**: no hay `gap` ni `nowrap` porque no hay
   un segundo hijo en el flujo que separar —el único que queda es el texto invisible, y ese sale
   del flujo—. Hasta ese día el rojo y el amarillo agregaban un rótulo al lado, y en esta barra,
   que está en `space-between`, eso ensanchaba el enlace hacia la izquierda y **movía el punto que
   está latiendo** justo cuando cambia de color, que es el momento en que se lo está mirando. */
.luz {
    display: inline-flex;
    align-items: center;
}

.luz .punto {
    width: 0.6rem;
    height: 0.6rem;
    flex: none;
    border-radius: 50%;
    background: var(--turquesa);
    /* El halo late desde acá adentro, así que el punto tiene que ser su marco de referencia. */
    position: relative;
}

/* El latido, que es lo que separa una luz de una calcomanía.

   Un punto quieto no distingue «el servicio está sano» de «esta pestaña quedó abierta desde ayer y
   ya no habla con nadie»: los dos se ven exactamente igual, verdes y inmóviles. El latido es la
   única señal de que la página sigue viva, y además se reinicia solo: el fragmento vuelve entero
   cada minuto, así que el nodo se reemplaza y la animación arranca de nuevo con cada encuesta que
   sí llegó.

   Se anima `opacity` y `transform` y no el `box-shadow` del que salió la idea: las dos las resuelve
   el compositor sin repintar, y esto late todo el día en una barra que está en todas las pantallas.
   El color no se repite tres veces —`background: inherit` lo toma del propio punto—, así que el
   halo del rojo sale rojo y el del ámbar, ámbar, sin una regla por estado ni un literal.

   El descanso entre latidos es a propósito: el halo llega a su borde en el 72 % y el resto del
   ciclo se queda apagado. Sin esa pausa el punto pulsa sin parar y se lee como una alarma, que es
   justo lo contrario de lo que dice un verde. */
.luz .punto::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: inherit;
    animation: latido-de-la-luz 1.7s ease-out infinite;
    /* No intercepta el clic que abre la pantalla de estado, aunque crece por encima del punto. */
    pointer-events: none;
}

@keyframes latido-de-la-luz {
    0% {
        opacity: 0.55;
        transform: scale(1);
    }

    72%, 100% {
        opacity: 0;
        transform: scale(3.6);
    }
}

/* Quien pidió no ver animaciones sigue viendo la luz: lo que se va es el halo, no el estado. Es la
   misma decisión que la confirmación de más abajo, que se queda quieta en vez de desaparecer. */
@media (prefers-reduced-motion: reduce) {
    .luz .punto::after {
        animation: none;
        opacity: 0;
    }
}

/* Rojo y ámbar salen de los mismos tokens que las etiquetas, así que el modo oscuro los sube de
   luminosidad junto con el resto y el punto no queda apagado sobre el grafito. */
.luz .punto[data-estado="ROJO"] {
    background: var(--rojo);
}

.luz .punto[data-estado="AMARILLO"] {
    background: var(--ambar-profundo);
}

/* **Acá vivía `.luz .rotulo`, la segunda señal, y se sacó el 02-09 con su costo a la vista.** El
   argumento con que se escribió sigue siendo cierto: el color no puede ser la única señal, hay
   quien no distingue el rojo del verde y esta luz vive en una barra donde no hay nada al lado con
   qué compararla. Lo que lo movió es que el rótulo **desplazaba el punto** al aparecer —ver el
   comentario de `.luz`—, y esas dos cosas no se podían tener juntas en una barra de una línea.

   **La segunda señal no se eliminó, se mudó a `/cobros/estado`**, que es adonde lleva el clic en
   la propia luz: ahí el estado se dice con un mensaje escrito, en el color que corresponde, y con
   el espacio para decir además qué hacer. En la barra queda el color, y para quien no lo ve queda
   el texto invisible del fragmento, que no ocupa lugar. Quien vuelva a poner un rótulo acá va a
   reintroducir el salto: lo que hay que resolver primero es reservarle el espacio. */

/* En una pantalla angosta el nombre largo se parte en tres líneas y estira la barra sobre
   el contenido. Lo que se va es el rol: se deduce de lo que la pantalla deja hacer, mientras
   que el nombre es lo único que distingue una sesión de otra en un computador compartido. */
@media screen and (max-width: 40rem) {
    .barra {
        flex-wrap: wrap;
        row-gap: 0.4rem;
    }

    .barra .sesion {
        white-space: nowrap;
    }

    .barra .rol {
        display: none;
    }
}

label {
    display: block;
    margin-top: 0.9rem;
    font-size: 0.9rem;
}

/* En el computador compartido del mesón la contraseña puede comprobarse sin quedar expuesta
   después: el ojo vive dentro del campo y solo la muestra mientras el control sigue presionado.
   Sin prefijo `.login` a propósito: el mismo componente viste el login, los tres campos de
   "cambiar mi contraseña", la contraseña inicial del alta y el reseteo —la razón del mesón
   compartido vale igual en todos—, y el JS engancha por clase, no por pantalla. */
.contrasena-momentanea {
    position: relative;
}

.contrasena-momentanea input {
    padding-right: 3rem;
}

/* Sin fondo ni borde: heredado de `button`, el turquesa dibujaba un cuadrado que pesaba más que
   el campo mismo y competía con «Entrar», que es el único botón que la pantalla quiere ofrecer.
   La caja de 2.15rem se conserva aunque no se vea, porque es la que se puede apretar con el
   pulgar. */
.revelar-contrasena {
    position: absolute;
    right: 0.25rem;
    bottom: 0.25rem;
    display: grid;
    width: 2.15rem;
    height: 2.15rem;
    margin: 0;
    padding: 0.45rem;
    place-items: center;
    background: none;
    touch-action: manipulation;
    user-select: none;
}

.revelar-contrasena[hidden] {
    display: none;
}

/* El PNG entregado es blanco. Usarlo como máscara deja que el ojo tome la tinta del texto y no
   la suya, que es lo que lo mantiene legible sobre el campo en Menta amable y en Grafito
   clínico. Va en la tinta tenue: acompaña al campo, no lo encabeza. */
.icono-cateye {
    width: 100%;
    height: 100%;
    background: var(--texto-tenue);
    -webkit-mask: url("/img/interfaz/cateye.png") center / contain no-repeat;
    mask: url("/img/interfaz/cateye.png") center / contain no-repeat;
    pointer-events: none;
    transition: background-color 0.12s ease;
}

/* Sin fondo que oscurecer, el `brightness()` que `button` aplica al pasar y al apretar no cambia
   nada —y sobre el campo claro aclararía el ojo, que es al revés de lo que un hover debe hacer.
   La respuesta pasa a ser el color de la tinta. */
.revelar-contrasena:hover,
.revelar-contrasena:active {
    filter: none;
}

.revelar-contrasena:hover .icono-cateye {
    background: var(--texto);
}

/* Mientras la contraseña está a la vista el ojo se pone turquesa. Se cuelga del `type` del campo
   y no de `:active` a propósito: es el mismo estado que ve quien la reveló con la barra
   espaciadora, y `:active` con el teclado no es fiable entre navegadores. */
.contrasena-momentanea input[type="text"] + .revelar-contrasena .icono-cateye {
    background: var(--turquesa-profundo);
}

button {
    margin-top: 1.25rem;
    padding: 0.55rem 1.1rem;
    border: 0;
    border-radius: 0.3rem;
    background: var(--turquesa);
    color: var(--sobre-turquesa);
    font: inherit;
    cursor: pointer;
    transition: filter 0.12s ease, background-color 0.12s ease;
}

button:hover {
    filter: brightness(1.06);
}

button:active {
    filter: brightness(0.94);
}

/* Un botón apagado que se ve igual que uno vivo se clickea igual, y el usuario concluye que
   la pantalla no responde. Los hay: los formularios dentro de un fieldset deshabilitado. */
button:disabled,
button:disabled:hover {
    filter: none;
    opacity: 0.5;
    cursor: not-allowed;
}

/* El que está esperando al servidor se apaga menos, y no es un matiz: lleva escrito lo que está
   pasando —«Registrando cobro…», «Cerrando el periodo…»— y a la mitad de tinta esa frase es
   justamente la que no se alcanza a leer, que es la única señal de que la pantalla no se colgó.
   El cursor tampoco es el de "no se puede": se va a poder en cuanto conteste. Lo pone
   `gesto-en-curso.js` al apagar el botón; `aria-busy` es lo que separa este caso del botón que
   nunca se pudo apretar, como el de un fieldset apagado. */
button[aria-busy="true"]:disabled,
button[aria-busy="true"]:disabled:hover {
    opacity: 0.75;
    cursor: progress;
}

button.enlace {
    margin: 0;
    padding: 0;
    background: none;
    color: var(--turquesa-profundo);
    text-decoration: underline;
}

/* brightness() sobre una superficie casi blanca o sobre nada no cambia nada: el botón
   secundario y el de texto necesitan su propio hover o quedan sin respuesta al pasar. */
button.secundario:hover,
a.boton.secundario:hover {
    filter: none;
    background: var(--menta-suave);
}

button.enlace:hover {
    filter: none;
    color: var(--texto);
}

/* Anular es irreversible. Va en rojo desde antes de tocarlo, no después en un mensaje. */
button.enlace.riesgo {
    color: var(--rojo-profundo);
}

/* "Salir" es un botón porque cerrar sesión es un POST, pero en la barra es un enlace más:
   sin esto queda turquesa y subrayado entre cuatro enlaces que no lo están. */
.barra button.enlace {
    color: var(--texto);
    text-decoration: none;
}

.barra button.enlace:hover {
    color: var(--turquesa-profundo);
    text-decoration: underline;
}

/* ---------------------------------------------------------------------------
   Mensajes del sistema
   --------------------------------------------------------------------------- */

/* "Guardado." como línea suelta de texto se pierde: después de un POST la pantalla se
   vuelve a dibujar entera y el ojo va al formulario, no a un párrafo del mismo tamaño y
   peso que todo lo demás. El mensaje va en un cuadro con icono para que se lea primero.

   El icono se dibuja con una máscara y no con un <img> ni un <svg> en la plantilla: así
   toma el color del mensaje —turquesa o rojo, claro u oscuro— sin repetir el mismo bloque
   de marcado en las veintitantas pantallas que muestran uno.

   El relleno izquierdo lo hace `padding` y no `flex`, a propósito: varios mensajes traen
   un <strong> adentro, y en un contenedor flex ese <strong> se convertiría en columna
   aparte en vez de seguir el párrafo. */
.aviso,
.error {
    position: relative;
    margin: 1rem 0;
    padding: 0.7rem 0.9rem 0.7rem 2.5rem;
    border: 1px solid;
    border-radius: 0.5rem;
    animation: mensaje-aparece 0.2s ease-out;
}

.aviso::before,
.error::before {
    content: "";
    position: absolute;
    top: 0.78rem;
    left: 0.85rem;
    width: 1.15rem;
    height: 1.15rem;
    background-color: currentColor;
    -webkit-mask: var(--icono) center / contain no-repeat;
    mask: var(--icono) center / contain no-repeat;
}

.aviso {
    color: var(--turquesa-profundo);
    background: var(--menta-suave);
    border-color: var(--turquesa);
    --icono: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9.2'/%3E%3Cpath d='m7.7 12.3 3 3 5.6-6.3'/%3E%3C/svg%3E");
}

.error {
    color: var(--rojo-profundo);
    background: var(--rojo-suave);
    border-color: var(--rojo);
    --icono: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9.2'/%3E%3Cpath d='M12 7.3v5.3'/%3E%3Ccircle cx='12' cy='16.4' r='1.05' fill='black' stroke='none'/%3E%3C/svg%3E");
}

/* Mismo tono que el aviso, otro icono. Para un mensaje de post-acción hay dos colores de señal
   —menta y rojo— y un tercero inventado para "ojo con esto" diría menos de lo que ensuciaría; el
   visto y la i separan "quedó hecho" de "hay algo que saber" sin agregar color. Eso vale entero
   para lo que aparece después de apretar algo, que es binario: resultó o no resultó. */
.aviso.info {
    --icono: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='9.2'/%3E%3Cpath d='M12 11.3v5.3'/%3E%3Ccircle cx='12' cy='7.6' r='1.05' fill='black' stroke='none'/%3E%3C/svg%3E");
}

/* **El ámbar, que entró acá el 02-09 y no contradice lo de arriba: no es un mensaje de
   post-acción.** Nadie apretó nada; es un estado que la pantalla informa —la conexión de este
   computador va lenta, o no está llegando al servidor— y que se queda mientras dure. Para eso el
   ámbar ya era el registro oficial de la paleta desde el 18-08 —"mirar, pero ya ocurrió y no es
   urgencia"—, y por eso reusa el nombre de `.etiqueta.revisar` en vez de inventar uno: es el
   mismo criterio, en el otro componente.

   Lo trajo la luz de estado: al quitarle el rótulo al punto de la barra, lo que el punto ámbar
   significa tiene que poder decirse en `/cobros/estado`, y decirlo en menta sería decir que todo
   está bien con la luz encendida.

   El icono es un triángulo y no un tercer círculo a propósito: es la forma la que separa este
   cuadro de los otros dos cuando el color no se distingue, que es justo lo que la barra ya no
   puede ofrecer. */
.aviso.revisar {
    color: var(--ambar-profundo);
    background: var(--ambar-suave);
    border-color: var(--ambar-profundo);
    --icono: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 3.6 1.9 20.4h20.2z'/%3E%3Cpath d='M12 9.4v4.9'/%3E%3Ccircle cx='12' cy='17.6' r='1.05' fill='black' stroke='none'/%3E%3C/svg%3E");
}

/* El mensaje llega con la página ya cargada, no aparece mientras se mira: sin el
   desplazamiento corto no hay nada que delate que algo cambió en la pantalla. */
@keyframes mensaje-aparece {
    from {
        opacity: 0;
        transform: translateY(-0.3rem);
    }
}

.tenue {
    color: var(--texto-tenue);
}

/* Microchips, RUT, folios y códigos: se leen dígito a dígito y se comparan con lo que trae
   el tutor en un papel. Antes iban en la monoespaciada del sistema, que es una cuarta
   familia fuera del sistema tipográfico oficial; Source Sans 3 con cifras tabulares alinea
   igual las columnas y el espaciado extra basta para no perder el dígito. */
.mono {
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.04em;
}

/* Los 64 caracteres del SHA-256 que acredita un respaldo, que no traen un solo espacio donde
   cortarse. En pantalla no molesta y por eso vivió sin regla. Al imprimir la hoja del art. 5° sí:
   esa celda sola exigía 568 px y dejaba la tabla de solicitudes anteriores pidiendo 839 cuando
   las otras cinco se acomodaban en 409, así que el navegador encogía el documento entero para que
   cupiera. En A5 y en media carta la respuesta salía en 7,1 y 6,6 puntos —letra chica de contrato
   en el papel que se le entrega a una persona—. Es `anywhere` y no `break-word` porque sólo
   `anywhere` le baja el ancho mínimo a la celda, que es lo que hay que bajar: `break-word` parte
   la línea pero la tabla sigue reservando el ancho entero.

   Va en una clase propia y no en `.mono`, que comparte con microchips, RUT y folios: ésos se
   comparan dígito a dígito contra el papel que trae el tutor, y partirlos es exactamente lo que
   la regla de arriba existe para impedir. */
.huella {
    overflow-wrap: anywhere;
}

/* Un texto que se pegó tal cual y que la pantalla tiene que devolver tal cual: el contenido
   íntegro de lo que se le contestó a un titular del art. 11, que es lo que esa constancia
   acredita. Sin esto el correo pegado se muestra como un párrafo corrido —los saltos de línea
   de un texto legal se pierden en el HTML— y quien lo revisa no puede compararlo con lo que
   salió. `overflow-wrap` porque una URL larga pegada adentro arrastraba la sección de lado en
   un teléfono. */
.texto-pegado {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

/* La coincidencia dentro de un texto clínico, en la revisión humana de una supresión (O4c c3): dónde
   está el nombre que hay que quitar sin tener que leer la nota entera. Sin esta regla el navegador
   pinta su amarillo de fábrica con letra negra, que en el modo oscuro es una franja que no se lee.
   Ámbar y no rojo: marca lo que hay que mirar, no un error, y a veces es un apellido que se parece. */
mark {
    padding: 0 0.1em;
    border-radius: 0.2em;
    background: var(--ambar-suave);
    color: var(--ambar-profundo);
}

/* Las piezas de una mención, en la revisión del acceso (O6 a3a): cada pedazo del texto con su
   casilla, para que quien revisa deje fuera lo de otra persona sin teclear posiciones. Van **en línea
   y dentro del `.texto-pegado`**, no apiladas: lo que se decide es un fragmento leído en su contexto, y
   en una lista de casillas la frase se desarma y ya no se sabe de quién habla.

   El `fieldset` pierde su caja porque la caja ya la pone el candidato, y una segunda adentro se lee
   como si fueran dos registros. `min-width: 0` porque un `fieldset` no se encoge por debajo de su
   contenido y una nota larga arrastraba la sección de lado en un teléfono. */
.piezas-del-texto {
    min-width: 0;
    margin: 0;
    padding: 0;
    border: 0;
}

.piezas-del-texto label {
    display: inline;
    font-weight: inherit;
}

.piezas-del-texto input {
    width: auto;
    margin: 0 0.2em 0 0;
    vertical-align: middle;
}

.piezas-del-texto button.enlace {
    margin: 0 0.35em;
    font-size: 0.85em;
}

/* La fila envuelve, y hasta F3 no lo hacía. Medida en un teléfono de 375 px, la barra de ADMIN
   ya se salía —526 px de enlaces— y **arrastraba la página entera de lado**: no era que la barra
   se viera apretada, era que toda la pantalla se corría al deslizar. El séptimo enlace lo llevó a
   579 px y lo hizo evidente al medirlo. Dos renglones de barra es lo que el `flex-wrap` de
   `.barra` ya hacía con el nombre de la sesión; esto es lo mismo para los enlaces. */
.barra nav {
    display: inline-flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.35rem 1rem;
}

.barra a {
    color: var(--texto);
    text-decoration: none;
}

.barra a:hover {
    color: var(--turquesa-profundo);
}

/* La insignia que es un enlace propio al lado de otro —hoy, las horas por confirmar junto a
   «Agenda» (V2)—. El `gap` de la barra la dejaba a un rem de su enlace, a la misma distancia que el
   enlace siguiente, y se leía como una sección más de la barra llamada «3». Pegada, se lee como del
   enlace de su izquierda, que es lo que es. */
.barra nav a.insignia-de-la-barra {
    margin-left: -0.65rem;
}

/* El envoltorio de la insignia de quien atiende (AG2) está siempre, porque es el que encuesta, y sin
   nada que decir queda vacío. Vacío, igual era un elemento más de la barra y el `gap` le sumaba un rem
   de hueco junto a «Agenda» a todo veterinario sin avisos. Oculto no deja de encuestar: el `every` de
   htmx no mira si se ve. `:has` y no `:empty`, porque la plantilla deja espacios adentro. */
.barra nav #aviso-de-la-persona:not(:has(*)) {
    display: none;
}

form.en-linea,
.barra form {
    display: inline;
}

/* El campo, en una sola regla y por descarte.

   Antes eran dos listas de tipos —`text, search, tel, date, number` acá, `email, password` cien
   líneas más arriba con las mismas nueve declaraciones copiadas— y había que acordarse de agregar
   el tipo nuevo a la correcta. Nadie se acordó: `time` no estaba en ninguna de las dos, y el campo
   de hora de la agenda salía a la pantalla como lo dibuja el navegador —74×24 px contra los 192×42
   de sus vecinos, borde gris de 2 px, monoespaciada de 13 px y un fondo que no está en la paleta—,
   justo al lado del campo de día, que sí estaba en la lista.

   Por descarte falla del lado correcto: el tipo que se use mañana queda vestido sin que nadie lo
   agregue, y lo que no es una caja de escribir —las casillas, las opciones, el archivo, que tienen
   sus propias reglas— se nombra una vez acá. Los `submit` y `reset` no existen hoy en ninguna
   plantilla —todo botón es un `<button>`— y se descartan igual, porque el día que aparezca uno el
   error sería mudo: se vería como un campo en vez de como un botón.

   La lista va dentro de un solo `:not()` a propósito. Escrita como `:not(a):not(b)…` la regla sube
   a especificidad 0,4,1 y le gana a `.cantidad input`, que es la que angosta a 4,5rem la cantidad
   dentro de la tabla del presupuesto; con la lista adentro, `:not()` pesa lo que su argumento más
   específico y el conjunto se queda en 0,1,1, que es lo que pesaban las dos listas viejas. */
input:not([type="checkbox"], [type="radio"], [type="file"], [type="hidden"], [type="submit"], [type="reset"], [type="button"], [type="image"], [type="range"], [type="color"]),
select,
textarea {
    width: 100%;
    padding: 0.5rem;
    margin-top: 0.25rem;
    border: 1px solid var(--borde);
    color: var(--texto);
    background: var(--campo);
    border-radius: 0.3rem;
    font: inherit;
}

textarea {
    resize: vertical;
}

/* El campo tiene que decir dónde está el cursor y cuál está bajo el puntero. Sin esto, un
   formulario largo —la ficha nueva son catorce campos— es una grilla de rectángulos
   iguales, y el anillo de foco es la única pista. */
input:hover:not(:disabled),
select:hover:not(:disabled),
textarea:hover:not(:disabled) {
    border-color: var(--texto-tenue);
}

input:focus,
select:focus,
textarea:focus {
    border-color: var(--turquesa);
}

/* La marca de una casilla y el punto de una opción los dibuja el sistema, y sin decirle nada los
   dibuja en el azul de Windows: el único color que quedaba en pantalla sin salir de la paleta.
   Estaba resuelto solo en `.casilla`, que es la del receptor del cobro y una de ocho —las otras
   siete son los tres tipos de preventivo, los roles del usuario, el estado de la ficha, los
   inactivos de los dos listados, y el exento y el pago previo del servicio—, así que la aplicación
   tenía una casilla verde y siete grupos azules.

   Va en todos los controles y no solo en las casillas por el panel del calendario y el del reloj.
   Ese panel **no es parte de la página**: lo dibuja el navegador aparte, y ni su fondo gris, ni sus
   esquinas rectas, ni su tipografía, ni los enlaces «Borrar» y «Hoy» se pueden alcanzar desde acá
   —no existe pseudo-elemento para ellos—. Las dos únicas cosas que cruzan esa frontera son
   `color-scheme`, que es lo que hace que el panel salga oscuro y no blanco, y `accent-color`.

   **`accent-color` NO llega al día seleccionado dentro del panel, comprobado a mano el 17-08**: la
   propiedad llega a los campos —turquesa en los dos temas, se ve en las casillas y los radios— pero
   Chromium dibuja el día resaltado de su date-picker en su azul y no la respeta ahí adentro. Se deja
   puesta igual, porque es la única palanca que existe y no cuesta nada, y porque el día que Chromium
   la respete el turquesa aparece solo. El panel no tiene otro arreglo desde CSS; el único camino
   sería un calendario propio en JavaScript, descartado por la decisión de controles nativos del
   14-08.

   **Y no todo Chromium la respeta igual, comprobado el 25-08 durante la §25**: en Chrome el radio
   marcado sale turquesa y en Opera sale oscuro, con la misma hoja y el mismo tema. No se arregla
   desde acá —pintar el control propio exige `appearance: none` y volver a dibujar el punto, que es
   la decisión de controles nativos otra vez—, y no es un defecto de la pantalla: queda anotado para
   que la próxima vez que alguien vea un radio apagado sepa que lo primero que hay que preguntar es
   en qué navegador está mirando. */
input,
select,
textarea {
    accent-color: var(--turquesa);
}

/* ---------------------------------------------------------------------------
   Lo que el navegador sigue dibujando adentro del campo

   Vestir la caja no alcanza. Dentro de un `date`, un `time`, un `number` y un `search` el navegador
   pone controles propios —el calendario, el reloj, las flechitas de subir y bajar, la equis de
   limpiar— y los dibuja como el sistema operativo: gris de Windows, del tamaño que él quiera,
   con su propia idea de dónde ponerlos. Es el mismo problema que tenía el campo de archivo antes
   de vestirlo, y se resuelve con el mismo criterio: se viste lo que se puede vestir, y solo se
   apaga lo que no le quita nada a nadie.
   --------------------------------------------------------------------------- */

/* El calendario y el reloj, dibujados con una máscara igual que el ojo del login y la flecha del
   campo de archivo: así toman la tinta del tema —tenue en Menta amable, tenue en Grafito clínico—
   en vez del gris del sistema, que en oscuro quedaba casi invisible sobre el campo.

   El `background` va en atajo y no en `background-color` a propósito: el atajo borra de paso el
   `background-image` con el que el navegador pinta su propio glifo, que si no se cuela por debajo
   de la máscara y se ven los dos dibujos encima. */
input[type="date"]::-webkit-calendar-picker-indicator,
input[type="time"]::-webkit-calendar-picker-indicator,
input[type="datetime-local"]::-webkit-calendar-picker-indicator {
    width: 1.1rem;
    height: 1.1rem;
    padding: 0;
    margin-left: 0.35rem;
    background: var(--texto-tenue);
    cursor: pointer;
    transition: background-color 0.12s ease;
}

input[type="date"]::-webkit-calendar-picker-indicator:hover,
input[type="time"]::-webkit-calendar-picker-indicator:hover,
input[type="datetime-local"]::-webkit-calendar-picker-indicator:hover {
    background: var(--texto);
}

input[type="date"]::-webkit-calendar-picker-indicator,
input[type="datetime-local"]::-webkit-calendar-picker-indicator {
    --icono-calendario: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3.4' y='5.4' width='17.2' height='15.2' rx='2.2'/%3E%3Cpath d='M3.4 10.2h17.2'/%3E%3Cpath d='M8.2 3.4v3.6'/%3E%3Cpath d='M15.8 3.4v3.6'/%3E%3C/svg%3E");
    -webkit-mask: var(--icono-calendario) center / contain no-repeat;
    mask: var(--icono-calendario) center / contain no-repeat;
}

input[type="time"]::-webkit-calendar-picker-indicator {
    --icono-reloj: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='8.6'/%3E%3Cpath d='M12 7.4V12l3.2 1.9'/%3E%3C/svg%3E");
    -webkit-mask: var(--icono-reloj) center / contain no-repeat;
    mask: var(--icono-reloj) center / contain no-repeat;
}

/* Los dos píxeles del campo de fecha. Medido: día y hora salían de 44 px de alto contra los 42 de
   todos los demás campos, y en la fila «Día · Hora» del formulario de la agenda eso deja los dos
   controles desalineados respecto de «Duración», que va al lado. No es el icono ni la tipografía
   —quitando el indicador el campo seguía en 44—: es el relleno vertical de un píxel que el
   navegador le pone por dentro a la caja donde viven los trozos editables. A cero quedan los 42
   exactos y el contenido no se recorta. */
input::-webkit-datetime-edit-fields-wrapper {
    padding: 0;
}

/* El trozo que se está editando —el día, el mes, la hora— lo resalta el navegador con el azul de
   selección del sistema. Es lo primero que se ve al tabular hasta el campo, y era lo más ajeno de
   la pantalla: un rectángulo azul dentro de un formulario que no tiene azul en ninguna parte.

   No apaga ningún foco: el resalte *es* el indicador de qué trozo recibe las teclas, y el campo
   entero además cambia su borde a turquesa con `input:focus`. Solo se le cambia el color. */
input::-webkit-datetime-edit-year-field:focus,
input::-webkit-datetime-edit-month-field:focus,
input::-webkit-datetime-edit-day-field:focus,
input::-webkit-datetime-edit-hour-field:focus,
input::-webkit-datetime-edit-minute-field:focus,
input::-webkit-datetime-edit-second-field:focus,
input::-webkit-datetime-edit-ampm-field:focus {
    border-radius: 0.15rem;
    background: var(--turquesa);
    color: var(--sobre-turquesa);
}

/* Las flechitas del campo numérico. Es lo único de este bloque que se apaga en vez de vestirse, y
   no por pereza: son un control que el navegador no deja redibujar —se le puede cambiar el alto y
   poco más— así que vestirlo es imposible y dejarlo es tener un objeto de Windows dentro del
   campo.

   Apagarlo no le quita el paso a nadie. Las flechas del teclado siguen subiendo y bajando el valor
   igual que antes, que es el camino que usa quien no puede apuntar con el mouse; el cuadrito de
   siete píxeles era justamente el que no servía ni con el dedo en el mesón. Y ninguno de los
   números de la aplicación se llega apretando: la duración va de 5 a 720, el precio y la cantidad
   se escriben, y el peso tiene tres decimales. */
input[type="number"] {
    -moz-appearance: textfield;
    appearance: textfield;
}

input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
    -webkit-appearance: none;
    appearance: none;
    margin: 0;
}

/* La equis que limpia la búsqueda, con la misma máscara y la misma tinta que el calendario. Se
   viste y no se apaga porque acá sí hace falta: los siete buscadores de la aplicación —fichas,
   usuarios, catálogo, la cola de cobros, la ficha de la hora, el detalle del presupuesto y el
   correo en el registro de accesos— se usan escribiendo, borrando y volviendo a escribir, y vaciar
   el campo de un clic es más rápido que dejar apretado el retroceso. */
input[type="search"]::-webkit-search-cancel-button {
    --icono-limpiar: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.1' stroke-linecap='round'%3E%3Cpath d='M6.8 6.8 17.2 17.2'/%3E%3Cpath d='M17.2 6.8 6.8 17.2'/%3E%3C/svg%3E");
    -webkit-appearance: none;
    appearance: none;
    width: 0.95rem;
    height: 0.95rem;
    margin-left: 0.35rem;
    background: var(--texto-tenue);
    -webkit-mask: var(--icono-limpiar) center / contain no-repeat;
    mask: var(--icono-limpiar) center / contain no-repeat;
    cursor: pointer;
    transition: background-color 0.12s ease;
}

input[type="search"]::-webkit-search-cancel-button:hover {
    background: var(--texto);
}

/* El gris por defecto del navegador no está en la paleta y en varios se lee casi tanto como
   el valor escrito, que es justo lo que un ejemplo no debe hacer. */
::placeholder {
    color: var(--texto-tenue);
    opacity: 1;
}

fieldset {
    border: 0;
    padding: 0;
    margin: 0;
    min-width: 0;
}

fieldset:disabled {
    opacity: 0.75;
}

.campos {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
    gap: 0 1rem;
}

.campos .ancho {
    grid-column: 1 / -1;
}

/* Un campo que se contesta en una palabra y se explica en tres renglones: "Cada cuánto se le
   paga", en el alta del acuerdo. Va con `.ancho` para que su ayuda se lea al ancho del
   formulario —dentro de una columna de la retícula se partía en cinco líneas cortas con media
   pantalla libre al lado, cosa que los campos de arriba no hacen porque tienen un vecino— y el
   control se queda en su tamaño: un desplegable de dos opciones estirado a lo ancho de la
   sección anuncia que ahí hay que escribir algo largo.

   El mínimo es el mismo `12rem` con el que la retícula arma sus columnas, así que el control
   queda a la altura de los de arriba en vez de alineado con nada. Y la ayuda vuelve a ser un
   bloque porque el control ya no ocupa la línea entera: sin esto se le sienta al lado y las dos
   primeras líneas del texto arrancan desde el borde del desplegable. */
.campo-corto select,
.campo-corto input {
    width: auto;
    min-width: 12rem;
}

.campo-corto small {
    display: block;
}

.acciones {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 1rem;
    margin-top: 1.5rem;
}

/* Los botones traen su propio margen superior para cuando cierran un formulario. Dentro de
   una fila de acciones ese margen los baja respecto de los enlaces que tienen al lado, y la
   fila queda escalonada. */
.acciones > button,
.acciones > a.boton {
    margin-top: 0;
}

/* Y lo mismo cuando el botón es un POST propio y viene envuelto en su `<form>`: ahí deja de ser
   hijo directo y recupera el margen que escalona la fila. Lo trajo el expediente del art. 11, donde
   acusar y prorrogar son dos formularios de un botón cada uno, uno al lado del otro. */
.acciones > form > button {
    margin-top: 0;
}

/* El formato de papel acompaña al botón porque modifica exactamente la impresión que ese botón
   abre. Es un control nativo y compacto: los cuatro nombres caben sin inventar otro componente,
   y su valor se comparte entre las hojas desde `imprimir.js`. */
.selector-papel {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0;
    color: var(--texto-tenue);
    font-size: 0.9rem;
}

.selector-papel select {
    width: auto;
    min-width: 8.5rem;
    margin-top: 0;
}

/* **El papel que se elige acá no manda en la impresora** (hallazgo 148, AG3). La hoja pide su tamaño,
   pero un destino que es una impresora imprime en el papel que tiene puesto en su propia ventana: en
   el bloque U, una media carta impresa con *Microsoft Print to PDF* salió dibujada sobre una Carta,
   con márgenes enormes. La receta en media carta impresa desde un teléfono salió igual, con márgenes
   grandes, y es la causa más probable; la confirma la pasada con impresora. Así que se dice al lado
   del selector, y sólo cuando se elige otro papel que Carta, que es el formato inicial.

   Abajo, el mismo aire que deja la fila de botones cuando el aviso no está: sin él quedaba pegado al
   membrete. */
.aviso-de-papel {
    display: none;
    margin: 0.5rem 0 1rem;
    color: var(--texto-tenue);
    font-size: 0.9rem;
}

html:is([data-papel="a4"], [data-papel="a5"], [data-papel="media-carta"]) .aviso-de-papel {
    display: block;
}

/* El enlace para volver (hallazgo 117): **arriba del título, con flecha y uno solo por pantalla**,
   en todas. Hasta el 03-10 cada pantalla lo ponía donde le cabía —arriba, abajo, al lado del
   título o en la fila de los botones— y la mitad sin flecha, así que había que buscarlo cada vez.
   En la atención iba al lado de *Guardar y cerrar*, que es donde más fácil se aprieta uno por otro.
   Lo decidió Javier con el criterio de las hojas de imprimir, que ya lo llevaban así.

   *Cancelar* en un formulario no es esto y se queda donde está: deshace lo que se estaba
   escribiendo. La regla la defiende `ElEnlaceParaVolverTest`, que recorre las plantillas. */
.volver {
    margin: 0;
}

/* El título pierde su margen de arriba porque el que lo separa del borde ahora es el enlace: con
   los dos, entre el enlace y su título quedaba un hueco que los hacía leer como cosas sueltas. */
.volver + h1,
.volver + * > h1:first-child {
    margin-top: 0.5rem;
}

.titulo-con-accion {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
}

/* Una fila de acciones que acompaña a un título no arrastra el margen que lleva cuando cierra
   un formulario: acá va a la altura del h2 y no debajo. */
.titulo-con-accion .acciones,
.titulo-con-accion .acciones button {
    margin-top: 0;
}

/* En un teléfono el título y sus botones no caben en la misma fila: "Vacunas y
   desparasitaciones" ya ocupa medio ancho y "Desparasitación" se salía del borde de la tarjeta.
   Bajo 40rem se apilan —título arriba, acciones debajo con el ancho entero— y los botones vuelven
   a caber en una fila que envuelve sola en vez de aplastarse en una columna a la derecha. */
@media screen and (max-width: 40rem) {
    .titulo-con-accion {
        flex-direction: column;
        align-items: stretch;
    }

    /* Pero **un botón suelto no es una fila de acciones**, y `stretch` no distingue. El catálogo,
       el inventario, los usuarios, las tasas, los acuerdos y las dos pantallas de la agenda
       cuelgan un solo `a.boton` del título —"Nuevo producto", "Nuevo servicio"— y estirado ocupa
       el ancho entero: se lee como una barra de sección, y encima contradice a los "Comisiones" e
       "Inventario" que van dos líneas más abajo con su ancho propio. Lo que tenía que ocupar todo
       el ancho era el contenedor `.acciones`, que adentro ya envuelve solo. Salió de la Parte G de
       la pasada del inventario, el 06-09. */
    .titulo-con-accion > a.boton,
    .titulo-con-accion > button {
        align-self: start;
    }

    /* Apilado, los botones quedan pegados al `dl` que sigue: un `dl` no trae margen propio —en la
       fila de escritorio el aire salía del margen inferior del h2 que tenía al lado, y apilado ese
       margen queda arriba de los botones, no debajo—. Solo le pasa al `dl`: al resto de las
       tarjetas lo que sigue al título es un `<p>` o una tabla, que traen su propio aire. */
    .titulo-con-accion + dl {
        margin-top: 1rem;
    }
}

/* La variante de contorno vale igual para un enlace que se ve como botón: la puerta a otro
   módulo es un `<a>`, no un envío. Va con contorno y no con relleno porque en esa pantalla ya
   manda otro botón —"Nuevo servicio"—, y dos rellenos turquesa seguidos compiten y el ojo elige
   mal, que es el mismo argumento de `.boton-archivo` y `.boton-tabla`. */
button.secundario,
a.boton.secundario {
    background: var(--superficie);
    color: var(--turquesa-profundo);
    border: 1px solid var(--turquesa);
}

a.boton {
    display: inline-block;
    margin-top: 0.75rem;
    padding: 0.55rem 1.1rem;
    border-radius: 0.3rem;
    background: var(--turquesa);
    color: var(--sobre-turquesa);
    text-decoration: none;
    transition: filter 0.12s ease;
}

/* Se ve como un botón: tiene que responder como un botón. */
a.boton:hover {
    filter: brightness(1.06);
}

a.boton:active {
    filter: brightness(0.94);
}

/* ---------------------------------------------------------------------------
   El campo de archivo

   Es el único control que el navegador dibuja entero a su manera: un botón gris de sistema y un
   "Sin archivos seleccionados" con la tipografía del sistema operativo, dos cosas que no se
   parecen a nada del resto de la aplicación. Sale en tres pantallas —el logo de la marca, y la
   firma y el timbre en la cuenta propia y en la ficha del usuario— y en las tres es lo primero
   que se ve de la sección, así que es lo que fija el tono.

   La caja exterior imita al campo de texto —mismo borde, mismo fondo, mismo hover, mismo foco—
   porque en el formulario ocupa el lugar de uno.

   Adentro se dibuja en dos capas. Sin JavaScript se viste el botón nativo con
   `::file-selector-button`: conserva el foco, el teclado y el anuncio del lector de pantalla sin
   una línea de código, y lo único que no se le puede cambiar son las palabras. Con JavaScript,
   archivo-elegido.js esconde el control y muestra el `label`, que sí dice "Elegir imagen" y
   escribe al lado el nombre y el peso de lo elegido. El peso importa: el tope son 30 MB
   (`application.yml`) y la clínica sube por la conexión que tiene, así que verlo antes de apretar
   "Subir" evita la espera larga que termina en un error.
   --------------------------------------------------------------------------- */
.campo-archivo {
    /* Lo pide el input escondido: `.visualmente-oculto` es absoluto, y sin un ancestro que lo
       sujete se va al origen de la página. Ahí pasan dos cosas, y la segunda es la grave:
       tabular hasta el campo salta el scroll al encabezado, y el globo de "Completa este
       campo" —el input es `required`— sale colgando del inicio de la página en vez de del
       campo que falta. Recortado a 1px sigue siendo enfocable, que es lo que permite que el
       navegador lo muestre; escondido con `display: none` Chrome no lo muestra en ninguna
       parte y el formulario se queda sin enviar sin decir por qué. */
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-top: 0.25rem;
    padding: 0.35rem;
    border: 1px solid var(--borde);
    border-radius: 0.3rem;
    background: var(--campo);
}

/* Lo mismo que `input:hover` e `input:focus` hacen con los demás campos, escrito aparte porque
   acá el campo es un <div> y quien recibe el foco es un hijo suyo. */
.campo-archivo:hover {
    border-color: var(--texto-tenue);
}

.campo-archivo:focus-within {
    border-color: var(--turquesa);
}

/* Mientras el archivo viene arrastrado encima, el campo se enciende: sin respuesta no hay cómo
   saber si soltarlo ahí sirve de algo, y el que suelta al lado pierde el archivo en una pestaña
   nueva. */
.campo-archivo.arrastrando {
    border-color: var(--turquesa);
    background: var(--menta-suave);
}

/* Contorno y no relleno turquesa, por lo mismo que `.boton-tabla`: debajo está "Subir el logo" o
   "Reemplazar", que es el que manda el formulario. Dos botones sólidos seguidos compiten y el ojo
   elige mal —elegir un archivo no sube nada—. */
.boton-archivo {
    display: inline-flex;
    align-items: center;
    flex: none;
    gap: 0.45rem;
    margin: 0;
    padding: 0.45rem 0.9rem;
    border: 1px solid var(--turquesa);
    border-radius: 0.25rem;
    background: var(--superficie);
    color: var(--turquesa-profundo);
    font: inherit;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color 0.12s ease;
}

/* Nace oculto y lo muestra archivo-elegido.js, igual que el ojo del login: sin ese script el
   control nativo sigue trayendo su propio botón y se verían dos para lo mismo. El `display`
   propio obliga a apagarlo a mano. */
.boton-archivo[hidden] {
    display: none;
}

.boton-archivo:hover {
    background: var(--menta-suave);
}

/* El foco lo tiene el input, que está escondido: sin esto, tabular hasta acá no se ve. */
.campo-archivo:focus-within .boton-archivo {
    outline: 2px solid var(--turquesa);
    outline-offset: 2px;
}

/* La flecha se dibuja con una máscara, igual que el icono de los mensajes: así toma la tinta del
   botón —turquesa en Menta amable, más clara en Grafito clínico— sin repetir un <svg> en cada
   plantilla. El negro del trazo no se pinta nunca, solo define la forma. */
.boton-archivo::before {
    --icono-subir: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 15.2V4.3'/%3E%3Cpath d='m7.8 8.5 4.2-4.2 4.2 4.2'/%3E%3Cpath d='M4.6 15.2v3.4c0 .9.7 1.6 1.6 1.6h11.6c.9 0 1.6-.7 1.6-1.6v-3.4'/%3E%3C/svg%3E");
    content: "";
    flex: none;
    width: 1.05rem;
    height: 1.05rem;
    background-color: currentColor;
    -webkit-mask: var(--icono-subir) center / contain no-repeat;
    mask: var(--icono-subir) center / contain no-repeat;
}

/* El nombre del archivo se recorta con puntos suspensivos y no parte la caja en dos líneas: un
   escaneo se llama "WhatsApp Image 2026-08-12 at 19.44.31.jpeg" y estiraría el campo a lo alto
   cada vez. */
.archivo-elegido {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--texto-tenue);
    font-size: 0.9rem;
}

/* Mientras no hay nada elegido el texto es una indicación; con archivo pasa a ser el dato del
   formulario y se lee a tinta entera. */
.archivo-elegido.elegido {
    color: var(--texto);
}

/* La capa sin JavaScript: el control nativo, ya dentro de la caja, aportando solo su botón y el
   nombre que escribe el navegador. Sin borde ni fondo propios porque la caja ya los puso. */
.campo-archivo input[type="file"] {
    flex: 1;
    min-width: 0;
    border: 0;
    background: none;
    color: var(--texto-tenue);
    font: inherit;
    font-size: 0.9rem;
}

/* Va en su propia regla y no junto a `.boton-archivo` aunque se vistan igual: un navegador que no
   entienda `::file-selector-button` descarta la regla entera, y de paso se llevaría el botón que
   sí se dibuja siempre. */
.campo-archivo input[type="file"]::file-selector-button {
    margin-right: 0.75rem;
    padding: 0.45rem 0.9rem;
    border: 1px solid var(--turquesa);
    border-radius: 0.25rem;
    background: var(--superficie);
    color: var(--turquesa-profundo);
    font: inherit;
    /* El input va en 0.9rem porque ahí escribe el navegador el nombre del archivo, que es
       secundario; el botón vuelve al cuerpo normal para pesar lo mismo que `.boton-archivo`. */
    font-size: 1rem;
    cursor: pointer;
    transition: background-color 0.12s ease;
}

.campo-archivo input[type="file"]::file-selector-button:hover {
    background: var(--menta-suave);
}

/* ---------------------------------------------------------------------------
   Una fecha opcional que se puede quitar de un golpe

   El control nativo no ofrece cómo vaciarse: hay que borrar el día, el mes y el año por separado
   y quedarse mirando si el campo volvió a "dd-mm-aaaa" o si quedó a medias. Salió probando el
   próximo control de la receta, que se fija y se corre seguido, y donde equivocarse en silencio
   manda al tutor de vuelta un día que no es.

   El botón vive al lado del campo y solo se ve cuando hay una fecha puesta, así que su ausencia
   ya dice que no quedó nada. Lo muestra `fecha-borrable.js`: sin JavaScript el campo conserva su
   conducta normal y no aparece un botón que no haría nada.
   --------------------------------------------------------------------------- */
.fecha-borrable {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 0.5rem;
}

/* El campo manda y el botón toma lo suyo: todo input de la aplicación es `width: 100%`, y sin
   esto empuja al botón fuera de la línea apenas la pantalla se angosta. */
.fecha-borrable input {
    flex: 1 1 10rem;
    min-width: 0;
}

/* Los botones nacen con `margin-top: 1.25rem`, que es el aire con que se separan de un formulario
   entero. Este acompaña a un campo y tiene que quedar a la altura del control, que arranca en el
   0.25rem de todo input. */
.fecha-borrable button {
    flex: none;
    margin-top: 0.25rem;
}

/* El aviso de que se quitó toma la fila entera debajo, y no una tercera columna que angostaría el
   campo cada vez que aparece. */
.fecha-borrable .fecha-quitada {
    flex: 1 0 100%;
    font-size: 0.9rem;
}

table {
    width: 100%;
    border-collapse: collapse;
    margin-top: 0.75rem;
}

th, td {
    text-align: left;
    padding: 0.5rem 0.6rem;
    border-bottom: 1px solid var(--borde);
    vertical-align: top;
}

th {
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--texto-tenue);
}

/* El `th` de una fila identifica, no encabeza. La regla de arriba —versalita, chica, apagada—
   es del encabezado de columna, y heredada por la celda del nombre deja "SALA CANINA" gritando
   en mitad del listado. Las tres tablas que ya tenían una celda así se escribieron esta misma
   corrección cada una por su cuenta; está acá para que la cuarta no tenga que descubrirla. */
th[scope="row"] {
    color: var(--texto);
    font-size: 1rem;
    font-weight: 400;
    letter-spacing: normal;
    text-transform: none;
}

/* ---------------------------------------------------------------------------
   La cola de cobro

   Seis columnas y la última es un control, así que el ancho está justo. Repartirlo a mano por
   porcentaje deja "Emitido" en dos líneas incluso cuando cabía de sobra: la fila se ve alta y
   desordenada todo el tiempo para cubrir el caso raro. Acá reparte la tabla y solo se sujeta
   lo que de verdad se desborda.
   --------------------------------------------------------------------------- */

/* Con seis columnas el relleno lateral se lleva por sí solo casi una palabra de cada nombre.
   Algo más apretada que el resto de las tablas es lo que deja la fila entera en una línea. */
.tabla-cola-cobros th,
.tabla-cola-cobros td {
    padding-left: 0.45rem;
    padding-right: 0.45rem;
}

/* Paciente, tutor y responsable los escribe la clínica y no tienen largo controlado. En el
   escritorio la tabla no tiene a dónde desbordarse, así que un nombre de una sola palabra
   larguísima se parte antes que empujar el saldo fuera de la sección.

   Solo en el escritorio: bajo 40rem la tabla ya se desplaza dentro de su sección, y ahí
   `anywhere` deja de proteger nada y pasa a hacer daño —le dice al navegador que la columna
   puede medir una letra, y "María González" baja partida en "María Gonz / ález". */
@media (min-width: 40rem) {
    .tabla-cola-cobros td:nth-child(2),
    .tabla-cola-cobros td:nth-child(3),
    .tabla-cola-cobros td:nth-child(4) {
        overflow-wrap: anywhere;
    }
}

/* Un saldo de la cola no pasa de seis cifras. Fijarle el ancho es lo que impide que la línea
   del abono, que es larga, se lleve un tercio de la tabla y deje a los nombres sin dónde caber. */
.tabla-cola-cobros .columna-saldo {
    width: 6.5rem;
}

/* El abono explica el saldo, no es otra cifra que se compare hacia abajo: si no cabe se apila
   en dos líneas cortas en vez de ensanchar la columna. Cada mitad se mantiene entera, porque
   partir "$200.000" entre el signo y el número es justo lo que `.numero` evita. */
.tabla-cola-cobros .abono-en-cola {
    white-space: normal;
}

.tabla-cola-cobros .abono-en-cola span {
    white-space: nowrap;
}

/* `width: 1%` con `nowrap` es cómo se le pide a una tabla automática que una columna se quede
   con lo justo de su contenido: el ancho que sobra va a las tres de texto, que es donde varía.
   El alto lo pone el botón, así que la celda aporta menos relleno propio para que la fila no
   crezca respecto de las demás pantallas. */
.tabla-cola-cobros .columna-accion {
    width: 1%;
    padding: 0.25rem 0.35rem;
    white-space: nowrap;
    vertical-align: middle;
}

dl {
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 0.35rem 1rem;
    margin: 0;
}

dt {
    color: var(--texto-tenue);
    font-size: 0.9rem;
}

dd {
    margin: 0;
}

.folio {
    font-size: 0.9rem;
    font-weight: normal;
    color: var(--texto-tenue);
}

/* Los datos que identifican el presupuesto son una sola fila de lectura. Cada pieza comparte
   el mismo eje vertical y, si falta ancho, salta completa en vez de cortar un nombre o una fecha. */
ul.metadatos-presupuesto {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.25rem 0.45rem;
    margin: 0.75rem 0 0;
    padding: 0;
    list-style: none;
}

/* El `gap` no es aire de más: un contenedor flex descarta el espacio en blanco entre sus
   hijos, así que "ficha <span>10</span>" se leía "ficha10". Es el único dato de la fila que
   lleva palabra y valor en piezas separadas, y era el único que salía pegado. */
.metadatos-presupuesto > li {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    min-height: 1.5rem;
    white-space: nowrap;
}

/* Descontado el `gap` que ahora separa a los hijos, para que la separación tras el punto
   quede donde estaba. */
.metadatos-presupuesto > li + li::before {
    content: "·";
    margin-right: 0.2rem;
    color: var(--texto-tenue);
}

/* La etiqueta es una sola pieza en todo el sistema —el estado de un presupuesto, la línea
   exenta, el paciente extraviado, el tutor principal— y por eso el alto lo pone ella y no su
   contenido: dos etiquetas seguidas miden igual aunque una diga "exenta" y la otra "nota de
   crédito pendiente". Lo que se ganó al subir esto desde la del presupuesto, que era la única
   que lo tenía, es que dejaran de sentarse medio renglón más abajo que el texto que acompañan. */
.etiqueta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 1.5rem;
    padding: 0.15rem 0.55rem;
    border-radius: 0.8rem;
    background: var(--menta-suave);
    color: var(--turquesa-profundo);
    font-size: 0.75rem;
    line-height: 1;
    vertical-align: middle;
}

/* Casilla y su texto en la misma línea, sin el display:block de los demás label. */
label.opcion {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

label.opcion input {
    width: auto;
    margin: 0;
}

/* El bloque de opciones que encabeza su propia pregunta dentro de un formulario: «Cómo trabaja
   para la clínica» y «Qué autoriza el acuerdo», en el alta del acuerdo de comisión.

   La retícula de `.campos` no separa filas —el aire entre una y otra lo pone cada campo con el
   margen de su etiqueta—, y un `fieldset` no tiene etiqueta: nacía pegado al texto de ayuda del
   campo de arriba, y en una pantalla que decide plata no se veía dónde empezaba cada bloque. El
   desnivel se empuja desde el `fieldset` y no desde el `legend` por lo mismo que en `.reparto`:
   el navegador no le aplica el margen de arriba a un `legend`, así que la regla lo pedía y no
   movía nada.

   Y el `legend` pesa como el encabezado que es. Con el estilo que le da el navegador se leía
   igual que la etiqueta de un campo, y entonces «Qué autoriza el acuerdo» parecía el nombre del
   radio que tenía debajo en vez del título de los tres. Misma tinta y misma familia que
   `.bloque-de-campos > legend`, sin su relleno lateral, que allá existe para montar el título
   sobre el borde de la caja y acá no hay caja. */
.bloque-de-opciones {
    margin-top: 1.6rem;
}

.bloque-de-opciones > legend {
    padding: 0;
    color: var(--texto);
    font-family: var(--fuente-marca);
    font-weight: 700;
}

/* **La línea que dice dónde termina un grupo de opciones.** Registrar una solicitud del art. 11
   apila cuatro seguidos —«qué datos quedan frenados», «qué usos», «qué vínculos» y sus candidatos—,
   cada uno con su párrafo de ayuda debajo, y sin línea se leen como un muro: la ayuda de un grupo
   queda más cerca del título del siguiente que de sus propias casillas, así que el aire solo no
   alcanza. Lo levantó el uso, registrando la primera solicitud de la pasada del bloque O.

   Sólo entre grupos y nunca sobre el primero: ahí la línea repetiría el borde de la sección a un
   centímetro de distancia.

   **Y va en el contenedor y no en el `fieldset`, que es la vuelta que hubo que darle.** Puesta en el
   `fieldset`, el `legend` hace lo que hace desde siempre: se superpone al borde y lo parte, así que
   la línea salía **a la altura del título y pegada a él**, como si lo subrayara por el lado. Desde
   afuera cruza entera y por encima. El `margin-top` propio del bloque se apaga acá porque el
   `padding` del contenedor ya puso ese aire, y sumados eran tres centímetros. */
.campos > * + *:has(> .bloque-de-opciones) {
    padding-top: 1.5rem;
    border-top: 1px solid var(--borde);
}

.campos > * + *:has(> .bloque-de-opciones) > .bloque-de-opciones {
    margin-top: 0;
}

/* El subtítulo de una lista dentro del grupo —«De qué paciente dice no ser responsable» sobre los
   pacientes del titular— nace pegado a la última casilla de la lista de arriba y se lee como parte
   de ella, que es justo lo contrario de lo que hace ahí. */
.bloque-de-opciones > .opcion + p {
    margin-top: 1.1rem;
}

/* Y la ayuda que cierra el grupo, separada de la última casilla por lo mismo: pegada, esa frase se
   lee como el rótulo de la opción de arriba y no como lo que explica el grupo entero. */
.bloque-de-opciones > small {
    display: block;
    margin-top: 0.7rem;
}

/* Una opción cuyo título no alcanza para decidir, porque elegirla mueve plata: la autorización
   del acuerdo de comisión decide si mover la matriz de tasas le cambia a alguien lo que gana.
   Ahí la explicación tiene que estar a la vista **antes** de elegir, no en una ayuda que se abre
   después.

   Debajo y no al lado: al lado, tres opciones con su frase cada una empujan el radio siguiente
   fuera de la pantalla angosta. Sangrada al ancho del radio para que se lea como parte de su
   opción y no de la de arriba, que es lo que pasaba sin la sangría. */
.opcion-explicada + .opcion-explicada {
    margin-top: 0.6rem;
}

.opcion-explicada small {
    display: block;
    padding-left: 1.4rem;
}

/* El dinero se lee comparando columnas, y para eso tiene que estar alineado a la derecha
   y con cifras de ancho fijo: si no, $9.000 y $130.000 no se pueden comparar de un vistazo.

   `nowrap` es por los negativos: en una columna angosta el navegador parte "−$25.000" entre
   el signo y el peso, y el menos queda huérfano al final de una línea. Justo lo que enPesos
   existe para evitar. */
.numero {
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Lo que ocupa el lugar de la cifra cuando no hay cifra: «lo que diga la matriz», en la columna
   de la comisión de un acuerdo que no pacta su propio porcentaje. El `nowrap` de arriba existe
   para que "−$25.000" no se parta entre el signo y el peso, y una frase no tiene ese problema;
   con él puesto, la columna le pedía a la tabla el ancho de una oración entera y se lo quitaba a
   la de al lado, que es la que dice qué autoriza el acuerdo. Sigue alineada a la derecha, que es
   lo que la deja leerse como parte de su columna y no como un texto suelto. */
.numero .en-palabras {
    white-space: normal;
}

/* Y su columna con ancho propio, porque lo de arriba sin esto arregla a medias: soltado el
   `nowrap`, la tabla le daba a la comisión lo que le sobraba —83 px con los acuerdos de Garras
   Garritas— y «lo que diga la matriz» bajaba en tres renglones de dos palabras pegados al borde.

   Las 8rem no son gusto: son **lo que ya pide el contenido más ancho que esta columna puede
   traer**, la etiqueta «sin tasa que lo cite» con el relleno de su celda —109,7 px medidos más
   2 × 9,6—. Con eso la columna mide igual haya o no una fila sin tasa, que es el mismo defecto
   que arregla `.autor-del-acuerdo` visto en la otra columna: el ancho de la tabla no puede
   depender de qué filas le tocaron hoy. Dejarla del ancho de la frase entera serían 9,6rem y se
   los quitaría a la columna que dice qué autoriza el acuerdo, que es la que se lee. */
.columna-comision {
    width: 8rem;
}

/* La acción que se repite en cada fila: abrir el presupuesto, editar al tutor, agregar el
   servicio del catálogo. Es un botón y no un enlace suelto porque en una columna de "abrir"
   idénticos la palabra sola no dice dónde termina un objetivo y empieza el siguiente, y en el
   mesón se apunta con el dedo sobre una pantalla táctil: 2.25rem es lo que hace que se acierte
   sin mirar.

   Ancho completo de su celda para que todas midan igual. Contorno y no relleno turquesa: hay
   una por fila, y una columna de botones sólidos pesa más que los datos que acompaña.

   Vale para `button` y para `a` —abrir es un GET y agregar del catálogo un POST— y por eso la
   caja se declara entera acá en vez de heredarla: un `a` no toma nada de la regla de `button`.
   El centrado va con flex porque `min-height` sobre un `a` estira la caja y deja el texto
   pegado arriba, mientras el `button` lo centraba solo; sin esto los dos no coincidían. */
button.boton-tabla,
a.boton-tabla {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    min-height: 2.25rem;
    margin: 0;
    padding: 0.35rem 0.7rem;
    border: 1px solid var(--turquesa);
    border-radius: 0.3rem;
    background: var(--superficie);
    color: var(--turquesa-profundo);
    font: inherit;
    font-weight: 400;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
}

button.boton-tabla:hover,
a.boton-tabla:hover {
    filter: none;
    background: var(--menta-suave);
}

button.boton-tabla:active,
a.boton-tabla:active {
    filter: none;
    background: var(--borde);
}

/* Las columnas que no son datos sino señales: el estado, la acción y la de "abierta" en las
   atenciones en curso. Se encogen a su contenido —`width: 1%` en una tabla al 100% deja que el
   sobrante lo repartan las columnas de datos— y no parten su contenido en dos líneas.

   El `nowrap` no es cosmético en ninguna: sin él el botón se estiraba hasta donde llegara la
   celda y cada tabla tenía un "abrir" de otro ancho; la etiqueta "en curso" se rompía por el
   espacio y quedaba de dos renglones dentro de una píldora pensada para uno; y "hace 21 días"
   se partía en "hace 21" / "días". Al encogerse estas señales, el ancho sobrante lo absorben
   Tutor y Veterinario, que sí pueden ir en varias líneas. */
.columna-accion,
.columna-estado,
.columna-abierta {
    width: 1%;
    white-space: nowrap;
}

/* Dos acciones en la misma celda —"abrir" y "receta" en el historial de la ficha—, una al lado de
   la otra.

   Estuvieron apiladas exactamente un día, y el motivo de apilarlas era cierto: mientras el
   historial metía el motivo y el diagnóstico en columna propia, la columna de acciones pasaba de
   ~6,5rem a ~11rem y lo que se comprimía era el texto, con la fecha partida en cuatro líneas. Ese
   motivo se fue con la prosa: en seis columnas de dato corto sobran 4rem de ancho, y apiladas la
   fila mide 4,8rem de alto para mostrar una sola línea de datos.

   El contenedor hace falta igual: `a.boton-tabla` trae `margin-top` propio para cerrar formularios
   y dentro de una celda eso deja las dos separadas de forma despareja. Acá el `gap` lo decide esta
   regla. */
.acciones-de-fila {
    display: flex;
    gap: 0.35rem;
}

/* Las mismas dos acciones una sobre otra, cuando al lado no caben: hoy, editar a un tutor y moverle
   el rótulo de principal (hallazgo 120). Se apilaban sin contenedor, la segunda dentro de su `form`
   y pegada a la primera borde con borde, y se leían como un solo botón partido —el mismo defecto que
   el detalle del presupuesto arregló el 05-09—. El `gap` es el de `.acciones-de-fila`, y el ancho lo
   pone el botón más largo: los dos miden lo mismo porque estiran a la columna. */
.acciones-apiladas {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

/* Los mismos dos botones cuando bajan a la fila propia del registro: hoy, la tabla de comisiones.

   `a.boton-tabla` nace al 100 % de su celda, y eso es lo correcto mientras la celda sea una columna
   angosta —así todas las tablas tienen un "abrir" del mismo ancho—. Cuando la celda cruza la tabla
   entera, ese mismo 100 % reparte dos botones de más de 20rem cada uno, y para un acto que no se
   deshace ése es justo el tamaño que no hay que darle: un blanco enorme se aprieta sin apuntar. */
.acciones-del-registro > .boton-tabla {
    width: auto;
}

/* Nace oculto y lo muestra copiar-mensaje.js, como `.boton-archivo`: sin ese script el mensaje sigue
   ahí para seleccionarlo, y un botón que no copia nada sería peor que ninguno. En las confirmaciones
   va como `.boton-tabla`, cuyo `display: flex` le gana al atributo `hidden`, así que hay que
   apagarlo a mano. */
.copiar-mensaje[hidden] {
    display: none;
}

/* La cantidad y su botón cuando comparten la celda: hoy, cuánto vuelve en una devolución.

   `.boton-tabla` nace con `margin: 0` porque casi siempre es lo único que hay en su celda, y el
   campo no trae margen abajo. Con los dos juntos las dos cajas se tocaban borde con borde y
   formaban una sola figura: "Devolver" se leía como el pie del campo y no como el botón que
   escribe el movimiento. Es el mismo 0.35rem con el que se separan las dos acciones de una fila
   y el botón del detalle del presupuesto. */
.columna-accion input[type="number"] + .boton-tabla {
    margin-top: 0.35rem;
}

/* ---------------------------------------------------------------------------
   El registro que ocupa dos filas

   Dos listados de la ficha llegaron acá por el mismo camino: pedían más ancho del que tiene la
   sección —43rem— y el navegador lo resolvía comprimiendo, que es lo peor que puede hacerle a una
   columna de fechas.

   El **historial** es el único listado con prosa adentro: el motivo y el diagnóstico los escribe el
   veterinario y no tienen largo controlado —un diagnóstico de tres líneas es lo normal—. Con los dos
   en columna propia eran ocho columnas y la tabla pedía 60rem de mínimo: primero se dibujaba encima
   del borde y, envuelta en `.tabla-ancha` para que no lo hiciera, lo que se fue de la pantalla
   fueron los botones de cada fila. El **carnet** no tiene prosa y llegó igual por cantidad: siete
   columnas de dato corto, dos de ellas cargando una etiqueta al lado, y lo que se partía en dos
   renglones era "01-01-2026", la fecha que ordena el listado entero (16-08).

   La corrección no es repartir mejor el ancho, es **sacar de la retícula lo que no se compara hacia
   abajo**. Cada registro es un `<tbody>` de dos filas: arriba las columnas cortas —las que se
   recorren con la vista— y abajo, a lo ancho de la tabla, lo que solo se lee cuando ya se eligió una
   fila. El historial queda en seis columnas que suman 39rem y el carnet en cinco, así que las dos
   caben enteras y el desplazamiento lateral desaparece en el escritorio. Bajo 40rem sigue habiendo:
   ni cinco ni seis columnas caben en un teléfono, y ahí vale lo mismo que para todos los listados.

   Lo que baja no es lo mismo en las dos —relato en una, procedencia en la otra— y por eso vive en el
   bloque de cada tabla. Acá está solo la mecánica de que un registro sean dos filas.
   --------------------------------------------------------------------------- */

/* La línea separa registros, no filas. Entre los datos de uno y su continuación no hay nada que
   separar —son el mismo registro—, así que el borde pasa de la celda al grupo.

   Escrito apagando el borde de **todas** las celdas y no solo el de la fila de datos, porque con un
   `<tbody>` por registro la regla general `tbody tr:last-child` —que existe para que la última fila
   no cierre por dos lados, contra el borde de la sección— pasa a alcanzar la última fila de cada
   grupo y dejaría el listado entero sin una sola línea. */
.registro-en-dos-filas tbody > tr > * {
    border-bottom: 0;
}

.registro-en-dos-filas tbody:not(:last-child) {
    border-bottom: 1px solid var(--borde);
}

/* El resaltado también es del grupo: apuntar la línea de datos e iluminar medio registro delata que
   por dentro son dos filas, que es justo lo que estas tablas no quieren decir. Nombra `th` además de
   `td` porque la fecha encabeza su fila y la regla general solo cubre celdas de dato. */
.registro-en-dos-filas tbody:hover th,
.registro-en-dos-filas tbody:hover td {
    background: var(--menta-suave);
}

/* La segunda fila cuelga de la primera, sin relleno propio arriba: es la continuación del mismo
   registro y no un bloque aparte.

   Por posición y no por una clase, porque cada tabla le da un nombre distinto a lo que baja y lo
   único que esta regla necesita saber es que no es la primera. */
.registro-en-dos-filas tbody > tr + tr > td {
    padding-top: 0;
}

/* Las columnas que son un dato y no prosa: las fechas de las dos tablas y las medidas del historial.

   El navegador partía "12-08-2026 17:31" en cada guion y separaba el número de su unidad: "4,2" en
   una línea y "kg" en la siguiente, "38,3" y "°C". **Un valor partido de su unidad no es un valor
   comprimido, es un valor que hay que rearmar leyendo**, y en la columna donde se sigue la evolución
   del peso de un paciente eso es justo lo que no puede costar trabajo. La fecha va sin tabla que la
   acote porque el problema no es de ninguna en particular: una fecha partida por un guion deja de
   leerse de un vistazo en cualquier listado que la use.

   No se usa `.numero` —que también trae `nowrap`— porque alinea a la derecha, y estas columnas son
   angostas y con el encabezado a la izquierda: el número se despegaría de su título. */
.columna-fecha,
.tabla-historial .columna-medida {
    white-space: nowrap;
}

/* Quién cargó el acuerdo, en su renglón debajo de la fecha. Es la excepción al `nowrap` de arriba
   y por eso lleva clase propia: la regla protege una fecha, y esto es prosa —"Cargado por Amador
   Administrador"—. Sin la excepción esa línea le fijaba a la columna once caracteres de ancho de
   más y estrujaba a las de texto hasta partir "Con contrato de trabajo" palabra por palabra, de
   modo que la tabla se repartía distinto según si el acuerdo se había cargado desde la pantalla o
   sembrado por `.sql`: la única diferencia entre esas dos filas es quién figura, y no tiene por
   qué verse en el ancho de las demás. */
.autor-del-acuerdo {
    white-space: normal;
}

/* Cómo trabaja la persona para la clínica, en la nómina de acuerdos. Es un vocabulario cerrado y
   corto —"Con contrato de trabajo" o "Boletea"— y encabeza la fila, así que se sujeta entero en
   vez de dejar que la tabla lo reparta: en cuanto otra columna crecía, "Con contrato de trabajo"
   bajaba una palabra por renglón y la fila entera se volvía ilegible para ahorrar el ancho de una
   sola. Bajo 40rem la tabla ya se desplaza dentro de su sección, así que acá el `nowrap` no
   arrastra la página. */
.columna-relacion {
    white-space: nowrap;
}

/* Los tutores en la ficha (hallazgo 116). **El RUT y el teléfono no se parten**: se comparan dígito
   a dígito contra la cédula y se marcan mirando la pantalla, y la tabla los partía en el guion y en
   cada espacio —«13907264-» en un renglón y «2» en el siguiente— porque eran las únicas columnas
   donde podía cortar.

   **El correo se parte sólo si no cabe entero**: `break-word` y no `anywhere`, al revés que
   `.huella`. Con `anywhere` la tabla lo tomaba como la columna que podía ceder y lo cortaba en la
   última letra —«example.co» arriba y «m» abajo— para ganar unos píxeles; así, el que cede es el
   nombre, que se parte entre palabras y se sigue leyendo. */
.tabla-tutores .columna-rut,
.tabla-tutores .telefono {
    white-space: nowrap;
}

.tabla-tutores .correo {
    overflow-wrap: break-word;
}

/* Motivo y diagnóstico con su nombre al lado, en la misma retícula con la que la sección de arriba
   muestra los datos del paciente: es el `dl` del sistema, con el interlineado apretado porque acá
   las dos filas son prosa y no dos datos sueltos.

   El `minmax(0, 1fr)` es lo único que no se hereda y hace falta: con `1fr` a secas una palabra larga
   —"antiparasitario"— fija el ancho mínimo de la celda, y como la celda cruza las seis columnas eso
   vuelve a empujar la tabla fuera de la sección, que es el problema que este bloque vino a terminar. */
.relato-atencion {
    grid-template-columns: max-content minmax(0, 1fr);
    gap: 0.15rem 0.9rem;
}

/* Lo que baja en el carnet: de qué frasco salió y quién la puso, en una sola línea.

   En `flex` y no en el `dl` del sistema que usa el relato, porque son dos datos cortos y no dos
   bloques de prosa: apilados ocupaban dos o tres renglones para decir "Lote A1234, aplicó María", y
   en un carnet de veinte filas eso es media pantalla de aire. El `wrap` es lo que lo salva en un
   teléfono sin una consulta de medios propia: cuando no cabe en una línea, baja el pedazo que sobra
   en vez de estirar la tabla. */
.procedencia {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem 1rem;
    font-size: 0.9rem;
}

/* Lo que el veterinario anotó de esa aplicación, en su propio renglón: es lo único del carnet sin
   largo controlado, y como un elemento más de la línea de arriba empujaba "Aplicó" fuera de la
   vista. Conserva el color del texto —no va en `.tenue`— porque "reaccionó a la anterior" no es un
   dato de respaldo: es lo que hay que leer antes de poner la siguiente. */
.observacion-preventiva {
    display: block;
    margin-top: 0.2rem;
    font-size: 0.9rem;
}

/* ---------------------------------------------------------------------------
   El catálogo del presupuesto

   Servicio, precio y acción forman una retícula estable. La confirmación ocupa el mismo lugar
   que el botón: el resultado del clic se ve donde se actuó, pero no ensancha la columna ni mueve
   el siguiente objetivo bajo el puntero.
   --------------------------------------------------------------------------- */
.catalogo-servicios {
    table-layout: fixed;
}

.catalogo-servicios th,
.catalogo-servicios td {
    padding-top: 0.35rem;
    padding-bottom: 0.35rem;
    vertical-align: middle;
}

/* Lo demás que esta celda corregía —el tamaño, el peso, la versalita— lo hace ahora
   `th[scope="row"]` para todas. */
.catalogo-servicios .servicio-catalogo {
    width: auto;
}

/* **10rem y no 7 desde el 03-10** (hallazgo 118): con la unidad al lado (hallazgo 110), «$9.490 /
   aplicación» no cabía, y como `.numero` no parte, la cifra se metía debajo de los botones y se
   leía «aplicació». El ancho es el de la unidad más larga del catálogo, «aplicación». */
.catalogo-servicios .precio-catalogo {
    width: 10rem;
    color: var(--texto);
    font-weight: 400;
}

/* Lo que cuesta el envase entero, en su renglón y más chico: es el dato del botón *Entero* de al
   lado, y adentro del botón lo partía en tres renglones y triplicaba el alto de la fila. */
.catalogo-servicios .envase-catalogo {
    display: block;
    color: var(--texto-tenue);
    font-size: 0.85rem;
}

/* Lo que miden *Entero* y *Agregar* juntos, con su `gap`: la columna es fija por la tabla, así que
   las filas sin envase también la tienen, con *Agregar* en el mismo lugar que las que sí. */
.catalogo-servicios .agregar-catalogo {
    width: 12rem;
    text-align: right;
}

.catalogo-servicios tbody tr:last-child > * {
    border-bottom: 0;
}

.catalogo-servicios tbody tr:hover > * {
    background: var(--menta-suave);
}

.control-catalogo {
    position: relative;
    display: inline-block;
}

/* Los dos botones uno al lado del otro y pegados a la derecha: *Agregar* es siempre el último, así
   que cae en el mismo lugar en todas las filas. El aviso de *Agregado* tapa el control entero —los
   dos botones cuando hay dos—, que es lo que se acaba de apretar. */
.control-catalogo form {
    display: flex;
    justify-content: flex-end;
    gap: 0.35rem;
}

/* `.boton-tabla` nace al 100 % de su celda; acá comparten una, así que cada uno mide lo suyo.
   *Agregar* lleva un piso porque el aviso de *Agregado* se dibuja encima y en una fila sin envase
   tiene que caber en él solo. */
.control-catalogo .boton-tabla {
    width: auto;
}

.control-catalogo .boton-agregar {
    min-width: 6rem;
}

.confirmacion {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.3rem;
    border: 1px solid var(--turquesa);
    border-radius: 0.3rem;
    background: var(--menta-suave);
    color: var(--turquesa-profundo);
    font-size: 0.85rem;
    font-weight: 600;
    opacity: 0;
    pointer-events: none;
}

.confirmacion::before {
    content: "✓";
    font-weight: 700;
}

.confirmacion.visible {
    animation: confirmar 1.6s ease-out;
}

@keyframes confirmar {
    0%   { opacity: 0; }
    15%  { opacity: 1; }
    70%  { opacity: 1; }
    100% { opacity: 0; }
}

/* Quien pidió no ver animaciones igual necesita la señal: se queda quieta y se va sin
   transición. */
@media (prefers-reduced-motion: reduce) {
    .confirmacion.visible {
        animation: confirmar 1.6s step-end;
    }
}

h2.categoria {
    margin: 1.75rem 0 0;
    font-size: 0.8rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--texto-tenue);
}

h2.categoria + table {
    margin-top: 0.25rem;
}

@media screen and (max-width: 32rem) {
    .catalogo-servicios,
    .catalogo-servicios tbody {
        display: block;
        overflow: visible;
    }

    .catalogo-servicios tr {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-areas:
            "servicio precio"
            "servicio accion";
        gap: 0.35rem 1rem;
        padding: 0.7rem 0.4rem;
        border-bottom: 1px solid var(--borde);
    }

    .catalogo-servicios th,
    .catalogo-servicios td {
        width: auto;
        padding: 0;
        border-bottom: 0;
    }

    .catalogo-servicios .servicio-catalogo {
        grid-area: servicio;
        align-self: center;
    }

    .catalogo-servicios .precio-catalogo {
        grid-area: precio;
    }

    .catalogo-servicios .agregar-catalogo {
        grid-area: accion;
    }

    .catalogo-servicios tbody tr:last-child {
        border-bottom: 0;
    }
}

/* El `th[scope="row"]` va con los `td`: es la celda del nombre, y una fila retirada con el
   nombre a plena tinta y el resto apagado se lee como si estuviera a medio cargar.

   El `tbody` está por la misma razón, un nivel más arriba: donde un registro son dos filas —el
   carnet—, apagar solo la primera dejaba el lote y quién la puso a plena tinta debajo de una
   línea gris, que es el mismo efecto de "a medio cargar" que esta regla vino a evitar. */
tr.inactiva td,
tr.inactiva th[scope="row"],
tbody.inactiva td,
tbody.inactiva th[scope="row"] {
    color: var(--texto-tenue);
}

/* La cantidad de una línea se edita dentro de la tabla del presupuesto, así que el input no
   puede llevar el ancho completo ni el margen que tiene en un formulario. */
.cantidad input {
    width: 4.5rem;
    margin: 0;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* El detalle repite la misma lógica visual del catálogo: la descripción absorbe el ancho
   disponible y las cifras y la acción conservan una columna estable para poder compararlas. */
.detalle-presupuesto {
    table-layout: fixed;
}

.detalle-presupuesto th,
.detalle-presupuesto td {
    vertical-align: middle;
}

/* Algo más apretada que el resto de las tablas, como la cola de cobro: con la unidad al lado de la
   cantidad (hallazgo 119) las seis columnas no cabían, y el relleno lateral es el único ancho que
   no es de ningún dato. */
.detalle-presupuesto th,
.detalle-presupuesto td {
    padding-left: 0.45rem;
    padding-right: 0.45rem;
}

/* Las líneas se alinean por la primera línea de cada celda y no por el centro (hallazgo 119): la
   casilla de la cantidad, el selector de responsable, las cifras y el botón quedan en la misma
   altura aunque una celda tenga un renglón de más abajo —la unidad que no cupo al lado, o el
   nombre de un servicio largo—. Centradas, esa celda subía su casilla y la fila se veía torcida. */
.detalle-presupuesto tbody th,
.detalle-presupuesto tbody td {
    vertical-align: baseline;
}

/* La descripción no lleva ancho: absorbe lo que dejan las cinco columnas fijas. Cuando esas
   sumaban casi toda la tabla le quedaban ~4rem, "Esterilización canina hembra" caía en tres
   renglones y la palabra larga se salía de la celda hasta pisar el selector de "Quién lo hizo".
   Se le devolvió aire recortando las cifras y la acción a lo que miden sus datos, y por si un
   nombre de servicio aún no cabe, que la celda parta la palabra antes que invadir la vecina. */
.detalle-presupuesto .item-detalle {
    overflow-wrap: break-word;
}

/* **8,75rem y no 6 desde el 03-10** (hallazgo 119): es lo que miden la casilla y «aplicación» al
   lado, la unidad de las pipetas. Lo pagaron el relleno de arriba, el selector de responsable, que
   tenía de sobra, y la acción; la descripción quedó casi igual. «aplicaciones», la única más larga,
   baja. */
.detalle-presupuesto .cantidad-detalle {
    width: 8.75rem;
}

/* La casilla, a lo que mide una cantidad de esta tabla —«60», «0,5», «100»— y no a las 4,5rem de un
   formulario: el ancho que sobra es el que necesita la unidad. */
.detalle-presupuesto .cantidad input {
    width: 3.75rem;
}

.cantidad-con-unidad .tenue {
    font-size: 0.85rem;
}

/* La casilla y su unidad en una fila, pegadas a la derecha como las cifras (hallazgo 119). Si la
   unidad no cabe al lado —«aplicaciones» es la más larga— baja ella, y la casilla se queda donde
   está: por eso la fila de la tabla se alinea por la primera línea y no por el centro, más abajo. */
.cantidad-con-unidad {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: flex-end;
    gap: 0 0.3rem;
}

/* Quién ejecutó la línea. El select va al ancho de la columna —con `table-layout: fixed` un
   nombre largo la desbordaría— y sin el margen que tiene en un formulario, igual que el input
   de cantidad. */
.detalle-presupuesto .ejecutor-detalle {
    width: 9.75rem;
}

.detalle-presupuesto .ejecutor-detalle select {
    width: 100%;
    margin: 0;
}

/* Ajustadas a lo que mide un monto de esta clínica —"$130.000", y con margen para siete cifras—
   en vez de las 7rem holgadas de antes: el sobrante se le devolvió a la descripción, que era la
   que se quedaba sin ancho. `.numero` las mantiene sin cortar. */
.detalle-presupuesto .precio-detalle,
.detalle-presupuesto .monto-detalle {
    width: 6rem;
}

/* La acción lleva "Quitar" y, en las líneas de servicio con kit, también "Kit"; su piso lo pone el
   botón más ancho, no un ancho elegido, así que se apretó hasta ahí para no robarle columna a la
   descripción. **5,25rem desde el 03-10**: con el relleno más angosto de esta tabla, *Quitar* —66 px—
   cabía con 16 de sobra, y ese sobrante es lo que le faltaba al selector de responsable para que
   «Paula Contreras» no se cortara cuando la cantidad se ensanchó (hallazgo 119). */
.detalle-presupuesto .accion-detalle {
    width: 5.25rem;
    text-align: right;
}

/* Los dos gestos de una línea de servicio —«Quitar» y «Kit»— se apilan, y hasta el 05-09 se
   apilaban **pegados y de anchos distintos**: el `form` de Quitar traía un ancho fijo de 4,75rem y
   el enlace del Kit, hijo directo de la celda, ocupaba los 6rem enteros. Dos botones sin aire entre
   medio se leen como un control partido, y el más ancho parece el que manda cuando el que manda es
   el otro. Ahora **la columna manda el ancho** —los dos al 100% de la celda— y el aire lo pone el
   margen del segundo, que sólo existe cuando hay segundo.

   **No con `display:flex` en el `td`**, que era la forma corta: un `td` que deja de ser celda sale
   del modelo de tabla y el navegador le fabrica una celda anónima, así que la columna deja de
   alinearse con su `<th>`. El margen no toca el modelo de nada. */
.detalle-presupuesto .accion-detalle form {
    width: 100%;
}

.detalle-presupuesto .accion-detalle > a.boton-tabla {
    margin-top: 0.35rem;
}

/* El total cierra la tabla: sin la línea de abajo, que ya no separa nada, y sin el gris de
   encabezado que lo dejaría más apagado que las líneas que suma. */
tfoot th,
tfoot td {
    border-bottom: 0;
    color: var(--texto);
    font-size: 1rem;
    font-weight: 600;
    text-transform: none;
    letter-spacing: normal;
}

/* ---------------------------------------------------------------------------
   El buscador de fichas

   Mismo criterio que el catálogo del presupuesto, y por el mismo motivo: el listado se vuelve a
   dibujar con cada tecla, así que con anchos automáticos las columnas se recalculan a mitad de
   la búsqueda y lo que se estaba leyendo se corre de sitio. Folio, especie y microchip miden lo
   que miden sus datos —el microchip son quince dígitos y no crece—, y paciente y tutor se
   reparten lo que sobra.

   Van dentro de una consulta de ancho porque solo aplican donde hay ancho que repartir: bajo
   40rem la tabla ya se desplaza sola dentro de su sección, y ahí imponerle veinte rem de mínimo
   entre tres columnas es garantizarle el desplazamiento lateral en vez de dejarla apretarse.
   --------------------------------------------------------------------------- */
@media (min-width: 40rem) {
    .tabla-fichas {
        table-layout: fixed;
    }

    .tabla-fichas .folio-ficha {
        width: 4rem;
    }

    .tabla-fichas .especie-ficha {
        width: 5rem;
    }

    .tabla-fichas .microchip-ficha {
        width: 9.5rem;
    }

    /* La columna del botón existe solo cuando esta tabla la abre una hora de la agenda que viene a
       buscar su ficha. Lleva ancho propio porque con `table-layout: fixed` el `width: 1%` con el
       que `.columna-accion` se encoge en las tablas automáticas se toma al pie de la letra: el
       botón se salía de su celda y quedaba encima de la columna del tutor. */
    .tabla-fichas .columna-accion {
        width: 6.5rem;
    }
}

/* La que manda el alto de la fila es la del tutor, que lleva dos líneas. Las demás se centran
   contra ella en vez de colgar del borde de arriba: así ficha, paciente, marca, especie y
   microchip se leen sobre un mismo eje y no escalonados. */
.tabla-fichas td {
    vertical-align: middle;
}

/* Nombre y marca, en ese orden y sin posibilidad de que la marca baje: es una fila flex que no
   envuelve, así que un nombre que no quepa se parte él y la marca se queda a su derecha. Corrido
   como texto suelto, era el largo del nombre el que decidía dónde caía la marca. */
.con-marca {
    display: flex;
    align-items: center;
    gap: 0.4rem;
}

.con-marca > .etiqueta {
    flex: none;
}

/* El tutor sí va en dos líneas: el RUT se compara dígito a dígito contra el papel que trae el
   tutor, y detrás del nombre el navegador lo partía por la mitad. Debajo empieza siempre en el
   mismo punto y se puede recorrer la columna con la vista. */
.apilado {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.25rem;
}

/* ---------------------------------------------------------------------------
   Cambio de tema
   --------------------------------------------------------------------------- */

/* Nace oculto y lo muestra tema.js: sin JavaScript el botón no haría nada, y un control
   muerto en la barra es peor que no tenerlo. */
.tema[hidden] {
    display: none;
}

.tema {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin: 0;
    padding: 0.35rem;
    border-radius: 0.3rem;
    background: none;
    color: var(--texto-tenue);
    cursor: pointer;
}

.tema:hover {
    filter: none;
    background: var(--menta-suave);
    color: var(--turquesa-profundo);
}

.tema svg {
    width: 1.15rem;
    height: 1.15rem;
    display: none;
}

/* Solo se dibuja el icono del estado actual: automático, claro u oscuro. */
.tema[data-estado="sistema"] .icono-sistema,
.tema[data-estado="claro"] .icono-claro,
.tema[data-estado="oscuro"] .icono-oscuro {
    display: block;
}

/* Para lectores de pantalla: el estado del tema se anuncia, pero en la barra lo dice el
   icono. */
.visualmente-oculto {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/* El caption de una tabla es la única excepción: se oculta igual, pero sin salirse del flujo.
   Con `table-layout: fixed` y sin `<colgroup>`, los anchos de columna salen de las celdas de la
   primera fila, y un caption absoluto se los hace perder: el navegador reparte la tabla en
   partes iguales y los `width` declarados no se aplican nunca. Eso dejaba el catálogo del
   presupuesto con tres columnas de 229px —"Esterilización canina hasta 15 kg" partido en dos
   líneas con 220px libres al lado— en vez de las de 450, 112 y 124 que pide el bloque del
   catálogo. Las tablas que sí declaran `<colgroup>` —usuarios y servicios— nunca dependieron de
   la primera fila y miden igual con o sin esto. Recortado a 1px ocupa lo mismo quieto que
   absoluto, y el lector de pantalla lo sigue anunciando. */
caption.visualmente-oculto {
    position: static;
}

/* La sección de la barra donde está parado el usuario. */
.barra a.actual {
    color: var(--turquesa-profundo);
    font-weight: 600;
}

tbody tr:hover td {
    background: var(--menta-suave);
}

/* La última línea de la tabla no separa nada de lo que viene abajo: es el borde de la
   sección el que cierra.

   **Nombra `> *` y no `td`, desde el 08-09-2026**, porque decía `td` y en las tablas cuyo primer
   dato encabeza su fila —la matriz de tasas, el catálogo, los usuarios, el inventario: veinte
   plantillas con `th[scope="row"]`— apagaba las celdas de dato y dejaba viva la del encabezado.
   El resultado era una rayita que cruzaba sólo la primera columna y se cortaba a la mitad de la
   tabla. **Un borde que llega hasta el final de una columna no es una decisión de nadie**, y
   estaba en todas partes: sobrevivió porque bajo el título de un grupo la tapaba la línea que ese
   título dibujaba, y se vio el día que el título dejó de dibujarla.

   En las tablas con un `<tbody>` por grupo esto apaga la última fila de **cada** grupo, que es lo
   que ya hacía con las celdas de dato: la separación entre grupos la pone el aire del título
   siguiente, no una línea. `.registro-en-dos-filas` no se entera —ya apaga todas sus celdas por su
   cuenta y monta el borde en el `<tbody>`, por esta misma razón y con este mismo argumento.

   **Y no es la primera vez que se arregla: es la cuarta.** `.catalogo-servicios`, `.tabla-usuarios`
   y `.tabla-servicios` traen las tres, cada una por su lado y sin comentario, este mismísimo
   `tbody tr:last-child > *` con su tabla por delante. Tres pantallas toparon con lo mismo, lo
   parcharon en su rincón y ninguna volvió a mirar la regla general —que es exactamente cómo un
   defecto de una regla compartida se vuelve invisible: cada quien lo esquiva y nadie lo cuenta—.
   Las tres quedan redundantes desde hoy; se borran la próxima vez que se toque cada pantalla, que
   es lo que esta hoja ya hace con `.tabla-usuarios .fila-rol`: no se desarma una pantalla ya
   verificada por algo que no es suyo. */
table:not(:has(tfoot)) tbody tr:last-child > * {
    border-bottom: 0;
}

/* En pantalla angosta las cuatro columnas de una tabla de montos no caben, y la página
   entera termina desplazándose de lado. Primero se recupera ancho apretando los rellenos;
   la tabla que aun así no quepa se desplaza sola dentro de su sección, que es lo que evita
   que el encabezado y el resto del contenido se vayan con ella. */
@media screen and (max-width: 40rem) {
    main {
        padding: 1.5rem 0.9rem;
    }

    section {
        padding: 1rem;
    }

    th,
    td {
        padding: 0.5rem 0.4rem;
    }

    /* Ojo con el selector: **ningún listado de la aplicación vive dentro de un `section`** —en la
       cola, en fichas y en usuarios el `</section>` cierra antes de la tabla—, así que esta regla
       no alcanza a ninguno y `.tabla-ancha` es la que hace el trabajo ahí. Ésta cubre las tablas
       de detalle y de formulario, que sí están adentro. */
    section table,
    form table {
        /* `relative` no coloca nada: encierra. Los títulos que solo oye un lector de pantalla
           —el `caption` de una tabla agrupada, el "Acción" de la columna del botón— van en
           `position: absolute`, y sin un ancestro posicionado se sitúan respecto de la página.
           Quedan a la derecha de la tabla desplazada, fuera del ancho del teléfono, y arrastran
           de lado justo lo que este bloque existe para no mover. */
        position: relative;
        display: block;
        overflow-x: auto;
    }
}

/* Un listado que no cabe se desplaza dentro de su marco en vez de arrastrar la página con él.

   Se descubrió el 11-08 en la bandeja de problemas: con la espera del outbox metida en la celda,
   su tabla se salía 189 px en un teléfono y lo que se movía de lado era el documento entero, con
   el encabezado y la barra incluidos. La regla de arriba dice hacer exactamente esto y no la
   alcanzaba, porque pide un `section` que ningún listado tiene.

   Envoltorio, y no `display: block` sobre la tabla: así conserva su reparto de columnas, y los
   títulos que solo oye un lector de pantalla siguen dentro de un ancestro que los contiene. Va sin
   `@media` porque `auto` no dibuja nada mientras la tabla quepa, y sin `tabindex`: los navegadores
   actuales dan foco solos a una zona que se puede desplazar, y un tabulador muerto en cada
   listado ancho costaría más de lo que arregla. */
.tabla-ancha {
    overflow-x: auto;
}

/* La portada del login: el símbolo hace de encabezado y el nombre va debajo. */
.portada {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.35rem;
    margin-bottom: 1.5rem;
    text-align: center;
}

.portada svg {
    width: 4rem;
    height: 4rem;
}

.portada h1 {
    margin: 0;
    font-size: 1.6rem;
    letter-spacing: 0.01em;
}

.portada p {
    margin: 0;
    font-size: 0.9rem;
}

/* En el login no hay barra donde colgar el cambio de tema, y sigue haciendo falta: el
   computador de recepción se configura una vez, desde la pantalla de entrada. */
.tema-esquina {
    position: absolute;
    top: 0.6rem;
    right: 0.75rem;
}

/* El desglose tributario: pocas cifras, alineadas a la derecha y sin competir con el total
   de la tabla, que es el número que se cobra. */
dl.desglose {
    grid-template-columns: max-content 7rem;
    justify-content: end;
    margin-top: 0.75rem;
    font-size: 0.9rem;
}

dl.desglose dd {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* En el mesón los cuatro importes se comparan antes de cobrar. Cantidad conserva su ancho y
   precio, monto y desgloses comparten una guía de siete rem, sin inmovilizar toda la tabla. */
.tabla-cobro .cantidad-cobro {
    width: 6rem;
}

.tabla-cobro .precio-cobro,
.tabla-cobro .monto-cobro {
    width: 7rem;
}

/* Un cobro mixto se lee como una lista corta de comprobantes, no como una sola grilla que
   accidentalmente ganó más columnas. El borde conserva juntas las tres piezas de cada pago
   cuando hay varios y sigue usando las mismas superficies en tema claro y oscuro. */
.lista-medios-cobro {
    display: grid;
    gap: 1rem;
}

.medio-cobro {
    padding: 1rem;
    border: 1px solid var(--borde);
    border-radius: 0.55rem;
    background: var(--superficie);
}

.medio-cobro legend {
    padding: 0 0.4rem;
    color: var(--texto);
    font-family: var(--fuente-marca);
    font-weight: 700;
}

.acciones-del-medio {
    justify-content: flex-end;
    margin-top: 0.35rem;
}

/* La factura es del cobro entero y no de un medio, así que va fuera de la lista de medios y con
   la misma superficie: dentro de `.lista-medios-cobro` se leía como un cuarto comprobante y en
   un cobro mixto invitaba a creer que se factura solo esa porción. */
.factura-cobro {
    margin-top: 1rem;
    padding: 1rem;
    border: 1px solid var(--borde);
    border-radius: 0.55rem;
    background: var(--superficie);
}

.factura-cobro legend {
    padding: 0 0.4rem;
}

/* La casilla y su texto forman un solo blanco de clic. En el mesón se marca al vuelo mientras el
   tutor dicta, y un cuadrito de un centímetro obliga a apuntar con el mouse. */
.casilla {
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    color: var(--texto);
    font-family: var(--fuente-marca);
    font-weight: 700;
    cursor: pointer;
}

/* Un poco más grande que la de fábrica: esta casilla abre los cinco datos del receptor y se marca
   mientras el tutor los dicta. El `accent-color` que estaba acá se subió al selector general de
   casillas y opciones, donde alcanza también a las otras ocho de la aplicación. */
.casilla input[type="checkbox"] {
    width: 1rem;
    height: 1rem;
}

/* Los cinco datos del receptor separados de la casilla que los abre: sin el aire, el bloque
   aparecía pegado al borde del fieldset y parecía parte de la etiqueta. */
#datos-del-receptor {
    margin-top: 0.75rem;
}

/* El comprobante lleva el texto más largo y necesita más aire que el monto. En ancho estrecho
   vuelve a mandar la grilla adaptable de `.campos`, que apila sin comprimir los controles. */
@media (min-width: 40rem) {
    .campos-del-medio {
        grid-template-columns: minmax(8rem, 0.85fr) minmax(10rem, 1fr) minmax(14rem, 1.3fr);
    }
}

/* Agregar un medio y comprobar el saldo son el mismo cierre del reparto del pago. La línea los
   reúne sin convertirlos en otra tarjeta dentro de la sección. */
.pie-medios-cobro {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: end;
    gap: 1rem 2rem;
    margin-top: 0.85rem;
    padding-top: 0.85rem;
    border-top: 1px solid var(--borde);
}

.acciones-medios-cobro {
    margin-top: 0;
}

dl.resumen-del-cobro {
    margin-top: 0;
}

@media screen and (max-width: 40rem) {
    .pie-medios-cobro {
        grid-template-columns: 1fr;
        align-items: start;
    }

    dl.resumen-del-cobro {
        width: 100%;
    }
}

.error-en-linea {
    color: var(--rojo-profundo);
    font-weight: 700;
}

/* El estado del presupuesto se busca de un vistazo desde recepción, y para eso el color
   tiene que decir algo antes que la palabra.

   `pagada` es el presupuesto pagado entero de una hora del calendario (Z5): comparte el relleno
   turquesa porque es el extremo de la misma escala —sin pagar en ámbar, en parte con el contorno
   turquesa, pagado en turquesa— y va con nombre propio porque en la agenda no hay estados de
   presupuesto con los que confundirlo, pero sí en la cola de cobro. */
.etiqueta.estado-emitido,
.etiqueta.pagada {
    background: var(--turquesa);
    color: var(--sobre-turquesa);
}

/* El presupuesto pagado en parte, en la misma escala (hallazgo 126). Iba con la etiqueta base, y
   su menta es el mismo fondo de la celda de una hora tomada: en el turno de noche quedaba el texto
   suelto, sin píldora, al lado de la ámbar y la turquesa. El contorno es el turquesa de «pagado»
   sin rellenar —a medio camino, que es lo que dice—, y el fondo es la superficie y no la menta para
   que la píldora se despegue de la celda en los dos temas. */
.etiqueta.en-parte {
    background: var(--superficie);
    border: 1px solid var(--turquesa-profundo);
    color: var(--turquesa-profundo);
}

/* `apagada` es el estado del paciente que cerró su historial. Comparte el gris con el
   presupuesto anulado porque dice lo mismo —esto ya no está en curso— y tiene nombre propio
   porque no es lo mismo: una ficha no se anula. */
.etiqueta.estado-anulado,
.etiqueta.apagada {
    background: var(--borde);
    color: var(--texto-tenue);
}

/* Ámbar de "revisar": algo que hay que mirar y que ya ocurrió —no es urgencia—. La caja cerrada
   con diferencia es el caso que lo trajo: un faltante es la fila que el admin tiene que pescar
   entre todas las verdes, y antes reusaba el gris de `estado-anulado` —el de lo muerto, un
   presupuesto anulado—, que la hacía recederse justo cuando tiene que saltar. No va en rojo porque
   el rojo de la paleta es "hay que hacer algo ahora" —frasco vencido, paciente extraviado, boleta
   en duda— y una caja ya cerrada, con su faltante registrado, no lo es. */
.etiqueta.revisar {
    background: var(--ambar-suave);
    color: var(--ambar-profundo);
}

/* El día que se acabó sin que nadie declarara el arqueo, en el historial de cierres. Ámbar como
   `revisar` porque pide lo mismo —mirar algo que ya ocurrió, sin urgencia—, y con contorno en vez
   de relleno por lo mismo que `sin-salida`: las dos filas que el historial tiene que hacer saltar
   son esta y la cerrada con diferencia, y con el relleno ámbar en las dos se leían como la misma
   cosa. No lo son —en una hay un número escrito que se investiga, en la otra no hay arqueo y
   alguien tiene que ir a contar— y el historial existe justo para separarlas. */
.etiqueta.sin-arqueo {
    background: none;
    border: 1px solid var(--ambar-profundo);
    color: var(--ambar-profundo);
}

/* El refuerzo atrasado y el frasco vencido son las dos cosas del carnet que hay que ver sin
   leer. Van en el rojo de la paleta —que es color de señal oficial, no uno inventado para la
   ocasión— y no en menta, porque menta acá diría "todo en orden".

   `alerta` es el mismo rojo para el paciente extraviado, y por el mismo motivo: es la única
   marca de la ficha que pide hacer algo ahora —llamar al tutor del perro que acaban de traer—.
   Van juntas para que nadie tenga que acordarse de cambiar dos rojos. */
.etiqueta.atrasada,
.etiqueta.alerta {
    background: var(--rojo-suave);
    color: var(--rojo-profundo);
}

/* El reverso de un pago no es un estado muerto como "anulado": es un movimiento que ocurrió
   y que mueve plata. Va con contorno y no con relleno para que se distinga de un vistazo de
   la fila anulada que tiene justo encima, que era el problema: dos etiquetas grises con
   nombres casi iguales se leían como la misma cosa repetida. */
.etiqueta.reverso {
    background: none;
    border: 1px solid var(--texto-tenue);
    color: var(--texto-tenue);
}

/* El trabajo que salió y no sabemos si ocurrió, en la bandeja de problemas. Es el mismo truco
   del reverso y por la misma razón, esta vez en rojo: "esperando a una persona" y "en duda" son
   las dos filas que piden atención, y con el rojo relleno de `alerta` en las dos se leían como
   la misma cosa. No lo son —una se arregla apretando "reintentar" y la otra no se puede
   reintentar nunca, que es el ADR-021 entero— y el contorno es lo que dice que acá no hay botón
   que apretar. */
.etiqueta.sin-salida {
    background: none;
    border: 1px solid var(--rojo-profundo);
    color: var(--rojo-profundo);
}

/* En qué está el intento, debajo del problema tributario que explica. Separado del texto de
   arriba porque son dos cosas distintas —qué le falta a la venta y qué está haciendo Vetika al
   respecto— y pegados se leían como una sola frase larga. */
.espera {
    /* Sin `margin-bottom`, y por eso va explícito: no hay reset de `p` en este archivo, así que el
       1em que pone el navegador dejaba un renglón muerto al pie de la celda y descolgaba el monto
       de la fila de al lado. */
    margin: 0.4rem 0 0;
}

/* ---------------------------------------------------------------------------
   Confirmar lo ejecutado, al cerrar la atención
   --------------------------------------------------------------------------- */

/* Un bloque por línea de servicio y no una tabla. Cada línea pregunta cuatro cosas —qué pasó,
   cuándo, quién y a veces por qué— y en 48rem eso son seis columnas que aprietan el nombre del
   servicio, que es lo único que se busca con la vista, hasta partirlo en tres renglones. */
.lista-por-confirmar {
    display: grid;
    gap: 1rem;
}

/* Un grupo de campos que se despega de la superficie que lo contiene. Es el mismo bloque que
   `.medio-cobro` y `.factura-cobro`, escrito acá **sin nombre de pantalla** porque es el tercero
   igual; las dos del cobro quedan pendientes de doblarse a esta la próxima vez que se toque esa
   pantalla, como `.tabla-usuarios .fila-rol` con `.fila-grupo`. */
.bloque-de-campos {
    padding: 1rem;
    border: 1px solid var(--borde);
    border-radius: 0.55rem;
    background: var(--superficie);
}

/* `>` y no a secas: adentro hay otro fieldset con su propio legend —las tres opciones— y con el
   selector suelto ese «Qué pasó» salía en Nunito Sans en negrita, compitiendo con el nombre del
   servicio que encabeza el bloque. */
.bloque-de-campos > legend {
    padding: 0 0.4rem;
    color: var(--texto);
    font-family: var(--fuente-marca);
    font-weight: 700;
}

/* El monto y el folio de la línea. Sin esto, el 1em que el navegador le pone a un `p` deja dos
   renglones muertos entre el nombre del servicio y su primera pregunta. */
.bloque-de-campos p {
    margin: 0.3rem 0;
}

/* El fieldset de las opciones no dibuja caja: la caja ya la pone el bloque de la línea, y una
   segunda adentro se lee como si fueran dos servicios. */
.gesto-del-servicio {
    margin: 0.7rem 0 0.2rem;
    padding: 0;
    border: 0;
}

.gesto-del-servicio legend {
    padding: 0;
}

/* Las tres en fila mientras quepan, apiladas cuando no. Apiladas siempre eran tres renglones por
   servicio: una atención de cinco líneas se iba a dos pantallas de alto, justo en el momento en
   que hay alguien esperando en el box. */
.opciones-del-gesto {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem 1.25rem;
    margin-top: 0.2rem;
}

/* El motivo nace visible y lo esconde `motivo-del-gesto.js` mientras no se marque «no se realizó».
   Sin `hidden` propio en el CSS: el atributo del HTML basta porque esta regla no fija `display`,
   y así el campo sigue a la vista cuando el script no corre, que es la degradación segura. */
.motivo-del-gesto {
    margin-top: 0.6rem;
}

/* El reparto entre varias personas (K5). El `fieldset` no dibuja caja —la regla general de arriba
   ya lo deja sin ella, que es lo que corresponde acá por lo mismo que en `.gesto-del-servicio`: la
   caja la pone el bloque de la línea, y una segunda adentro se lee como si fueran dos servicios—.
   Lo único suyo es el margen de arriba, y su porqué está dos párrafos más abajo.

   «Quién lo hizo» es la misma pregunta que «Cuándo se hizo», que está en la columna de al lado, y
   tiene que pesar igual. Con el estilo que el navegador le da a un `legend` salía más grande y
   medio renglón más arriba, y las dos preguntas dejaban de leerse como pareja.

   **El desnivel se empuja desde el `fieldset` y no desde el `legend`**: el navegador no le aplica
   el margen de arriba a un `legend`, así que la regla lo pedía y no movía nada —la pregunta de la
   derecha quedaba los mismos 0,9rem más arriba que la de la izquierda, y el selector no coincidía
   con el campo de fecha—. El `fieldset` sí es un elemento de la grilla, como el `div` de al lado,
   y empujarlo a él baja la pregunta y su selector juntos. Lo encontró la §25 el 25-08 mirando la
   pantalla: es exactamente lo que ninguna prueba automática puede decir. */
.reparto {
    margin-top: 0.9rem;
}

.reparto > legend {
    padding: 0;
    margin-top: 0;
    font-size: 0.9rem;
}

/* Persona y porcentaje en una fila. Envuelve en vez de apretar: en el teléfono, un selector de
   nombres comprimido a dos letras es justo el dato que hay que comprobar antes de acreditar plata.

   El margen es el mismo `0.25rem` que todo campo lleva bajo su etiqueta, y no uno propio: es lo que
   deja el selector a la altura exacta del campo de fecha de la columna de al lado. Con 0,35 sobraba
   un pelo y las dos columnas volvían a leerse desparejas después de emparejar las preguntas. */
.fila-del-reparto {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.25rem;
}

/* Cada persona como un bloque, y no como una línea más, cuando el reparto tiene varias.

   La fila se envuelve en cuanto lleva rol y porcentaje, así que el porcentaje, el monto y «Quitar»
   caen a un segundo renglón, y ese renglón quedaba a la misma distancia de la persona de arriba que
   de la de abajo: mirando la pantalla no se podía decir a cuál pertenecía «Quitar» (30-08). No es un
   problema de estética —es el botón que saca a alguien de la plata de una cirugía—.

   **El aire se compara contra el `row-gap` de la propia fila, que son 0,5rem, y no contra el margen
   que había antes.** El primer intento del 30-08 subió el margen de 0,25 a 0,55rem creyendo que con
   eso separaba «más», y en pantalla las dos distancias quedaron iguales: el `gap: 0.5rem` de
   `.fila-del-reparto` gobierna **también** el salto entre sus dos renglones cuando envuelve, y
   0,55rem no le gana a 0,5rem. Con 1rem, dos personas quedan al doble de lo que separa a una fila de
   su propia continuación, que es la comparación que el ojo hace de verdad.

   La barra y el sangrado acompañan, y por eso no hay caja: adentro ya hay dos —la del registro y la
   del `fieldset`— y una tercera se leería como otro servicio, que es lo mismo que decide
   `.gesto-del-servicio` dos bloques más arriba.

   **3px y no 2, que es el filete del sistema** (`.hecho-vigente`). **Y neutro y no turquesa**,
   aunque aquél lo use: dentro de esta misma caja el turquesa ya significa *«esto es lo que hay que
   leer antes de tocar nada»*, y repetirlo por persona le quitaría a esa frase lo único que la hace
   saltar. */
.fila-del-reparto.de-varias {
    margin-top: 1rem;
    padding-left: 0.6rem;
    border-left: 3px solid var(--borde);
}

/* El selector se lleva lo que sobre. `min-width: 0` porque sin él un nombre largo estira la fila y
   saca la pantalla de sus 48rem, que es lo que el `main` no puede hacer. */
.fila-del-reparto select {
    flex: 1 1 8rem;
    min-width: 0;
    margin-top: 0;
}

/* El nombre de la persona pesa más que el rol, y el primer `select` de la fila es siempre él.
   Con el reparto de K5 —un selector, un número y un botón— los 8rem alcanzaban. L5 le agregó a la
   fila **el selector del rol y un segundo botón**, los dos selectores se repartieron el sobrante
   por igual, y el que se cortó fue el largo: en la corrida del 28-08 se leía «Vania Veterinaria»
   sin la última letra y «Amador Adminis», mientras «Cirujano» sobraba de ancho. Se corta el que
   hay que leer antes de acreditar plata, y los nombres de rol son cortos por naturaleza —el tope
   de 40 caracteres es una guarda contra el dedazo, no un ancho de trabajo—. */
.fila-del-reparto select:first-of-type {
    flex: 2 1 11rem;
}

.peso-del-reparto {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

/* Ancho fijo y chico: son tres dígitos y dos decimales. Suelto dentro del flex se estiraba a media
   fila y el porcentaje parecía otro campo de texto. */
.peso-del-reparto input {
    width: 6rem;
    margin-top: 0;
}

/* Los botones del reparto no cierran ningún formulario, así que no llevan el margen de arriba que
   `button` trae para eso: acá los dejaba descolgados media línea bajo el selector de al lado. */
.fila-del-reparto button,
.acciones-del-reparto button {
    margin-top: 0;
    padding: 0.5rem 0.8rem;
    font-size: 0.9rem;
}

.acciones-del-reparto {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem 0.75rem;
    margin-top: 0.55rem;
}

/* «No se le acredita a nadie» es una respuesta y no un hueco, así que ocupa el lugar donde
   estarían las filas: el bloque en blanco no distingue esa decisión de que esto se haya roto. */
.sin-reparto {
    margin: 0.5rem 0 0;
}

/* Lo que la fila devenga, al final de la fila (L5, ADR-035 §7). Ancho mínimo y `margin-left: auto`
   para que los montos de las dos o tres filas queden alineados entre sí y contra el borde derecho:
   es el único dato de la fila que se compara de arriba abajo, y en el resto de la aplicación la
   plata ya se busca a la derecha. **Escrito de una y todavía sin ver en pantalla**: la pasada
   manual de L es la que dice si con dos participantes y un nombre largo esto se sostiene. */
.costo-de-la-fila {
    min-width: 4.5rem;
    margin-left: auto;
    color: var(--texto-tenue);
    font-size: 0.9rem;
}

/* El total del reparto, sobre el fondo de la página y no suelto como las notas de al lado: es la
   respuesta a lo que se está decidiendo —cuánto sale este reparto— y no un pie de página, así que
   se le da superficie propia en vez de dejarlo en `.tenue` con el resto de los avisos. Es una
   decisión de escritorio, no un ajuste después de mirarla. */
.costo-del-reparto {
    margin-top: 0.6rem;
    padding: 0.5rem 0.65rem;
    border-radius: 0.3rem;
    background: var(--fondo);
}

.costo-del-reparto p {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
    margin: 0;
    font-size: 0.9rem;
}

/* Los motivos van en lista y no corridos: son de cero a cuatro frases completas que vienen del
   mismo fragmento que usa el cierre del periodo, y una detrás de otra en un párrafo se leerían como
   una sola frase mal puntuada. */
.costo-del-reparto ul {
    margin: 0.35rem 0 0;
    padding-left: 1.1rem;
    font-size: 0.85rem;
}

/* ---------------------------------------------------------------------------
   Corregir lo ya confirmado (K4)
   --------------------------------------------------------------------------- */

/* Lo que el sistema afirma hoy sobre la línea, encima de un formulario que llega con esos mismos
   valores puestos. Va con fondo y no en `.tenue` como el resto de las notas: es la única frase de la
   pantalla que hay que leer antes de tocar nada, y en gris se confundía con el monto y el folio de
   arriba, que sí son contexto. */
.hecho-vigente {
    margin: 0.5rem 0 0;
    padding: 0.5rem 0.7rem;
    border-left: 3px solid var(--turquesa);
    border-radius: 0.3rem;
    background: var(--menta-suave);
    color: var(--turquesa-profundo);
}

/* El de la corrección se ve siempre, así que no hereda de `.motivo-del-gesto`: ese lo esconde un
   script mientras no se marque «no se realizó», y compartir la clase habría bastado para que la
   próxima vuelta de ese archivo escondiera un campo obligatorio de otra pantalla. */
.motivo-de-la-correccion {
    margin-top: 0.6rem;
}

/* Los dos gestos de un vínculo del art. 11 —«No era suyo» y «Sí era suyo»— con su motivo delante.
   **Es la misma pieza que `.fila-del-reparto.de-varias` y nace del mismo defecto**: sin aire propio,
   los botones de una venta quedaban a la misma distancia del folio de arriba que del de abajo, y con
   las ocho ventas de un tutor una tras otra había que contar hacia arriba para saber sobre cuál se
   estaba apretando. «No era suyo» saca el vínculo y no se deshace desde ninguna pantalla, así que es
   justo donde una agrupación ambigua no se puede dejar. El filete es neutro y no turquesa, por lo
   mismo que allá. */
.gesto-del-vinculo {
    margin: 0.6rem 0 1.4rem;
    padding-left: 0.6rem;
    border-left: 3px solid var(--borde);
}

/* El motivo se pide siempre y su rótulo vive en el `placeholder`, porque la etiqueta visible
   repetiría el nombre del vínculo que está una línea más arriba. Con el ancho que el navegador le da
   a un `input` suelto —unos veinte caracteres— la frase se cortaba en «Por qué esa venta no era
   su», o sea justo antes de la mitad que dice que el campo también sirve para confirmar. */
.gesto-del-vinculo input[type="text"] {
    width: 100%;
    max-width: 26rem;
}

/* Las constancias anteriores. Numerada y compacta: son pocas —una línea corregida dos veces ya es
   raro— y lo que se busca en ellas es la fecha y el nombre, no leerlas como prosa. */
.historial-del-hecho {
    margin-top: 0.7rem;
    font-size: 0.9rem;
}

.historial-del-hecho ol {
    margin: 0.4rem 0 0;
    padding-left: 1.2rem;
    display: grid;
    gap: 0.3rem;
}

/* Sin esto, `.mono` con su `letter-spacing` pega la hora contra el punto medio que la sigue. */
.historial-del-hecho .mono {
    margin-right: 0.15rem;
}

/* ---------------------------------------------------------------------------
   Usuarios
   --------------------------------------------------------------------------- */

.panel-usuarios {
    margin-top: 1.5rem;
}

.controles-usuarios {
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--borde);
}

.controles-usuarios > label:first-child {
    margin-top: 0;
}

label.filtro-inactivos {
    margin-top: 0.75rem;
}

.resultados-usuarios {
    margin-top: 0.75rem;
}

.tabla-usuarios {
    table-layout: fixed;
    margin-top: 0;
}

.tabla-usuarios .columna-persona {
    width: 31%;
}

.tabla-usuarios .columna-correo {
    width: 43%;
}

.tabla-usuarios .columna-estado {
    width: 26%;
}

.tabla-usuarios th,
.tabla-usuarios td {
    vertical-align: middle;
}

.tabla-usuarios .correo-usuario {
    overflow-wrap: anywhere;
}

/* Los cargos bajo el nombre, en su propia línea y sin la negrita del encabezado de fila (ADR-061 §3):
   corridos detrás del nombre, «Rodrigo Anestesista» se leía como un apellido. */
.tabla-usuarios .persona-usuario small {
    display: block;
    font-weight: normal;
}

.tabla-usuarios .estado-usuario {
    text-align: right;
}

.estado-usuario-contenido {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 0.35rem;
}

.estado-usuario-contenido .etiqueta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 1.5rem;
    line-height: 1;
}

.etiqueta.inicial {
    border: 1px solid var(--borde);
    background: transparent;
    color: var(--texto-tenue);
}

/* El encabezado de un grupo dentro de una tabla, sin tabla que lo acote: lo usa el listado de
   tasas de comisión, agrupado por a qué alcanza cada una. Va sin prefijo a propósito, porque el
   patrón no es de ninguna tabla en particular —lo mismo que ya pasó con `.columna-fecha`—.

   **Y hasta el 08-09-2026 este párrafo mentía**: las tasas —y la nómina de acuerdos, que llegó
   después copiándoles el marcado— escribían `fila-nivel` en el `<tr>`, una clase que no existe en
   esta hoja. Nadie lo notó porque un nombre de clase sin regla no falla: la fila cae en el estilo
   base de `th` y se dibuja, sólo que con el borde inferior puesto y sin el aire de arriba, o sea
   se lee como una fila más de datos en vez de como el título de un grupo. **Un selector que no
   calza con nada no sale rojo en ninguna parte**, y por eso el defecto sobrevivió a las dos
   pantallas; se vio mirándolas, no leyéndolas.

   `.tabla-usuarios .fila-rol`, acá abajo, es este mismo bloque con otro nombre y con scope. No se
   unificaron dentro de este cambio para no tocar una pantalla ya verificada por algo que no es
   suyo: la próxima vez que se toque el listado de usuarios, esa clase se dobla en esta.

   La segunda línea va tenue y sin versalita: dice por qué ese nivel le gana a los de abajo, y esa
   es la única parte de la cascada que no se deduce mirando las filas. */
.fila-grupo th {
    padding: 1.25rem 0.6rem 0.35rem;
    border-bottom: 0;
    color: var(--texto-tenue);
    font-size: 0.8rem;
    letter-spacing: 0.03em;
    text-transform: uppercase;
}

tbody:first-of-type .fila-grupo th {
    padding-top: 0.75rem;
}

.fila-grupo th .tenue {
    display: block;
    margin-top: 0.15rem;
    font-size: 0.75rem;
    font-weight: 400;
    letter-spacing: normal;
    text-transform: none;
}

.tabla-usuarios .fila-rol th {
    padding: 1.25rem 0.6rem 0.35rem;
    border-bottom: 0;
    color: var(--texto-tenue);
    font-size: 0.8rem;
    letter-spacing: 0.03em;
    text-transform: uppercase;
}

.tabla-usuarios tbody:first-of-type .fila-rol th {
    padding-top: 0.75rem;
}

.cantidad-rol {
    margin-left: 0.45rem;
    font-size: 0.75rem;
    font-weight: 400;
    letter-spacing: normal;
    text-transform: none;
}

.tabla-usuarios tbody tr:last-child > * {
    border-bottom: 0;
}

.tabla-usuarios tr:not(.fila-rol):hover > * {
    background: var(--menta-suave);
}

.tabla-usuarios tr.inactiva .persona-usuario a {
    color: var(--texto-tenue);
}

.resumen-usuarios {
    margin: 1rem 0 0;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.vacio-usuarios {
    margin: 0;
    padding: 1.5rem 0;
    text-align: center;
}

@media screen and (max-width: 40rem) {
    .tabla-usuarios,
    .tabla-usuarios tbody {
        display: block;
        overflow: visible;
    }

    .tabla-usuarios colgroup,
    .tabla-usuarios thead {
        display: none;
    }

    .tabla-usuarios .fila-rol {
        display: block;
    }

    .tabla-usuarios .fila-rol th {
        display: block;
        width: auto;
        padding-right: 0.4rem;
        padding-left: 0.4rem;
    }

    .tabla-usuarios tr:not(.fila-rol) {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-areas:
            "persona estado"
            "correo estado";
        gap: 0.15rem 1rem;
        padding: 0.7rem 0.4rem;
        border-bottom: 1px solid var(--borde);
    }

    .tabla-usuarios tr:not(.fila-rol) > * {
        width: auto;
        padding: 0;
        border-bottom: 0;
    }

    .tabla-usuarios tr:not(.fila-rol) .persona-usuario {
        grid-area: persona;
    }

    .tabla-usuarios tr:not(.fila-rol) .correo-usuario {
        grid-area: correo;
    }

    .tabla-usuarios tr:not(.fila-rol) .estado-usuario {
        grid-area: estado;
        align-self: center;
    }
}

/* ---------------------------------------------------------------------------
   Servicios
   --------------------------------------------------------------------------- */

.panel-servicios {
    margin-top: 1.5rem;
}

.controles-servicios {
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--borde);
}

.controles-servicios > label:first-child {
    margin-top: 0;
}

label.filtro-inactivos-servicios {
    margin-top: 0.75rem;
}

.resultados-servicios {
    margin-top: 0.75rem;
}

.tabla-servicios {
    table-layout: fixed;
    margin-top: 0;
}

.tabla-servicios .columna-servicio {
    width: 46%;
}

.tabla-servicios .columna-codigo {
    width: 18%;
}

.tabla-servicios .columna-precio {
    width: 17%;
}

.tabla-servicios .columna-estado-servicio {
    width: 19%;
}

.tabla-servicios th,
.tabla-servicios td {
    vertical-align: middle;
}

.descripcion-servicio {
    display: block;
    margin-top: 0.1rem;
    font-size: 0.85rem;
    font-weight: 400;
}

.tabla-servicios .codigo-servicio {
    overflow-wrap: anywhere;
}

/* De qué es el precio, debajo del precio y solo cuando no es «unidad». En su propia línea
   porque la columna es angosta y "$300 por mL" corrido se partía entre el número y la unidad,
   que es justo lo que no se puede separar: el precio del mililitro leído sin su unidad parece
   un servicio de $300. Hereda el `tabular-nums` de `.numero` sin arrastrar su `nowrap`. */
.unidad-servicio {
    display: block;
    margin-top: 0.1rem;
    font-size: 0.85rem;
    font-weight: 400;
}

.tabla-servicios .estado-servicio {
    text-align: right;
}

.estado-servicio-contenido {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 0.35rem;
}

.estado-servicio-contenido .etiqueta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 1.5rem;
    line-height: 1;
}

.etiqueta.exenta {
    border: 1px solid var(--borde);
    background: transparent;
    color: var(--texto-tenue);
}

.tabla-servicios .fila-categoria-servicio th {
    padding: 1.25rem 0.6rem 0.35rem;
    border-bottom: 0;
    color: var(--texto-tenue);
    font-size: 0.8rem;
    letter-spacing: 0.03em;
    text-transform: uppercase;
}

.tabla-servicios tbody:first-of-type .fila-categoria-servicio th {
    padding-top: 0.75rem;
}

.cantidad-categoria {
    margin-left: 0.45rem;
    font-size: 0.75rem;
    font-weight: 400;
    letter-spacing: normal;
    text-transform: none;
}

.tabla-servicios tbody tr:last-child > * {
    border-bottom: 0;
}

.tabla-servicios tr:not(.fila-categoria-servicio):hover > * {
    background: var(--menta-suave);
}

.tabla-servicios tr.inactiva .nombre-servicio,
.tabla-servicios tr.inactiva .nombre-servicio a {
    color: var(--texto-tenue);
}

.resumen-servicios {
    margin: 1rem 0 0;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.vacio-servicios {
    margin: 0;
    padding: 1.5rem 0;
    text-align: center;
}

.vacio-catalogo > :first-child {
    margin-top: 0;
}

@media screen and (max-width: 40rem) {
    .tabla-servicios,
    .tabla-servicios tbody {
        display: block;
        overflow: visible;
    }

    .tabla-servicios colgroup,
    .tabla-servicios thead {
        display: none;
    }

    .tabla-servicios .fila-categoria-servicio {
        display: block;
    }

    .tabla-servicios .fila-categoria-servicio th {
        display: block;
        width: auto;
        padding-right: 0.4rem;
        padding-left: 0.4rem;
    }

    .tabla-servicios tr:not(.fila-categoria-servicio) {
        display: grid;
        grid-template-columns: minmax(0, 1fr) auto;
        grid-template-areas:
            "servicio precio"
            "codigo estado";
        gap: 0.3rem 1rem;
        padding: 0.7rem 0.4rem;
        border-bottom: 1px solid var(--borde);
    }

    .tabla-servicios tr:not(.fila-categoria-servicio) > * {
        width: auto;
        padding: 0;
        border-bottom: 0;
    }

    .tabla-servicios tr:not(.fila-categoria-servicio) .nombre-servicio {
        grid-area: servicio;
    }

    .tabla-servicios tr:not(.fila-categoria-servicio) .codigo-servicio {
        grid-area: codigo;
    }

    .tabla-servicios tr:not(.fila-categoria-servicio) .precio-servicio {
        grid-area: precio;
    }

    .tabla-servicios tr:not(.fila-categoria-servicio) .estado-servicio {
        grid-area: estado;
    }
}

/* ---------------------------------------------------------------------------
   Auditoría
   --------------------------------------------------------------------------- */

/* Cambios y accesos son dos pantallas de la misma sección. La barra de arriba marca la
   sección; esto marca en cuál de las dos se está parado.

   `flex-wrap` desde el 31-08, cuando comisiones estrenó la primera de cinco pestañas: con dos o
   tres etiquetas cortas el `nowrap` por defecto nunca se notó, pero cinco no entran en un teléfono
   de 375px ni recortando los nombres, y sin envolver se salen de la pantalla en vez de bajar. Se
   envuelve y no se hace scroll horizontal a propósito: una pestaña escondida en la barra que
   existe justamente para que esas pantallas se encuentren es peor que dos filas. */
nav.sub {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 1.25rem;
    margin: 0.5rem 0 1rem;
    border-bottom: 1px solid var(--borde);
}

nav.sub a {
    padding: 0.35rem 0;
    margin-bottom: -1px;
    border-bottom: 2px solid transparent;
    text-decoration: none;
}

nav.sub a.actual {
    color: var(--turquesa-profundo);
    font-weight: 600;
    border-bottom-color: var(--turquesa);
}

/* El diff vive dentro de una celda: sin viñetas ni sangría, porque compite con el resto de
   la fila y lo que tiene que leerse primero es el valor nuevo. */
ul.diff {
    margin: 0;
    padding: 0;
    list-style: none;
    font-size: 0.9rem;
}

ul.diff li + li {
    margin-top: 0.15rem;
}

/* De dónde venía el valor: presente para poder comparar, apagado para no disputarle la
   atención a en qué quedó. */
.antes {
    color: var(--texto-tenue);
}

/* Una celda de auditoría puede traer ocho campos; sin esto, una nota larga estira la
   columna y desplaza la tabla entera de lado. */
ul.diff li {
    overflow-wrap: anywhere;
}

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

/* ---------------------------------------------------------------------------
   La agenda del día

   Una tabla y no una retícula dibujada a mano: la pregunta que trae a alguien acá —"¿a qué hora
   tengo libre la sala felina?"— se contesta bajando por una columna, y una tabla con encabezados
   es lo único que también se puede recorrer con un lector de pantalla.

   Todo lo que sigue existe para que se lea como un día y no como un listado: alto de fila
   constante, la media hora más callada que la hora en punto, y el hueco comportándose como lo que
   es, un control del tamaño de la celda.
   --------------------------------------------------------------------------- */
.agenda-dia .columna-hora {
    width: 4.5rem;
}

/* La fila de las salas queda fija al bajar por el día (hallazgo 142): abajo, a las seis de la tarde,
   ya no se sabía cuál columna era la felina, cuál el pabellón y cuál la canina. Se pega **debajo de la
   barra**, que también es fija y cuya altura mide `alto-de-la-barra.js`: pegada a `top: 0` quedaba
   escondida detrás de ella. Fondo opaco, porque las horas pasan por debajo; y la línea de abajo como
   sombra y no como borde, porque con `border-collapse` el borde se queda en su lugar y no viaja con la
   celda fija. */
.agenda-dia thead th {
    position: sticky;
    top: var(--alto-barra, 3.25rem);
    z-index: 2;
    background: var(--superficie);
    box-shadow: inset 0 -1px 0 var(--borde);
}

/* La agenda del día en el teléfono (hallazgo 142): la tabla no cabe de lado y se desplaza dentro de
   su marco, como cualquier tabla angosta. Pero **una caja que se desplaza de lado no puede fijar su
   cabecera contra la página**: `sticky` se pega a la caja que se desplaza más cerca, y ésta no se
   desplazaba en vertical. Así que el marco se desplaza en los dos sentidos, con el alto de la pantalla
   menos la barra, y adentro quedan fijas la fila de las salas y la columna de la hora. Se le quita a la
   tabla el `display: block` del bloque de arriba, que ahora hace el marco. */
@media screen and (max-width: 40rem) {
    /* Menos 3rem y no menos 1rem: debajo del marco quedan el relleno de la sección y su margen, unos
       40 px, y con menos alto la página bajaba hasta dejar el borde de arriba del marco —con la fila de
       las salas— escondido bajo la barra. */
    .agenda-marco {
        overflow: auto;
        max-height: calc(100dvh - var(--alto-barra, 3.25rem) - 3rem);
    }

    .agenda-marco table {
        display: table;
        overflow: visible;
    }

    .agenda-dia thead th {
        top: 0;
    }

    .agenda-dia .columna-hora {
        position: sticky;
        left: 0;
        z-index: 1;
        background: var(--superficie);
    }

    .agenda-dia thead th.columna-hora {
        z-index: 3;
    }
}

/* Un ancho mínimo por recurso, y no un reparto elástico: con cinco columnas el nombre del tutor
   se parte en cuatro renglones y las filas dejan de medir lo mismo, que es de lo único que
   depende poder leer el día. Cuando no caben, la tabla se desplaza dentro de su sección —eso ya
   lo hace el bloque de pantallas angostas— en vez de apretarse hasta ser ilegible. */
.agenda-dia thead th:not(.columna-hora) {
    min-width: 7rem;
}

/* El alto fijo es lo que convierte la tabla en una escala de tiempo. Sin él, media hora vacía
   mide dos milímetros y media hora con una consulta mide tres centímetros: la columna deja de
   poder recorrerse de un vistazo y las horas dejan de estar donde uno las va a buscar. */
.agenda-dia th,
.agenda-dia td {
    height: 2.5rem;
    padding: 0.25rem 0.4rem;
}

/* La hora en punto manda y la media hora acompaña: rotularlas igual llena la columna de la
   izquierda de cifras que compiten entre ellas. */
.agenda-dia tr.media th[scope="row"] {
    color: var(--texto-tenue);
    font-size: 0.85rem;
}

/* La única línea fuerte es la del cambio de hora; las divisiones de adentro se callan. Qué fila
   cierra la hora depende de en cuántos bloques se divida el día —con medias horas es la de las
   09:30 y con cuartos la de las 09:45—, y por eso la clase la pone Kotlin: el CSS no sabe cuánto
   dura un bloque. Sin esto, un día en cuartos se lee como cuatro líneas iguales por hora y deja de
   distinguirse dónde empieza cada una. */
.agenda-dia tbody tr:not(.cierra-hora) > * {
    border-bottom-color: transparent;
}

/* El hover de fila del resto de las tablas acá estorba: pinta de menta las celdas libres, que es
   justo el color con el que se distingue lo ocupado. Lo que se resalta es la celda que está bajo
   el cursor, que además es la única que se puede pinchar. */
.agenda-dia tbody tr:hover td {
    background: none;
}

.agenda-dia td.hueco {
    padding: 0;
}

/* El hueco es un enlace del tamaño de la celda: en el mesón se pincha con el dedo y sin dar en el
   blanco a la primera. El "+" aparece al apuntarlo —dibujarlo siempre llena la grilla de cruces y
   el día deja de leerse— y también al recibir el foco, porque quien tabula necesita ver dónde
   está parado. */
.agenda-dia td.hueco a {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 100%;
    min-height: 2rem;
    color: transparent;
    text-decoration: none;
}

.agenda-dia td.hueco a:hover,
.agenda-dia td.hueco a:focus-visible {
    background: var(--menta-suave);
    color: var(--turquesa-profundo);
}

/* La hora tomada se lee como un bloque macizo con el canto marcado: es lo que hace que una
   cirugía de tres horas se vea como una y no como seis medias horas seguidas. */
.agenda-dia td.tomada {
    background: var(--menta-suave);
    border-left: 3px solid var(--turquesa);
}

/* La hora tomada en tres renglones fijos (hallazgo 133): quién y en qué estado, cuándo y qué, y el
   pago con lo que se puede hacer. Antes cada pieza iba en línea y caía donde alcanzaba: el
   *Ver la atención* de una hora atendida quedaba pegado a la píldora del pago, el *Abrir atención*
   de la de al lado bajaba a su propio renglón, y dos horas vecinas no se leían igual. Arriba y no
   centrada en su celda: la celda es una escala de tiempo, y la hora empieza donde empieza. */
.agenda-dia td.tomada {
    padding: 0.4rem 0.6rem;
}

.agenda-dia .hora-tomada {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

/* El nombre a la izquierda y el estado al otro extremo: así el estado se busca siempre en el
   mismo lugar al recorrer la columna, y no detrás de nombres de largo distinto. */
.agenda-dia .hora-tomada-cabeza {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.25rem 0.5rem;
}

.agenda-dia .hora-tomada-cabeza a {
    font-weight: 600;
}

/* El pago a la izquierda y la acción a la derecha, en el mismo renglón mientras quepan. En una sala
   angosta la acción baja, pero entera y con aire, no pegada al borde de la píldora. */
.agenda-dia .hora-tomada-pie {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.3rem 0.75rem;
    font-size: 0.9rem;
}

/* Sin pago ni acción —quien no atiende, una hora sin presupuesto— el pie no existe. `:empty` no
   sirve: los saltos de línea de la plantilla ya cuentan como contenido para él. */
.agenda-dia .hora-tomada-pie:not(:has(*)) {
    display: none;
}

.agenda-dia .hora-tomada-pie form {
    margin: 0;
}

/* Lo que ya ocurrió —atendida, no asistió— sigue ocupando su franja, que es el registro de lo que
   se reservó, pero deja de pedir algo. */
.agenda-dia .hora-tomada.cerrada {
    color: var(--texto-tenue);
}

/* Dos horas cortas caídas en la misma media hora comparten celda, porque no hay dos columnas
   donde ponerlas. La línea las separa para que no se lean como una sola reserva. */
.agenda-dia .hora-tomada + .hora-tomada {
    margin-top: 0.3rem;
    padding-top: 0.3rem;
    border-top: 1px solid var(--borde);
}

/* En la columna Terreno (V85, ADR-060 §5) dos horas que comparten celda son, casi siempre, dos personas
   afuera a la vez: van lado a lado, porque una debajo de la otra se leían como una sola visita del doble
   de largo. Cada una dice su rango, así que dos seguidas de la misma persona tampoco se confunden. En una
   sala esto no pasa —dos horas en la misma celda son dos cortas seguidas— y siguen una bajo la otra.
   **La columna A distancia (V98, ADR-065 §1) es igual**: dos teleconsultas en la misma celda son dos
   personas atendiendo a la vez. */
.agenda-dia td.en-terreno .horas-de-la-celda,
.agenda-dia td.a-distancia .horas-de-la-celda {
    display: flex;
    gap: 0.6rem;
}

.agenda-dia td.en-terreno .horas-de-la-celda > .hora-tomada,
.agenda-dia td.a-distancia .horas-de-la-celda > .hora-tomada {
    flex: 1 1 0;
    min-width: 0;
}

.agenda-dia td.en-terreno .hora-tomada + .hora-tomada,
.agenda-dia td.a-distancia .hora-tomada + .hora-tomada {
    margin-top: 0;
    padding-top: 0;
    border-top: none;
    padding-left: 0.6rem;
    border-left: 1px solid var(--borde);
}

/* Lado a lado necesita más ancho que una sala, o cada visita se parte en una palabra por renglón. */
.agenda-dia thead th.columna-terreno,
.agenda-dia thead th.columna-distancia {
    min-width: 11rem;
}

/* Dónde está quien salió: una dirección larga se parte donde haga falta, en vez de empujar la columna
   hasta sacar el día de la pantalla. */
.agenda-dia .hora-tomada-donde {
    overflow-wrap: anywhere;
}

/* Los minutos que sobran dentro de un bloque tomado. La línea de puntos es la que dice que esto
   no es otra reserva sino lo que queda entre medio: con la línea entera de arriba se leía como
   una segunda hora tomada, que es exactamente lo contrario de lo que ofrece.

   `block` y no en línea porque comparte celda con el nombre del tutor, que ya ocupa su renglón, y
   corrido detrás quedaba partido entre dos líneas. Más chico y más apagado que la cita: lo que se
   recorre buscando en esta pantalla son las horas comprometidas, no los ratos sueltos. */
.agenda-dia .hueco-parcial {
    display: block;
    margin-top: 0.3rem;
    padding-top: 0.3rem;
    border-top: 1px dashed var(--borde);
    font-size: 0.85rem;
    text-decoration: none;
}

/* Y cuando caen antes de la cita, la línea va abajo: separa del mismo modo y deja los minutos
   libres arriba, que es donde ocurren. */
.agenda-dia .hueco-parcial:first-child {
    margin-top: 0;
    padding-top: 0;
    border-top: none;
    margin-bottom: 0.3rem;
    padding-bottom: 0.3rem;
    border-bottom: 1px dashed var(--borde);
}

.agenda-dia .hueco-parcial:hover,
.agenda-dia .hueco-parcial:focus-visible {
    text-decoration: underline;
}

/* Los dos campos que dependen del tipo de atención viven dentro de un `div` para que htmx pueda
   reemplazarlos de una pieza. Sin esto, ese envoltorio se lleva **una** celda de la grilla de
   campos y los dos quedan uno debajo del otro y angostos; con `contents` el envoltorio existe
   para htmx y desaparece para el diseño. */
#propuesta {
    display: contents;
}

/* ---- El mes de la disponibilidad: quién atiende cada día (hallazgo 115) ---- */

/* Las personas en una fila que envuelve, con el botón al final: es un filtro, y en vertical una
   clínica con seis personas empujaba el mes fuera de la pantalla. */
.personas-del-calendario {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 0.5rem 1rem;
    margin-top: 0.75rem;
}

.personas-del-calendario fieldset {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem 1.25rem;
}

.personas-del-calendario legend {
    margin-bottom: 0.35rem;
    color: var(--texto-tenue);
    font-size: 0.9rem;
}

.personas-del-calendario button {
    margin-top: 0;
}

/* Siete columnas iguales, fijas: con anchos automáticos el martes con tres nombres se llevaba el
   doble que el domingo vacío, y un calendario se lee bajando por columnas que miden lo mismo. */
.calendario-del-mes {
    table-layout: fixed;
}

.calendario-del-mes th {
    padding: 0.35rem 0.25rem;
    text-align: center;
}

.calendario-del-mes td {
    height: 5.25rem;
    padding: 0.2rem;
    border: 1px solid var(--borde);
    vertical-align: top;
}

/* La última semana vuelve a cerrar por abajo. La regla general `table:not(:has(tfoot)) tbody
   tr:last-child > *` le quita el borde a la última fila de toda tabla, y le gana a la de arriba por
   especificidad: está pensada para un listado que termina contra el borde de su sección, y una
   grilla de casillas sin su línea de base queda abierta. Hallazgo de la Parte Z10, paso Z10.9. */
.calendario-del-mes tbody tr:last-child > td {
    border-bottom: 1px solid var(--borde);
}

/* La casilla entera es el enlace: se apunta a un día, no a su número. El foco se ve en la casilla
   completa, que es lo que se está eligiendo. */
.dia-del-calendario {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 4.85rem;
    padding: 0.2rem 0.3rem;
    border-radius: 0.3rem;
    color: var(--texto);
    text-decoration: none;
}

.dia-del-calendario:hover {
    background: var(--menta-suave);
}

.dia-del-calendario > span[aria-hidden] {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.1rem;
}

.numero-del-dia {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* El día de la semana sólo hace falta cuando el mes es una lista: en la retícula lo dice la columna. */
.dia-de-la-semana {
    display: none;
    font-weight: 400;
}

/* Lo que va en la casilla —nombres o horas— más chico que el número del día y sin partirse: si no
   cabe se corta con puntos suspensivos, porque el detalle del día lo dice entero. */
.dia-del-calendario .renglon {
    max-width: 100%;
    overflow: hidden;
    font-size: 0.8rem;
    line-height: 1.25;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dia-del-calendario .etiqueta {
    min-height: 1.2rem;
    padding: 0.05rem 0.4rem;
}

/* El día sin nadie se tiñe además de llevar su palabra: es lo que se busca al mirar la cobertura
   del mes, y tiene que saltar sin leer casilla por casilla. La palabra es la que lo dice para quien
   no distingue el ámbar. */
.dia-del-calendario.sin-nadie {
    background: var(--ambar-suave);
}

.una-persona .dia-del-calendario.sin-nadie {
    background: none;
}

.calendario-del-mes .pasado .dia-del-calendario {
    opacity: 0.6;
}

.calendario-del-mes .fuera-del-mes {
    background: var(--fondo);
}

/* El día abierto, con el borde de la marca: es el que se describe abajo, en su detalle. */
.dia-del-calendario.abierto {
    outline: 2px solid var(--turquesa);
    outline-offset: -2px;
}

/* La semana declarada, agrupada por horario: los días a la izquierda, las horas a la derecha, en la
   retícula del `dl` del sistema. */
.semana-resumida {
    gap: 0.15rem 1rem;
}

.semana-resumida dt {
    color: var(--texto);
}

/* Las cuatro horas de un cambio de un día en una fila: cada par —desde y hasta— se lee junto. En
   la retícula de `.campos` cabían tres y el segundo «Hasta» caía solo en la fila siguiente. */
.franjas-del-dia {
    grid-template-columns: repeat(4, minmax(0, 1fr));
}

/* Bajo 40rem el mes deja de ser una retícula: siete columnas de 45 px no llevan un nombre. Cada
   día pasa a ser un renglón, con su día de la semana, y los que son de otro mes desaparecen. Es lo
   mínimo para que no se rompa: el mes en el teléfono se mide en la pasada final del teléfono. */
@media screen and (max-width: 40rem) {
    .calendario-del-mes,
    .calendario-del-mes tbody,
    .calendario-del-mes tr,
    .calendario-del-mes td {
        display: block;
    }

    .calendario-del-mes thead,
    .calendario-del-mes .fuera-del-mes {
        display: none;
    }

    .calendario-del-mes td {
        height: auto;
        border-width: 0 0 1px;
    }

    .dia-del-calendario,
    .dia-del-calendario > span[aria-hidden] {
        flex-direction: row;
        flex-wrap: wrap;
        align-items: baseline;
        gap: 0.2rem 0.6rem;
        min-height: 0;
    }

    .dia-de-la-semana {
        display: inline;
    }

    .franjas-del-dia {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* ---------------------------------------------------------------------------
   Mis comisiones: lo propio, en la mano (N2)

   Es la única pantalla del sistema dibujada a 360–390 px desde el primer trazo, y no porque N
   adelante la pasada angosta de nadie: su enunciado *es* el teléfono —«este mes llevo 600 lucas»,
   dicho por alguien que no va a abrir un computador para saberlo—. De ahí sale todo lo de acá
   abajo: ninguna tabla que desplazar de lado, el número grande primero y el detalle como lista.
   --------------------------------------------------------------------------- */

/* El monto es la pregunta entera de la pantalla, y por eso es lo único acá con tamaño de titular.
   `clamp` y no una medida fija: seis cifras a 2.6rem se salen del borde en un teléfono de 360 px,
   y 2rem en el escritorio no se distingue de un `h2` cualquiera. */
.monto-del-periodo {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.15rem 0.6rem;
    margin: 0 0 0.4rem;
}

.monto-del-periodo strong {
    color: var(--turquesa-profundo);
    font-family: var(--fuente-marca);
    font-size: clamp(2rem, 10vw, 2.6rem);
    font-variant-numeric: tabular-nums;
    line-height: 1.1;
}

/* El rango va pegado al monto porque es lo que lo hace verdadero: «$63.400» sin fechas no dice
   nada. Con el `1em` que el navegador le pone a un `p`, el periodo flotaba lejos de la cifra que
   acota y en el teléfono quedaba abajo del pliegue. */
.periodo-del-monto {
    margin: 0 0 0.4rem;
}

/* Los dos saltos, uno en cada extremo. `space-between` con un solo enlace lo deja a la izquierda,
   que es donde tiene que quedar «Periodo anterior» cuando el siguiente todavía no ha empezado. */
.paso-de-periodo {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
    gap: 0.5rem 1rem;
    margin-top: 0.9rem;
}

/* El detalle es una lista y no una tabla. Sin `list-style: none` el bullet se come, a 360 px, el
   ancho que necesita el monto para no bajar de línea. */
.mis-operaciones {
    display: grid;
    gap: 0.6rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

/* La caja de una operación. Es el mismo bloque que `.bloque-de-campos` —relleno, borde, radio y
   superficie— y no es esa clase: aquella viste un `fieldset` de formulario y su nombre lo dice.
   Con `.medio-cobro` y `.factura-cobro` ya son cuatro iguales, y queda anotado acá como está
   anotado allá: conviene doblarlos en uno la próxima vez que se toque el cobro. */
.mi-operacion {
    padding: 0.7rem 0.8rem;
    border: 1px solid var(--borde);
    border-radius: 0.55rem;
    background: var(--superficie);
}

/* El nombre a la izquierda y el monto a la derecha, con `wrap` para que en el teléfono el monto
   baje entero en vez de comprimir el nombre hasta partirlo por sílabas. */
.encabezado-de-operacion {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.2rem 0.8rem;
}

/* El que cede es el nombre y no el monto: el número es lo que se viene a mirar. Sin `min-width: 0`
   un nombre de servicio largo fija el mínimo del elemento y empuja el monto fuera de la caja. */
.encabezado-de-operacion .apilado {
    flex: 1 1 12rem;
    min-width: 0;
}

/* Los párrafos de adentro sin el `1em` del navegador: son dos renglones muertos por operación, y
   en una lista de doce eso es media pantalla de teléfono. Es lo mismo que hace `.bloque-de-campos`
   con los suyos, por la misma razón. */
.mi-operacion p {
    margin: 0.35rem 0 0;
}

/* La cuenta que produjo la comisión va más chica y debajo: se lee cuando alguien pregunta por qué
   ese número, que no es cada vez que abre la pantalla. Es lo que el anexo pone en su segunda fila,
   escrito para una pantalla angosta en vez de para una tabla de seis columnas. */
.cuenta-de-la-operacion {
    font-size: 0.85rem;
}

/* ---------------------------------------------------------------------------
   La hoja: todo lo que se imprime

   Nació para la epicrisis, que fue la primera, y hoy la llevan todas las hojas: cuáles son lo dice
   `FormatoDePapelTest`, que es la lista que se comprueba, y no este comentario —que las contó
   «la única» mientras eran cuatro—. Lo propio de los documentos del mesón viene más abajo.

   En pantalla se ve como el resto del sistema —hereda `main`— pero está pensada para el
   papel. Todo lo que acá se ajusta responde a algo que se rompe al imprimir: los fondos de
   sección que se comen el tóner, la consulta que queda partida entre dos páginas, y el
   encabezado de la clínica, que en pantalla no existe en ninguna otra pantalla.
   --------------------------------------------------------------------------- */
/* El membrete: lo único de la aplicación que se dibuja para el papel y no para la pantalla, y
   desde F3 tiene que probarlo. Los colores de la clínica se comprueban contra blanco —el único
   fondo que la impresora garantiza— y su logo es un PNG con las tintas que eligió su diseñador.
   Sobre Grafito clínico las dos cosas se caen: un color que pasa 4,5:1 sobre blanco queda casi
   negro contra el gris de la superficie, y un logo de tinta oscura desaparece. Así que acá gana
   el papel en los dos temas, que además es lo que se espera de una vista previa.

   Los tokens se redefinen para el subárbol en vez de escribir el color en cada regla: así el
   `.tenue` de adentro también queda en tinta de papel. Eso arregla de paso algo que se imprimía
   mal desde antes —en tema oscuro el RUT salía en gris claro sobre blanco, casi invisible—, pero
   solo dentro del membrete: el resto de la hoja sigue como estaba. */
.hoja .membrete {
    --texto: var(--tinta-papel);
    --texto-tenue: var(--tinta-papel-tenue);
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.85rem 1rem;
    border-radius: 0.5rem 0.5rem 0 0;
    background: var(--blanco);
    color: var(--tinta-papel);
    /* El color principal de la clínica cuando lo hay; si no, la paleta del sistema, que es como
       se imprimía hasta F3. Lo declara la hoja entera —`th:style` en el `<main>`— porque el otro
       color de la marca cierra el pie, que está fuera de este bloque. */
    border-bottom: 2px solid var(--marca-principal, var(--turquesa));
}

.hoja .membrete .tenue {
    display: block;
    font-size: 0.85rem;
}

/* Alto y no ancho: los logos llegan cuadrados, apaisados o verticales, y limitar el ancho dejaría
   uno alto ocupando media hoja. 3,5rem son unos 15 mm impresos, la altura de un membrete de
   carta. El ancho máximo es la guarda del caso raro —un logo muy apaisado— y `contain` impide que
   cualquiera de los dos topes lo deforme. */
.logo-clinica {
    max-height: 3.5rem;
    max-width: 12rem;
    width: auto;
    object-fit: contain;
}

/* La marca de agua de la clínica (Z6): su imagen, aclarada y al centro de cada hoja.

   **La opacidad es la guarda de legibilidad, y el 8 % lo decidimos nosotros.** No se mira la
   imagen: se acota lo peor que la clínica pueda subir. El negro al 8 % queda en un gris de 235, y
   sobre él la tinta de papel conserva 8,67:1 y la tenue 4,41:1 —sobre blanco son 10,33 y 5,25—. Al
   12 % la tenue ya baja de 4:1 en la hoja de una clínica de logo oscuro, que es justo el texto que
   una fotocopia aclara primero.

   **La caja —60 % del ancho, 50 % del alto— también es nuestra**: grande para que se lea como marca y
   no como un sello perdido, y baja para que en media carta no alcance el membrete. `contain` la
   agranda o la achica hasta tocar un borde de la caja sin deformarla, así que un PNG de 200 px y uno
   de 2000 salen del mismo tamaño.

   **Es un `<img>` y no un `background-image`**: el navegador no imprime fondos salvo que alguien
   encienda *gráficos de fondo*, y una marca que depende de esa casilla no sale nunca en el mesón.

   En pantalla va **encima** del contenido y sin recibir clics: las secciones tienen superficie propia
   y una marca detrás no se vería en ninguna vista previa. En papel va **detrás** (ver `@media print`),
   que es donde vale la cuenta de contraste de arriba. */
.hoja {
    position: relative;
}

.marca-de-agua {
    position: absolute;
    inset: 0;
    margin: auto;
    width: 60%;
    height: 50%;
    object-fit: contain;
    opacity: 0.08;
    z-index: 1;
    pointer-events: none;
}

/* El nombre de la clínica en su color. Es lo que hace que una clínica sin logo igual tenga
   membrete propio, y es la razón por la que a este color se le exige el más alto de los dos
   umbrales de contraste sobre blanco: acá es texto y no adorno (ver ColorDeMarca, que además
   dice por qué esos umbrales ya no son los de WCAG AA). */
.nombre-clinica {
    color: var(--marca-principal, inherit);
}

/* En el teléfono el logo se va arriba y el texto abajo. Al lado, un logo de 12rem deja el RUT en
   una columna de tres palabras por línea. */
@media screen and (max-width: 30rem) {
    .hoja .membrete {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.6rem;
    }
}

/* Una atención se lee como bloque: dos columnas de etiqueta y contenido, con el texto largo
   —anamnesis, tratamiento— respetando los saltos de línea que escribió el veterinario. */
.hoja .consulta dd {
    white-space: pre-wrap;
}

/* La columna de etiquetas, del mismo ancho en todas las atenciones (hallazgo 141). Cada atención es
   su propia lista, y con el `max-content` de todas las `dl` la columna medía lo que su etiqueta más
   larga: una consulta con motivo y peso quedaba más angosta que la de al lado, que trae examen físico,
   y el texto de la hoja saltaba de margen de una atención a la siguiente. 5,75 rem es *Examen físico*
   —la más larga, 5,1 rem a la letra de una etiqueta— con holgura; en `rem` y no en píxeles para que
   siga a la escala del papel al imprimir. */
.hoja .consulta dl {
    grid-template-columns: minmax(5.75rem, max-content) 1fr;
}

/* La línea que cierra la hoja, y el segundo de los dos colores de la marca. Un membrete de verdad
   abre arriba y cierra abajo; acá además es lo que le da un lugar al color de acento sin ponerlo
   debajo de ningún texto, que es lo que permite exigirle 3:1 y no 4,5:1 (ver ColorDeMarca).

   La línea la tenían tres de las cuatro hojas —vivía en `.pie-documento`— y la epicrisis no. Se
   subió acá para que la marca cierre las cuatro igual; la epicrisis gana una línea sobre su pie,
   que es lo que ya hacían el presupuesto, la boleta y la receta. */
.hoja .pie {
    margin-top: 2.5rem;
    padding-top: 1rem;
    border-top: 1px solid var(--marca-acento, var(--borde));
}

/* Contra el margen derecho, que es donde se firma un papel. Pegada al izquierdo quedaba justo
   debajo del texto del pie y se leía como un párrafo más —un renglón en blanco con una raya—;
   a la derecha el espacio vacío a su izquierda es lo que la anuncia como lugar para firmar.
   Lo decidimos nosotros: no es exigencia de ninguna norma y vale para todas las clínicas.

   `width` y no `max-width` porque el margen automático es lo que la empuja: con el ancho en
   `auto` los márgenes automáticos se resuelven en cero y la caja se queda a la izquierda. */
.hoja .firma {
    width: min(18rem, 100%);
    margin-top: 3rem;
    margin-left: auto;
    /* El rótulo centrado bajo la línea, igual que en la receta: son el mismo objeto en dos
       hojas distintas y no tienen por qué verse distinto. */
    text-align: center;
}

/* La línea sobre la que se firma. Va con borde y no con guiones bajos para que no se corte
   entre dos líneas cuando el pie cae justo al final de la página. */
.hoja .firma span {
    display: block;
    border-top: 1px solid var(--texto);
}

.hoja .firma p {
    margin: 0.25rem 0 0;
}

/* Quién emitió la hoja y cuándo, contra el mismo borde que la firma. Pegada a la izquierda le
   quedaba enfrentada: una esquina abajo a la izquierda y otra abajo a la derecha, y el pie se
   leía como dos cierres distintos de la misma hoja. Con las dos al mismo lado el papel cierra
   por uno solo, que es además como cierra la receta, y las dos se entregan en el mismo mesón.

   Es la única línea de pie que se mueve. La de la boleta se queda a la izquierda porque esa hoja no
   lleva firma, y la del presupuesto también: la suya es la aceptación del tutor, que ocupa el ancho
   entero y no una esquina, así que no hay nada enfrente con qué chocar.
   Lo decidimos nosotros: no lo manda ninguna norma. */
.hoja .emitido-por {
    text-align: right;
}

/* ---- La aceptación del tutor en el presupuesto (Z3; 7.2 del plan, ADR-052 §5) ----

   Nombre, RUT, firma y fecha bajo «Acepto este presupuesto». Son cuatro rayas y no la `.firma` de
   una esquina porque acá no firma la clínica sino quien acepta, y lo que la clínica guarda de este
   papel es **quién** aceptó: una firma sola es un garabato sin nombre.

   En dos columnas para que el bloque no se coma media hoja en los papeles chicos. Lo decidimos
   nosotros; se mide con el resto de las hojas en Z6. */
.hoja .aceptacion {
    margin-top: 2rem;
}

.hoja .campos-de-aceptacion {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 2.5rem 2rem;
    margin-top: 2.5rem;
}

/* La raya, como la de `.firma`: con borde y no con guiones bajos, para que no se corte entre dos
   líneas. */
.hoja .campos-de-aceptacion span {
    display: block;
    border-top: 1px solid var(--texto);
}

.hoja .campos-de-aceptacion p {
    margin: 0.25rem 0 0;
}

/* **«Acepto este presupuesto» va al lado del total, y no debajo** (hallazgo 150, AG3). Los márgenes de
   20 mm le quitaron a la Carta dos ítems antes de que la firma pasara a la hoja siguiente —medido en
   PDF: cabían 12 y quedaban 10—, y este renglón, con el aire que lo separaba del total, devuelve uno:
   caben 11. Se lee igual: la frase a la izquierda, el total que acepta a la derecha y las rayas
   debajo. `display: contents` deja que la frase y las rayas se acomoden en la grilla del bloque sin
   sacarlas del `div` que las agrupa. Lo decidimos nosotros. */
.hoja .cierre-del-presupuesto {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    column-gap: 2rem;
    align-items: end;
}

.hoja .cierre-del-presupuesto .aceptacion {
    display: contents;
}

.hoja .cierre-del-presupuesto .desglose {
    grid-column: 2;
    grid-row: 1;
}

.hoja .cierre-del-presupuesto .aceptacion > p {
    grid-column: 1;
    grid-row: 1;
    margin: 0;
}

.hoja .cierre-del-presupuesto .campos-de-aceptacion {
    grid-column: 1 / -1;
}

@media print {
    /* Los botones y el enlace de volver no son parte del documento. */
    .sin-imprimir {
        display: none !important;
    }

    /* La marca de agua en papel (Z6): **fija, y por eso en cada hoja**. Un elemento fijo se repite en
       todas las páginas al imprimir —Chromium y Firefox lo hacen—, y centrado respecto de la página y
       no del documento, que es lo que pide «al centro de cada hoja»: absoluta, una epicrisis de tres
       páginas la llevaría una sola vez, a media altura de las tres.

       **Y detrás del texto**, con `z-index` negativo: en papel ninguna sección pinta fondo, así que
       no hay nada que la tape, y es donde vale la cuenta de contraste de `.marca-de-agua`. Lo único
       que queda encima es el blanco del membrete, si alguien imprime con *gráficos de fondo*. */
    .marca-de-agua {
        position: fixed;
        z-index: -1;
    }

    /* Sobre papel manda el papel: aunque la pantalla esté en Grafito clínico, lo que sale de
       la impresora es tinta sobre blanco. Sin esto, el tema oscuro imprime un rectángulo
       gris de tinta por cada sección.

       **Y una sola tinta, en dos niveles.** Es la regla de la hoja impresa entera: el cuerpo en
       `--tinta-papel`, y lo secundario —etiquetas, encabezados de tabla, el folio, el pie— en
       `--tinta-papel-tenue`. Nada más, aparte de los dos colores que configura la clínica, que
       tocan el membrete y las dos líneas y ninguna otra cosa.

       Hasta el 16-08-2026 eran tres tintas y ninguna decidida: `black` acá, `var(--texto)` en las
       reglas que declaran su color y `var(--texto-tenue)` en las apagadas. Las dos primeras hacen
       exactamente el mismo trabajo —texto a plena tinta— y salían distintas, con el agravante de
       que el membrete ya se imprimía en `--tinta-papel`: el encabezado y el cuerpo de la misma hoja
       en dos negros que no eran el mismo. Medido sobre una factura: cuerpo `#000000`, Total
       `#244643`, etiquetas `#58716d`.

       Se eligió la tinta de papel y no el negro puro justamente por el membrete: al revés habría
       que repintarlo a él, y eso ya no es legibilidad sino identidad. Con 10,33:1 sobre blanco
       —y 5,25:1 el nivel apagado— las dos siguen siendo texto legible, no gris decorativo. */
    body {
        background: white;
        color: var(--tinta-papel);
    }

    /* Y los tokens con él, que es la otra mitad del mismo problema: `color` se hereda, pero toda
       regla que **declare** `color: var(--texto)` se lleva el valor de la pantalla a la impresora.
       En Grafito eso es `#f1f6f4` sobre blanco, o sea nada, y así salió la fila del **Total** de la
       primera factura que se imprimió, mientras el detalle que esa fila suma se leía a plena tinta.

       Redefinir los dos tokens en vez de pintar cada regla es lo que ya hace `.hoja .membrete`
       —desde que el RUT salía gris claro por esto mismo—, y acá tiene además una garantía exacta:
       valen lo mismo que `--texto` y `--texto-tenue` del tema claro, así que imprimir desde Grafito
       produce la misma hoja que imprimir desde Menta. Antes eran dos hojas y solo una servía. */
    .hoja {
        --texto: var(--tinta-papel);
        --texto-tenue: var(--tinta-papel-tenue);
        max-width: none;
        padding: 0;
        /* El 1,5 de la pantalla es interlineado de lectura larga a 16 px; en papel, a 10 pt, deja
           cada renglón con un tercio de aire y es la mitad de lo que hacía crecer la epicrisis. */
        line-height: 1.35;
    }

    /* La escala del papel (bloque U, U1).

       En la impresora un `rem` valía 12 pt fijo: la raíz no declara tamaño y el navegador pone
       16 px. Todo lo que la hoja escribe en `rem` —casi todo— salía entonces a escala de pantalla:
       la epicrisis con el cuerpo a 12 pt y el título a 24, el presupuesto con los rótulos a 10,8 y
       el dato que rotulan a 10,5, y un presupuesto de seis ítems que ya no cabía en una Carta. El
       `10.5pt` que tenía `.hoja-documento` alcanzaba sólo a lo que hereda, y la epicrisis ni eso.

       **Se mueve el ancla, no cada tamaño.** La jerarquía que el CSS ya tiene en `rem` —el rótulo
       a 0,9, el encabezado de tabla a 0,8, la línea tenue del membrete a 0,85— es correcta, y en
       papel sigue siéndolo si la raíz vale lo que tiene que valer el cuerpo. Con ella baja también
       el aire, porque rellenos, márgenes y separaciones están en `rem`. Lo que no debe seguir a la
       letra —la firma, el timbre, el logo— se escribe en mm más abajo.

       `html[data-papel]` y no `html`: lo llevan las ocho hojas y ninguna otra pantalla, así que lo
       que alguien imprima con Ctrl+P fuera de ellas sale como salía.

       **10 pt y 9 pt los decidimos nosotros** y valen para todas las clínicas: cada una elige el
       papel en la propia hoja, y la escala sigue al papel. Si alguna pide la letra más grande, es
       este número y no un mecanismo nuevo. */
    html[data-papel] {
        font-size: 10pt;
    }

    html[data-papel="a5"],
    html[data-papel="media-carta"] {
        font-size: 9pt;
    }

    /* **La receta en hoja grande va a 12 pt** (hallazgo 149, AG3). A 10 pt una receta corta ocupaba
       media Carta y la línea del membrete quedaba en 8,5 pt —*«bien chiquitito»*, dijo la clínica—.
       Es la única hoja que se lee en la casa, con el animal delante, y es corta: lo que llevó a bajar
       la escala en U1 fueron la epicrisis y el presupuesto, que se alargaban, y esos siguen en 10.
       **Los 12 pt los decidimos nosotros**, y son el mismo número que movía la escala antes de U1.
       Los papeles chicos no cambian: ahí lo que sobra es letra, no espacio. */
    html[data-papel="carta"][data-hoja="receta"],
    html[data-papel="a4"][data-hoja="receta"] {
        font-size: 12pt;
    }

    /* Los títulos con tamaño propio. Salían del tamaño por omisión del navegador —2em y 1,5em—,
       que sobre el cuerpo daba 21 a 24 pt y 15,8 a 18: cada fecha de atención de la epicrisis
       ocupaba el alto de dos renglones. El subtítulo va a 1,2 veces el cuerpo y no menos: el
       hallazgo 94 ya encontró que un título a un punto del cuerpo deja de leerse como título. */
    .hoja h1 {
        font-size: 1.6rem;
        line-height: 1.2;
    }

    /* Y ningún subtítulo queda solo al pie de una hoja, con su contenido en la siguiente. Lo tenían
       sólo la receta y la del art. 5°, cada una por su cuenta; es la misma regla en las ocho (U2). */
    .hoja h2 {
        font-size: 1.2rem;
        line-height: 1.25;
        margin-bottom: 0.3rem;
        break-after: avoid;
    }

    /* El nombre de la clínica heredaba el cuerpo, así que con la escala nueva el membrete se
       achicaba junto con el texto. Va un poco más grande y no le cuesta un renglón: está al lado
       del logo. */
    .hoja .nombre-clinica {
        font-size: 1.2rem;
    }

    /* El aire de papel. Con `:where` para no pesar más que las reglas propias de cada hoja: una
       celda que ya decide su relleno —la fila del cálculo del anexo, pegada a su operación—, un
       párrafo que ya decide su margen —el folio— o el primer y último hijo de una sección siguen
       mandando.

       La fila de tabla medía ~28 pt de alto con su relleno de pantalla, que es lo que empujaba el
       pie de un presupuesto corto a la hoja siguiente. */
    :where(.hoja) p {
        margin: 0.4em 0;
    }

    :where(.hoja) table {
        margin-top: 0.35rem;
    }

    :where(.hoja) th,
    :where(.hoja) td {
        padding: 0.22rem 0.35rem;
    }

    /* Rótulo y dato sobre la misma línea base: con tamaños distintos y alineados arriba se ven
       desfasados, y más con la escala nueva, donde el rótulo queda un punto por debajo del dato. */
    :where(.hoja) dl {
        gap: 0.15rem 0.9rem;
        align-items: baseline;
    }

    /* El piso: 7,5 pt, y lo decidimos nosotros. El hallazgo 94 llamó *letra chica de contrato* a
       los 7,1 en el papel que se le entrega a una persona. Sólo lo necesitan las dos piezas que en
       los papeles chicos caerían debajo —el encabezado de tabla a 0,8 y la etiqueta a 0,75 de
       9 pt—; en Carta ya quedan en 8 y en 7,5.

       `thead` y no `th` a secas: la celda *Total* es un `th` del `tfoot`, va al tamaño del cuerpo, y
       en el prototipo esta misma regla escrita sobre `th` la dejó en 8 pt. */
    :where(.hoja) thead th {
        font-size: max(0.8rem, 7.5pt);
    }

    .hoja section {
        background: none;
        border: none;
        box-shadow: none;
        padding: 0;
        margin-top: 0.9rem;
        /* Que una consulta no quede partida entre dos hojas: leerla a caballo entre dos
           páginas es exactamente lo que hace que un resumen clínico se malinterprete. Se volvió a
           decidir el 21-09-2026 (bloque U): partirla entre campos ahorraba una hoja cada catorce
           atenciones, y no vale la regla. */
        break-inside: avoid;
    }

    /* **Lo corto no se parte; lo largo sí, por filas o por líneas** (U2). El `avoid` de arriba
       alcanzaba a toda sección, y una que no cabe salta entera y deja atrás el hueco: la tabla de
       vacunas dejaba la primera hoja de la epicrisis al 63 %, y la política transcrita en la del
       art. 5° dejaba casi vacía la hoja donde empezaba. El hallazgo 95 lo arregló sólo para las
       secciones con tabla de esa hoja; es la misma causa en todas.

       Una tabla o un texto pegado pueden seguir en la hoja siguiente; siguen enteros los datos, el
       desglose, cada atención y cada operación del anexo con su cálculo, que ahí se mantienen
       juntos a propósito. `:has` pesa lo que su argumento más pesado, y por eso esta regla le gana
       al `avoid` de `.datos-documento` sin depender del orden. */
    .hoja section:has(table, .texto-pegado) {
        break-inside: auto;
    }

    /* Partir la sección no puede partir una fila. El comentario del 95 contaba con que las filas ya
       eran indivisibles, y eso valía sólo para `.tabla-documento`: las seis tablas de la hoja del
       art. 5° y la de vacunas no llevan esa clase, así que una fila de dos renglones podía quedar
       con uno en cada hoja. */
    .hoja tbody tr {
        break-inside: avoid;
    }

    /* Un texto pegado largo continúa, pero no deja un renglón suelto a cada lado del corte, y el
       rótulo que lo nombra —la versión de la política, de qué nota sale una mención— se queda con
       él. */
    .hoja .texto-pegado {
        orphans: 3;
        widows: 3;
    }

    .hoja section .folio-documento {
        break-after: avoid;
    }

    /* **El Total sale una vez.** Chrome repite el `tfoot` al pie de cada hoja que la tabla cruza, y
       un presupuesto de treinta ítems imprimía *«Total $888.900»* al final de la primera con el
       detalle siguiendo en la segunda: se lee como la suma de lo que va hasta ahí. En el anexo y en
       la hoja del externo es peor, porque ese total es el que alguien va a boletear. Como grupo de
       filas común queda donde está en el HTML, al final. El `thead` sí se sigue repitiendo en cada
       hoja, que es lo que tiene que hacer. */
    .hoja tfoot {
        display: table-row-group;
    }

    /* **La firma viaja con lo último que firma.** El pie no se parte y no empieza una hoja solo: una
       receta larga mandaba a la segunda hoja la raya y la línea de identidad y nada más, y una
       firma sola en una hoja es un papel que la clínica no entrega. Si el pie no cabe, se lleva
       consigo el final del último bloque. */
    .hoja .pie {
        break-inside: avoid;
        break-before: avoid;
    }

    /* **El total del presupuesto y su aceptación no se parten** (hallazgos 131 y 135). El 131 contó
       con el `avoid` de `.hoja section`, pero la hoja del presupuesto es también `.hoja-documento`,
       y `.hoja-documento section { break-inside: auto }` pesa lo mismo y va después: en Carta, *Firma*
       y *Fecha* se fueron solas a la hoja 2 y el tutor firmaba sin el precio a la vista. Nombrar el
       bloque por su clase le gana a las dos sin depender del orden. Si no cabe, pasa entero.

       **Y no pasa solo** (hallazgo 150, AG3): con catorce ítems en Carta, la primera hoja terminaba en
       el último ítem con un cuarto de hoja en blanco, y la segunda llevaba sólo el total y las rayas.
       El tutor firmaba una hoja aparte, sin nada de lo que aceptaba. Con el `avoid` de antes del
       bloque y el de antes de la última fila, el corte cae antes del penúltimo ítem: **los dos
       últimos ítems viajan con el total y la firma**. Si todo cabe en una hoja, no cambia nada. */
    .hoja .cierre-del-presupuesto {
        break-inside: avoid;
        break-before: avoid;
    }

    .hoja-presupuesto .tabla-documento tbody tr:last-child {
        break-before: avoid;
    }

    /* **Cada hoja dice de qué documento es y cuál es** (U3). Ninguna lo decía, y es lo que hace que
       al tutor se le pierdan: una hoja suelta de una epicrisis no se podía devolver a su lugar ni
       se sabía que faltaba otra. A la izquierda el documento, a la derecha *«Hoja 2 de 3»*.

       «Hoja» y no «Página» porque la continuación del art. 5° ya llama *página 2 de 4* a sus tandas,
       y el pie de esa misma hoja habría dicho *Página 1 de 1*.

       Es una página con nombre para que valga sólo en las ocho hojas: las cajas de margen que no se
       nombran valen para todo lo que se imprima, y el resto de las pantallas sigue saliendo con lo
       que ponga el navegador. En `main` y no en `.hoja`, porque la vista previa de `/marca` también
       es una `.hoja`, y un cambio de página con nombre obliga a un salto antes y después. */
    main.hoja {
        page: hoja;
    }

    html[data-papel] {
        --pie-tamano: 8pt;
    }

    html[data-papel="a5"],
    html[data-papel="media-carta"] {
        --pie-tamano: 7.5pt;
    }

    /* Las cajas de margen existen en Chrome desde la 131; uno anterior no dibuja el pie y no rompe
       nada. `string()` no existe todavía, así que el texto del documento no puede salir de la hoja:
       lo pone la plantilla en `--pie-de-pagina`, sobre el `<html>`, porque la página hereda de la
       raíz. Lo arma `PieDePagina`, que es donde vive la guarda de escribir texto dentro de un `style`.

       **La caja de arriba, vacía, apaga lo que imprime Chrome** con la casilla *Encabezados y pies de
       página*: la fecha, el título —*«… — Vetika»*, en el papel de la clínica— y la URL interna. Es
       el mismo argumento con que se declaró el tamaño de papel: dos computadores del mesón no pueden
       sacar dos hojas distintas según cómo quedó una casilla.

       **Alineado arriba de su caja, pegado al contenido y no al borde.** Centrado, en A5 caía a 2,8 mm
       del borde: dentro de lo que muchas impresoras no imprimen, y bajo los 5 mm libres que el SII
       pide en un documento tributario. Arriba queda a 5,2 mm en A5, y en Carta quedaba a 11 con el
       margen de 15 mm; con los 20 de AG3 queda unos 5 mm más adentro. */
    @page hoja {
        @top-center {
            content: "";
        }

        @bottom-left {
            content: var(--pie-de-pagina, "");
            font-family: var(--fuente-interfaz);
            font-size: var(--pie-tamano, 8pt);
            color: var(--tinta-papel-tenue);
            vertical-align: top;
        }

        @bottom-right {
            content: "Hoja " counter(page) " de " counter(pages);
            font-family: var(--fuente-interfaz);
            font-size: var(--pie-tamano, 8pt);
            color: var(--tinta-papel-tenue);
            vertical-align: top;
        }
    }

    /* El `h1` sí necesita su regla: fuera de la impresora se pinta con `--turquesa-profundo`, que
       es marca de Vetika y no tiene nada que hacer en el papel que una clínica le entrega a un
       tutor. Lo que cambió el 16-08-2026 es a qué se lo repinta: antes a `black`, que era la
       tercera tinta entrando por la puerta de atrás. */
    .hoja h1,
    .hoja h2 {
        color: var(--tinta-papel);
    }

    .hoja .etiqueta {
        border: 1px solid var(--tinta-papel);
        background: none;
        color: var(--tinta-papel);
        font-size: max(0.75rem, 7.5pt);
    }
}

/* ---------------------------------------------------------------------------
   Documentos impresos: todas las hojas menos la epicrisis

   Las que llevan `.hoja-documento`: presupuesto, documento tributario y receta, y después el anexo,
   la hoja del externo y la respuesta del art. 5°. Comparten la gramática de la epicrisis —membrete, hoja blanca y controles que desaparecen—
   pero no su estructura clínica. La jerarquía acá es emisor → documento → detalle → firma o
   advertencia, que es la lectura natural de una hoja que se entrega en el mesón.
   --------------------------------------------------------------------------- */
.hoja-documento {
    max-width: 58rem;
}

.cabecera-documento {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 2rem;
    margin-top: 2rem;
}

.cabecera-documento h1 {
    margin-bottom: 0.15rem;
}

.folio-documento {
    margin: 0;
    color: var(--texto-tenue);
    font-variant-numeric: tabular-nums;
}

/* Se lee como un sello de documento, no como un estado interactivo de la aplicación. */
.sello-no-boleta {
    display: inline-block;
    flex: 0 0 auto;
    padding: 0.55rem 0.75rem;
    border: 2px solid var(--rojo);
    color: var(--rojo-profundo);
    font-size: 0.85rem;
    line-height: 1.2;
    text-align: center;
}

/* El mismo sello, en el ámbar de "hay que mirarlo y ya ocurrió": el anexo de un periodo que
   todavía no se cierra puede crecer, y entregado sin decirlo se lee como definitivo. No va en el
   rojo del "no válido como boleta" porque ahí el papel afirma algo que no es —esto no es una
   boleta— y acá el papel es correcto, solo que todavía no está completo. */
.sello-provisorio {
    display: inline-block;
    flex: 0 0 auto;
    padding: 0.55rem 0.75rem;
    border: 2px solid var(--ambar-profundo);
    color: var(--ambar-profundo);
    font-size: 0.85rem;
    line-height: 1.2;
    text-align: center;
}

.advertencia-impresa {
    margin-top: 1.25rem;
    padding: 0.85rem 1rem;
    border: 1px solid var(--rojo);
    background: var(--rojo-suave);
    color: var(--rojo-profundo);
}

.advertencia-impresa strong {
    display: block;
    margin-bottom: 0.15rem;
}

.hoja-documento .datos-documento dl {
    grid-template-columns: minmax(5rem, max-content) 1fr;
}

.tabla-documento tbody tr,
.tabla-documento tfoot tr {
    break-inside: avoid;
}

/* ---- El anexo del art. 54 bis: la comisión y la cuenta que la produjo, en dos filas ----

   El art. 54 bis inc. 3.º pide la operación **y la forma empleada para su cálculo**. Son cinco
   pasos —bruto, insumo, neto, participación, tasa— y en una columna más no caben: se leen como una
   frase, así que van en una fila propia debajo de su operación.

   Sin quitarle el borde a la de arriba, las dos se ven como dos operaciones distintas y la hoja
   parece tener el doble de filas de las que tiene. */
tr:has(+ .calculo-de-la-comision) td {
    border-bottom: none;
}

.calculo-de-la-comision td {
    padding-top: 0;
    font-size: 0.85rem;
}

/* Cada operación es su propio `tbody` justamente para esto: que la comisión y su explicación no
   queden a caballo entre dos hojas. Una cifra cuyo cálculo pasó a la página siguiente es lo que
   estas dos hojas existen para evitar: el anexo porque la ley pide la forma del cálculo pegada a
   su operación, y la del externo porque ese total es el que alguien va a boletear.

   **Sólo el `tbody` de una operación con su cálculo, no cualquiera** (U2, medido el 21-09-2026). La
   tabla de las que no devengaron tiene un único `tbody` con todas sus filas, y la regla escrita para
   todo `tbody` la volvía indivisible entera: saltaba a la hoja siguiente y dejaba atrás 75 mm libres
   en Carta y dos tercios de una media carta, con la primera fila cabiendo de sobra. Sus filas ya son
   indivisibles una a una por `.tabla-documento tbody tr`. */
@media print {
    .hoja-anexo .tabla-documento tbody:has(.calculo-de-la-comision),
    .hoja-del-externo .tabla-documento tbody:has(.calculo-de-la-comision) {
        break-inside: avoid;
    }
}

.desglose-impreso {
    break-inside: avoid;
}

.texto-documento {
    max-width: 75ch;
    white-space: pre-wrap;
}

.bloque-receta .texto-documento {
    min-height: 4rem;
    font-size: 1.05rem;
    line-height: 1.65;
}

/* Si la firma de una receta pasa completa a otra página, esta identificación pasa con ella. Es
   deliberadamente compacta: no compite con el membrete cuando ambas quedan en la misma página. */
.identidad-firma {
    margin: 0;
    color: var(--texto-tenue);
    font-size: 0.85rem;
    text-align: right;
}

/* La clase sigue existiendo aunque ya no traiga borde ni relleno propios —los subió `.hoja .pie`
   cuando el color de acento necesitó estar en las cuatro hojas—: es el gancho con el que
   `@media print` mantiene el pie entero en la misma página. */

/* A la derecha por lo mismo que `.hoja .firma`, y con ella tiene que moverse: la receta y la
   epicrisis se entregan en el mismo mesón y una hoja firma abajo a la izquierda y la otra abajo
   a la derecha se ve como dos sistemas. */
.firma-profesional {
    width: min(20rem, 100%);
    margin-top: 5rem;
    margin-left: auto;
    text-align: center;
}

.firma-profesional > span {
    display: block;
    border-top: 1px solid var(--texto);
}

.firma-profesional p {
    margin: 0.25rem 0 0;
}

/* La firma y el timbre descansan sobre la raya, no flotan encima: alineados abajo, para que la
   imagen termine donde empieza la línea igual que una firma de puño.

   4rem son unos 17 mm impresos, que es lo que ocupa una firma sobre una receta de la clínica. El
   `min-height` mantiene la raya en el mismo lugar cuando hay una sola de las dos imágenes, o
   ninguna todavía cargada, para que la hoja no cambie de forma según quién atendió. */
.credencial-aplicada {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    gap: 1rem;
    min-height: 4rem;
}

.credencial-aplicada img,
.muestra-de-credencial img {
    max-height: 4rem;
    max-width: 45%;
    object-fit: contain;
}

/* Una firma escaneada es tinta oscura sobre transparencia, así que sobre Grafito clínico
   desaparece. Es exactamente el defecto que F3 encontró con el logo y resolvió dándole papel al
   membrete, y acá vale por la misma razón: esto se dibuja para la impresora.

   El papel se pone **solo cuando hay imagen** —de ahí la clase aparte—: sin credencial este bloque
   es una raya y dos líneas de texto que se leen perfecto en los dos temas, y una tarjeta blanca en
   medio de una hoja oscura sería peor que lo que arregla.

   `.muestra-de-credencial` es lo mismo en la pantalla de la cuenta propia, donde alguien está
   mirando precisamente si la imagen que subió se ve. */
.firma-profesional.con-credencial,
.muestra-de-credencial {
    --texto: var(--tinta-papel);
    --texto-tenue: var(--tinta-papel-tenue);
    padding: 0.5rem 0.75rem;
    border-radius: 0.5rem;
    background: var(--blanco);
    color: var(--tinta-papel);
}

/* En la cuenta propia la muestra es una caja chica dentro de la sección, no un pie de hoja. */
.muestra-de-credencial {
    width: min(20rem, 100%);
    margin: 0.5rem 0;
    border: 1px solid var(--borde);
    text-align: center;
}

/* Cada bloque —la firma, el timbre— se separa del anterior sin necesitar una sección propia: son
   dos formularios cortos que se leen como una sola pregunta. */
.credencial + .credencial {
    margin-top: 2rem;
    padding-top: 1.5rem;
    border-top: 1px solid var(--borde);
}

/* La vista previa de la pantalla de marca: la misma hoja, en chico y dentro de una sección.

   Va sobre papel entero y no solo en el membrete, porque acá lo que se está mirando es
   precisamente si los dos colores funcionan sobre blanco. Es la única parte de la aplicación
   —fuera del membrete— que no sigue al tema, y por la misma razón: se está previendo una
   impresión, no una pantalla. */
.vista-previa {
    --texto-tenue: var(--tinta-papel-tenue);
    padding: 0 1rem 1rem;
    background: var(--blanco);
    color: var(--tinta-papel);
    border: 1px solid var(--borde);
    border-radius: 0.5rem;
}

/* El membrete llega al borde de la hoja, como en el papel. Los márgenes negativos son lo que
   deja que la banda blanca ocupe el ancho completo sin sacar al resto del relleno. */
.vista-previa .membrete {
    margin: 0 -1rem;
}

/* El mensaje de cobro escrito tal cual sale: de ejemplo en la pantalla de datos de transferencia,
   y de verdad en la de cobro cuando el tutor no tiene teléfono con el que armar el enlace y hay
   que copiarlo a mano.

   Es un `pre` y no un párrafo porque los saltos de línea son parte del mensaje: el tutor copia el
   número de cuenta de una línea suya hacia la aplicación de su banco, y un párrafo los colapsa
   dejando los cinco datos corridos. Lo que hay que apagarle es la monoespaciada que el navegador
   le pone de fábrica —en este sistema esa familia no existe— y el `pre` a secas, que en un mensaje
   de sesenta caracteres obligaría a desplazar de lado.

   Angosto a propósito, y esta sí sigue al tema, al revés que la vista previa del membrete: el
   mensaje se lee en la pantalla de un teléfono y no se imprime. A 48rem un mensaje de seis líneas
   se ve como un párrafo suelto y no como lo que le va a llegar al tutor. */
.mensaje-de-cobro {
    font-family: inherit;
    font-size: 1rem;
    line-height: 1.6;
    white-space: pre-wrap;
    max-width: 26rem;
    margin: 0;
    padding: 1rem;
    background: var(--campo);
    color: var(--texto);
    border: 1px solid var(--borde);
    border-radius: 0.75rem;
}

@media screen and (max-width: 640px) {
    .cabecera-documento {
        flex-direction: column;
        gap: 1rem;
    }
}

@media print {
    /* Una tabla larga puede continuar en la hoja siguiente; cada fila se mantiene unida. */
    .hoja-documento section {
        break-inside: auto;
    }

    /* Los datos del documento son cortos y se leen juntos. Las secciones de la hoja del art. 5°
       también llevan esta clase, las de tabla incluidas, y hasta el hallazgo 95 esto las mandaba
       enteras a la hoja siguiente; ahora les gana `.hoja section:has(table, .texto-pegado)`, que es
       la regla general de lo largo y vive con las demás de la hoja. El pie ya no se nombra acá: es
       de todas las hojas y vive allá. */
    .hoja-documento .datos-documento {
        break-inside: avoid;
    }

    /* Una indicación corta queda junta por sus viudas y huérfanas; una larga tiene que poder
       continuar en la página siguiente. Declarar el bloque entero indivisible dejaba casi vacía
       la primera media carta cuando el texto ya no cabía completo. */
    .hoja-receta .bloque-receta {
        break-inside: auto;
    }

    .hoja-receta .texto-documento {
        orphans: 3;
        widows: 3;
    }

    /* **En hoja grande, la firma va al pie de la hoja** (hallazgo 149, AG3). La receta corta usaba la
       mitad de arriba de una Carta y dejaba la otra en blanco, debajo de la firma. Al pie queda como
       un recetario: el membrete arriba, lo indicado debajo y la firma abajo, con el espacio entre los
       dos para lo que el veterinario quiera agregar a mano. Lo decidimos nosotros.

       El alto sale del papel elegido, `--alto-util-del-papel`, que declara cada hoja de estilo de
       papel junto a su margen. **Los 3 mm de menos son la guarda**: un contenido que mide justo la
       hoja, con un redondeo en contra, sale con una segunda hoja en blanco. Una receta que no cabe
       en una hoja sigue partiéndose como siempre: el alto mínimo ya está cumplido y la firma viaja
       con lo último, por `.hoja .pie`. */
    html[data-hoja="receta"]:is([data-papel="carta"], [data-papel="a4"]) .hoja-receta {
        display: flex;
        flex-direction: column;
        min-height: calc(var(--alto-util-del-papel, 0mm) - 3mm);
    }

    /* El margen automático es lo que la empuja al fondo. El último bloque guarda la distancia mínima
       que el pie tenía antes, para que una receta que llena la hoja no lo deje pegado al texto. */
    html[data-hoja="receta"]:is([data-papel="carta"], [data-papel="a4"]) .hoja-receta > .pie {
        margin-top: auto;
    }

    html[data-hoja="receta"]:is([data-papel="carta"], [data-papel="a4"]) .hoja-receta > section:last-of-type {
        margin-bottom: 1.2rem;
    }

    /* El sello del provisorio se había quedado fuera, y en papel su ámbar es el de la pantalla:
       impreso desde Grafito clínico, `--ambar-profundo` es un amarillo claro sobre blanco. */
    .sello-no-boleta,
    .sello-provisorio,
    .advertencia-impresa {
        border-color: var(--tinta-papel);
        background: none;
        color: var(--tinta-papel);
    }

    /* Lo que advierte no baja del cuerpo. Los dos sellos van a 0,85rem porque en pantalla compiten
       con el título a su lado; con la raíz de papel eso los dejaba bajo el texto de la hoja, y un
       «No válido como boleta» más chico que el detalle es lo último que se quiere achicar. */
    .sello-no-boleta,
    .sello-provisorio {
        font-size: 1rem;
    }

    .cabecera-documento {
        gap: 1.25rem;
        margin-top: 0.9rem;
    }

    .hoja .pie {
        margin-top: 1.2rem;
        padding-top: 0.6rem;
    }

    /* El 1,65 de pantalla, a 12,6 pt, hacía de cada renglón de la receta casi dos. Sigue un punto
       sobre el cuerpo —1,05rem— porque es lo único que el tutor lee en la casa, con el animal
       delante, pero con el interlineado de un texto impreso. */
    .bloque-receta .texto-documento {
        line-height: 1.45;
    }

    /* Lo físico, en mm: no sigue a la letra. Una firma, un timbre y un logo miden lo que miden en
       el papel, y en `rem` se habrían achicado con la escala. Son los tamaños que ya tenían —4rem,
       3,5rem, 12rem, 5rem, 18rem y 20rem a 12 pt, convertidos—, y **la única medida que cambia es
       la reserva para firmar de la epicrisis**: tenía 3rem, 13 mm para *«Firma y timbre»*, y sube a
       la de la receta. Las dos se entregan en el mismo mesón y se firman con el mismo timbre. */
    .logo-clinica {
        max-height: 15mm;
        max-width: 51mm;
    }

    .credencial-aplicada {
        min-height: 17mm;
    }

    .credencial-aplicada img {
        max-height: 17mm;
    }

    .firma-profesional {
        width: min(85mm, 100%);
        margin-top: 21mm;
    }

    .hoja .firma {
        width: min(76mm, 100%);
        margin-top: 21mm;
    }

    /* Sobre papel, la banda del membrete ya no tiene por qué dibujarse: el papel es el fondo.
       Lo que sí queda es su línea, y en el color de la clínica cuando lo hay.

       Sin marca la línea sale **en la tinta del papel y no en turquesa**, que es un cambio respecto
       de antes de F3: el turquesa es la marca de Vetika, y no corresponde en el papel que una
       clínica le entrega a un tutor. La epicrisis lo venía imprimiendo así porque nunca tuvo esta
       regla. La alternativa era `black` hasta el 16-08-2026, y la cambió la regla de una sola
       tinta: una clínica sin marca configurada tenía sus dos líneas en un negro que no era el de
       ninguna otra cosa de la hoja. */
    .hoja .membrete {
        padding: 0 0 0.75rem;
        border-radius: 0;
        background: none;
        border-bottom-color: var(--marca-principal, var(--tinta-papel));
    }

    .hoja .pie {
        border-top-color: var(--marca-acento, var(--tinta-papel));
    }

    /* La línea sobre la que se firma, en tinta y no en el color del tema. La receta ya lo hacía;
       la epicrisis no, y por eso imprimir desde Grafito clínico le dejaba la raya casi blanca
       sobre el papel: `var(--texto)` sigue al tema y la impresora no. Se ve al mover las dos
       firmas juntas y es la misma regla, así que va en el mismo lugar.

       `.firma-profesional` necesita nombrarse aparte y no le basta con heredar: vive fuera de
       `.hoja` en la vista previa de `/marca`, donde redefine los tokens por su cuenta.

       Las cuatro rayas de la aceptación del presupuesto (Z3) se habían quedado fuera, y es la misma
       raya: se vio al mover el bloque en el hallazgo 131. */
    .firma-profesional > span,
    .hoja .firma span,
    .hoja .campos-de-aceptacion span {
        border-color: var(--tinta-papel);
    }

    /* A5 y media carta no son una versión encogida de Carta: conservan la lectura, pero recuperan
       el espacio que en una hoja corta se pierde en rellenos, separaciones y la reserva de firma.
       Los selectores dependen del formato elegido, no del ancho calculado por el navegador; así
       una impresora con otra resolución no activa por accidente el diseño de teléfono.

       **La letra ya no se decide acá** (U1): la pone la raíz de 9 pt, y con ella bajan en proporción
       el título, el subtítulo y la línea tenue del membrete, que hasta el 21-09 tenían aquí cada uno
       su tamaño en `pt`. Lo que queda es aire que en una hoja corta sobra, y lo físico en mm. */
    html[data-papel="a5"] .hoja .membrete,
    html[data-papel="media-carta"] .hoja .membrete {
        gap: 0.65rem;
        padding-bottom: 0.55rem;
    }

    html[data-papel="a5"] .logo-clinica,
    html[data-papel="media-carta"] .logo-clinica {
        max-height: 12mm;
        max-width: 38mm;
    }

    html[data-papel="a5"] .advertencia-impresa,
    html[data-papel="media-carta"] .advertencia-impresa {
        margin-top: 0.85rem;
        padding: 0.55rem 0.65rem;
    }

    html[data-papel="a5"] .bloque-receta .texto-documento,
    html[data-papel="media-carta"] .bloque-receta .texto-documento {
        min-height: 0;
    }

    html[data-papel="a5"] .firma-profesional,
    html[data-papel="media-carta"] .firma-profesional,
    html[data-papel="a5"] .hoja .firma,
    html[data-papel="media-carta"] .hoja .firma {
        margin-top: 11mm;
    }

    html[data-papel="a5"] .credencial-aplicada,
    html[data-papel="media-carta"] .credencial-aplicada {
        min-height: 13mm;
    }

    html[data-papel="a5"] .credencial-aplicada img,
    html[data-papel="media-carta"] .credencial-aplicada img {
        max-height: 13mm;
    }
}
