/* ==========================================================================
   sistema.css — Capa base del sistema de diseño municipal · SRRH
   ==========================================================================

   PORTADO DESDE control-insumos-sssur/static/css/style.css

   ═══════════════════════════════════════════════════════════════════════════
   POR QUÉ SOLO UNA PARTE, Y NO EL ARCHIVO ENTERO
   ═══════════════════════════════════════════════════════════════════════════

   El style.css de allá trae también las clases de componente —.tarjeta, .btn,
   .campo, .chip, .tabla, .barra-inferior—. Traerlas hoy rompería cosas:

     · `.btn` existe en los dos archivos. El de allá ganaría o perdería según
       el orden de carga, y en cualquiera de los dos casos los botones de las
       17 vistas cambiarían de aspecto a medias.
     · `.modal-enter-active`, `.modal-enter-from`, `.modal-leave-active` y
       `.modal-leave-to` también están en los dos.

   El resto de sus componentes no choca porque están en español (.tarjeta vs
   .card, .campo vs .form-input, .chip vs .badge, .tabla vs .srrh-table), pero
   convivirían dos sistemas a la vez sin que nadie sepa cuál usar.

   Así que aquí va SOLO la capa base: medidas, superficies que siguen al tema,
   scrollbars, transiciones nuevas y utilidades. Los componentes llegan en la
   Fase 4, cuando las vistas se migren y sus equivalentes de main.css se
   retiren en el mismo commit.

   ═══════════════════════════════════════════════════════════════════════════
   ORDEN DE CARGA: ESTE ARCHIVO VA ANTES QUE main.css
   ═══════════════════════════════════════════════════════════════════════════

   Es deliberado. main.css sigue ganando en todo lo que ya definía, así que
   esta fase NO cambia cómo se ve nada. Lo de aquí solo rellena lo que hoy no
   está cubierto por nadie.
   ========================================================================== */


/* ── Medidas del armazón ────────────────────────────────────────────────────
   Los COLORES no viven aquí: los escribe tema/tema-store.js como variables
   --sci-* sobre <html>, y tema/theme-boot.js las reinyecta antes del primer
   pintado. Estas medidas las consumirá el armazón nuevo de la Fase 2.

   main.css ya define --sidebar-width y --topbar-height con otros valores para
   el armazón actual; estos nombres son distintos a propósito para que los dos
   puedan convivir mientras dure la migración. */
:root {
    --radio-tarjeta: 16px;
    --ancho-lateral: 290px;
    --ancho-lateral-min: 90px;
    --alto-cabecera: 68px;
}


/* ── El fondo sigue al modo ─────────────────────────────────────────────────
   Sin esto, al activar el modo oscuro el <body> se quedaría con su color
   claro y asomaría una franja por debajo del contenido. */
body {
    background-color: rgb(var(--sci-fondo, 238 241 247));
    color: rgb(var(--sci-texto-2, 71 84 103));
}

/* Quita el destello gris al tocar en móvil. */
* {
    -webkit-tap-highlight-color: transparent;
}

html {
    scroll-behavior: smooth;
}


/* ── Scrollbars discretos ───────────────────────────────────────────────── */

.scrollbar-fino::-webkit-scrollbar {
    width: 6px;
    height: 6px;
}

.scrollbar-fino::-webkit-scrollbar-track {
    background: transparent;
}

.scrollbar-fino::-webkit-scrollbar-thumb {
    background: rgb(var(--sci-texto-3, 152 162 179) / 0.45);
    border-radius: 999px;
}

.scrollbar-fino::-webkit-scrollbar-thumb:hover {
    background: rgb(var(--sci-texto-3, 152 162 179) / 0.75);
}

/* En oscuro no hace falta regla aparte: --sci-texto-3 ya cambia con el modo,
   así que el pulgar se aclara solo. */

.sin-scrollbar::-webkit-scrollbar {
    display: none;
}

.sin-scrollbar {
    -ms-overflow-style: none;
    scrollbar-width: none;
}


/* ── Transiciones de vista ──────────────────────────────────────────────────
   Se llaman `vista-*` y no `fade-*` porque main.css ya tiene .fade-* y
   .slide-up-* para el armazón actual. Los dos juegos conviven hasta la
   Fase 4. */

.vista-enter-active,
.vista-leave-active {
    transition: opacity 0.18s ease, transform 0.18s ease;
}

.vista-enter-from {
    opacity: 0;
    transform: translateY(6px);
}

.vista-leave-to {
    opacity: 0;
    transform: translateY(-4px);
}


/* ── Formularios: estados consistentes ─────────────────────────────────── */

input[type="date"]::-webkit-calendar-picker-indicator {
    cursor: pointer;
    opacity: 0.55;
}

.dark input[type="date"]::-webkit-calendar-picker-indicator {
    filter: invert(1);
    opacity: 0.5;
}

input:disabled,
select:disabled,
textarea:disabled {
    cursor: not-allowed;
    opacity: 0.6;
}

/* Oculta las flechas de los campos numéricos. */
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
    margin: 0;
    -webkit-appearance: none;
}

input[type="number"] {
    -moz-appearance: textfield;
}


/* ── Carga: esqueleto con brillo ────────────────────────────────────────────
   Para las tablas y tarjetas mientras llegan los datos. Sustituye al spinner
   centrado, que no dice nada sobre la forma de lo que viene. */

.esqueleto {
    position: relative;
    overflow: hidden;
    background: rgb(var(--sci-superficie-2, 242 244 247));
}

.esqueleto::after {
    position: absolute;
    inset: 0;
    content: "";
    background: linear-gradient(90deg, transparent, rgb(255 255 255 / 0.55), transparent);
    transform: translateX(-100%);
    animation: brillo 1.4s infinite;
}

.dark .esqueleto::after {
    background: linear-gradient(90deg, transparent, rgb(255 255 255 / 0.06), transparent);
}

@keyframes brillo {
    100% {
        transform: translateX(100%);
    }
}

/* Quien haya pedido menos animación no ve el brillo recorrer. */
@media (prefers-reduced-motion: reduce) {
    .esqueleto::after {
        animation: none;
    }
}


/* ── Utilidades puntuales ───────────────────────────────────────────────── */

/* Cifras monoespaciadas y de ancho fijo, para que los valores en USD y los
   saldos de los aportes queden alineados en columna. */
.numeros-tabulares {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
    font-variant-numeric: tabular-nums;
    letter-spacing: -0.01em;
}

.recorte-2 {
    display: -webkit-box;
    overflow: hidden;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
}

/* Foco visible en todo elemento interactivo. Sigue al color de marca del tema
   activo, así que no se queda desfasado al cambiar de tema. */
:where(a, button, input, select, textarea, [tabindex]):focus-visible {
    outline: 2px solid rgb(var(--sci-marca-solido, 0 27 160));
    outline-offset: 2px;
}


/* ══════════════════════════════════════════════════════════════════════════
   FASE 2 — ARMAZÓN
   Portado de control-insumos. Solo lo que el armazón necesita; los
   componentes de las vistas (.campo, .chip, .tabla) llegan en la Fase 4.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── Tarjeta ────────────────────────────────────────────────────────────────
   UNA TARJETA NUNCA ESTIRA A SU CONTENEDOR. Sin `min-width: 0`, una tarjeta
   dentro de una rejilla se dimensiona por su contenido: una gráfica o una
   tabla ancha empuja la columna, la columna empuja la rejilla y la página
   entera se sale de la pantalla del teléfono. Taparlo con `overflow-x-hidden`
   solo esconde la barra: el contenido sigue fuera y sin poder verse. */
.tarjeta {
    min-width: 0;
    background-color: rgb(var(--sci-superficie, 252 252 253));
    border: 1px solid rgb(var(--sci-borde-suave, 228 231 236));
    border-radius: var(--radio-tarjeta);
    box-shadow: var(--sci-sombra-xs, 0 1px 2px 0 rgba(16, 24, 40, 0.05));
}

.tarjeta-interactiva {
    transition: border-color 0.18s ease, box-shadow 0.18s ease;
}

.tarjeta-interactiva:hover {
    border-color: rgb(var(--sci-marca-300, 115 138 249));
    box-shadow: var(--sci-sombra-md, 0 4px 8px -2px rgba(16, 24, 40, 0.10));
}


/* ── Navegación del teléfono ────────────────────────────────────────────────
   `env(safe-area-inset-bottom)` es el hueco de la barra de gestos en los
   teléfonos sin botón. En todo lo demás vale cero, así que no estorba.

   Va en CSS y no como clase de Tailwind porque `pb-[env(...)]` obliga a
   escribir el valor entre corchetes en cada sitio, y basta olvidarlo una vez
   para que el fallo aparezca solo en un modelo de teléfono. */
.barra-inferior {
    padding-bottom: calc(0.5rem + env(safe-area-inset-bottom, 0px));
}

.hoja-modulos {
    padding-bottom: calc(1.25rem + env(safe-area-inset-bottom, 0px));
    max-height: 80vh;
}

/* El contenido no puede quedar debajo de la barra.
   MEDIDO, NO ESTIMADO: 8 (pt-2) + 4+4 (py-1) + 28 (icono) + 2 + 13 (rótulo)
   = 59 px, más el relleno inferior de la propia barra. Con 5.5rem sobra
   margen y la última fila de cada lista queda alcanzable. */
.con-barra-inferior {
    padding-bottom: calc(5.5rem + env(safe-area-inset-bottom, 0px));
}


/* ── Transiciones del armazón ───────────────────────────────────────────────
   Se llaman `velo` y `panel`, NO `modal`: main.css ya define .modal-enter-*
   para los diálogos de las vistas, y reutilizar ese nombre haría que el
   comportamiento dependiera del orden de carga. */

.velo-enter-active,
.velo-leave-active {
    transition: opacity 0.2s ease;
}

.velo-enter-from,
.velo-leave-to {
    opacity: 0;
}

.panel-enter-active {
    transition: opacity 0.15s ease, transform 0.15s ease;
}

.panel-enter-from {
    opacity: 0;
    transform: translateY(-6px);
}

.panel-leave-active {
    transition: opacity 0.12s ease;
}

.panel-leave-to {
    opacity: 0;
}

/* La hoja «Más» sube desde abajo. Quien pidió menos movimiento la ve aparecer
   sin el desplazamiento. */
@media (prefers-reduced-motion: reduce) {
    .animate-hoja { animation: none; }
}


/* ── Desfase de las manchas del acceso ──────────────────────────────────────
   Las tres manchas del panel de marca comparten la misma animación `blob`.
   Sin desfase arrancan a la vez y se mueven en bloque, que se lee como un
   solo fondo temblando en lugar de tres luces sueltas.

   Va aquí y no como `[animation-delay:2s]` en la plantilla: una propiedad
   arbitraria de Tailwind depende de que el generador la reconozca, y una
   clase de una línea no depende de nada. */

.retraso-2s { animation-delay: 2s; }
.retraso-4s { animation-delay: 4s; }

/* Quien pidió menos movimiento en su sistema operativo no ve las manchas
   moverse. El panel se queda quieto y con el mismo aspecto. */
@media (prefers-reduced-motion: reduce) {
    .animate-blob { animation: none; }
}


/* ══════════════════════════════════════════════════════════════════════════
   FASE 4 — CAMPOS
   Lo que necesita la biblioteca de componentes (ui-input, ui-select,
   ui-combo, ui-search). El resto de sus componentes usa utilidades de
   Tailwind directamente, asi que no hace falta nada mas.

   NO se define `.btn`: main.css ya lo tiene para las vistas sin migrar, y
   ui-btn usa utilidades puras, asi que no hay colision.
   ══════════════════════════════════════════════════════════════════════════ */

.campo {
    width: 100%;
    height: 2.75rem;
    background-color: rgb(var(--sci-campo, 255 255 255));
    border: 1px solid rgb(var(--sci-borde, 208 213 221));
    border-radius: 0.5rem;
    padding: 0 0.875rem;
    font-size: 0.875rem;
    color: rgb(var(--sci-texto, 16 24 40));
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

/* UN <select> NUNCA MÁS ANCHO QUE SU HUECO.
   Un select se dimensiona por su opción MÁS LARGA. En este sistema eso son
   los nombres completos de los departamentos, y en un teléfono estrecho
   empujan la página entera de lado.

   `min-width: 0` es la mitad importante: dentro de un contenedor flex, un
   hijo no baja de su tamaño de contenido por mucho max-width que lleve. */
select.campo {
    max-width: 100%;
    min-width: 0;
    text-overflow: ellipsis;
}

textarea.campo {
    height: auto;
    padding: 0.625rem 0.875rem;
}

.campo::placeholder {
    color: rgb(var(--sci-texto-3, 152 162 179));
}

.campo:focus {
    outline: none;
    border-color: rgb(var(--sci-marca-300, 115 138 249));
    box-shadow: 0 0 0 4px rgb(var(--sci-marca-solido, 0 27 160) / 0.12);
}

.campo:disabled {
    background-color: rgb(var(--sci-superficie-2, 242 244 247));
    opacity: 0.7;
    cursor: not-allowed;
}

.etiqueta {
    display: block;
    margin-bottom: 0.375rem;
    font-size: 0.8125rem;
    font-weight: 500;
    color: rgb(var(--sci-texto-2, 71 84 103));
}

/* Con un «?» al lado, la etiqueta no lleva su margen: lo pone la fila que
   las agrupa. Sin esto, el boton queda medio renglon mas abajo que el texto
   al que acompaña. */
.etiqueta.mb-0 { margin-bottom: 0; }


/* ══════════════════════════════════════════════════════════════════════════
   EL MANUAL DE USUARIO
   ══════════════════════════════════════════════════════════════════════════

   Portado de fiesta-empleados. Es una CAPA A PANTALLA COMPLETA y no un
   diálogo pequeño, y esa es la diferencia que lo hace usable:

   Un manual no es un sitio donde se trabaja, es un sitio donde se consulta
   algo y se vuelve. Con el menú al costado, cerrarlo era elegir otra pantalla
   del menú —que no siempre es de la que se venía—. Tapando todo, el único
   camino de vuelta es el que trajo.

   Y con el ancho completo cabe lo que hace entender: un icono grande, una
   frase corta y el índice al lado. En una caja de 600 px no cabe nada de eso
   y el manual acaba siendo un párrafo dentro de una ventana.

   Los colores salen de los tokens --sci-*, así que sigue al tema elegido. */

.manual-capa {
    position: fixed;
    inset: 0;
    z-index: 999990;
    display: flex;
    flex-direction: column;
    background-color: rgb(var(--sci-fondo));
    height: 100vh;
    height: 100dvh;
    animation: manual-entrar 260ms cubic-bezier(0.22, 1, 0.36, 1) both;
}

@keyframes manual-entrar {
    from { opacity: 0; transform: scale(.98); }
    to   { opacity: 1; transform: scale(1); }
}

.manual-encabezado {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-shrink: 0;
    padding: .75rem 1rem;
    border-bottom: 1px solid rgb(var(--sci-borde-suave));
    background-color: rgb(var(--sci-superficie));
    /* El área del sistema, en los teléfonos con muesca. */
    padding-top: calc(.75rem + env(safe-area-inset-top));
}

.manual-cuerpo {
    display: flex;
    flex: 1;
    min-height: 0;
    position: relative;
}

/* El índice: fijo al costado en pantalla ancha, cajón deslizante en angosta.
   En angosta se sale del flujo para no empujar la diapositiva. */
.manual-indice {
    position: absolute;
    inset: 0 auto 0 0;
    z-index: 20;
    width: 17rem;
    max-width: 85vw;
    padding: 1rem;
    overflow-y: auto;
    background-color: rgb(var(--sci-superficie));
    border-right: 1px solid rgb(var(--sci-borde-suave));
    transform: translateX(-100%);
    transition: transform 260ms cubic-bezier(0.22, 1, 0.36, 1);
}

.manual-indice.esta-abierto { transform: translateX(0); }

@media (min-width: 1024px) {
    .manual-indice {
        position: relative;
        inset: auto;
        transform: none;
        flex-shrink: 0;
    }
}

.manual-escenario {
    flex: 1;
    min-width: 0;
    overflow-y: auto;
    padding: 1.5rem 1rem 2rem;
    display: flex;
    align-items: flex-start;
}

@media (min-width: 640px) {
    .manual-escenario {
        padding: 2.5rem 2rem 3rem;
        align-items: center;
    }
}

.manual-pie {
    flex-shrink: 0;
    padding: .875rem 1rem;
    border-top: 1px solid rgb(var(--sci-borde-suave));
    background-color: rgb(var(--sci-superficie));
    padding-bottom: calc(.875rem + env(safe-area-inset-bottom));
}

/* Cada diapositiva entra desplazándose desde la derecha, que es de donde
   viene al avanzar. Es corta a propósito: una transición de media pantalla se
   disfruta la primera vez y estorba a partir de la tercera. */
.animar-diapositiva {
    animation: diapositiva-entrar 320ms cubic-bezier(0.22, 1, 0.36, 1) both;
}

@keyframes diapositiva-entrar {
    from { opacity: 0; transform: translateX(16px); }
    to   { opacity: 1; transform: translateX(0); }
}

@media (prefers-reduced-motion: reduce) {
    .manual-capa,
    .animar-diapositiva { animation: none; }
    .manual-indice { transition: none; }
}


/* ══════════════════════════════════════════════════════════════════════════
   LOS DIAGRAMAS DEL MANUAL
   ══════════════════════════════════════════════════════════════════════════

   Portados de fiesta-empleados. Los colores salen de los tokens --sci-*, así
   que el dibujo sigue al tema que cada persona haya elegido y se lee igual en
   claro y en oscuro sin una segunda paleta. */

.diagrama-marco {
    overflow-x: auto;
    overflow-y: hidden;
    padding-bottom: .25rem;
}

/* En horizontal el dibujo necesita su ancho: si se encoge, las etiquetas se
   pisan unas con otras. Se desplaza dentro de su marco. */
.diagrama-marco > .diagrama { min-width: 520px; }

.diagrama-marco.es-vertical { overflow-x: visible; }
.diagrama-marco.es-vertical > .diagrama {
    min-width: 0;
    max-width: 300px;
    margin: 0 auto;
}

.diagrama-circulo {
    fill: var(--tono, rgb(var(--sci-marca-500)));
    stroke: none;
}

.diagrama-numero {
    fill: #fff;
    font-size: 15px;
    font-weight: 600;
    font-family: inherit;
}

.diagrama-simbolo { font-size: 14px; }

.diagrama-etiqueta {
    fill: rgb(var(--sci-texto-2));
    font-size: 12px;
    font-family: inherit;
}

.diagrama-linea {
    stroke: rgb(var(--sci-borde));
    stroke-width: 2;
}

.diagrama-punta { fill: rgb(var(--sci-borde)); }

.diagrama-viajero {
    fill: rgb(var(--sci-marca-500));
    opacity: 0;
}

/* Los nodos aparecen en el orden en que se leen, no todos de golpe. */
.diagrama-nodo,
.diagrama-rama {
    animation: diagrama-aparecer 460ms cubic-bezier(0.22, 1, 0.36, 1) both;
    animation-delay: var(--retraso, 0s);
}

@keyframes diagrama-aparecer {
    from { opacity: 0; transform: translateY(6px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* Con el movimiento apagado el diagrama se enseña armado y quieto. El punto
   viajero se esconde desde el <style> de cada SVG, porque ahí sí se puede
   apuntar al elemento concreto. */
@media (prefers-reduced-motion: reduce) {
    .diagrama-nodo,
    .diagrama-rama { animation: none; }
}
