/* =====================================================================
   LEGIO-RECORD — Hoja de estilos del sitio

   Sistema visual tomado del canvas «Fe Diaria»: papel crema, tinta azul
   apagada, oro litúrgico y un acento por módulo.

   Adaptación deliberada: aquél es un lector devocional, con mucho aire y
   serif grande. Esto es una trastienda administrativa. Se conserva la
   paleta y el gesto, pero la densidad de las rejillas se mantiene: el
   serif va SOLO en títulos y marca; los datos van en Karla, que a 13,5 px
   aguanta una tabla de doce columnas sin cansar.

   Las tipografías se alojan en assets/webfonts (ver fuentes.css): la CSP
   lleva font-src 'self' y no queremos abrirla a un host externo.
   ===================================================================== */

@import url('../webfonts/fuentes.css');

:root {
    /* ---- Papel y tinta ------------------------------------------ */
    --papel:        #FAF6EF;
    --superficie:   #FFFDF9;
    --superficie-2: #FCFAF6;
    /* Los tonos de tinta llevan ~20% más de contraste sobre el papel que
       la primera versión. No es gusto: quien usa esto pasa de los 60 y
       trabaja desde el celular, muchas veces a la luz del salón. Los
       valores están medidos contra --papel, no elegidos a ojo. */
    --tinta:        #323A47;   /* antes #3C4655 — 8.86 : 1  ->  10.64 : 1 */
    --tinta-suave:  #515B6A;   /* antes #5C6779 — 5.31 : 1  ->   6.40 : 1 */
    --tinta-tenue:  #69717B;   /* antes #9AA6B5 — 2.29 : 1  ->   4.60 : 1 */
    --linea:        rgba(50, 58, 71, .22);
    --linea-suave:  rgba(50, 58, 71, .11);

    /* ---- Los cinco colores de la paleta -------------------------
       Cada uno con su tono hondo (para texto, que necesita contraste),
       su agua (fondos suaves) y su par de degradado (superficies).
       Los degradados son los del canvas original. */
    --oro:        #C9A44C;   --oro-hondo:      #7B6739;  --oro-agua:      #FBF6EC;
    --oro-g1:     #D8B463;   --oro-g2:         #C09339;

    --azul:       #8FA9C4;   --azul-hondo:     #405166;  --azul-agua:     #F1F4F8;
    --azul-g1:    #A7BDD3;   --azul-g2:        #7E96B2;

    --salvia:     #A9B79A;   --salvia-hondo:   #556D49;  --salvia-agua:   #F1F4EE;
    --salvia-g1:  #BCC8AF;   --salvia-g2:      #8B9B77;

    --terracota:  #D3A08F;   --terracota-hondo:#944B37;  --terracota-agua:#FAF0EC;
    --terracota-g1: #E0B7A8; --terracota-g2:   #C88E76;

    --lavanda:    #A79BB8;   --lavanda-hondo:  #625874;  --lavanda-agua:  #F4F2F7;
    --lavanda-g1: #BCB2CA;   --lavanda-g2:     #8D80A2;

    /* ---- Acento activo -------------------------------------------
       Lo redefine cada módulo del menú; por omisión, el oro. */
    --acento:       var(--oro);
    --acento-hondo: var(--oro-hondo);
    --acento-agua:  var(--oro-agua);

    /* ---- Semánticos, derivados de la misma paleta ---------------- */
    --ok:          #556D49;
    --ok-fondo:    #EFF3EA;
    --error:       #944B37;
    --error-fondo: #F9EDE8;
    --aviso:       #7B6739;
    --aviso-fondo: #FAF3E4;

    /* ---- Tipografía ---------------------------------------------- */
    --serif: 'Cormorant Garamond', Cambria, Georgia, serif;
    --sans:  Karla, 'Segoe UI', system-ui, -apple-system, Arial, sans-serif;

    --radio:       10px;
    --radio-chico: 7px;
    --sombra:      0 1px 2px rgba(60, 70, 85, .05), 0 18px 40px -28px rgba(60, 70, 85, .35);
}

* { box-sizing: border-box; }

body {
    margin: 0;
    color: var(--tinta);
    /* 16px de base, no 15: todo lo que se mide en rem sube con ella. */
    font: 400 16px/1.6 var(--sans);
    -webkit-font-smoothing: antialiased;

    /* El lavado radial del canvas original, muy rebajado: da carácter
       sin competir con los datos. */
    background:
        radial-gradient(680px 480px at 8% 2%, rgba(232, 213, 208, .38), transparent 60%),
        radial-gradient(720px 520px at 94% 0%, rgba(143, 169, 196, .20), transparent 62%),
        var(--papel);
    background-attachment: fixed;
}

a { color: var(--azul-hondo); text-decoration: none; }
a:hover { color: var(--oro-hondo); }

:focus-visible {
    outline: 2px solid var(--acento);
    outline-offset: 2px;
    border-radius: 3px;
}

h1 {
    font: 500 1.75rem/1.15 var(--serif);
    margin: 0;
    letter-spacing: -.005em;
}
h1 small {
    display: block;
    margin-top: .2rem;
    font: 400 .8rem/1.4 var(--sans);
    color: var(--tinta-tenue);
    letter-spacing: 0;
}
h2 { font: 500 1.3rem/1.25 var(--serif); margin: 0 0 .7rem; }

/* Rótulo en versalitas: el gesto más característico del sistema.
   Se conserva, pero a 10.5px con seguimiento ancho era ilegible para el
   ojo al que va dirigido. Sube a 12, y el que estructura el formulario
   —el que dice en qué punto de la junta vas— a 13. */
.nav-title, .grid th, .form-seccion {
    font-family: var(--sans);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .13em;
    text-transform: uppercase;
}
.form-seccion { font-size: 13px; color: var(--tinta-suave); }

/* ---- Barra superior ------------------------------------------------ */
.topbar {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0 1.5rem;
    height: 62px;
    background: var(--superficie);
    border-bottom: 1px solid var(--linea);
}

.brand { display: flex; align-items: center; gap: .75rem; color: var(--tinta); text-decoration: none; }

/* El Vexillum de la Legión sustituye al monograma. Es una pieza vertical
   (75x133), así que se fija por altura y el ancho sigue la proporción:
   forzar un cuadrado la deformaría. */
.brand-mark {
    display: block;
    height: 40px;
    width: auto;
}
.brand-text strong { display: block; font: 500 1.05rem/1.1 var(--serif); }
.brand-text small { font-size: .68rem; color: var(--tinta-tenue); letter-spacing: .08em; text-transform: uppercase; }

.topbar-user { margin-left: auto; display: flex; align-items: center; gap: .5rem; }
.user-name { font-size: .84rem; color: var(--tinta-suave); }

.menu-toggle {
    display: none;
    flex-direction: column; gap: 4px;
    background: none; border: 0; cursor: pointer; padding: .4rem;
}
.menu-toggle span { display: block; width: 20px; height: 1.4px; background: var(--tinta-suave); border-radius: 2px; }

/* ---- Estructura ---------------------------------------------------- */
.layout { display: grid; grid-template-columns: 232px minmax(0, 1fr); min-height: calc(100vh - 110px); }

.sidebar { padding: 1.6rem 0; border-right: 1px solid var(--linea); }

.nav-group + .nav-group { margin-top: 1.6rem; }
.nav-title { margin: 0 0 .5rem; padding: 0 1.5rem; color: var(--tinta-tenue); }

/* Cada módulo lleva su color, como en el canvas original: ayuda a saber
   dónde estás sin tener que leer. El bloque redefine --acento y de ahí
   lo heredan tablas, tarjetas y formularios de esa zona. */
[data-modulo="estructura"] { --acento: var(--lavanda);   --acento-hondo: var(--lavanda-hondo);   --acento-agua: var(--lavanda-agua);   --g1: var(--lavanda-g1);   --g2: var(--lavanda-g2); }
[data-modulo="juntas"]     { --acento: var(--oro);       --acento-hondo: var(--oro-hondo);       --acento-agua: var(--oro-agua);       --g1: var(--oro-g1);       --g2: var(--oro-g2); }
[data-modulo="tesoreria"]  { --acento: var(--salvia);    --acento-hondo: var(--salvia-hondo);    --acento-agua: var(--salvia-agua);    --g1: var(--salvia-g1);    --g2: var(--salvia-g2); }
[data-modulo="documentos"],
[data-modulo="informes"]   { --acento: var(--terracota); --acento-hondo: var(--terracota-hondo); --acento-agua: var(--terracota-agua); --g1: var(--terracota-g1); --g2: var(--terracota-g2); }
[data-modulo="seguridad"]  { --acento: var(--azul);      --acento-hondo: var(--azul-hondo);      --acento-agua: var(--azul-agua);      --g1: var(--azul-g1);      --g2: var(--azul-g2); }
[data-modulo="general"]    { --acento: var(--lavanda);   --acento-hondo: var(--lavanda-hondo);   --acento-agua: var(--lavanda-agua);   --g1: var(--lavanda-g1);   --g2: var(--lavanda-g2); }

.nav-title::before {
    content: '';
    display: inline-block;
    width: 6px; height: 6px;
    margin-right: .5rem;
    border-radius: 50%;
    background: var(--acento);
    vertical-align: middle;
}

.nav-list { list-style: none; margin: 0; padding: 0; }
.nav-link {
    display: block;
    margin: 0 .75rem;
    padding: .42rem .75rem;
    border-radius: 999px;
    color: var(--tinta-suave);
    text-decoration: none;
    font-size: .885rem;
}
.nav-link:hover { background: var(--superficie); color: var(--tinta); }
.nav-link.current { background: var(--acento-agua); color: var(--acento-hondo); font-weight: 600; }

.content { padding: 1.9rem 2.1rem 3.5rem; min-width: 0; }

.sitefoot {
    display: flex; justify-content: space-between; align-items: center;
    padding: .8rem 2.1rem;
    border-top: 1px solid var(--linea);
    font-size: .76rem;
    color: var(--tinta-tenue);
}
.env-tag { background: var(--aviso-fondo); color: var(--aviso); padding: .15rem .6rem; border-radius: 999px; font-weight: 600; }

/* ---- Cabecera de página -------------------------------------------- */
.page-head {
    display: flex; align-items: flex-end; justify-content: space-between;
    gap: 1rem; margin-bottom: 1.35rem;
}
.page-help { margin: -.55rem 0 1.1rem; color: var(--tinta-suave); font-size: .88rem; max-width: 68ch; }

/* ---- Avisos --------------------------------------------------------- */
.alert {
    padding: .75rem 1.05rem;
    border-radius: var(--radio-chico);
    border: 1px solid;
    margin-bottom: 1.1rem;
    font-size: .9rem;
}
.alert-ok    { background: var(--ok-fondo);    border-color: rgba(95, 122, 82, .3);  color: var(--ok); }
.alert-error { background: var(--error-fondo); border-color: rgba(168, 85, 63, .3);  color: var(--error); }
.alert-aviso { background: var(--aviso-fondo); border-color: rgba(138, 116, 64, .3); color: var(--aviso); }

/* ---- Botones -------------------------------------------------------- */
.btn {
    /* inline-flex y no inline-block: es lo que permite centrar el texto
       dentro de los 48px de alto sin calcular el padding a mano. */
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 48px;
    min-width: 44px;
    padding: .5rem 1.25rem;
    border: 1px solid var(--linea);
    border-radius: 999px;
    background: var(--superficie);
    color: var(--tinta);
    font: 500 16px var(--sans);
    text-decoration: none;
    cursor: pointer;
    white-space: nowrap;
    transition: background .12s ease, border-color .12s ease, color .12s ease;
}
.btn:focus-visible {
    outline: 3px solid var(--acento-hondo);
    outline-offset: 2px;
}
.btn:hover { background: var(--superficie-2); border-color: var(--tinta-tenue); color: var(--tinta); }
.btn:disabled { opacity: .45; cursor: default; }

.btn-primary {
    background: var(--oro); border-color: var(--oro); color: #fff;
    box-shadow: 0 6px 16px -10px rgba(201, 164, 76, .9);
}
.btn-primary:hover { background: var(--oro-hondo); border-color: var(--oro-hondo); color: #fff; }

.btn-danger { color: var(--error); border-color: rgba(168, 85, 63, .35); background: var(--superficie); }
.btn-danger:hover { background: var(--error-fondo); border-color: var(--error); color: var(--error); }

.btn-plain { background: transparent; border-color: transparent; color: var(--tinta-suave); }
.btn-plain:hover { background: var(--superficie); border-color: var(--linea); }

/* El «pequeño» sigue siendo pulsable: 40px es el suelo que se acepta
   cuando el control está dentro de una fila de tabla. */
.btn-small { min-height: 40px; padding: .3rem .9rem; font-size: 15px; }

/* En la barra oscura no hay: la superior ahora es clara. */
.topbar .btn-plain { color: var(--tinta-suave); border-color: var(--linea); }
.topbar .btn-plain:hover { background: var(--superficie-2); color: var(--tinta); }

/* ---- Barra de herramientas ------------------------------------------ */
.toolbar { display: flex; gap: .5rem; margin-bottom: 1.1rem; flex-wrap: wrap; align-items: center; }
.toolbar-label { font-size: .84rem; color: var(--tinta-suave); }
.search-input {
    flex: 1 1 260px; max-width: 380px;
    min-height: 48px;
    padding: .5rem 1.1rem;
    border: 1px solid var(--linea); border-radius: 999px;
    /* 17px por lo mismo que los demás campos: por debajo de 16 el iPhone
       amplía la página al enfocar. */
    font: 400 17px var(--sans);
    background: var(--superficie);
    color: var(--tinta);
}
.search-input:focus { border-color: var(--acento); outline: none; }

/* ---- Tabla ----------------------------------------------------------
   Aquí es donde el sistema original NO se sigue al pie de la letra: una
   rejilla necesita densidad y contraste, no aire y serif. */
.table-wrap {
    overflow-x: auto;
    background: var(--superficie);
    border: 1px solid var(--linea);
    border-radius: var(--radio);
    box-shadow: var(--sombra);
}
.grid { border-collapse: collapse; width: 100%; font-size: .845rem; }
.grid th {
    text-align: left;
    padding: .7rem .85rem;
    background: var(--superficie-2);
    border-bottom: 1px solid var(--linea);
    color: var(--tinta-tenue);
    white-space: nowrap;
}
.grid td {
    padding: .58rem .85rem;
    border-bottom: 1px solid var(--linea-suave);
    vertical-align: top;
    color: var(--tinta-suave);
}
.grid td:first-child { color: var(--tinta); }
.grid tbody tr:last-child td { border-bottom: 0; }
.grid tbody tr:hover td { background: var(--acento-agua); }

/* ---- Encabezado de grupo dentro de la tabla --------------------------
   Una fila entera con el nombre del bloque. Va en el cuerpo, así que
   hereda el color de las celdas y hay que devolverle el peso: si no se
   distingue de un dato, no encabeza nada.

   `white-space: normal` deshace el `nowrap` de las cabeceras de columna:
   ahí evita que «Observaciones» se parta, pero un rótulo de grupo largo
   en un celular tiene que poder envolver en vez de ensanchar la tabla. */
.grid-grupo th {
    background: var(--superficie-2);
    border-top: 1px solid var(--linea);
    border-bottom: 1px solid var(--linea-suave);
    color: var(--tinta);
    font: 500 .92rem/1.3 var(--serif);
    letter-spacing: .01em;
    padding: .55rem .85rem;
    white-space: normal;
}
.grid tbody tr.grid-grupo:hover th { background: var(--superficie-2); }

/* ---- La cantidad, editable dentro de la fila -------------------------

   Es el dato que más se corrige, y abrir el formulario para cambiar una
   tecla son tres pantallas en un celular.

   El orden del HTML es [Guardar] [−] [número] [+], y el de la pantalla
   es [−] [número] [+] [Guardar]. No es capricho: al pulsar Intro en el
   campo, el navegador envía con el PRIMER botón del formulario. Si ese
   fuera «−», teclear «7» y pulsar Intro guardaría 6. Yendo primero el
   neutro (paso = 0), guarda el 7. `order` lo recoloca sin tocar el HTML,
   y con JavaScript el neutro se esconde porque se guarda solo. */
/* Dos renglones: «− [n] +» arriba y «Guardar» abajo, a todo el ancho de
   la celda.

   En una sola línea los cuatro controles se apretaban hasta no poder
   tocarse, y el que de verdad escribe en la base —el diskette— quedaba el
   más chico de todos. Abajo tiene sitio para su dibujo y su palabra, y un
   objetivo del ancho entero es el más fácil de acertar con el pulgar.

   `flex-wrap` más `flex-basis: 100%` en el botón es lo que abre el segundo
   renglón: sin el wrap el 100% apretaría a los otros tres hasta cero. */
/* ---- Dos renglones de verdad, no un flex que envuelve ----------------

   El formulario es una COLUMNA de dos cosas: el grupo «− [n] +» arriba y
   el botón de guardar abajo. Antes era una sola fila con `flex-wrap` y el
   botón a `100%`, y funcionaba… mientras la columna midiera lo que dice
   que mide.

   No lo mide: `.grid` es `width: 100%` con `table-layout: auto`, así que
   en una pantalla estrecha el navegador estruja las columnas para que la
   tabla quepa y el `width: 150px` se queda en sugerencia. Con menos hueco
   del previsto, el flex envolvía por donde no debía y el «+» aparecía
   debajo del número.

   En columna no hay nada que envolver: los dos renglones son dos, y punto. */
.cant {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: .3rem;
}

/* Y el grupo, en fila y SIN envolver. `nowrap` no es solo cosmético: le da
   al grupo un ancho mínimo de contenido real, y ESE sí lo respeta el
   reparto de columnas de la tabla. La columna deja de poder estrujarse por
   debajo de lo que sus controles necesitan. */
.cant-fila {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
}

/* `order: 2` y no el orden del HTML: en el documento este botón va PRIMERO
   —lo necesita para que Intro en el campo envíe con él y no con «−»— y
   aquí se recoloca abajo, que es donde se lee. */
.cant-ok {
    order: 2;
    width: 100%;
    /* Lo que aportaba `btn-icono`, que ya no lleva: esa clase esconde el
       rótulo por debajo de 860 px y aquí la palabra tiene que verse
       también en el celular. */
    gap: .4rem;
    /* Menos holgura a los lados que un .btn-small normal: la columna mide
       160px y dentro hay que meter dibujo y palabra sin que «Guardar» se
       parta en dos renglones. */
    padding-left: .5rem;
    padding-right: .5rem;
}
.cant-ok .icono { flex: 0 0 auto; }

/* ---- «−» «+» pegados al número, como un solo control -----------------

   Los tres comparten alto y se tocan: el «−» redondea por la izquierda, el
   «+» por la derecha y el número queda cuadrado en medio, así que el
   conjunto se lee como una pieza y no como tres cosas sueltas.

   Chicos a propósito. El que de verdad escribe en la base es el diskette
   —que ya tiene su renglón entero debajo—; estos dos solo mueven un número
   en la pantalla y no hacen falta del tamaño de un botón de acción.

   30x38 queda por debajo de los 44px que recomiendan las guías táctiles.
   Es una decisión tomada a sabiendas: van PEGADOS a un campo que sí es
   grande, así que un dedo que falle cae dentro del número —donde no pasa
   nada— y no sobre otra acción. Nada de lo que hay al lado destruye datos.

   `margin` negativo para que los bordes no se dupliquen: dos líneas de 1px
   pegadas se ven como una de 2px y delatan la costura. */
.cant-paso {
    order: 1;   /* dentro de .cant-fila */
    flex: 0 0 auto;
    width: 30px;
    min-height: 38px;
    padding: 0;
    border: 1px solid var(--linea);
    border-radius: 8px 0 0 8px;
    background: var(--superficie-2);
    color: var(--tinta);
    font: 500 17px/1 var(--sans);
    cursor: pointer;
}
.cant-paso[value="1"] {
    order: 3;
    border-radius: 0 8px 8px 0;
    margin-left: -1px;
}
.cant-paso[value="-1"] { margin-right: -1px; }

/* Al pasar por encima se levanta sobre sus vecinos, o el borde de color
   quedaría medio tapado por el del campo. */
.cant-paso:hover:not(:disabled) {
    position: relative;
    z-index: 1;
    background: var(--acento-agua);
    border-color: var(--acento);
}
.cant-paso:active:not(:disabled) { background: var(--acento-agua); }

/* Apagado, no escondido: que el hueco no baile cuando se llega a 1. */
.cant-paso:disabled { opacity: .35; cursor: default; }

/* 2.8rem = 45px. Tres dígitos caben de sobra —el tope es 999— y el trío
   entero mide 103px en una columna que da 123 de hueco útil.

   Estos números se comprueban: `probar_aportes` lee los anchos de esta
   hoja y el de la columna, los suma y avisa si el renglón se va a partir.
   No es celo de más: con 3.4rem el trío sumaba 134px contra 133 de hueco
   y se partía POR UN PÍXEL, dejando el «+» solo en su línea. Eso no lo ve
   ninguna prueba de HTTP y en la pantalla se lee como un fallo. */
.cant-num {
    order: 2;
    flex: 0 0 2.8rem;
    /* El mismo alto que los botones: si difirieran, el conjunto dejaría de
       leerse como una pieza. */
    min-height: 38px;
    padding: .2rem .2rem;
    border: 1px solid var(--linea);
    /* Cuadrado en medio: el redondeo lo ponen los extremos. */
    border-radius: 0;
    background: var(--superficie);
    color: var(--tinta);
    /* 16px o más, o iOS hace zoom al enfocar y descoloca la tabla. */
    font: 500 17px/1 var(--serif);
    text-align: center;
}

/* Las flechitas nativas sobran: al lado de dos botones de 44px son un
   objetivo de tres píxeles que nadie acierta con el pulgar. */
.cant-num::-webkit-outer-spin-button,
.cant-num::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
.cant-num { -moz-appearance: textfield; appearance: textfield; }

/* ---- NADA DE TEXTO DENTRO DE LA CELDA --------------------------------

   Aquí vivía un renglón que decía «sin guardar», «guardando…» o el motivo
   de un rechazo, y rompía la tabla: al aparecer, la celda crecía de alto,
   la fila daba un salto y las de al lado se descolocaban. En una tabla,
   un mensaje que aparece y desaparece mueve el sitio de todo lo demás.

   El resultado se dice ahora con `.aviso-flotante`, que va encima de la
   página y no dentro de ninguna celda. Lo único que queda aquí es el
   diskette encendido mientras haya algo sin guardar: es color, y no ocupa
   un píxel de más. */
.cant-sucia .cant-ok {
    background: var(--acento-agua);
    border-color: var(--acento);
    color: var(--acento-hondo);
}

/* ---- El aviso flotante: el gancho, medio segundo ---------------------

   Aparece centrado encima de todo, dice «Guardado» y se va. Medio segundo
   es justo lo que hace falta para que el ojo lo registre sin que estorbe
   a quien va a tocar el siguiente botón.

   `pointer-events: none` no es un detalle: durante ese medio segundo la
   caja cubre el centro de la pantalla, y sin esto se comería el toque
   siguiente —que en esta pantalla es casi siempre otro «+»—. */
.aviso-flotante {
    position: fixed;
    inset: 0;
    z-index: 60;
    display: flex;
    align-items: center;
    justify-content: center;
    pointer-events: none;
}

/* `display: flex` pisa el `[hidden]` del navegador, que es solo
   `display: none` sin peso ninguno: sin esta línea el aviso saldría
   plantado en mitad de la pantalla desde que carga la página y no se
   iría nunca. Toda regla que fije `display` tiene que devolver el
   `hidden`, y esta es la primera de la hoja que lo necesitaba. */
.aviso-flotante[hidden] { display: none; }

.aviso-flotante-caja {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .3rem;
    min-width: 8.5rem;
    padding: 1.1rem 1.4rem;
    border-radius: var(--radio);
    background: var(--superficie);
    border: 1px solid var(--linea);
    box-shadow: 0 8px 28px rgba(50, 58, 71, .22);
    color: var(--acento-hondo);
    animation: aviso-entra .16s ease-out;
}

.aviso-flotante-texto {
    margin: 0;
    font: 500 1rem/1.2 var(--sans);
    color: var(--tinta);
    text-align: center;
}

/* Un icono u otro según cómo haya ido; los dos están en el HTML y aquí se
   elige, que es más barato que rehacer el dibujo desde JavaScript. */
.aviso-flotante-mal { display: none; }
.aviso-flotante-fallo .aviso-flotante-bien { display: none; }
.aviso-flotante-fallo .aviso-flotante-mal  { display: block; }

.aviso-flotante-fallo .aviso-flotante-caja {
    color: var(--error);
    border-color: rgba(148, 75, 55, .4);
}

@keyframes aviso-entra {
    from { opacity: 0; transform: scale(.94); }
    to   { opacity: 1; transform: scale(1); }
}

/* Con el acta cerrada no hay control: el número y nada más. El motivo lo
   dice la columna de Acciones, una sola vez por fila. */
.cant-fija { font: 500 17px/1 var(--serif); }

/* ---- De qué junta se está hablando, y cómo volver --------------------

   Cuando se llega desde un paso del asistente, la pantalla se filtra a esa
   junta. Eso hay que DECIRLO: una lista que de pronto enseña tres filas en
   vez de cuarenta, sin explicación, se lee como que se perdieron datos.

   Y la salida tiene que estar a la vista. En el celular el botón pasa a
   ocupar el ancho entero y va debajo, porque ahí es donde llega el pulgar
   y porque al lado no cabe sin apretar la frase. */
.contexto-junta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: .6rem;
    margin: 0 0 1rem;
    padding: .7rem .9rem;
    border: 1px solid var(--linea);
    border-left: 3px solid var(--acento);
    border-radius: var(--radio);
    background: var(--superficie-2);
}

.contexto-junta-que {
    margin: 0;
    min-width: 0;
    font-size: .92rem;
    color: var(--tinta-suave);
}
.contexto-junta-que strong { color: var(--tinta); }

.volver-junta { flex: 0 0 auto; }

@media (max-width: 860px) {
    .contexto-junta { flex-direction: column; align-items: stretch; }
    .volver-junta   { width: 100%; }
}

/* ---- Pestañas encima de un listado -----------------------------------
   Dos estados de la misma lista, no dos pantallas. Se ven como pestañas
   —con la abierta sobre una línea— y no como botones, para que se lea
   que hay algo debajo y que sigue siendo el mismo sitio.

   Envuelven en vez de desplazarse de lado: son dos o tres, no una
   barra, y en el celular una fila que se arrastra se pierde. */
.tabs {
    display: flex; flex-wrap: wrap; gap: .25rem;
    margin: 0 0 .9rem;
    border-bottom: 1px solid var(--linea);
}

.tab {
    display: inline-flex; align-items: center; gap: .4rem;
    padding: .5rem .9rem;
    border: 1px solid transparent;
    border-bottom: 0;
    border-radius: var(--radio) var(--radio) 0 0;
    color: var(--tinta-suave);
    text-decoration: none;
    font-size: .92rem;
    /* Se pisa la línea del contenedor: es lo que hace que la abierta
       parezca continuar en el contenido. */
    margin-bottom: -1px;
}
.tab:hover { color: var(--acento-hondo); background: var(--acento-agua); }

.tab-activa {
    background: var(--superficie);
    border-color: var(--linea);
    border-bottom: 1px solid var(--superficie);
    color: var(--tinta);
    font-weight: 500;
}

/* La cuenta al lado del rótulo: responde «¿cuántos llevo?» sin entrar. */
.tab-cuenta {
    min-width: 1.5rem;
    padding: 0 .35rem;
    border-radius: 999px;
    background: var(--linea-suave);
    color: var(--tinta-suave);
    font-size: .78rem; text-align: center; line-height: 1.5rem;
}
.tab-activa .tab-cuenta { background: var(--acento-agua); color: var(--acento-hondo); }

.th-sort { color: inherit; text-decoration: none; }
.th-sort:hover, .th-sort.active { color: var(--acento-hondo); }

.al-left   { text-align: left; }
.al-center { text-align: center; }
.al-right  { text-align: right; font-variant-numeric: tabular-nums; }

.col-acciones { white-space: nowrap; width: 1%; }
.acc-corto { display: none; }
.inline-form { display: inline; }
.empty { text-align: center; color: var(--tinta-tenue); padding: 2.5rem .85rem; font-style: italic; }

.pill {
    display: inline-block; padding: .12rem .6rem;
    border-radius: 999px; font-size: .72rem; font-weight: 600;
    white-space: nowrap;
}
.pill-si { background: var(--salvia-agua); color: var(--salvia-hondo); }
.pill-no { background: rgba(60, 70, 85, .06); color: var(--tinta-tenue); }

/* Estados de asistencia: el color dice el estado, y una lista entera se
   lee de un vistazo sin detenerse en las palabras. */
.pill-presente { background: var(--salvia-agua);    color: var(--salvia-hondo); }
.pill-excusado { background: var(--oro-agua);       color: var(--oro-hondo); }
.pill-ausente  { background: var(--terracota-agua); color: var(--terracota-hondo); }

/* Niveles de la jerarquía: cinco niveles, los cinco colores. Ayuda a
   leer el árbol de consejos de un golpe. */
.pill-senatus    { background: var(--lavanda-agua);   color: var(--lavanda-hondo); }
.pill-regia      { background: var(--terracota-agua); color: var(--terracota-hondo); }
.pill-comitium   { background: var(--salvia-agua);    color: var(--salvia-hondo); }
.pill-curia      { background: var(--azul-agua);      color: var(--azul-hondo); }
.pill-praesidium { background: var(--oro-agua);       color: var(--oro-hondo); }

/* Un punto del color, para cuando la píldora es demasiado. */
.punto-nivel {
    display: inline-block; width: 7px; height: 7px;
    border-radius: 50%; margin-right: .45rem; vertical-align: middle;
}
.punto-senatus    { background: var(--lavanda); }
.punto-regia      { background: var(--terracota); }
.punto-comitium   { background: var(--salvia); }
.punto-curia      { background: var(--azul); }
.punto-praesidium { background: var(--oro); }

/* ---- Paginación ----------------------------------------------------- */
.pager {
    display: flex; align-items: center; justify-content: space-between;
    gap: 1rem; margin-top: 1rem; flex-wrap: wrap;
}
.pager-count { margin: 0; font-size: .8rem; color: var(--tinta-tenue); }
.pager-links { display: flex; gap: .3rem; }
.pager-size { display: flex; align-items: center; gap: .45rem; font-size: .8rem; color: var(--tinta-tenue); }
.pager-size select {
    padding: .24rem .6rem; border: 1px solid var(--linea);
    border-radius: 999px; font: 400 .8rem var(--sans);
    background: var(--superficie); color: var(--tinta);
}

/* ---- Tarjetas y formularios ----------------------------------------- */
.card {
    background: var(--superficie);
    border: 1px solid var(--linea);
    border-radius: var(--radio);
    padding: 1.5rem 1.7rem;
    box-shadow: var(--sombra);
}
.form { max-width: 640px; }
.form.ancho { max-width: 880px; }

.field { margin-bottom: 1.25rem; }
.field label {
    display: block; margin-bottom: .38rem;
    font-size: 15px; font-weight: 600; color: var(--tinta-suave);
}

/* ---- Controles ---------------------------------------------------------
   Los tres números de aquí no son estéticos, son de uso:

   · 17px de letra. Safari en iPhone AMPLÍA la página al enfocar cualquier
     campo de menos de 16px, y luego hay que volver a alejarla a dos dedos.
     Va en px y no en rem para que no lo arrastre ningún cambio de base.
   · 48px de alto. La yema de un dedo pide 44 como mínimo; antes eran 33.
   · font-size heredado no: los navegadores le ponen a select y textarea
     su propia fuente del sistema si no se dice lo contrario. */
.field input[type=text], .field input[type=email], .field input[type=password],
.field input[type=number], .field input[type=date], .field input[type=datetime-local],
.field input[type=search], .field input[type=time], .field input[type=tel],
.field select, .field textarea {
    width: 100%;
    min-height: 48px;
    padding: .6rem .85rem;
    border: 1px solid var(--linea);
    border-radius: var(--radio-chico);
    font: 400 17px/1.4 var(--sans);
    background: var(--superficie);
    color: var(--tinta);
}
.field input:focus, .field select:focus, .field textarea:focus {
    border-color: var(--acento-hondo);
    outline: 2px solid transparent;   /* visible en modo de alto contraste */
    box-shadow: 0 0 0 3px var(--acento-agua), 0 0 0 4px var(--acento-hondo);
}
.field textarea { resize: vertical; min-height: 7rem; line-height: 1.6; }
.field .req { color: var(--terracota-hondo); }
.hint { display: block; margin-top: .35rem; font-size: 14px; color: var(--tinta-tenue); font-weight: 400; }
.hint-aviso { color: var(--aviso); }

/* ---- Campo que rechazó el guardado ------------------------------------
   Ámbar y no rojo: el dato no está perdido, solo hay que corregirlo. El
   detalle de qué pasa ya se lee arriba en el aviso; esto únicamente dice
   dónde mirar. Además del color va una barra a la izquierda, para que se
   distinga sin depender de la vista del color. */
.field.con-error > label { color: var(--aviso); }
.field.con-error input, .field.con-error select, .field.con-error textarea {
    border-color: var(--aviso);
    background: var(--aviso-fondo);
}
.field.con-error input:focus, .field.con-error select:focus, .field.con-error textarea:focus {
    border-color: var(--aviso);
    box-shadow: 0 0 0 3px rgba(138, 116, 64, .18);
}
.field.con-error {
    border-left: 3px solid var(--aviso);
    padding-left: .7rem;
    margin-left: -.7rem;
}
.readonly { display: block; padding: .5rem 0; color: var(--tinta-suave); font-variant-numeric: tabular-nums; }

.switch { display: flex !important; align-items: center; gap: .55rem; font-weight: 400 !important; }
.switch input { width: auto !important; accent-color: var(--oro); }

.form-actions {
    display: flex; gap: .6rem; margin-top: 1.6rem;
    padding-top: 1.2rem; border-top: 1px solid var(--linea-suave);
}

.form-seccion {
    margin: 2rem 0 1rem;
    padding-bottom: .4rem;
    border-bottom: 1px solid var(--linea);
    color: var(--acento-hondo);
}
.form-seccion:first-child { margin-top: 0; }

.checklist { display: grid; grid-template-columns: repeat(auto-fill, minmax(210px, 1fr)); gap: .35rem; }
.checklist label { display: flex; align-items: center; gap: .5rem; font-weight: 400; font-size: .87rem; margin: 0; }
.checklist input { width: auto; accent-color: var(--oro); }

/* El motivo por el que una fila no se puede tocar, en la columna de
   acciones. Se acota el ancho: sin tope, un mensaje largo estira la
   columna y empuja los datos fuera de la pantalla. */
.fila-cerrada { display: block; max-width: 16rem; line-height: 1.3; }

/* ---- Vista previa dentro del asistente de la junta -------------------
   Enseña un trozo del acta tal como se va a imprimir. Se dibuja como
   papel —fondo claro, borde, letra del documento— para que se lea como
   lo que es: una muestra, no un campo que se pueda editar. */
.vista-previa {
    margin: 0 0 1.25rem;
    padding: .9rem 1rem;
    border: 1px solid var(--linea);
    border-radius: var(--radio);
    background: var(--papel);
}
.vista-previa h3 {
    margin: 0 0 .5rem;
    font: 500 .95rem/1.2 var(--serif);
    color: var(--tinta-suave);
}

/* El renglón, con el mismo aire del impreso: subrayado y sin apretar. */
.vista-previa-texto {
    margin: 0;
    line-height: 1.7;
    border-bottom: 1px solid var(--linea);
    padding-bottom: .2rem;
    color: var(--tinta);
}

/* ---- Formulario con una lista al lado --------------------------------

   El HTML va SIEMPRE en el mismo orden: primero el formulario, después
   el bloque de apoyo. Así, cuando no hay dos columnas —el celular, que
   es donde se usa esto— los campos quedan arriba y la lista debajo, que
   es el orden en que se trabaja: se escribe, y luego se comprueba.

   Solo a partir de 900 px se ponen en paralelo. Antes esta lista iba
   encima del formulario y, en cuanto pasó de diez apuntes, empujaba los
   campos fuera de la pantalla en la única pantalla donde se meten cosas
   de tres en tres. */
.form-lado { display: flex; flex-direction: column; gap: 1.25rem; }

.form-lado-principal { min-width: 0; }
.form-lado-apoyo     { min-width: 0; }

@media (min-width: 900px) {
    .form-lado { flex-direction: row; align-items: flex-start; }

    /* El formulario manda: 3 de 5. La lista es de consulta y con menos
       ancho se lee igual —cantidad, nombre y un botón—. */
    .form-lado-principal { flex: 3 1 0; }
    .form-lado-apoyo     { flex: 2 1 0; position: sticky; top: 1rem; }
}

/* ---- Lo ya apuntado, al lado del formulario --------------------------
   Se vuelve al formulario tras cada apunte, así que esta lista es lo
   único que dice si lo anterior entró. La cantidad va delante y grande:
   es lo que se comprueba de un vistazo al repetir. */
.apuntado { margin-bottom: 1.25rem; }

.apuntado-vacio,
.apuntado-aviso {
    margin: 0 0 .5rem;
    font-size: .87rem;
    color: var(--tinta-suave);
}

/* El aviso sí destaca: explica una ausencia, y una ausencia sin
   explicación se lee como un fallo. */
.apuntado-aviso {
    background: var(--acento-agua);
    border-left: 3px solid var(--acento);
    padding: .5rem .6rem;
}

.apuntado-cabeza {
    display: flex; align-items: baseline; justify-content: space-between;
    flex-wrap: wrap; gap: .5rem; margin-bottom: .5rem;
}
.apuntado-cabeza h2 { margin: 0; font: 500 1.05rem/1.2 var(--serif); }
.apuntado-cabeza p  { margin: 0; font-size: .87rem; color: var(--tinta-suave); }

.apuntado-fila {
    display: flex; align-items: center; gap: .75rem;
    padding: .5rem 0;
    border-top: 1px solid var(--linea-suave);
}

/* La que se está corrigiendo, marcada: si no, se edita a ciegas. */
.apuntado-actual { background: var(--acento-agua); }

.apuntado-cuanto {
    flex: 0 0 2.2rem; text-align: right;
    font: 500 1.2rem/1 var(--serif); color: var(--acento-hondo);
}
.apuntado-que { flex: 1 1 auto; display: flex; flex-direction: column; min-width: 0; }
.apuntado-que small { font-size: .78rem; }

.apuntado-pie { margin: .75rem 0 0; font-size: .87rem; }

/* ---- Panel acumulado de aportes --------------------------------------
   Una línea por actividad: a la izquierda qué es, a la derecha cuánto.
   El número va grande y a la derecha porque es lo que se busca de un
   vistazo; el nombre puede envolver, el número no. */
.resumen-cabeza {
    display: flex; align-items: baseline; justify-content: space-between;
    flex-wrap: wrap; gap: .5rem;
}

.resumen-gran { margin: 0; display: flex; align-items: baseline; gap: .5rem; }
.resumen-gran strong { font: 500 2.2rem/1 var(--serif); color: var(--acento-hondo); }
.resumen-gran span { color: var(--tinta-suave); }
.resumen-pendiente { margin: 0; font-size: .87rem; color: var(--aviso); }

.resumen { display: grid; gap: 0; }

.resumen-fila {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: 1rem; padding: .6rem 0;
    border-top: 1px solid var(--linea-suave);
}
.resumen-fila:first-child { border-top: 0; }

.resumen-que { display: flex; flex-direction: column; }
.resumen-que small { font-size: .78rem; }

.resumen-cuanto {
    font: 500 1.35rem/1 var(--serif);
    color: var(--tinta);
    /* Que no se pegue al nombre cuando este es largo. */
    flex: 0 0 auto;
}

/* El total de la categoría, junto a su rótulo. */
.form-seccion small { font-weight: 400; margin-left: .5rem; }

/* ---- Membresías dentro del formulario de Miembros --------------------
   Cada membresía es un bloque con su borde: sin él, ocho controles
   seguidos se leen como una lista suelta y no se ve dónde acaba una y
   empieza la otra. En pantalla ancha van de dos en dos; en el teléfono,
   apilados. */
.membresias { display: grid; gap: .75rem; margin-bottom: 1.25rem; }

.membresia {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
    gap: 0 1rem;
    margin: 0; padding: .9rem 1rem .2rem;
    border: 1px solid var(--linea);
    border-radius: var(--radio);
    background: var(--superficie-2);
}

/* La fila de sobra se distingue: está para rellenarla, no es un dato. */
.membresia-nueva { border-style: dashed; background: transparent; }

.membresia .field { margin-bottom: .9rem; }

/* «Quitar» ocupa su propia línea: es destructivo y no debe quedar
   pegado a un desplegable donde se pulse sin querer. */
.membresia .field-quitar { grid-column: 1 / -1; }

.membresias-mas { margin: -.5rem 0 1.25rem; }

/* ---- Visitas a la junta ---------------------------------------------
   Cada visita ocupa su propia línea de la rejilla: la casilla y el
   nombre a la izquierda y, si es socia de otro consejo, el desplegable
   de en representación de quién viene. En el teléfono se apilan. */
.visita-fila { display: flex; flex-wrap: wrap; align-items: center; gap: .3rem .75rem; }
.visita-fila > label:first-child { flex: 1 1 12rem; }

/* El cargo va bajo el nombre, no al lado: en pantalla estrecha, al lado
   partiría el nombre en dos renglones. */
.visita-fila label > span { display: flex; flex-direction: column; }
.visita-fila label small { font-size: .78rem; }

.visita-representa { display: flex; align-items: center; gap: .4rem; flex-wrap: wrap; }
.visita-representa select { width: auto; max-width: 100%; font-size: .87rem; }

/* ---- Buscar una visita que ya es socia de otro consejo --------------- */
.visita-buscar .toolbar { margin: .5rem 0; }

.lista-resultados { list-style: none; margin: .5rem 0 0; padding: 0; }
.lista-resultados li {
    display: flex; align-items: center; justify-content: space-between;
    gap: .75rem; padding: .55rem 0;
    border-top: 1px solid var(--linea-suave);
}
.lista-resultados li > span { display: flex; flex-direction: column; }
.lista-resultados small { font-size: .78rem; }

/* ---- Campo de contraseña con botón de revelar ------------------------ */
.pswd-wrap { position: relative; display: block; }
.pswd-wrap input[type=password],
.pswd-wrap input[type=text] { padding-right: 2.7rem !important; }

.pswd-eye {
    position: absolute; top: 50%; right: .5rem;
    transform: translateY(-50%);
    display: grid; place-items: center;
    width: 1.95rem; height: 1.95rem;
    padding: 0; border: 0; border-radius: 50%;
    background: transparent; color: var(--tinta-tenue); cursor: pointer;
}
.pswd-eye:hover { background: var(--superficie-2); color: var(--tinta); }
.pswd-eye.revelado { color: var(--oro-hondo); }

/* Se muestra el icono contrario al estado actual. */
.pswd-eye .icon-eye-off { display: none; }
.pswd-eye.revelado .icon-eye { display: none; }
.pswd-eye.revelado .icon-eye-off { display: block; }

/* ---- Páginas sueltas: acceso y error ---------------------------------- */
.plain-page {
    display: grid; place-items: center; min-height: 100vh;
    padding: 2rem 1rem;
    background:
        radial-gradient(700px 520px at 12% 8%, rgba(232, 213, 208, .55), transparent 60%),
        radial-gradient(760px 560px at 88% 4%, rgba(143, 169, 196, .30), transparent 62%),
        radial-gradient(900px 620px at 70% 92%, rgba(201, 164, 76, .20), transparent 60%),
        var(--papel);
}
.plain-page .card { width: 100%; max-width: 410px; border-radius: 18px; padding: 2.2rem 2rem; }
.plain-page.wide .card { max-width: 580px; }

.login-head { text-align: center; margin-bottom: 1.6rem; }

/* En el acceso la marca es la pieza principal de la tarjeta: va más
   grande y con un halo cálido detrás, porque la plata sobre crema se
   apaga si no se le da algo de temperatura. */
.login-head .brand-mark {
    display: inline-block;
    height: 88px;
    width: auto;
    margin-bottom: .7rem;
    padding: .35rem 1.4rem;
    background: radial-gradient(ellipse at center, rgba(201, 164, 76, .18), transparent 68%);
}
.login-head h1 { font-size: 1.6rem; }
.login-head p {
    margin: .25rem 0 0; color: var(--tinta-tenue);
    font-size: .72rem; letter-spacing: .14em; text-transform: uppercase;
}

.notice h1 { margin-bottom: .7rem; }
.notice p { color: var(--tinta-suave); }
.error-code {
    font-family: ui-monospace, Consolas, monospace;
    font-size: 1.05rem; font-weight: 700;
    background: var(--superficie-2); border: 1px solid var(--linea);
    border-radius: var(--radio-chico); padding: .55rem .9rem; display: inline-block;
}
.dev-detail { margin-top: 1.2rem; }
.dev-detail pre {
    background: var(--superficie-2); border: 1px solid var(--linea);
    border-radius: var(--radio-chico); padding: .9rem; overflow-x: auto;
    font-size: .78rem; white-space: pre-wrap;
}

.form-links { margin-top: 1.2rem; text-align: center; font-size: .84rem; }
.form-links a { display: inline-block; margin: 0 .45rem; }

/* ---- Menú de aplicaciones ---------------------------------------------
   Cada tarjeta abre con una franja del color de su módulo, como los
   tiles del canvas. Es la zona más visible de la aplicación y no
   compite con ningún dato, así que aquí el color puede respirar. */
.app-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(215px, 1fr)); gap: .85rem; }

.app-card {
    display: block;
    background: var(--superficie);
    border: 1px solid var(--linea);
    border-radius: var(--radio);
    overflow: hidden;
    text-decoration: none; color: var(--tinta);
    transition: border-color .14s ease, transform .14s ease, box-shadow .14s ease;
}
/* La banda de color lleva el icono de la aplicación. Antes era un
   ::before decorativo; ahora es un elemento real porque tiene contenido. */
.app-card-banda {
    display: flex;
    align-items: center;
    height: 46px;
    padding: 0 1.2rem;
    background: linear-gradient(150deg, var(--g1, var(--lavanda-g1)), var(--g2, var(--lavanda-g2)));
    color: rgba(255, 255, 255, .92);
}
.app-card > strong, .app-card > small { padding-left: 1.2rem; padding-right: 1.2rem; }
.app-card strong { display: block; padding-top: .9rem; font: 500 1.04rem var(--serif); }
.app-card small { display: block; padding-bottom: 1rem; color: var(--tinta-tenue); font-size: .74rem; }

.app-card:hover {
    border-color: var(--acento);
    transform: translateY(-2px);
    box-shadow: 0 14px 30px -20px rgba(60, 70, 85, .5);
    color: var(--acento-hondo);
}

/* La ficha de consejo del inicio no es un enlace: no salta al pasar. */
.app-card.estatica { cursor: default; }
.app-card.estatica:hover { transform: none; box-shadow: none; border-color: var(--linea); color: var(--tinta); }

/* ---- Documentos del praesidium ---------------------------------------- */
.doc-list { display: flex; flex-direction: column; gap: .55rem; }
.doc-row {
    display: flex; align-items: center; justify-content: space-between;
    gap: 1.2rem; flex-wrap: wrap;
    padding: .9rem 1.15rem;
    background: var(--superficie);
    border: 1px solid var(--linea);
    border-radius: var(--radio);
}
.doc-row:hover { border-color: var(--acento); }
.doc-info strong { display: block; font: 500 1rem var(--serif); }
.doc-info small { color: var(--tinta-tenue); font-size: .79rem; }
.doc-params { display: flex; align-items: center; gap: .45rem; flex-wrap: wrap; }
.doc-params input[type=date], .doc-params select {
    padding: .3rem .65rem; border: 1px solid var(--linea);
    border-radius: 999px; font: 400 .8rem var(--sans);
    background: var(--superficie); color: var(--tinta);
}

/* ---- Pasar lista ------------------------------------------------------- */
.roll td small { display: block; font-size: .75rem; }
.roll .col-estado { width: 112px; }

.radio-cell { display: inline-flex; align-items: center; justify-content: center; cursor: pointer; padding: .3rem; margin: 0; }
.radio-cell input { width: 1.05rem; height: 1.05rem; cursor: pointer; margin: 0; accent-color: var(--oro); }
.radio-cell input:disabled { cursor: default; opacity: .4; }

/* Botón que parece enlace, para «marcar todos» en la cabecera. */
.link-mini {
    display: block; margin: .2rem auto 0; padding: 0;
    border: 0; background: none;
    color: var(--azul-hondo);
    font: 400 .66rem var(--sans);
    text-transform: none; letter-spacing: 0;
    text-decoration: underline; cursor: pointer;
}
.link-mini:hover { color: var(--oro-hondo); }

/* ---- Utilidades -------------------------------------------------------- */
.block { margin-bottom: 1.6rem; }
.app-grid + h2 { margin-top: 1.7rem; }
h2 + .app-grid { margin-bottom: 1.6rem; }
.tenue { color: var(--tinta-tenue); }

.sr-only {
    position: absolute; width: 1px; height: 1px;
    padding: 0; margin: -1px; overflow: hidden;
    clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* ---- Pantallas estrechas ----------------------------------------------- */
@media (max-width: 860px) {
    .layout { grid-template-columns: 1fr; }
    .sidebar { display: none; border-right: 0; border-bottom: 1px solid var(--linea); }
    .sidebar.open { display: block; }
    .menu-toggle { display: flex; }
    .content { padding: 1.3rem 1.1rem 2.8rem; }
    .user-name { display: none; }
    .doc-row { flex-direction: column; align-items: flex-start; }

    /* ---- Lo que cambia para el pulgar ------------------------------
       Este es el tamaño en el que se usa el sistema de verdad: nadie
       abre esto en una computadora. */

    /* El botón del menú era un icono de 3 rayas con 6px de padding.
       Ahora es un objetivo de 48px como manda cualquier guía táctil. */
    .menu-toggle {
        width: 48px; height: 48px;
        align-items: center; justify-content: center;
    }

    /* Guardar y Cancelar apilados y a todo el ancho. En una columna de
       360px, dos botones en fila quedan estrechos y se falla el toque;
       además así «Guardar» cae siempre bajo el pulgar derecho. */
    .form-actions { flex-direction: column-reverse; gap: .7rem; }
    .form-actions .btn { width: 100%; }

    /* La barra de herramientas de los listados: la búsqueda ocupa la
       línea entera en vez de competir con los botones. */
    .toolbar { gap: .7rem; }
    .search-input { flex: 1 1 100%; max-width: none; }


    /* ---- Contraseña y Salir, en icono -----------------------------
       Aquí no cabe todo: el logotipo, el nombre, dos botones de texto y
       el botón del menú compiten por 360px. Se quedan los dibujos —una
       llave y una puerta— que además se reconocen antes que dos palabras
       en letra pequeña.

       El texto no se elimina, se esconde: sigue leyéndose con lector de
       pantalla, y vuelve a aparecer en cuanto hay sitio. */
    .btn-icono .rotulo {
        position: absolute; width: 1px; height: 1px;
        padding: 0; margin: -1px; overflow: hidden;
        clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
    }
    .btn-icono {
        width: 44px;
        min-width: 44px;
        padding-left: 0;
        padding-right: 0;
        justify-content: center;
    }
    .topbar-user { gap: .25rem; }


    /* ---- Acciones de la fila, en icono ----------------------------
       La tabla se desplaza a lo ancho en el celular. Las acciones van
       ahora al principio de la fila, y además se quedan CLAVADAS a la
       izquierda: se puede arrastrar la tabla para leer las columnas de
       la derecha sin perder de vista a qué fila pertenecen.

       El fondo tiene que ser opaco, o el resto de la tabla se ve por
       debajo al desplazarla. */
    .grid .col-acciones {
        position: sticky;
        left: 0;
        z-index: 1;
        background: var(--superficie);
        border-right: 1px solid var(--linea-suave);
    }
    .grid thead .col-acciones { background: var(--superficie-2); }

    .col-acciones .btn-icono {
        width: 44px;
        min-width: 44px;
        padding-left: 0;
        padding-right: 0;
        justify-content: center;
    }

    /* ---- Editar y Borrar, uno debajo del otro ------------------
       En una fila ocupaban 94px de ancho en una columna CLAVADA a la
       izquierda: esos 94px se los quitaba a los datos en una pantalla
       de 360px, y la tabla había que arrastrarla de lado para leer
       cualquier cosa. Apilados son 44px, la mitad, y siguen siendo dos
       objetivos de 44px de alto cada uno.

       `inline-form` es inline por defecto —lo necesita en el resto del
       sistema—, así que aquí se pasa a bloque para que baje. */
    /* Se hace SIN tocar el modelo de tabla: un `display: flex` en un
       <td> deja de ser celda, y esta columna va clavada con
       `position: sticky` —que entonces se comporta de otro modo—. Basta
       con que el formulario de Borrar pase a bloque: al ser bloque
       fuerza el salto y baja él solo, debajo del enlace de Editar, que
       es inline-flex por .btn.

       Es la misma técnica que usan las fichas más abajo, no una nueva. */
    .col-acciones .inline-form { display: block; margin-left: 0; }
    .grid tbody .col-acciones .btn-icono { margin-bottom: .3rem; }

    /* La cabecera, en corto: «Acciones» fijaba un ancho mayor que el de
       los botones que hay debajo. El largo se esconde sin borrarse, para
       que el lector de pantalla lo siga leyendo. */
    .acc-corto { display: inline; }
    .acc-largo {
        position: absolute; width: 1px; height: 1px;
        padding: 0; margin: -1px; overflow: hidden;
        clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
    }

    /* «−», el número y «+» miden lo mismo en los dos tamaños: ya son
       chicos, y achicarlos otra vez aquí los dejaría sin sitio donde caer
       el dedo. El que crece con el pulgar es el diskette, que tiene su
       renglón entero debajo.

       Antes esta regla los ponía en 34px, MÁS grandes que los 30 de
       ahora: se retira para que no deshaga lo de arriba. */


    /* ---- El menú y el modal en el celular -------------------------
       Aquí el menú es un panel que se despliega desde arriba, así que
       cada grupo cerrado ahorra una pantalla entera de desplazamiento.
       El logo se achica: en 360 px de ancho, 84 px de imagen se comen
       un cuarto de la altura útil antes de llegar al primer enlace. */
    /* El modal, a todo el ancho y pegado abajo: es donde llega el
       pulgar. Los campos conservan sus 17 px y sus 48 px de alto
       porque salen de .field, que no se toca aquí. */
    .modal {
        width: 100%;
        max-width: none;
        margin: auto auto 0;
        border-radius: var(--radio) var(--radio) 0 0;
        border-bottom: 0;
    }
    .modal form { padding: 1.2rem 1.1rem calc(1.2rem + env(safe-area-inset-bottom)); }

    /* La ventana de un punto, a pantalla completa: dentro va una
       pantalla entera y cualquier recorte la deja inservible.
       `100dvh` y no `100vh` porque en el celular la barra del
       navegador aparece y desaparece, y con `vh` el botón de cerrar
       queda debajo de ella justo al abrir. */
    .modal-panel {
        width: 100%;
        height: 100dvh;
        max-height: 100dvh;
        margin: 0;
        border-radius: 0;
        border: 0;
    }
    .modal-panel-cuerpo {
        padding: .9rem .8rem calc(.9rem + env(safe-area-inset-bottom));
    }

    /* Desde y Hasta, uno debajo del otro: en una columna de 360 px, dos
       campos de fecha en fila quedan estrechos y se falla el toque. */
    .modal-fechas { flex-direction: column; gap: 0; }

    /* Generar arriba del todo y a lo ancho, que es la acción que se
       busca; Cancelar debajo. */
    .modal-acciones { flex-direction: column; }
    .modal-acciones .btn { width: 100%; }

    /* Girar el teléfono no debe cambiar el tamaño de la letra. */
    html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
}

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

/* ---- Fichas de consejo por nivel --------------------------------------
   El mismo color que la píldora de nivel, para que la ficha del inicio y
   el listado de Consejos hablen el mismo idioma. */
.app-card[data-nivel="senatus"]    { --g1: var(--lavanda-g1);   --g2: var(--lavanda-g2); }
.app-card[data-nivel="regia"]      { --g1: var(--terracota-g1); --g2: var(--terracota-g2); }
.app-card[data-nivel="comitium"]   { --g1: var(--salvia-g1);    --g2: var(--salvia-g2); }
.app-card[data-nivel="curia"]      { --g1: var(--azul-g1);      --g2: var(--azul-g2); }
.app-card[data-nivel="praesidium"] { --g1: var(--oro-g1);       --g2: var(--oro-g2); }

/* El h2 de cada área toma su color, para atar el título con sus tarjetas. */
[data-modulo] > h2 { color: var(--acento-hondo); }

/* ---- Pasar lista: cada columna con el color de su estado -------------- */
.roll th.col-presente, .roll th.col-excusado, .roll th.col-ausente { color: var(--tinta-suave); }
.roll th.col-presente { background: var(--salvia-agua); }
.roll th.col-excusado { background: var(--oro-agua); }
.roll th.col-ausente  { background: var(--terracota-agua); }

.roll td.cel-presente input { accent-color: var(--salvia-hondo); }
.roll td.cel-excusado input { accent-color: var(--oro); }
.roll td.cel-ausente  input { accent-color: var(--terracota-g2); }

/* =====================================================================
   PANTALLAS DE ACCESO — fondo oscuro con el Vexillum

   El azul tinta de la paleta llevado a su extremo profundo: sigue siendo
   la misma familia que el resto del sistema, no un negro ajeno. El
   Vexillum en plata sobre ese azul es el contraste que pide la pieza.
   ===================================================================== */

:root {
    --tinta-honda: #2A3240;
    --tinta-noche: #1E2530;
}

.plain-page.acceso {
    position: relative;
    overflow: hidden;
    background:
        radial-gradient(720px 540px at 78% 18%, rgba(201, 164, 76, .20), transparent 62%),
        radial-gradient(620px 480px at 12% 88%, rgba(232, 213, 208, .12), transparent 60%),
        linear-gradient(160deg, var(--tinta) 0%, var(--tinta-honda) 45%, var(--tinta-noche) 100%);
}

/* Halo cálido DETRÁS de la paloma: la plata sobre azul pide algo de
   temperatura o se apaga.
   Va en ::before y el Vexillum en ::after porque el orden de pintado es
   ese. Nada de z-index negativo: mandaría el halo por detrás del fondo
   del propio elemento y no se vería. */
.plain-page.acceso::before {
    content: '';
    position: absolute;
    inset: 0;
    background: radial-gradient(38vh 38vh at 72% 50%, rgba(201, 164, 76, .20), transparent 70%);
    pointer-events: none;
}

/* El Vexillum ocupa TODA la página y se escala con `contain`, que ajusta
   la imagen entera dentro del área respetando su proporción: nunca se
   recorta ni se deforma. Antes tenía un ancho tope y una altura derivada,
   y en pantallas poco altas el elemento desbordaba y `overflow: hidden`
   se lo comía por arriba y por abajo.
   Va en un pseudoelemento para graduar su opacidad sin afectar a la
   tarjeta, que debe quedar plenamente legible encima. */
.plain-page.acceso::after {
    content: '';
    position: absolute;
    inset: 0;
    background: url('../img/vexillum.webp') no-repeat right center / contain;
    opacity: .2;
    pointer-events: none;
    filter: blur(15px);
    transition: filter .35s ease;
}

/* Al posarse sobre la tarjeta el Vexillum se enfoca: el fondo empieza
   difuminado y se revela cuando la persona va a entrar, en vez de al
   revés.
   Se usa `filter` sobre el pseudoelemento y no `backdrop-filter` sobre la
   tarjeta porque esta es opaca: un desenfoque de lo que hay detrás no se
   vería. `:focus-within` lo dispara también al tabular, para que quien no
   usa ratón obtenga lo mismo. */
.plain-page.acceso:has(.card:hover)::after,
.plain-page.acceso:has(.card:focus-within)::after {
    filter: none;
}

/* La tarjeta va centrada —el centrado lo pone `place-items: center` del
   contenedor— y sube por encima de ambos pseudoelementos. */
.plain-page.acceso .card {
    position: relative;
    z-index: 1;
    box-shadow: 0 30px 70px -30px rgba(0, 0, 0, .65), 0 2px 8px rgba(0, 0, 0, .2);
}

/* En pantallas estrechas no hay sitio para la composición partida: el
   Vexillum pasa a ser marca de agua centrada y la tarjeta se centra. */
@media (max-width: 900px) {
    .plain-page.acceso::before {
        background: radial-gradient(40vh 40vh at 50% 42%, rgba(201, 164, 76, .16), transparent 70%);
    }
    /* En estrecho el Vexillum se centra, para que quede detrás de la
       tarjeta y no asomando por un lado. La opacidad ya es la misma. */
    .plain-page.acceso::after { background-position: center 38%; }
}

/* =====================================================================
   ICONOGRAFÍA

   Trazo de 1.5 y extremos redondeados, como el canvas. Van en línea, así
   que heredan el color del contexto con `currentColor`: el mismo icono
   sirve en el menú (color tenue), en la banda de una tarjeta (blanco) y
   en un título de área (acento del módulo).
   ===================================================================== */

.icono { display: block; flex: none; }

/* ---- En el menú lateral ---- */
.nav-link {
    display: flex;
    align-items: center;
    gap: .6rem;
}
.nav-link .icono { color: var(--tinta-tenue); transition: color .12s ease; }
.nav-link:hover .icono { color: var(--tinta-suave); }
.nav-link.current .icono { color: var(--acento-hondo); }

/* El icono del módulo sustituye al punto que había en el rótulo. */
.nav-title {
    display: flex;
    align-items: center;
    gap: .45rem;
}
.nav-title::before { display: none; }
.nav-title .icono { color: var(--acento); }

/* ---- En los títulos de área del inicio ---- */
[data-modulo] > h2 { display: flex; align-items: center; gap: .5rem; }
[data-modulo] > h2 .icono { color: var(--acento); }

/* =====================================================================
   IMÁGENES SUBIDAS
   ===================================================================== */

/* Miniatura en los listados. */
.miniatura {
    display: block;
    width: 62px;
    height: 42px;
    object-fit: cover;
    border-radius: var(--radio-chico);
    border: 1px solid var(--linea);
    margin: 0 auto;
}

/* Vista previa dentro del formulario, con la casilla de quitar. */
.imagen-actual {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin-bottom: .7rem;
    padding: .7rem;
    background: var(--superficie-2);
    border: 1px solid var(--linea);
    border-radius: var(--radio-chico);
}
.imagen-actual img {
    width: 120px;
    height: 82px;
    object-fit: cover;
    border-radius: var(--radio-chico);
    border: 1px solid var(--linea);
    flex: none;
}
.imagen-actual .switch { margin: 0; font-size: .85rem; }

.field input[type=file] {
    width: 100%;
    padding: .5rem .7rem;
    border: 1px dashed var(--linea);
    border-radius: var(--radio-chico);
    background: var(--superficie);
    font: 400 .85rem var(--sans);
    color: var(--tinta-suave);
    cursor: pointer;
}
.field input[type=file]:hover { border-color: var(--acento); }

/* ---- Fondo del inicio: la imagen del praesidium ----------------------
   Detrás de las tarjetas, rebajada: es una fotografía, y a plena
   intensidad haría ilegible todo lo que lleva encima. */
.content { position: relative; }
.content > *:not(.fondo-consejo) { position: relative; z-index: 1; }

.fondo-consejo {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;

    /* QUIETA AL DESPLAZAR.

       La fotografía se ancla a la ventana, no al documento: el contenido
       pasa por encima de ella en vez de arrastrarla. Es la misma técnica
       que ya usa `body` para sus lavados radiales, así que la pantalla
       entera se comporta igual.

       Con `fixed`, `cover` encuadra contra la VENTANA y no contra este
       elemento, así que lo que se ve es el trozo de esa imagen que cae
       dentro del área de contenido. Es lo que se quiere: la foto se queda
       donde está aunque la página suba.

       Ojo con Safari de iPhone: ahí `background-attachment: fixed` se
       comporta como `scroll` y no hay forma de arreglarlo con esta
       propiedad. Si hiciera falta también en iOS, el elemento tendría que
       pasar a `position: fixed`, y entonces hay que darle fondo opaco a
       `.sidebar` —hoy es transparente— o la foto se vería por debajo del
       menú. Se deja así porque es lo que ya hace `body`. */
    background-attachment: fixed;
    opacity: .7;
    pointer-events: none;
    z-index: 0;

    /* Se difumina hacia abajo para que no corte en seco donde termina
       el contenido. */
    -webkit-mask-image: linear-gradient(180deg, #000 55%, transparent 100%);
            mask-image: linear-gradient(180deg, #000 55%, transparent 100%);
}


/* =====================================================================
   ASISTENTE POR PASOS

   La junta semanal tiene cuarenta campos y se llena desde un celular,
   durante la reunión. Aquí se sirve de uno en uno, y los pasos son los
   puntos del acta con su numeración: lo que está impreso en la cartilla
   que quien captura tiene delante.
   ===================================================================== */

.asistente { max-width: 640px; }

/* ---- El riel de puntos -------------------------------------------
   En celular es una tira que se desliza a lo ancho, con el punto actual
   siempre a la vista. En pantalla ancha se queda quieto arriba. */
.riel { margin: 0 0 1.2rem; }
.riel ol {
    display: flex;
    gap: .4rem;
    margin: 0;
    padding: 0 0 .5rem;
    list-style: none;
    overflow-x: auto;
    scrollbar-width: thin;
    -webkit-overflow-scrolling: touch;
}
.riel li { flex: 0 0 auto; }

.riel a, .riel span {
    display: flex;
    align-items: center;
    gap: .4rem;
    min-height: 44px;
    padding: .35rem .8rem;
    border: 1px solid var(--linea);
    border-radius: 999px;
    background: var(--superficie);
    color: var(--tinta-tenue);
    font-size: 14px;
    text-decoration: none;
    white-space: nowrap;
}
.riel a:hover { border-color: var(--acento-hondo); color: var(--tinta); }

.riel-num {
    display: inline-flex;
    align-items: center; justify-content: center;
    min-width: 26px; height: 26px;
    padding: 0 .35rem;
    border-radius: 999px;
    background: var(--linea-suave);
    color: var(--tinta-suave);
    font-size: 13px; font-weight: 700;
}

/* El punto en el que se está: el único con color de verdad. */
.riel .aqui a, .riel .aqui span {
    border-color: var(--acento-hondo);
    background: var(--acento-agua);
    color: var(--tinta);
    font-weight: 600;
}
.riel .aqui .riel-num { background: var(--acento-hondo); color: #fff; }

/* Los ya pasados: se ven hechos sin gritar. */
.riel .hecho a { color: var(--tinta-suave); }
.riel .hecho .riel-num { background: var(--salvia); color: #fff; }

/* En pantalla estrecha el rótulo largo estorba: queda el número, salvo
   en el punto actual, que es el que hay que poder leer. */
@media (max-width: 560px) {
    .riel li:not(.aqui) .riel-txt { display: none; }
    .riel a, .riel span { padding: .35rem .55rem; }
}

/* ---- La tarjeta del paso ----------------------------------------- */
.paso-head { margin-bottom: 1.4rem; }
.paso-rotulo {
    margin: 0 0 .2rem;
    color: var(--acento-hondo);
    font-size: 13px; font-weight: 600;
    letter-spacing: .13em; text-transform: uppercase;
}
.paso-head h2 { margin: 0; font-size: 1.45rem; }
.paso-ayuda { margin: .5rem 0 0; color: var(--tinta-suave); font-size: 15px; }

.paso-remite { margin: 1.2rem 0; }

.paso-actions { margin-top: 1.8rem; }
.paso-cuenta {
    margin: 1rem 0 0;
    color: var(--tinta-tenue);
    font-size: 14px;
    text-align: center;
}

/* El campo de «Otra persona…»: aparece pegado bajo su select. */
.campo-otro { margin-top: .5rem; }

/* ---- El deslizamiento entre pasos ---------------------------------
   Un solo gesto y corto. Nada de tarjetas flotando: en un Android de
   hace seis años eso se ve a tirones y delata que lo hizo una máquina.
   El bloque de prefers-reduced-motion que ya existe lo anula entero. */
.paso-card { animation: paso-entra .18s ease-out both; }

@keyframes paso-entra {
    from { opacity: 0; transform: translateX(14px); }
    to   { opacity: 1; transform: none; }
}
.asistente[data-atras] .paso-card { animation-name: paso-entra-atras; }

@keyframes paso-entra-atras {
    from { opacity: 0; transform: translateX(-14px); }
    to   { opacity: 1; transform: none; }
}

/* Sitio para que el campo enfocado no quede bajo el teclado: el JS lo
   ajusta, pero con esto ya hay margen aunque el JS no llegue a correr. */
.asistente .field { scroll-margin-block: 5rem 12rem; }

/* ======================================================================
   GASTOS Y COMPROBANTES  ·  apps/treasury/gastos.php
   ======================================================================
   Va dentro del formulario del apunte, bajo el mismo botón Guardar. Se
   piensa primero para el celular, que es desde donde se usa: la tarjeta
   de cada gasto se apila, la miniatura del recibo es grande —hay que
   reconocerlo de un vistazo, no adivinarlo— y las casillas de borrar
   piden 44 px de dedo.

   Los controles de cada línea repiten los 17 px y los 48 px de alto de
   .field: no cuelgan de él porque van dentro de la lista, pero para el
   dedo y para Safari son el mismo control. */

.gastos-aviso {
    margin: 0 0 1rem;
    padding: .8rem 1rem;
    border-left: 3px solid var(--aviso);
    border-radius: var(--radio-chico);
    background: var(--aviso-fondo);
    color: var(--tinta);
    font-size: 15px;
}
.gastos-vacio { margin: 0 0 1rem; color: var(--tinta-tenue); font-size: 15px; }

.gastos-lista { margin: 0 0 1rem; padding: 0; list-style: none; }

.gasto {
    padding: .9rem 1rem;
    border: 1px solid var(--linea-suave);
    border-radius: var(--radio-chico);
    background: var(--superficie-2);
}
.gasto + .gasto { margin-top: .7rem; }

.gasto-datos { display: flex; flex-wrap: wrap; gap: .6rem; align-items: center; }

.gasto-datos .gasto-desc { flex: 1 1 14rem; }
.gasto-datos .gasto-monto { flex: 0 0 8rem; text-align: right; font-variant-numeric: tabular-nums; }

input.gasto-desc, input.gasto-monto {
    min-height: 48px;
    padding: .5rem .75rem;
    border: 1px solid var(--linea);
    border-radius: var(--radio-chico);
    font: 400 17px/1.4 var(--sans);
    background: var(--superficie);
    color: var(--tinta);
}
input.gasto-desc:focus, input.gasto-monto:focus {
    border-color: var(--acento-hondo);
    outline: 2px solid transparent;
    box-shadow: 0 0 0 3px var(--acento-agua), 0 0 0 4px var(--acento-hondo);
}
span.gasto-desc { flex: 1 1 14rem; color: var(--tinta); font-size: 16px; }
span.gasto-monto {
    flex: 0 0 8rem; text-align: right;
    color: var(--tinta); font-size: 16px; font-weight: 600;
    font-variant-numeric: tabular-nums;
}

.gasto-recibos { display: flex; flex-wrap: wrap; gap: .8rem; margin-top: .8rem; }

.recibo { display: block; }
.recibo img {
    display: block;
    width: 88px; height: 88px;
    object-fit: cover;
    border: 1px solid var(--linea);
    border-radius: var(--radio-chico);
    background: var(--superficie);
}
.recibo a:focus-visible img {
    outline: 2px solid var(--acento-hondo);
    outline-offset: 2px;
}
.recibo-quitar, .gasto-borrar {
    display: flex; align-items: center; gap: .4rem;
    min-height: 44px;                      /* la yema del dedo */
    color: var(--tinta-suave);
    font-size: 14px; font-weight: 400;
    cursor: pointer;
}
.recibo-quitar input, .gasto-borrar input {
    width: 22px; height: 22px;
    accent-color: var(--terracota-hondo);
}
.gasto-borrar { margin-top: .3rem; }

/* Ámbar y no rojo: que falte el comprobante no es un error, es algo
   pendiente. El tesorero tiene que verlo ANTES de que firme el
   presidente, y por eso se cuenta también abajo. */
.gasto-falta {
    display: inline-block;
    padding: .3rem .6rem;
    border-radius: var(--radio-chico);
    background: var(--aviso-fondo);
    color: var(--aviso);
    font-size: 14px;
}

.gastos-cuenta {
    margin: 0 0 1.2rem;
    color: var(--tinta-suave);
    font-size: 15px;
    font-variant-numeric: tabular-nums;
}
.gastos-cuenta strong { color: var(--aviso); }

.gasto-nuevo {
    padding: 1rem;
    border: 1px dashed var(--linea);
    border-radius: var(--radio-chico);
    background: var(--acento-agua);
}
.gasto-nuevo h4 {
    margin: 0 0 .9rem;
    font: 600 15px/1.2 var(--sans);
    letter-spacing: .04em; text-transform: uppercase;
    color: var(--acento-hondo);
}
.gasto-nuevo .field:last-child { margin-bottom: 0; }

.gasto-nuevo-linea { display: flex; flex-wrap: wrap; gap: 0 1rem; }
.gasto-nuevo-linea .field { flex: 1 1 14rem; }
.gasto-nuevo-linea .field-monto { flex: 0 0 9rem; }

@media (max-width: 640px) {
    /* En un celular las dos columnas del gasto nuevo no caben una al
       lado de la otra sin que el importe quede en tres caracteres. */
    .gasto-nuevo-linea .field, .gasto-nuevo-linea .field-monto { flex: 1 1 100%; }
    .gasto-datos .gasto-desc { flex: 1 1 100%; }
    .gasto-datos .gasto-monto { flex: 1 1 100%; text-align: left; }
    .recibo img { width: 76px; height: 76px; }
}

/* ---- Las dos maneras de traer una foto -------------------------------
   Dos botones con dibujo en vez de un campo de archivo. La cámara hace
   la foto en el momento; la flecha busca en lo que ya está guardado.

   El campo de archivo real está oculto con .sr-only —sigue en el
   documento y sigue recibiendo el foco— y lo que se ve y se toca es su
   etiqueta. Por eso el foco del teclado se dibuja con el selector de
   hermano: sin esto, quien navegue con tabulador no vería dónde está.

   56 px de alto: son la acción principal del bloque y se pulsan con el
   pulgar, a menudo de pie y con el celular en una mano. */
.foto-opciones { display: flex; gap: .7rem; }
.foto-opcion { flex: 1 1 0; min-width: 0; }

.foto-opcion label {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    min-height: 56px;
    padding: .6rem .5rem;
    border: 1px dashed var(--linea);
    border-radius: var(--radio-chico);
    background: var(--superficie);
    color: var(--tinta-suave);
    font-size: 15px;
    font-weight: 600;
    text-align: center;
    cursor: pointer;
}
.foto-opcion label:hover {
    border-color: var(--acento);
    color: var(--acento-hondo);
    background: var(--acento-agua);
}
.foto-opcion label .icono { flex: 0 0 auto; color: var(--acento-hondo); }

.foto-opcion input[type=file]:focus-visible + label {
    border-color: var(--acento-hondo);
    outline: 2px solid transparent;
    box-shadow: 0 0 0 3px var(--acento-agua), 0 0 0 4px var(--acento-hondo);
}

/* El rótulo de encima. Es un <p> y no un <label>: son dos campos, y una
   etiqueta solo puede apuntar a uno. */
.foto-rotulo {
    margin: 0 0 .4rem;
    font-size: 15px;
    font-weight: 600;
    color: var(--tinta-suave);
}

.gasto-anadir-foto { margin-top: .9rem; }

/* Bajo una miniatura de 88 px no caben dos botones al lado del otro. */
.recibo .foto-opciones { flex-direction: column; gap: .3rem; margin-top: .35rem; }
.recibo .foto-opcion label {
    min-height: 40px;
    padding: .35rem .4rem;
    font-size: 13px;
    font-weight: 600;
}
.recibo .foto-opcion label .icono { width: 18px; height: 18px; }

@media (max-width: 400px) {
    /* En las pantallas más estrechas el texto de los dos botones se
       parte en tres renglones. Mejor uno encima del otro. */
    .foto-opciones { flex-direction: column; }
}

/* ---- Botón que puede quedarse en icono --------------------------------
   En pantalla ancha se ve el dibujo Y la palabra: el dibujo solo es
   ambiguo hasta que se aprende, y aquí sobra el sitio para no obligar a
   nadie a aprenderlo. En el celular se queda el dibujo (ver el bloque de
   pantallas estrechas). */
.btn-icono { display: inline-flex; align-items: center; gap: .4rem; }
.btn-icono .icono { flex: 0 0 auto; }

/* La columna de acciones abre la fila: se alinea a la izquierda como el
   resto del contenido, no a la derecha como cuando la cerraba. */
.col-acciones { text-align: left; }

/* ======================================================================
   EL MENÚ LATERAL: LOGO, GRUPOS PLEGABLES E INFORMES
   ====================================================================== */

/* ---- El logo del praesidium, encima de todo -------------------------
   Cuadrado y contenido, para que dé igual la forma que traiga el archivo
   que se suba. `object-fit: contain` no lo recorta ni lo deforma: lo
   encaja dentro y deja el aire alrededor. */
.sidebar-logo {
    display: flex;
    justify-content: center;
    padding: 5px;
    margin-bottom: 1.2rem;
    border-bottom: 1px solid var(--linea-suave);
}

/* El logo ocupa el ancho del menú, menos los 5 px de aire del contenedor.
   El alto lo pone la propia imagen: `height: auto` con `width: 100%` la
   deja crecer a lo que le toque por su proporción, sea cuadrada, alta o
   apaisada, sin recortarla ni deformarla. */
.sidebar-logo img {
    width: 100%;
    height: auto;
    object-fit: contain;
}

/* El logo del praesidium en la BARRA SUPERIOR. En la computadora no se
   ve: allí está arriba del menú, que siempre está desplegado, y
   repetirlo sería decir dos veces lo mismo. Se enciende más abajo, en
   el bloque de pantallas estrechas. */
.logo-praesidium { display: none; }

/* En el celular el menú es un panel a todo el ancho de la pantalla, así
   que un logo al 100 % ocuparía media pantalla antes de llegar al primer
   enlace. Se le pone de tope el ancho que tiene el menú en la
   computadora y se centra: el logo se ve igual en los dos sitios.

   Va AQUÍ, después de la regla base, y no en el bloque de pantallas
   estrechas de más arriba: una @media no pesa más que una regla suelta,
   gana la que va después en el archivo. Puesta antes, el margen de abajo
   se lo comía la base. */
@media (max-width: 860px) {
    /* El logo también encabeza el menú desplegado: al abrirlo, lo
       primero que se ve es de quién es el praesidium, igual que en la
       computadora. Pero el panel ocupa todo el ancho, y al 100 % el logo
       se comería media pantalla antes del primer enlace: se topa en
       140 px por lado y se centra. Un logo apaisado queda a 140 de
       ancho; uno vertical, a 140 de alto. */
    .sidebar-logo {
        padding: .2rem 0 .9rem;
        margin: 0 1rem .9rem;
    }
    .sidebar-logo img {
        width: auto;
        max-width: 140px;
        max-height: 140px;
    }

    /* A la izquierda del nombre. 75 px de ancho y el alto por su
       proporción; el tope de altura evita que un logo muy vertical
       estire la barra y descoloque todo lo demás. */
    .logo-praesidium {
        display: block;
        width: 75px;
        height: auto;
        max-height: 48px;
        object-fit: contain;
    }

    /* Los 75 px del logo hay que sacarlos de algún lado: con la barra
       tal como estaba, en un celular de 360 px se pasaba por 69. Lo que
       sobra es el nombre de la aplicación —«LEGIO-RECORD · Legión de
       María»—, que dice lo mismo en todas las pantallas. El logo del
       praesidium informa mucho más, y el Vexillum de la izquierda sigue
       ahí y sigue llevando al inicio. */
    .brand-text { display: none; }
    .topbar { padding: 0 1rem; gap: .6rem; }
}

/* ---- Grupos plegables ------------------------------------------------
   Son <details>/<summary> del propio HTML: se pliegan sin JavaScript y
   se manejan con el teclado. El JS solo recuerda cuáles quedan abiertos.

   El marcador que pone el navegador se quita y se dibuja uno propio: el
   de serie es distinto en cada navegador y aquí ya hay un icono a la
   izquierda con el que tendría que convivir. */
details.nav-group > summary { cursor: pointer; list-style: none; }
details.nav-group > summary::-webkit-details-marker { display: none; }
details.nav-group > summary::marker { content: ''; }

.nav-title {
    position: relative;
    padding-right: 2.4rem;   /* sitio para la flecha */
    min-height: 44px;        /* se toca con el dedo */
}

/* La flecha, a la derecha. Gira al abrirse. */
.nav-title::after {
    content: '';
    position: absolute;
    right: 1.5rem;
    top: 50%;
    width: 7px;
    height: 7px;
    margin-top: -5px;
    border-right: 2px solid var(--tinta-tenue);
    border-bottom: 2px solid var(--tinta-tenue);
    transform: rotate(45deg);
    transition: transform .18s ease;
}
details.nav-group[open] > .nav-title::after {
    transform: rotate(-135deg);
    margin-top: -2px;
}

details.nav-group > summary:hover { color: var(--acento-hondo); }
details.nav-group > summary:focus-visible {
    outline: 2px solid var(--acento-hondo);
    outline-offset: -2px;
    border-radius: var(--radio-chico);
}

/* ---- Las dos subsecciones de Informes -------------------------------
   «Asistencia» y «Directorios» agrupan cuatro y seis listas largas. Sin
   ellas, Informes serían diez enlaces seguidos y no se distinguiría lo
   de cada junta de lo que es un padrón. */
.nav-sub { margin-top: .6rem; }
.nav-sub-title {
    display: flex;
    align-items: center;
    gap: .4rem;
    margin: 0 0 .25rem;
    padding: 0 1.5rem;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--tinta-tenue);
}
.nav-sub-title .icono { color: var(--acento); }
.nav-sub .nav-list .nav-link { margin-left: 1.6rem; }

/* Los informes no llevan icono propio: son diez y una columna de diez
   dibujos distintos es ruido, no ayuda. */
[data-modulo="informes"] .nav-link { padding-left: 1rem; }

/* ======================================================================
   EL MODAL DE INFORMES
   ======================================================================
   <dialog> con showModal(): el navegador lo pone en su capa superior, así
   que queda por encima del menú lateral sin pelear con ningún z-index, y
   atrapa el foco del teclado por su cuenta. */
.modal {
    width: min(30rem, calc(100vw - 2rem));
    padding: 0;
    border: 1px solid var(--linea);
    border-radius: var(--radio);
    background: var(--superficie);
    color: var(--tinta);
    box-shadow: var(--sombra);
}
.modal::backdrop { background: rgba(50, 58, 71, .45); }

.modal form { padding: 1.5rem; }

/* ---- La ventana de un punto de la junta ------------------------------

   El modal de informes pide cuatro datos y le sobra con 30rem. Este trae
   una pantalla entera —una tabla con su buscador, o la hoja de pasar
   lista— así que necesita todo el ancho útil y tope de alto, con el
   contenido desplazándose por dentro.

   El alto se fija, no se deja crecer: si creciera, la cabecera con el
   botón de cerrar se iría hacia arriba al cargar una lista larga y
   habría que bajar hasta el final para salir. */
/* ---- AL CERRAR TIENE QUE DESAPARECER DE VERDAD ----------------------

   El navegador esconde un diálogo cerrado con `dialog:not([open]) {
   display: none }`, que es una regla de su hoja por omisión y la pisa
   CUALQUIER regla de autor que fije `display`. Y la de abajo fija
   `display: flex`.

   Sin esta línea pasaba lo siguiente, y se veía rarísimo: al pulsar
   «Cerrar», `close()` sacaba el diálogo de la capa superior pero la
   caja seguía pintada —ya sin fondo oscurecido y ya sin estar por
   encima—, así que el contenido de la página, que lleva `z-index: 1`,
   le pasaba por delante. La ventana no se cerraba: se hundía.

   Es la MISMA trampa que `.aviso-flotante[hidden]`, y me la volví a
   comer. La regla general: toda declaración de `display` sobre algo que
   el navegador esconde por su cuenta —`[hidden]`, `dialog:not([open])`—
   tiene que devolverle esa forma de esconderse.

   `.modal`, el de informes, no la necesita porque no fija `display`. */
.modal-panel:not([open]) { display: none; }

.modal-panel {
    width: min(60rem, calc(100vw - 2rem));
    max-width: none;
    height: min(44rem, calc(100vh - 3rem));
    max-height: none;
    display: flex;
    flex-direction: column;
    padding: 0;
    overflow: hidden;
}

/* La cabecera se queda quieta; lo que se mueve es el cuerpo. */
.modal-panel-cabeza {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .8rem;
    padding: .9rem 1.1rem;
    border-bottom: 1px solid var(--linea);
    background: var(--superficie-2);
}
.modal-panel-cabeza .modal-titulo { margin: 0; padding: 0; border: 0; }

.modal-panel-cuerpo {
    flex: 1 1 auto;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    padding: 1.1rem;
}

/* Lo que se inyecta viene de una pantalla entera y trae sus propios
   márgenes de página. Dentro de la ventana sobran: el primero despegaría
   el contenido de la cabecera y el último dejaría un hueco muerto. */
.modal-panel-cuerpo > *:first-child { margin-top: 0; }
.modal-panel-cuerpo > *:last-child  { margin-bottom: 0; }

/* El título de la pantalla invitada se baja de tamaño: ya hay un título
   arriba, en la cabecera de la ventana, y dos del mismo peso compiten. */
.modal-panel-cuerpo .page-head h1 { font-size: 1.15rem; }

/* Y dentro no hay a dónde volver: la vuelta es cerrar la ventana. */
.modal-panel-cuerpo .contexto-junta .volver-junta { display: none; }

.modal-titulo {
    margin: 0 0 1.2rem;
    padding-bottom: .8rem;
    border-bottom: 1px solid var(--linea-suave);
    font: 600 19px/1.3 var(--serif);
    color: var(--acento-hondo);
}

/* Desde y Hasta, uno al lado del otro mientras quepan. */
.modal-fechas { display: flex; gap: 1rem; }
.modal-fechas .field { flex: 1 1 0; min-width: 0; }

.modal-nota {
    margin: 0 0 1rem;
    color: var(--tinta-tenue);
    font-size: 15px;
}

.modal-acciones {
    display: flex;
    flex-wrap: wrap;
    gap: .6rem;
    margin-top: 1.4rem;
    padding-top: 1.2rem;
    border-top: 1px solid var(--linea-suave);
}
.modal .field:last-of-type { margin-bottom: 0; }

/* ======================================================================
   FICHAS  ·  la alternativa a la tabla, cuando hay demasiadas columnas
   ======================================================================
   Nacen por Miembros: doce columnas obligaban a arrastrar la tabla de
   lado en el celular para leer un teléfono. Una ficha por persona se lee
   de un vistazo y entra en cualquier pantalla. */

.fichas {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(21rem, 1fr));
    gap: 1rem;
}

.ficha {
    display: flex;
    flex-direction: column;
    padding: 1.1rem 1.2rem;
    border: 1px solid var(--linea);
    border-radius: var(--radio);
    background: var(--superficie);
    box-shadow: var(--sombra);
}
.ficha:hover { border-color: var(--acento); }

/* ---- Cabeza: la foto y el nombre ---------------------------------- */
.ficha-cabeza {
    display: flex;
    align-items: center;
    gap: .9rem;
    padding-bottom: .9rem;
    margin-bottom: .9rem;
    border-bottom: 1px solid var(--linea-suave);
}

/* El círculo. `object-fit: cover` recorta al centro en vez de deformar:
   una foto apaisada se corta por los lados y la cara queda entera, que es
   lo contrario de lo que haría un estirón. */
.ficha-foto {
    flex: 0 0 auto;
    width: 68px;
    height: 68px;
    border-radius: 50%;
    object-fit: cover;
    border: 2px solid var(--acento-agua);
    background: var(--superficie-2);
}

/* Sin foto, las iniciales. Se distingue una ficha de otra aunque nadie
   haya subido nada todavía, cosa que una silueta gris repetida no logra. */
.ficha-iniciales {
    display: flex;
    align-items: center;
    justify-content: center;
    font: 600 24px/1 var(--serif);
    letter-spacing: .04em;
    color: var(--acento-hondo);
    background: var(--acento-agua);
    border-color: var(--acento);
}

.ficha-quien { min-width: 0; }
.ficha-nombre {
    margin: 0 0 .25rem;
    font: 500 1.15rem/1.25 var(--serif);
    /* Un nombre muy largo no debe empujar la ficha a lo ancho. */
    overflow-wrap: anywhere;
}
.ficha-sub {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .4rem;
    margin: 0;
    font-size: 14px;
    color: var(--tinta-tenue);
}

/* ---- Los datos ----------------------------------------------------- */
.ficha-datos {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
    gap: .55rem .9rem;
    margin: 0 0 1rem;
    flex: 1 1 auto;
}
.ficha-dato { min-width: 0; }
.ficha-dato dt {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--tinta-tenue);
}
.ficha-dato dd {
    margin: 0;
    font-size: 15px;
    color: var(--tinta);
    overflow-wrap: anywhere;
}

/* ---- Los botones ---------------------------------------------------- */
.ficha-acciones {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    padding-top: .9rem;
    border-top: 1px solid var(--linea-suave);
}
.ficha-acciones .btn { display: inline-flex; align-items: center; gap: .4rem; }

/* ---- Quien está de baja --------------------------------------------
   Atenuada, pero legible: sigue siendo alguien con historial, no un
   registro tachado. La foto en gris dice de un vistazo quién ya no está. */
.ficha-inactiva { background: var(--superficie-2); border-style: dashed; }
.ficha-inactiva .ficha-foto { filter: grayscale(1); opacity: .75; }
.ficha-inactiva .ficha-nombre { color: var(--tinta-suave); }

.fichas .empty { grid-column: 1 / -1; }

@media (max-width: 640px) {
    /* Una ficha por fila: a 360 px, dos columnas dejan los datos en
       tiras de cuatro caracteres. */
    .fichas { grid-template-columns: 1fr; }

    /* Los botones a todo el ancho y apilados, como en los formularios:
       es donde llega el pulgar y no se falla el toque. */
    .ficha-acciones { flex-direction: column; }
    .ficha-acciones .btn { width: 100%; justify-content: center; min-height: 48px; }
    .ficha-acciones .inline-form { display: block; }

    /* El círculo, algo menor: deja sitio al nombre, que es lo que se
       busca al recorrer la lista. */
    .ficha-foto { width: 56px; height: 56px; }
    .ficha-iniciales { font-size: 20px; }
}

/* Una ficha que se ve pero no se toca: los consejos superiores miran el
   padrón de los suyos, pero no lo llevan. En vez de botones que van a
   rebotar, se dice por qué. */
.ficha-ajena {
    margin: 0;
    padding: .6rem .8rem;
    border-radius: var(--radio-chico);
    background: var(--superficie-2);
    border-left: 3px solid var(--linea);
    color: var(--tinta-tenue);
    font-size: 14px;
}

/* La barra del selector de consejo, encima del buscador. */
.toolbar-label {
    font-size: 15px;
    font-weight: 600;
    color: var(--tinta-suave);
}

/* ---- Biblioteca del Legionario ----------------------------------------
   El título ES el enlace que abre el PDF: un bloque entero que se toca
   con el pulgar, de 48 px como mínimo, en vez de un botón pequeño al
   final de una fila que en el celular queda fuera de la pantalla. Debajo,
   el peso: con datos móviles no es lo mismo 300 KB que 30 MB. */
.biblio-doc {
    display: flex;
    align-items: center;
    gap: .6rem;
    min-height: 48px;
    padding: .3rem 0;
    color: var(--tinta);
    text-decoration: none;
}
.biblio-doc .icono { flex: 0 0 auto; color: var(--acento-hondo); }
.biblio-doc strong { display: block; font-size: 17px; line-height: 1.3; }
.biblio-doc small { display: block; font-size: 14px; color: var(--tinta-tenue); }
.biblio-doc:hover strong,
.biblio-doc:focus-visible strong { color: var(--acento-hondo); text-decoration: underline; }
.biblio-desc { margin: .1rem 0 .3rem 2.3rem; font-size: 15px; color: var(--tinta-suave); }
.biblio-actual { margin: 0 0 .5rem; font-size: 15px; color: var(--tinta-suave); }

/* ---- Biblia Legionis (inicio) -----------------------------------------
   La única tarjeta del inicio que no lleva a otra pantalla: los documentos
   están dentro, a un toque. Se distingue por el oro —el color del
   praesidium y del Vexillum—, puesto en una franja arriba y en el fondo de
   la cabecera. El texto NO va blanco sobre el oro, como en las otras
   bandas: ahí solo hay un icono decorativo, y un título blanco sobre
   #D8B463 no llega a 2,5 : 1. Va en tinta sobre oro-agua.

   Dos columnas en pantalla ancha; en el celular, una encima de otra. */
.biblia-card {
    background: var(--superficie);
    border: 1px solid var(--linea);
    border-top: 6px solid var(--oro);
    border-radius: var(--radio);
    box-shadow: var(--sombra);
    overflow: hidden;
}
.biblia-banda {
    display: flex;
    align-items: center;
    gap: .8rem;
    padding: .9rem 1.2rem;
    background: var(--oro-agua);
    border-bottom: 1px solid var(--linea);
}
.biblia-banda .icono { flex: 0 0 auto; color: var(--oro-hondo); }
.biblia-banda h2 { margin: 0; font: 600 1.45rem/1.15 var(--serif); color: var(--tinta); }
.biblia-banda small { display: block; font-size: 14px; color: var(--tinta-suave); }

.biblia-columnas {
    display: grid;
    grid-template-columns: 1fr 1fr;
}
.biblia-columna { padding: .9rem 1.2rem 1rem; min-width: 0; }
.biblia-columna + .biblia-columna { border-left: 1px solid var(--linea); }
/* El nombre del estante, en negativo: blanco sobre oro hondo, 5,5 : 1.
   Sobre el oro claro de la franja no llegaría a 2,5 : 1. */
.biblia-columna h3 {
    margin: 0 0 .5rem;
    padding: .5rem .8rem;
    border-radius: var(--radio-chico);
    background: var(--oro-hondo);
    color: #FFFFFF;
    font-size: 14px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
}
.biblia-columna ul { list-style: none; margin: 0; padding: 0; }
.biblia-columna li + li { border-top: 1px solid var(--linea); }

/* Cada título es un renglón entero que se toca con el pulgar: 48 px. */
.biblia-columna a {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .7rem;
    min-height: 48px;
    padding: .45rem 0;
    color: var(--tinta);
    text-decoration: none;
    font-size: 17px;
    line-height: 1.3;
}
.biblia-columna a small { flex: 0 0 auto; font-size: 14px; color: var(--tinta-tenue); }
.biblia-columna a:hover span,
.biblia-columna a:focus-visible span { color: var(--oro-hondo); text-decoration: underline; }

/* El título va dentro de un <summary>: sin el triángulo del navegador,
   que se cambia por una flecha propia (más abajo). */
.biblia-columna summary { list-style: none; }
.biblia-columna summary::-webkit-details-marker { display: none; }
.biblia-columna summary h3 { display: flex; align-items: center; gap: .4rem; }
.biblia-cuenta { font-weight: 400; opacity: .85; }

@media (max-width: 700px) {
    .biblia-columnas { grid-template-columns: 1fr; }
    .biblia-columna + .biblia-columna { border-left: 0; border-top: 1px solid var(--linea); }

    /* En el celular el título crece a 48 px, el blanco del pulgar. */
    .biblia-columna summary h3 { min-height: 48px; }
    .biblia-columna { padding-top: .7rem; padding-bottom: .7rem; }
}

/* El título de cada estante es un botón en TODAS las pantallas: pliega su
   estante (la cabecera «Biblia Legionis» pliega los dos). Una flecha dice
   que se abre, y gira sin animación —en un Android viejo una transición
   se ve a tirones—. */
.biblia-columna summary { cursor: pointer; }
.biblia-columna summary h3 { margin-bottom: 0; }
.biblia-columna[open] summary h3 { margin-bottom: .5rem; }
.biblia-columna summary h3::after {
    content: '';
    margin-left: auto;
    width: 9px; height: 9px;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: translateY(-2px) rotate(45deg);
}
.biblia-columna[open] summary h3::after { transform: translateY(2px) rotate(-135deg); }
.biblia-columna summary:focus-visible h3 { outline: 3px solid var(--oro); outline-offset: 2px; }

/* ---- Asistencias: resumen por miembro ----------------------------------
   Lo que se viene a leer son los números, así que van grandes y en
   columnas estrechas: en un celular de 360 px caben el nombre y las tres
   cifras sin desplazar la tabla. El nombre es el enlace al detalle, con
   renglón de 48 px para el pulgar. La fila de totales se separa con una
   raya doble, como en un libro de cuentas. */
.asistencia-resumen td.al-center { font-size: 18px; font-variant-numeric: tabular-nums; width: 1%; padding-left: .9rem; padding-right: .9rem; }
.asistencia-resumen td a { display: inline-flex; align-items: center; min-height: 48px; font-size: 17px; }
.asistencia-resumen th .pill { font-size: 13px; }
.asistencia-resumen tfoot th,
.asistencia-resumen tfoot td { border-top: 3px double var(--linea); }
.asistencia-resumen tfoot th { text-align: left; }

/* La foto del miembro junto a su nombre: un círculo de 40 px, el mismo
   dibujo que la ficha de Miembros en pequeño. Sin foto, sus iniciales. */
.asistencia-resumen td a.asistencia-quien { gap: .65rem; }
.asistencia-foto {
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    object-fit: cover;
    border: 2px solid var(--acento-agua);
    background: var(--superficie-2);
}
.asistencia-iniciales {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font: 600 15px/1 var(--serif);
    letter-spacing: .04em;
    color: var(--acento-hondo);
    background: var(--acento-agua);
    border-color: var(--acento);
}

/* En el celular la tabla tiene que caber sin la barra de desplazamiento:
   las cabeceras quedan en P / A / E (ver apps/attendance) y las columnas
   de números se estrechan al mínimo. El sitio que se gana es para el
   nombre, que es lo que se lee. */
@media (max-width: 860px) {
    .asistencia-resumen th,
    .asistencia-resumen td { padding-left: .45rem; padding-right: .45rem; }
    .asistencia-resumen td.al-center { padding-left: .35rem; padding-right: .35rem; }
    .asistencia-resumen th .pill { min-width: 2rem; padding-left: .45rem; padding-right: .45rem; text-align: center; }
    .asistencia-resumen td a.asistencia-quien { gap: .5rem; font-size: 16px; }
    .asistencia-resumen td a.asistencia-quien span:last-child { overflow-wrap: anywhere; }
    .asistencia-foto { width: 34px; height: 34px; }
}

/* ---- Ficha del socio en el inicio: asistencia y aportes ----------------
   Dos bloques bajo los datos, separados por una raya. La asistencia son
   tres píldoras con el número delante, en los colores de siempre; los
   aportes, una tabla corta por categoría con el total abajo. La tabla va
   a 14 px y con renglones bajos: con veinte actividades se iba muy abajo.
   De 14 no se baja, que la leen personas mayores en el celular. */
.ficha-bloque {
    margin-top: .9rem;
    padding-top: .8rem;
    border-top: 1px solid var(--linea-suave);
}
.ficha-bloque h4 {
    margin: 0 0 .5rem;
    font-size: 13px;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--tinta-suave);
}
.ficha-asistencia { display: flex; flex-wrap: wrap; gap: .45rem; margin: 0; padding: 0; list-style: none; }
.ficha-asistencia .pill { font-size: 15px; padding: .3rem .75rem; }
.ficha-asistencia strong { font-size: 18px; margin-right: .2rem; }

.ficha-aportes { width: 100%; border-collapse: collapse; margin-top: .45rem; font-size: 14px; line-height: 1.3; }
.ficha-aportes th, .ficha-aportes td { padding: .22rem .3rem; border-bottom: 1px solid var(--linea-suave); text-align: left; }
.ficha-aportes thead th { font-size: 13px; color: var(--acento-hondo); border-bottom-color: var(--linea); }
.ficha-aportes td.al-right, .ficha-aportes th.al-right { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.ficha-aportes tfoot th, .ficha-aportes tfoot td { border-top: 3px double var(--linea); border-bottom: 0; }

/* ---- Inicio del socio: ficha y Biblia Legionis lado a lado -------------
   En pantalla ancha la ficha conserva su ancho —el mismo de Miembros— y
   la Biblia se queda con todo lo que sobra. Ahí los dos estantes van uno
   encima del otro, como en el celular: en media pantalla, dos columnas
   partían cada título en tres renglones. En el celular, todo apilado. */
@media (min-width: 861px) {
    .inicio-socio {
        display: grid;
        grid-template-columns: minmax(24rem, 32rem) minmax(0, 1fr);
        gap: 1.2rem;
        align-items: start;
    }
    .inicio-socio > .fichas { grid-template-columns: 1fr; }
}

.biblia-al-lado .biblia-columnas { grid-template-columns: 1fr; }
.biblia-al-lado .biblia-columna + .biblia-columna { border-left: 0; border-top: 1px solid var(--linea); }

/* ---- Ficha del socio y Biblia Legionis: cristal sobre el fondo ---------
   El fondo del praesidium se ve a través, desenfocado. Lo que baja a .7 es
   el COLOR DE FONDO —rgba de --superficie y --oro-agua—, no la opacidad
   del bloque: con `opacity` se aclararían también el texto, las fotos y
   los números, y perderían contraste. `-webkit-` es para Safari de iPhone
   anterior a la 18, que todavía lo pide con prefijo. */
.inicio-socio .ficha,
.biblia-card {
    background: rgba(255, 253, 249, .7);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
}
.biblia-card .biblia-banda { background: rgba(251, 246, 236, .7); }

/* La ficha del socio entera se toca para plegar sus aportes: que se note
   que se puede. El título del bloque lleva la misma flecha que los
   estantes de la Biblia, sin animación. */
[data-ficha-plegable] { cursor: pointer; }
.ficha-plegable > summary { list-style: none; display: flex; align-items: center; min-height: 32px; }
.ficha-plegable > summary::-webkit-details-marker { display: none; }
.ficha-plegable > summary h4 { margin: 0; flex: 1 1 auto; }
.ficha-plegable > summary::after {
    content: '';
    width: 8px; height: 8px;
    margin-right: .3rem;
    border-right: 2px solid var(--tinta-suave);
    border-bottom: 2px solid var(--tinta-suave);
    transform: translateY(-2px) rotate(45deg);
}
.ficha-plegable[open] > summary::after { transform: translateY(2px) rotate(-135deg); }
.ficha-plegable[open] > summary { margin-bottom: .3rem; }
.ficha-plegable > summary:focus-visible { outline: 3px solid var(--acento); outline-offset: 2px; }

/* En pantalla ancha la cabecera de la Biblia pliega los dos estantes:
   cursor de mano y la misma flecha que los estantes. app.js le pone
   role="button" solo en ese modo, así que la flecha sale solo ahí. */
.biblia-banda[role="button"] { cursor: pointer; }
.biblia-banda[role="button"]::after {
    content: '';
    margin-left: auto;
    width: 10px; height: 10px;
    border-right: 2px solid var(--oro-hondo);
    border-bottom: 2px solid var(--oro-hondo);
    transform: translateY(2px) rotate(-135deg);
}
.biblia-banda[aria-expanded="false"]::after { transform: translateY(-3px) rotate(45deg); }
.biblia-banda[role="button"]:focus-visible { outline: 3px solid var(--oro); outline-offset: -3px; }

/* ---- Vatican News ------------------------------------------------------
   La misma tarjeta de cristal que la Biblia, debajo y con su ancho. El
   widget va dentro de un iframe aislado; arranca a 520 px y app.js lo
   ajusta a lo que mide de verdad en cuanto el widget avisa. */
.inicio-socio-lado { min-width: 0; }
.vaticano-marco {
    display: block;
    width: 100%;
    height: 520px;
    border: 0;
    background: transparent;
}

/* Vatican News plegado: solo la cabecera. El iframe se esconde, no se
   quita, para que al abrirlo no se descargue otra vez. La flecha y el
   cursor de mano salen de las reglas de `.biblia-banda[role="button"]`. */
.vaticano-card.plegada .vaticano-marco { display: none; }
.vaticano-card.plegada .biblia-banda { border-bottom: 0; }

/* ---- Portada de los oficiales ------------------------------------------
   «Juntas del Praesidium»: las cuatro pantallas de cada semana en una sola
   fila en pantalla ancha, y una debajo de otra en el celular. */
.juntas-praesidium { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 700px) {
    .juntas-praesidium { grid-template-columns: 1fr; }
}

/* «Miembros del Praesidium»: la tarjeta de cristal de la Biblia, con los
   totales del praesidium por categoría a la derecha de la cabecera (debajo
   en el celular) y las fichas dentro. Cada ficha va plegada; al abrirse
   una no estira a sus vecinas de fila: `align-items: start`. */
.miembros-banda { flex-wrap: wrap; }
.miembros-totales {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
    margin: 0 0 0 auto;
    padding: 0;
    list-style: none;
}
.miembros-totales li {
    padding: .3rem .7rem;
    border-radius: 999px;
    background: var(--superficie);
    border: 1px solid var(--linea);
    font-size: 14px;
    color: var(--tinta-suave);
    white-space: nowrap;
}
.miembros-totales strong { font-size: 17px; color: var(--oro-hondo); margin-right: .15rem; }
@media (max-width: 700px) {
    .miembros-totales { margin-left: 0; width: 100%; }
}

.miembros-fichas { padding: 1rem 1.2rem 1.2rem; align-items: start; }

/* La ficha plegada es más baja: foto de 52 px y menos aire. Lo que se
   viene a ver de un vistazo es quién es y cómo va de asistencia. */
.ficha-compacta { padding: .8rem 1rem; }
.ficha-compacta .ficha-foto { width: 52px; height: 52px; }
.ficha-compacta .ficha-iniciales { font-size: 19px; }
.ficha-compacta .ficha-bloque { margin-top: .6rem; padding-top: .55rem; }

/* Miembros del Praesidium plegado: solo la cabecera, con sus totales. */
.miembros-card.plegada .miembros-fichas { display: none; }
.miembros-card.plegada .biblia-banda { border-bottom: 0; }

/* ---- Portada de los oficiales: dos columnas -----------------------------
   Mitad y mitad en pantalla ancha: Juntas y Miembros a la izquierda, la
   Biblia y Vatican News a la derecha. En el celular, apiladas. */
@media (min-width: 861px) {
    .inicio-oficial {
        display: grid;
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        gap: 1.2rem;
        align-items: start;
    }
}
.inicio-oficial-izq, .inicio-oficial-der { min-width: 0; }

/* «Juntas del Praesidium» como tarjeta: las cuatro dentro, con aire; al
   plegarla queda solo la cabecera. En media pantalla las cuatro en fila
   quedan justas, así que el nombre de la carpeta, que no le dice nada a
   quien lo lee, se recorta en vez de ensanchar la tarjeta. */
.juntas-card .juntas-praesidium { padding: 1rem 1.2rem 1.2rem; gap: .7rem; }
.juntas-card .app-card > strong,
.juntas-card .app-card > small { padding-left: .8rem; padding-right: .8rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.juntas-card .app-card-banda { padding: 0 .8rem; }
.juntas-card.plegada .juntas-praesidium { display: none; }
.juntas-card.plegada .biblia-banda { border-bottom: 0; }

/* El nombre del praesidium, junto a «Juntas del Praesidium»: en el oro
   hondo del módulo y en cursiva, para que se lea como el nombre propio
   que es y no como parte del rótulo. */
.juntas-nombre { color: var(--oro-hondo); font-style: italic; }

/* ---- Asignación de trabajos: a quién --------------------------------------
   Una casilla por socio, cada una un renglón de 48 px con letra de 17 px:
   se marca con el pulgar sin acertar a un cuadrito. «Todos» va arriba y
   separado, porque cambia a todas las demás. En pantalla ancha, dos o
   tres columnas; en el celular, una. */
.trabajo-socios { border: 0; padding: 0; margin: 0 0 1.2rem; min-width: 0; }
.trabajo-socios legend { padding: 0; margin-bottom: .4rem; font-weight: 600; color: var(--tinta-suave); }
.trabajo-socios .casillas {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
    gap: 0 .8rem;
}
.trabajo-socios .casilla {
    display: flex;
    align-items: center;
    gap: .6rem;
    min-height: 48px;
    margin: 0;
    font-size: 17px;
    font-weight: 400;
    color: var(--tinta);
    cursor: pointer;
}
.trabajo-socios .casilla input {
    flex: 0 0 auto;
    width: 22px;
    height: 22px;
    margin: 0;
    accent-color: var(--oro-hondo);
}
.trabajo-socios .casilla-todos {
    margin-bottom: .3rem;
    padding-bottom: .3rem;
    border-bottom: 1px solid var(--linea);
}
.trabajo-socios .trabajo-otro { display: block; margin-top: 1rem; }
