@keyframes swing {
    0% {
        transform: rotate(0deg);
    }
    10% {
        transform: rotate(10deg);
    }
    30% {
        transform: rotate(0deg);
    }
    40% {
        transform: rotate(-10deg);
    }
    50% {
        transform: rotate(0deg);
    }
    60% {
        transform: rotate(5deg);
    }
    70% {
        transform: rotate(0deg);
    }
    80% {
        transform: rotate(-5deg);
    }
    100% {
        transform: rotate(0deg);
    }
}

@keyframes sonar {
    0% {
        transform: scale(0.9);
        opacity: 1;
    }
    100% {
        transform: scale(2);
        opacity: 0;
    }
}
body {
    font-size: 0.9rem;
}
.page-wrapper .sidebar-wrapper,
.sidebar-wrapper .sidebar-brand > a,
.sidebar-wrapper .sidebar-dropdown > a:after,
.sidebar-wrapper .sidebar-menu .sidebar-dropdown .sidebar-submenu li a:before,
.sidebar-wrapper ul li a i,
.page-wrapper .page-content,
.sidebar-wrapper .sidebar-search input.search-menu,
.sidebar-wrapper .sidebar-search .input-group-text,
.sidebar-wrapper .sidebar-menu ul li a,
#show-sidebar,
#close-sidebar {
    -webkit-transition: all 0.3s ease;
    -moz-transition: all 0.3s ease;
    -ms-transition: all 0.3s ease;
    -o-transition: all 0.3s ease;
    transition: all 0.3s ease;
}

/*----------------page-wrapper----------------*/

.page-wrapper {
    height: 100vh;
}

.page-wrapper .theme {
    width: 40px;
    height: 40px;
    display: inline-block;
    border-radius: 4px;
    margin: 2px;
}

.page-wrapper .theme.chiller-theme {
    background: #1e2229;
}

/*----------------toggeled sidebar----------------*/

.page-wrapper.toggled .sidebar-wrapper {
    left: 0px;
}

@media screen and (min-width: 768px) {
    .page-wrapper.toggled .page-content {
        padding-left: 260px;
    }
}

@media screen and (max-width: 768px) {
    #main-content {
        padding-left: 15px;
        padding-right: 15px;
    }
}

/*----------------show sidebar button----------------*/
#show-sidebar {
    position: fixed;
    left: 0;
    top: 10px;
    border-radius: 0 4px 4px 0px;
    width: 35px;
    transition-delay: 0.3s;
}
.page-wrapper.toggled #show-sidebar {
    left: -40px;
}
/*----------------sidebar-wrapper----------------*/

.sidebar-wrapper {
    width: 260px;
    height: 100%;
    max-height: 100%;
    position: fixed;
    top: 0;
    left: -300px;
    z-index: 999;
}

.sidebar-wrapper ul {
    list-style-type: none;
    padding: 0;
    margin: 0;
}

.sidebar-wrapper a {
    text-decoration: none;
}

/*----------------sidebar-content----------------*/

.sidebar-content {
    max-height: calc(100% - 30px);
    height: calc(100% - 30px);
    overflow-y: auto;
    position: relative;
}

.sidebar-content.desktop {
    overflow-y: hidden;
}

/*--------------------sidebar-brand----------------------*/

.sidebar-wrapper .sidebar-brand {
    padding: 10px 20px;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.sidebar-wrapper .sidebar-brand > a {
    text-transform: uppercase;
    font-weight: bold;
    flex-grow: 0;
}

.sidebar-wrapper .sidebar-brand #close-sidebar {
    cursor: pointer;
    font-size: 20px;
}
/*--------------------sidebar-header----------------------*/

.sidebar-wrapper .sidebar-header {
    padding: 10px;
    overflow: hidden;
}

.sidebar-wrapper .sidebar-header .user-pic {
    float: left;
    width: 60px;
    padding: 2px;
    border-radius: 12px;
    margin-right: 15px;
    overflow: hidden;
}

.sidebar-wrapper .sidebar-header .user-pic img {
    object-fit: cover;
    height: 100%;
    width: 100%;
}

.sidebar-wrapper .sidebar-header .user-info {
    float: left;
}

.sidebar-wrapper .sidebar-header .user-info > span {
    display: block;
}

.sidebar-wrapper .sidebar-header .user-info .user-role {
    font-size: 12px;
}

.sidebar-wrapper .sidebar-header .user-info .user-status {
    font-size: 11px;
    margin-top: 4px;
}

.sidebar-wrapper .sidebar-header .user-info .user-status i {
    font-size: 8px;
    margin-right: 4px;
    color: #5cb85c;
}

/*-----------------------sidebar-search------------------------*/

.sidebar-wrapper .sidebar-search > div {
    padding: 10px 20px;
}

/*----------------------sidebar-menu-------------------------*/

.sidebar-wrapper .sidebar-menu {
    padding-bottom: 10px;
}

.sidebar-wrapper .sidebar-menu .header-menu span {
    font-weight: bold;
    font-size: 14px;
    padding: 15px 20px 5px 20px;
    display: inline-block;
}

@media screen and (min-width: 1921px) {
    .menuitem-fontsize {
        font-size: 1rem;
    }
    .sidebar-wrapper .sidebar-menu .header-menu span {
        font-size: 1rem;
    }
    
    body {
        font-size: 1rem;
    }
}


.sidebar-wrapper .sidebar-menu ul li a {
    display: inline-block;
    width: 100%;
    text-decoration: none;
    position: relative;
    padding: 8px 30px 8px 20px;
}

.sidebar-wrapper .sidebar-menu ul li a i {
    margin-right: 10px;
    font-size: 12px;
    width: 30px;
    height: 30px;
    line-height: 30px;
    text-align: center;
    border-radius: 4px;
}

.sidebar-wrapper .sidebar-menu ul li a:hover > i::before {
    display: inline-block;
    animation: swing ease-in-out 0.5s 1 alternate;
}

.sidebar-wrapper .sidebar-menu .sidebar-dropdown > a:after {
    font-family: "Font Awesome 5 Free";
    font-weight: 900;
    content: "\f105";
    font-style: normal;
    display: inline-block;
    font-style: normal;
    font-variant: normal;
    text-rendering: auto;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-align: center;
    background: 0 0;
    position: absolute;
    right: 15px;
    top: 14px;
}

.sidebar-dropdown-subitem div > a:after {
    font-family: "Font Awesome 5 Free";
    font-weight: 900;
    content: "\f105";
    font-style: normal;
    display: inline-block;
    font-style: normal;
    font-variant: normal;
    text-rendering: auto;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-align: center;
    background: 0 0;
    position: absolute;
    right: 15px;
    top: 7px;
}

/*
 * Feedback del 2026-09-04 — el título y la flecha de un subitem CON hijos (ej. "Reportes") tienen
 * que terminar en el mismo borde derecho que el `.nivel-1` (ej. "Ventas"), no en el borde real del
 * sidebar.
 *
 * `.sidebar-dropdown > .nivel-1` (más abajo) es un contenedor `display: flex` con `width: auto`:
 * ahí un `margin` SÍ retrae la caja, porque el ancho automático de un bloque se recalcula
 * descontando los márgenes. Esta `<a>`, en cambio, es `inline-block` con `width: 100%`
 * (`.sidebar-wrapper .sidebar-menu ul li a`, más arriba) — con el ancho fijado en un 100% literal,
 * un `margin-right` NO achica la caja: se suma afuera, desborda el contenedor y un `overflow`
 * ancestro lo recorta sin que se note nada (por eso un primer intento con `margin-right` no cambió
 * nada visible). Hay que retraer el ANCHO mismo, con la misma técnica que ya usa `.menuitem` más
 * abajo en este archivo.
 *
 * ENMIENDA del 2026-09-10 (spec-20260910-001-lucayuvdev, AC2-bis) — ESTA REGLA SE FUE ENTERA: SU
 * `width` PASÓ A LA FÓRMULA CONSOLIDADA DE MÁS ABAJO.
 *
 *   Lo que la enmienda de más abajo (`li > .menuitem`, "cada hoja se queda a `--separacion-guia` de
 *   SU PROPIA GUÍA") le daba a la HOJA y no a esta fila era el par completo: `margin-left` +
 *   `width` compensado. Acá sólo estaba la mitad del ancho, sin `margin-left`, así que el fondo de
 *   "Reportes" nacía pegado (0px) a su guía mientras el de su hermana sin hijos nacía 5px adentro.
 *
 *   El pedido era igualarlos. La forma de igualarlos NO es escribir la fórmula acá también: dos
 *   reglas declarando el `width` del MISMO `<a>` hacen que el resultado correcto dependa del orden
 *   de aparición en el archivo, y cambiar la separación pasaría a ser dos ediciones en vez de una.
 *   Por eso el selector de esta fila se sumó a la lista de la regla de la fórmula (más abajo, buscar
 *   `li > .menuitem`) y esta regla se borró: sin el `width` no le quedaba ninguna declaración.
 *
 *   Tampoco se resolvió por el otro lado —darle la clase `menuitem` al `<a>` en `Sidebar.jsx`, que
 *   es la causa raíz literal de que la fórmula no lo alcanzara—: `.menuitem` arrastra el bullet-dot
 *   `::before` (ver la nota de más abajo), y al subitem le aparecería un punto que hoy no tiene.
 */

.sidebar-wrapper .sidebar-menu .sidebar-dropdown .sidebar-submenu ul {
    padding: 5px 0;
}

.sidebar-wrapper .sidebar-menu .sidebar-dropdown .sidebar-submenu li {
    padding-left: 25px;
    font-size: 13px;
}

.sidebar-dropdown-subitem div > a:before {
    content: "\f111";
    font-family: "Font Awesome 5 Free";
    font-weight: 900 !important ;
    font-style: normal;
    display: inline-block;
    text-align: center;
    text-decoration: none;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    margin-right: 6px;
    font-size: 8px;
}

.sidebar-wrapper .sidebar-menu .sidebar-dropdown .sidebar-submenu li a:before {
    content: "\f111";
    font-family: "Font Awesome 5 Free";
    font-weight: 400;
    font-style: normal;
    display: inline-block;
    text-align: center;
    text-decoration: none;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    margin-right: 6px;
    font-size: 8px;
}

.sidebar-wrapper .sidebar-menu ul li a span.label,
.sidebar-wrapper .sidebar-menu ul li a span.badge {
    float: right;
    margin-top: 8px;
    margin-left: 5px;
}

.sidebar-wrapper .sidebar-menu .sidebar-dropdown .sidebar-submenu li a .badge,
.sidebar-wrapper .sidebar-menu .sidebar-dropdown .sidebar-submenu li a .label {
    float: right;
    margin-top: 0px;
}

/*
 * spec-20260826-003-lucayuvdev, AC7 — el panel de submenú se DESPLIEGA animado, en los dos niveles.
 *
 * Hasta esta spec el panel de nivel 1 se montaba y desmontaba desde React
 * (`{abiertas[clave] && <div>}`) y encima tenía `display: none`: dos formas distintas de "no
 * existe", y sobre ninguna de las dos el navegador puede interpolar nada — de ahí el "popea" que
 * describe el pedido. El de nivel 2 (`.toggle`) directamente no tenía estado: siempre expandido.
 *
 * Ahora los dos paneles quedan SIEMPRE en el árbol y lo que cambia es su `max-height`, que es la
 * propiedad que el navegador sabe animar. `overflow: hidden` es lo que impide que el contenido se
 * escape mientras la caja está colapsada; la clase `active` del `<li>` (la misma que ya rotaba la
 * flechita indicadora) es la que decide cuál de los paneles montados se ve expandido.
 *
 * El tope de la altura expandida es deliberadamente holgado: `max-height` no fuerza altura, así que
 * un valor mayor que el contenido real deja la caja en su alto natural y sólo acota la animación.
 */
.sidebar-wrapper .sidebar-menu .sidebar-submenu,
.sidebar-wrapper .sidebar-menu .sidebar-dropdown-subitem > .toggle {
    display: block;
    overflow: hidden;
    max-height: 0;
    transition: all 0.3s ease;
}

.sidebar-wrapper .sidebar-menu .sidebar-dropdown.active > .sidebar-submenu,
.sidebar-wrapper .sidebar-menu .sidebar-dropdown-subitem.active > .toggle {
    max-height: 1000px;
}

.sidebar-wrapper .sidebar-menu .sidebar-dropdown.active > a:after {
    transform: rotate(90deg);
    right: 17px;
}

.sidebar-dropdown-subitem.active div > a:after {
    transform: rotate(90deg);  /* Rotar el icono cuando está activo */
    right: 15px;  /* Mover el icono hacia la derecha cuando está activo */
    transition: 0.5s all;
}

.sidebar-dropdown-subitem div a:after {
    transform: rotate(0deg);
    right: 15px;
    transition: 0.5s all;
}

/*--------------------------side-footer------------------------------*/

.sidebar-footer {
    position: absolute;
    width: 100%;
    bottom: 0;
    display: flex;
}

.sidebar-footer > a {
    flex-grow: 1;
    text-align: center;
    height: 30px;
    line-height: 30px;
    position: relative;
}

.sidebar-footer > a .notification {
    position: absolute;
    top: 0;
}

.badge-sonar {
    display: inline-block;
    background: #980303;
    border-radius: 50%;
    height: 8px;
    width: 8px;
    position: absolute;
    top: 0;
}

.badge-sonar:after {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    border: 2px solid #980303;
    opacity: 0;
    border-radius: 50%;
    width: 100%;
    height: 100%;
    animation: sonar 1.5s infinite;
}

/*--------------------------page-content-----------------------------*/

/* spec-20260908-002-lucayuvdev (AC6): el `padding-top: 20px` que el contrato congelado de
   `GeometriaDeLayoutSobreviveAlReworkTest::test_ac17` (de `spec-20260902-002`) exige desde entonces y
   que este archivo no declaraba — dos rojos preexistentes que `spec-20260907-002` dejó fuera de
   alcance. Va acá y NO en `#main-content`: ese nodo hijo trae un `padding-top: 0px` INLINE
   incondicional (`React/main.blade.php:247`) que pisaría cualquier valor que le diera una clase.
   Es eje VERTICAL, ortogonal al pedido horizontal del resto de esta spec. */
.page-wrapper .page-content {
    display: inline-block;
    width: 100%;
    padding-left: 0px;
    padding-top: 20px;
}

/* 2026-09-16 — EL PADDING VERTICAL TENÍA DOS HOGARES Y SE SUMABAN.

   Reportado por el usuario sobre Cuenta Corriente, y pedido expresamente como arreglo GENERAL y no
   por pantalla: el área de contenido arrancaba 40px abajo del borde en las 21 pantallas, porque
   `.page-wrapper .page-content` declara `padding-top: 20px` y esta regla declaraba otros 20 en su
   `padding` de cuatro valores.

   LA HOJA CREÍA QUE NO SE SUMABAN, y lo dejó escrito arriba: el comentario de `.page-content` dice
   que `#main-content` "trae un `padding-top: 0px` INLINE incondicional que pisaría cualquier valor
   que le diera una clase". Ese inline sigue emitido por `React/main.blade.php`, pero en el documento
   que el usuario inspeccionó el atributo `style` NO ESTÁ y DevTools reporta `Padding 20px 40px` sobre
   ese nodo. O sea que la premisa no se cumple en runtime, y nadie se enteró porque el contrato
   congelado afirma las dos declaraciones por separado y ninguna guarda las sumaba.

   POR QUÉ SE CORRIGE ACÁ Y NO SACANDO EL `padding-top` DEL PADRE: así el resultado es el mismo
   EXISTA O NO el inline. Con el inline presente, el top de este nodo ya era 0 y esta regla no
   aportaba nada; sin él, ahora tampoco. En los dos casos el vertical lo aporta `.page-content` y
   sólo él. Sacarlo del padre, en cambio, daría 20px con el inline ausente y 0px con el inline
   presente — el mismo defecto al revés, y dependiendo de un atributo que ya demostró no ser
   confiable.

   EL EJE HORIZONTAL NO SE TOCA: sigue teniendo su hogar único acá, que es lo que
   `spec-20260908-002-lucayuvdev` estableció y lo que vigila
   `resources/js/components/__tests__/hogarUnicoDelPaddingHorizontal.test.jsx`. Los dos ejes quedan
   con un solo hogar cada uno; que no sean el mismo nodo está dictado por el inline de arriba. */
.page-wrapper .page-content > div {
    padding: 0 40px 20px;
}

.page-wrapper .page-content {
    overflow-x: hidden;
}

/* ============================================================================================
 * LA SEPARACIÓN ENTRE FILAS DE UN FORMULARIO — UN SOLO HOGAR, PEDIDO DEL USUARIO (2026-09-17)
 *
 * QUÉ SE REPORTÓ: "el row gap de 20 en los formularios abm quedó muy grande, tokenicémoslo para
 * todos los abm y llevémoslo a 5", y sobre el modal de caso del CRM: "ese row gap de 15 está muy
 * grande, tokenicémoslo y llevémoslo a 5 también".
 *
 * EL PROBLEMA NO ERA EL NÚMERO, ERAN DOS NÚMEROS. La misma decisión —cuánto se separan las filas
 * de un formulario— estaba escrita en dos lugares y con dos valores distintos:
 * `Common/ABM/FormAbmContainer.jsx` pasaba `rowGap={20}` y el default de
 * `Common/FormConValidacionRenderInputs.jsx` era `15`. Cambiar "el row gap de los formularios"
 * obligaba a editar los dos y a acordarse de que existían los dos. Acá queda uno.
 *
 * POR QUÉ ACÁ Y NO EN `tokensDeDiseno.css`: esa hoja declara en su encabezado que NO contiene ni
 * una regla de geometría, y ésta lo es. La geometría de layout vive en este archivo, que es donde
 * ya viven `--margen-nivel-1`, `--padding-lateral-hoja` y `--separacion-guia`.
 *
 * POR QUÉ `:root` Y NO UN ALCANCE DE COMPONENTE, que es como se declaran los tres de arriba: los
 * formularios que lo consumen también se montan DENTRO de modales, y los modales de
 * react-bootstrap cuelgan de `document.body`, que es hermano de `.page-wrapper`. Un alcance más
 * cerrado no llegaría al modal de caso del CRM, que es justamente la mitad del pedido. Es el mismo
 * argumento por el que `tokensDeDiseno.css` puso `.tema-oscuro` en el `<body>` y no en el wrapper.
 *
 * QUIÉN LO CONSUME: los dos archivos de arriba, por `style` inline (`rowGap`/`marginBottom`). Un
 * llamador puntual puede seguir pasando su propio `rowGap` —`Screens/PantallaAsientosContables.jsx`
 * pasa `10`— y ese override sigue ganando: el token es el DEFAULT, no una imposición.
 * ============================================================================================ */
:root {
    /* 0 por pedido del usuario (2026-09-17): "los gaps de modal ABM y modal caso unificalos,
       ponelos en 0, para que todos los formularios tengan un solo valor". El valor vive acá y en
       ningun otro lado, asi que cambiarlo mueve TODOS los formularios de la aplicacion a la vez —
       que es exactamente lo que se pidio al tokenizarlo. */
    --separacion-de-filas-de-formulario: 0px;

    /* LA SEPARACIÓN ENTRE TARJETAS ES OTRA DECISIÓN, y por eso es otro token.
       PEDIDO DEL USUARIO (2026-09-17): "el abm de órdenes de producción no tiene gap entre las
       cards". Lo causó llevar el token de arriba a 0: las tarjetas de un formulario se apilan como
       columnas dentro de la MISMA fila que los campos, así que heredaban su `row-gap`. Pero "cuánto
       se separan dos filas de campos dentro de una tarjeta" y "cuánto se separa una tarjeta de la
       siguiente" no son la misma pregunta: la primera se quiere apretada y la segunda necesita aire
       para que se lea dónde termina un bloque y empieza el otro. Un solo valor para las dos obligaba
       a elegir cuál de las dos se veía mal. */
    --separacion-entre-tarjetas-de-formulario: 1rem;
}

/* LAS DOS CLASES QUE CONSUMEN EL TOKEN, y por qué el JSX no lo consume con `var()` directo.
 *
 * `Common/FormConValidacionRenderInputs.jsx` aplicaba la separación con un `style` inline. Poner
 * ahí un `var(--separacion-de-filas-de-formulario)` dejaba el token sin hogar válido entre dos
 * contratos del proyecto que se cruzan:
 *
 *   - `resources/js/__tests__/componentesSinLiteralesNeutros.test.js` (AC7) exige que todo `var()`
 *     que aparezca en un estilo inline de `Common/**` esté declarado en LOS DOS alcances de
 *     `public/css/tokensDeDiseno.css`;
 *   - y esa hoja declara en su encabezado que no contiene ni una regla de geometría, cosa que
 *     `tests/Feature/Common/TokensDeDisenoServidosTest::test_ac1` vigila.
 *
 * Un token de geometría consumido desde JSX no podía cumplir los dos a la vez. Sacando el `var()`
 * del inline y dejándolo del lado del CSS, los dos quedan satisfechos sin renegociar ninguno — y
 * el resultado es además el que ese guard existe para empujar: menos medidas escritas en el JSX.
 *
 * El componente aplica estas clases sólo cuando nadie le pasó un `rowGap` explícito. Un llamador
 * que pase un número (`Screens/PantallaAsientosContables.jsx` pasa `10`) vuelve al `style` inline y
 * lo sigue pisando. */
.separacion-de-filas-de-formulario {
    row-gap: var(--separacion-de-filas-de-formulario);
}

.margen-inferior-de-fila-de-formulario {
    margin-bottom: var(--separacion-de-filas-de-formulario);
}

/* La tarjeta de un formulario. Se separa con `margin-bottom` y no con el `row-gap` de su fila
   porque comparte esa fila con los campos sueltos, que van pegados: un `row-gap` no distingue
   entre un hermano tarjeta y un hermano campo. La última no arrastra margen sobrante. */
.tarjeta-de-formulario {
    margin-bottom: var(--separacion-entre-tarjetas-de-formulario);
}

.tarjeta-de-formulario:last-child {
    margin-bottom: 0;
}

/* LA MARCA DE ERRORES EN EL TÍTULO DE UNA SOLAPA — spec-20261015-001-lucayuvdev (AC4, AC5, AC17).
 *
 * La emite `Common/FormConValidacionRenderInputs.jsx` cuando la solapa tiene campos con error: un
 * número al lado del título, para que el usuario sepa en qué solapa está lo que le traba el botón.
 * Va en esta hoja y no en `resources/css/EstilosAbm.css` porque el formulario se monta también en el
 * login, en el cambio de clave y en los modales, y esta es la hoja que llega a todos ellos.
 *
 * Color SÓLO con tokens de `tokensDeDiseno.css`, y es el par que esa hoja ya diseñó para leerse
 * junto en los dos temas: fondo `--danger-tint` y texto `--danger-text`. Ningún literal: con un
 * color escrito acá la marca no seguiría al tema oscuro. El contraste en los dos temas no lo mide
 * Jest (jsdom no resuelve `var()` ni `oklch()`): se mira a mano en la app real (AC17). */
.marca-de-errores-de-solapa {
    display: inline-block;
    min-width: 1.5em;
    margin-left: 0.4em;
    padding: 0 0.45em;
    border-radius: 999px;
    font-size: 0.75em;
    font-weight: 600;
    line-height: 1.5;
    text-align: center;
    vertical-align: middle;
    background-color: var(--danger-tint);
    color: var(--danger-text);
}

/* ============================================================================================
 * LOS ENLACES DE FULLCALENDAR — PEDIDO DEL USUARIO (2026-09-17)
 *
 * QUÉ SE REPORTÓ: "la vista de calendario no respeta el accent, se muestra en azul bootstrap".
 *
 * QUÉ SE MIDIÓ, EN LA PANTALLA REAL. El color computado de un número de día era
 * `rgb(13, 110, 253)`, que es el `#0d6efd` de Bootstrap. Los botones, los eventos y el punto del
 * evento SÍ estaban en el acento del tenant (`#d195f9` medido en los tres): el tema de
 * `resources/css/FullCalendarTema.css` funciona. Lo que no seguía al tema eran los números de día
 * y los nombres de los días de la semana, porque FullCalendar los emite como `<a>` y no les asigna
 * color: los pintaba el default de enlace del documento.
 *
 * POR QUÉ NO VA EN `FullCalendarTema.css`, que sería su casa natural: esa hoja tiene un contrato
 * explícito y vigilado —`hojasCustomSinLiteralesNeutros.test.js` AC11 exige que sea UNA sola regla
 * `.fc` cuyas declaraciones sean SÓLO custom properties—, y un color de enlace necesita una
 * propiedad real. Meterlo ahí obligaba a renegociar ese AC.
 *
 * POR QUÉ ACÁ Y NO EN LA HOJA DE CADA PANTALLA: son DOS los consumidores del calendario
 * (`CRM/Calendario.jsx` y `OrdenesDeProduccion/CalendarioProcesos.jsx`) y cada uno tiene su propia
 * hoja. Escribirlo en las dos sería la misma decisión en dos lugares. Esta hoja la sirve el layout
 * autenticado, que es donde viven las dos pantallas, y ya declara 32 reglas de color con token.
 *
 * EL SUBRAYADO SE VA CON EL COLOR: el default de Bootstrap también los subraya, y un número de día
 * subrayado se lee como un enlace a otra página, que no es lo que hace. El `:hover` sí lo trae de
 * vuelta junto con el acento, que es donde el enlace sí quiere avisar que es clickeable.
 * ============================================================================================ */
.fc a {
    color: var(--text);
    text-decoration: none;
}

.fc a:hover {
    color: var(--accent);
    text-decoration: underline;
}

/* Los días que no son del mes mostrado ya vienen atenuados por la opacidad de FullCalendar; el
   token de texto apagado los deja coherentes con el resto de la aplicación en los dos temas. */
.fc .fc-day-other a {
    color: var(--text-muted);
}

/* ============================================================================================
 * LAS CUATRO SUPERFICIES QUE REEMPLAZAN A LAS UTILIDADES CIEGAS AL TEMA
 * PEDIDO DEL USUARIO (2026-09-17)
 *
 * QUÉ SE REPORTÓ: "falta modo oscuro en algunas cards. Resolver este problema de forma general.
 * Igual que el de aplicar la identidad con el accent elegido y aplacar los colores saturados".
 *
 * QUÉ SE MIDIÓ, CON EL TEMA OSCURO PUESTO EN LA PANTALLA REAL (Clientes Potenciales → Tablero):
 * el panel de las tarjetas computaba `rgb(255, 255, 255)` y los avatares `rgb(13, 110, 253)`. No
 * eran hex escritos por nosotros: eran `bg-white` y `bg-primary`, utilidades de Bootstrap.
 *
 * POR QUÉ NO SE ARREGLA EN LA CAPA TOKENIZADA, que sería lo primero que uno intenta. El encabezado
 * de `public/css/bootstrapTokenizado.css` § "LÍMITE MEDIDO Y DECLARADO" ya tenía este problema
 * analizado y devuelto como deuda: Bootstrap escribe sus utilidades con `!important` y compone su
 * color como `rgba(var(--bs-<x>-rgb), …)`, que espera un TRIPLETE; los tokens de este proyecto son
 * `oklch()` y no se convierten a triplete de forma estática. Esa nota deja dos salidas —duplicar
 * cada token como triplete, o volver a usar `!important` en esa capa— y dice que ninguna estaba
 * declarada por un AC, así que no se inventó ninguna.
 *
 * ESTA ES UNA TERCERA SALIDA, y es la que no paga ninguno de esos dos costos: **dejar de pedirle a
 * Bootstrap un color fijo**. Las utilidades siguen existiendo para quien las quiera; lo que cambia
 * es que NUESTRO marcado pide una superficie del proyecto. No duplica ningún token (cada color
 * sigue teniendo un solo hogar), no reintroduce `!important`, no renegocia AC2/AC8 de esa hoja, y
 * ataca la causa en vez del síntoma: el problema nunca fue que Bootstrap pintara de blanco, fue
 * que le pedíamos blanco cuando queríamos "la superficie de una tarjeta".
 *
 * El alcance es acotado y medido: 9 `bg-white`, 2 `bg-light` (los `text-bg-light` son otra cosa y
 * ya los cubre la capa tokenizada), 4 `bg-primary` y 1 `text-dark` en JSX propio.
 * ============================================================================================ */
.superficie {
    background-color: var(--surface);
}

.superficie-suave {
    background-color: var(--border-soft);
}

.fondo-acento {
    background-color: var(--accent);
}

.texto-principal {
    color: var(--text);
}

/* spec-20260908-002-lucayuvdev (AC5b): reemplaza al `.container` de Bootstrap que
   `Screens/PantallaCargando.jsx` y `Screens/PantallaErrorTenant.jsx` traían en su nodo raíz. Mismo
   procedimiento que `.formulario-de-acceso` (más abajo en este archivo) ya aplicó para `PantallaLogin`.

   POR QUÉ NO SIMPLEMENTE SACARLES LA CLASE, como sí se hace con las otras tres pantallas de esta
   spec: `.container` a secas no aporta sólo los 15px de padding horizontal que el pedido quiere
   eliminar, aporta además `max-width` + márgenes automáticos. Estas dos son pantallas de MENSAJE del
   sistema (el anillo de carga y el aviso de tenant inexistente), donde estirarse hasta el borde en un
   monitor ancho es un empeoramiento y no el pedido — decisión humana registrada en el gate del paso 3.

   POR QUÉ 1140px: es exactamente el `max-width` que Bootstrap le da hoy a `.container` en su
   breakpoint más ancho (`public/bootstrap/css/bootstrap.min.css`, `@media (min-width: 1200px)`), o
   sea el ancho que estas dos pantallas YA tienen en un monitor grande. El AC pide conservar el ancho
   máximo, así que el número se hereda del que había en vez de elegirse por gusto. Se declara UNO solo
   y sin `@media`, en vez de replicar los cuatro escalones de Bootstrap (540/720/960/1140): por debajo
   de 1140px el bloque ocupa el ancho disponible sin saltos, que para una pantalla de mensaje es mejor
   que la escalera y no pierde nada de lo que el AC pide.

   SIN `padding-left`/`padding-right` A PROPÓSITO: reintroducirlos acá sería volver a poner, con otro
   nombre, los mismos 15px que se le sacan a la utilidad de Bootstrap, y el hogar del padding
   horizontal dejaría de ser único (`.page-wrapper .page-content > div`, arriba). */
.bloque-centrado {
    max-width: 1140px;
    margin-left: auto;
    margin-right: auto;
}

/*------scroll bar---------------------*/

::-webkit-scrollbar {
    width: 5px;
    height: 7px;
}
::-webkit-scrollbar-button {
    width: 0px;
    height: 0px;
}
::-webkit-scrollbar-thumb {
    background: #525965;
    border: 0px none #ffffff;
    border-radius: 0px;
}
::-webkit-scrollbar-thumb:hover {
    background: #525965;
}
::-webkit-scrollbar-thumb:active {
    background: #525965;
}
::-webkit-scrollbar-track {
    background: transparent;
    border: 0px none #ffffff;
    border-radius: 50px;
}
::-webkit-scrollbar-track:hover {
    background: transparent;
}
::-webkit-scrollbar-track:active {
    background: transparent;
}
::-webkit-scrollbar-corner {
    background: transparent;
}

/*=============================================================================================
 * spec-20260902-002-lucayuvdev — EL SHELL, PORTADO DEL CANVAS DE DISEÑO.
 *
 * ACÁ ESTABA EL BLOQUE `.chiller-theme`, Y SE FUE ENTERO. Eran ~90 líneas de color escrito a mano
 * (`#31353d`, `#818896`, `#16c7ff`, …) que fijaban UN tema oscuro fijo, sin forma de conmutar y sin
 * relación con el acento del tenant. Lo reemplaza esta sección, que no declara un solo color
 * literal: todo sale de los custom properties de `public/css/tokensDeDiseno.css`, que valen distinto
 * según el `<body>` lleve o no la clase `tema-oscuro` (AC8 de aquella spec; spec-20260904-005 AC1
 * mudó el portador de la clase del `.page-wrapper` al `<body>` para que los portales de
 * `document.body` la hereden). La clase `chiller-theme` sigue en el marcado —tiene tests vivos que
 * la usan como ancestro— pero ya no decide ningún color.
 *
 * POR QUÉ EL SHELL SE ESTILIZA ACÁ Y NO EN LA HOJA DE TOKENS: `tokensDeDiseno.css` contiene
 * EXCLUSIVAMENTE los 40 custom properties de color (AC1), y una regla de `.sidebar-wrapper` con su
 * `padding` no es un token, es la aplicación de uno. Los dos archivos se separan por tipo de regla,
 * no por tema.
 *
 * LO QUE ESTA SECCIÓN NO TOCA, y está unas líneas más arriba en este mismo archivo: la geometría de
 * layout que AC17 protege —`body{font-size}`, `.page-wrapper .page-content`, las dos `@media` de
 * sidebar y el override de 1921px—. `research-20260902-002` midió que tienen dependientes reales y
 * masivos (el offset que evita que el sidebar fijo tape el contenido en desktop; el tamaño de celda
 * que heredan `TablaGenerica`, `TablaAbm` y `TablaReporte`) y que el canvas no trae reemplazo para
 * ninguna, porque usa otro paradigma de layout.
 *=============================================================================================*/

/*----------------------------- el fondo y el texto del shell -----------------------------*/

/* El fondo y el texto del shell salen de los tokens, así que ninguna regla de acá depende de qué
   tema esté puesto: los `var()` ya valen distinto según el alcance.

   VA SOBRE EL `.page-wrapper` Y NO SOBRE EL `body`, Y SIGUE SIENDO A PROPÓSITO aunque desde
   spec-20260904-005 (AC1) sea el `<body>` el que lleva la clase `tema-oscuro`: el `body` del login
   trae el degradado del tenant, que es otra decisión de marca y no se toca. Que el portador de la
   clase y el nodo que pinta el fondo sean distintos no rompe nada — los custom properties heredan,
   así que `var(--bg)` acá resuelve al valor del tema que declaró el `<body>`; el lienzo del `<body>`
   propiamente dicho lo cubre `color-scheme` (`tokensDeDiseno.css`, AC5). */
.page-wrapper {
    background: var(--bg);
    color: var(--text);
}

/*-------------------------------- el armazón del sidebar ---------------------------------*/

.sidebar-wrapper {
    display: flex;
    flex-direction: column;
    background: var(--surface);
    border-right: 1px solid var(--border);
    color: var(--text);
    font-family: var(--font-cuerpo);
}

/* El contenido crece y el pie queda abajo por FLEXBOX y no por `position: absolute` + una altura
   calculada a mano. El pie del canvas tiene dos renglones (nombre y rol) más los controles, así que
   los 30px que el layout anterior le reservaba dejaron de alcanzar; con flex, cuánto mide el pie
   deja de ser un número que hay que mantener sincronizado en dos lugares. */
.sidebar-content {
    flex: 1 1 auto;
    height: auto;
    max-height: none;
    min-height: 0;
}

/*
 * Feedback del 2026-09-04 — la scrollbar de ESTA zona no se ve, aunque el contenido siga scrolleable
 * con rueda/touch/teclado. Scopeado a `.sidebar-content` a propósito: la regla global
 * `::-webkit-scrollbar` de más abajo (`------scroll bar------`) sigue pintando la scrollbar fina en
 * el resto de la aplicación (tablas, modales, etc.) — esto no la reemplaza, la esconde sólo acá.
 */
.sidebar-content {
    scrollbar-width: none; /* Firefox */
    -ms-overflow-style: none; /* Edge legacy / IE */
}

.sidebar-content::-webkit-scrollbar {
    display: none; /* Chrome, Safari, Edge Chromium */
}

/*----------------------------------- marca y cabecera ------------------------------------*/

.sidebar-wrapper .sidebar-brand {
    gap: 10px;
    padding: 14px 16px;
    border-bottom: 1px solid var(--border-soft);
}

.sidebar-wrapper .sidebar-brand .marca-logotipo {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border-radius: 9px;
    overflow: hidden;
    /* spec-20260908-002-lucayuvdev (AC1): el fondo deja de pintar el color de acento del tenant. El
       acento es arbitrario por tenant y el logotipo que se apoya encima también lo es, así que ese
       fondo nunca garantizó contraste; `transparent` deja el logotipo directamente sobre el
       `--surface` del sidebar sin agregar una decisión de color nueva. El PNG de fallback ya es RGBA
       con alfa real (`research-20260908-002` § P5), y `border-radius` + `overflow: hidden` recortan la
       caja sin depender de que haya un color pintado detrás. */
    background: transparent;
}

.sidebar-wrapper .sidebar-brand .marca-logotipo img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
}

.sidebar-wrapper .sidebar-brand > a {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-family: var(--font-marca);
    font-weight: 800;
    font-size: 13.5px;
    letter-spacing: -0.01em;
    text-transform: none;
    color: var(--text);
}

.page-wrapper .sidebar-wrapper .sidebar-brand > a:hover {
    color: var(--accent);
}

.page-wrapper.toggled #close-sidebar {
    color: var(--text-faint);
}

.page-wrapper.toggled #close-sidebar:hover {
    color: var(--text);
}

/*-------------------------------------- el buscador --------------------------------------*/

.sidebar-wrapper .sidebar-search input.search-menu,
.sidebar-wrapper .sidebar-search .input-group-text {
    background: var(--bg);
    border-color: var(--border);
    box-shadow: none;
    color: var(--text);
    font-family: var(--font-cuerpo);
    font-size: 12.5px;
}

.sidebar-wrapper .sidebar-search input.search-menu::placeholder {
    color: var(--text-faint);
}

.sidebar-wrapper .sidebar-search input.search-menu:focus {
    border-color: var(--accent);
    box-shadow: none;
}

/*------------------------- los encabezados de sección (AC10) -----------------------------*/

/* El rótulo de agrupación del canvas (`Main.dc.html:72`). Comparte forma con el `.header-menu` que
   ya existía, así que los dos se declaran juntos: son el mismo objeto visual con dos orígenes. */
.sidebar-wrapper .sidebar-menu .header-seccion span,
.sidebar-wrapper .sidebar-menu .header-menu span {
    display: block;
    padding: 16px 18px 6px 18px;
    font-family: var(--font-marca);
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--text-faint);
}

/*
 * Feedback del 2026-09-04 — el spinner de "cargando" va AL LADO del rótulo "Menú Principal", no
 * debajo. `.header-menu span` (arriba) es `display: block` a propósito, compartido con
 * `.header-seccion span`: sin este `display: flex` en el `<li>` que lo contiene, ese `span` ocupa
 * el 100% del ancho y empuja al spinner (el `<div data-testid="menu-cargando">` que le sigue) a su
 * propia línea, debajo del texto en vez de a su lado.
 */
.sidebar-wrapper .sidebar-menu .header-menu {
    display: flex;
    align-items: center;
}

/*
 * El color del spinner es el MISMO token que el rótulo "Menú Principal" (arriba), no un blanco o
 * negro fijo. Antes de la Fase 9 (spec-20260902-002) el encabezado tenía un fondo oscuro fijo
 * (`#6c7b88`, `.chiller-theme`) y un spinner blanco se justificaba; con el tema claro/oscuro
 * tokenizado eso ya no es cierto en ningún sentido — ni blanco ni negro fijo se ven bien en los dos
 * temas. `.spinner-border` dibuja su borde con `currentColor`, así que basta con declararlo acá.
 *
 * SE USA UNA CLASE PROPIA (`.menu-cargando-spinner`) Y NO `.spinner-border` COMO SELECTOR, a
 * propósito: `SpinnerDibujableEnHojaServidaTest::reglaDeLaClaseEn()` (PHPUnit) busca "la" regla de
 * `.spinner-border` por su ÚLTIMO selector simple, sin importar los ancestros — una regla como
 * `.header-menu .spinner-border { color: … }` cuenta como esa regla igual que la real, y como
 * `mainmenu.css` se enlaza ANTES que `estilosAWA.css` (donde vive el `.spinner-border` completo,
 * con su `animation`), esa regla la taparía: el detector la encontraría primero, sin animación, y
 * reportaría el spinner como "no gira" en los tres documentos que lo hospedan. Con una clase propia
 * el color sigue aplicando (`currentColor` sobre `border`) sin interferir con esa cadena.
 */
.menu-cargando-spinner {
    color: var(--text-faint);
}

/*
 * EL SKELETON DEL MENÚ (feedback del 2026-09-04), mientras `agrupadas` todavía está vacío.
 *
 * Deliberadamente NO reusa `Common/SkeletonText.jsx`: ese componente pinta un degradé con colores
 * fijos (`#e0e0e0`/`#f5f5f5`), pensado para una vista previa puntual sobre fondo claro, y se vería
 * mal en el sidebar en tema oscuro. Acá el degradé usa `--border-soft`/`--surface`, los mismos
 * tokens que ya pintan el resto del árbol, así que el shimmer se ve bien en los dos temas sin
 * duplicar la paleta.
 */
.sidebar-wrapper .sidebar-menu .menu-skeleton-row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px var(--margen-nivel-1, 10px);
}

.sidebar-wrapper .sidebar-menu .menu-skeleton-icon,
.sidebar-wrapper .sidebar-menu .menu-skeleton-bar {
    display: block;
    flex: none;
    border-radius: 6px;
    background: linear-gradient(90deg, var(--border-soft) 25%, var(--surface) 37%, var(--border-soft) 63%);
    background-size: 400% 100%;
    animation: menu-skeleton-loading 1.4s ease infinite;
}

.sidebar-wrapper .sidebar-menu .menu-skeleton-icon {
    width: 18px;
    height: 18px;
    border-radius: 50%;
}

.sidebar-wrapper .sidebar-menu .menu-skeleton-bar {
    height: 12px;
}

@keyframes menu-skeleton-loading {
    0% {
        background-position: 100% 50%;
    }
    100% {
        background-position: 0 50%;
    }
}

/*--------------------------- el árbol de navegación (AC9) --------------------------------*/

/*
 * spec-20260903-004-lucayuvdev — LA GEOMETRÍA HORIZONTAL DEL ÁRBOL, NOMBRADA UNA SOLA VEZ.
 *
 * Estos cuatro valores ya estaban en el bloque, como literales repartidos: el margen lateral del
 * `.nivel-1`, la sangría de cada grupo y el padding lateral de una hoja. El fix de esta spec
 * necesita ARITMÉTICA entre ellos —el fondo de la hoja activa tiene que nacer y terminar donde
 * nace y termina el del `.nivel-1` que la contiene, sin mover el texto—, y con los valores
 * sueltos esa cuenta queda hecha a mano en seis números derivados (-17, -26, +7, +16, 25, 34)
 * que nadie puede mantener en sincronía: cambiar el margen del nivel 1 devolvería el bug en
 * silencio. Nombrados, la cuenta se escribe una vez y sigue al valor.
 *
 * NO SON TOKENS DE DISEÑO, y por eso no viven en `tokensDeDiseno.css`: esa hoja declara color y
 * tipografía, y su propio encabezado deja escrito que la geometría de layout se queda acá (AC17
 * de spec-20260902-002). Éstos son geometría interna de este componente, con su alcance.
 */
.sidebar-wrapper .sidebar-menu {
    /* El margen lateral del `.nivel-1`. Define la COLUMNA de toda la rama: dónde empieza y dónde
       termina cualquier fondo del árbol, en cualquiera de los tres niveles. */
    --margen-nivel-1: 10px;
    /* La sangría que agrega cada grupo respecto de su padre. La del nivel 3 es el ADICIONAL sobre
       la del nivel 2, porque así la aplica el marcado: el `nivel-3-grupo` cuelga de un `<li>` del
       `nivel-2-grupo`, no del `<li>` de la categoría. */
    --sangria-nivel-2: 27px;
    --sangria-nivel-3: 9px;
    /* Lo que separa el texto de una hoja del borde de su propia caja. */
    --padding-lateral-hoja: 8px;
    /* Feedback del 2026-09-04 — cuánto se retira el fondo de "activo"/"hover" de una hoja
       respecto de SU PROPIA guía vertical de 1px (`.nivel-2-grupo::before` / `.nivel-3-grupo::before`,
       más abajo), para no solaparse con ella. El texto NO se mueve: la resta se le devuelve al
       `padding-left` de la misma fórmula (ver `.menuitem`, más abajo). */
    --separacion-guia: 5px;
}

.sidebar-wrapper .sidebar-menu ul li a {
    color: var(--text-muted);
    border-radius: 8px;
}

.sidebar-wrapper .sidebar-menu ul li a i {
    background: none;
    color: var(--text-faint);
}

/*
 * NIVEL 1 — ícono propio, rótulo en la tipografía de marca.
 *
 * spec-20261019-001-estefano99 (AC18): `.sidebar-inicio` (el acceso fijo a Inicio) se suma como
 * alternativa de selector en estas cuatro reglas para verse, pasarse y activarse igual que el título
 * de una categoría. No lleva `sidebar-dropdown` a propósito: así no hereda la flechita del acordeón.
 */
.sidebar-wrapper .sidebar-menu .sidebar-dropdown > .nivel-1,
.sidebar-wrapper .sidebar-menu .sidebar-inicio > .nivel-1 {
    display: flex;
    align-items: center;
    gap: 4px;
    margin: 1px var(--margen-nivel-1);
    padding: 7px 8px;
    width: auto;
    font-family: var(--font-marca);
    font-weight: 600;
    font-size: 13px;
    color: var(--text);
}

.sidebar-wrapper .sidebar-menu .sidebar-dropdown > .nivel-1:hover,
.sidebar-wrapper .sidebar-menu .sidebar-inicio > .nivel-1:hover {
    background: var(--border-soft);
}

/*
 * NIVEL 1 ACTIVO — fondo de TINTE, no acento sólido (`MenuDetail.dc.html:35`, "fondo lleno, no
 * borde lateral"). La distinción es la que sostiene toda la jerarquía: si el nivel 1 y el nivel 3
 * se pintaran igual, no habría forma de saber en qué pantalla está uno parado.
 */
.sidebar-wrapper .sidebar-menu .sidebar-dropdown.active > .nivel-1,
.sidebar-wrapper .sidebar-menu .sidebar-inicio.active > .nivel-1 {
    background: var(--accent-tint);
    color: var(--accent-tint-text);
}

.sidebar-wrapper .sidebar-menu .sidebar-dropdown.active > .nivel-1 i,
.sidebar-wrapper .sidebar-menu .sidebar-inicio.active > .nivel-1 i {
    color: var(--accent-tint-text);
}

/*
 * LAS GUÍAS VERTICALES DE 1px (`MenuDetail.dc.html:41-48`).
 *
 * La línea conecta cada rama con su padre y es un PSEUDO-ELEMENTO del contenedor de los hijos, no un
 * nodo: dibujarla con un `border-left` del propio contenedor la haría llegar hasta el borde de la
 * caja, y el canvas la corta antes del último hijo (`bottom: 8px`).
 */
/*
 * spec-20260903-004-lucayuvdev — SE FUE UN `padding-left: 14px` QUE NO PINTABA NADA.
 *
 * Estaba escrito acá pero jamás llegó a aplicarse: `… .sidebar-dropdown .sidebar-submenu ul`
 * (más arriba en este mismo archivo) declara `padding: 5px 0` con 4 clases + 1 elemento contra
 * las 3 clases de este selector, y a mayor especificidad no la salva el orden. Medido en Chrome
 * sobre el marcado real: `getComputedStyle(grupo).paddingLeft === "0px"` en los DOS grupos.
 *
 * No se borra por prolijidad: la sangría real de cada hoja es la entrada de la cuenta que alinea
 * su fondo con el del `.nivel-1`, y estos 14px fantasma ya hicieron estimar esa sangría en 41px y
 * 64px cuando de verdad es 27px y 36px. Dejarlos era dejar la trampa armada para el próximo que
 * toque la fórmula. Borrarlos no mueve un píxel —justamente porque nunca movió ninguno.
 */
.sidebar-wrapper .sidebar-menu .nivel-2-grupo,
.sidebar-wrapper .sidebar-menu .nivel-3-grupo {
    position: relative;
    margin-left: var(--sangria-nivel-2);
}

.sidebar-wrapper .sidebar-menu .nivel-2-grupo::before,
.sidebar-wrapper .sidebar-menu .nivel-3-grupo::before {
    content: "";
    position: absolute;
    width: 1px;
    top: 2px;
    bottom: 8px;
    left: 0;
    background: var(--border);
}

.sidebar-wrapper .sidebar-menu .nivel-3-grupo {
    margin-left: var(--sangria-nivel-3);
}

/* NIVELES 2 Y 3 — sin ícono propio: la jerarquía se lee por peso tipográfico y por la guía, no
   repitiendo íconos (`MenuDetail.dc.html:69`). El punto del nivel 2 es un pseudo-elemento de 8px,
   que ya vive más arriba en este archivo, no un ícono. */
.sidebar-wrapper .sidebar-menu .sidebar-dropdown .sidebar-submenu li {
    padding-left: 0;
}

.sidebar-wrapper .sidebar-menu .sidebar-dropdown .sidebar-submenu li a {
    /* Feedback del 2026-09-04 — separación vertical entre hojas consecutivas: sin este margen, el
       fondo de una hoja activa/hover queda pegado al de la siguiente, sin ningún respiro entre
       las dos. LONGHANDS a propósito y NO el shorthand `margin`: éste resetea `margin-right`/
       `margin-left` a `0`, y aunque a `.menuitem` (más abajo) no lo tocaba porque su selector es
       más específico SOLO para `margin-left`, sí pisaba en silencio el `margin-right` del subitem
       con hijos (`.sidebar-dropdown-subitem > div > a`, unas líneas más arriba), que es MENOS
       específico que esta regla y no tiene con qué ganarle a un `margin-right: 0` de acá. */
    margin-top: 1px;
    margin-bottom: 1px;
    padding: 6px var(--padding-lateral-hoja);
    font-family: var(--font-marca);
    font-weight: 600;
    font-size: 12.5px;
    color: var(--text-muted);
}


.sidebar-wrapper .sidebar-menu .sidebar-dropdown .sidebar-submenu li a:hover {
    background: var(--border-soft);
    color: var(--text);
}

.sidebar-wrapper .sidebar-menu .nivel-3-grupo li a {
    font-family: var(--font-cuerpo);
    font-weight: 400;
    font-size: 12px;
}

/*
 * EL ÚNICO ACENTO SÓLIDO DE TODA LA RAMA: la hoja activa (`MenuDetail.dc.html:50`).
 *
 * Va con más especificidad que el color de toda hoja del menú, y después, porque si no no se vería
 * — es la misma razón por la que la regla que reemplaza (`… a.menuitem.active { color: #5ecbeb }`,
 * spec-20260826-003 AC2) estaba escrita al final del bloque anterior.
 */
.sidebar-wrapper .sidebar-menu ul li .menuitem.active {
    background: var(--accent);
    color: #ffffff;
    font-weight: 600;
}

.sidebar-wrapper .sidebar-menu ul li .menuitem.active::before {
    color: #ffffff;
}

/*
 * spec-20260903-004-lucayuvdev — EL FONDO DE UNA HOJA LLEGA A LA COLUMNA DEL `.nivel-1`, Y EL
 * TEXTO NO SE MUEVE.
 *
 * ============================================================================================
 * EL BUG, MEDIDO EN CHROME SOBRE EL MARCADO REAL (sidebar de 260px, contenido de 254px)
 *
 *   .nivel-1 (el fondo de tinte de la categoría)   x=10   borde derecho=244   ancho=234
 *   hoja de nivel 2 activa (acento sólido)         x=27   borde derecho=254   ancho=227
 *   hoja de nivel 3 activa (acento sólido)         x=36   borde derecho=254   ancho=218
 *
 *   La marca de "activo" nacía DENTRO de la caja del nivel 1 (17px o 26px más adentro, según la
 *   profundidad) y terminaba 10px MÁS AFUERA: más angosta y corrida a la derecha, que es
 *   exactamente lo que reportó el hallazgo 2b de la review de spec-20260902-002.
 *
 *   Y son DOS profundidades, no una: `Sidebar.jsx::renderizarSubitem` cuelga una hoja sin submenú
 *   directo del `nivel-2-grupo` (sangría 27px) y una hoja con padre del `nivel-3-grupo` (27+9).
 *   Un offset fijo calculado para una arregla esa y corre la otra en la diferencia.
 *
 * ============================================================================================
 * LA CUENTA, QUE ES LA MISMA PARA LAS DOS PROFUNDIDADES
 *
 *   Sea `S` la sangría acumulada de la hoja (27px en el nivel 2, 27+9 en el nivel 3) y `M` el
 *   margen lateral del `.nivel-1`. La caja de la hoja mide `100%` = (ancho del `<li>` de la
 *   categoría) − S, así que la fórmula ORIGINAL de esta spec era:
 *
 *     margin-left : M − S          -> el borde izquierdo aterriza en M, el del `.nivel-1`
 *     width       : 100% + S − 2M  -> el ancho queda en (ancho del `<li>`) − 2M, el del `.nivel-1`
 *     padding-left: S − M + padding propio  -> el TEXTO no se entera: la caja creció hacia la
 *                                              izquierda exactamente lo que el padding devuelve
 *
 * ============================================================================================
 * ENMIENDA del 2026-09-04 (feedback de usuario) — EL BORDE IZQUIERDO YA NO APUNTA A `M`
 *
 *   La fórmula de arriba hace nacer el fondo EXACTAMENTE en `M` (10px, la misma columna del
 *   `.nivel-1`) — y esa columna está a la IZQUIERDA de `S` (27px o 36px), que es donde vive la
 *   guía vertical de 1px de ESTA hoja (`.nivel-2-grupo::before` / `.nivel-3-grupo::before`, más
 *   arriba). Con el borde izquierdo en `M < S`, la guía queda ADENTRO del rango que el fondo
 *   cubre (`M` a `M + ancho`) sin importar cuánto se corra ese borde hacia la derecha — un primer
 *   intento de esta misma enmienda corrió el borde +5px y el problema seguía igual, porque seguía
 *   siendo menor que `S`. La única forma de que el fondo NO tape la guía es que su borde izquierdo
 *   quede a la DERECHA de `S`, no a la izquierda de `M`.
 *
 *   Se abandona entonces "todo nivel llega a la misma columna que el `.nivel-1`" (el objetivo
 *   original de esta spec) a favor de "cada hoja se queda a `--separacion-guia` de SU PROPIA
 *   guía", que es lo que el usuario pidió: `la línea que le corresponde`, en singular por hoja, no
 *   una columna compartida entre niveles. La cuenta nueva, mucho más simple porque ya no depende
 *   de `S` en absoluto (se cancela):
 *
 *     margin-left : separación                    -> el borde izquierdo aterriza en `S + separación`
 *     width       : 100% − M − separación         -> el borde derecho SIGUE en `100% − M` (sin cambios)
 *     padding-left: padding propio − separación   -> el TEXTO tampoco se mueve de donde estaba
 *
 *   El borde DERECHO no se toca — sigue siendo el de `.nivel-1` (`100% − M`), que es lo que el
 *   usuario confirmó que ya estaba bien. `--sangria-acumulada` deja de hacer falta del todo con
 *   esta cuenta —ni el fondo de la hoja ni el panel del nivel 3 (ver la nota de `.toggle` más
 *   abajo) la necesitan ya— así que esta enmienda la borra en vez de dejarla declarada sin uso.
 *
 * ============================================================================================
 * POR QUÉ SE LE CAMBIA LA CAJA A LA HOJA Y NO SE LE PINTA UN PSEUDO-ELEMENTO ENCIMA
 *
 *   La otra vía era un `::after` absoluto desbordado. Se descartó por dos razones, y ninguna es
 *   estética: (1) `.menuitem` ya tiene su `::before` ocupado por el bullet-dot y el guard de AC4
 *   resuelve la cascada de los pseudo-elementos de la hoja sin distinguir `::before` de `::after`,
 *   así que cualquier `content:` nuevo ahí le gana al glifo y pone la suite en rojo; (2) un fondo
 *   pintado por un pseudo con `z-index: -1` depende del contexto de apilamiento de tres ancestros
 *   —frágil— y el `overflow: hidden` de los paneles del acordeón lo recorta igual.
 *
 * ============================================================================================
 * POR QUÉ APLICA A TODA HOJA Y NO SÓLO A LA ACTIVA
 *
 *   Porque si sólo la activa cambiara de caja, cambiaría también su ANCHO DE TEXTO (10px menos, el
 *   borde derecho se retrae de 254 a 244), y hay rótulos de 54 caracteres en
 *   `config/menuitems.php` que ya envuelven en dos líneas: la fila crecería o se encogería una
 *   línea al navegar a ella. Con la caja igual para toda hoja, el ancho de texto es el mismo
 *   activa o no, y lo único que cambia con `.active` es el color del fondo —que es lo que la spec
 *   pide. De paso, los tres anchos de resaltado que había (27, 36 y 27) pasan a ser uno.
 *
 *   La fila de un subitem CON submenú (`.sidebar-dropdown-subitem > div > a`, sin la clase
 *   `menuitem`) SÍ se retrae: su `:after` —la flechita— está anclado con `right: 15px` a esa caja,
 *   y el pedido fue justamente que termine en el mismo borde derecho que el `.nivel-1`. Desde la
 *   enmienda del 2026-09-10 se retrae con ESTA MISMA fórmula (es el segundo selector de la regla de
 *   acá abajo), no con una regla propia — ver la nota de esa regla.
 */
/*
 * ENMIENDA del 2026-09-04 (feedback de usuario) — EL FONDO YA NO APUNTA A LA COLUMNA DEL
 * `.nivel-1`, SE QUEDA A `--separacion-guia` DE SU PROPIA GUÍA.
 *
 * La cuenta ya NO depende de `S` (la sangría acumulada: 27px en el nivel 2, 27+9 en el nivel 3):
 * se cancela sola en la derivación (ver el bloque grande de arriba, "ENMIENDA del 2026-09-04").
 * Por eso `.nivel-2-grupo`/`.nivel-3-grupo` ya no necesitan declarar `--sangria-acumulada` — se
 * borraron con esta misma enmienda, ver la nota de esa clase más arriba en este archivo.
 *
 *     margin-left : separación                  -> el borde izquierdo aterriza en `S + separación`
 *     width       : 100% − M − separación       -> el borde derecho sigue en `100% − M` (sin cambios)
 *     padding-left: padding propio − separación -> el texto tampoco se mueve
 *
 * ENMIENDA del 2026-09-10 (spec-20260910-001-lucayuvdev, AC1/AC2/AC2-bis) — EL SEGUNDO SELECTOR:
 * LA FILA-TÍTULO DEL SUBITEM CON HIJOS ENTRA A LA MISMA FÓRMULA, NO A UNA COPIA.
 *
 *   El `<a>` de un subitem CON submenú (`renderizarSubitem`, `Sidebar.jsx:546`) NO lleva la clase
 *   `menuitem` —la lleva sólo la hoja—, así que el primer selector nunca lo alcanzaba: quedaba con
 *   `margin-left` inicial (0) y su fondo nacía pegado a la guía, mientras el de su hermana sin
 *   hijos nacía a `--separacion-guia`. Se lo agrega por su lugar en el árbol
 *   (`li.sidebar-dropdown-subitem > div > a`) y no por una clase, porque `.menuitem` traería además
 *   el bullet-dot `::before` que esta fila no tiene ni debe tener.
 *
 *   POR QUÉ ACÁ Y NO EN SU PROPIA REGLA (Q2, un solo hogar): la geometría de esta fila es la MISMA
 *   cuenta que la de la hoja, con las mismas dos variables. Escrita dos veces, cambiar la
 *   separación serían dos ediciones y el `width` del subitem lo decidiría el orden de aparición en
 *   el archivo (había dos reglas peleándolo). Por eso la regla de `.sidebar-dropdown-subitem > div
 *   > a` que vivía más arriba en este archivo —la de la enmienda del 2026-09-04, que declaraba sólo
 *   `width: calc(100% − M)`— se borró en la misma enmienda: sin su `width` no le quedaba nada.
 */
.sidebar-wrapper .sidebar-menu .sidebar-dropdown .sidebar-submenu li > .menuitem,
.sidebar-wrapper .sidebar-menu .sidebar-dropdown .sidebar-submenu li.sidebar-dropdown-subitem > div > a {
    margin-left: var(--separacion-guia);
    width: calc(100% - var(--margen-nivel-1) - var(--separacion-guia));
}

/*
 * EL PANEL DEL NIVEL 3 YA NO NECESITA ENSANCHARSE (revertido por la enmienda del 2026-09-04).
 *
 * `.toggle` es el panel que colapsa el acordeón del nivel 2 (`max-height: 0` + `overflow: hidden`,
 * más arriba en este archivo). `spec-20260903-004` le agregaba margen/padding acá porque el fondo
 * de la hoja de nivel 3 (arriba) se extendía hacia la IZQUIERDA más allá de su propio `<li>`, y ese
 * `overflow` se lo recortaba. Con la fórmula nueva el fondo ya no se extiende hacia la izquierda
 * —al contrario, se retira un poco (`--separacion-guia`) de su borde natural—, así que no hay nada
 * que ensanchar: el panel vuelve a su tamaño normal, sin margin-left ni padding-left propios.
 */

/*----------------------------------- el pie del sidebar ----------------------------------*/

.sidebar-footer {
    position: static;
    flex: none;
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 12px;
    background: var(--surface);
    border-top: 1px solid var(--border-soft);
    box-shadow: none;
}

.sidebar-footer .pie-usuario {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    align-items: center;
    gap: 10px;
    cursor: pointer;
}

.sidebar-footer .avatar-iniciales {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    border-radius: 9px;
    background: var(--accent-tint);
    color: var(--accent-tint-text);
    font-family: var(--font-marca);
    font-weight: 700;
    font-size: 12px;
}

.sidebar-footer .pie-usuario-texto {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.sidebar-footer .pie-usuario-texto .user-name {
    font-family: var(--font-marca);
    font-weight: 700;
    font-size: 12.5px;
    color: var(--text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.sidebar-footer .pie-usuario-texto .user-role {
    font-size: 11px;
    color: var(--text-faint);
}

.sidebar-footer .pie-controles {
    flex: none;
    display: flex;
    align-items: center;
    gap: 2px;
}

.sidebar-footer > a,
.sidebar-footer .control-de-pie {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 7px;
    line-height: normal;
    color: var(--text-faint);
}

.sidebar-footer .control-de-pie:hover {
    background: var(--border-soft);
    color: var(--text);
}

/*------------------------------- el formulario de acceso ---------------------------------*/

/* spec-20260902-002-lucayuvdev (AC12): reemplaza al `.container` de Bootstrap que `PantallaLogin`
   traía. Ver el motivo en el propio componente. */
.formulario-de-acceso {
    width: 100%;
    font-family: var(--font-cuerpo);
}

.formulario-de-acceso h5 {
    font-family: var(--font-marca);
    font-weight: 800;
    font-size: 18px;
    letter-spacing: -0.01em;
    color: var(--text);
}

.formulario-de-acceso hr {
    border-top-color: var(--border);
}

/*------------------------- las cuatro piezas sin artboard (AC15) -------------------------*/

/* Ninguna de estas cuatro tiene diseño de referencia (P6 del refinamiento): el criterio no es
   fidelidad pixel-a-pixel sino que se lean del mismo sistema de color que el resto. */
#modalConfirmarLogout .modal-content {
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 12px;
}

#modalConfirmarLogout .modal-header,
#modalConfirmarLogout .modal-footer {
    border-color: var(--border-soft);
}

#modalConfirmarLogout .modal-title {
    font-family: var(--font-marca);
    font-weight: 700;
    font-size: 15px;
}

#modalConfirmarLogout .btn-danger {
    background: var(--danger);
    border-color: var(--danger);
}

#modalConfirmarLogout .btn-secondary {
    background: var(--border-soft);
    border-color: var(--border);
    color: var(--text);
}

#mensajeAjax #mensajeAjax_clase {
    background: var(--surface);
    color: var(--text);
    border: 1px solid var(--border);
    border-radius: 8px;
}

/* Las ocho barras del preloader. El selector lleva `.middle` porque `public/css/preloader.css`
   declara `.bar` a secas y hace falta ganarle por especificidad —el orden de los `<link>` no
   alcanza, esa hoja va después—, y porque así cubre a la vez el preloader del layout autenticado
   (`#cargandoutilidad`) y el que el acceso pinta dentro de la tarjeta. */
.middle .bar {
    background: var(--accent);
}

/* El verde de marca de WhatsApp NO se retematiza: es la identidad de un servicio ajeno y cambiarlo
   lo volvería irreconocible. Lo único que se ajusta es que tenga contraste contra el fondo del
   tema. */
#iconowhatsapp {
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.25);
}

/* ============================================================================================
 * LA CANALETA DE UNA COLUMNA QUE NO CUELGA DE UNA `.row`
 * PEDIDO DEL USUARIO (2026-09-17) — "el input de país provincia localidad desborda el padding
 * del formulario".
 *
 * RUPTURA DE BOOTSTRAP 4 -> 5, medida en la pantalla real. En Bootstrap 4 el padding de canaleta
 * lo declaraba la propia clase `.col-*`. En Bootstrap 5 se mudó a `.row > *`, un selector de HIJO
 * DIRECTO: una `.col-*` que cuelga de un `d-flex` en vez de una `.row` no recibe padding ninguno.
 *
 * `Common/ABM/MultiInputConModalBase.jsx` hace exactamente eso con sus dos columnas (la de los
 * campos y la de los botones), y adentro de la primera hay una `.row` cuyo `margin: 0 -12px` no
 * tenía qué cancelar: la fila salía 12px a cada lado — 557px dentro de un padre de 533, medido.
 *
 * Esta clase devuelve la canaleta que Bootstrap 4 daba. No se usa `px-3` de Bootstrap porque ese
 * valor es fijo (1rem) y la canaleta es `--bs-gutter-x` (1.5rem por defecto, y configurable por
 * `.row`): tomarla de la variable es lo que mantiene la columna consistente con las de al lado si
 * alguien cambia la canaleta del formulario.
 * ============================================================================================ */
.canaleta-de-columna-suelta {
    padding-right: calc(var(--bs-gutter-x, 1.5rem) * 0.5);
    padding-left: calc(var(--bs-gutter-x, 1.5rem) * 0.5);
}

/* ============================================================================================
   spec-20260929-001-lucayuvdev (AC16/AC17/AC20) — EL INDICADOR DE VERSION DEL SIDEBAR.

   VIVE EN ESTA HOJA, con el resto del sidebar, y no en una hoja del bundle: el sidebar se pinta
   apenas llega el documento y una hoja que entra por style-loader llega despues del primer cuadro.

   UN SOLO ESTADO SE MARCA, y ahora se marca en VERDE. Los otros dos siguen sin marcarse: un
   indicador que grita "todo bien" compite por atencion con lo que la persona esta haciendo, y lo
   que hay que ver de reojo es la diferencia.

   POR QUE VERDE Y NO AMBAR (decision del decisor, 2026-09-30). El ambar decia "algo anda mal con
   tu pantalla" y ponia al usuario a la defensiva por un hecho que, en la practica, casi siempre es
   una buena noticia: salio una version nueva. El estado pasa a contarse como lo que la persona
   puede hacer —verla— en vez de como un defecto.

   LO QUE SE PIERDE, DECLARADO: `difiere` tambien cubre el caso en que el navegador quedo con bytes
   raros por un despliegue a medias, y ese caso ya no lo señala ningun color. Se lo lleva el boton
   de reportar, que es el camino por el que esa persona escala el problema.

   El color sale del token del tema (`--success`), asi que sigue al tenant como cualquier otro.
   ============================================================================================ */
.indicador-de-version {
    padding: 0 12px 6px;
    font-size: 11px;
    position: relative;
}

/* spec-20261008-001-lucayuvdev — EL DISPARADOR ES UN ICONO, a pedido del usuario.
   Se fue la caja con borde y el `vX.Y.Z` en monospace, y con ellos la regla del `<span>` que lo
   pintaba, que quedaba sin sujeto. El `border: none` de abajo no es la caja: es lo que le quita al
   `<button>` nativo el borde que trae de fabrica. La fila sigue ocupando el ancho del sidebar —el panel se ancla a ella con
   `left: 8px; right: 8px`, y una fila que encogiera a 28px lo dejaria en 12px de ancho—; lo que se
   alinea a la derecha es el CONTENIDO del boton, para que el icono caiga en la columna de los
   controles del pie (la fila y `.sidebar-footer` comparten los 12px de padding lateral). */
.indicador-de-version__boton {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    padding: 0;
    background: none;
    border: none;
    color: var(--text-muted);
    cursor: pointer;
}

.indicador-de-version__boton--difiere {
    color: var(--success);
}

/* EL ICONO MIDE UN CONTROL DEL PIE: 28x28, el mismo radio y el mismo color tenue que
   `.sidebar-footer .control-de-pie`. Se declara aca y no se reusa esa clase porque su selector
   cuelga de `.sidebar-footer`, y este boton es HERMANO del pie, no hijo.
   El glifo es un `<svg>` de 16x16 con trazo `currentColor` (seguimiento post-PR del 2026-10-08,
   antes `fas fa-download`): toma el `color` de aca y su tamaño no depende del `font-size`, asi que
   el `font-size: 0.9rem` que igualaba el glifo de Font Awesome con los del pie se fue sin sujeto. */
.indicador-de-version__icono {
    position: relative;
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 7px;
    color: var(--text-faint);
}

.indicador-de-version__boton:hover .indicador-de-version__icono {
    background: var(--border-soft);
    color: var(--text);
}

/* EL PUNTO DE ACENTO, solo en `difiere` (el componente lo pinta solo en ese estado). Arriba a la
   derecha del glifo, sin salirse del control.
   EL COLOR ES `var(--accent)` Y NO UN LITERAL: es el token que el tenant pisa (`--accent-light`
   sobre `<html>`) y que cambia con el tema oscuro. El anillo de `--surface` lo despega del glifo y
   del fondo en los dos temas sin escribir ningun color fijo. */
.indicador-de-version__punto {
    position: absolute;
    top: 4px;
    right: 4px;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 0 2px var(--surface);
}

/* LAS DOS LINEAS DEL AVISO. Van en bloque y no en linea porque son dos frases con jerarquia
   distinta: la primera es el hecho, la segunda es que hacer con el. En una sola linea el cartelito
   —que mide el ancho del sidebar— las parte donde caiga.
   `align-items: flex-end` las pega al icono, que esta a su derecha: es lo que antes hacia el
   `text-align: right` del boton, que se fue con la caja. */
.indicador-de-version__aviso-de-actualizacion {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 1px;
}

.indicador-de-version__aviso-titulo {
    font-weight: bold;
}

/* Mas chica: es una invitacion, no un dato. (El `font-family: inherit` que tenia anulaba el
   monospace del boton, que se fue con la caja del `vX.Y.Z`.) */
.indicador-de-version__aviso-invitacion {
    font-size: 10px;
    text-decoration: underline;
}

/* El panel se apoya sobre el sidebar en vez de empujarlo: abrirlo no puede mover el menu que la
   persona estaba mirando.
   Queda 6px ARRIBA de la fila del icono, no pegado a ella: lo pidio el usuario probando la app
   (seguimiento post-PR de spec-20261008-001, 2026-10-08). El ancho no cambia: lo marcan `left` y
   `right`, no `bottom`. */
.indicador-de-version__panel {
    position: absolute;
    bottom: calc(100% + 6px);
    left: 8px;
    right: 8px;
    z-index: 1040;
    max-height: 60vh;
    overflow: auto;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 10px;
    color: var(--text);
}

/* EL PANEL MUESTRA DOS PARRAFOS Y DOS BOTONES, y nada mas (decision del decisor el 2026-09-30,
   probando la app real): el detalle tecnico —las dos huellas, el bundle, el user agent, los siete
   assets con sus sellos— salio de la vista y viaja por el boton de copiar. Para un usuario final
   eso era ruido incomprensible.
   Con el se fueron las reglas de `.indicador-de-version__datos` y `.indicador-de-version__hojas`,
   que quedaban sin sujeto. */
.indicador-de-version__version {
    font-weight: 600;
    margin: 0 0 4px;
}

.indicador-de-version__estado-en-palabras {
    margin: 0 0 10px;
    color: var(--text-muted);
}

/* DOS REGLAS SE FUERON CON EL MARCADO QUE LAS USABA, las dos por decision del decisor el
   2026-09-30: `.indicador-de-version__fallidas ul` (el panel dejo de prometer la lista de archivos
   fallidos, porque cuando ese dato llega el documento ya se esta yendo) y
   `.indicador-de-version__limites` (los limites del boton salieron de la interfaz: son
   documentacion para quien mantiene la feature, no para el usuario final).
   Una regla sin sujeto es una hoja mas grande que no pinta nada, y despues nadie sabe si sobra o si
   falta el marcado. */
/* LOS DOS BOTONES OCUPAN EL ANCHO ENTERO, uno debajo del otro (pedido del decisor, 2026-09-30).

   QUE PASABA: la fila era `flex` con `flex-wrap`, asi que cada boton se dimensionaba a SU texto y,
   al no entrar los dos, el segundo caia abajo con otro ancho. Dos botones de anchos distintos, uno
   encima del otro, se leen como si tuvieran jerarquias distintas cuando la unica diferencia real
   es cuantas letras tiene cada rotulo.

   COMO: columna con `align-items: stretch` —el default del eje cruzado en una columna— en vez de
   fila que envuelve. Con eso el ancho lo fija el contenedor y no el texto, asi que los dos miden
   lo mismo y van a seguir midiendo lo mismo si manana cambia un rotulo.

   EL `gap` SE QUEDA y ahora separa verticalmente, que es lo que hace falta cuando apilan. */
.indicador-de-version__acciones {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 6px;
    margin-bottom: 8px;
}

/* SE FUE `.indicador-de-version__informe`, el <pre> que mostraba el informe para copiar a mano:
   el panel dejo de copiar al portapapeles y ahora reporta al servidor, asi que no hay ningun texto
   que la persona tenga que transcribir. Una regla sin sujeto es una hoja mas grande que no pinta
   nada, y despues nadie sabe si sobra o si falta el marcado. */
.indicador-de-version__aviso {
    margin-top: 8px;
    font-size: 11px;
    color: var(--text-muted);
}

.indicador-de-version__aviso p {
    margin: 0;
}

