﻿/*
    ══════════════════════════════════════════════════════════════════════════
    PANTALLA — el formato de las pantallas de listado
    ══════════════════════════════════════════════════════════════════════════

    Una pantalla de listado de esta plataforma es siempre la misma columna:

        cabecera  →  filtros  →  indicadores  →  tabla  →  paginador

    con alto de ventana, sin desplazamiento de página y con el desplazamiento
    ocurriendo DENTRO de la tabla. Este archivo es esa columna, y es el único
    sitio donde vive.

    ── Por qué existe ────────────────────────────────────────────────────────
    El formato nació en la pantalla de facturas y se copió a la de presupuestos
    cambiándole el prefijo. Resultado: dos archivos de mil líneas diciendo casi
    lo mismo, y cada ajuste —el alto de una fila, el relleno de un botón— había
    que hacerlo dos veces y acordarse de las dos. Al extenderlo a las demás
    pantallas del sistema, ese «dos» se convertía en «quince».

    Aquí las reglas se escriben una vez con el prefijo .pan-. Cada módulo
    conserva su propia hoja sólo para lo que de verdad es suyo: los iconos de
    enlace de una factura, la cuadrícula de doce meses de un presupuesto.

    ── Cómo se usa ───────────────────────────────────────────────────────────
    El marcado lleva la clase compartida y, cuando necesita ajustar algo, añade
    también la suya:

        <div class="pan-filtros fac-filtros">

    y en facturas.css se declara únicamente lo que cambia:

        .fac-filtros { grid-template-columns: 96px 132px auto …; }

    Las dos rejillas de columnas —la de filtros y la de indicadores— son el
    único punto donde casi toda pantalla necesita decir lo suyo, porque
    dependen de cuántos controles tenga. Ambas traen un valor por defecto que
    se acomoda solo, así que una pantalla que no declare nada funciona igual.

    ── Regla de oro ──────────────────────────────────────────────────────────
    Nada de lo que se escriba aquí puede depender de una pantalla concreta. Si
    una regla lleva el nombre de un dato del negocio, va en la hoja del módulo.
*/

:root {
    /* Paleta institucional, la misma de la pantalla de carga. */
    --pan-tinta: #0C2740;
    --pan-azul: #185FA5;
    --pan-apagado: #5b7186;
    --pan-tenue: #8fa1b1;
    --pan-linea: #e6ecf2;
    --pan-papel: #ffffff;
    --pan-fondo: #f6f8fb;
    --pan-rojo: #d32f14;
    --pan-ambar: #b8541b;
    --pan-verde: #1c8a5a;
    --pan-radio: 10px;

    /*
        Altos fijos de la columna. Se declaran como variables para que la
        tarjeta de la tabla sepa cuánto espacio le queda sin medir nada en
        JavaScript. Una pantalla sin franja de indicadores pone
        --pan-alto-tira: 0px y el resto se reacomoda solo.
    */
    /*
        88 y no 114. Los 114 salían de la barra de acciones en dos filas con sus
        botones de 32 px. Apretando el botón a 28 —el relleno, no la letra— la
        barra baja a 60, y con 14 px de relleno arriba y abajo la cabecera cabe
        en 88. Son 26 px que le pasan enteros a la tabla, que es la única parte
        de la pantalla donde el alto se traduce en filas visibles.
    */
    --pan-alto-cabecera: 88px;
    --pan-alto-filtros: 82px;
    --pan-alto-tira: 58px;

    --pan-sombra: 0 1px 2px rgba(12, 39, 64, .04), 0 12px 32px -18px rgba(12, 39, 64, .35);

    /*
        La sombra de las tarjetas pequeñas es más corta y más cerrada que la de
        los bloques grandes. La de arriba está calculada para una tarjeta que
        ocupa media pantalla; bajo una de 58 px se desparrama y la deja
        flotando en vez de apoyada.
    */
    --pan-sombra-tarjeta: 0 1px 2px rgba(12, 39, 64, .05), 0 6px 16px -10px rgba(12, 39, 64, .30);
    --pan-sans: 'IBM Plex Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
    --pan-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
}

/* ═══════════════════ La pantalla ═══════════════════ */

/*
    Una columna que ocupa el alto de la ventana. Los bloques de arriba tienen
    alto propio y la tabla se queda con lo que sobra, desplazándose por dentro.

    ── De dónde salen los números ────────────────────────────────────────────
    En escritorio, MainLayout.razor.css deja «main» en height: 100vh con su
    propio desplazamiento, y el «article» de dentro lleva padding-left/right de
    1.5rem con !important más un relleno en línea de 2 px arriba y abajo.

    Los márgenes negativos cancelan esos 1.5rem a cada lado y los 2 px de
    arriba; el relleno propio devuelve un aire de 10 px. Neto: se recuperan 28
    px de ancho, que en una tabla de trece columnas es una columna que no hay
    que truncar.

    El alto descuenta 10 px y no 4: sobran seis para que un redondeo de
    subpíxel no dispare la barra de desplazamiento de «main», que sacaría la
    tabla de cuadro.
*/
.pan-pantalla,
.pan-pantalla-fluida {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin: -2px -1.5rem 0;
    padding: 4px 10px 6px;
    font-family: var(--pan-sans);
}

.pan-pantalla {
    height: calc(100vh - 10px);
    overflow: hidden;
}

/*
    ── La variante que sí crece ──────────────────────────────────────────────
    Un tablero no es un listado: lleva gráfico, pestañas y varios bloques por
    área, y no hay forma de meterlo en una ventana sin volverlo ilegible. Ésta
    hereda los márgenes y la separación —que es lo que hace que las pantallas se
    lean como la misma plataforma— y renuncia sólo al alto de ventana.

    El desplazamiento vuelve a ser el de la página, así que sus hijos no
    necesitan «min-height: 0» ni desplazarse por dentro.
*/
.pan-pantalla-fluida {
    height: auto;
    overflow: visible;
}

/*
    ── Contrato: los hijos directos no llevan margen ─────────────────────────
    La separación entre bloques la pone el «gap» del envoltorio. Un margen
    inferior en un bloque se SUMA al gap y descuadra la pantalla contra las
    demás.

    Y no se puede arreglar desde aquí: una regla como

        .pan-pantalla > * { margin-bottom: 0 }

    empata en especificidad con .pres-cabecera y pierde, porque las hojas de
    módulo se cargan después. Cada módulo declara sus bloques sin margen; es
    responsabilidad suya, no de este archivo.
*/

/* ═══════════════════ Cabecera ═══════════════════ */

/*
    Flex y no rejilla de tres pistas: la barra de acciones vive dentro de la
    cabecera y hay pantallas que la llevan y pantallas que no. Con pistas
    declaradas, la que falta deja igualmente su separación colgando a la
    derecha.
*/
.pan-cabecera {
    display: flex;
    align-items: center;
    flex: 0 0 auto;
    min-height: var(--pan-alto-cabecera);
    padding: 14px 22px;
    gap: 22px;
    /*
        Degradado apenas insinuado: el papel se enfría hacia los cantos y deja el
        centro limpio, que es donde va el título. Es lo que separa la cabecera
        del fondo de la página sin recurrir a un color de relleno.
    */
    background: var(--pan-papel);
    background: linear-gradient(90deg, #eef3f8 0%, var(--pan-papel) 18%, var(--pan-papel) 82%, #eef3f8 100%);
    border: 1px solid var(--pan-linea);
    border-radius: var(--pan-radio);
    box-shadow: var(--pan-sombra-tarjeta);
}

.pan-cabecera-marca,
.pan-cabecera-logo {
    flex: 0 0 auto;
}

/* 44 y no 58: la cabecera bajó a 88 px y el logo tiene que caber en los 60 de
   contenido junto al resto. A este tamaño la marca sigue leyéndose entera. */
.pan-cabecera-logo,
.pan-cabecera-marca img {
    height: 44px;
    width: auto;
    display: block;
}

.pan-cabecera-texto {
    flex: 1 1 auto;
    min-width: 0;
}

/*
    La razón social en versalitas, encima del título, y en azul institucional y
    no en gris: es la línea que dice de quién es la pantalla, y en gris se leía
    como un pie de página puesto arriba.
*/
.pan-cabecera-empresa {
    margin: 0;
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .16em;
    line-height: 1.2;
    text-transform: uppercase;
    color: var(--pan-azul);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.pan-cabecera-titulo {
    margin: 1px 0 2px;
    font-size: 24px;
    font-weight: 700;
    letter-spacing: -.015em;
    line-height: 1.15;
    color: var(--pan-tinta);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Interlínea ceñida: las tres líneas del bloque de texto tienen que caber en
   los 60 px que deja libre la cabecera. */
.pan-cabecera-sub {
    margin: 0;
    font-size: 12.5px;
    line-height: 1.3;
    color: var(--pan-apagado);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* La cifra que resume la pantalla, alineada a la derecha. */
.pan-cabecera-sello {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    flex: 0 0 auto;
    gap: 1px;
    padding-left: 22px;
    border-left: 1px solid var(--pan-linea);
    line-height: 1.1;
}

.pan-sello-rotulo {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--pan-tenue);
}

.pan-sello-monto {
    font-family: var(--pan-mono);
    font-size: 25px;
    font-weight: 600;
    letter-spacing: -.02em;
    color: var(--pan-tinta);
    font-variant-numeric: tabular-nums;
}

.pan-sello-pie {
    font-size: 11px;
    color: var(--pan-tenue);
}

/* ═══════════════════ Barra de descarga y acciones ═══════════════════ */

/*
    Dentro de la cabecera y en dos filas de dos.

    ── Por qué en bloque y no en línea ───────────────────────────────────────
    En una sola fila, cuatro botones rotulados se estiran unos 250 px, y ese
    ancho sale del título, que es el único elemento elástico de la cabecera. En
    dos filas el bloque gasta altura en vez de ancho, que es lo que sobra: dos
    botones de 32 px con su separación son 68 px, y la cabecera tiene 70 px
    libres entre sus rellenos.

    Al caber en dos filas, el rótulo puede ir al lado del icono en lugar de
    debajo —se lee mejor— sin estirar la barra hasta comerse el título.
*/
.pan-barra-doc {
    display: grid;
    grid-template-columns: repeat(2, auto);
    gap: 4px 6px;
    align-content: center;
    flex: 0 0 auto;
    padding-left: 16px;
    border-left: 1px solid var(--pan-linea);
}

/*
    Con MÁS de cuatro botones, tres columnas. En dos, los siete de la planilla
    eran cuatro filas y la cabecera crecía media pantalla; en tres son tres
    filas y el bloque sigue gastando altura antes que ancho. Con cuatro o menos
    se quedan las dos filas de dos, que es la medida para la que se pensó.

    Se cuenta con «:has» y un quinto hijo, así que la regla se ajusta sola cuando
    un botón depende del estado —el de BANCO sólo sale aprobada la planilla— o
    del rol, sin que cada pantalla tenga que declarar cuántos trae.
*/
.pan-barra-doc:has(> :nth-child(5)) {
    grid-template-columns: repeat(3, auto);
}

/*
    El botón llena su celda para que los rótulos de las dos filas arranquen en
    la misma vertical: si cada uno se ciñe a su texto, la rejilla los centra y
    quedan escalonados.

    El marco se dibuja aquí y no con Variant.Outlined porque el contorno de
    Radzen para ButtonStyle.Dark es tinta plena: cuatro rectángulos negros en la
    cabecera pesan más que el propio título. Ésta es la misma línea que separa
    la cabecera del sello, así que delimita sin gritar.
*/
.pan-barra-doc .rz-button,
.pan-barra-doc-columna {
    width: 100%;
    min-width: 0;
}

/* Relleno de 3 y no de 5: dos filas de botones de 28 px son 60, que es lo que
   deja libre una cabecera de 88. El recorte va en el aire, no en la letra. */
.pan-barra-doc .rz-button {
    padding: 3px 9px;
    border: 1px solid var(--pan-linea);
    border-radius: 8px;
    background: var(--pan-papel);
    box-shadow: none;
    transition: border-color .18s ease, background-color .18s ease;
}

.pan-barra-doc .rz-button:hover:not(.rz-state-disabled) {
    border-color: var(--pan-azul);
    background: rgba(24, 95, 165, .05);
}

.pan-barra-doc .rz-button.rz-state-disabled {
    opacity: .45;
}

/*
    La caja interna es quien coloca icono y texto —el botón de Radzen es
    «inline-block»—, y por venir en «inline-flex» se ciñe a su contenido.
    Pasarla a «flex» al 100 % es lo que permite alinear a la izquierda; el
    «gap» también vive aquí, porque el icono no lleva margen propio.
*/
.pan-barra-doc .rz-button .rz-button-box {
    display: flex;
    width: 100%;
    justify-content: flex-start;
    gap: 6px;
}

.pan-barra-doc .rz-button .rz-button-text {
    font-size: 11px;
    font-weight: 600;
    /* Espaciado corto: los rótulos largos multiplican cada centésima de «em»
       por su número de letras en el ancho de la columna. */
    letter-spacing: .03em;
    text-transform: uppercase;
    white-space: nowrap;
    /* La caja del botón trae interlínea de 1.25rem, que aquí sólo sirve para
       descuadrar el texto respecto del icono. */
    line-height: 1;
    color: var(--pan-apagado);
}

.pan-barra-doc .rz-button:hover .rz-button-text {
    color: inherit;
}

/* Una acción con barra de avance —una exportación que tarda— necesita que su
   celda sea a su vez una columna. */
.pan-barra-doc-columna {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

/* ═══════════════════ Filtros ═══════════════════ */

/*
    Una sola fila, en rejilla de columnas declaradas.

    ── Por qué no flex ───────────────────────────────────────────────────────
    Con flex y «flex: 0 0 124px» por control, cada desplegable salía igualmente
    a 162 px: un elemento flexible trae «min-width: auto», de modo que no se
    encoge por debajo del ancho mínimo de su contenido y la base declarada se
    ignora. Sumados, los controles se comían la línea entera y el botón de
    agregar caía a una segunda fila.

    En rejilla manda la pista: el control se encoge dentro de su columna.

    ── Las pistas las pone cada pantalla ─────────────────────────────────────
    Porque dependen de cuántos controles haya y de qué anchura pide cada uno.
    El valor de aquí es un respaldo que se acomoda solo; una pantalla que
    quiera mandar declara sus pistas en su propia hoja.
*/
.pan-filtros {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(132px, 1fr));
    align-items: end;
    gap: 14px;
    flex: 0 0 auto;
    min-height: var(--pan-alto-filtros);
    padding: 14px 18px;
    background: var(--pan-papel);
    border: 1px solid var(--pan-linea);
    border-radius: var(--pan-radio);
}

/* Sin esto, el contenido de la celda vuelve a imponer su ancho mínimo y la
   rejilla se desborda: es el mismo «min-width: auto», ahora en el elemento de
   la rejilla. */
.pan-filtros > .pan-filtro {
    min-width: 0;
}

.pan-filtros .pan-filtro > label {
    display: block;
    margin-bottom: 5px;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--pan-tenue);
    white-space: nowrap;
}

.pan-filtro-acciones {
    display: flex;
    align-items: flex-end;
    justify-content: flex-end;
    gap: 8px;
    min-width: 0;
    /* Hay pantallas con cinco acciones (presupuesto de gastos, por ejemplo): sin
       esto la quinta se sale de la celda en vez de bajar a un segundo renglón. */
    flex-wrap: wrap;
}

/*
    ── Los desplegables no se tocan ──────────────────────────────────────────
    Radzen centra el texto repartiendo el relleno de la etiqueta dentro del
    alto que él mismo calcula. Al fijarle el alto por fuera y reescribir el
    relleno, la cuenta deja de cuadrar: el texto queda pegado al borde de
    arriba mientras la flecha sigue centrada. El alto de la fila lo pone
    --pan-alto-filtros como mínimo del contenedor, no forzándoselo a cada
    control.

    Sólo los campos de texto nativos necesitan que se les diga el alto, y se
    les pide el mismo que Radzen usa para los suyos —su propia variable— para
    que la fila quede pareja pase lo que pase con el tema.
*/
.pan-filtros .pan-input {
    height: var(--rz-input-height, 36px);
    font-size: 13px;
    border-radius: 8px;
}

.pan-input {
    border: 1px solid var(--pan-linea);
    transition: border-color .18s ease, box-shadow .18s ease;
}

.pan-input:focus {
    border-color: var(--pan-azul);
    box-shadow: 0 0 0 3px rgba(24, 95, 165, .12);
    outline: none;
}

/* La barra de estado no se estira: se ciñe a sus opciones y aprieta la letra,
   porque los rótulos suelen ser palabras largas en versalitas. */
.pan-filtro-estado .rz-selectbutton {
    display: inline-flex;
    width: auto !important;
}

.pan-filtro-estado .rz-selectbutton .rz-button {
    font-size: 10.5px;
    letter-spacing: .02em;
    padding-left: 12px;
    padding-right: 12px;
    white-space: nowrap;
}

/*
    La acción principal de la pantalla —agregar el registro— se distingue con
    color y con un relieve propio, no ocupando una barra para ella sola.
*/
.pan-boton-agregar {
    font-weight: 600;
    letter-spacing: .01em;
    box-shadow: 0 1px 2px rgba(12, 39, 64, .10), 0 6px 16px -10px rgba(24, 95, 165, .55);
}

.pan-boton-agregar:hover {
    transform: translateY(-1px);
    box-shadow: 0 2px 4px rgba(12, 39, 64, .12), 0 10px 22px -10px rgba(24, 95, 165, .65);
}

.pan-error {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
    padding: 6px 12px;
    border-radius: 8px;
    border: 1px solid rgba(211, 47, 20, .25);
    background: rgba(211, 47, 20, .06);
    color: var(--pan-rojo);
    font-size: 12.5px;
}

/*
    ── Los dos hermanos del error ────────────────────────────────────────────
    Nacieron en presupuestos como .pres-aviso y .pres-novedad y suben aquí sin
    cambiar nada más que el prefijo: no llevan el nombre de ningún dato del
    negocio —son «algo salió bien» y «lo que está en pantalla quedó viejo»—, así
    que por la regla de oro del formato les toca esta hoja y no la del módulo.

    Los tres comparten cuerpo, relleno y radio para que la fila no salte de
    altura según cuál de ellos aparezca, y el texto se estira para empujar la
    acción al extremo derecho.
*/
.pan-aviso {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
    padding: 6px 12px;
    border-radius: 8px;
    border: 1px solid rgba(28, 138, 90, .25);
    background: rgba(28, 138, 90, .06);
    color: #16704a;
    font-size: 12.5px;
}

/* En azul y no en verde ni en rojo: no es un logro ni un fallo, es un estado. */
.pan-novedad {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
    padding: 6px 12px;
    border-radius: 8px;
    border: 1px solid rgba(24, 95, 165, .28);
    background: rgba(24, 95, 165, .07);
    color: var(--pan-azul);
    font-size: 12.5px;
}

.pan-aviso > span,
.pan-novedad > span {
    flex: 1 1 auto;
    min-width: 0;
}

.pan-error > span {
    flex: 1 1 auto;
    min-width: 0;
}

/* ═══════════════════ Franja de indicadores ═══════════════════ */

/*
    Tarjetas sueltas, cada indicador con su marco y su separación.

    ── El reparto y el alto ──────────────────────────────────────────────────
    Tres líneas —rótulo, cifra, pie— una debajo de otra, que es lo que hace
    legible un indicador, en 58 px, que es lo que la tabla puede permitirse.
    Leerlo en renglón ahorraba cuatro píxeles y costaba la jerarquía; darle
    120 px de tarjeta le quitaba dos filas a la tabla.

    Como las de filtros, las pistas por defecto se acomodan solas y cada
    pantalla puede declarar las suyas.
*/
.pan-tira {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 10px;
    flex: 0 0 auto;
    min-height: var(--pan-alto-tira);
}

/*
    ── Rejilla de dos columnas y no una pila ─────────────────────────────────
    A la izquierda el icono, ocupando las tres filas; a la derecha el rótulo, la
    cifra y el pie. El icono es OPCIONAL, y de ahí que la separación entre las
    dos columnas la ponga su margen y no un «column-gap»: una pista vacía emite
    igualmente su separación, y una tarjeta sin icono habría quedado con doce
    píxeles muertos a la izquierda. Es la misma trampa que la barra de acciones
    en la cabecera.

    Las tres líneas de texto se asignan a la segunda columna de forma explícita.
    Sin eso, la colocación automática mandaría el rótulo a la primera y la
    tarjeta sin icono se rompería.
*/
.pan-tira-dato {
    position: relative;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    /*
        Las tres filas se declaran explícitamente por una razón concreta: sin
        ellas la rejilla es implícita, y en una rejilla implícita el «-1» de
        «grid-row: 1 / -1» se resuelve contra la rejilla EXPLÍCITA —que no tiene
        líneas—, así que degenera en una sola fila. El icono se quedaba en el
        renglón del rótulo y lo estiraba a sus 34 px, abriendo un hueco entre el
        rótulo y la cifra.
    */
    grid-template-rows: repeat(3, auto);
    align-content: center;
    row-gap: 2px;
    padding: 7px 14px 7px 15px;
    background: var(--pan-papel);
    border: 1px solid var(--pan-linea);
    border-radius: 12px;
    box-shadow: var(--pan-sombra-tarjeta);
    overflow: hidden;
    min-width: 0;
}

.pan-tira-rotulo,
.pan-tira-monto,
.pan-tira-pie {
    grid-column: 2;
}

/*
    El icono va en pastilla teñida del mismo color que el filete del canto, no
    suelto: un glifo sobre el papel compite con la cifra, que es lo que hay que
    leer. La pastilla lo convierte en marca de identidad y lo saca del recorrido
    de lectura.

    El color sale de --pan-acento, así que cada indicador tiñe su pastilla sin
    declarar nada: el mismo valor que ya pinta el filete.
*/
.pan-tira-icono {
    grid-column: 1;
    grid-row: 1 / -1;
    align-self: center;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 34px;
    height: 34px;
    margin-right: 11px;
    border-radius: 9px;
    /* Respaldo primero, por si el navegador no resuelve color-mix. */
    background: rgba(24, 95, 165, .09);
    background: color-mix(in srgb, var(--pan-acento, var(--pan-azul)) 12%, transparent);
    color: var(--pan-acento, var(--pan-azul));
}

.pan-tira-icono .rzi,
.pan-tira-icono .rz-icon,
.pan-tira-icono .notranslate {
    font-size: 19px !important;
    line-height: 1;
}

/* Filete de color en el canto: identifica el indicador sin teñir la tarjeta
   entera, que la vuelve ilegible. */
.pan-tira-dato::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: var(--pan-acento, var(--pan-azul));
}

/* Un indicador que pide atención: fondo apenas teñido, no un bloque de color. */
.pan-tira-alerta {
    background: rgba(184, 84, 27, .05);
}

/* Las tres líneas van ceñidas: en 58 px de tarjeta, la interlínea por defecto
   de cada una sumaría sola más de la mitad del alto. */
.pan-tira-rotulo {
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: .12em;
    line-height: 1;
    text-transform: uppercase;
    color: var(--pan-tenue);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.pan-tira-monto {
    font-family: var(--pan-mono);
    font-size: 18px;
    font-weight: 600;
    letter-spacing: -.02em;
    line-height: 1.05;
    color: var(--pan-tinta);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.pan-tira-pie {
    font-size: 10.5px;
    line-height: 1.15;
    color: var(--pan-tenue);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

.pan-tira-pie b { color: var(--pan-apagado); }

/*
    ── La letra pequeña del indicador (PanMetrica) ──────────────────────────
    Cuarta línea: de dónde sale la cifra, qué cubre y a qué hora se consultó.
    Visible y no sólo en el título, para que la lea también el lector de
    pantalla; gris y de 9,5 px para que no compita con la cifra. La tarjeta
    declara una fila más sólo cuando la lleva.
*/
.pan-tira-con-fuente { grid-template-rows: repeat(4, auto); }

.pan-tira-fuente {
    grid-column: 2;
    font-size: 9.5px;
    line-height: 1.15;
    color: var(--pan-tenue);
    opacity: .9;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    min-width: 0;
}

.pan-tira-total .pan-tira-fuente { color: rgba(255, 255, 255, .55); }

/* Un indicador que filtra o navega: se ve y se maneja como botón. */
.pan-tira-boton { cursor: pointer; transition: box-shadow .15s ease, transform .15s ease; }
.pan-tira-boton:hover { box-shadow: 0 6px 18px rgba(12, 39, 64, .12); transform: translateY(-1px); }
.pan-tira-boton:focus-visible { outline: 2px solid var(--pan-azul); outline-offset: 2px; }
.pan-tira-activa { outline: 2px solid var(--pan-acento, var(--pan-azul)); outline-offset: -2px; }

/* La barra de avance es el canto inferior de la tarjeta: apilada consumiría su
   alto más el margen, que en 58 px no hay. */
.pan-tira-barra {
    position: absolute;
    left: 3px;
    right: 0;
    bottom: 0;
    height: 2px;
    background: rgba(12, 39, 64, .07);
}

.pan-tira-barra > div {
    height: 100%;
    background: var(--pan-acento, var(--pan-azul));
    transition: width .4s ease;
}

/* La tarjeta oscura, para el total que cierra la fila. */
.pan-tira-total {
    background: linear-gradient(150deg, #0C2740 0%, #14395c 100%);
    border-color: transparent;
}

.pan-tira-total .pan-tira-rotulo,
.pan-tira-total .pan-tira-pie {
    color: rgba(255, 255, 255, .62);
}

.pan-tira-total .pan-tira-monto {
    color: #fff;
}

/* Sobre la tarjeta oscura la pastilla teñida no se ve: el acento y el fondo son
   la misma familia. Se sustituye por un velo claro. */
.pan-tira-total .pan-tira-icono {
    background: rgba(255, 255, 255, .13);
    color: rgba(255, 255, 255, .88);
}

/* ═══════════════════ La tabla ═══════════════════ */

/*
    La tarjeta se queda con todo el alto que sobra y no crece con su contenido:
    el desplazamiento ocurre DENTRO de la tabla, con el encabezado y los
    filtros de columna congelados arriba y el paginador anclado abajo.

    min-height: 0 no es decorativo: sin él, un hijo flexible con contenido alto
    se niega a encogerse por debajo de su tamaño natural y la tarjeta desborda
    la ventana en vez de desplazarse por dentro.
*/
.pan-tarjeta {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    margin: 0 !important;
    padding: 0 !important;
    border-radius: var(--pan-radio) !important;
    border: 1px solid var(--pan-linea) !important;
    box-shadow: var(--pan-sombra) !important;
    overflow: hidden;
}

/* No hay envoltorio intermedio: RadzenCard 5.5.5 pone el contenido
   directamente dentro de .rz-card, que es este mismo elemento. La cadena flex
   va de .pan-pantalla a .pan-tarjeta y de ahí a la tabla, sin escalones. */

.pan-rejilla {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-height: 0;
    border: 0 !important;
    font-family: var(--pan-sans);
}

/* El cuerpo desplazable de Radzen. */
.pan-rejilla .rz-data-grid-data {
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
}

/*
    Encabezado congelado. Radzen ya deja el thead en position: sticky, pero el
    th es transparente: al desplazar, las filas se ven pasar POR DEBAJO del
    título. Con FilterMode.Simple el filtro de columna vive dentro del mismo th
    —no hay una segunda fila que congelar aparte—, así que esta regla los cubre
    a los dos.
*/
.pan-rejilla .rz-grid-table thead th {
    position: sticky;
    top: 0;
    z-index: 3;
    background: var(--pan-papel) !important;
    font-size: 10px !important;
    font-weight: 600 !important;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--pan-tenue) !important;
    padding-top: 7px !important;
    padding-bottom: 7px !important;
}

/*
    Las cajas de filtro vienen con el alto de un campo de formulario —36 px—
    dentro de un encabezado cuya letra mide 10. Es la banda vacía más ancha de
    la pantalla y no la ocupa ningún dato. El selector va contra «input» y no
    contra la clase de Radzen a propósito: en el thead no hay más campos que
    los del filtro.
*/
.pan-rejilla .rz-grid-table thead th input {
    height: 26px !important;
    font-size: 11.5px !important;
    padding-top: 2px !important;
    padding-bottom: 2px !important;
}

.pan-rejilla .rz-grid-table thead th .rz-column-title,
.pan-rejilla .rz-grid-table thead th .rz-column-title-content {
    white-space: normal !important;
    overflow: visible !important;
    text-overflow: clip !important;
    line-height: 1.15;
}

/*
    Cinco píxeles de relleno.

    Con la pantalla cargada, cada píxel de relleno se paga por cada fila: diez
    en lugar de cinco cuestan unos 120 px en una docena de registros, que son
    tres filas menos a la vista. El recorte va en el relleno y no en la letra:
    esto se lee a diario y con cifras dentro.
*/
.pan-rejilla .rz-grid-table tbody td {
    font-size: 12.5px;
    padding-top: 5px !important;
    padding-bottom: 5px !important;
    vertical-align: middle;
}

/* Los distintivos traen relleno de sobra para una fila apretada: son dos o
   tres siglas y ocupaban tanto como el nombre que llevan al lado. */
.pan-rejilla .rz-grid-table tbody td .rz-badge {
    padding: 2px 7px !important;
    font-size: 9.5px !important;
    line-height: 1.35 !important;
}

/* La fila seleccionada se marca con un filo, no sólo con un fondo tenue: con
   una ficha abierta encima hay que saber de vuelta dónde se estaba. */
.pan-rejilla .rz-grid-table tbody tr.rz-state-highlight > td:first-child {
    box-shadow: inset 3px 0 0 var(--pan-azul);
}

.pan-rejilla .rz-pager {
    flex: 0 0 auto;
    border-top: 1px solid var(--pan-linea);
    padding: 2px 8px !important;
    min-height: 34px;
}

/* ═══════════════════ Celdas ═══════════════════ */

/*
    El vocabulario de una fila. Son cinco piezas y con ellas se arma cualquier
    columna: lo que identifica el registro, lo que lo acompaña en pequeño, un
    dato suelto, una cifra y un texto libre.
*/

/* Lo que identifica la fila: el nombre del proveedor, del colaborador, del
   producto. Nunca envuelve; si no cabe, se recorta. */
.pan-principal {
    display: block;
    font-weight: 600;
    font-size: 12.5px;
    line-height: 1.2;
    color: var(--pan-tinta);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* El código que acompaña al nombre: el NIT, el correlativo, el número de
   empleado. En monoespaciada, porque son dígitos que se comparan en vertical. */
.pan-secundario {
    display: block;
    font-family: var(--pan-mono);
    font-size: 10px;
    color: var(--pan-tenue);
    line-height: 1.2;
}

/* Un dato corto: una fecha, una forma de pago, un estado en texto. */
.pan-dato {
    font-size: 11.5px;
    color: var(--pan-apagado);
    white-space: nowrap;
}

/* Como el anterior, pero de dígitos: series, autorizaciones, referencias. */
.pan-mono {
    font-family: var(--pan-mono);
    font-size: 11.5px;
    color: var(--pan-apagado);
    white-space: nowrap;
}

.pan-mono-sep { color: var(--pan-tenue); }

/*
    Texto libre, dos líneas y corta. Una descripción puede traer párrafos
    enteros; sin el recorte, una sola fila se come el alto de cinco. El texto
    completo vive en la ficha, a un clic.
*/
.pan-texto {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: 12px;
    line-height: 1.4;
    color: var(--pan-apagado);
}

.pan-monto {
    font-family: var(--pan-mono);
    font-size: 13px;
    font-weight: 600;
    color: var(--pan-tinta);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Una celda de dos renglones: arriba la categoría en versalitas, abajo el
   detalle. Sirve para rubro/nombre, bodega/ubicación, grupo/puesto. */
.pan-doble {
    display: flex;
    flex-direction: column;
    line-height: 1.2;
    min-width: 0;
}

.pan-doble-sup {
    font-size: 9px;
    font-weight: 600;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--pan-tenue);
}

.pan-doble-inf {
    font-size: 11.5px;
    color: var(--pan-apagado);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pan-alerta { color: var(--pan-rojo) !important; }

.pan-enlace {
    margin-left: 6px;
    color: var(--pan-azul);
    text-decoration: none;
    border-bottom: 1px dotted currentColor;
    cursor: pointer;
}

.pan-enlace:hover { color: var(--pan-tinta); }

.pan-acciones {
    display: inline-flex;
    gap: 2px;
    justify-content: flex-end;
}

/* ═══════════════════ Iconos de la fila ═══════════════════ */

/*
    Enlaces a documentos, cada uno con su color. Un icono se reconoce de un
    vistazo; una sigla obliga a leer texto en cada fila.

    ── Por qué no envuelve ───────────────────────────────────────────────────
    Si la columna se queda corta, el último icono cae a una segunda línea y
    estira ESA fila y sólo ésa: el listado queda con escalones. La columna se
    dimensiona para todos —24 px cada uno más dos de separación más el relleno
    de la celda— y el envoltorio se prohíbe.
*/
.pan-iconos {
    display: inline-flex;
    flex-wrap: nowrap;
    gap: 2px;
}

.pan-icono {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 24px;
    height: 24px;
    border-radius: 7px;
    text-decoration: none;
    /* Apagados, para que no compitan con los datos de la fila. */
    opacity: .65;
    transition: opacity .15s ease, background-color .15s ease, transform .15s ease;
}

.pan-icono:hover {
    opacity: 1;
    background: rgba(12, 39, 64, .06);
    transform: translateY(-1px);
}

/* El foco tiene que verse: son enlaces y se recorren con el tabulador. */
.pan-icono:focus-visible {
    opacity: 1;
    outline: 2px solid var(--pan-azul);
    outline-offset: 1px;
}

.pan-icono .rzi,
.pan-icono .rz-icon,
.pan-icono .notranslate {
    font-size: 18px !important;
    line-height: 1;
}

.pan-icono-rojo  { color: var(--pan-rojo); }
.pan-icono-verde { color: var(--pan-verde); }
.pan-icono-azul  { color: var(--pan-azul); }
.pan-icono-ambar { color: var(--pan-ambar); }

/* ═══════════════════ Arrastrar filas para reordenar ═══════════════════ */

/*
    El gesto lo pinta el escucha de Presupuestos.js, que pone y quita estas
    clases; aquí sólo se dice cómo se ven. Son la versión genérica de las
    «pres-» del presupuesto, para las tablas que no son de ese módulo.

    ── Qué es cada cosa ──────────────────────────────────────────────────────
    .pan-tabla-orden        marca la tabla que admite soltar filas (sin ella el
                            escucha ni cancela el «dragover» ni pinta nada).
    .pan-asa                el asa: lo único que se agarra para arrastrar.
    .pan-fila-arrastrando   la fila que va en el aire.
    .pan-fila-destino       dónde va a caer: barra arriba de la señalada, o
    .pan-fila-destino-abajo abajo, según se venga subiendo o bajando.
*/
.pan-asa {
    display: inline-flex;
    align-items: center;
    color: var(--pan-tenue);
    cursor: grab;
    vertical-align: middle;
    transition: color .15s ease;

    /* Sin selección de texto ni gestos táctiles: si el navegador puede entender
       el gesto como «seleccionar el icono» o «desplazar la página», lo entiende
       así y el arrastre no llega a empezar. */
    user-select: none;
    -webkit-user-select: none;
    touch-action: none;
}

.pan-asa:hover { color: var(--pan-apagado); }
.pan-asa:active { cursor: grabbing; }

.pan-asa .rzi,
.pan-asa .rz-icon,
.pan-asa .notranslate {
    font-size: 16px !important;
    line-height: 1;
}

/* La fila en el aire se atenúa: dice «esto es lo que llevo en la mano». La
   clase llega en el tick siguiente al «dragstart», cuando el navegador ya tomó
   la foto de lo que se arrastra; antes, el fantasma salía casi invisible. */
.pan-fila-arrastrando {
    opacity: .4;
}

/* Una línea gruesa y no un fondo: el gesto es «ponlo aquí», y un relleno
   señala una fila, no un hueco entre dos. Box-shadow interior en vez de border
   para que la fila no crezca dos píxeles y empuje a las de abajo mientras se
   apunta. */
.pan-fila-destino > td {
    box-shadow: inset 0 2px 0 0 var(--pan-azul);
}

.pan-fila-destino-abajo > td {
    box-shadow: inset 0 -2px 0 0 var(--pan-azul);
}

@media print {
    .pan-asa { display: none; }
    .pan-fila-arrastrando { opacity: 1; }

    .pan-fila-destino > td,
    .pan-fila-destino-abajo > td { box-shadow: none; }
}

/* ═══════════════════ Pie de la tarjeta ═══════════════════ */

.pan-pie {
    flex: 0 0 auto;
    padding: 4px 10px;
    border-top: 1px solid var(--pan-linea);
    font-size: 11px;
    color: var(--pan-tenue);
}

.pan-pie b { color: var(--pan-apagado); }

/* ═══════════════════ Ficha en ventana emergente ═══════════════════ */

/*
    Se abre encima y no debajo de la tabla: al seleccionar una fila la página
    se alargaba y el listado desaparecía justo cuando uno está comparando un
    registro con los de al lado.
*/
.pan-modal {
    position: fixed;
    inset: 0;
    z-index: 1200;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: rgba(12, 39, 64, .42);
    backdrop-filter: blur(2px);
    animation: pan-aparecer .16s ease both;
}

.pan-modal-caja {
    display: flex;
    flex-direction: column;
    width: min(1080px, 100%);
    max-height: 100%;
    background: var(--pan-papel);
    border-radius: 14px;
    box-shadow: 0 24px 64px -20px rgba(12, 39, 64, .55);
    outline: none;
    overflow: hidden;
    animation: pan-subir .18s ease backwards;
}

.pan-modal-cab {
    display: flex;
    align-items: center;
    gap: 14px;
    flex: 0 0 auto;
    flex-wrap: wrap;
    padding: 10px 14px;
    border-bottom: 1px solid var(--pan-linea);
}

.pan-modal-titulo {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-width: 0;
    line-height: 1.2;
}

.pan-modal-enlaces {
    display: inline-flex;
    gap: 4px;
    flex: 0 0 auto;
}

/* Recorrer el listado sin cerrar la ficha: ← y → dentro de lo filtrado. */
.pan-modal-navega {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    flex: 0 0 auto;
    padding: 0 8px;
    border-left: 1px solid var(--pan-linea);
    border-right: 1px solid var(--pan-linea);
}

.pan-modal-contador {
    font-family: var(--pan-mono);
    font-size: 11px;
    color: var(--pan-apagado);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    min-width: 56px;
    text-align: center;
}

.pan-modal-acciones {
    display: inline-flex;
    gap: 6px;
    flex: 0 0 auto;
}

/* El cuerpo se desplaza por dentro: la ventana nunca es más alta que la
   pantalla. */
.pan-modal-cuerpo {
    flex: 1 1 auto;
    min-height: 0;
    overflow: auto;
    padding: 12px 14px 16px;
}

@keyframes pan-aparecer { from { opacity: 0; } to { opacity: 1; } }
@keyframes pan-subir {
    from { opacity: 0; transform: translateY(10px) scale(.99); }
    to   { opacity: 1; transform: none; }
}

/* ═══════════════════ Vacío y esqueleto ═══════════════════ */

.pan-vacio {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    flex: 1 1 auto;
    min-height: 0;
    padding: 30px 20px;
    background: var(--pan-papel);
    border: 1px dashed var(--pan-linea);
    border-radius: var(--pan-radio);
    text-align: center;
}

.pan-vacio .rzi,
.pan-vacio .rz-icon {
    font-size: 34px;
    color: var(--pan-tenue);
}

.pan-vacio h4 {
    margin: 0;
    font-size: 15px;
    font-weight: 600;
    color: var(--pan-tinta);
}

.pan-vacio p {
    margin: 0 0 6px;
    font-size: 12.5px;
    color: var(--pan-tenue);
    max-width: 46ch;
}

/* Mientras carga se enseña la forma de lo que viene, no una rueda girando: el
   salto de la rueda a la tabla es lo que hace que la pantalla parezca lenta. */
.pan-esqueleto {
    display: flex;
    flex-direction: column;
    gap: 8px;
    flex: 1 1 auto;
    min-height: 0;
    padding: 10px;
    background: var(--pan-papel);
    border: 1px solid var(--pan-linea);
    border-radius: var(--pan-radio);
}

.pan-esqueleto-fila {
    height: 34px;
    border-radius: 7px;
    background: linear-gradient(90deg, #eef2f6 25%, #f7f9fb 37%, #eef2f6 63%);
    background-size: 400% 100%;
    animation: pan-cargando 1.3s ease infinite;
}

@keyframes pan-cargando {
    from { background-position: 100% 50%; }
    to   { background-position: 0 50%; }
}

@media (prefers-reduced-motion: reduce) {
    .pan-esqueleto-fila,
    .pan-modal,
    .pan-modal-caja,
    .pan-tira-barra > div,
    .pan-boton-agregar { animation: none !important; transition: none !important; }

    .pan-boton-agregar:hover { transform: none; }
}

/* ═══════════════════ Pantallas estrechas ═══════════════════ */

@media (max-width: 1100px) {
    /* Se suelta el alto de ventana: por debajo de este ancho la tabla no cabe
       de ninguna manera y es mejor desplazar la página entera. */
    .pan-pantalla {
        height: auto;
        min-height: calc(100vh - 8px);
        overflow: visible;
    }

    /* La fluida ya crece; aquí sólo pierde el mínimo de ventana, que en pantalla
       estrecha no significa nada. */
    .pan-pantalla-fluida { min-height: 0; }

    .pan-tarjeta { min-height: 420px; }

    .pan-cabecera-sub { display: none; }

    /* Sin sitio para los rótulos: vuelven a ser iconos en una sola fila y el
       nombre queda en el «title», que es de donde salió. */
    .pan-barra-doc {
        display: flex;
        align-items: center;
        gap: 2px;
    }

    .pan-barra-doc .rz-button .rz-button-text { display: none; }

    /* Sin rótulo el relleno lateral sobra: el marco quedaría muy holgado
       alrededor de un icono de 20 px. */
    .pan-barra-doc .rz-button,
    .pan-barra-doc-columna { width: auto; }

    .pan-barra-doc .rz-button { padding: 3px 5px; }
}

@media (max-width: 760px) {
    .pan-pantalla,
    .pan-pantalla-fluida { margin-left: -1rem; margin-right: -1rem; padding: 4px 6px; }

    .pan-cabecera { flex-wrap: wrap; }
    .pan-cabecera-sello { padding-left: 0; border-left: 0; }
    .pan-barra-doc { padding-left: 0; border-left: 0; }

    .pan-tira { grid-template-columns: 1fr; }

    .pan-filtros { grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); }

    .pan-modal { padding: 0; }
    .pan-modal-caja { max-height: 100%; height: 100%; border-radius: 0; width: 100%; }

    /* Los avisos y los botones de la ficha bajan de renglón en vez de salirse de
       la pantalla; un botón de aviso no se encoge hasta cortar su rótulo
       (septiembre de 2026: «Verlas» se cortaba a 360 px en requerimientos, y
       «Rehacer el asiento» se salía de la ficha de bodega). */
    .pan-aviso, .pan-novedad, .pan-error { flex-wrap: wrap; }
    .pan-aviso > .rz-button, .pan-novedad > .rz-button, .pan-error > .rz-button { flex-shrink: 0; }
    .pan-modal-acciones { flex-wrap: wrap; max-width: 100%; }
    .pan-modal-acciones .rz-button { min-height: 40px; min-width: 40px; }
}

/* ═══════════════════ Impresión ═══════════════════ */

/*
    El PDF se genera con window.print() sobre esta misma vista —generarPDF
    oculta .hideWhenPrint—, así que la hoja impresa se cuida aquí y no en otro
    documento.
*/
@media print {
    /* En papel no hay ventana que llenar: la columna se suelta y la tabla
       imprime todas sus filas en vez de desplazarse por dentro. */
    .pan-pantalla,
    .pan-pantalla-fluida {
        display: block;
        height: auto;
        overflow: visible;
        margin: 0;
        padding: 0;
    }

    /*
        El !important del «display» no sobra: Radzen declara
        .rz-data-grid { display: flex } con la misma especificidad que
        .pan-rejilla y su hoja se carga después, así que sin él la tabla seguiría
        siendo una columna flexible en el papel.
    */
    .pan-tarjeta,
    .pan-rejilla,
    .pan-rejilla .rz-data-grid-data {
        display: block !important;
        height: auto !important;
        max-height: none !important;
        overflow: visible !important;
    }

    .pan-cabecera,
    .pan-tira-dato,
    .pan-tarjeta {
        box-shadow: none !important;
        border-color: #d8e0e8 !important;
        animation: none !important;
        break-inside: avoid;
    }

    /* El degradado de los cantos se imprime como dos bandas grises. */
    .pan-cabecera { background: #fff !important; }

    /* La tarjeta del total va en fondo oscuro: en papel sale como un rectángulo
       negro con la cifra invisible dentro (y gastando tóner). Se invierte. */
    .pan-tira-total {
        background: #fff !important;
        border: 1px solid var(--pan-tinta) !important;
    }

    .pan-tira-total .pan-tira-monto { color: var(--pan-tinta) !important; }

    .pan-tira-total .pan-tira-rotulo,
    .pan-tira-total .pan-tira-pie { color: var(--pan-apagado) !important; }

    /* El encabezado congelado se suelta y se repite en cada página. */
    .pan-rejilla .rz-grid-table thead th { position: static !important; }
    .pan-rejilla .rz-grid-table thead { display: table-header-group; }

    .pan-rejilla .rz-grid-table tbody tr { break-inside: avoid; }

    /* La columna congelada de Radzen se apoya en position: sticky, que al
       imprimir deja la celda flotando sobre el resto de la fila. */
    .pan-rejilla .rz-frozen-cell { position: static !important; }

    /* El paginador no dice nada en papel. La clase es .rz-pager: .rz-paginator
       no existe en Radzen 5.5.5 y la regla no habría hecho nada. */
    .pan-rejilla .rz-pager { display: none !important; }

    /* En papel cabe el texto completo: no hay fila de al lado que desalinear. */
    .pan-texto {
        -webkit-line-clamp: unset;
        overflow: visible;
    }
}


/* ════════════════════════════════════════════════════════════════════════════
   Que los diálogos cubran la ventana

   ── El defecto ──────────────────────────────────────────────────────────────
   Los dos diálogos modales de la plataforma —.pan-modal, de las fichas
   emergentes, y .pres-editor, del módulo presupuestario— salían recortados. En
   la pestaña de movimientos de caja de Ingresos, con el panel casi vacío y por
   tanto bajo, el formulario aparecía cortado por arriba y por abajo: sin título
   y sin los botones de Guardar y Cancelar. No había forma de completarlo.

   ── La causa, medida en el navegador ────────────────────────────────────────
   El ancestro `<section class="pres-panel">` reportaba

       transform: matrix(1, 0, 0, 1, 0, 0)

   que es la matriz identidad: no mueve, no escala, no rota. Pero NO es `none`, y
   cualquier transform distinto de `none` convierte al elemento en el BLOQUE
   CONTENEDOR de sus descendientes `position: fixed`. `inset: 0` deja de
   significar «la ventana» y pasa a significar «esta caja».

   ¿De dónde sale una matriz identidad que nadie escribió? De la animación de
   entrada:

       .pres-panel { animation: pres-entrada .4s ease both; }
       @keyframes pres-entrada {
           from { opacity: 0; transform: translateY(6px); }
           to   { opacity: 1; transform: none; }
       }

   `animation-fill-mode: both` RETIENE el último fotograma después de terminar. Y
   al interpolar, el navegador convierte el valor a forma matricial, así que el
   `transform: none` del fotograma final se conserva como `matrix(1,0,0,1,0,0)`.
   Visualmente idéntico; para el bloque contenedor, todo lo contrario. La
   animación dura 400 ms y el efecto dura para siempre.

   ── El arreglo ──────────────────────────────────────────────────────────────
   Cambiar `both` por `backwards` en las ocho reglas de animación de entrada del
   sistema —.pres-panel, .pres-cabecera, .pres-kpi, .pres-grafico-card,
   .pres-novedad, .pres-panel-editor, .pan-modal-caja y .uso-aparece—. Con
   `backwards` el fotograma inicial se aplica durante el retardo, que es lo que
   hace falta para que el elemento no parpadee antes de empezar, y el final NO se
   retiene: al acabar, el elemento vuelve a sus estilos base, que son justamente
   `opacity: 1` y `transform: none`. La animación se ve exactamente igual y el
   transform retenido desaparece.

   ── Lo que NO era ───────────────────────────────────────────────────────────
   Se probó primero con `.rz-layout .rz-body { transform: translateZ(0) }`, una
   regla real del tema de Radzen que produce este mismo defecto. No era: esta
   aplicación no usa RadzenLayout —su MainLayout es propio, .page > main >
   article— así que esa regla nunca llegó a aplicarse. La lección para la próxima
   vez: medir el `transform` computado de la cadena de ancestros en el navegador
   ANTES de escribir el arreglo, no después.
   ════════════════════════════════════════════════════════════════════════════ */

/* ── Y el diálogo, a prueba de que algún día vuelva a pasar ──────────────────
   Aunque otro ancestro creara un bloque contenedor —una animación con
   transform, un backdrop-filter, un `contain`—, con esto el diálogo no se
   recorta: la capa desplaza y la caja nunca pasa de la altura de la ventana.
   Es el cinturón además del tirante, porque el síntoma —un formulario cortado
   sin botones— es demasiado caro para depender de una sola regla. */

.pan-modal,
.pres-editor {
    overflow: auto;
    overscroll-behavior: contain;

    /*
        Y sin margen. La capa es hija de un panel que reparte separación entre
        sus hijos, así que heredaba 4 px de margen superior: con `inset: 0` eso
        la baja cuatro píxeles y le resta cuatro de alto, de modo que la capa
        empieza en y=4 y la ventana queda con una franja sin cubrir arriba. Se
        nota poco y es incorrecto igual: una capa modal no participa del flujo
        del panel que la contiene.
    */
    margin: 0;
}

/*
    max-height en unidades de VENTANA y no el «100%» que había.

    Con `100%` la altura se mide contra la capa, y la capa se medía contra el
    bloque contenedor equivocado: ése era el segundo eslabón del mismo defecto.
    Contra la ventana, el diálogo no puede pasarse aunque algún ancestro vuelva
    a atrapar la capa.

    Las dos declaraciones no sobran: `dvh` descuenta la barra de direcciones en
    el móvil y `vh` no, pero `dvh` no existe en navegadores viejos y una
    declaración que el navegador no entiende se descarta sola. La segunda pisa a
    la primera donde se entiende, y donde no, queda la primera.
*/
/*
    Con el `not all and (max-width: 760px)` esta regla se queda fuera del móvil
    a propósito. Ahí manda el bloque de arriba, que pone el diálogo a pantalla
    completa —«max-height: 100%; height: 100%; border-radius: 0»— y ésa es la
    forma correcta en una pantalla estrecha. Como este bloque va DESPUÉS en el
    archivo, sin la exclusión lo pisaría y el diálogo perdería el pantalla
    completa que ya tenía ganado.
*/
@media not all and (max-width: 760px) {
    .pan-modal-caja,
    .pres-panel-editor {
        max-height: calc(100vh - 48px);
        max-height: calc(100dvh - 48px);
    }
}

/* Con la ventana baja el diálogo se pega arriba en vez de centrarse: centrado,
   una caja más alta que la ventana se sale por los dos lados y el encabezado
   queda fuera de alcance. */
@media (max-height: 720px) {
    .pan-modal,
    .pres-editor { align-items: flex-start; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   FORMULARIOS — vocabulario pan-form-*

   NO BORRAR NI REESCRIBIR ESTE BLOQUE. Lo usan ~180 páginas de captura y los
   componentes PanPaso / PanFranjaDatos / PanDato / PanBarraEnvio (Client\Shared).
   Sin él, TODOS los formularios de la plataforma se pintan sin formato: los
   pasos pierden su círculo numerado, las cajas pierden el borde y la zona de
   adjuntos deja de verse como tal. Si hay que tocar pantalla.css, se edita;
   no se sustituye el archivo entero.

   Principios:
   · Lo EDITABLE es lo único con caja: blanco, borde definido, sombra interior.
   · Lo RESUELTO no es un campo: celda gris con candado, rótulo y valor.
   · Los obligatorios llevan punto rojo en el rótulo y, mientras están vacíos,
     una barra ámbar a la izquierda: el mismo ámbar del chip «Falta:».
   ═══════════════════════════════════════════════════════════════════════════ */

.pan-form-cuerpo { width: 100%; margin-top: 12px; }

/* Los diálogos de Radzen (altas rápidas, contactos, selectores) deben quedar SOBRE
   el pan-modal (z-index 1200) cuando se abren desde una ficha, y SOBRE el menú
   lateral (1050); los popups de Radzen ya van en 2000.

   Con «:root» esto no se aplicaba nunca: el tema de Radzen (software-base.css) se
   carga DESPUÉS de este archivo y su propio «:root» pone 1001 y 1000; a igual
   especificidad gana el último. Los diálogos quedaban en 1001, debajo del menú
   lateral, y uno ancho se escondía detrás de él (octubre de 2026: «Seleccionar
   facturas para la liquidación» con la columna del proveedor tapada). «html:root»
   pesa más que «:root» y gana sin depender del orden de carga.

   Lo que se abre DESDE un diálogo tiene que ir por encima: las notificaciones de
   Radzen (1002 de fábrica) suben a 1350, y SweetAlert (confirmaciones, avisos y
   el velo) a 1400, como ya iba la capa pan-avisos-capa. */
html:root { --rz-dialog-zindex: 1300; --rz-dialog-mask-zindex: 1299; }
html .rz-notification { z-index: 1350; }
body .swal2-container { z-index: 1400; }

/* Caja de cada paso (pan-tarjeta trae padding 0: está hecha para rejillas) */
.pan-form-caja {
    background: #fff; border: 1px solid var(--pan-linea); border-radius: var(--pan-radio);
    padding: 14px 22px 20px; margin: 0 0 14px; box-shadow: 0 1px 2px rgba(0,0,0,.04);
}
.pan-form-caja.pan-form-cerrada { padding-bottom: 14px; }
.pan-form-caja .pan-vacio { padding: 12px 10px; gap: 4px; background: #f8f9fb; border: 1px dashed #c3cdd8; border-radius: var(--pan-radio); }
.pan-form-caja .pan-vacio h4 { font-size: 14px; margin: 2px 0 0; }
.pan-form-caja .pan-vacio p { margin: 0 0 6px; }

/* Banda de encabezado del paso: contrae/expande al hacer clic */
.pan-form-paso {
    display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
    margin: -14px -22px 16px; padding: 10px 22px;
    background: #f3f5f8; border-bottom: 1px solid var(--pan-linea);
    border-radius: var(--pan-radio) var(--pan-radio) 0 0;
    cursor: pointer; user-select: none;
}
.pan-form-paso:hover { background: #eef1f5; }
.pan-form-paso.pan-form-fija { cursor: default; }
.pan-form-cerrada .pan-form-paso { margin-bottom: -14px; border-bottom: 0; border-radius: var(--pan-radio); }
.pan-form-num {
    width: 26px; height: 26px; border-radius: 50%; background: #1a1a1a; color: #fff;
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 13px; font-weight: 700; flex: none; transition: background .25s;
}
.pan-form-num.ok { background: var(--pan-verde); }
.pan-form-num .rzi { font-size: 16px; }
.pan-form-paso h5 { margin: 0; font-weight: 700; letter-spacing: .3px; font-size: 15px; }
.pan-form-paso .pan-form-pista { margin-left: auto; font-size: 12px; color: #777; }
.pan-form-paso .pan-form-resumen {
    margin-left: auto; font-size: 12.5px; color: #333; font-weight: 500;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 62%;
}
.pan-form-paso .pan-form-acciones { display: flex; align-items: center; gap: 8px; }
.pan-form-chevron { color: #888; flex: none; }
.pan-form-mini-rotulo { font-size: 11px; letter-spacing: .6px; text-transform: uppercase; color: #666; font-weight: 600; }

/* Franja de datos resueltos: una celda gris por dato, sin cajas blancas */
.pan-form-fijos { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px 18px; margin-bottom: 4px; }
.pan-form-fijo {
    display: flex; flex-direction: column; gap: 3px; min-width: 0;
    background: #e9edf2; border: 1px solid #d9dfe6; border-radius: 6px; padding: 8px 12px;
}
.pan-form-fijo-rotulo {
    display: inline-flex; align-items: center; gap: 4px; font-size: 10.5px; letter-spacing: .6px;
    text-transform: uppercase; color: #7f8a96; font-weight: 600;
}
.pan-form-fijo-rotulo .rzi { font-size: 13px; }
.pan-form-fijo-valor {
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    font-size: 14px; color: #3d4b59; font-weight: 500; min-height: 24px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.pan-form-fijos .rz-dropdown { background: #fff !important; border: 1px solid #b7c3d0 !important; border-radius: 6px !important; }

/* Cuadrícula de 12 columnas para los campos */
.pan-form-campos { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 14px 18px; align-items: start; }
.pan-form-c2 { grid-column: span 2; }
.pan-form-c3 { grid-column: span 3; }
.pan-form-c4 { grid-column: span 4; }
.pan-form-c5 { grid-column: span 5; }
.pan-form-c6 { grid-column: span 6; }
.pan-form-c7 { grid-column: span 7; }
.pan-form-c8 { grid-column: span 8; }
.pan-form-c9 { grid-column: span 9; }
.pan-form-c12 { grid-column: span 12; }
.pan-form-campos .rz-form-field { width: 100%; }
.pan-form-bloque { margin-top: 14px; }

/* Un solo estilo de rótulo (los flotantes de Radzen incluidos) */
.pan-form-rotulo,
.pan-form-caja .rz-form-field-label {
    display: block; font-size: 10.5px; letter-spacing: .6px; text-transform: uppercase;
    color: #666; font-weight: 600; margin: 0 0 4px;
}
.pan-form-caja .rz-form-field-label { margin: 0; }
.pan-form-rotulo.pan-form-req::after,
.rz-form-field.pan-form-req .rz-form-field-label::after,
.pan-form-mini-rotulo.pan-form-req::after { content: " •"; color: var(--pan-rojo); font-weight: 700; }
.rz-form-field.pan-form-solo .rz-form-field-label::before {
    font-family: 'Material Symbols Outlined'; content: "lock"; font-size: 12px;
    vertical-align: -2px; margin-right: 3px; color: #98a6b4;
}
.pan-form-hint { font-size: 11.5px; color: #888; margin: 3px 0 0; }

/* Editable: la única caja de la pantalla */
.pan-form-caja .rz-form-field.rz-variant-flat {
    background: #fff !important; border: 1px solid #b7c3d0 !important; border-radius: 6px !important;
    box-shadow: inset 0 1px 2px rgba(16, 34, 51, .05);
    transition: background .15s, border-color .15s, box-shadow .15s;
}
.pan-form-caja .rz-form-field.rz-variant-flat .rz-form-field-content { background: transparent !important; }
.pan-form-caja .rz-form-field.rz-variant-flat:hover { border-color: #91a2b4 !important; }
.pan-form-caja .rz-form-field.rz-variant-flat:focus-within {
    background: #fff !important; border-color: var(--pan-azul) !important;
    box-shadow: 0 0 0 3px rgba(24,95,165,.12);
}

/* Resuelto dentro de un RadzenFormField (pan-form-solo o control deshabilitado) */
.pan-form-caja .rz-form-field.rz-variant-flat.pan-form-solo,
.pan-form-caja .rz-form-field.rz-variant-flat:has(.rz-state-disabled) {
    background: transparent !important; border: 0 !important;
    border-bottom: 1px dashed #d7dee6 !important; border-radius: 0 !important; box-shadow: none !important;
}
.pan-form-caja .rz-form-field.pan-form-solo .rz-inputtext,
.pan-form-caja .rz-form-field.pan-form-solo .rz-dropdown-label,
.pan-form-caja .rz-form-field:has(.rz-state-disabled) .rz-inputtext,
.pan-form-caja .rz-form-field:has(.rz-state-disabled) .rz-dropdown-label { color: #56687a !important; opacity: 1 !important; }
.pan-form-caja .rz-form-field.pan-form-solo .rz-dropdown-trigger,
.pan-form-caja .rz-form-field.pan-form-solo .rz-datepicker-trigger,
.pan-form-caja .rz-form-field:has(.rz-state-disabled) .rz-dropdown-trigger,
.pan-form-caja .rz-form-field:has(.rz-state-disabled) .rz-datepicker-trigger { display: none !important; }
.pan-form-caja .rz-form-field .rz-dropdown,
.pan-form-caja .rz-form-field .rz-textbox,
.pan-form-caja .rz-form-field .rz-numeric,
.pan-form-caja .rz-form-field .rz-datepicker .rz-inputtext { background: transparent !important; border: 0 !important; box-shadow: none !important; }

/* Obligatorio vacío: barra ámbar a la izquierda */
.pan-form-caja .rz-form-field.rz-variant-flat.pan-form-req:has(.rz-state-empty) {
    border-inline-start: 3px solid #e8a33d !important; background: #fffdf8 !important;
}
.pan-form-caja .rz-form-field.rz-variant-flat.pan-form-req:has(.rz-state-empty):focus-within {
    border-inline-start-color: var(--pan-azul) !important; background: #fff !important;
}

/* Controles sueltos (fuera de RadzenFormField) */
.pan-form-caja .pan-form-inline .rz-dropdown,
.pan-form-caja .pan-form-inline .rz-numeric,
.pan-form-caja .pan-form-inline .rz-textbox,
.pan-form-caja .pan-form-campos > div > .rz-datepicker,
.pan-form-caja .pan-form-campos > div > .rz-dropdown,
.pan-form-caja .pan-form-campos > div > .rz-textbox,
.pan-form-caja .pan-form-campos > div > .rz-numeric,
.pan-form-caja textarea.form-control,
.pan-form-caja input.form-control {
    background: #fff !important; border: 1px solid #b7c3d0 !important; border-radius: 6px !important;
    box-shadow: inset 0 1px 2px rgba(16, 34, 51, .05);
}
.pan-form-caja .pan-form-inline .rz-dropdown:hover,
.pan-form-caja .pan-form-campos > div > .rz-datepicker:hover,
.pan-form-caja textarea.form-control:hover,
.pan-form-caja input.form-control:hover { border-color: #91a2b4 !important; }
.pan-form-caja .pan-form-campos > div > .rz-datepicker .rz-inputtext { border: 0 !important; background: transparent !important; }
.pan-form-caja .pan-form-inline .rz-dropdown:focus-within,
.pan-form-caja .pan-form-campos > div > .rz-datepicker:focus-within,
.pan-form-caja .pan-form-campos > div > .rz-dropdown:focus-within,
.pan-form-caja textarea.form-control:focus,
.pan-form-caja input.form-control:focus {
    background: #fff !important; border-color: var(--pan-azul) !important;
    box-shadow: 0 0 0 3px rgba(24,95,165,.12);
}
.pan-form-caja .pan-form-rotulo.pan-form-req + textarea.form-control:placeholder-shown,
.pan-form-caja .pan-form-rotulo.pan-form-req + input.form-control:placeholder-shown {
    border-inline-start: 3px solid #e8a33d !important; background: #fffdf8 !important;
}
.pan-form-caja .pan-form-rotulo.pan-form-req + .pan-form-inline .rz-dropdown:has(.rz-state-empty),
.pan-form-caja .pan-form-rotulo.pan-form-req + .pan-form-inline .rz-dropdown.rz-state-empty {
    border-inline-start: 3px solid #e8a33d !important; background: #fffdf8 !important;
}
.pan-form-caja textarea.form-control { padding: 9px 11px; font-size: 14px; resize: vertical; }
.pan-form-inline { display: flex; align-items: center; gap: 8px; max-width: 680px; }
.pan-form-inline .rz-dropdown, .pan-form-inline .form-select, .pan-form-inline .rz-textbox { flex: 1; min-width: 0; }
.pan-form-nota { background: #f6f7f9; border-radius: 8px; padding: 8px 12px; font-size: 12.5px; color: #555; margin-top: 8px; max-width: 680px; }
.pan-form-tabla { border: 1px solid var(--pan-linea); border-radius: var(--pan-radio); overflow: hidden; }
.pan-form-chip-color {
    display: inline-block; padding: 3px 14px; border-radius: 999px; color: #fff;
    font-size: 12px; font-weight: 700; letter-spacing: .4px; white-space: nowrap;
    box-shadow: 0 1px 2px rgba(0,0,0,.25);
}

/* Zona de arrastrar y soltar archivos */
.pan-form-soltar {
    position: relative; cursor: pointer;
    border: 2px dashed #b7c3d0; border-radius: var(--pan-radio); padding: 16px; text-align: center;
    color: #6b7681; font-size: 13px; background: #fafbfc; transition: background .15s, border-color .15s;
}
.pan-form-soltar:hover, .pan-form-soltar.activa { background: #f0f6fc; border-color: var(--pan-azul); }
/* El input cubre la zona entera y transparente: así el clic y el soltar caen sobre él */
.pan-form-soltar input[type=file] {
    display: block !important; position: absolute; inset: 0;
    width: 100%; height: 100%; opacity: 0; cursor: pointer;
}
.pan-form-soltar input[type=file][disabled] { cursor: not-allowed; }

/* Barra de envío fija: resumen, lo que falta y el botón acompañan hasta el final */
.pan-form-envio {
    position: sticky; bottom: 0; z-index: 5;
    display: flex; align-items: center; gap: 14px;
    background: #fff; border-top: 1px solid rgba(0,0,0,.12);
    box-shadow: 0 -4px 14px rgba(0,0,0,.08);
    padding: 10px 14px; margin: 14px 0 0; border-radius: 8px 8px 0 0;
}
.pan-form-envio-resumen { display: flex; flex-direction: column; min-width: 180px; }
.pan-form-envio-resumen b { font-size: 18px; }
.pan-form-envio-resumen span { font-size: 12px; color: #777; }
.pan-form-chip {
    display: inline-flex; align-items: center; gap: 6px; padding: 5px 12px;
    border-radius: 999px; font-size: 12px; font-weight: 600; white-space: nowrap;
    max-width: 46%; overflow: hidden; text-overflow: ellipsis;
}
.pan-form-chip .rzi { font-size: 16px; }
.pan-form-chip-ok { background: #e6f6ee; color: #135c3c; }
.pan-form-chip-falta { background: #fff4e5; color: #7a3a0f; }
.pan-form-envio .pan-form-boton { flex: 1; }

/* El «Cancelar» de la barra (Light con contorno) se leía apagado con este tema,
   como si estuviera deshabilitado (octubre de 2026). Habilitado, lleva el texto y
   el borde de un botón que se puede pulsar; el deshabilitado de verdad sigue tenue. */
.pan-form-envio .rz-button.rz-light.rz-variant-outlined:not(.rz-state-disabled) {
    color: #3d4b59; border-color: #9fb0c1; box-shadow: inset 0 0 0 1px #9fb0c1;
}
.pan-form-envio .rz-button.rz-light.rz-variant-outlined:not(.rz-state-disabled):hover {
    color: #1f2d3a; background: #f1f4f7; border-color: #5b7186; box-shadow: inset 0 0 0 1px #5b7186;
}

/* Dentro de un diálogo (alta rápida): sin cabecera, cajas compactas y barra no fija */
.pan-form-dialogo .pan-form-caja { padding: 12px 16px 16px; }
.pan-form-dialogo .pan-form-paso { margin: -12px -16px 14px; padding: 8px 16px; }
.pan-form-dialogo .pan-form-envio { position: static; box-shadow: none; border-top: 1px solid var(--pan-linea); margin-top: 8px; padding: 10px 0 0; border-radius: 0; }

@media (max-width: 900px) {
    .pan-form-envio { flex-wrap: wrap; }
    .pan-form-chip { max-width: 100%; white-space: normal; }
    /* El botón de envío va en su propio renglón, a lo ancho: con botones extra
       al lado se encogía hasta esconder el rótulo (septiembre de 2026:
       «AUTORIZAR Y APLICAR» quedaba en 47 px en el teléfono). */
    .pan-form-envio .pan-form-boton { flex: 1 1 100%; }
    .pan-form-c2, .pan-form-c3, .pan-form-c4, .pan-form-c5, .pan-form-c6, .pan-form-c7, .pan-form-c8, .pan-form-c9 { grid-column: span 12; }
    .pan-form-fijos { grid-template-columns: repeat(2, minmax(0, 1fr)) !important; }
    .pan-form-caja { padding: 12px 14px 16px; }
    .pan-form-paso { margin: -12px -14px 14px; padding: 10px 14px; }
    .pan-form-cerrada .pan-form-paso { margin-bottom: -12px; }
    .pan-form-paso .pan-form-resumen { max-width: 100%; margin-left: 0; }
}

@media print {
    .pan-form-envio, .pan-form-paso .pan-form-acciones, .pan-form-chevron { display: none !important; }
    .pan-form-caja { break-inside: avoid; box-shadow: none; }
}

/* ═══════════════════ Avisos que se ven desde donde uno está ═══════════════════ */

/*
    ── Por qué existen ───────────────────────────────────────────────────────
    En una pantalla larga —mil filas de conciliación, un formulario de doce
    pasos— el mensaje de error de arriba y la barra de progreso de la cabecera
    quedan fuera de la vista cuando se pulsa el botón de la barra de abajo. El
    usuario no se entera de que faltó algo ni de que el servidor está
    trabajando hasta que sube. Tres piezas lo resuelven, y las tres son de la
    plataforma y no de una pantalla:

      · la LÍNEA DE PROGRESO se pega al borde superior de la ventana mientras
        la pantalla se desplaza (es la misma RadzenProgressBar de siempre);
      · la TOSTADA (panAviso) sale arriba a la derecha, sin tapar la barra de
        envío, dice qué pasó y se va sola;
      · el VELO (panEsperar) cubre la página con una rueda mientras el
        servidor trabaja, y bloquea a propósito.

    Las dos últimas van sobre SweetAlert2 —que la página ya cargaba para las
    confirmaciones— vestido con la paleta y la letra de aquí, para que no
    parezca un componente de otra aplicación.
*/

/* La línea de progreso indeterminada de la cabecera, pegada al borde superior
   del contenedor que se desplaza (main en escritorio, la página en móvil). Sólo
   la indeterminada: las barras con porcentaje son contenido, no señal. */
.pan-pantalla-fluida .rz-progressbar.rz-progressbar-indeterminate {
    position: sticky;
    top: 0;
    z-index: 7;
    box-shadow: 0 1px 0 rgba(255, 255, 255, .6);
}

/* La capa de SweetAlert2 va por encima de la ficha emergente (1200) y de los
   diálogos de Radzen (1300): un aviso disparado desde dentro de un diálogo
   tiene que verse. */
.swal2-container.pan-avisos-capa { z-index: 1400; }

/* ── La tostada ── */
.swal2-popup.swal2-toast.pan-tostada {
    font-family: var(--pan-sans);
    flex-direction: column;
    align-items: stretch;
    width: auto;
    min-width: 280px;
    max-width: 440px;
    padding: 11px 16px 12px 18px;
    border-radius: var(--pan-radio);
    background: var(--pan-papel);
    border: 1px solid var(--pan-linea);
    box-shadow: 0 1px 2px rgba(12, 39, 64, .06), 0 16px 36px -14px rgba(12, 39, 64, .45);
    overflow: hidden;
    --pan-acento: var(--pan-azul);
}
.pan-tostada.pan-tostada-success  { --pan-acento: var(--pan-verde); }
.pan-tostada.pan-tostada-error    { --pan-acento: var(--pan-rojo); }
.pan-tostada.pan-tostada-warning  { --pan-acento: var(--pan-ambar); }
.pan-tostada.pan-tostada-info,
.pan-tostada.pan-tostada-question { --pan-acento: var(--pan-azul); }

/* El canto de color: es la única señal de tipo además del icono, y basta. */
.swal2-popup.pan-tostada::before {
    content: "";
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 4px;
    background: var(--pan-acento);
}

.pan-tostada .swal2-header {
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    gap: 10px;
    padding: 0;
}
.pan-tostada .swal2-title {
    margin: 0;
    padding: 0;
    font-size: 13px;
    font-weight: 700;
    letter-spacing: .1px;
    color: var(--pan-tinta);
    text-align: left;
    justify-content: flex-start;
}
.pan-tostada .swal2-content,
.pan-tostada .swal2-html-container {
    margin: 3px 0 0 calc(1.7em + 10px);
    padding: 0;
    font-size: 12.5px;
    line-height: 1.45;
    color: var(--pan-apagado);
    text-align: left;
    justify-content: flex-start;
}
/* El icono de SweetAlert2, a la medida y en la paleta de aquí. */
.pan-tostada .swal2-icon {
    width: 1.7em; height: 1.7em; min-width: 1.7em;
    margin: 0;
    border-width: 2px;
    font-size: 14px;
}
.pan-tostada .swal2-icon .swal2-icon-content { font-size: 1.25em; font-weight: 700; }
.pan-tostada .swal2-icon.swal2-success { border-color: var(--pan-verde); color: var(--pan-verde); }
.pan-tostada .swal2-icon.swal2-success [class^="swal2-success-line"] { background-color: var(--pan-verde); }
.pan-tostada .swal2-icon.swal2-success .swal2-success-ring { border-color: rgba(28, 138, 90, .35); }
.pan-tostada .swal2-icon.swal2-error { border-color: var(--pan-rojo); color: var(--pan-rojo); }
.pan-tostada .swal2-icon.swal2-error [class^="swal2-x-mark-line"] { background-color: var(--pan-rojo); }
.pan-tostada .swal2-icon.swal2-warning { border-color: var(--pan-ambar); color: var(--pan-ambar); }
.pan-tostada .swal2-icon.swal2-info,
.pan-tostada .swal2-icon.swal2-question { border-color: var(--pan-azul); color: var(--pan-azul); }

/* La cuenta atrás, en el color del tipo y discreta. */
.pan-tostada .swal2-timer-progress-bar {
    height: 3px;
    background: var(--pan-acento);
    opacity: .55;
}

/* ── El velo ── */
.swal2-container.pan-velo-fondo {
    background: rgba(12, 39, 64, .42);
    backdrop-filter: blur(2px);
}
.swal2-popup.pan-velo {
    font-family: var(--pan-sans);
    width: 380px;
    max-width: calc(100vw - 32px);
    padding: 26px 28px 26px;
    border-radius: 14px;
    background: var(--pan-papel);
    box-shadow: 0 2px 4px rgba(12, 39, 64, .08), 0 28px 64px -22px rgba(12, 39, 64, .6);
}
.pan-velo .swal2-header { padding: 0; }
.pan-velo .swal2-title {
    margin: 0 0 4px;
    padding: 0;
    font-size: 17px;
    font-weight: 700;
    color: var(--pan-tinta);
    letter-spacing: -.1px;
}
/* La ceja de arriba, como el rótulo de empresa de las cabeceras. */
.pan-velo .swal2-title::before {
    content: "Un momento";
    display: block;
    margin-bottom: 8px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: .8px;
    text-transform: uppercase;
    color: var(--pan-apagado);
}
.pan-velo .swal2-content,
.pan-velo .swal2-html-container {
    padding: 0;
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--pan-apagado);
}
.pan-velo .swal2-actions { margin: 20px 0 0; }
/* La rueda: azul institucional sobre línea tenue, sin el amarillo de fábrica. */
.pan-velo .swal2-loader,
.pan-velo .swal2-actions.swal2-loading .swal2-confirm {
    width: 2.4em; height: 2.4em;
    border-width: 3px;
    border-color: var(--pan-azul) var(--pan-linea) var(--pan-azul) var(--pan-linea);
}

@media (max-width: 640px) {
    .swal2-popup.swal2-toast.pan-tostada { max-width: calc(100vw - 24px); }
}

@media print {
    .swal2-container { display: none !important; }
}

/* ═══════════════════ Estados de una operación (PanEstado) ═══════════════════ */

/*
    ── Seis desenlaces, cuatro colores ───────────────────────────────────────
    Error (rojo, .pan-error) y confirmado (verde, .pan-aviso) ya existían. Se
    suman dos hermanos con la MISMA geometría —misma altura, mismo relleno,
    mismo radio— para que la fila no salte según cuál aparezca:

      .pan-parcial    ámbar: una parte quedó y otra no. No es un error —algo
                      SÍ se guardó y repetirlo todo lo duplicaría—, así que no
                      puede ir en rojo; tampoco es un logro.
      .pan-conflicto  violeta: el registro cambió o ya está en otro estado. Ni
                      rojo (no falló nada) ni ámbar (no quedó nada a medias):
                      hay que mirar cómo quedó antes de seguir.

    Cargando y sin registros usan el esqueleto y el vacío de siempre. Lo que
    sí es nuevo es el cuerpo de dos líneas (título y detalle), las listas de lo
    que quedó y lo que falta, y el sitio de los botones a la derecha.
*/
:root {
    --pan-violeta: #6a3fa0;
    --pan-ambar-claro: #e8a33d;
}

.pan-parcial {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
    padding: 6px 12px;
    border-radius: 8px;
    border: 1px solid rgba(184, 84, 27, .30);
    border-left: 3px solid var(--pan-ambar-claro);
    background: rgba(232, 163, 61, .10);
    color: #8a3d10;
    font-size: 12.5px;
}

.pan-conflicto {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
    padding: 6px 12px;
    border-radius: 8px;
    border: 1px solid rgba(106, 63, 160, .30);
    background: rgba(106, 63, 160, .07);
    color: #56308a;
    font-size: 12.5px;
}

.pan-parcial > .rzi, .pan-parcial > .rz-icon,
.pan-conflicto > .rzi, .pan-conflicto > .rz-icon,
.pan-estado > .rzi, .pan-estado > .rz-icon { flex: none; }

/* El cuerpo: título en negrita y, debajo, qué significa. Se estira para
   empujar los botones al extremo derecho, igual que el <span> de los banners
   de siempre. */
.pan-estado-cuerpo {
    display: flex;
    flex-direction: column;
    gap: 1px;
    flex: 1 1 auto;
    min-width: 0;
}
.pan-estado-titulo { font-weight: 700; }
.pan-estado-detalle { opacity: .92; line-height: 1.4; }

.pan-parcial > span,
.pan-conflicto > span {
    flex: 1 1 auto;
    min-width: 0;
}

/* Más específico que «.pan-error > span» (que estira todo span hijo): los
   botones se quedan de su tamaño y a la derecha. */
.pan-estado > .pan-estado-acciones,
.pan-borrador > .pan-estado-acciones,
.pan-sesion > .pan-estado-acciones { flex: none; }

.pan-estado-acciones {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex: none;
    flex-wrap: wrap;
    justify-content: flex-end;
}

/* Lo que quedó (✓) y lo que falta: pastillas pequeñas, para leerlo de un vistazo. */
.pan-estado-listas { display: flex; flex-wrap: wrap; gap: 4px 6px; margin-top: 4px; }
.pan-estado-hecho,
.pan-estado-falta {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 1px 8px 1px 5px;
    border-radius: 999px;
    font-size: 11.5px;
    font-weight: 600;
    white-space: nowrap;
}
.pan-estado-hecho { background: rgba(28, 138, 90, .10); color: #16704a; }
.pan-estado-falta { background: rgba(232, 163, 61, .20); color: #7a3a0f; }
.pan-estado-hecho .rzi, .pan-estado-falta .rzi { font-size: 14px; }

/* El banner recibe el foco tras un envío fallido (PanEstado Enfocar): que se vea. */
.pan-estado:focus { outline: none; }
.pan-estado:focus-visible { outline: 2px solid var(--pan-azul); outline-offset: 2px; }

.pan-estado-cerrado { display: none !important; }

/* Compacto: dentro de un paso, una tarjeta o la barra de envío. */
.pan-estado-compacto { padding: 5px 10px; font-size: 12px; }
.pan-estado-compacto .pan-estado-detalle { font-size: 11.5px; }

/* «Consultando…» en una línea: tres puntos que laten, sin rueda. */
.pan-estado-cargando {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 2px;
    font-size: 12px;
    color: var(--pan-apagado);
}
.pan-estado-puntos { display: inline-flex; gap: 3px; }
.pan-estado-puntos i {
    width: 5px; height: 5px; border-radius: 50%;
    background: var(--pan-azul);
    opacity: .25;
    animation: pan-latido 1.1s ease-in-out infinite;
}
.pan-estado-puntos i:nth-child(2) { animation-delay: .18s; }
.pan-estado-puntos i:nth-child(3) { animation-delay: .36s; }
@keyframes pan-latido {
    0%, 100% { opacity: .25; transform: scale(.85); }
    50%      { opacity: 1;   transform: scale(1); }
}

/* Sólo para lectores de pantalla: presente para ellos, invisible en pantalla. */
.pan-solo-lector {
    position: absolute !important;
    width: 1px !important;
    height: 1px !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip: rect(0, 0, 0, 0) !important;
    white-space: nowrap !important;
    border: 0 !important;
}

/* ═══════════════════ Borrador y sesión ═══════════════════ */

/*
    El borrador que se ofrece (PanBorrador) va en azul —es un estado, no un
    fallo— con el filo punteado: es trabajo que todavía no está en el servidor.
*/
.pan-borrador {
    display: flex;
    align-items: center;
    gap: 8px;
    flex: 0 0 auto;
    padding: 6px 12px;
    border-radius: 8px;
    border: 1px dashed rgba(24, 95, 165, .45);
    background: rgba(24, 95, 165, .06);
    color: var(--pan-azul);
    font-size: 12.5px;
    margin: 0 0 10px;
}

/*
    La sesión venció: un solo aviso, pegado arriba de cualquier pantalla, que no
    se va hasta volver a ingresar. Lleva sombra porque flota sobre el contenido
    que se desplaza por debajo.
*/
.pan-sesion {
    position: sticky;
    top: 0;
    z-index: 30;
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 0 0 8px;
    padding: 8px 14px;
    border-radius: 0 0 10px 10px;
    border: 1px solid rgba(211, 47, 20, .30);
    border-top: 0;
    background: #fff5f3;
    color: var(--pan-rojo);
    font-size: 12.5px;
    box-shadow: 0 8px 20px -12px rgba(12, 39, 64, .45);
}
.pan-sesion > .rzi, .pan-sesion > .rz-icon { font-size: 22px; flex: none; }

/* ═══════════════════ Pasos y barra: estados y teclado ═══════════════════ */

/* El título del paso es un botón (acordeón accesible) que se ve igual que el
   texto de siempre; el foco del teclado sí se marca. */
.pan-form-paso-boton {
    background: none;
    border: 0;
    padding: 0;
    margin: 0;
    font: inherit;
    color: inherit;
    letter-spacing: inherit;
    text-transform: inherit;
    text-align: left;
    cursor: pointer;
}
.pan-form-paso-boton:focus { outline: none; }
.pan-form-paso-boton:focus-visible {
    outline: 2px solid var(--pan-azul);
    outline-offset: 3px;
    border-radius: 4px;
}

/* El círculo del paso cuenta el estado de sus datos. */
.pan-form-num.error   { background: var(--pan-rojo); }
.pan-form-num.parcial { background: var(--pan-ambar-claro); }
.pan-form-num.cargando { animation: pan-latido 1.1s ease-in-out infinite; }
.pan-form-paso-estado { margin: -4px 0 12px; }
.pan-form-paso-estado .pan-estado-cargando { padding-top: 0; }

/* El error de UN campo (PanCampo), bajo su ayuda. */
.pan-form-error-campo {
    display: flex;
    align-items: center;
    gap: 4px;
    margin: 3px 0 0;
    font-size: 11.5px;
    color: var(--pan-rojo);
}
.pan-form-error-campo .rzi { font-size: 14px; }
.pan-form-caja [aria-invalid="true"],
.pan-form-caja .rz-form-field:has([aria-invalid="true"]) { border-color: var(--pan-rojo) !important; }

/* La barra de envío con el resultado encima de sus controles. */
.pan-form-envio.pan-form-envio-con-estado { flex-wrap: wrap; }
.pan-form-envio-estado { flex: 1 0 100%; order: -1; }
.pan-form-envio-estado > .pan-estado { margin: 0; }
.pan-form-envio-borrador { font-size: 11px; color: var(--pan-tenue); }
.pan-form-envio-borrador.pan-alerta { font-weight: 600; }
.pan-form-envio.pan-form-envio-bloqueada .pan-form-boton { opacity: .85; }

/* Una cifra que no se pudo consultar: se dice, no se enseña un cero. */
.pan-sin-dato {
    font-family: var(--pan-sans) !important;
    font-size: 12px !important;
    font-weight: 600 !important;
    color: var(--pan-ambar) !important;
}

@media (max-width: 640px) {
    .pan-parcial, .pan-conflicto, .pan-estado, .pan-borrador, .pan-sesion { flex-wrap: wrap; }
    .pan-estado-acciones { width: 100%; justify-content: flex-start; }
}

/* Con el dedo (teléfono o tableta, de cualquier ancho), REINTENTAR y compañía
   miden 40 px de alto: el botón extrachico de Radzen (20 px) es para el ratón. */
@media (pointer: coarse) {
    .pan-estado-acciones .rz-button { min-height: 40px; padding-inline: 12px; }
}

@media (prefers-reduced-motion: reduce) {
    .pan-estado-puntos i,
    .pan-form-num.cargando { animation: none !important; }
    .pan-estado-puntos i { opacity: .7; }
}

@media print {
    .pan-sesion, .pan-borrador, .pan-estado, .pan-form-paso-estado { display: none !important; }
}

