/* EL ENSUEÑO — estilos base.
 * Layout: navbar + (sidebar pegado a la izquierda | contenido)
 * Theming: light por default, [data-bs-theme="dark"] sobreescribe tokens.
 *
 * Paleta agro: verde bosque (#166534) + dorado trigo (#F0B429).
 * El naranja quedó reservado para el estado "warning" y el teal para "info":
 * son semántica, no marca. Tipografía: Inter (cargada en base.html).
 */

/* ============================================================
 * 1. Design tokens
 * ============================================================ */
:root {
    /* Brand — verde + dorado */
    --pzf-primary: #166534;          /* verde bosque, 7.13:1 sobre blanco */
    --pzf-primary-hover: #0F4A26;
    --pzf-primary-rgb: 22, 101, 52;
    --pzf-primary-soft: rgba(22, 101, 52, .10);
    /* En claro el primario ya contrasta como texto; en oscuro diverge del
       relleno porque ningún verde sirve a la vez de fondo y de texto. */
    --pzf-primary-text: var(--pzf-primary);
    --pzf-primary-text-hover: var(--pzf-primary-hover);

    /* El teal dejó de ser color de marca. Sobrevive como 3ra serie de gráfico
       (charts.js): verde y dorado solos no alcanzan para 5 series. Para el
       tono semántico "info" usar --pzf-info, no esto. */
    --pzf-accent: #2DA4C4;
    --pzf-accent-rgb: 45, 164, 196;
    --pzf-accent-soft: rgba(45, 164, 196, .14);

    --pzf-gold: #F0B429;             /* dorado trigo */
    --pzf-gold-hover: #D89E14;
    --pzf-gold-rgb: 240, 180, 41;
    --pzf-gold-soft: rgba(240, 180, 41, .16);
    /* El dorado no admite texto blanco encima (1.86:1): va casi negro. */
    --pzf-on-gold: #241C05;
    /* Y como texto/icono sobre fondo claro necesita esta versión oscurecida. */
    --pzf-gold-text: #8A6206;

    --pzf-success: #15A36B;
    --pzf-success-rgb: 21, 163, 107;
    --pzf-warning: #E8763A;          /* naranja: atención/pendiente */
    --pzf-warning-rgb: 232, 118, 58;
    --pzf-danger:  #DC3545;
    --pzf-danger-rgb: 220, 53, 69;
    --pzf-info:    #2A8FA8;
    --pzf-info-rgb: 42, 143, 168;

    /* El naranja de --pzf-warning no llega a 4.5:1 sobre fondo claro: para
       texto e iconos va esta versión oscurecida. En oscuro se aclara. */
    --pzf-warning-text: #B4501C;
    /* Texto sobre un relleno de color (primary, danger, etc.) */
    --pzf-on-color: #FFFFFF;
    --pzf-on-warning: #2E1405;
    /* Relleno del tono "secondary" (gris Bootstrap), antes literal ×7. */
    --pzf-secondary-soft: var(--pzf-secondary-soft);

    /* Surfaces */
    --pzf-bg: #F5F8F4;
    --pzf-surface: #FFFFFF;
    --pzf-surface-2: #EBF1EA;
    --pzf-surface-alt: #FFFFFF;      /* sidebar */

    /* Text */
    --pzf-text: #26332B;
    --pzf-text-muted: #64748B;

    /* Borders */
    --pzf-border: #E2E8F0;
    --pzf-border-strong: #CBD5E1;

    /* Effects */
    --pzf-hover: rgba(22, 101, 52, .07);
    --pzf-focus-ring: 0 0 0 .2rem rgba(22, 101, 52, .24);
    --pzf-shadow-sm: 0 1px 2px rgba(15, 23, 42, .04), 0 1px 1px rgba(15, 23, 42, .03);
    --pzf-shadow:    0 4px 14px rgba(15, 23, 42, .07), 0 1px 3px rgba(15, 23, 42, .04);
    --pzf-shadow-lg: 0 18px 38px rgba(15, 23, 42, .11), 0 4px 10px rgba(15, 23, 42, .05);

    /* Geometry */
    --pzf-radius-sm: .4rem;
    --pzf-radius: .6rem;
    --pzf-radius-lg: .85rem;

    /* Easing */
    --pzf-ease: cubic-bezier(.4, 0, .2, 1);
    --pzf-ease-out: cubic-bezier(.16, 1, .3, 1);
    --pzf-ease-spring: cubic-bezier(.34, 1.56, .64, 1);

    /* Layout */
    --pzf-navbar-h: 52px;
    --pzf-sidebar-w: 240px;
    --pzf-sidebar-w-collapsed: 60px;
    --pzf-sidebar-current: var(--pzf-sidebar-w);
}

[data-bs-theme="dark"] {
    /* El verde bosque da 2.24:1 sobre superficie oscura: ilegible. Acá el
       relleno se aclara lo justo para sostener texto blanco (4.54:1) y el
       texto/link usa un verde bastante más claro. */
    --pzf-primary: #2F855A;
    --pzf-primary-hover: #37A06C;
    --pzf-primary-rgb: 47, 133, 90;
    --pzf-primary-text: #5DBE7D;
    --pzf-primary-text-hover: #85DDA8;

    --pzf-bg: #0F1512;
    --pzf-surface: #141A17;
    --pzf-surface-2: #1B231E;
    --pzf-surface-alt: #111713;

    --pzf-text: #E4EDE7;
    --pzf-text-muted: #93A69A;

    /* Con el primario verde, el verde esmeralda de "success" queda demasiado
       cerca en oscuro (1.40:1). Se corre a menta para que el badge de estado
       no se confunda con un botón de marca. */
    --pzf-success: #2DD4A7;
    --pzf-success-rgb: 45, 212, 167;

    /* Sobre fondo oscuro el naranja y el dorado ya contrastan de sobra. */
    --pzf-warning-text: #F0996B;
    --pzf-gold-text: #F0B429;

    --pzf-border: #2A3830;
    --pzf-border-strong: #3C5147;

    --pzf-hover: rgba(93, 190, 125, .15);
    --pzf-focus-ring: 0 0 0 .2rem rgba(93, 190, 125, .35);
    --pzf-primary-soft: rgba(93, 190, 125, .15);
    --pzf-shadow-sm: 0 1px 2px rgba(0, 0, 0, .35);
    --pzf-shadow:    0 4px 14px rgba(0, 0, 0, .45);
    --pzf-shadow-lg: 0 18px 38px rgba(0, 0, 0, .60);
}

/* ============================================================
 * 2. Reset / base
 * ============================================================ */
html, body { height: 100vh; }

body {
    background: var(--pzf-bg);
    color: var(--pzf-text);
    display: flex;
    flex-direction: column;
    overflow: hidden; /* el body no scrollea: navbar fija arriba, scroll va en .pzf-page-main */
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
                 Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
    font-feature-settings: 'cv02', 'cv03', 'cv04', 'cv11';
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

main { flex: 1 1 auto; min-height: 0; }

a { color: var(--pzf-primary-text); text-decoration: none; }
a:hover { color: var(--pzf-primary-text-hover); }

code, kbd {
    background: var(--pzf-surface-2);
    color: var(--pzf-text);
    border: 1px solid var(--pzf-border);
    border-radius: .25rem;
    padding: 0 .3rem;
    font-size: .875em;
}
/* Dentro de tablas, code se usa para valores numéricos —
 * no queremos el fondo gris de "código" ahí. */
.table code,
.pzf-table code {
    background: transparent;
    border: 0;
    padding: 0;
    color: inherit;
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
    font-size: inherit;
    font-variant-numeric: tabular-nums;
}
pre {
    background: var(--pzf-surface-2);
    color: var(--pzf-text);
    border: 1px solid var(--pzf-border);
    border-radius: var(--pzf-radius-sm);
    padding: .75rem 1rem;
    overflow-x: auto;
}

.text-muted { color: var(--pzf-text-muted) !important; }

/* Selección de texto con el azul de marca */
::selection { background: var(--pzf-primary-soft); color: var(--pzf-text); }

/* Scrollbars sutiles */
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
    background: var(--pzf-border-strong);
    border-radius: 6px;
    border: 2px solid transparent;
    background-clip: padding-box;
}
*::-webkit-scrollbar-thumb:hover {
    background: var(--pzf-text-muted);
    background-clip: padding-box;
}

/* ============================================================
 * 3. Topbar (navbar superior) — clase .pzf-topbar
 * Look: blanca, borde inferior, items grises con underline animado.
 * ============================================================ */
.navbar.pzf-topbar {
    background: var(--pzf-surface);
    border-bottom: 1px solid var(--pzf-border);
    box-shadow: var(--pzf-shadow-sm);
    min-height: var(--pzf-navbar-h);
    padding-top: .2rem;
    padding-bottom: .2rem;
    /* `body` es un flex column de altura fija: sin esto el navbar se comprime
     * y el menú desplegado queda cortado al medio. */
    flex-shrink: 0;
}

.pzf-topbar .navbar-brand {
    display: inline-flex;
    align-items: center;
    gap: .65rem;
    font-weight: 700;
    letter-spacing: -.01em;
    color: var(--pzf-text);
    padding: 0;
}
.pzf-topbar .navbar-brand:hover { color: var(--pzf-primary-text); }

.pzf-brand-mark {
    width: 30px;
    height: 30px;
    border-radius: 8px;
    background: linear-gradient(135deg, var(--pzf-primary) 0%, var(--pzf-primary-hover) 45%, var(--pzf-gold) 115%);
    color: var(--pzf-on-color);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: .95rem;
    box-shadow: 0 4px 10px rgba(var(--pzf-primary-rgb), .25);
    flex-shrink: 0;
}

/* Emblema de la empresa. Es apaisado (3:2) y transparente, así que se dimensiona
   por alto y va sin plato ni border-radius: encajarlo en el cuadrado de
   .pzf-brand-mark lo dejaba con dos franjas vacías y 20px de alto útil.
   El anillo amarillo lo sostiene contra el fondo claro y el oscuro por igual. */
.pzf-brand-lockup {
    height: 30px;
    width: auto;
    display: block;
    flex-shrink: 0;
}

.pzf-topbar .nav-link {
    color: var(--pzf-text-muted);
    font-weight: 500;
    font-size: .88rem;
    padding: .4rem .75rem;
    border-radius: var(--pzf-radius-sm);
    position: relative;
    transition: color .15s var(--pzf-ease), background-color .15s var(--pzf-ease);
}
.pzf-topbar .nav-link:hover,
.pzf-topbar .nav-link:focus {
    color: var(--pzf-primary-text);
    background: var(--pzf-primary-soft);
}
.pzf-topbar .nav-link.active,
.pzf-topbar .nav-item.show > .nav-link {
    color: var(--pzf-primary-text);
}

/* Underline animado en items principales (no en dropdowns toggleados ni iconos) */
.pzf-topbar .nav-link:not(.dropdown-toggle):not(.pzf-icon-link)::after {
    content: "";
    position: absolute;
    left: .85rem;
    right: .85rem;
    bottom: .25rem;
    height: 2px;
    background: var(--pzf-primary);
    border-radius: 2px;
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform .25s var(--pzf-ease-out);
}
.pzf-topbar .nav-link:not(.dropdown-toggle):not(.pzf-icon-link):hover::after,
.pzf-topbar .nav-link:not(.dropdown-toggle):not(.pzf-icon-link).active::after {
    transform: scaleX(1);
}

.pzf-topbar .pzf-icon-btn {
    color: var(--pzf-text-muted);
    background: transparent;
    border: 0;
    padding: .35rem .55rem;
    border-radius: var(--pzf-radius-sm);
    transition: background .15s var(--pzf-ease), color .15s var(--pzf-ease);
    font-size: 1rem;
    line-height: 1;
}
.pzf-topbar .pzf-icon-btn:hover {
    color: var(--pzf-primary-text);
    background: var(--pzf-primary-soft);
}

.pzf-topbar .navbar-toggler {
    border-color: var(--pzf-border);
    color: var(--pzf-text-muted);
}
.pzf-topbar .navbar-toggler:focus {
    box-shadow: var(--pzf-focus-ring);
}
.pzf-topbar .navbar-toggler-icon {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='%2364748B' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
}

/* Campanita badge */
.pzf-topbar .badge.bg-danger {
    background: var(--pzf-gold) !important;
}

/* Las utilidades (carga rápida, tema, campanita, usuario) viven fuera del
 * .navbar-collapse para seguir accesibles en mobile. En el DOM van antes del
 * toggler — porque el collapse tiene flex-basis:100% y arrastraría a la
 * siguiente fila todo lo que venga después — así que en desktop hay que
 * reordenarlas al extremo derecho. */
@media (min-width: 992px) {
    .pzf-topbar .pzf-topbar-utils { order: 1; }
}

@media (max-width: 991.98px) {
    /* El body no scrollea (ver sección 2): sin esto, el menú desplegado excede
     * el viewport y se recorta sin forma de llegar al final. `dvh` porque en
     * mobile el `vh` no descuenta la barra del navegador. */
    .pzf-topbar .navbar-collapse {
        max-height: 60vh;   /* fallback: sin dvh, la regla entera se descarta */
        max-height: 60dvh;
        overflow-y: auto;
        overscroll-behavior: contain;
    }

    /* La primera fila tiene que entrar entera: si el toggler baja a una
     * segunda fila, tapa el contenido. El único que puede ceder ancho es el
     * nombre de la marca — el resto son targets táctiles. */
    .pzf-topbar .navbar-brand {
        min-width: 0;
        margin-right: .5rem;
        /* A 1.25rem el nombre no entra junto al toggler en un teléfono de
         * 390px; el ellipsis de abajo es la red por si aun así no alcanza. */
        font-size: 1rem;
    }
    .pzf-topbar .navbar-brand > span:last-child {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    .pzf-topbar .pzf-topbar-utils,
    .pzf-topbar .navbar-toggler { flex-shrink: 0; }

    /* Bootstrap le pone `position: static` a los .dropdown-menu de un
     * .navbar-nav colapsado, porque los piensa apilados dentro del collapse.
     * Estas utilidades ya no viven ahí: son una fila horizontal fija, y un
     * menú en flujo infla su <li> y parte la fila. Se anclan al grupo y no al
     * <li> para que queden alineados al borde de la pantalla: la campanita
     * mide 340px y desde su propio <li> se saldría por la izquierda. */
    .pzf-topbar .pzf-topbar-utils { position: relative; }
    .pzf-topbar .pzf-topbar-utils .nav-item.dropdown { position: static; }
    .pzf-topbar .pzf-topbar-utils .dropdown-menu {
        position: absolute;
        top: 100%;
        right: 0;
        left: auto;
    }

    /* Targets táctiles, pero sin gastar ancho de más en horizontal. */
    .pzf-topbar .pzf-icon-btn,
    .pzf-topbar .nav-link { padding: .55rem .45rem; }
    .pzf-topbar .pzf-topbar-utils { margin-left: auto; }
}

/* No puede desbordar un teléfono de 360px */
.pzf-dropdown-campanita {
    min-width: min(340px, calc(100vw - 1.5rem));
    max-width: min(380px, calc(100vw - 1.5rem));
    max-height: min(70vh, 440px);
    overflow-y: auto;
}

/* ============================================================
 * 4. Layout: main = sidebar (sticky, full-bleed) + contenido
 * ============================================================ */
main.pzf-main {
    display: block;
    padding: 0;
    height: 100%;
    min-height: 0;
    overflow: hidden;
}

.pzf-page {
    display: grid;
    grid-template-columns: var(--pzf-sidebar-current) minmax(0, 1fr);
    gap: 0;
    height: 100%;
    min-height: 0;
    transition: grid-template-columns .2s var(--pzf-ease);
}

/* Cuando el bloque sidebar queda vacío (home, login), full-width */
.pzf-page:has(.pzf-page-sidebar:empty) {
    grid-template-columns: minmax(0, 1fr);
}

.pzf-page-sidebar {
    background: var(--pzf-surface-alt);
    border-right: 1px solid var(--pzf-border);
    box-shadow: var(--pzf-shadow-sm);
    padding: 1rem .75rem;
    height: 100%;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
}
.pzf-page-sidebar:empty { display: none; }

/* Sin tree que mostrar (home, login), el toggle de la topbar no tiene qué
   togglear: escondido evita el no-op en desktop y el backdrop sobre un
   drawer vacío en mobile. */
body:has(.pzf-page-sidebar:empty) #pzf-sidebar-toggle { display: none; }

.pzf-page-main {
    min-width: 0;
    height: 100%;
    overflow-y: auto;
    /* El bottom no es simetría rota: el FAB de ayuda ocupa 4.5rem fijos en la
       esquina inferior derecha (1rem + 3.5rem) y ahí cae la paginación de todo
       listado. Sin colchón, el `?` se come el botón de "página siguiente". */
    padding: 1.1rem 1.35rem 5rem;
}

@media (max-width: 992px) {
    .pzf-page { grid-template-columns: minmax(0, 1fr); }
    .pzf-page-main { padding: 1rem .9rem 5rem; }

    .pzf-page-sidebar {
        position: fixed;
        top: var(--pzf-navbar-h);
        left: 0;
        bottom: 0;
        width: 280px;
        z-index: 1040;
        transform: translateX(-100%);
        transition: transform .25s var(--pzf-ease-out);
        box-shadow: var(--pzf-shadow-lg);
        height: auto;
    }
    [data-pzf-mobile-sidebar="open"] .pzf-page-sidebar { transform: translateX(0); }
    [data-pzf-mobile-sidebar="open"] body::after {
        content: "";
        position: fixed;
        inset: var(--pzf-navbar-h) 0 0 0;
        background: rgba(0, 0, 0, .4);
        backdrop-filter: blur(2px);
        z-index: 1039;
    }
}

/* ============================================================
 * 5. Sidebar tree
 * ============================================================ */
.pzf-tree { font-size: .85rem; }

.pzf-tree-header {
    font-weight: 700;
    font-size: .75rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--pzf-text);
    padding: .2rem .5rem .6rem;
    border-bottom: 1px solid var(--pzf-border);
    margin-bottom: .4rem;
    display: flex;
    align-items: center;
    gap: .5rem;
    white-space: nowrap;
    overflow: hidden;
}
.pzf-tree-header i { color: var(--pzf-primary-text); }

.pzf-tree ul { list-style: none; padding-left: 0; margin: 0; }
.pzf-tree ul ul {
    padding-left: .5rem;
    border-left: 1px dashed var(--pzf-border-strong);
    margin-left: .75rem;
}
.pzf-tree li { margin: .1rem 0; }

.pzf-tree-group-label {
    display: block;
    font-size: .66rem;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--pzf-text);
    opacity: .55;
    padding: .55rem .5rem .2rem;
    font-weight: 700;
    white-space: nowrap;
}

.pzf-tree-leaf {
    display: flex;
    align-items: center;
    gap: .55rem;
    padding: .4rem .65rem;
    border-radius: var(--pzf-radius-sm);
    color: var(--pzf-text);
    font-weight: 500;
    text-decoration: none;
    transition: background .15s var(--pzf-ease), color .15s var(--pzf-ease), transform .15s var(--pzf-ease);
    white-space: nowrap;
    position: relative;
}
.pzf-tree-leaf:hover {
    background: var(--pzf-hover);
    color: var(--pzf-primary-text);
    transform: translateX(2px);
}
.pzf-tree-leaf.active {
    background: var(--pzf-primary-soft);
    color: var(--pzf-primary-text);
    font-weight: 600;
}
/* Dot indicador a la derecha cuando está activo (microdetalle) */
.pzf-tree-leaf.active::after {
    content: "";
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--pzf-primary);
    margin-left: auto;
    flex-shrink: 0;
}
.pzf-tree-leaf.active i { color: var(--pzf-primary-text); opacity: 1; }

.pzf-tree-leaf i {
    width: 1.1rem;
    text-align: center;
    opacity: .8;
    flex-shrink: 0;
    font-size: 1rem;
}

.pzf-tree-label {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* ---- Sidebar colapsado (icon-only + hover-flyout) ---- */
@media (min-width: 992px) {
    [data-pzf-sidebar="collapsed"] {
        --pzf-sidebar-current: var(--pzf-sidebar-w-collapsed);
    }
    [data-pzf-sidebar="collapsed"] .pzf-page-sidebar {
        padding: 1rem .25rem;
        overflow: visible;
    }
    [data-pzf-sidebar="collapsed"] .pzf-tree-header {
        justify-content: center;
        padding: .25rem 0 .75rem;
    }
    [data-pzf-sidebar="collapsed"] .pzf-tree-header > span { display: none; }
    [data-pzf-sidebar="collapsed"] .pzf-tree-group-label { display: none; }
    [data-pzf-sidebar="collapsed"] .pzf-tree ul ul {
        padding-left: 0;
        border-left: 0;
        margin-left: 0;
    }
    [data-pzf-sidebar="collapsed"] .pzf-tree-leaf {
        justify-content: center;
        padding: .55rem .25rem;
        border-radius: var(--pzf-radius);
        margin: .15rem auto;
        width: 44px;
    }
    [data-pzf-sidebar="collapsed"] .pzf-tree-leaf.active {
        background: var(--pzf-primary);
        color: var(--pzf-on-color);
    }
    [data-pzf-sidebar="collapsed"] .pzf-tree-leaf.active::after { display: none; }
    [data-pzf-sidebar="collapsed"] .pzf-tree-leaf.active i { opacity: 1; color: var(--pzf-on-color); }
    [data-pzf-sidebar="collapsed"] .pzf-tree-label {
        position: absolute;
        left: calc(100% + .35rem);
        top: 50%;
        transform: translateY(-50%);
        background: var(--pzf-surface);
        color: var(--pzf-text);
        border: 1px solid var(--pzf-border);
        border-radius: var(--pzf-radius-sm);
        padding: .3rem .65rem;
        white-space: nowrap;
        box-shadow: var(--pzf-shadow);
        opacity: 0;
        pointer-events: none;
        transition: opacity .15s var(--pzf-ease);
        z-index: 50;
        font-weight: 500;
        flex: none;
        min-width: 0;
    }
    [data-pzf-sidebar="collapsed"] .pzf-tree-leaf:hover .pzf-tree-label {
        opacity: 1;
    }
}

/* ============================================================
 * 6. Widgets (.pzf-widget)
 * ============================================================ */
.pzf-widget {
    background: var(--pzf-surface);
    border: 1px solid var(--pzf-border);
    border-radius: var(--pzf-radius);
    padding: .85rem 1rem;
    margin-bottom: .85rem;
    box-shadow: var(--pzf-shadow-sm);
    transition: box-shadow .2s var(--pzf-ease), border-color .2s var(--pzf-ease);
}
.pzf-widget-interactive:hover {
    border-color: var(--pzf-primary-soft);
    box-shadow: var(--pzf-shadow);
}

.pzf-widget-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: .65rem;
    gap: .5rem;
}

.pzf-widget-title {
    font-size: .98rem;
    font-weight: 600;
    margin: 0;
    color: var(--pzf-text);
    letter-spacing: -.01em;
}

.pzf-widget-body { min-height: 60px; }

.pzf-loading { opacity: .5; pointer-events: none; position: relative; }
.pzf-loading::after {
    content: "";
    position: absolute;
    inset: 0;
    background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 50 50'><circle cx='25' cy='25' r='20' fill='none' stroke='%23166534' stroke-width='4' stroke-dasharray='80' stroke-dashoffset='60'><animateTransform attributeName='transform' type='rotate' from='0 25 25' to='360 25 25' dur='1s' repeatCount='indefinite'/></circle></svg>") center / 32px no-repeat;
}

/* ============================================================
 * 7. Forms (inputs, selects)
 * ============================================================ */
.form-label {
    color: var(--pzf-text);
    font-weight: 500;
    font-size: .82rem;
    margin-bottom: .25rem;
}

.form-control,
.form-select {
    background-color: var(--pzf-surface);
    color: var(--pzf-text);
    border: 1px solid var(--pzf-border-strong);
    border-radius: var(--pzf-radius-sm);
    padding: .4rem .7rem;
    font-size: .875rem;
    transition: border-color .15s var(--pzf-ease), box-shadow .15s var(--pzf-ease), background-color .15s var(--pzf-ease);
}

.form-control::placeholder {
    color: var(--pzf-text-muted);
    opacity: .7;
}

.form-control:hover:not(:focus):not(:disabled):not([readonly]),
.form-select:hover:not(:focus):not(:disabled) {
    border-color: var(--pzf-primary);
}

.form-control:focus,
.form-select:focus {
    border-color: var(--pzf-primary);
    background-color: var(--pzf-surface);
    color: var(--pzf-text);
    box-shadow: var(--pzf-focus-ring);
    outline: 0;
}

.form-control:disabled,
.form-select:disabled,
.form-control[readonly] {
    background-color: var(--pzf-surface-2);
    color: var(--pzf-text-muted);
    cursor: not-allowed;
    opacity: .85;
}

.form-control.is-invalid,
.form-select.is-invalid {
    border-color: var(--pzf-danger);
}
.form-control.is-invalid:focus,
.form-select.is-invalid:focus {
    box-shadow: 0 0 0 .2rem rgba(var(--pzf-danger-rgb), .22);
}

.form-text { color: var(--pzf-text-muted); font-size: .8rem; }

/* El ⓘ de ayuda al lado del label (core/_help_tip.html). Discreto hasta que se
   lo mira: la explicación es para la primera vez, no para todos los días. */
.pzf-help {
    color: var(--pzf-text-muted);
    font-size: .8rem;
    margin-left: .25rem;
    cursor: help;
    vertical-align: baseline;
    transition: color .15s var(--pzf-ease);
}
.pzf-help:hover, .pzf-help:focus { color: var(--pzf-primary-text); }
.pzf-help:focus-visible { outline: none; box-shadow: var(--pzf-focus-ring); border-radius: 50%; }
.form-check-input { background-color: var(--pzf-surface); border-color: var(--pzf-border-strong); }
.form-check-input:checked { background-color: var(--pzf-primary); border-color: var(--pzf-primary); }
.form-check-input:focus { box-shadow: var(--pzf-focus-ring); border-color: var(--pzf-primary); }

/* input-group con botón portal "+" */
.input-group > .btn { border-color: var(--pzf-border-strong); }

/* Tipo + punto de venta + número del comprobante: un solo control visual.
   Sin repartir el ancho a mano, el <select> del tipo se come la fila y al
   número no le queda lugar para los 13 caracteres que llegan a tener. */
.pzf-grupo-comprobante > .form-select { flex: 0 0 8rem; }
.pzf-grupo-comprobante > input[name="punto_venta"] { flex: 0 0 5rem; text-align: center; }
.pzf-grupo-comprobante > input[name="numero_comprobante"] { flex: 1 1 auto; min-width: 0; }

/* Card header de secciones de form más prominente */
.card > .card-header {
    background: var(--pzf-surface-2);
    border-bottom: 1px solid var(--pzf-border);
    font-weight: 600;
}

[data-bs-theme="dark"] .form-select {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%23E6EDF5' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3e%3c/svg%3e");
}

.invalid-feedback.pzf-server-error { display: block; }
.invalid-feedback { color: var(--pzf-danger); font-size: .8rem; }

/* ---- Tom Select: alinear a tokens EL ENSUEÑO ---- */
.ts-wrapper {
    padding: 0 !important;
}

/* Single: altura FIJA igual a .form-control para no empujar el layout
   cuando se escribe en el buscador o aparece la X de clear. */
.ts-wrapper.single .ts-control {
    background: var(--pzf-surface);
    border: 1px solid var(--pzf-border-strong);
    border-radius: var(--pzf-radius-sm);
    padding: .4rem .7rem;
    box-shadow: none;
    height: calc(1.5em + .8rem + 2px);
    min-height: 0;
    color: var(--pzf-text);
    font-size: .875rem;
    flex-wrap: nowrap;
    overflow: hidden;
    transition: border-color .15s var(--pzf-ease), box-shadow .15s var(--pzf-ease);
}
.ts-wrapper.single .ts-control > input {
    flex: 1 1 auto;
    min-width: 0 !important;
    max-width: 100%;
    width: 100% !important;
}
.ts-wrapper.single .ts-control > .item {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}

/* Multi: altura crece con items pero acotada — scrollea internamente
   en vez de empujar el form hacia abajo sin límite. */
.ts-wrapper.multi .ts-control {
    background: var(--pzf-surface);
    border: 1px solid var(--pzf-border-strong);
    border-radius: var(--pzf-radius-sm);
    padding: .25rem .45rem;
    box-shadow: none;
    min-height: calc(1.5em + .8rem + 2px);
    max-height: calc(3 * (1.5em + .8rem + 2px));
    overflow-y: auto;
    color: var(--pzf-text);
    font-size: .875rem;
    transition: border-color .15s var(--pzf-ease), box-shadow .15s var(--pzf-ease);
}
.ts-wrapper.single .ts-control:hover,
.ts-wrapper.multi .ts-control:hover { border-color: var(--pzf-primary); }
.ts-wrapper.focus .ts-control {
    border-color: var(--pzf-primary) !important;
    box-shadow: var(--pzf-focus-ring) !important;
}
.ts-wrapper.disabled .ts-control {
    background: var(--pzf-surface-2);
    color: var(--pzf-text-muted);
    opacity: .85;
}
.ts-wrapper.is-invalid .ts-control,
.ts-wrapper .ts-control.is-invalid { border-color: var(--pzf-danger) !important; }
.ts-wrapper .ts-control input,
.ts-wrapper .ts-control input::placeholder { color: var(--pzf-text); }
.ts-wrapper .ts-control input::placeholder { color: var(--pzf-text-muted); opacity: .7; }

.ts-dropdown {
    background: var(--pzf-surface);
    border: 1px solid var(--pzf-border-strong);
    border-radius: var(--pzf-radius-sm);
    box-shadow: var(--pzf-shadow);
    color: var(--pzf-text);
    margin-top: .25rem;
}
/* El dropdown se monta en <body> (dropdownParent en PZF.enhanceSelects) para
   escapar del overflow del modal / .pzf-widget / .pzf-table-wrap: ahí tiene que
   pisar al modal (1055) y al sidebar (1040). */
body > .ts-dropdown { z-index: 1060; }

.ts-dropdown .option,
.ts-dropdown .create { color: var(--pzf-text); padding: .45rem .75rem; }
.ts-dropdown .option.active,
.ts-dropdown .active {
    background: var(--pzf-hover);
    color: var(--pzf-primary-text);
}
.ts-dropdown .option.selected {
    background: var(--pzf-primary-soft);
    color: var(--pzf-primary-text);
    font-weight: 600;
}
.ts-dropdown .no-results,
.ts-dropdown .optgroup-header { color: var(--pzf-text-muted); }

/* Buscador dentro del panel (plugin dropdown_input, sólo single). El CSS del
   plugin trae colores propios (#d0d0d0, blanco) que rompen el modo oscuro. */
.ts-dropdown .dropdown-input-wrap {
    padding: .4rem;
    border-bottom: 1px solid var(--pzf-border);
}
.ts-dropdown .dropdown-input {
    width: 100%;
    background: var(--pzf-surface);
    color: var(--pzf-text);
    border: 1px solid var(--pzf-border-strong);
    border-radius: var(--pzf-radius-sm);
    padding: .35rem .6rem;
    font-size: .875rem;
    box-shadow: none;
}
.ts-dropdown .dropdown-input:focus,
.ts-dropdown.plugin-dropdown_input .dropdown-input:focus {
    outline: none;
    border-color: var(--pzf-primary);
    box-shadow: var(--pzf-focus-ring);
}
.ts-dropdown .dropdown-input::placeholder { color: var(--pzf-text-muted); opacity: .7; }
/* El plugin deja un <input class="items-placeholder"> dentro del control para
   mostrar el placeholder: sin esto se ve como un input blanco en modo oscuro. */
.ts-wrapper .ts-control > .items-placeholder {
    background: transparent;
    color: var(--pzf-text);
    padding: 0;
    height: auto;
}
/* El plugin apaga el borde del control mientras el panel está abierto: acá el
   control sigue siendo el elemento "enfocado" para el usuario. */
.ts-wrapper.plugin-dropdown_input.focus.dropdown-active .ts-control {
    border-color: var(--pzf-primary) !important;
    box-shadow: var(--pzf-focus-ring) !important;
}

.ts-wrapper.multi .item {
    background: var(--pzf-primary-soft);
    color: var(--pzf-primary-text);
    border: 1px solid rgba(var(--pzf-primary-rgb), .25);
    border-radius: var(--pzf-radius-sm);
    padding: .1rem .5rem;
    margin: .1rem .25rem .1rem 0;
}
.ts-wrapper.plugin-clear_button .clear-button {
    color: var(--pzf-text-muted);
    opacity: .6;
}
.ts-wrapper.plugin-clear_button .clear-button:hover {
    color: var(--pzf-danger);
    opacity: 1;
}

/* ============================================================
 * 8. Tablas
 * ============================================================ */
.pzf-table-wrap {
    overflow-x: auto;
    border-radius: var(--pzf-radius-sm);
}

.pzf-table,
.table {
    width: 100%;
    margin-bottom: 0;
    color: var(--pzf-text);
    --bs-table-bg: transparent;
    --bs-table-color: var(--pzf-text);
    --bs-table-hover-color: var(--pzf-text);
    --bs-table-hover-bg: var(--pzf-hover);
    --bs-table-border-color: var(--pzf-border);
    --bs-table-striped-bg: var(--pzf-surface-2);
    --bs-table-striped-color: var(--pzf-text);
    font-variant-numeric: tabular-nums;
}

.pzf-table thead th,
.table thead th {
    background: var(--pzf-surface-2);
    color: var(--pzf-text-muted);
    font-size: .7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .05em;
    border-bottom: 1px solid var(--pzf-border);
    padding: .5rem .75rem;
    position: sticky;
    top: 0;
    z-index: 1;
    white-space: nowrap;
}

.pzf-table tbody td,
.table tbody td {
    padding: .35rem .75rem;
    border-top: 1px solid var(--pzf-border);
    vertical-align: middle;
    font-size: .80rem;
    transition: background-color .12s var(--pzf-ease);
}

.pzf-table tbody tr:first-child td,
.table tbody tr:first-child td { border-top: 0; }

/* Columna de acciones: los botones van en una fila, siempre.
   `width: 1%` la deja del ancho de su contenido —el resto del espacio se lo
   reparten las columnas de datos— y el `nowrap` evita que el último botón se
   caiga a un renglón nuevo cuando la tabla tiene muchas columnas. */
.pzf-table td.pzf-actions,
.table td.pzf-actions,
.pzf-table th.pzf-actions,
.table th.pzf-actions {
    white-space: nowrap;
    width: 1%;
}
.pzf-actions .btn + .btn { margin-left: .25rem; }

.pzf-table tbody tr,
.table tbody tr {
    transition: background-color .12s var(--pzf-ease);
}
.pzf-table tbody tr:hover,
.table tbody tr:hover { background: var(--pzf-hover); }

/* Fila a remover en delete: fade-out animado */
.pzf-table tbody tr.pzf-row-removing,
.table tbody tr.pzf-row-removing {
    opacity: 0;
    transform: translateX(-6px);
    transition: opacity .18s var(--pzf-ease), transform .18s var(--pzf-ease);
}

/* Fade-in stagger genérico — el JS (PZF.utils.fadeInChildren) lo aplica
 * tanto a filas de tabla como a tarjetas, módulos, etc. */
.pzf-row-fade-in {
    opacity: 0;
    animation: pzf-fade-in .35s var(--pzf-ease-out) forwards;
}

.pzf-empty {
    color: var(--pzf-text-muted);
    text-align: center;
    padding: 1.5rem 1rem;
    font-style: italic;
    font-size: .88rem;
}

/* ============================================================
 * 9. Filtros (wrapper opcional para barras de filtros)
 * ============================================================ */
.pzf-filters {
    background: var(--pzf-surface);
    border: 1px solid var(--pzf-border);
    border-radius: var(--pzf-radius);
    padding: .65rem .85rem;
    margin-bottom: .85rem;
    box-shadow: var(--pzf-shadow-sm);
}

/* botón "Filtros" — solo visible en mobile (lo inyecta pzf-list-mobile.js) */
.pzf-filters-toggle { display: none; }

@media (max-width: 767.98px) {
    .pzf-filters-toggle { display: inline-flex; align-items: center; gap: .35rem; }
    /* campos ocultos hasta abrir; el toggle agrega .pzf-filters-open */
    .pzf-filters > .row { display: none; }
    .pzf-filters.pzf-filters-open > .row { display: flex; }
}

/* ============================================================
 * 9a. Rango de fechas — atajos Hoy · Ayer · Esta semana · Este mes · Todo
 *     (core/_rango_fechas_atajos.html). Fuera del .row colapsable: en el
 *     celular se ven sin abrir "Filtros".
 * ============================================================ */
.pzf-rango {
    display: flex;
    flex-wrap: nowrap;
    gap: .4rem;
    margin-bottom: .55rem;
    /* Si no entran, scrollean ellos solos; la página no se corre de costado. */
    overflow-x: auto;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
}
.pzf-rango::-webkit-scrollbar { display: none; }
.pzf-rango .btn {
    flex: 0 0 auto;
    white-space: nowrap;
    border-radius: 999px;
    padding-inline: .85rem;
}
.pzf-rango-resumen {
    font-size: .8rem;
    color: var(--pzf-text-muted);
    margin: -.2rem 0 .5rem;
}
/* Safari iOS achica el date vacío y desarma la grilla de dos columnas. */
.pzf-filters input[type="date"] {
    min-width: 0;
    width: 100%;
}

/* ============================================================
 * 9c. Barra de flujo — pasos de un circuito repartido en pantallas
 *     (ej. Costo hora → Horas trabajadas → Absorción)
 * ============================================================ */
.pzf-flujo {
    display: flex;
    align-items: stretch;
    gap: .35rem;
    margin-bottom: .85rem;
}

.pzf-flujo-paso {
    flex: 1 1 0;
    display: block;
    padding: .5rem .75rem;
    border: 1px solid var(--pzf-border);
    border-radius: var(--pzf-radius);
    background: var(--pzf-surface);
    color: var(--pzf-text-muted);
    text-decoration: none;
    transition: background .15s ease, border-color .15s ease;
}

a.pzf-flujo-paso:hover {
    background: var(--pzf-surface-2);
    border-color: var(--pzf-border-strong);
    color: var(--pzf-text-muted);
}

.pzf-flujo-paso.active {
    background: var(--pzf-primary-soft);
    border-color: var(--pzf-primary);
}

/* Sin permiso: se ve que el paso existe, pero no a dónde va. */
.pzf-flujo-paso.disabled { opacity: .45; }

.pzf-flujo-nombre {
    display: flex;
    align-items: center;
    gap: .35rem;
    font-size: .85rem;
    font-weight: 600;
    color: var(--pzf-text);
}

.pzf-flujo-paso.active .pzf-flujo-nombre { color: var(--pzf-primary-text); }

.pzf-flujo-num {
    flex: 0 0 auto;
    width: 1.15rem;
    height: 1.15rem;
    border-radius: 50%;
    background: var(--pzf-surface-2);
    color: var(--pzf-text-muted);
    font-size: .7rem;
    line-height: 1.15rem;
    text-align: center;
    font-weight: 700;
}

.pzf-flujo-paso.active .pzf-flujo-num {
    background: var(--pzf-primary);
    color: var(--pzf-on-color);
}

.pzf-flujo-desc {
    display: block;
    margin-top: .1rem;
    font-size: .74rem;
    line-height: 1.25;
    color: var(--pzf-text-muted);
}

@media (max-width: 575.98px) {
    .pzf-flujo { flex-wrap: wrap; gap: .25rem; }
    .pzf-flujo-paso { flex: 1 1 auto; padding: .35rem .5rem; }
    .pzf-flujo-desc { display: none; }
}

/* ============================================================
 * 9b. Tablas como cards apiladas en mobile
 *     (pzf-list-mobile.js inyecta data-label desde el thead)
 * ============================================================ */
@media (max-width: 767.98px) {
    .pzf-table-wrap:has(.pzf-table-mobile) { overflow-x: visible; }

    .pzf-table-mobile thead,
    .pzf-table-mobile colgroup { display: none; }

    .pzf-table-mobile tbody { display: block; }

    .pzf-table-mobile tbody tr {
        display: block;
        background: var(--pzf-surface);
        border: 1px solid var(--pzf-border);
        border-radius: var(--pzf-radius-sm);
        box-shadow: var(--pzf-shadow-sm);
        margin-bottom: .55rem;
        padding: .35rem .8rem;
    }
    .pzf-table-mobile tbody tr:hover { background: var(--pzf-surface); }
    .pzf-table-mobile tbody tr:first-child td { border-top: 0; }

    .pzf-table-mobile tbody td {
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: 1rem;
        border: 0 !important;
        border-top: 0 !important;
        padding: .3rem 0 !important;
        text-align: right;
        white-space: normal;
    }
    .pzf-table-mobile tbody td::before {
        content: attr(data-label);
        font-size: .66rem;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: .04em;
        color: var(--pzf-text-muted);
        text-align: left;
        flex-shrink: 0;
    }
    /* En card, la celda es flex con `space-between`: sin esto la etiqueta y los
       tres botones se reparten el ancho y quedan desparramados. El `auto`
       empuja todo lo demás a la derecha y los botones quedan juntos. */
    .pzf-table-mobile tbody td.pzf-actions { gap: .25rem; }
    .pzf-table-mobile tbody td.pzf-actions::before { margin-right: auto; }
    .pzf-table-mobile tbody td.pzf-actions .btn { flex: 0 0 auto; }

    /* celdas sin etiqueta o vacías (acciones, filas "cargando/sin datos") */
    .pzf-table-mobile tbody td:empty { display: none; }
    .pzf-table-mobile tbody td.pzf-empty,
    .pzf-table-mobile tbody td[colspan] {
        display: block;
        text-align: center;
    }
    .pzf-table-mobile tbody td.pzf-empty::before,
    .pzf-table-mobile tbody td[colspan]::before { content: none; }
}

/* ============================================================
 * 10. Botones
 * ============================================================ */
.btn {
    border-radius: var(--pzf-radius-sm);
    font-weight: 500;
    transition: transform .1s var(--pzf-ease), box-shadow .15s var(--pzf-ease), background-color .15s var(--pzf-ease), border-color .15s var(--pzf-ease), color .15s var(--pzf-ease);
}
.btn:focus,
.btn:focus-visible {
    box-shadow: var(--pzf-focus-ring);
}
.btn:active { transform: scale(.97); }

.btn-primary {
    background: var(--pzf-primary);
    border-color: var(--pzf-primary);
    color: var(--pzf-on-color);
}
.btn-primary:hover {
    background: var(--pzf-primary-hover);
    border-color: var(--pzf-primary-hover);
    color: var(--pzf-on-color);
}
.btn-primary:active { transform: scale(.97); }

.btn-outline-primary {
    color: var(--pzf-primary-text);
    border-color: var(--pzf-primary);
    background: transparent;
}
.btn-outline-primary:hover {
    background: var(--pzf-primary);
    color: var(--pzf-on-color);
}

.btn-link { color: var(--pzf-primary-text); }
.btn-link:hover { color: var(--pzf-primary-text-hover); }

/* Botón dorado: CTA destacado del producto (no para errores).
 * Lleva texto oscuro: sobre el dorado el blanco da 1.86:1. */
.btn-gold {
    background: var(--pzf-gold);
    border: 1px solid var(--pzf-gold);
    color: var(--pzf-on-gold);
}
.btn-gold:hover,
.btn-gold:focus {
    background: var(--pzf-gold-hover);
    border-color: var(--pzf-gold-hover);
    color: var(--pzf-on-gold);
}
.btn-outline-gold {
    background: transparent;
    border: 1px solid var(--pzf-gold);
    color: var(--pzf-gold-text);
}
.btn-outline-gold:hover,
.btn-outline-gold:focus {
    background: var(--pzf-gold);
    color: var(--pzf-on-gold);
}

/* ============================================================
 * 11. Badges suaves (override Bootstrap text-bg-*)
 * ============================================================ */
.badge {
    font-weight: 600;
    padding: .3em .6em;
    border-radius: 999px;
    font-size: .68rem;
    letter-spacing: .01em;
}

.badge.text-bg-primary {
    background-color: var(--pzf-primary-soft) !important;
    color: var(--pzf-primary-text) !important;
}
.badge.text-bg-success {
    background-color: rgba(var(--pzf-success-rgb), .14) !important;
    color: var(--pzf-success) !important;
}
.badge.text-bg-warning {
    background-color: rgba(var(--pzf-warning-rgb), .18) !important;
    color: var(--pzf-warning-text) !important;
}
.badge.text-bg-danger {
    background-color: rgba(var(--pzf-danger-rgb), .14) !important;
    color: var(--pzf-danger) !important;
}
.badge.text-bg-info {
    background-color: rgba(var(--pzf-info-rgb), .14) !important;
    color: var(--pzf-info) !important;
}
.badge.text-bg-secondary {
    background-color: var(--pzf-secondary-soft) !important;
    color: var(--pzf-text-muted) !important;
}
.badge.text-bg-gold {
    background-color: var(--pzf-gold-soft) !important;
    color: var(--pzf-gold-text) !important;
}

/* ============================================================
 * 12. Cards / modals / dropdowns / alerts (dark-mode aware)
 * ============================================================ */
.card {
    background: var(--pzf-surface);
    color: var(--pzf-text);
    border-color: var(--pzf-border);
}

.alert {
    border-radius: var(--pzf-radius);
    padding: .65rem .85rem;
    font-size: .88rem;
    margin-bottom: .75rem;
}

/* Breadcrumb default compacto — usado fuera del portal también */
.breadcrumb {
    margin-bottom: .65rem;
    font-size: .8rem;
}
.breadcrumb-item + .breadcrumb-item::before {
    color: var(--pzf-text-muted);
}
[data-bs-theme="dark"] .alert-info,
[data-bs-theme="dark"] .alert-primary {
    background-color: var(--pzf-primary-soft);
    border-color: rgba(var(--pzf-primary-rgb), .25);
    color: var(--pzf-primary-text);
}
[data-bs-theme="dark"] .alert-success {
    background-color: rgba(var(--pzf-success-rgb), .14);
    border-color: rgba(var(--pzf-success-rgb), .25);
    color: var(--pzf-success);
}
[data-bs-theme="dark"] .alert-warning {
    background-color: rgba(var(--pzf-warning-rgb), .14);
    border-color: rgba(var(--pzf-warning-rgb), .28);
    color: var(--pzf-warning-text);
}
[data-bs-theme="dark"] .alert-danger {
    background-color: rgba(var(--pzf-danger-rgb), .14);
    border-color: rgba(var(--pzf-danger-rgb), .28);
    color: #F08089;
}

/* Modales scrollables por default. */
.modal .modal-content {
    max-height: calc(100vh - 1rem);
    display: flex;
    flex-direction: column;
    overflow: hidden;
    width: 100%;
    border: 1px solid var(--pzf-border);
    border-radius: var(--pzf-radius);
    box-shadow: var(--pzf-shadow-lg);
}
@media (min-width: 576px) {
    .modal .modal-content {
        max-height: calc(100vh - 3.5rem);
    }
}
.modal .modal-body {
    overflow-y: auto;
    min-height: 0;
    flex: 1 1 auto;
    padding: .85rem 1rem;
}
.modal .modal-header,
.modal .modal-footer {
    flex-shrink: 0;
    padding: .65rem 1rem;
}
.modal .modal-title {
    font-size: 1rem;
    font-weight: 600;
}
.modal .modal-content > form {
    display: contents;
}

/* Entrada animada del modal: fade + slide-up sutil */
.modal.fade .modal-dialog {
    transform: translateY(-12px);
    transition: transform .25s var(--pzf-ease-out), opacity .2s var(--pzf-ease);
}
.modal.show .modal-dialog {
    transform: translateY(0);
}

/* Backdrop con blur si el browser lo soporta */
.modal-backdrop.show { opacity: .55; }
@supports (backdrop-filter: blur(2px)) {
    .modal-backdrop.show { backdrop-filter: blur(2px); }
}

[data-bs-theme="dark"] .modal-content {
    background: var(--pzf-surface);
    color: var(--pzf-text);
    border-color: var(--pzf-border);
}
[data-bs-theme="dark"] .modal-header,
[data-bs-theme="dark"] .modal-footer { border-color: var(--pzf-border); }

.dropdown-menu {
    background: var(--pzf-surface);
    border-color: var(--pzf-border);
    box-shadow: var(--pzf-shadow);
    border-radius: var(--pzf-radius);
    padding: .35rem;
    animation: pzf-dropdown-in .15s var(--pzf-ease-out);
}
.dropdown-item {
    color: var(--pzf-text);
    border-radius: var(--pzf-radius-sm);
    padding: .45rem .65rem;
}
.dropdown-item:hover,
.dropdown-item:focus {
    background: var(--pzf-hover);
    color: var(--pzf-primary-text);
}
.dropdown-divider { border-color: var(--pzf-border); }
.dropdown-header { color: var(--pzf-text-muted); }

/* Navbar de módulos: el módulo es el destino, los sub_items son sus hijos.
   La jerarquía es sólo visual — en el DOM son hermanos, porque Bootstrap 5 no
   soporta submenús anidados. El max-height no es cosmético: "Administración"
   pasa de 7 líneas a ~35 y en un portátil se sale de la pantalla. */
.pzf-nav-menu {
    max-height: 70vh;
    overflow-y: auto;
}
.pzf-nav-modulo { font-weight: 600; }
.pzf-nav-subitem {
    padding-left: 2.1rem;
    font-size: .85rem;
    color: var(--pzf-text-muted);
}
.pzf-nav-subitem:hover,
.pzf-nav-subitem:focus { color: var(--pzf-primary-text); }
.pzf-nav-subdivider {
    margin-left: 2.1rem;
    opacity: .5;
}

.pagination .page-link {
    color: var(--pzf-primary-text);
    background: var(--pzf-surface);
    border-color: var(--pzf-border);
    transition: background-color .12s var(--pzf-ease), color .12s var(--pzf-ease);
}
.pagination .page-link:hover {
    background: var(--pzf-hover);
    border-color: var(--pzf-border);
    color: var(--pzf-primary-text-hover);
}
.pagination .page-item.active .page-link {
    background: var(--pzf-primary);
    border-color: var(--pzf-primary);
    color: var(--pzf-on-color);
}
.pagination .page-item.disabled .page-link {
    background: var(--pzf-surface);
    color: var(--pzf-text-muted);
}

/* ============================================================
 * 13. KPI tiles
 * ============================================================ */
.pzf-kpi-tile {
    display: flex;
    align-items: center;
    gap: .7rem;
    background: var(--pzf-surface);
    border: 1px solid var(--pzf-border);
    border-left: 3px solid var(--pzf-primary);
    border-radius: var(--pzf-radius);
    padding: .75rem .95rem;
    text-decoration: none;
    color: var(--pzf-text);
    height: 100%;
    box-shadow: var(--pzf-shadow-sm);
    transition: transform .2s var(--pzf-ease-out), box-shadow .2s var(--pzf-ease-out), border-color .2s var(--pzf-ease);
    position: relative;
    overflow: hidden;
}
.pzf-kpi-tile:hover {
    transform: translateY(-3px);
    box-shadow: var(--pzf-shadow-lg);
    color: var(--pzf-text);
}

.pzf-kpi-icon {
    width: 36px; height: 36px; flex-shrink: 0;
    border-radius: 10px;
    display: flex; align-items: center; justify-content: center;
    font-size: 1.05rem;
    background: var(--pzf-primary-soft);
    color: var(--pzf-primary-text);
}
.pzf-kpi-body { min-width: 0; }
.pzf-kpi-value {
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1.1;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--pzf-text);
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
}
.pzf-kpi-label {
    font-size: .7rem;
    color: var(--pzf-text-muted);
    text-transform: uppercase;
    letter-spacing: .04em;
    margin-top: .1rem;
    font-weight: 500;
}

.pzf-kpi-primary { border-left-color: var(--pzf-primary); }
.pzf-kpi-primary .pzf-kpi-icon { background: var(--pzf-primary-soft); color: var(--pzf-primary-text); }
.pzf-kpi-success { border-left-color: var(--pzf-success); }
.pzf-kpi-success .pzf-kpi-icon { background: rgba(var(--pzf-success-rgb), .12); color: var(--pzf-success); }
.pzf-kpi-warning { border-left-color: var(--pzf-warning); }
.pzf-kpi-warning .pzf-kpi-icon { background: rgba(var(--pzf-warning-rgb), .14); color: var(--pzf-warning-text); }
.pzf-kpi-danger { border-left-color: var(--pzf-danger); }
.pzf-kpi-danger .pzf-kpi-icon { background: rgba(var(--pzf-danger-rgb), .12); color: var(--pzf-danger); }
.pzf-kpi-info { border-left-color: var(--pzf-info); }
.pzf-kpi-info .pzf-kpi-icon { background: rgba(var(--pzf-info-rgb), .14); color: var(--pzf-info); }
.pzf-kpi-gold { border-left-color: var(--pzf-gold); }
.pzf-kpi-gold .pzf-kpi-icon { background: var(--pzf-gold-soft); color: var(--pzf-gold-text); }
.pzf-kpi-secondary { border-left-color: var(--pzf-border-strong); }
.pzf-kpi-secondary .pzf-kpi-icon { background: var(--pzf-secondary-soft); color: var(--pzf-text-muted); }

/* ============================================================
 * 14. Cards de módulo (home)
 * ============================================================ */
.pzf-modulo-card {
    display: flex;
    align-items: flex-start;
    gap: .8rem;
    background: var(--pzf-surface);
    border: 1px solid var(--pzf-border);
    border-radius: var(--pzf-radius);
    padding: .85rem 1rem;
    text-decoration: none;
    color: var(--pzf-text);
    height: 100%;
    box-shadow: var(--pzf-shadow-sm);
    transition: transform .2s var(--pzf-ease-out), box-shadow .2s var(--pzf-ease-out), border-color .2s var(--pzf-ease);
    position: relative;
}
.pzf-modulo-card::before {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: var(--pzf-radius);
    pointer-events: none;
    box-shadow: inset 0 0 0 0 var(--pzf-primary);
    transition: box-shadow .25s var(--pzf-ease);
}
.pzf-modulo-card:hover {
    transform: translateY(-3px);
    box-shadow: var(--pzf-shadow-lg);
    border-color: rgba(var(--pzf-primary-rgb), .35);
    color: var(--pzf-text);
}

.pzf-modulo-icon {
    width: 40px; height: 40px; flex-shrink: 0;
    border-radius: var(--pzf-radius-sm);
    display: flex; align-items: center; justify-content: center;
    font-size: 1.25rem;
    background: var(--pzf-primary-soft);
    color: var(--pzf-primary-text);
}
.pzf-modulo-body { min-width: 0; }
.pzf-modulo-title { font-weight: 600; font-size: .92rem; margin-bottom: .15rem; color: var(--pzf-text); letter-spacing: -.01em; }
.pzf-modulo-desc { font-size: .78rem; color: var(--pzf-text-muted); line-height: 1.4; }

.pzf-modulo-primary .pzf-modulo-icon { background: var(--pzf-primary-soft); color: var(--pzf-primary-text); }
.pzf-modulo-success .pzf-modulo-icon { background: rgba(var(--pzf-success-rgb), .12); color: var(--pzf-success); }
.pzf-modulo-warning .pzf-modulo-icon { background: rgba(var(--pzf-warning-rgb), .14); color: var(--pzf-warning-text); }
.pzf-modulo-danger  .pzf-modulo-icon { background: rgba(var(--pzf-danger-rgb), .12); color: var(--pzf-danger); }
.pzf-modulo-info    .pzf-modulo-icon { background: rgba(var(--pzf-info-rgb), .14); color: var(--pzf-info); }
.pzf-modulo-gold  .pzf-modulo-icon { background: var(--pzf-gold-soft); color: var(--pzf-gold-text); }
.pzf-modulo-secondary .pzf-modulo-icon { background: var(--pzf-secondary-soft); color: var(--pzf-text-muted); }

/* ============================================================
 * 15. Home header
 * ============================================================ */
.pzf-home-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    flex-wrap: wrap;
    gap: 1rem;
    margin-bottom: 1.5rem;
}

/* ============================================================
 * 16. Dashboards — section headers, charts, progress, deltas
 * ============================================================ */

.pzf-section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .65rem;
    margin: .95rem 0 .55rem;
    flex-wrap: wrap;
}
.pzf-section-header:first-child { margin-top: 0; }
.pzf-section-header-title {
    display: inline-flex;
    align-items: center;
    gap: .45rem;
    font-size: .92rem;
    font-weight: 600;
    color: var(--pzf-text);
    margin: 0;
    letter-spacing: -.01em;
}
.pzf-section-header-title i {
    color: var(--pzf-primary-text);
    font-size: 1rem;
}
.pzf-section-header-meta {
    font-size: .76rem;
    color: var(--pzf-text-muted);
}

.pzf-chart {
    background: var(--pzf-surface);
    border: 1px solid var(--pzf-border);
    border-radius: var(--pzf-radius);
    box-shadow: var(--pzf-shadow-sm);
    padding: .65rem .75rem;
    min-height: 220px;
    position: relative;
}
.pzf-chart-title {
    font-size: .78rem;
    font-weight: 600;
    color: var(--pzf-text);
    margin-bottom: .4rem;
}
.pzf-chart-canvas {
    width: 100%;
    height: 240px;
}

.pzf-progress {
    height: 6px;
    background: var(--pzf-primary-soft);
    border-radius: 999px;
    overflow: hidden;
    margin-top: .5rem;
}
.pzf-progress-bar {
    height: 100%;
    border-radius: 999px;
    background: var(--pzf-primary);
    transition: width .5s var(--pzf-ease-out);
}
.pzf-progress-primary .pzf-progress-bar { background: var(--pzf-primary); }
.pzf-progress-success .pzf-progress-bar { background: var(--pzf-success); }
.pzf-progress-warning .pzf-progress-bar { background: var(--pzf-warning); }
.pzf-progress-danger  .pzf-progress-bar { background: var(--pzf-danger); }
.pzf-progress-info    .pzf-progress-bar { background: var(--pzf-info); }
.pzf-progress-gold  .pzf-progress-bar { background: var(--pzf-gold); }

.pzf-stat-delta {
    display: inline-flex;
    align-items: center;
    gap: .2rem;
    font-size: .68rem;
    font-weight: 600;
    padding: .12rem .45rem;
    border-radius: 999px;
    line-height: 1;
}
.pzf-stat-delta-up {
    color: var(--pzf-success);
    background: rgba(var(--pzf-success-rgb), .12);
}
.pzf-stat-delta-down {
    color: var(--pzf-danger);
    background: rgba(var(--pzf-danger-rgb), .12);
}
.pzf-stat-delta-flat {
    color: var(--pzf-text-muted);
    background: var(--pzf-secondary-soft);
}

.pzf-kpi-tile.has-spark { align-items: stretch; }
.pzf-kpi-spark {
    width: 90px; height: 36px;
    margin-left: auto;
    align-self: center;
    flex-shrink: 0;
}

.pzf-timeline { list-style: none; padding: 0; margin: 0; }
.pzf-timeline-item {
    display: flex;
    align-items: flex-start;
    gap: .65rem;
    padding: .5rem .25rem;
    border-bottom: 1px solid var(--pzf-border);
}
.pzf-timeline-item:last-child { border-bottom: 0; }
.pzf-timeline-icon {
    width: 28px; height: 28px;
    border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--pzf-primary-soft);
    color: var(--pzf-primary-text);
    flex-shrink: 0;
    font-size: .85rem;
}
.pzf-timeline-icon.tone-success { background: rgba(var(--pzf-success-rgb), .12); color: var(--pzf-success); }
.pzf-timeline-icon.tone-warning { background: rgba(var(--pzf-warning-rgb), .14); color: var(--pzf-warning-text); }
.pzf-timeline-icon.tone-danger  { background: rgba(var(--pzf-danger-rgb), .12);  color: var(--pzf-danger); }
.pzf-timeline-icon.tone-info    { background: rgba(var(--pzf-info-rgb), .14);            color: var(--pzf-info); }
.pzf-timeline-icon.tone-gold  { background: var(--pzf-gold-soft);            color: var(--pzf-gold-text); }
.pzf-timeline-icon.tone-secondary { background: var(--pzf-secondary-soft); color: var(--pzf-text-muted); }
.pzf-timeline-body { min-width: 0; flex: 1; }
.pzf-timeline-title {
    font-size: .85rem;
    color: var(--pzf-text);
    line-height: 1.35;
}
.pzf-timeline-meta {
    font-size: .7rem;
    color: var(--pzf-text-muted);
    margin-top: .1rem;
}

/* ---------- KPI list (lista compacta de KPIs dentro de un .pzf-widget) ---------- */
.pzf-kpi-list { display: flex; flex-direction: column; }
.pzf-kpi-row {
    display: grid;
    grid-template-columns: 26px 1fr auto;
    align-items: center;
    gap: .65rem;
    padding: .5rem .2rem;
    border-top: 1px solid var(--pzf-border);
    transition: background-color .15s var(--pzf-ease);
}
.pzf-kpi-row:first-child { border-top: 0; }
.pzf-kpi-row:hover { background: var(--pzf-hover); }
.pzf-kpi-row-icon {
    width: 26px; height: 26px;
    display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%;
    background: var(--pzf-secondary-soft);
    color: var(--pzf-text-muted);
    font-size: .8rem;
    flex-shrink: 0;
}
.pzf-kpi-row-label {
    font-size: .85rem;
    color: var(--pzf-text);
    line-height: 1.3;
    min-width: 0;
}
.pzf-kpi-row-label small {
    display: block;
    font-size: .7rem;
    color: var(--pzf-text-muted);
    margin-top: .08rem;
}
.pzf-kpi-row-value {
    font-size: .98rem;
    font-weight: 600;
    color: var(--pzf-text);
    text-align: right;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.pzf-kpi-row.tone-primary .pzf-kpi-row-icon { background: var(--pzf-primary-soft); color: var(--pzf-primary-text); }
.pzf-kpi-row.tone-success .pzf-kpi-row-icon { background: rgba(var(--pzf-success-rgb), .12); color: var(--pzf-success); }
.pzf-kpi-row.tone-success .pzf-kpi-row-value { color: var(--pzf-success); }
.pzf-kpi-row.tone-warning .pzf-kpi-row-icon { background: rgba(var(--pzf-warning-rgb), .14); color: var(--pzf-warning-text); }
.pzf-kpi-row.tone-warning .pzf-kpi-row-value { color: var(--pzf-warning-text); }
.pzf-kpi-row.tone-danger  .pzf-kpi-row-icon { background: rgba(var(--pzf-danger-rgb), .12);  color: var(--pzf-danger); }
.pzf-kpi-row.tone-danger  .pzf-kpi-row-value { color: var(--pzf-danger); }
.pzf-kpi-row.tone-info    .pzf-kpi-row-icon { background: rgba(var(--pzf-info-rgb), .14);            color: var(--pzf-info); }
.pzf-kpi-row.tone-gold  .pzf-kpi-row-icon { background: var(--pzf-gold-soft);            color: var(--pzf-gold-text); }
.pzf-kpi-row.tone-gold  .pzf-kpi-row-value { color: var(--pzf-gold-text); }

.pzf-kpi-row-with-progress { grid-template-columns: 28px 1fr auto; }
.pzf-kpi-row-progress {
    grid-column: 1 / -1;
    margin-top: .45rem;
}

.pzf-widget-title-h {
    display: flex;
    align-items: center;
    gap: .45rem;
    font-size: .92rem;
    font-weight: 600;
    color: var(--pzf-text);
    margin: 0 0 .65rem 0;
    letter-spacing: -.01em;
}
.pzf-widget-title-h i { color: var(--pzf-primary-text); font-size: 1rem; }
.pzf-widget-title-h .pzf-widget-title-meta {
    margin-left: auto;
    font-size: .72rem;
    font-weight: 400;
    color: var(--pzf-text-muted);
}

.pzf-dashboard-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .85rem;
    flex-wrap: wrap;
    margin-bottom: .95rem;
}
.pzf-dashboard-header h1 {
    display: inline-flex; align-items: center; gap: .5rem;
    margin: 0;
    font-size: 1.25rem;
    font-weight: 700;
    letter-spacing: -.02em;
}
.pzf-dashboard-header h1 i { color: var(--pzf-primary-text); }
.pzf-dashboard-header-meta {
    font-size: .76rem;
    color: var(--pzf-text-muted);
}

/* ============================================================
 * 17. Skeleton loaders (placeholders animados durante AJAX)
 * ============================================================ */
.pzf-skeleton {
    position: relative;
    overflow: hidden;
    background: var(--pzf-surface-2);
    border-radius: var(--pzf-radius-sm);
    display: inline-block;
}
.pzf-skeleton::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(255, 255, 255, .55) 50%,
        transparent 100%);
    transform: translateX(-100%);
    animation: pzf-shimmer 1.4s infinite var(--pzf-ease);
}
[data-bs-theme="dark"] .pzf-skeleton::after {
    background: linear-gradient(90deg,
        transparent 0%,
        rgba(255, 255, 255, .08) 50%,
        transparent 100%);
}
.pzf-skeleton-text {
    height: .8rem;
    width: 100%;
    border-radius: var(--pzf-radius-sm);
    margin: .25rem 0;
}
.pzf-skeleton-text.sm  { width: 35%; }
.pzf-skeleton-text.md  { width: 60%; }
.pzf-skeleton-text.lg  { width: 90%; }
.pzf-skeleton-circle {
    width: 32px;
    height: 32px;
    border-radius: 50%;
}
.pzf-skeleton-card {
    width: 100%;
    height: 120px;
    border-radius: var(--pzf-radius);
}
.pzf-skeleton-row td {
    border-top: 1px solid var(--pzf-border) !important;
    padding: .85rem !important;
}
.pzf-skeleton-row .pzf-skeleton {
    height: .9rem;
    width: 80%;
}

/* ============================================================
 * 18. Toasts (slide-down arriba a la derecha)
 * ============================================================ */
.pzf-toast-container {
    position: fixed;
    top: calc(var(--pzf-navbar-h) + .75rem);
    right: 1rem;
    z-index: 2000;
    display: flex;
    flex-direction: column;
    gap: .5rem;
    pointer-events: none;
}
.pzf-toast {
    background: var(--pzf-surface);
    border: 1px solid var(--pzf-border);
    border-left: 4px solid var(--pzf-primary);
    border-radius: var(--pzf-radius);
    box-shadow: var(--pzf-shadow-lg);
    padding: .75rem 1rem .75rem .85rem;
    min-width: 260px;
    max-width: 380px;
    display: flex;
    align-items: flex-start;
    gap: .65rem;
    color: var(--pzf-text);
    font-size: .9rem;
    pointer-events: auto;
    animation: pzf-toast-in .3s var(--pzf-ease-out);
}
.pzf-toast.pzf-toast-out {
    animation: pzf-toast-out .25s var(--pzf-ease) forwards;
}
.pzf-toast-icon {
    flex-shrink: 0;
    font-size: 1.15rem;
    line-height: 1.2;
    color: var(--pzf-primary-text);
}
.pzf-toast-body { flex: 1; min-width: 0; }
.pzf-toast-close {
    background: transparent;
    border: 0;
    color: var(--pzf-text-muted);
    padding: 0 .25rem;
    cursor: pointer;
    line-height: 1;
    font-size: 1.1rem;
    transition: color .15s var(--pzf-ease);
}
.pzf-toast-close:hover { color: var(--pzf-text); }

.pzf-toast.tone-success { border-left-color: var(--pzf-success); }
.pzf-toast.tone-success .pzf-toast-icon { color: var(--pzf-success); }
.pzf-toast.tone-danger  { border-left-color: var(--pzf-danger); }
.pzf-toast.tone-danger  .pzf-toast-icon { color: var(--pzf-danger); }
.pzf-toast.tone-warning { border-left-color: var(--pzf-warning); }
.pzf-toast.tone-warning .pzf-toast-icon { color: var(--pzf-warning-text); }
.pzf-toast.tone-info    { border-left-color: var(--pzf-info); }
.pzf-toast.tone-info    .pzf-toast-icon { color: var(--pzf-info); }
.pzf-toast.tone-gold  { border-left-color: var(--pzf-gold); }
.pzf-toast.tone-gold  .pzf-toast-icon { color: var(--pzf-gold-text); }

/* ============================================================
 * 19. Animaciones globales
 * ============================================================ */
@keyframes pzf-fade-in {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes pzf-shimmer {
    100% { transform: translateX(100%); }
}

@keyframes pzf-dropdown-in {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes pzf-toast-in {
    from { opacity: 0; transform: translateY(-12px); }
    to   { opacity: 1; transform: translateY(0); }
}

@keyframes pzf-toast-out {
    from { opacity: 1; transform: translateY(0); }
    to   { opacity: 0; transform: translateY(-12px); }
}

/* ============================================================
 * 20. Cuenta corriente (clientes / proveedores)
 *     Hero + display de saldo + tabla de movimientos.
 * ============================================================ */
.pzf-cc-hero {
    background: var(--pzf-surface);
    border: 1px solid var(--pzf-border);
    border-radius: var(--pzf-radius);
    box-shadow: var(--pzf-shadow-sm);
    padding: 1rem 1.15rem;
    margin-bottom: .85rem;
    position: relative;
    overflow: hidden;
    display: grid;
    grid-template-columns: 1.2fr minmax(220px, .9fr);
    gap: 1.25rem;
    align-items: center;
}
.pzf-cc-hero::before {
    content: "";
    position: absolute;
    top: 0; left: 0;
    width: 5px;
    height: 100%;
    background: linear-gradient(180deg, var(--pzf-primary), var(--pzf-gold));
}
@media (max-width: 768px) {
    .pzf-cc-hero { grid-template-columns: 1fr; gap: 1.25rem; }
}

.pzf-cc-hero-info { min-width: 0; }
.pzf-cc-hero-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--pzf-text-muted);
    margin-bottom: .25rem;
}
.pzf-cc-hero-eyebrow i { color: var(--pzf-primary-text); }
.pzf-cc-hero-title {
    font-size: 1.2rem;
    font-weight: 700;
    letter-spacing: -.02em;
    color: var(--pzf-text);
    margin: 0 0 .25rem 0;
    line-height: 1.2;
    display: flex;
    align-items: center;
    gap: .45rem;
    flex-wrap: wrap;
}
.pzf-cc-hero-meta {
    color: var(--pzf-text-muted);
    font-size: .8rem;
    display: flex;
    gap: .85rem;
    flex-wrap: wrap;
    margin-top: .15rem;
}
.pzf-cc-hero-meta span {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
}
.pzf-cc-hero-meta strong {
    color: var(--pzf-text);
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}

/* Saldos del hero: uno, o dos lado a lado (pesos y divisa) */
.pzf-cc-saldos {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    gap: .5rem;
}
@media (max-width: 480px) {
    .pzf-cc-saldos { grid-auto-flow: row; }
}

/* Display de saldo principal */
.pzf-cc-saldo {
    background: var(--pzf-surface-2);
    border: 1px solid var(--pzf-border);
    border-radius: var(--pzf-radius-sm);
    padding: .8rem 1rem;
    text-align: right;
    position: relative;
}
.pzf-cc-saldo-label {
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--pzf-text-muted);
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: .3rem;
    margin-bottom: .25rem;
}
.pzf-cc-saldo-value {
    font-size: 1.65rem;
    font-weight: 700;
    line-height: 1.05;
    letter-spacing: -.02em;
    font-variant-numeric: tabular-nums;
    color: var(--pzf-text);
}
.pzf-cc-saldo-currency {
    font-size: .92rem;
    font-weight: 600;
    color: var(--pzf-text-muted);
    margin-right: .3rem;
}

.pzf-cc-saldo.tone-debt {
    background: rgba(var(--pzf-danger-rgb), .07);
    border-color: rgba(var(--pzf-danger-rgb), .25);
}
.pzf-cc-saldo.tone-debt .pzf-cc-saldo-label { color: var(--pzf-danger); }
.pzf-cc-saldo.tone-debt .pzf-cc-saldo-value { color: var(--pzf-danger); }

.pzf-cc-saldo.tone-credit {
    background: rgba(var(--pzf-success-rgb), .07);
    border-color: rgba(var(--pzf-success-rgb), .25);
}
.pzf-cc-saldo.tone-credit .pzf-cc-saldo-label { color: var(--pzf-success); }
.pzf-cc-saldo.tone-credit .pzf-cc-saldo-value { color: var(--pzf-success); }

.pzf-cc-saldo.tone-zero {
    background: var(--pzf-surface-2);
}
.pzf-cc-saldo.tone-zero .pzf-cc-saldo-value { color: var(--pzf-text-muted); }

/* Toolbar de acciones */
.pzf-cc-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .65rem;
    flex-wrap: wrap;
    margin-bottom: .75rem;
}
.pzf-cc-toolbar-actions {
    display: flex;
    gap: .5rem;
    flex-wrap: wrap;
}
.pzf-cc-toolbar-filter {
    display: flex;
    align-items: center;
    gap: .5rem;
    background: var(--pzf-surface);
    border: 1px solid var(--pzf-border);
    border-radius: var(--pzf-radius);
    padding: .25rem .5rem .25rem .75rem;
    box-shadow: var(--pzf-shadow-sm);
}
.pzf-cc-toolbar-filter label {
    font-size: .78rem;
    color: var(--pzf-text-muted);
    margin: 0;
    white-space: nowrap;
}
.pzf-cc-toolbar-filter .form-control {
    border: 0;
    padding: .35rem .5rem;
    background: transparent;
    min-width: 120px;
    box-shadow: none;
    font-size: .85rem;
}
.pzf-cc-toolbar-filter .form-control:focus { box-shadow: none; }

/* Tabla de movimientos: tonos y signos por columna */
.pzf-cc-table td.pzf-cc-debe-cell  { color: var(--pzf-danger); font-weight: 500; }
.pzf-cc-table td.pzf-cc-haber-cell { color: var(--pzf-success); font-weight: 500; }
.pzf-cc-table td.pzf-cc-saldo-cell {
    font-weight: 600;
    font-variant-numeric: tabular-nums;
}
.pzf-cc-table td.pzf-cc-saldo-cell.is-debt   { color: var(--pzf-danger); }
.pzf-cc-table td.pzf-cc-saldo-cell.is-credit { color: var(--pzf-success); }
.pzf-cc-table td.pzf-cc-saldo-cell.is-zero   { color: var(--pzf-text-muted); }

.pzf-cc-table tfoot td {
    background: var(--pzf-surface-2);
    border-top: 2px solid var(--pzf-border-strong);
    padding: .75rem .85rem;
    font-weight: 600;
}

/* Badge por tipo de movimiento (tono según texto del tipo via JS o data-attr) */
.pzf-cc-tipo-badge {
    display: inline-block;
    padding: .25em .65em;
    border-radius: 999px;
    font-size: .72rem;
    font-weight: 600;
    letter-spacing: .01em;
    background: var(--pzf-secondary-soft);
    color: var(--pzf-text-muted);
    white-space: nowrap;
}
.pzf-cc-tipo-badge[data-tone="primary"] { background: var(--pzf-primary-soft); color: var(--pzf-primary-text); }
.pzf-cc-tipo-badge[data-tone="success"] { background: rgba(var(--pzf-success-rgb), .14); color: var(--pzf-success); }
.pzf-cc-tipo-badge[data-tone="danger"]  { background: rgba(var(--pzf-danger-rgb), .14);  color: var(--pzf-danger); }
.pzf-cc-tipo-badge[data-tone="warning"] { background: rgba(var(--pzf-warning-rgb), .18); color: var(--pzf-warning-text); }
.pzf-cc-tipo-badge[data-tone="info"]    { background: rgba(var(--pzf-info-rgb), .14); color: var(--pzf-info); }
.pzf-cc-tipo-badge[data-tone="gold"]  { background: var(--pzf-gold-soft); color: var(--pzf-gold-text); }

/* Empty state amigable */
.pzf-cc-empty {
    text-align: center;
    padding: 2rem 1rem;
    color: var(--pzf-text-muted);
    font-size: .9rem;
}
.pzf-cc-empty i {
    font-size: 2rem;
    color: var(--pzf-border-strong);
    margin-bottom: .35rem;
    display: block;
}


/* ---- Pestañas de cuentas corrientes del cliente ---- */
.pzf-cc-cuentas {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    margin-bottom: 1rem;
}
.pzf-cc-cuenta-tab {
    display: flex;
    flex-direction: column;
    gap: .15rem;
    padding: .55rem .9rem;
    border: 1px solid var(--pzf-border);
    border-radius: var(--pzf-radius);
    background: var(--pzf-surface);
    color: var(--pzf-text);
    text-decoration: none;
    transition: border-color .15s var(--pzf-ease), background .15s var(--pzf-ease);
}
.pzf-cc-cuenta-tab:hover {
    border-color: var(--pzf-border-strong);
    background: var(--pzf-hover);
    color: var(--pzf-text);
}
.pzf-cc-cuenta-tab.is-active {
    border-color: var(--pzf-primary);
    background: var(--pzf-primary-soft);
}
.pzf-cc-cuenta-nombre {
    font-weight: 600;
    font-size: .9rem;
    display: flex;
    align-items: center;
    gap: .35rem;
}
.pzf-cc-cuenta-moneda {
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .04em;
    padding: .05rem .35rem;
    border-radius: var(--pzf-radius-sm);
    background: var(--pzf-gold-soft);
    color: var(--pzf-gold-text);
}
.pzf-cc-cuenta-saldo {
    font-size: .8rem;
    color: var(--pzf-text-muted);
    font-variant-numeric: tabular-nums;
}
.pzf-cc-cuenta-tab.is-active .pzf-cc-cuenta-saldo { color: var(--pzf-primary-text); }

/* ---- Vista previa de una compensación ---- */
.pzf-compensacion-preview {
    border: 1px solid var(--pzf-border);
    border-left: 3px solid var(--pzf-primary);
    border-radius: var(--pzf-radius);
    background: var(--pzf-surface-alt);
    padding: .85rem 1rem;
}
.pzf-compensacion-preview-title {
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .06em;
    color: var(--pzf-text-muted);
    margin-bottom: .5rem;
}
.pzf-compensacion-preview-grid {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: .3rem 1rem;
    margin: 0;
}
.pzf-compensacion-preview-grid dt {
    font-weight: 400;
    color: var(--pzf-text-muted);
    font-size: .88rem;
}
.pzf-compensacion-preview-grid dd {
    margin: 0;
    text-align: right;
    font-variant-numeric: tabular-nums;
    font-size: .92rem;
}
.pzf-compensacion-preview-grid dd.is-strong {
    font-weight: 700;
    color: var(--pzf-primary-text);
}
.pzf-compensacion-preview-nota {
    margin-top: .6rem;
    padding-top: .5rem;
    border-top: 1px solid var(--pzf-border);
    font-size: .8rem;
    color: var(--pzf-text-muted);
}

/* ============================================================
 * 21. Overrides utilidades Bootstrap para alinear a la paleta.
 * Bootstrap usa --bs-primary internamente para .bg-primary, .text-primary, etc.
 * Lo redirigimos al token EL ENSUEÑO para evitar el azul Bootstrap default.
 * ============================================================ */
:root {
    --bs-primary: var(--pzf-primary);
    --bs-primary-rgb: var(--pzf-primary-rgb);
    --bs-link-color: var(--pzf-primary-text);
    --bs-link-hover-color: var(--pzf-primary-text-hover);
    --bs-body-color: var(--pzf-text);
    --bs-body-bg: var(--pzf-bg);
    --bs-border-color: var(--pzf-border);
    /* Sin esto los ~40 bg-warning de los templates usarían el #ffc107 stock
       de Bootstrap y el naranja de "atención" no se vería en pantalla. */
    --bs-warning: var(--pzf-warning);
    --bs-warning-rgb: var(--pzf-warning-rgb);
    --bs-success: var(--pzf-success);
    --bs-success-rgb: var(--pzf-success-rgb);
    --bs-info: var(--pzf-info);
    --bs-info-rgb: var(--pzf-info-rgb);
    --bs-danger: var(--pzf-danger);
    --bs-danger-rgb: var(--pzf-danger-rgb);
}

.bg-primary {
    background-color: var(--pzf-primary) !important;
}
.text-primary {
    color: var(--pzf-primary-text) !important;
}
.border-primary {
    border-color: var(--pzf-primary) !important;
}
.link-primary {
    color: var(--pzf-primary-text) !important;
}
.link-primary:hover,
.link-primary:focus {
    color: var(--pzf-primary-text-hover) !important;
}

.bg-warning {
    background-color: var(--pzf-warning) !important;
}
.text-warning {
    color: var(--pzf-warning-text) !important;
}
.border-warning {
    border-color: var(--pzf-warning) !important;
}
.text-success { color: var(--pzf-success) !important; }
.text-info    { color: var(--pzf-info) !important; }

/* Relleno naranja: el blanco encima da 2.96:1, va texto oscuro (5.81:1). */
.bg-warning,
.bg-warning * {
    color: var(--pzf-on-warning);
}
.btn-warning {
    background-color: var(--pzf-warning);
    border-color: var(--pzf-warning);
    color: var(--pzf-on-warning);
}
.btn-warning:hover,
.btn-warning:focus {
    background-color: var(--pzf-warning-text);
    border-color: var(--pzf-warning-text);
    color: var(--pzf-on-color);
}
.btn-outline-warning {
    color: var(--pzf-warning-text);
    border-color: var(--pzf-warning);
    background: transparent;
}
.btn-outline-warning:hover,
.btn-outline-warning:focus {
    background: var(--pzf-warning);
    color: var(--pzf-on-color);
}

/* Respeta usuarios que prefieren menos movimiento. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: .01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .01ms !important;
        scroll-behavior: auto !important;
    }
    .pzf-skeleton::after { animation: none; }
}

/* ──────────────────────────────────────────────────────────────────────────
   Detalle de obra — navegación de pestañas en mobile
   Las ~16 pestañas envuelven en varias filas y se ven amontonadas. En mobile
   las convertimos en una sola fila horizontal scrolleable (swipe), con
   indicador inferior estilo "underline". (#obraTabs vive en obra_detalle.html)
   ────────────────────────────────────────────────────────────────────────── */
@media (max-width: 767.98px) {
    #obraTabs {
        flex-wrap: nowrap;
        overflow-x: auto;
        overflow-y: hidden;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;                 /* Firefox */
        border-bottom: 1px solid var(--pzf-border);
        gap: .15rem;
    }
    #obraTabs::-webkit-scrollbar { display: none; }   /* WebKit */
    #obraTabs .nav-item { flex: 0 0 auto; }
    #obraTabs .nav-link {
        white-space: nowrap;
        border: 0;
        border-bottom: 2px solid transparent;
        border-radius: 0;
        padding: .5rem .8rem;
        color: var(--pzf-text-muted);
        font-weight: 500;
    }
    #obraTabs .nav-link:hover { color: var(--pzf-primary-text); }
    #obraTabs .nav-link.active {
        color: var(--pzf-primary-text);
        background: transparent;
        border-bottom-color: var(--pzf-primary);
    }
}

/* ===========================================================================
   Carga rápida del home (F6)

   Todo con tokens `--pzf-*`, que ya cubren claro y oscuro: no hay un solo
   color literal acá. Ver docs/agro/07-carga-rapida-home.md.
   =========================================================================== */

/* `.pzf-quick-btn` nació en la barra de acciones del home, que se retiró
   cuando el FAB pasó a cubrir escritorio y mobile por igual. Sobrevive porque
   los tiles del modal de carga rápida lo reusan tal cual. */

.pzf-quick-btn {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .35rem;
    padding: .85rem .5rem;
    border: 1px solid var(--pzf-border);
    border-radius: var(--pzf-radius);
    background: var(--pzf-surface-2);
    color: var(--pzf-text);
    font-size: .82rem;
    font-weight: 600;
    line-height: 1.2;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: transform .12s ease, box-shadow .12s ease, border-color .12s ease;
}

.pzf-quick-btn i {
    font-size: 1.45rem;
    line-height: 1;
}

.pzf-quick-btn:hover,
.pzf-quick-btn:focus-visible {
    color: var(--pzf-text);
    transform: translateY(-2px);
    box-shadow: var(--pzf-shadow);
}

/* El color del icono es lo único que distingue una acción de otra: el fondo
   queda neutro para que la barra no compita con los KPIs. */
.pzf-quick-primary i   { color: var(--pzf-primary-text); }
.pzf-quick-success i   { color: var(--pzf-success); }
.pzf-quick-warning i   { color: var(--pzf-warning-text, var(--pzf-warning)); }
.pzf-quick-info i      { color: var(--pzf-info); }
.pzf-quick-secondary i { color: var(--pzf-text-muted); }
.pzf-quick-danger i    { color: var(--pzf-danger); }

.pzf-quick-primary:hover   { border-color: var(--pzf-primary); }
.pzf-quick-success:hover   { border-color: var(--pzf-success); }
.pzf-quick-warning:hover   { border-color: var(--pzf-warning); }
.pzf-quick-info:hover      { border-color: var(--pzf-info); }
.pzf-quick-secondary:hover { border-color: var(--pzf-border-strong); }
.pzf-quick-danger:hover    { border-color: var(--pzf-danger); }

@media (prefers-reduced-motion: reduce) {
    .pzf-quick-btn { transition: none; }
    .pzf-quick-btn:hover { transform: none; }
}

/* ===========================================================================
   Medios de pago en bloque (`PZF.Medios.fila({bloque: true})`)
   ---------------------------------------------------------------------------
   En los forms angostos (el modal de carga rápida) cada medio es una tarjeta:
   método y monto arriba, el cheque abajo a todo el ancho. En la tabla de las
   pantallas completas el cheque quedaba apretado entre el método y el monto.
   =========================================================================== */
.pzf-medio {
    background: var(--pzf-surface);
    border: 1px solid var(--pzf-border);
    border-radius: var(--pzf-radius-sm, .375rem);
    padding: .5rem .75rem .6rem;
}
.pzf-medio + .pzf-medio { margin-top: .5rem; }
.pzf-medio .med-cheque { padding-top: .25rem; border-top: 1px dashed var(--pzf-border); margin-top: .35rem; }

/* ===========================================================================
   Ingesta por IA — marcado de lo que hay que revisar (F8)
   ---------------------------------------------------------------------------
   Un campo precargado por IA que el sistema no pudo resolver con certeza. El
   amarillo es señal de "mirá esto", no de error: el dato puede estar bien.
   Usa los tokens de warning, que ya están resueltos para claro y oscuro.
   =========================================================================== */
.pzf-ia-dudoso {
    background-color: rgba(var(--pzf-warning-rgb), .14);
    border-radius: var(--pzf-radius-sm, .375rem);
    box-shadow: inset 0 0 0 1px rgba(var(--pzf-warning-rgb), .45);
}

/* Dentro de una celda de tabla el fondo solo no se distingue del zebrado. */
td.pzf-ia-dudoso,
tr[data-lote-nuevo] td.pzf-ia-dudoso {
    box-shadow: inset 0 0 0 2px rgba(var(--pzf-warning-rgb), .5);
}

/* El marcado se saca al tocar el campo: si alguien ya lo revisó, dejarlo
   amarillo hace que el resto de las marcas pierdan sentido. */
.pzf-ia-dudoso:focus-within {
    background-color: transparent;
    box-shadow: none;
}

/* El motivo de la marca, debajo del campo: "la fecha es de hace 2.000 días". */
.form-text.pzf-ia-aviso {
    color: var(--pzf-warning-text);
}

/* El pie del form de orden: el importe facturable es el número que la persona
   está tratando de obtener, así que acompaña el scroll en vez de quedar al
   final. La clase se usaba desde F3 pero nunca se había estilado — el total
   quedaba tres pantallas más abajo. */
/* El pie se pega al borde del *content box* del contenedor de scroll, así que
   el padding-bottom de `.pzf-page-main` lo dejaba flotando con una franja de
   fondo abajo. Donde hay pie de acción propio ese colchón sobra: el pie ya tapa
   la zona. (Valía para mobile desde F9; en escritorio faltaba.) */
.pzf-page-main:has(.pzf-ot-footer) { padding-bottom: 0; }

.pzf-ot-footer {
    position: sticky;
    bottom: 0;
    z-index: 5;
    background: var(--pzf-surface);
    border-top: 1px solid var(--pzf-border);
    box-shadow: 0 -4px 12px rgba(0, 0, 0, .08);
    padding: .75rem 0;
    margin-top: 1rem;
}


/* ===========================================================================
   Carga de orden de trabajo en el celular
   ---------------------------------------------------------------------------
   La labor se carga desde un escritorio, casi siempre importando el PDF del
   ingeniero — no parado al lado de la máquina, como suponía el diseño
   original. Esto igual se mantiene: el responsive es obligatorio, y la
   pantalla de recursos sí se completa a veces desde el celular.

   Los formsets son tablas de 4 a 8 columnas: en un celular obligan a un
   scroll horizontal por fila, que es la forma más segura de que alguien cargue
   las hectáreas en la columna del rinde. En mobile se apilan como fichas
   "etiqueta → campo", con el mismo criterio que `pzf-list-mobile.js` usa para
   los listados — pero acá sin JS, porque las filas las clona `ot_form.js` y un
   observer se perdería las nuevas.
   =========================================================================== */
@media (max-width: 767.98px) {
    .pzf-ot-form .pzf-table-wrap { overflow-x: visible; }

    .pzf-ot-form table.pzf-table thead,
    .pzf-ot-form table.pzf-table tfoot {
        display: none;
    }

    .pzf-ot-form table.pzf-table,
    .pzf-ot-form table.pzf-table tbody,
    .pzf-ot-form table.pzf-table tr,
    .pzf-ot-form table.pzf-table td {
        display: block;
        width: 100%;
    }

    .pzf-ot-form table.pzf-table tr.pzf-formset-row {
        border: 1px solid var(--pzf-border);
        border-radius: var(--pzf-radius);
        background: var(--pzf-surface);
        padding: .75rem;
        margin-bottom: .75rem;
    }

    .pzf-ot-form table.pzf-table td {
        border: 0;
        padding: .25rem 0;
    }

    .pzf-ot-form table.pzf-table td[data-label]::before {
        content: attr(data-label);
        display: block;
        font-size: .72rem;
        font-weight: 600;
        text-transform: uppercase;
        letter-spacing: .04em;
        color: var(--pzf-text-muted);
        margin-bottom: .15rem;
    }

    /* Las reglas de toque salieron de acá a `.pzf-touch` (abajo), porque las
       necesita también el modal de carga rápida. El form de OT la hereda. */

    /* En mobile el pie ocupa el ancho completo y los botones se agrandan. */
    .pzf-ot-footer .btn { min-height: 2.75rem; }

    /* Sangrado completo: sin esto quedan dos franjas del fondo a los costados
       del pie, porque `.pzf-page-main` mete .9rem de padding lateral. */
    /* .9rem de `.pzf-page-main` + .75rem del `.container-xl` que lo envuelve. */
    .pzf-ot-footer {
        margin-inline: -1.65rem;
        padding-left: 1.65rem;
        padding-right: 1.65rem;
        padding-bottom: calc(.75rem + env(safe-area-inset-bottom, 0px));
    }

    .pzf-ot-footer > .container-xl { padding-inline: 0; }

    /* El FAB de carga rápida caía justo encima de "Siguiente". Estando dentro
       del form de una OT el atajo no aporta nada: el pie es la acción. */
    body:has(.pzf-ot-footer) .pzf-fab { display: none; }
}


/* ===========================================================================
   .pzf-touch — pantallas que se usan con el dedo
   ---------------------------------------------------------------------------
   Dos reglas, y la primera no es estética: **por debajo de 16px iOS hace zoom
   al enfocar un input**, y después la página queda corrida. En un modal a
   pantalla completa eso descoloca todo.

   La segunda es el objetivo de toque de 44px, que es lo que hace falta para
   acertarle con guantes o con las manos sucias.

   Nació scopeada al form de orden de trabajo (F9); la carga rápida mobile la
   necesita igual, así que se promovió a una clase propia.
   =========================================================================== */
@media (max-width: 767.98px) {
    .pzf-touch .form-control,
    .pzf-touch .form-select,
    .pzf-touch .ts-control,
    .pzf-ot-form .form-control,
    .pzf-ot-form .form-select,
    .pzf-ot-form .ts-control {
        font-size: 16px;
        min-height: 2.75rem;
    }

    /* El dropdown se monta en <body>, fuera de .pzf-touch: la regla va suelta. */
    .ts-dropdown .dropdown-input {
        font-size: 16px;
        min-height: 2.75rem;
    }

    .pzf-touch .btn,
    .pzf-ot-form .btn { min-height: 2.75rem; }

    .pzf-touch input[type="checkbox"],
    .pzf-ot-form input[type="checkbox"] {
        width: 1.35rem;
        height: 1.35rem;
    }
}


/* ===========================================================================
   Carga rápida: botón flotante y selector de tipo
   =========================================================================== */

/* El botón que hace que esto esté "desde el inicio" en toda pantalla.
   `env(safe-area-inset-bottom)` no es opcional: con `viewport-fit=cover` en el
   viewport (ya está en el `<head>`), sin él el botón queda debajo de la barra
   de gestos del iPhone y no se puede tocar. */
.pzf-fab {
    position: fixed;
    right: calc(1rem + env(safe-area-inset-right, 0px));
    bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
    z-index: 1040;              /* debajo del modal (1055), encima del resto */
    width: 3.5rem;
    height: 3.5rem;
    border: 0;
    border-radius: 50%;
    background: var(--pzf-primary);
    color: var(--pzf-on-color);
    font-size: 1.5rem;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 6px 18px rgba(var(--pzf-primary-rgb), .45);
    transition: transform .15s ease, background-color .15s ease;
}

.pzf-fab:hover,
.pzf-fab:focus-visible {
    background: var(--pzf-primary-hover, var(--pzf-primary));
    transform: scale(1.06);
    color: var(--pzf-on-color);
}

.pzf-fab:active { transform: scale(.96); }

/* Con el modal abierto el botón sólo estorba. */
body.modal-open .pzf-fab { display: none; }

/* En escritorio el acceso vive en la navbar: un botón flotante taparía
   contenido y nadie lo buscaría ahí. La excepción es el home, que antes tenía
   una barra de seis botones ocupando media pantalla: el FAB hace lo mismo sin
   empujar los KPI hacia abajo. */
@media (min-width: 768px) {
    .pzf-fab { display: none; }
    body.pzf-en-home .pzf-fab { display: flex; }

    /* Los dos FAB comparten esquina; en mobile ya se apilan, acá hace falta
       repetirlo porque aquella regla vive en un `max-width`. */
    body.pzf-en-home .pzf-fab-ayuda {
        bottom: calc(5.5rem + env(safe-area-inset-bottom, 0px));
    }

    /* Con dos botones apilados, sin colchón tapan el final del contenido. */
    body.pzf-en-home .pzf-page-main { padding-bottom: 5rem; }
}

@media (prefers-reduced-motion: reduce) {
    .pzf-fab { transition: none; }
    .pzf-fab:hover, .pzf-fab:focus-visible, .pzf-fab:active { transform: none; }
}

/* Los tiles del paso 1. Reusa `.pzf-quick-btn` y sus variantes de color, que
   ya están verificadas en tema claro y oscuro; acá sólo se define la grilla. */
.pzf-rapido-tiles,
.pzf-rapido-subtiles {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: .75rem;
}

.pzf-rapido-tiles .pzf-quick-btn,
.pzf-rapido-subtiles .pzf-quick-btn {
    position: relative;
    flex-direction: column;
    justify-content: center;
    text-align: center;
    gap: .4rem;
    min-height: 6rem;
    padding: 1rem .75rem;
}

.pzf-rapido-tiles .pzf-quick-btn i:first-child,
.pzf-rapido-subtiles .pzf-quick-btn i:first-child {
    font-size: 1.75rem;
}

/* La flecha que avisa que el tile despliega más opciones en vez de abrir. */
.pzf-rapido-tile-mas {
    position: absolute;
    top: .5rem;
    right: .5rem;
    font-size: .8rem;
    opacity: .5;
}

@media (min-width: 576px) {
    .pzf-rapido-tiles,
    .pzf-rapido-subtiles { grid-template-columns: repeat(3, 1fr); }
}

/* Pagar cheques: con muchos pendientes, la lista scrollea y el método de pago
   y el botón Guardar siguen a la vista. */
.pzf-cheques-pagar {
    max-height: 45vh;
    overflow-y: auto;
}

.pzf-cheques-pagar .list-group-item { cursor: pointer; }


/* ===========================================================================
   Ayuda contextual: botón flotante y contenido del modal
   =========================================================================== */

/* Clase propia y no `.pzf-fab` por dos motivos: aquél se esconde en escritorio
   (su acceso vive en la navbar) y la ayuda tiene que estar en los dos lados, y
   además comparten esquina. El reparto queda así:

       escritorio   carga rápida oculta  ·  ayuda abajo a la derecha
       mobile       carga rápida abajo   ·  ayuda apilada encima

   `env(safe-area-inset-*)` no es opcional: el viewport usa `viewport-fit=cover`
   y sin él el botón queda debajo de la barra de gestos del iPhone. */
.pzf-fab-ayuda {
    position: fixed;
    right: calc(1rem + env(safe-area-inset-right, 0px));
    bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
    z-index: 1040;              /* mismo escalón que .pzf-fab: bajo el modal (1055) */
    width: 3.5rem;
    height: 3.5rem;
    padding: 0;
    border: 1px solid var(--pzf-border);
    border-radius: 50%;
    /* Superficie neutra a propósito: el verde lleno es del botón de carga
       rápida, que es la acción primaria. La ayuda no compite con él. */
    background: var(--pzf-surface);
    color: var(--pzf-text-muted);
    font-size: 1.35rem;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: var(--pzf-shadow);
    transition: transform .15s ease, background-color .15s ease, color .15s ease;
}

.pzf-fab-ayuda:hover,
.pzf-fab-ayuda:focus-visible {
    background: var(--pzf-primary);
    border-color: var(--pzf-primary);
    color: var(--pzf-on-color);
    transform: scale(1.06);
}

.pzf-fab-ayuda:focus-visible {
    outline: 2px solid var(--pzf-focus-ring);
    outline-offset: 2px;
}

.pzf-fab-ayuda:active { transform: scale(.96); }

/* Con un modal abierto el botón sólo estorba — mismo criterio que .pzf-fab. */
body.modal-open .pzf-fab-ayuda { display: none; }

@media (max-width: 767.98px) {
    /* Apilado sobre el FAB de carga rápida (1rem + 3.5rem de alto + aire). */
    .pzf-fab-ayuda {
        bottom: calc(5.5rem + env(safe-area-inset-bottom, 0px));
        width: 3rem;
        height: 3rem;
        font-size: 1.15rem;
    }

    /* Con dos botones apilados en la esquina, sin este colchón la última fila
       de la tabla y la paginación quedan tapadas al llegar al fondo. */
    .pzf-page-main { padding-bottom: 5rem; }
}

@media (prefers-reduced-motion: reduce) {
    .pzf-fab-ayuda { transition: none; }
    .pzf-fab-ayuda:hover,
    .pzf-fab-ayuda:focus-visible,
    .pzf-fab-ayuda:active { transform: none; }
}

/* ---------- Contenido del modal ---------- */
.pzf-ayuda-seccion {
    font-size: .8rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--pzf-text-muted);
    margin-top: 1rem;
    margin-bottom: .5rem;
}

.pzf-ayuda-seccion:first-child { margin-top: 0; }

.pzf-ayuda-pasos { padding-left: 1.25rem; margin-bottom: 0; }
.pzf-ayuda-pasos li { margin-bottom: .5rem; }

.pzf-ayuda-tips { list-style: none; padding-left: 0; margin-bottom: 0; }

.pzf-ayuda-tips li {
    display: flex;
    gap: .5rem;
    align-items: baseline;
    margin-bottom: .5rem;
    color: var(--pzf-text-muted);
}

/* Dorado *como texto* va con el token de texto: `--pzf-gold` es relleno y
   sobre fondo claro no llega al contraste mínimo. */
.pzf-ayuda-tips .bi-lightbulb {
    color: var(--pzf-gold-text);
    flex-shrink: 0;
}


/* ===========================================================================
   Form de la labor de campo
   ---------------------------------------------------------------------------
   Hasta la simplificación esto era un wizard de cuatro pasos, justificado en
   que la orden "se carga en el campo, con el teléfono en una mano". No era
   cierto: se carga desde un escritorio, casi siempre importando el PDF del
   ingeniero. Con el personal y las máquinas fuera del alta y el precio saliendo
   de la tarifa, lo que queda entra en una pantalla y el stepper se fue.
   =========================================================================== */

/* Datos que sólo se conocen al terminar el trabajo (rinde, fecha de fin,
   horómetro, km al cerrar). En el alta nadie los tiene a mano. */
.pzf-cierre-oculto .pzf-cierre { display: none !important; }

/* Precio y observaciones por lote: la excepción (una cosecha que se paga
   distinto en cada parcela), no el caso. */
.pzf-detalle-lote-oculto .pzf-col-detalle { display: none !important; }

/* --- Bloque plegable ------------------------------------------------------
   Para lo que existe pero no es el caso: el ajuste de precio de una labor, los
   datos que se completan después. Pedir menos arriba vale sólo si lo que se
   pliega sigue estando a un clic y se ve que está. */
.pzf-plegable > summary {
    cursor: pointer;
    color: var(--pzf-primary-text);
    list-style: none;
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    padding: .25rem 0;
}
.pzf-plegable > summary::-webkit-details-marker { display: none; }
.pzf-plegable > summary::before {
    content: "›";
    display: inline-block;
    transition: transform .15s ease;
    font-size: 1.1em;
    line-height: 1;
}
.pzf-plegable[open] > summary::before { transform: rotate(90deg); }
.pzf-plegable > summary:hover { color: var(--pzf-primary-text-hover); }
.pzf-plegable > summary:focus-visible {
    outline: 2px solid var(--pzf-primary-text);
    outline-offset: 2px;
    border-radius: var(--pzf-radius);
}
