
/* Ocultar numeritos de prioridad de orden en encabezados del admin */
table thead th .sortpriority {
    display: none !important;
}

:root {
    /* Los tokens de marca NO se declaran acá: salen de design_tokens.css, que
       templates/admin/base_site.html carga JUSTO ANTES de este archivo.
       Estaban escritos dos veces -- 30 tokens idénticos, acá y allá -- porque el
       admin no cargaba aquel archivo. Ahora el admin, el portal y el login leen
       la misma fuente, y de este :root quedan sólo los SEIS que son propios del
       admin y no le sirven a nadie más.

       Si alguna pantalla del admin llegara a linkear este archivo por su cuenta,
       tiene que poner design_tokens.css delante o se queda sin tokens. */

    /* El hover del azul de acción: sólo existe en el admin, que es el único con
       botones que cambian al pasar el mouse. */
    --net-action-hover: #002c96;

    /* Ancho de la columna de contenido centrada de la casa (header, breadcrumb,
       changelists, main). Fuente única de este valor DENTRO del admin: antes
       estaba escrito 4 veces como literal. No alcanza a depositos.css (logística
       no carga este archivo, tiene su propio :root con el mismo token).
       PENDIENTE de la misma limpieza: las variantes de forms
       `min(100% - 32px, 760px)` y `min(100% - 32px, 820px)`, hoy repetidas. */
    --net-content-width: min(100% - 32px, 1440px);

    /* Alias retrocompatibles: mismos nombres que ya consumían las reglas de
       este archivo, ahora resueltos contra los tokens canónicos de
       design_tokens.css. */
    --azul-principal: var(--net-ink);
    --azul-medio: var(--net-teal);
    --borde-sidebar: var(--net-border);
    --activo-sidebar: #bfcef1;
}

/* ============================================================
   FASE 1 — vestir el molde base del admin de Django (base.css)
   ============================================================
   Django (6.0.6) centraliza casi todo el theming del admin en custom
   properties CSS definidas en su propio `:root` (base.css, líneas 6-91:
   --primary, --secondary, --header-bg, --breadcrumbs-bg, --button-bg,
   --link-fg, --message-*-bg, --object-tools-bg, --delete-button-bg,
   --font-family-primary, etc.). Como admin_custom.css se carga DESPUÉS
   del base.css nativo (vía {% block extrastyle %} en
   templates/admin/base_site.html), alcanza con REDEFINIR esas mismas
   variables acá — Django ya las consume en botones, breadcrumbs,
   mensajes, herramientas de objeto y el header, sin que haya que tocar
   ni un selector propio de Django. Cero riesgo de romper el JS nativo
   del admin (no se toca estructura DOM ni display, solo colores/
   tipografía). No cubre el toggle de modo oscuro del admin
   (html[data-theme="dark"], en dark_mode.css) — el resto del sistema
   no tiene modo oscuro, así que queda fuera de esta fase a propósito;
   si hace falta se revisa aparte. Aprobado por Nacho, 2026-07-15.

   FASE 2 — changelists.css (listados): revisado el archivo completo
   (371 líneas) — tabla de resultados, thead, paginación, buscador,
   panel de filtros y barra de acciones en lote reusan las MISMAS
   variables que ya redefinimos en la Fase 1 (--hairline-color,
   --darkened-bg, --body-quiet-color, --button-bg, --link-hover-color,
   --border-color, --selected-bg, --selected-row), así que no hizo
   falta CSS nuevo. Único ajuste: --selected-bg (fondo de la columna
   por la que se está ordenando el listado) estaba mapeada al verde de
   "éxito" (--net-accent-bg) desde la Fase 1 sin pensar en este uso
   específico — semánticamente no es un estado de éxito, es solo
   "columna activa", así que se cambió a --net-info-bg (celeste) acá
   en la Fase 2. 2026-07-15.

   FASE 3 — forms.css (520 líneas) + widgets.css: revisados completos.
   Fieldsets (fieldset .fieldset-heading), form-rows, labels, inline
   groups (.inline-related, .inline-group .add-row) y el date/time
   picker emergente (.calendar, .datetimeshortcuts) reusan las mismas
   variables de la Fase 1 (--header-bg, --hairline-color,
   --darkened-bg, --body-quiet-color, --body-medium-color, --primary,
   --secondary, --accent, --button-fg) — tampoco hizo falta CSS nuevo.
   Verificado en vivo el único punto con color propio fuera de
   variables (el caption del calendario, verde con texto oscuro
   #333 — respeta la regla de marca "el verde nunca lleva texto
   blanco encima"). 2026-07-15. */
html[data-theme="light"],
:root {
    --primary: var(--net-action);
    --secondary: var(--net-action);
    --accent: var(--net-accent);
    --primary-fg: #ffffff;

    --body-fg: var(--net-text);
    --body-bg: var(--net-bg);
    --body-quiet-color: var(--net-muted);
    --body-medium-color: var(--net-text);
    --body-loud-color: var(--net-ink);

    --header-color: #ffffff;
    --header-branding-color: #ffffff;
    --header-bg: var(--net-ink);
    --header-link-color: #ffffff;

    --breadcrumbs-fg: var(--net-muted);
    --breadcrumbs-link-fg: var(--net-action);
    --breadcrumbs-bg: var(--net-surface-2);

    --link-fg: var(--net-action);
    --link-hover-color: var(--net-action-hover);
    --link-selected-fg: var(--net-action);

    --hairline-color: var(--net-border-soft);
    --border-color: var(--net-border);

    --error-fg: var(--net-danger-text);

    --message-success-bg: var(--net-ok-bg);
    --message-warning-bg: var(--net-warn-bg);
    --message-error-bg: var(--net-danger-bg);
    --message-info-bg: var(--net-info-bg);

    --darkened-bg: var(--net-surface-2);
    --selected-bg: var(--net-info-bg);
    --selected-row: #fff8db;

    --button-fg: #ffffff;
    --button-bg: var(--net-action);
    --button-hover-bg: var(--net-action-hover);
    --default-button-bg: var(--net-ink);
    --default-button-hover-bg: var(--net-action);
    --close-button-bg: #64748b;
    --close-button-hover-bg: #475569;
    --delete-button-bg: var(--net-danger-text);
    --delete-button-hover-bg: #7f1d1d;

    --object-tools-fg: #ffffff;
    --object-tools-bg: var(--net-action);
    --object-tools-hover-bg: var(--net-action-hover);

    --font-family-primary: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
}

.net-admin-back-button {
    display: inline-flex;
    align-items: center;
    width: fit-content;
    margin: 10px 0 0 20px;
    padding: 7px 11px;
    border: 1px solid var(--borde-sidebar);
    border-radius: var(--net-radius-sm);
    background: var(--net-surface-2);
    color: var(--azul-principal) !important;
    font-size: 13px;
    font-weight: 700;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
}

.net-admin-back-button:hover {
    background: var(--activo-sidebar);
    border-color: var(--azul-medio);
    color: var(--azul-principal) !important;
}

/* Header del admin más grande que el genérico .net-topbar (compartido con
   dashboard/logística, no tocar esas proporciones) -- acá al lado hay
   contenido a todo el ancho sin sidebar, así que el header necesita más
   peso visual para no sentirse chico en comparación. Scopeado a
   .net-shell-header-admin para no afectar los otros usos de .net-topbar. */
.net-shell-header-admin .net-topbar {
    min-height: 64px;
    padding: 14px 20px;
}

.net-shell-header-admin .net-brand-logo {
    height: 42px;
}

/* Menú desplegable de módulos (Opción B) -- reemplaza tener que volver
   siempre al Dashboard para saltar de módulo. Vanilla JS/CSS, sin
   librerías (admin_module_menu.js): cada categoría es un <button> +
   panel posicionado en absoluto, togglea aria-expanded/hidden. */
.net-shell-header-admin .net-topbar {
    flex-wrap: wrap;
}

.net-admin-module-nav {
    display: flex;
    align-items: center;
    gap: 4px;
    flex: 1;
    margin: 0 20px;
    flex-wrap: wrap;
}

.net-admin-module-group {
    position: relative;
}

.net-admin-module-btn {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    min-height: 36px;
    padding: 6px 12px;
    border: 1px solid transparent;
    border-radius: 8px;
    background: transparent;
    color: var(--net-ink);
    font-size: 13px;
    font-weight: 800;
    font-family: inherit;
    cursor: pointer;
}

.net-admin-module-btn:hover {
    background: var(--net-surface-2);
}

.net-admin-module-btn[aria-expanded="true"] {
    background: var(--net-surface-2);
    border-color: var(--net-border);
}

.net-admin-module-btn::after {
    content: "▾";
    font-size: 10px;
    opacity: 0.6;
}

.net-admin-module-panel {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: 40;
    min-width: 230px;
    padding: 6px;
    border: 1px solid var(--net-border);
    border-radius: 12px;
    background: var(--net-surface);
    box-shadow: 0 12px 28px rgba(15, 23, 42, 0.12);
}

.net-admin-module-panel a {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 9px 10px;
    border-radius: 8px;
    color: var(--net-ink) !important;
    font-size: 13px;
    font-weight: 700;
    text-decoration: none !important;
}

.net-admin-module-panel a:hover,
.net-admin-module-panel a:focus {
    background: var(--net-surface-2);
    outline: none;
}

@media (max-width: 760px) {
    .net-admin-module-nav {
        order: 3;
        width: 100%;
        margin: 10px 0 0;
    }
}

/* Migas de pan -- venían como una franja de fábrica de Django (fondo
   plano, ancho completo, padding propio) totalmente desconectada del
   header nuevo. Se le da el mismo tratamiento de tarjeta (ancho
   capado + centrado, borde, radio, sombra) que .net-topbar, para que
   lea como parte del mismo bloque en vez de una franja aparte. Misma
   especificidad que la regla nativa de Django (div.breadcrumbs) para
   ganarle en la cascada sin necesitar !important. */
div.breadcrumbs {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
    align-items: center;
    gap: 12px;
    box-sizing: border-box;
    width: var(--net-content-width);
    margin: 14px auto 22px;
    padding: 14px 18px;
    border: 1px solid rgba(217, 222, 229, 0.84);
    border-radius: 12px;
    background: var(--net-surface);
    box-shadow: 0 4px 12px rgba(15, 23, 42, 0.04);
}

.net-admin-breadcrumb-title {
    grid-column: 2;
    font-size: 22px;
    font-weight: 800;
    color: var(--net-ink);
    text-align: center;
}

/* "← Volver" pasa de quedar colgado debajo de las migas de pan a vivir
   adentro de la misma tarjeta, a la izquierda -- misma columna donde
   vive la acción principal (derecha) en el otro extremo, así el título
   queda centrado entre las dos. */
.breadcrumbs .net-admin-back-button {
    grid-column: 1;
    justify-self: start;
    margin: 0;
    flex-shrink: 0;
}

/* Acciones del listado (ej. "Agregar Cobro", "Resumen de caja") -- se
   reubican acá desde .object-tools (admin_title_bar_action.js) para que
   la tarjeta del título quede Volver / título / acciones en una sola
   fila, consistente en cualquier modelo del admin. La de "Agregar X"
   siempre es la primaria (azul, a la derecha de todo); cualquier otro
   item de .object-tools (reportes, resúmenes) queda como secundaria al
   lado, en vez de colgar suelta más abajo. */
.breadcrumbs .net-admin-title-bar-actions {
    grid-column: 3;
    justify-self: end;
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

.net-admin-title-bar-action {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 9px 16px;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 700;
    text-decoration: none !important;
    white-space: nowrap;
}

.net-admin-title-bar-action-primaria {
    background: var(--net-action, #1a4fd6);
    color: #fff !important;
    border: 1px solid transparent;
}

.net-admin-title-bar-action-primaria:hover {
    filter: brightness(1.08);
}

.net-admin-title-bar-action-secundaria {
    background: transparent;
    color: var(--net-ink) !important;
    border: 1px solid var(--net-border);
}

.net-admin-title-bar-action-secundaria:hover {
    background: var(--net-surface-2);
}

/* Pantallas angostas: con dos acciones (ej. "Resumen de caja" +
   "Agregar Movimiento de caja") la fila única Volver/título/acciones no
   entra más -- se apila en 3 filas en vez de superponerse. */
@media (max-width: 640px) {
    div.breadcrumbs {
        grid-template-columns: 1fr;
        justify-items: center;
        text-align: center;
    }

    .breadcrumbs .net-admin-back-button {
        justify-self: center;
    }

    .breadcrumbs .net-admin-title-bar-actions {
        justify-self: stretch;
        width: 100%;
        justify-content: center;
    }
}

/* El <h1> con el mismo título que ya inyecta Django admin/base.html
   (content_title) queda redundante ahora que el título grande y
   centrado vive en la tarjeta de arriba. Las vistas con reportes
   propios ya vacían este bloque (content_title vacío), así que ocultar
   el h1 acá no les afecta. */
#content > h1 {
    display: none;
}

/* Changelists (todas, no solo Cobros) -- Django flota #content-main a
   ancho completo cuando no hay #changelist-filter (sidebar sacado en todo
   el admin), lo que estira el listado edge-to-edge por debajo de la
   tarjeta del título. Se lo contiene con el mismo ancho/margen que el
   header y las migas de pan para que los bordes coincidan en cualquier
   pantalla. */
.change-list #content {
    padding: 0;
}

.change-list #content-main {
    float: none;
    width: var(--net-content-width);
    margin: 0 auto 24px;
}

/* Red de seguridad: si una tabla puntual (columnas muy anchas, texto
   largo sin wrap) termina siendo más ancha que el contenedor centrado,
   el scroll horizontal queda contenido en la tabla y no se lleva puesta
   toda la página. */
.change-list .results {
    overflow-x: auto;
}

/* Custom views del admin que NO son changelists pero quieren el mismo ancho
   centrado que el header/breadcrumb (ej. facturador). Es el mismo tratamiento
   que `.change-list #content-main` de arriba: se le saca el padding a #content
   (para que el min() se centre respecto del viewport, no de #content) y se
   centra el cuerpo con el mismo --net-content-width. Se activa solo con la
   clase `net-admin-page` en el <body>, así no toca ninguna otra pantalla. */
body.net-admin-page #content {
    padding: 0;
}

body.net-admin-page #content > .net-admin-page-body {
    width: var(--net-content-width);
    margin: 0 auto 24px;
}

/* Tarjetas de navegación — mismo componente "módulos operativos" que ya
   usa el dashboard de logística (.opsdash-module en
   static/logistica_paquetes/css/depositos.css: ícono + título +
   descripción + flechita), reutilizado acá para el panel administrativo.
   Se eligió sobre .opsdash-kpi (pensada para mostrar un número grande)
   porque estos accesos del panel administrativo son navegación, no
   métricas. Valores copiados 1:1 (no aproximados) de los computados en
   vivo de logistica_operaciones/panel.html el 2026-07-15 — colores
   hex/rgba literales tal cual depositos.css, no tokens --net-*, porque
   el propio componente original tampoco los usa y el pedido es paridad
   pixel a pixel, no una reinterpretación con la paleta de marca. Único
   ajuste intencional: se le saca el truncado a una línea (overflow
   hidden/nowrap/ellipsis) de strong/small, porque acá hay títulos más
   largos que en logística ("Pendientes a Cuenta Corriente" vs "WR /
   Paquetes") — los títulos cortos igual caben en los mismos 82px sin
   wrap ni espacio de más; los largos crecen a 2 líneas en vez de
   truncar, sin inflar el resto de las tarjetas. Extensión aprobada por
   Nacho, 2026-07-15: unificar el panel administrativo
   (dashboard/clientes/caja/cotizador) con el lenguaje visual de
   tarjetas que ya tienen logística y portal. */
.opsdash-modules {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: 10px;
    margin-bottom: 14px;
}

.opsdash-module {
    display: grid;
    grid-template-columns: 34px minmax(0, 1fr) auto;
    grid-template-areas: "mark copy arrow";
    gap: 10px;
    align-items: center;
    min-height: 82px;
    padding: 12px;
    border: 1px solid #d8e2ea;
    border-radius: 12px;
    background: #fbfdff;
    color: #0f2f44 !important;
    text-decoration: none !important;
    transition: background 0.14s ease, border-color 0.14s ease, box-shadow 0.14s ease, transform 0.14s ease;
    min-width: 0;
}

.opsdash-module:hover {
    border-color: rgba(11, 111, 136, 0.36);
    background: #f6fbfd;
    color: #0f2f44 !important;
    text-decoration: none !important;
    transform: translateY(-1px);
    box-shadow: 0 10px 22px rgba(15, 47, 68, 0.08);
}

.opsdash-module-mark {
    grid-area: mark;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    border: 1px solid rgba(11, 111, 136, 0.18);
    border-radius: 10px;
    background: rgba(11, 111, 136, 0.08);
    color: #0b6f88;
    font-size: 24px;
    font-weight: 950;
    line-height: 1;
    text-transform: uppercase;
}

.opsdash-module-copy {
    grid-area: copy;
    min-width: 0;
}

.opsdash-module-copy strong,
.opsdash-module-copy small {
    display: block;
}

.opsdash-module-copy strong {
    color: #0f2f44 !important;
    font-size: 15px;
    font-weight: 950;
    line-height: 1.15;
    text-decoration: none !important;
}

.opsdash-module-copy small {
    margin-top: 2px;
    color: #64748b !important;
    font-size: 12px;
    font-weight: 750;
    text-decoration: none !important;
}

.opsdash-module-arrow {
    grid-area: arrow;
    justify-self: end;
    color: #0b6f88;
    font-size: 22px;
    font-weight: 850;
    line-height: 1;
    opacity: 0.45;
    transition: opacity 0.14s ease, transform 0.14s ease;
}

.opsdash-module:hover .opsdash-module-arrow {
    opacity: 0.85;
    transform: translateX(2px);
}

.opsdash-module-warning .opsdash-module-mark {
    border-color: rgba(180, 83, 9, 0.24);
    background: rgba(180, 83, 9, 0.08);
    color: #b45309;
}

.opsdash-module-success .opsdash-module-mark {
    border-color: rgba(21, 128, 61, 0.24);
    background: rgba(21, 128, 61, 0.08);
    color: #15803d;
}

.opsdash-module-danger .opsdash-module-mark {
    border-color: rgba(15, 47, 68, 0.24);
    background: rgba(15, 47, 68, 0.08);
    color: #0f2f44;
}

/* Título de página — mismo componente .opsdash-header que ya usa
   logística (título chico + subtítulo + línea separadora + pill de
   fecha a la derecha), reutilizado acá en vez del cartel grande con
   logo duplicado que tenía antes el panel administrativo (el logo ya
   vive en el header persistente de arriba). Valores 1:1 de
   static/logistica_paquetes/css/depositos.css. Reemplazo aprobado por
   Nacho, 2026-07-15 (opción "igual que logística" de 3 alternativas
   mostradas). */
.opsdash-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 18px;
    margin-bottom: 12px;
    padding: 4px 2px 12px;
    border-bottom: 1px solid #d8e2ea;
}

.opsdash-header h1 {
    margin: 0;
    color: #0f2f44;
    font-size: 18px;
    font-weight: 950;
    line-height: 1.1;
    letter-spacing: 0.01em;
}

.opsdash-header p {
    margin: 4px 0 0;
    color: #64748b;
    font-size: 12px;
    font-weight: 800;
}

.opsdash-header aside {
    display: flex;
    align-items: center;
    gap: 8px;
    min-height: 32px;
    padding: 6px 10px;
    border: 1px solid #d8e2ea;
    border-radius: 999px;
    background: #fff;
    color: #64748b;
    font-size: 12px;
    font-weight: 850;
    white-space: nowrap;
}

.opsdash-header aside span {
    color: #64748b;
}

.opsdash-header aside small {
    color: #0f2f44;
    font-size: 12px;
    font-weight: 950;
}

/* Header/shell de pantalla — mismo componente que ya usa el módulo de
   logística (.net-shell-header/.net-topbar/.net-brand/.user-menu en
   static/logistica_paquetes/css/depositos.css), reutilizado acá para
   sacar pantallas del panel administrativo de adentro del shell del
   admin de Django. Valores tomados 1:1 de los estilos ya vigentes en
   logística (computados en vivo desde logistica_operaciones/panel.html,
   2026-07-15) para que se vea igual. Los botones y la lista de mensajes
   se namespacean como .net-shell-btn/.net-shell-messages (en vez de
   .btn/.messages) porque admin_custom.css se carga en ~20 pantallas del
   admin que ya podrían tener sus propias reglas .btn/.messages locales
   — nombres genéricos acá pisarían esas reglas sin querer. El resto
   de los nombres (net-brand, net-shell-header, etc.) ya son específicos
   y se reutilizan tal cual. Extensión aprobada por Nacho, 2026-07-15.

   .net-shell-body fija la misma familia tipográfica y el mismo color
   de fondo que ya usa logística (Inter, con la MISMA cadena de
   fallback y orden que depositos.css — no la de --net-font-body, que
   tiene otro orden de fallback y podía renderizar distinto si Inter
   no está instalado; y #f5f7fa, el mismo hex vigente en depositos.css,
   no var(--net-bg) que es #f5f7fc — 2 dígitos de diferencia en el
   canal azul, casi imperceptible pero no pixel-exacto). Sin este
   background la página queda transparente/blanca, exactamente del
   mismo blanco que .net-topbar, y el margen de .net-shell-header deja
   de notarse aunque exista geométricamente — esa fue la causa real
   del header "pegado a los bordes" que se veía antes acá. Se aplica
   solo vía clase en <body> de dashboard/_base.html, no en el selector
   body global, para no tocar el admin de Django clásico
   (changelists/formularios) que sigue usando su fondo nativo.

   margin:0 — sin este reset, el body se queda con el margin default
   del navegador (8px en Chrome/Safari), que se suma al margin:0 16px
   de .net-shell-header y corre el header 8px de más en cada eje,
   dejándolo 16px más angosto que en logística (que sí resetea
   body{margin:0} en depositos.css). Confirmado con
   getBoundingClientRect() comparando ambas pantallas a la misma
   resolución, 2026-07-15: sin el reset, header real 1352px de ancho
   en x=24/y=8; con logística, 1368px de ancho en x=16/y=0. */
.net-shell-body {
    margin: 0;
    background: #f5f7fa;
    font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Arial, sans-serif;
}

/* box-sizing:border-box — mismo reset universal `* {box-sizing:border-box}`
   que depositos.css aplica en logística. Sin esto, todo lo que tenga
   padding+border (net-shell-btn, net-user-pill, net-topbar, opsdash-module,
   etc.) mide más de lo declarado, porque el navegador suma padding/border
   POR FUERA del min-height/width en vez de incluirlos adentro. Encontrado
   comparando getBoundingClientRect() de "Admin" (net-shell-btn) entre
   panel y logística, 2026-07-15: mismo min-height:32px declarado, pero
   altura real 46px acá vs 32px en logística — 6px padding + 1px border
   por lado, sumados por fuera al no tener este reset. Scopeado a
   .net-shell-body para no tocar el admin clásico de Django. */
.net-shell-body,
.net-shell-body *,
.net-shell-body *::before,
.net-shell-body *::after {
    box-sizing: border-box;
}

.net-shell-header {
    width: var(--net-content-width);
    margin: 0 auto;
    padding: 16px 0 0;
}

.net-topbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    min-height: 54px;
    padding: 8px 12px;
    border: 1px solid rgba(217, 222, 229, 0.84);
    border-radius: 14px;
    background: var(--net-surface);
    box-shadow: 0 8px 22px rgba(15, 23, 42, 0.06);
}

.net-brand {
    display: flex;
    align-items: center;
    margin-right: 26px;
    color: var(--net-ink) !important;
    text-decoration: none !important;
}

.net-brand-logo {
    display: block;
    height: 36px;
    width: auto;
    max-width: 140px;
    object-fit: contain;
}

.net-main {
    width: var(--net-content-width);
    margin: 0 auto;
    padding: 18px 0 34px;
}

.user-menu {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
}

.net-user-pill {
    display: flex;
    align-items: center;
    padding: 5px 10px;
    border: 1px solid var(--net-border);
    border-radius: 999px;
    background: var(--net-surface-2);
    color: var(--net-muted);
    font-size: 12px;
    font-weight: 800;
}

.net-logout-form {
    display: block;
    margin: 0;
}

.net-shell-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    min-height: 32px;
    padding: 6px 10px;
    border: 1px solid var(--net-border);
    border-radius: 8px;
    background: var(--net-surface);
    color: var(--net-ink) !important;
    font-size: 12px;
    font-weight: 850;
    cursor: pointer;
    text-decoration: none !important;
}

.net-shell-btn:hover {
    background: var(--net-surface-2);
}

/* Variante "Salir": en logística, el botón de logout es un <button> y
   choca con el selector `button.btn` de depositos.css (specificity
   0,1,1), que le gana a `.btn-secondary`/`.btn-sm` (0,1,0) aunque
   aparezcan después en el archivo — el resultado real, hoy, es que
   "Salir" sale azul y más grande (38px) que "Admin"/"Ingresar" (32px,
   blanco). Es un artefacto de especificidad en el CSS original, no un
   diseño deliberado, pero el pedido es paridad pixel a pixel con lo
   que se ve hoy en logística, así que se replica tal cual con una
   variante explícita en vez de depender de ese mismo accidente de
   especificidad acá. Valores medidos en vivo, 2026-07-15. */
.net-shell-btn-primary {
    min-height: 38px;
    padding: 9px 14px;
    border-color: transparent;
    border-radius: 10px;
    background: var(--net-action);
    color: #ffffff !important;
    font-size: 14px;
    box-shadow: 0 7px 14px rgba(11, 111, 136, 0.14);
}

.net-shell-btn-primary:hover {
    background: var(--net-action-hover, #002c96);
    color: #ffffff !important;
}

.net-shell-messages {
    margin: 0 0 16px;
    padding: 0;
    list-style: none;
}

.net-shell-messages li {
    margin-bottom: 8px;
    padding: 11px 13px;
    border: 1px solid var(--net-border);
    border-radius: 10px;
    background: var(--net-surface);
    box-shadow: var(--net-shadow-sm);
}

.net-shell-messages .success {
    border-color: #bbf7d0;
    background: var(--net-ok-bg);
    color: var(--net-ok-text);
}

.net-shell-messages .warning {
    border-color: #fde68a;
    background: var(--net-warn-bg);
    color: var(--net-warn-text);
}

.net-shell-messages .error {
    border-color: #fecaca;
    background: var(--net-danger-bg);
    color: var(--net-danger-text);
}

/* Breakpoints de .net-shell-header/.net-main — mismo orden relativo que
   depositos.css (760 → 900 → 640, en ese orden de aparición) para que
   la cascada resuelva igual en anchos donde más de una condición está
   activa a la vez (ej. <640px activa las 3; la última en el archivo,
   640px, gana para las propiedades que comparten). Valores 1:1 medidos
   contra logística, 2026-07-15. */
@media (max-width: 760px) {
    .net-shell-header,
    .net-main {
        width: min(100% - 20px, 1320px);
    }

    .net-shell-header {
        padding-top: 10px;
    }

    .net-topbar {
        align-items: flex-start;
        padding: 10px;
    }

    .net-userbar {
        max-width: 44%;
    }
}

@media (max-width: 900px) {
    .net-shell-header,
    .net-main {
        width: min(100% - 24px, 1440px);
    }

    .net-topbar {
        gap: 10px;
    }

    .user-menu {
        gap: 6px;
    }

    .net-brand {
        margin-right: 12px;
    }
}

@media (max-width: 640px) {
    .net-shell-header,
    .net-main {
        width: min(100% - 16px, 1440px);
    }

    .net-topbar {
        align-items: stretch;
        flex-direction: column;
    }

    .user-menu {
        max-width: none;
        justify-content: flex-start;
    }
}

/* =====================================================
   Listado de Cobros (cuentas.Pago) -- cliente/responsable,
   chips de imputación / medio de pago, importe destacado.
   ===================================================== */

.model-pago .net-pago-medio-wrap {
    display: inline-flex;
    align-items: center;
    white-space: nowrap;
}

.model-pago .net-pago-chip {
    display: inline-flex;
    align-items: center;
    padding: 3px 10px;
    border-radius: 999px;
    font-size: 12px;
    white-space: nowrap;
}

/* Imputación: color por tipo, texto en peso normal (no negrita). Lo que
   no esté mapeado a un tipo específico (ver IMPUTACION_CHIP_CLASE en
   cuentas/admin.py) cae acá, en el gris neutro por defecto. */
.model-pago .net-pago-chip-imputacion {
    font-weight: 400;
    background: var(--net-cat-neutra-bg);
    color: var(--net-cat-neutra-text);
}

.model-pago .net-pago-chip-imputacion-cargas {
    background: var(--net-cat-1-bg);
    color: var(--net-cat-1-text);
}

/* OJO: este ámbar NO es un aviso y por eso NO usa --net-warn-*. Acá el par
   cat-1 / cat-2 distingue dos CATEGORÍAS de imputación (Cargas / Compras): una
   compra no es más urgente que una carga. Pintarlo de warning le metería una
   semántica que no tiene, y además dejaría al azul de al lado huérfano, porque
   los dos colores se eligieron juntos. Ver el bloque de categorías en
   design_tokens.css. */
.model-pago .net-pago-chip-imputacion-compras {
    background: var(--net-cat-2-bg);
    color: var(--net-cat-2-text);
}

.model-pago .net-pago-chip-medio {
    font-weight: 700;
    background: #eef1f4;
    color: #41505c;
}

.model-pago .net-pago-caja-tilde {
    display: inline-flex;
    margin-left: 6px;
    color: #1a9c5c;
    font-weight: 800;
    font-size: 13px;
}

.model-pago #result_list .field-importe_usd_formateado {
    text-align: right;
    font-weight: 800;
    font-size: 15px;
    color: var(--net-ink);
    white-space: nowrap;
}

.model-pago #result_list .field-cliente {
    font-weight: 500;
}

.model-pago #result_list th.column-importe_usd_formateado,
.model-pago #result_list th.column-importe_usd_formateado a {
    text-align: right;
}

.model-pago .net-pago-total-pantalla {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-left: auto;
    padding-left: 12px;
    font-size: 13px;
    color: var(--net-muted);
    white-space: nowrap;
}

.model-pago .net-pago-total-pantalla strong {
    color: var(--net-ink);
    font-size: 15px;
}

/* =====================================================
   Franja de buscador de Cobros -- busqueda + filtros
   desplegables + total en pantalla, todo en una fila,
   reemplaza el sidebar "FILTRAR" de fábrica.
   ===================================================== */

.model-pago .net-pago-toolbar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 16px;
}

.model-pago .net-pago-search-wrap {
    flex: 1 1 auto;
    min-width: 260px;
}

.model-pago .net-pago-search-wrap #toolbar {
    margin: 0;
    padding: 0;
    border: none;
    background: transparent;
}

.model-pago .net-pago-search-wrap #changelist-search > div {
    display: flex;
    align-items: center;
    gap: 8px;
}

.model-pago .net-pago-search-wrap #changelist-search label {
    display: none;
}

.model-pago .net-pago-search-field {
    position: relative;
    display: inline-flex;
    align-items: center;
}

.model-pago .net-pago-search-field #searchbar {
    padding-right: 26px;
}

.model-pago .net-pago-search-clear {
    display: none;
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    border: none;
    background: transparent;
    color: var(--net-muted);
    font-size: 13px;
    line-height: 1;
    cursor: pointer;
    padding: 2px 4px;
}

.model-pago .net-pago-search-clear:hover {
    color: var(--net-ink);
}

.model-pago .net-pago-search-field.net-pago-search-tiene-texto .net-pago-search-clear {
    display: inline-flex;
}

.model-pago .net-pago-filtros-dropdown {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}

.model-pago .net-pago-filtros-dropdown details {
    position: relative;
}

.model-pago .net-pago-filtros-dropdown summary {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    list-style: none;
    min-height: 32px;
    padding: 6px 12px;
    border: 1px solid var(--net-border);
    border-radius: 999px;
    background: var(--net-surface);
    color: var(--net-ink);
    font-size: 12px;
    font-weight: 700;
    cursor: pointer;
    white-space: nowrap;
}

.model-pago .net-pago-filtros-dropdown summary::-webkit-details-marker {
    display: none;
}

.model-pago .net-pago-filtros-dropdown summary::before {
    display: none;
}

.model-pago .net-pago-filtros-dropdown summary::after {
    content: "▾";
    font-size: 10px;
    opacity: 0.6;
}

.model-pago .net-pago-filtros-dropdown details[open] summary {
    background: var(--net-surface-2);
    border-color: var(--net-action, #1a4fd6);
}

.model-pago .net-pago-filtros-dropdown details > ul {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: 30;
    min-width: 200px;
    max-height: 320px;
    overflow-y: auto;
    margin: 0;
    padding: 6px;
    list-style: none;
    border: 1px solid var(--net-border);
    border-radius: 12px;
    background: var(--net-surface);
    box-shadow: 0 12px 28px rgba(15, 23, 42, 0.12);
}

.model-pago .net-pago-filtros-dropdown details > ul li {
    list-style: none;
}

.model-pago .net-pago-filtros-dropdown details > ul a {
    display: block;
    padding: 7px 10px;
    border-radius: 8px;
    color: var(--net-ink) !important;
    font-size: 13px;
    font-weight: 600;
    text-decoration: none !important;
    white-space: nowrap;
}

.model-pago .net-pago-filtros-dropdown details > ul a:hover,
.model-pago .net-pago-filtros-dropdown details > ul a:focus {
    background: var(--net-surface-2);
    outline: none;
}

.model-pago .net-pago-filtros-dropdown details > ul li.selected a {
    color: var(--net-action, #1a4fd6) !important;
    font-weight: 800;
}

.model-pago #result_list tr.net-pago-fecha-separador td {
    padding: 0;
    background: #E6F1FB;
    border-top: 1px solid var(--net-border);
    border-bottom: 1px solid var(--net-border);
    font-size: 12px;
    font-weight: 700;
    color: #003AC8;
}

.model-pago .net-pago-fecha-separador-inner {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 8px 12px;
}

.model-pago .net-pago-fecha-separador-dia {
    color: #003AC8;
    text-transform: capitalize;
}

.model-pago .net-pago-fecha-separador-subtotal {
    margin-left: auto;
    color: #003AC8;
}

/* Barra de acciones masivas (seleccionar / anular) -- solo aparece
   cuando hay filas tildadas (admin_pago_changelist.js). */
.model-pago .actions {
    display: none;
}

.model-pago .actions.net-pago-actions-visible {
    display: block;
}

/* =====================================================
   Listado de Movimientos de caja (caja.MovimientoCaja) --
   mismo tratamiento base que Cobros: toolbar con buscador + filtros
   desplegables + totales, agrupado por día, concepto/categoría/cuenta/
   importe en vez de las 11 columnas de fábrica.
   ===================================================== */

.model-movimientocaja .net-mov-concepto {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.model-movimientocaja .net-mov-concepto-origen {
    display: flex;
    align-items: center;
}

.model-movimientocaja .net-mov-concepto-sub {
    color: var(--net-muted);
    font-size: 11px;
    font-weight: 500;
}

.model-movimientocaja .net-mov-auto-tag,
.model-movimientocaja .net-mov-anulado-tag {
    display: inline-flex;
    align-items: center;
    margin-left: 6px;
    padding: 1px 7px;
    border-radius: 999px;
    background: var(--net-surface-2);
    color: var(--net-muted);
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

.model-movimientocaja .net-mov-anulado-tag {
    background: #fbe4e4;
    color: #a12b2b;
}

/* Movimiento anulado: se muestra tachado y apagado -- queda el rastro,
   pero se lee claramente que no cuenta. */
.model-movimientocaja .net-mov-concepto-anulado .net-mov-concepto-origen strong {
    text-decoration: line-through;
    color: var(--net-muted);
}

.model-movimientocaja .net-mov-importe-anulado {
    font-weight: 700;
    font-size: 15px;
    color: var(--net-muted);
    text-decoration: line-through;
}

.model-movimientocaja .net-mov-chip {
    display: inline-flex;
    align-items: center;
    padding: 3px 10px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 400;
    white-space: nowrap;
}

/* Mismo trío de categoría que Cobros y Cargas Courier, y acá se usan DOS de los
   tres: no hay una segunda categoría que distinguir. Ver design_tokens.css. */
.model-movimientocaja .net-mov-chip-categoria {
    background: var(--net-cat-neutra-bg);
    color: var(--net-cat-neutra-text);
}

.model-movimientocaja .net-mov-chip-categoria-cobranza {
    background: var(--net-cat-1-bg);
    color: var(--net-cat-1-text);
}

.model-movimientocaja #result_list .field-cuenta {
    color: var(--net-muted);
    font-size: 12px;
}

.model-movimientocaja #result_list .field-importe_coloreado {
    text-align: right;
    white-space: nowrap;
}

.model-movimientocaja #result_list th.column-importe_coloreado,
.model-movimientocaja #result_list th.column-importe_coloreado a {
    text-align: right;
}

.model-movimientocaja .net-mov-importe {
    font-weight: 800;
    font-size: 15px;
}

.model-movimientocaja .net-mov-importe-ingreso {
    color: #0E7A3D;
}

.model-movimientocaja .net-mov-importe-egreso {
    color: #C0212B;
}

/* Franja de buscador -- mismo patrón que Cobros (busqueda + filtros
   desplegables + bloque de totales), reemplaza el sidebar "FILTRAR" de
   fábrica. */
.model-movimientocaja .net-mov-toolbar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 16px;
}

.model-movimientocaja .net-mov-search-wrap {
    flex: 1 1 auto;
    min-width: 260px;
}

.model-movimientocaja .net-mov-search-wrap #toolbar {
    margin: 0;
    padding: 0;
    border: none;
    background: transparent;
}

.model-movimientocaja .net-mov-search-wrap #changelist-search > div {
    display: flex;
    align-items: center;
    gap: 8px;
}

.model-movimientocaja .net-mov-search-wrap #changelist-search label {
    display: none;
}

.model-movimientocaja .net-mov-search-field {
    position: relative;
    display: inline-flex;
    align-items: center;
}

.model-movimientocaja .net-mov-search-field #searchbar {
    padding-right: 26px;
}

.model-movimientocaja .net-mov-search-clear {
    display: none;
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    border: none;
    background: transparent;
    color: var(--net-muted);
    font-size: 13px;
    line-height: 1;
    cursor: pointer;
    padding: 2px 4px;
}

.model-movimientocaja .net-mov-search-clear:hover {
    color: var(--net-ink);
}

.model-movimientocaja .net-mov-search-field.net-mov-search-tiene-texto .net-mov-search-clear {
    display: inline-flex;
}

.model-movimientocaja .net-mov-filtros-dropdown {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}

.model-movimientocaja .net-mov-filtros-dropdown details {
    position: relative;
}

.model-movimientocaja .net-mov-filtros-dropdown summary {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    list-style: none;
    min-height: 32px;
    padding: 6px 12px;
    border: 1px solid var(--net-border);
    border-radius: 999px;
    background: var(--net-surface);
    color: var(--net-ink);
    font-size: 12px;
    font-weight: 700;
    cursor: pointer;
    white-space: nowrap;
}

.model-movimientocaja .net-mov-filtros-dropdown summary::-webkit-details-marker {
    display: none;
}

.model-movimientocaja .net-mov-filtros-dropdown summary::before {
    display: none;
}

.model-movimientocaja .net-mov-filtros-dropdown summary::after {
    content: "▾";
    font-size: 10px;
    opacity: 0.6;
}

.model-movimientocaja .net-mov-filtros-dropdown details[open] summary {
    background: var(--net-surface-2);
    border-color: var(--net-action, #1a4fd6);
}

.model-movimientocaja .net-mov-filtros-dropdown details > ul {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: 30;
    min-width: 200px;
    max-height: 320px;
    overflow-y: auto;
    margin: 0;
    padding: 6px;
    list-style: none;
    border: 1px solid var(--net-border);
    border-radius: 12px;
    background: var(--net-surface);
    box-shadow: 0 12px 28px rgba(15, 23, 42, 0.12);
}

.model-movimientocaja .net-mov-filtros-dropdown details > ul li {
    list-style: none;
}

.model-movimientocaja .net-mov-filtros-dropdown details > ul a {
    display: block;
    padding: 7px 10px;
    border-radius: 8px;
    color: var(--net-ink) !important;
    font-size: 13px;
    font-weight: 600;
    text-decoration: none !important;
    white-space: nowrap;
}

.model-movimientocaja .net-mov-filtros-dropdown details > ul a:hover,
.model-movimientocaja .net-mov-filtros-dropdown details > ul a:focus {
    background: var(--net-surface-2);
    outline: none;
}

.model-movimientocaja .net-mov-filtros-dropdown details > ul li.selected a {
    color: var(--net-action, #1a4fd6) !important;
    font-weight: 800;
}

/* Totales de pantalla -- partidos por moneda, nunca sumados entre sí. */
.model-movimientocaja .net-mov-totales-pantalla {
    display: flex;
    align-items: center;
    gap: 18px;
    margin-left: auto;
    flex-wrap: wrap;
}

.model-movimientocaja .net-mov-totales-moneda {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    white-space: nowrap;
}

.model-movimientocaja .net-mov-totales-etiqueta {
    color: var(--net-muted);
    font-weight: 700;
}

.model-movimientocaja .net-mov-totales-ingreso {
    color: #0E7A3D;
    font-weight: 800;
}

.model-movimientocaja .net-mov-totales-egreso {
    color: #C0212B;
    font-weight: 800;
}

/* Fila separadora por día -- mismo tinte de marca que Cobros. */
.model-movimientocaja #result_list tr.net-mov-fecha-separador td {
    padding: 0;
    background: #E6F1FB;
    border-top: 1px solid var(--net-border);
    border-bottom: 1px solid var(--net-border);
    font-size: 12px;
    font-weight: 700;
    color: #003AC8;
}

.model-movimientocaja .net-mov-fecha-separador-inner {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 8px 12px;
}

.model-movimientocaja .net-mov-fecha-separador-dia {
    color: #003AC8;
    text-transform: capitalize;
}

.model-movimientocaja .net-mov-fecha-separador-netos {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-left: auto;
}

.model-movimientocaja .net-mov-fecha-separador-neto {
    color: #003AC8;
    white-space: nowrap;
}

.model-movimientocaja .net-mov-fecha-separador-neto-negativo {
    color: #C0212B;
}

/* Barra de acciones masivas -- solo aparece cuando hay filas tildadas
   (admin_movimientocaja_changelist.js). */
.model-movimientocaja .actions {
    display: none;
}

.model-movimientocaja .actions.net-mov-actions-visible {
    display: block;
}

/* =====================================================
   Rediseño del form de alta/edición (patrón reusable).
   Aplicado por ahora al form de Movimiento de caja como
   implementación de referencia (scope :is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario)).
   Tarjeta centrada + labels arriba + 2 columnas + toggle de
   Tipo + secciones livianas + botones jerarquizados.
   ===================================================== */

.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) #content {
    padding: 0;
}

/* Cada fieldset pasa a ser una tarjeta lisa, centrada y de ancho cómodo:
   un solo borde gris parejo en los cuatro lados (sin acento azul arriba
   -- Django le pone un border-top de color al fieldset.module). */
.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) fieldset.module {
    width: min(100% - 32px, 760px);
    margin: 0 auto 20px;
    padding: 22px 26px;
    border: 1px solid var(--net-border);
    border-top: 1px solid var(--net-border);
    border-radius: 14px;
    background: var(--net-surface);
    box-shadow: 0 4px 12px rgba(15, 23, 42, 0.04);
}

/* Encabezado de sección: en Movimiento de caja hay una sola sección y su
   título es redundante con el de la página, así que se oculta. En Cobros
   hay varias secciones (Conversión a USD, Caja...), así que se muestran
   como títulos livianos dentro de la tarjeta (sin la barra azul a todo el
   ancho). */
.change-form.model-movimientocaja fieldset.module > h2 {
    display: none;
}

.change-form:is(.model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) fieldset.module > h2 {
    margin: 4px 0 12px;
    padding: 0 0 8px;
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--net-border);
    color: var(--net-ink);
    font-size: 14px;
    font-weight: 800;
    letter-spacing: 0.01em;
    text-transform: none;
}

/* La primera sección del form de Carga no tiene título (fecha/cliente/detalle
   van sin encabezado, como en Cobros). */
.change-form.model-carga fieldset.module.aligned:first-of-type > h2 {
    display: none;
}

.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) fieldset.module .description {
    margin: 0 0 14px;
    padding: 0;
    color: var(--net-muted);
    font-size: 12px;
}

/* Campos separados solo por espacio vertical: sin líneas horizontales
   (border-bottom) entre .form-row. */
.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .form-row {
    padding: 9px 0;
    border: none;
}

.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .form-row:first-child {
    padding-top: 0;
}

.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .form-row:last-child {
    padding-bottom: 0;
}

/* Labels arriba de cada campo. Se pisa el .form-row label / .aligned label
   del admin (que los flota a la izquierda con ancho fijo) con más
   especificidad (body + 2 clases + .form-row label). */
body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .form-row label,
body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .aligned label {
    float: none;
    display: block;
    width: auto;
    min-width: 0;
    margin: 0 0 5px;
    padding: 0;
    color: var(--net-ink);
    font-size: 13px;
    font-weight: 700;
    text-align: left;
    white-space: nowrap;
}

body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .form-row label:after,
body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .aligned label:after {
    content: "";
}

/* Estilo base de inputs, con box-sizing parejo. Los anchos son por campo
   (abajo): distinto ancho según lo que va en cada uno, ninguno a todo lo
   ancho de la tarjeta. */
body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .form-row input[type="text"],
body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .form-row input[type="number"],
body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .form-row input[type="date"],
body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .form-row select,
body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .form-row textarea {
    max-width: 100%;
    box-sizing: border-box;
}

/* Anchos diferenciados por campo. Fecha usa el AdminDateWidget, que es un
   <input type="text" class="vDateField"> (no type="date"). */
body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .field-fecha input {
    width: 150px;
    vertical-align: middle;
}

/* Fecha: el label arriba (Django lo mete en un .flex-container en fila,
   por eso quedaba al costado); el input y "Hoy | 📅" en una fila
   verticalmente centrada. El :not(.form-multiline) es clave: cuando Fecha
   comparte fila con Cliente, el .form-row lleva la clase field-fecha y este
   selector matcheaba TAMBIÉN el contenedor .form-multiline de dos columnas,
   forzándolo a display:block y apilando Fecha/Cliente. */
body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .field-fecha .flex-container:not(.form-multiline) {
    display: block;
}

body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .field-fecha label {
    float: none;
    display: block;
    margin: 0 0 5px;
}

body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .field-fecha p.date {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
}

body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .field-fecha .datetimeshortcuts {
    display: inline-flex;
    align-items: center;
    margin: 0;
}

body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .field-importe input {
    width: 180px;
}

body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .field-detalle input[type="text"] {
    width: 420px;
}

/* Origen / Categoría: cada uno ocupa el ancho de su columna (~340px). */
body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .form-row.field-origen.field-categoria select {
    width: 100%;
}

/* Observaciones ya no va en el form (se sacó); Detalle alcanza. */

/* Filas de dos columnas (Tipo|Moneda, Origen|Categoría): las columnas ya
   las arma Django con .flex-container.form-multiline; solo hay que ensanchar
   cada columna para que respire. */
body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .form-row .flex-container.form-multiline {
    display: flex;
    gap: 26px;
    align-items: flex-start;
}

body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .form-row .flex-container.form-multiline > div {
    flex: 1 1 220px;
    min-width: 0;
}

/* Cada .fieldBox del admin es un .flex-container (label + input en fila);
   se pasa a columna para que la etiqueta quede ARRIBA del campo, no al lado. */
body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .fieldBox {
    display: block;
    margin: 0;
}

/* Guías, secciones Cálculos y Auditoría: son RESULTADOS, no campos de carga.
   El fieldset lleva la clase gp-panel (puesta desde "classes" en el fieldset,
   que es el mecanismo del propio admin) y pasa a leerse como panel: tres por
   renglón, etiqueta chica arriba y valor destacado. Todo cuelga de
   .model-cargaprivada y de .gp-panel: ningún otro form del admin se entera. */
body.change-form:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) fieldset.gp-panel {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 12px 24px;
}

body.change-form:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) fieldset.gp-panel > h2,
body.change-form:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) fieldset.gp-panel > .description {
    grid-column: 1 / -1;
}

/* Cada dato es una celda del panel, no una fila del form: sin el padding
   vertical que el molde le da a los .form-row apilados. */
body.change-form:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) fieldset.gp-panel .form-row {
    padding: 0;
}

body.change-form:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) fieldset.gp-panel .form-row label {
    margin-bottom: 2px;
    color: var(--net-muted);
    font-size: 10px;
    font-weight: 800;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

body.change-form:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) fieldset.gp-panel .readonly {
    padding: 0;
    color: var(--net-ink);
    font-size: 15px;
    font-weight: 800;
    line-height: 1.3;
}

/* Los que NO son plata (tarifas y los x kg) van distintos de los importes:
   más chicos, en gris y sin el peso del dinero. El $ ya los diferencia, esto
   lo remata para que no se confundan de un vistazo.

   neto_x_kilo y amarillo_x_kg se sumaron después, cuando el Resumen Diario pasó
   al panel: son la misma clase de número que costo_x_kg -- las tres son por kilo
   -- y salían dos grandes y una gris, que es al revés de lo que uno espera. Los
   dos nombres sólo existen en esa ficha, así que no alcanzan a las otras. */
body.change-form:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) fieldset.gp-panel .form-row:is(.field-tarifa_configurada_readonly, .field-tarifa_calculo_readonly, .field-flete_x_kg_readonly, .field-eze_x_kg_readonly, .field-costo_x_kg_readonly, .field-neto_x_kilo_readonly, .field-amarillo_x_kg_readonly) .readonly {
    color: var(--net-muted);
    font-size: 13px;
    font-weight: 700;
}

/* Tipo de cálculo y Mes son etiquetas de texto, no números. */
body.change-form:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) fieldset.gp-panel .form-row:is(.field-tipo_calculo_readonly, .field-mes_readonly) .readonly {
    font-size: 13px;
    font-weight: 700;
}

/* En pantallas angostas el panel de tres no entra: pasa a dos. */
@media (max-width: 720px) {
    body.change-form:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) fieldset.gp-panel {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* Guías: etiqueta arriba en TODOS los campos del form. El molde lo resuelve
   campo por campo (.field-fecha, .field-origen...), pero acá la lista es larga
   y pareja, asi que va de una. Dos casos segun como arma Django la fila:
   - fila de un solo campo: .form-row > div > .flex-container (label + campo);
   - fila de dos columnas: cada columna es un .flex-container.fieldBox, que ya
     baja a bloque mas arriba, salvo Fecha, que tiene su propia regla en fila
     para dejar el "Hoy" al lado del input -- por eso se repite acá con mas
     especificidad. Scopeado solo a .model-cargaprivada: los otros modelos del
     :is() de arriba siguen igual. */
body.change-form:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .form-row > div > .flex-container,
body.change-form:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .form-row .flex-container.fieldBox {
    display: block;
}

/* Toggles segmentados de Tipo y Moneda. El admin envuelve cada RadioSelect
   en un .flex-container que le achica el ancho; se neutraliza para que el
   toggle tome el ancho de su contenido. */
.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) :is(.fieldBox.field-tipo, .fieldBox.field-tipo_movimiento) .flex-container,
.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .fieldBox.field-moneda .flex-container {
    display: block;
}

/* Los campos RadioSelect (Tipo, Moneda) los envuelve Django en <fieldset>
   con <legend> como etiqueta -- y el legend viene FLOTADO a la izquierda,
   por eso quedaba al costado del toggle con un hueco. Se desflota y se pone
   en bloque para que la etiqueta quede ARRIBA del toggle, pegada. (El
   selector correcto es .form-row legend: el legend está por encima del
   .fieldBox.field-tipo, no adentro.) */
body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .form-row fieldset {
    border: none;
    padding: 0;
    margin: 0;
    min-width: 0;
}

body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .form-row legend {
    float: none;
    display: block;
    width: auto;
    margin: 0 0 5px;
    padding: 0;
    color: var(--net-ink);
    font-size: 13px;
    font-weight: 700;
    white-space: nowrap;
}

/* La fila Tipo|Moneda: los dos fieldsets uno al lado del otro (dos
   columnas), cada uno con su legend arriba. */
body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .form-row.field-tipo.field-moneda .form-multiline {
    display: flex;
    flex-direction: row;
    gap: 40px;
    align-items: flex-start;
}

body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .form-row.field-tipo.field-moneda .form-multiline > fieldset {
    flex: 0 0 auto;
}

.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) :is(.field-tipo #id_tipo, .field-tipo_movimiento #id_tipo_movimiento),
.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .field-moneda #id_moneda {
    display: inline-flex;
    border: 1px solid var(--net-border);
    border-radius: 10px;
    overflow: hidden;
}

.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) :is(.field-tipo #id_tipo, .field-tipo_movimiento #id_tipo_movimiento) > div,
.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .field-moneda #id_moneda > div {
    flex: 0 0 auto;
    margin: 0;
}

.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) :is(.field-tipo #id_tipo, .field-tipo_movimiento #id_tipo_movimiento) > div + div label,
.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .field-moneda #id_moneda > div + div label {
    border-left: 1px solid var(--net-border);
}

.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) :is(.field-tipo #id_tipo, .field-tipo_movimiento #id_tipo_movimiento) label,
.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .field-moneda #id_moneda label {
    display: block;
    margin: 0;
    padding: 9px 26px;
    background: var(--net-surface);
    color: var(--net-muted);
    font-weight: 800;
    font-size: 13px;
    cursor: pointer;
}

.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) :is(.field-tipo #id_tipo, .field-tipo_movimiento #id_tipo_movimiento) input[type="radio"],
.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .field-moneda #id_moneda input[type="radio"] {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}

/* OJO con el NOMBRE del campo: las cajas lo llaman "tipo" y DG
   "tipo_movimiento", asi que las reglas aceptan los dos. Apuntando solo a
   #id_tipo el toggle no aparecia en DG y los radios salian sueltos.

   Tipo: Ingreso verde, Egreso rojo. Las dos cajas dicen lo mismo pero lo
   guardan distinto -- el backoffice usa INGRESO/EGRESO y Caja Gerencia
   ENTRADA/SALIDA, valores que ya estaban en la base y no se tocan -- asi que
   la regla acepta los dos pares. Es el mismo componente hecho un poco mas
   general, no una copia: si manana aparece una tercera caja, se suma su valor
   aca y nada mas. */
.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) :is(.field-tipo #id_tipo, .field-tipo_movimiento #id_tipo_movimiento) label:has(input[value="INGRESO"]:checked),
.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) :is(.field-tipo #id_tipo, .field-tipo_movimiento #id_tipo_movimiento) label:has(input[value="ENTRADA"]:checked) {
    background: #0E7A3D;
    color: #fff;
}

.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) :is(.field-tipo #id_tipo, .field-tipo_movimiento #id_tipo_movimiento) label:has(input[value="EGRESO"]:checked),
.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) :is(.field-tipo #id_tipo, .field-tipo_movimiento #id_tipo_movimiento) label:has(input[value="SALIDA"]:checked) {
    background: #C0212B;
    color: #fff;
}

/* Moneda: el seleccionado (Pesos o Dólares) en azul de marca. */
.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .field-moneda #id_moneda label:has(input:checked) {
    background: #003AC8;
    color: #fff;
}

/* Prefijo de moneda ($ / US$) dentro del box de Importe. */
.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .net-mov-importe-wrap {
    position: relative;
    display: inline-flex;
    align-items: center;
    width: 180px;
    max-width: 100%;
}

.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .net-mov-importe-prefijo {
    position: absolute;
    left: 10px;
    color: var(--net-muted);
    font-size: 13px;
    font-weight: 700;
    pointer-events: none;
}

.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .net-mov-importe-wrap input {
    width: 100%;
    /* padding-left lo fija el JS según el ancho real del prefijo ($ / US$)
       para que el número quede separado del símbolo en ambos casos; este
       valor es solo el fallback si el JS todavía no corrió. */
    padding-left: 40px;
}

/* Botones con jerarquía: Guardar primario, y agregar otro secundario,
   y seguir editando terciario. */
.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .submit-row {
    width: min(100% - 32px, 760px);
    margin: 0 auto;
    padding: 16px 0 0;
    background: transparent;
    border: none;
    box-shadow: none;
    display: flex;
    gap: 10px;
    align-items: center;
}

.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .submit-row input[type="submit"] {
    margin: 0;
    padding: 10px 18px;
    border-radius: 9px;
    font-weight: 700;
    text-transform: none;
    letter-spacing: 0;
    box-shadow: none;
}

.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .submit-row input[name="_save"] {
    background: var(--net-action, #1a4fd6);
    color: #fff;
    border: 1px solid transparent;
}

.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .submit-row input[name="_addanother"] {
    background: var(--net-surface);
    color: var(--net-ink);
    border: 1px solid var(--net-border);
}

/* "Guardar y continuar editando": botón secundario con borde visible (como
   "Guardar y agregar otro"), no texto subrayado. Se apaga un poco el color
   para mantener la jerarquía por debajo del primario. */
.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .submit-row input[name="_continue"] {
    background: var(--net-surface);
    color: var(--net-muted);
    border: 1px solid var(--net-border);
    text-decoration: none;
}

.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .submit-row .deletelink-box {
    margin-left: auto;
}

/* ---- Nuevo cobro (cuentas.Pago): saldos del cliente + iconos ---- */

/* Etiqueta siempre ARRIBA del box, también en filas de un solo campo
   (Imputación, Detalle, saldos, conversión), para que toda la columna
   izquierda arranque en la misma línea. El :not(.form-multiline) evita
   volver a romper las filas de dos columnas. */
body.change-form.model-pago .form-row .flex-container:not(.form-multiline):not(.field-ingresa_a_caja) {
    display: block;
}

/* Saldos de cuenta corriente, justo debajo de Cliente. */
.change-form.model-pago .field-cuenta_corriente_cliente > label {
    color: var(--net-muted);
    font-weight: 700;
}

.change-form.model-pago .pago-cuenta-corriente {
    max-width: 100%;
}

/* El estado textual ("Seleccione un cliente...") se saca: las tarjetas ya
   muestran "–" como estado vacío. */
.change-form.model-pago .pago-cuenta-corriente__estado {
    display: none;
}

.change-form.model-pago .pago-cuenta-corriente__grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 12px;
}

.change-form.model-pago .pago-cuenta-corriente__grid > div {
    border: 1px solid var(--net-border);
    border-radius: 10px;
    background: var(--net-surface-2);
    padding: 10px 12px;
}

.change-form.model-pago .pago-cuenta-corriente__grid strong {
    display: block;
    margin-bottom: 4px;
    color: var(--net-muted);
    font-size: 11px;
    font-weight: 700;
}

.change-form.model-pago .pago-cuenta-corriente__grid span {
    display: block;
    color: var(--net-ink);
    font-size: 16px;
    font-weight: 800;
}

@media (max-width: 720px) {
    .change-form.model-pago .pago-cuenta-corriente__grid {
        grid-template-columns: 1fr;
    }
}

/* Medio de pago + "Ingresa a caja": van pegados, no como dos columnas
   estiradas de un multiline (por eso el check quedaba flotando a la derecha).
   Se saca el estiramiento (flex:1) y se alinea todo a la izquierda; el check
   queda inmediatamente al lado del desplegable. */
.change-form.model-pago .form-row.field-medio_pago.field-ingresa_a_caja .flex-container.form-multiline {
    justify-content: flex-start;
    align-items: flex-end;
    gap: 16px;
}

.change-form.model-pago .form-row.field-medio_pago.field-ingresa_a_caja .flex-container.form-multiline > div {
    flex: 0 0 auto;
}

.change-form.model-pago .field-medio_pago select {
    width: 240px;
}

/* Columna izquierda pareja: Importe, Medio de pago e Imputación al mismo
   ancho y mismo borde izquierdo. (Importe pisa el 180px del bloque
   compartido; el prefijo de moneda va dentro del wrap, así que el ancho
   se fija sobre el wrap.) */
body.change-form.model-pago .field-importe input,
body.change-form.model-pago .net-mov-importe-wrap {
    width: 240px;
}

body.change-form.model-pago .field-imputacion select {
    width: 240px;
}

/* Detalle ocupa toda su columna (la derecha). */
body.change-form.model-pago .field-detalle input[type="text"] {
    width: 100%;
}

/* Grilla ÚNICA para TODAS las filas de dos columnas de datos (Fecha/Cliente,
   Importe/Moneda, Imputación/Detalle, Tipo de cambio/Importe USD). Misma
   grilla y mismo gutter en todas, para que el borde izquierdo de la columna 1
   y de la columna 2 caiga en el mismo eje en cada fila. Se usa grid (no flex)
   porque una de las columnas es un <fieldset> —Moneda— que el flex no
   estiraba igual y desalineaba la columna derecha. align-items:start deja los
   dos boxes arrancando en el mismo top. La fila Medio de pago/Ingresa a caja
   queda afuera a propósito: ese check va pegado al select, no en columna. */
body.change-form.model-pago .form-row.field-fecha.field-cliente .flex-container.form-multiline,
body.change-form.model-pago .form-row.field-importe.field-moneda .flex-container.form-multiline,
body.change-form.model-pago .form-row.field-imputacion.field-detalle .flex-container.form-multiline,
body.change-form.model-pago .form-row.field-tipo_cambio.field-importe_usd .flex-container.form-multiline {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 26px;
    align-items: start;
}

body.change-form.model-pago .form-row.field-fecha.field-cliente .flex-container.form-multiline > *,
body.change-form.model-pago .form-row.field-importe.field-moneda .flex-container.form-multiline > *,
body.change-form.model-pago .form-row.field-imputacion.field-detalle .flex-container.form-multiline > *,
body.change-form.model-pago .form-row.field-tipo_cambio.field-importe_usd .flex-container.form-multiline > * {
    min-width: 0;
    margin: 0;
}

/* Importe aplicado USD: resultado calculado con presencia. Box con prefijo
   "US$" y el valor destacado (solo lectura, lo completa el JS). */
body.change-form.model-pago .field-importe_usd .readonly {
    display: inline-flex;
    align-items: baseline;
    gap: 8px;
    width: 240px;
    box-sizing: border-box;
    padding: 9px 12px;
    border: 1px solid var(--net-border);
    border-radius: 8px;
    background: var(--net-surface-2);
    color: var(--net-ink);
    font-size: 14px;
    font-weight: 600;
    line-height: 1.2;
}

body.change-form.model-pago .field-importe_usd .readonly::before {
    content: "US$";
    font-size: 12px;
    font-weight: 700;
    color: var(--net-muted);
}

/* "Ingresa a caja": check chico. La etiqueta va a la derecha del check (no
   arriba) y la celda se alinea abajo, a la altura del select de Medio de pago. */
.change-form.model-pago .fieldBox.field-ingresa_a_caja {
    display: flex;
    align-items: center;
    gap: 8px;
    padding-bottom: 8px;
}

.change-form.model-pago .fieldBox.field-ingresa_a_caja input[type="checkbox"] {
    width: 16px;
    height: 16px;
    margin: 0;
    flex: 0 0 auto;
}

.change-form.model-pago .fieldBox.field-ingresa_a_caja label.vCheckboxLabel {
    margin: 0;
    color: var(--net-ink);
    font-weight: 600;
    text-transform: none;
    letter-spacing: 0;
}

/* Aviso suave "Cobro Cliente" ya registrado (no bloquea, solo sugiere). */
.change-form.model-movimientocaja .net-mov-aviso-cobro {
    margin: 6px 0 0;
    padding: 8px 12px;
    border-radius: 8px;
    border: 1px solid #ead48a;
    background: #fff8e1;
    color: #5d4200;
    font-size: 12px;
    max-width: 520px;
}

/* =====================================================
   Listado de Cargas Courier (operaciones.Carga) -- misma receta que
   Cobros / Movimientos de caja: toolbar con buscador + filtros
   desplegables + total en pantalla, agrupado por día (sin subtotal),
   Tipo como chip, Kilos en gris chico y Total USD destacado.
   ===================================================== */

.model-carga .net-carga-chip {
    display: inline-flex;
    align-items: center;
    padding: 3px 10px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 400;
    white-space: nowrap;
}

/* Tipo: color por tipo, texto en peso normal. Lo no mapeado (Saldo
   inicial) cae en el gris neutro por defecto. */
.model-carga .net-carga-chip-tipo {
    background: var(--net-cat-neutra-bg);
    color: var(--net-cat-neutra-text);
}

.model-carga .net-carga-chip-courier {
    background: var(--net-cat-1-bg);
    color: var(--net-cat-1-text);
}

/* OJO: mismo caso que el chip de imputación de Cobros. Este ámbar distingue el
   TIPO de carga (Courier / Compra), no avisa nada, así que no va con
   --net-warn-*. Ver el bloque de categorías en design_tokens.css. */
.model-carga .net-carga-chip-compra {
    background: var(--net-cat-2-bg);
    color: var(--net-cat-2-text);
}

.model-carga .net-carga-detalle-link {
    color: var(--net-action, #1a4fd6) !important;
    font-weight: 600;
    text-decoration: none !important;
}

.model-carga .net-carga-detalle-link:hover {
    text-decoration: underline !important;
}

.model-carga .net-carga-kilos {
    color: var(--net-muted);
    font-size: 12px;
    white-space: nowrap;
}

.model-carga .net-carga-kilos-vacio {
    opacity: 0.6;
}

.model-carga #result_list .field-cliente {
    font-weight: 500;
}

.model-carga #result_list .field-total_destacado {
    text-align: right;
    font-weight: 800;
    font-size: 15px;
    color: var(--net-ink);
    white-space: nowrap;
}

.model-carga #result_list th.column-total_destacado,
.model-carga #result_list th.column-total_destacado a {
    text-align: right;
}

.model-carga .net-carga-total-pantalla {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-left: auto;
    padding-left: 12px;
    font-size: 13px;
    color: var(--net-muted);
    white-space: nowrap;
}

.model-carga .net-carga-total-pantalla strong {
    color: var(--net-ink);
    font-size: 15px;
}

/* Franja de buscador -- busqueda + filtros desplegables + total en
   pantalla, en una fila, reemplaza el sidebar "FILTRAR" de fábrica. */
.model-carga .net-carga-toolbar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 16px;
}

.model-carga .net-carga-search-wrap {
    flex: 1 1 auto;
    min-width: 260px;
}

.model-carga .net-carga-search-wrap #toolbar {
    margin: 0;
    padding: 0;
    border: none;
    background: transparent;
}

.model-carga .net-carga-search-wrap #changelist-search > div {
    display: flex;
    align-items: center;
    gap: 8px;
}

.model-carga .net-carga-search-wrap #changelist-search label {
    display: none;
}

.model-carga .net-carga-search-field {
    position: relative;
    display: inline-flex;
    align-items: center;
}

.model-carga .net-carga-search-field #searchbar {
    padding-right: 26px;
}

.model-carga .net-carga-search-clear {
    display: none;
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    border: none;
    background: transparent;
    color: var(--net-muted);
    font-size: 13px;
    line-height: 1;
    cursor: pointer;
    padding: 2px 4px;
}

.model-carga .net-carga-search-clear:hover {
    color: var(--net-ink);
}

.model-carga .net-carga-search-field.net-carga-search-tiene-texto .net-carga-search-clear {
    display: inline-flex;
}

.model-carga .net-carga-filtros-dropdown {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}

.model-carga .net-carga-filtros-dropdown details {
    position: relative;
}

.model-carga .net-carga-filtros-dropdown summary {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    list-style: none;
    min-height: 32px;
    padding: 6px 12px;
    border: 1px solid var(--net-border);
    border-radius: 999px;
    background: var(--net-surface);
    color: var(--net-ink);
    font-size: 12px;
    font-weight: 700;
    cursor: pointer;
    white-space: nowrap;
}

.model-carga .net-carga-filtros-dropdown summary::-webkit-details-marker {
    display: none;
}

.model-carga .net-carga-filtros-dropdown summary::before {
    display: none;
}

.model-carga .net-carga-filtros-dropdown summary::after {
    content: "▾";
    font-size: 10px;
    opacity: 0.6;
}

.model-carga .net-carga-filtros-dropdown details[open] summary {
    background: var(--net-surface-2);
    border-color: var(--net-action, #1a4fd6);
}

.model-carga .net-carga-filtros-dropdown details > ul {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: 30;
    min-width: 200px;
    max-height: 320px;
    overflow-y: auto;
    margin: 0;
    padding: 6px;
    list-style: none;
    border: 1px solid var(--net-border);
    border-radius: 12px;
    background: var(--net-surface);
    box-shadow: 0 12px 28px rgba(15, 23, 42, 0.12);
}

.model-carga .net-carga-filtros-dropdown details > ul li {
    list-style: none;
}

.model-carga .net-carga-filtros-dropdown details > ul a {
    display: block;
    padding: 7px 10px;
    border-radius: 8px;
    color: var(--net-ink) !important;
    font-size: 13px;
    font-weight: 600;
    text-decoration: none !important;
    white-space: nowrap;
}

.model-carga .net-carga-filtros-dropdown details > ul a:hover,
.model-carga .net-carga-filtros-dropdown details > ul a:focus {
    background: var(--net-surface-2);
    outline: none;
}

.model-carga .net-carga-filtros-dropdown details > ul li.selected a {
    color: var(--net-action, #1a4fd6) !important;
    font-weight: 800;
}

.model-carga #result_list tr.net-carga-fecha-separador td {
    padding: 0;
    background: #E6F1FB;
    border-top: 1px solid var(--net-border);
    border-bottom: 1px solid var(--net-border);
    font-size: 12px;
    font-weight: 700;
    color: #003AC8;
}

.model-carga .net-carga-fecha-separador-inner {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 8px 12px;
}

.model-carga .net-carga-fecha-separador-dia {
    color: #003AC8;
    text-transform: capitalize;
}

/* =====================================================
   Form Agregar Carga Courier (operaciones.Carga) -- mismo patrón que
   Nuevo cobro / Movimiento de caja: tarjeta, labels arriba, dos columnas,
   secciones livianas. Acá: Fecha/Cliente y Kilos/Valor por kilo en fila,
   Detalle a todo el ancho, Total como box de resultado calculado.
   ===================================================== */

/* Etiqueta siempre ARRIBA del box, también en filas de un solo campo. */
body.change-form.model-carga .form-row .flex-container:not(.form-multiline) {
    display: block;
}

/* Grilla única para las filas de dos columnas. */
body.change-form.model-carga .form-row.field-fecha.field-cliente .flex-container.form-multiline,
body.change-form.model-carga .form-row.field-kilos.field-valor_kg .flex-container.form-multiline {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 26px;
    align-items: start;
}

body.change-form.model-carga .form-row.field-fecha.field-cliente .flex-container.form-multiline > *,
body.change-form.model-carga .form-row.field-kilos.field-valor_kg .flex-container.form-multiline > * {
    min-width: 0;
    margin: 0;
}

/* Detalle / Referencia a todo el ancho. */
body.change-form.model-carga .field-detalle input[type="text"] {
    width: 100%;
}

/* Kilos y Valor por kilo: mismo ancho (240px), borde izquierdo alineado. */
body.change-form.model-carga .field-kilos input,
body.change-form.model-carga .net-carga-kg-wrap,
body.change-form.model-carga .net-mov-importe-wrap {
    width: 240px;
}

/* Sufijo "kg" dentro del box de Kilos, a la derecha del número. */
body.change-form.model-carga .net-carga-kg-wrap {
    position: relative;
    display: inline-flex;
    align-items: center;
    max-width: 100%;
}

body.change-form.model-carga .net-carga-kg-wrap input {
    width: 100%;
    padding-right: 36px;
}

body.change-form.model-carga .net-carga-kg-sufijo {
    position: absolute;
    right: 12px;
    color: var(--net-muted);
    font-weight: 700;
    font-size: 13px;
    pointer-events: none;
}

/* Checkbox "Amarillo" al lado del Valor por kilo (elige la tarifa a
   pre-cargar; no se guarda en la Carga). */
body.change-form.model-carga .net-carga-amarillo {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin: 8px 0 0;
    color: var(--net-ink);
    font-weight: 600;
    font-size: 13px;
    cursor: pointer;
}

body.change-form.model-carga .net-carga-amarillo input[type="checkbox"] {
    width: 16px;
    height: 16px;
    margin: 0;
    accent-color: #C79A00;
}

/* Total USD: resultado calculado con presencia (US$ + valor destacado),
   de solo lectura. Lo completa el JS en vivo (kilos x valor por kilo). */
body.change-form.model-carga .field-total .readonly {
    display: inline-flex;
    align-items: baseline;
    gap: 8px;
    width: 240px;
    box-sizing: border-box;
    padding: 9px 12px;
    border: 1px solid var(--net-border);
    border-radius: 8px;
    background: var(--net-surface-2);
    color: var(--net-ink);
    font-size: 14px;
    font-weight: 600;
    line-height: 1.2;
}

body.change-form.model-carga .field-total .readonly::before {
    content: "US$";
    font-size: 12px;
    font-weight: 700;
    color: var(--net-muted);
}

/* =====================================================
   Listado de Clientes (clientes.Cliente) -- misma receta que Cobros /
   Caja / Cargas: franja de buscador + filtros como pills, sin el sidebar
   FILTRAR, barra de acciones contextual. Sin agrupado ni totales.
   ===================================================== */

.model-cliente .net-cliente-toolbar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 16px;
}

.model-cliente .net-cliente-search-wrap {
    flex: 1 1 auto;
    min-width: 260px;
}

.model-cliente .net-cliente-search-wrap #toolbar {
    margin: 0;
    padding: 0;
    border: none;
    background: transparent;
}

.model-cliente .net-cliente-search-wrap #changelist-search > div {
    display: flex;
    align-items: center;
    gap: 8px;
}

.model-cliente .net-cliente-search-wrap #changelist-search label {
    display: none;
}

.model-cliente .net-cliente-search-field {
    position: relative;
    display: inline-flex;
    align-items: center;
}

.model-cliente .net-cliente-search-field #searchbar {
    padding-right: 26px;
}

.model-cliente .net-cliente-search-clear {
    display: none;
    position: absolute;
    right: 6px;
    top: 50%;
    transform: translateY(-50%);
    border: none;
    background: transparent;
    color: var(--net-muted);
    font-size: 13px;
    line-height: 1;
    cursor: pointer;
    padding: 2px 4px;
}

.model-cliente .net-cliente-search-clear:hover {
    color: var(--net-ink);
}

.model-cliente .net-cliente-search-field.net-cliente-search-tiene-texto .net-cliente-search-clear {
    display: inline-flex;
}

.model-cliente .net-cliente-filtros-dropdown {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}

.model-cliente .net-cliente-filtros-dropdown details {
    position: relative;
}

.model-cliente .net-cliente-filtros-dropdown summary {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    list-style: none;
    min-height: 32px;
    padding: 6px 12px;
    border: 1px solid var(--net-border);
    border-radius: 999px;
    background: var(--net-surface);
    color: var(--net-ink);
    font-size: 12px;
    font-weight: 700;
    cursor: pointer;
    white-space: nowrap;
}

.model-cliente .net-cliente-filtros-dropdown summary::-webkit-details-marker {
    display: none;
}

.model-cliente .net-cliente-filtros-dropdown summary::before {
    display: none;
}

.model-cliente .net-cliente-filtros-dropdown summary::after {
    content: "▾";
    font-size: 10px;
    opacity: 0.6;
}

.model-cliente .net-cliente-filtros-dropdown details[open] summary {
    background: var(--net-surface-2);
    border-color: var(--net-action, #1a4fd6);
}

.model-cliente .net-cliente-filtros-dropdown details > ul {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    z-index: 30;
    min-width: 180px;
    max-height: 320px;
    overflow-y: auto;
    margin: 0;
    padding: 6px;
    list-style: none;
    border: 1px solid var(--net-border);
    border-radius: 12px;
    background: var(--net-surface);
    box-shadow: 0 12px 28px rgba(15, 23, 42, 0.12);
}

.model-cliente .net-cliente-filtros-dropdown details > ul li {
    list-style: none;
}

.model-cliente .net-cliente-filtros-dropdown details > ul a {
    display: block;
    padding: 7px 10px;
    border-radius: 8px;
    color: var(--net-ink) !important;
    font-size: 13px;
    font-weight: 600;
    text-decoration: none !important;
    white-space: nowrap;
}

.model-cliente .net-cliente-filtros-dropdown details > ul a:hover,
.model-cliente .net-cliente-filtros-dropdown details > ul a:focus {
    background: var(--net-surface-2);
    outline: none;
}

.model-cliente .net-cliente-filtros-dropdown details > ul li.selected a {
    color: var(--net-action, #1a4fd6) !important;
    font-weight: 800;
}

/* =====================================================
   Ficha de Cliente (clientes.Cliente) -- patrón de form compartido, con
   los datos principales en dos columnas (alineados con el alta web) y el
   valor por kilo amarillo diferenciado con acento ámbar.
   ===================================================== */

/* Etiqueta siempre ARRIBA del box, también en filas de un solo campo. */
body.change-form.model-cliente .form-row .flex-container:not(.form-multiline) {
    display: block;
}

/* La primera sección (datos principales) no lleva título. */
.change-form.model-cliente fieldset.module.aligned:first-of-type > h2 {
    display: none;
}

/* Grilla única para todas las filas de dos columnas. */
body.change-form.model-cliente .form-row .flex-container.form-multiline {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 26px;
    align-items: start;
}

body.change-form.model-cliente .form-row .flex-container.form-multiline > * {
    min-width: 0;
    margin: 0;
}

/* Campos de texto a todo el ancho de su columna. */
body.change-form.model-cliente .form-row input[type="text"],
body.change-form.model-cliente .form-row input[type="email"],
body.change-form.model-cliente .form-row select {
    width: 100%;
}

/* Valores por kilo: mismo ancho, con el prefijo US$ del patrón. */
body.change-form.model-cliente .net-mov-importe-wrap {
    width: 100%;
}

/* Valor por kilo amarillo: acento ámbar (puntito en la etiqueta + borde)
   para distinguirlo de la tarifa normal de un vistazo. */
body.change-form.model-cliente .fieldBox.field-valor_kg_amarillo > label {
    display: flex;
    align-items: center;
    gap: 7px;
}

body.change-form.model-cliente .fieldBox.field-valor_kg_amarillo > label::before {
    content: "";
    width: 9px;
    height: 9px;
    border-radius: 50%;
    flex: 0 0 auto;
    background: #C79A00;
}

/* Ojo: la .form-row lleva las clases de los DOS campos, así que el acento
   se scopea al .fieldBox (la celda) para no pintar también el normal. */
body.change-form.model-cliente .fieldBox.field-valor_kg_amarillo input {
    border-color: #E3B341;
    background: #FFFDF5;
}

body.change-form.model-cliente .fieldBox.field-valor_kg_amarillo input:focus {
    border-color: #C79A00;
    outline-color: #C79A00;
}

/* =====================================================
   Inlines dentro del patrón de form (Cargas / Cobros en la ficha de
   Cliente, y cualquier otro inline de estos modelos).
   ===================================================== */

/* El patrón de tarjeta se aplicaba al fieldset.module INTERNO del inline,
   dejando su wrapper (.inline-related, que Django marca position:relative)
   a todo el ancho arrancando en x=0. Como Django posiciona el nombre del
   objeto de cada fila con `td.original p { position:absolute; left:0 }`,
   ese texto se anclaba al borde de la página y colgaba suelto a la
   izquierda, fuera de la tarjeta. La tarjeta pasa a ser el .inline-group
   (el wrapper), y el fieldset de adentro se neutraliza. */
.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .inline-group {
    width: min(100% - 32px, 760px);
    margin: 0 auto 20px;
    padding: 22px 26px;
    border: 1px solid var(--net-border);
    border-radius: 14px;
    background: var(--net-surface);
    box-shadow: 0 4px 12px rgba(15, 23, 42, 0.04);
    /* Las tablas de inline tienen varias columnas: que scrollee la tabla y
       no se lleve puesto el ancho de la página. */
    overflow-x: auto;
}

.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .inline-group fieldset.module {
    width: auto;
    margin: 0;
    padding: 0;
    border: none;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
}

/* Los <tr class="form-row"> de los inlines tabulares no son filas del form
   principal: no les corresponde el espaciado ni el label en bloque. */
.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .inline-group .form-row {
    padding: 0;
}

body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .inline-group .form-row label,
body.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) .inline-group td label {
    display: inline;
    margin: 0;
    font-weight: inherit;
}

/* Subtítulo que Django agrega en la vista de edición (el __str__ del
   objeto). Con el #content sin padding del patrón quedaba pegado al borde
   izquierdo; se alinea con la tarjeta. */
.change-form:is(.model-movimientocaja, .model-pago, .model-carga, .model-cliente, .model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario) #content > h2 {
    width: min(100% - 32px, 760px);
    margin: 0 auto 12px;
    color: var(--net-muted);
    font-size: 14px;
    font-weight: 700;
}

/* =====================================================
   Listado de Órdenes de compra (operaciones.OrdenCompraCliente) -- misma
   receta que Cobros / Caja / Cargas / Clientes: franja de buscador con
   filtros de Cliente y Estado, sin sidebar, barra de acciones contextual.
   Acá: estado operativo como chip de color con barrita de progreso,
   total destacado y Solicitado por en gris chico.
   ===================================================== */

.model-ordencompracliente .net-oc-toolbar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 16px;
}

.model-ordencompracliente .net-oc-toolbar-form {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    width: 100%;
}

.model-ordencompracliente .net-oc-search-field {
    flex: 1 1 260px;
    display: inline-flex;
    align-items: center;
    min-width: 220px;
}

.model-ordencompracliente .net-oc-search-field #searchbar {
    width: 100%;
}

.model-ordencompracliente .net-oc-toolbar select {
    min-height: 32px;
    min-width: 180px;
}

.model-ordencompracliente .net-oc-btn-buscar,
.model-ordencompracliente .net-oc-btn-limpiar {
    display: inline-flex;
    align-items: center;
    height: 32px;
    padding: 0 14px;
    border-radius: 8px;
    border: 1px solid var(--net-border);
    background: #fff;
    color: var(--net-ink);
    font-size: 13px;
    line-height: 1;
    text-decoration: none;
    cursor: pointer;
}

.model-ordencompracliente .net-oc-btn-buscar {
    border-color: var(--net-ink);
    background: var(--net-ink);
    color: #fff;
}

.model-ordencompracliente .net-oc-btn-limpiar:hover {
    border-color: var(--net-ink);
}

/* Estado operativo: chip de color + barrita de progreso debajo. Gris
   pendiente, azul en curso (tránsito / parcial Miami / parcial Bs As),
   ámbar parcial entregada, verde entregada completa, rojo cancelada. */
.model-ordencompracliente .net-oc-chip {
    display: inline-flex;
    align-items: center;
    padding: 3px 10px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 400;
    white-space: nowrap;
}

.model-ordencompracliente .net-oc-chip-pendiente {
    background: var(--net-neutral-bg);
    color: var(--net-neutral-text);
}

.model-ordencompracliente .net-oc-chip-curso {
    background: var(--net-info-bg);
    color: var(--net-info-text);
}

/* La escala de estados sale de los tokens semánticos donde hay uno: parcial es
   el aviso, entregada el ok y cancelada el peligro. "pendiente" y "curso" siguen
   con su literal porque todavía no tienen token equivalente (el azul de curso NO
   es --net-info, es otro). Los mismos pares están espejados en
   net_sistema/colores.py, que es lo que usa el documento imprimible y el mail. */
.model-ordencompracliente .net-oc-chip-parcial {
    background: var(--net-warn-bg);
    color: var(--net-warn-text);
}

.model-ordencompracliente .net-oc-chip-entregada {
    background: var(--net-ok-bg);
    color: var(--net-ok-text);
}

.model-ordencompracliente .net-oc-chip-cancelada {
    background: var(--net-danger-bg);
    color: var(--net-danger-text);
}

.model-ordencompracliente .net-oc-progreso {
    display: block;
    margin-top: 6px;
    max-width: 160px;
}

.model-ordencompracliente .net-oc-progreso-barra {
    display: block;
    height: 4px;
    border-radius: 999px;
    background: #E7E9EF;
    overflow: hidden;
}

.model-ordencompracliente .net-oc-progreso-relleno {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: #5F5E5A;
}

.model-ordencompracliente .net-oc-progreso-relleno.net-oc-chip-curso {
    background: #0C447C;
}

.model-ordencompracliente .net-oc-progreso-relleno.net-oc-chip-parcial {
    background: #C77E0A;
}

.model-ordencompracliente .net-oc-progreso-relleno.net-oc-chip-entregada {
    background: var(--net-ok-text);
}

.model-ordencompracliente .net-oc-progreso-relleno.net-oc-chip-cancelada {
    background: var(--net-danger-text);
}

.model-ordencompracliente .net-oc-progreso-texto {
    display: block;
    margin-top: 4px;
    color: var(--net-muted);
    font-size: 11px;
    white-space: nowrap;
}

/* Ítems: solo el conteo, sin link (la columna Orden ya lleva a la OC). */
.model-ordencompracliente .net-oc-items {
    color: var(--net-ink);
    white-space: nowrap;
}

.model-ordencompracliente #result_list .field-cliente {
    font-weight: 500;
}

.model-ordencompracliente #result_list .field-total_destacado_admin {
    text-align: right;
}

.model-ordencompracliente #result_list th.column-total_destacado_admin,
.model-ordencompracliente #result_list th.column-total_destacado_admin a {
    text-align: right;
}

.model-ordencompracliente .net-oc-total {
    display: block;
    text-align: right;
    font-weight: 800;
    font-size: 15px;
    color: var(--net-ink);
    white-space: nowrap;
}

/* Solicitado por: gris chico y centrado, para despegarlo del total. */
.model-ordencompracliente .net-oc-solicitado {
    color: var(--net-muted);
    font-size: 12px;
    white-space: nowrap;
}

.model-ordencompracliente #result_list .field-solicitado_admin,
.model-ordencompracliente #result_list th.column-solicitado_admin,
.model-ordencompracliente #result_list th.column-solicitado_admin a {
    text-align: center;
}

/* PDF y Email: links planos (icono + texto) en el mismo renglón. */
.model-ordencompracliente .net-oc-acciones {
    display: inline-flex;
    align-items: center;
    gap: 14px;
}

.model-ordencompracliente .net-oc-email-link {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    color: var(--net-action, #1a4fd6) !important;
    font-weight: 600;
    text-decoration: none !important;
    white-space: nowrap;
}

.model-ordencompracliente .net-oc-email-link:hover {
    opacity: 0.75;
}

.model-ordencompracliente .net-oc-email-icono {
    flex: none;
    fill: currentColor;
}

.model-ordencompracliente .net-oc-pdf-link {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 0;
    background: none;
    color: var(--net-action, #1a4fd6) !important;
    font-weight: 600;
    text-decoration: none !important;
    white-space: nowrap;
}

.model-ordencompracliente .net-oc-pdf-link:hover {
    opacity: 0.75;
}

/* Hoja en el mismo azul del link, con el "PDF" calado en blanco. */
.model-ordencompracliente .net-oc-pdf-icono {
    flex: none;
}

.model-ordencompracliente .net-oc-pdf-icono path {
    fill: currentColor;
}

.model-ordencompracliente .net-oc-pdf-icono text {
    fill: #fff;
}

/* =====================================================
   Form de alta/edición de Orden de compra (operaciones.OrdenCompraCliente).
   Misma receta visual que Movimiento de caja / Nuevo cobro / Cargas /
   Clientes: tarjeta centrada, etiquetas arriba, secciones livianas,
   dos columnas sobre la grilla de Django (.form-multiline), y el ítem
   partido en tres bloques con caja de resultado calculada en vivo.

   Ojo: el patrón NO se enchufa vía el :is(...) compartido a propósito
   (ahí se filtraba a los inlines y rompía el layout). Las tarjetas del
   encabezado se limitan a los fieldset SIN clase net-oc-item-*; los ítems
   (StackedInline) se estilan aparte como fichas.
   ===================================================== */

.change-form.model-ordencompracliente #content {
    padding: 0;
}

/* Subtítulo que Django agrega al editar (el __str__ de la orden). Sin esto
   cuelga pegado al borde izquierdo, fuera de la tarjeta (mismo fix que la
   ficha de Clientes). Se alinea con las tarjetas y queda gris chico. */
.change-form.model-ordencompracliente #content > h2 {
    width: min(100% - 32px, 820px);
    margin: 0 auto 12px;
    color: var(--net-muted);
    font-size: 14px;
    font-weight: 700;
}

/* ---- Tarjetas del encabezado de la orden (no los ítems) ---- */
/* box-sizing: border-box es clave para que el ancho declarado sea el ancho
   REAL de la tarjeta. Sin esto el fieldset (content-box) mide 820 + padding +
   borde = 874, mientras la tarjeta del ítem mide 820 justos: quedaban
   desalineadas 27px por lado. */
.change-form.model-ordencompracliente fieldset.module:not([class*="net-oc-item"]) {
    box-sizing: border-box;
    width: min(100% - 32px, 820px);
    margin: 0 auto 20px;
    padding: 22px 26px;
    border: 1px solid var(--net-border);
    border-radius: 14px;
    background: var(--net-surface);
    box-shadow: 0 4px 12px rgba(15, 23, 42, 0.04);
}

.change-form.model-ordencompracliente fieldset.module:not([class*="net-oc-item"]) > h2 {
    margin: 4px 0 12px;
    padding: 0 0 8px;
    background: transparent;
    border: none;
    border-bottom: 1px solid var(--net-border);
    color: var(--net-ink);
    font-size: 14px;
    font-weight: 800;
    letter-spacing: 0.01em;
    text-transform: none;
}

.change-form.model-ordencompracliente fieldset.module:not([class*="net-oc-item"]) .description {
    margin: 0 0 14px;
    padding: 0;
    color: var(--net-muted);
    font-size: 12px;
}

/* ---- Etiquetas arriba + filas sin líneas (encabezado e ítems) ---- */
.change-form.model-ordencompracliente .form-row {
    padding: 9px 0;
    border: none;
}

body.change-form.model-ordencompracliente .form-row label,
body.change-form.model-ordencompracliente .aligned label {
    float: none;
    display: block;
    width: auto;
    min-width: 0;
    margin: 0 0 5px;
    padding: 0;
    color: var(--net-ink);
    font-size: 13px;
    font-weight: 700;
    text-align: left;
}

body.change-form.model-ordencompracliente .form-row label:after,
body.change-form.model-ordencompracliente .aligned label:after {
    content: "";
}

/* Cada .fieldBox del admin es label+input en fila; se pasa a columna para
   que la etiqueta quede arriba. */
body.change-form.model-ordencompracliente .fieldBox {
    display: block;
    margin: 0;
}

body.change-form.model-ordencompracliente .form-row input[type="text"],
body.change-form.model-ordencompracliente .form-row input[type="url"],
body.change-form.model-ordencompracliente .form-row input[type="number"],
body.change-form.model-ordencompracliente .form-row input[type="date"],
body.change-form.model-ordencompracliente .form-row select,
body.change-form.model-ordencompracliente .form-row textarea {
    max-width: 100%;
    box-sizing: border-box;
}

/* Dos columnas: grilla 1fr/1fr como el resto del patrón (Nuevo cobro /
   Cliente). Django ya arma .flex-container.form-multiline con los tuples
   del fieldset; acá se lo pasa a grilla pareja. */
body.change-form.model-ordencompracliente .form-row .flex-container.form-multiline {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 24px;
    align-items: start;
}

body.change-form.model-ordencompracliente .form-row .flex-container.form-multiline > * {
    min-width: 0;
    margin: 0;
}

/* Etiqueta ARRIBA también en las filas de un solo campo (Numero pedido,
   Tracking, Observaciones, Impuesto...): por defecto el admin las pone en
   fila (label a la izquierda). El :not(.form-multiline) no toca las de dos
   columnas. */
body.change-form.model-ordencompracliente .form-row .flex-container:not(.form-multiline) {
    display: block;
}

/* Casos especiales donde 1fr/1fr no equilibra: el link ocupa casi todo y
   "Abrir" va justo al lado; la cantidad es chica y la descripción llena. */
body.change-form.model-ordencompracliente .form-row.field-link_producto.field-abrir_producto_inline .flex-container.form-multiline {
    grid-template-columns: 1fr auto;
    align-items: end;
}

body.change-form.model-ordencompracliente .form-row.field-cantidad.field-descripcion .flex-container.form-multiline {
    grid-template-columns: 120px 1fr;
}

/* Importes en una sola fila de tres: Precio unitario | Flete | Impuesto %. */
body.change-form.model-ordencompracliente .form-row.field-valor_compra.field-flete.field-impuesto_porcentaje .flex-container.form-multiline {
    grid-template-columns: 1fr 1fr 1fr;
}

/* Tracking con su "Abrir ↗" al lado, igual que el link del producto. */
body.change-form.model-ordencompracliente .form-row.field-tracking.field-abrir_tracking_inline .flex-container.form-multiline {
    grid-template-columns: 1fr auto;
    align-items: end;
}

/* Checkbox "Aplica comisión": etiqueta al lado del tilde, no arriba. */
body.change-form.model-ordencompracliente .form-row.field-aplica_comision .flex-container,
body.change-form.model-ordencompracliente .fieldBox.field-aplica_comision .flex-container {
    display: flex;
    align-items: center;
    gap: 8px;
}

body.change-form.model-ordencompracliente .fieldBox.field-aplica_comision label,
body.change-form.model-ordencompracliente .form-row.field-aplica_comision label {
    margin: 0;
    font-weight: 600;
}

body.change-form.model-ordencompracliente .fieldBox.field-aplica_comision input[type="checkbox"] {
    width: auto;
    margin: 0;
}

/* El chip de estado (readonly) en la fila Cliente | Estado. */
.change-form.model-ordencompracliente .form-row.field-estado_derivado_admin .readonly {
    padding-top: 2px;
}

/* ---- El ítem: cada ficha es una tarjeta propia, al mismo nivel que Datos
   principales / Observaciones (sin una tarjeta "Ítems" que las envuelva: ese
   anidado hacía el "Ítems / Ítem 1"). El .inline-group es solo el envoltorio
   que las centra. ---- */
.change-form.model-ordencompracliente .inline-group {
    box-sizing: border-box;
    width: min(100% - 32px, 820px);
    margin: 0 auto;
    padding: 0;
    background: transparent;
    border: none;
    border-radius: 0;
    box-shadow: none;
}

/* El título "Ítems" del inline se saca: cada tarjeta ya dice "Ítem N". */
.change-form.model-ordencompracliente .inline-group > .module > h2.inline-heading {
    display: none;
}

/* Se neutraliza el fieldset interno del admin (borde/fondo/ancho): la tarjeta
   es el .inline-group. Así desaparece una de las "rayas grises". */
.change-form.model-ordencompracliente .inline-group > fieldset.module {
    width: auto;
    margin: 0;
    padding: 0;
    border: none;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
}

/* Cada ítem = una tarjeta, con el mismo ancho y el mismo padding interno que
   las demás (mismo box-sizing, mismo padding: si no, el contenido del ítem
   arranca más a la derecha). */
.change-form.model-ordencompracliente .inline-related {
    box-sizing: border-box;
    width: 100%;
    margin: 0 0 20px;
    padding: 22px 26px;
    border: 1px solid var(--net-border);
    border-radius: 14px;
    background: var(--net-surface);
    box-shadow: 0 4px 12px rgba(15, 23, 42, 0.04);
}

/* El admin le mete padding lateral al fieldset interno de cada ficha (en
   responsive.css, bajo max-width:767px): eso sangraba el contenido del ítem
   respecto de las otras tarjetas. La sangría la da la tarjeta, no el fieldset. */
.change-form.model-ordencompracliente .inline-related fieldset.module {
    padding-left: 0;
    padding-right: 0;
}

.change-form.model-ordencompracliente .inline-related.empty-form {
    display: none;
}

/* Cabecera de la ficha: "Ítem N" a la izquierda y "Eliminar" discreto a la
   derecha, en la misma línea. */
.change-form.model-ordencompracliente .inline-related > h3 {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin: -4px 0 10px;
    padding: 0 0 10px;
    border-bottom: 1px solid var(--net-border);
    background: transparent;
    text-transform: none;
    letter-spacing: 0;
}

.change-form.model-ordencompracliente .inline-related > h3 .net-oc-item-num {
    color: var(--net-ink);
    font-size: 13px;
    font-weight: 800;
}

/* "Eliminar" del ítem: chip chico y gris, no un texto suelto arriba a la
   derecha. */
.change-form.model-ordencompracliente .inline-related > h3 .net-oc-item-del {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    color: var(--net-muted);
    font-size: 12px;
    font-weight: 600;
}

.change-form.model-ordencompracliente .inline-related > h3 .net-oc-item-del label {
    margin: 0;
    color: var(--net-muted);
    font-weight: 600;
    cursor: pointer;
}

/* Los tres bloques dentro de la ficha: subsecciones livianas, sin borde
   ni fondo, con un título chico. */
.change-form.model-ordencompracliente fieldset.net-oc-item-bloque {
    margin: 0 0 6px;
    padding: 12px 0 6px;
    border: none;
    border-top: 1px solid var(--net-border);
    background: transparent;
}

.change-form.model-ordencompracliente fieldset.net-oc-item-cabecera {
    margin: 0;
    padding: 0 0 4px;
    border: none;
    background: transparent;
}

/* El primer bloque de la tarjeta no lleva línea arriba: ya está la de la
   cabecera "Ítem N" (si no, quedan dos rayas pegadas). */
.change-form.model-ordencompracliente .inline-related fieldset.net-oc-item-bloque:first-of-type {
    border-top: none;
    padding-top: 4px;
}

/* En Django 5.x el título del fieldset del inline es <h4 class="fieldset-heading">
   (las tarjetas de la orden usan <h2 class="fieldset-heading">). */
.change-form.model-ordencompracliente fieldset.net-oc-item-bloque > .fieldset-heading {
    margin: 0 0 6px;
    padding: 0;
    background: transparent;
    border: none;
    color: var(--net-muted);
    font-size: 12px;
    font-weight: 800;
    letter-spacing: 0.01em;
    text-transform: none;
}

/* "Abrir" como link chico pegado al campo del link, sin etiqueta ni caja
   propia: la celda del readonly se alinea con el input. */
body.change-form.model-ordencompracliente .fieldBox.field-abrir_producto_inline label,
body.change-form.model-ordencompracliente .fieldBox.field-abrir_tracking_inline label {
    display: none;
}

.change-form.model-ordencompracliente .form-multiline > .fieldBox.field-abrir_producto_inline,
.change-form.model-ordencompracliente .form-multiline > .fieldBox.field-abrir_tracking_inline {
    align-self: center;
    padding-bottom: 0;
}

.change-form.model-ordencompracliente .field-abrir_producto_inline .readonly,
.change-form.model-ordencompracliente .field-abrir_tracking_inline .readonly {
    padding: 0;
}

.change-form.model-ordencompracliente .net-oc-abrir {
    color: var(--net-action, #1a4fd6);
    font-size: 12px;
    font-weight: 600;
    text-decoration: none;
    white-space: nowrap;
}

.change-form.model-ordencompracliente .net-oc-abrir:hover {
    text-decoration: underline;
}

/* Anchos cómodos para los porcentajes y montos del ítem. */
.change-form.model-ordencompracliente .field-impuesto_porcentaje input,
.change-form.model-ordencompracliente .field-comision_porcentaje input,
.change-form.model-ordencompracliente .field-valor_compra input,
.change-form.model-ordencompracliente .field-flete input {
    width: 140px;
}

/* ---- Caja de resultado del ítem (calculada en vivo) ---- */
/* Caja de resultado: recuadro (fondo + borde redondeado) al mismo ancho que
   los inputs de arriba. box-sizing: border-box es lo que hace que el borde
   EXTERIOR quede en 337→1103 (igual que "Número de pedido") aunque adentro
   tenga padding: sin esto, width:100% + padding + borde daba 804px y la caja
   se pasaba a la derecha. El sangrado interno del contenido es esperable. */
.change-form.model-ordencompracliente .net-oc-resultado {
    box-sizing: border-box;
    width: 100%;
    margin-top: 10px;
    padding: 14px 18px;
    border: 1px solid var(--net-border);
    border-radius: 10px;
    background: var(--net-surface-muted, #F7F8FA);
}

.change-form.model-ordencompracliente .net-oc-resultado-fila {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    padding: 3px 0;
}

.change-form.model-ordencompracliente .net-oc-resultado-etiqueta {
    color: var(--net-muted);
    font-size: 12px;
}

.change-form.model-ordencompracliente .net-oc-resultado-valor {
    color: var(--net-ink);
    font-variant-numeric: tabular-nums;
    font-size: 13px;
}

.change-form.model-ordencompracliente .net-oc-resultado-total {
    margin-top: 4px;
    padding-top: 8px;
    border-top: 1px solid var(--net-border);
}

.change-form.model-ordencompracliente .net-oc-resultado-total .net-oc-resultado-etiqueta {
    color: var(--net-ink);
    font-weight: 800;
    font-size: 13px;
}

.change-form.model-ordencompracliente .net-oc-resultado-total .net-oc-resultado-valor {
    font-weight: 800;
    font-size: 15px;
}

/* ---- Resumen de importes de la orden (calculado en vivo) ---- */

/* Etiquetas redundantes: la caja de resultado y el resumen ya se explican
   solas. (La label del readonly no es hija directa del .form-row: va dentro
   del .flex-container, por eso el selector es descendiente.) */
.change-form.model-ordencompracliente .form-row.field-resumen_importes_oc label,
.change-form.model-ordencompracliente .form-row.field-resultado_item_admin label {
    display: none;
}

.change-form.model-ordencompracliente .net-oc-resumen {
    width: 100%;
}

/* Todos los valores del resumen con el mismo color (Unidades totales salía
   distinto por ser un número suelto dentro del .readonly). */
.change-form.model-ordencompracliente .net-oc-resumen .net-oc-resumen-valor {
    color: var(--net-ink);
}

.change-form.model-ordencompracliente .net-oc-resumen-fila {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 20px;
    padding: 5px 0;
}

.change-form.model-ordencompracliente .net-oc-resumen-fila + .net-oc-resumen-fila {
    border-top: 1px solid var(--net-border);
}

.change-form.model-ordencompracliente .net-oc-resumen-etiqueta {
    color: var(--net-muted);
    font-size: 13px;
}

.change-form.model-ordencompracliente .net-oc-resumen-valor {
    color: var(--net-ink);
    font-variant-numeric: tabular-nums;
    font-size: 14px;
}

.change-form.model-ordencompracliente .net-oc-resumen-total {
    margin-top: 4px;
}

.change-form.model-ordencompracliente .net-oc-resumen-total .net-oc-resumen-etiqueta {
    color: var(--net-ink);
    font-weight: 800;
    font-size: 14px;
}

.change-form.model-ordencompracliente .net-oc-resumen-total .net-oc-resumen-valor {
    font-weight: 800;
    font-size: 17px;
}

/* ---- Segunda pasada: parejo con Nuevo cobro / Movimiento de caja ---- */

/* El autocomplete de Cliente (select2) que llene su columna. */
.change-form.model-ordencompracliente .field-cliente .select2,
.change-form.model-ordencompracliente .field-cliente .select2-selection {
    width: 100% !important;
}

/* Fuera los iconos del related-widget (lápiz / + / ✕ / ojo) de Cliente y
   Depósito de destino: no se usan desde el form de la orden. */
.change-form.model-ordencompracliente .related-widget-wrapper-link {
    display: none !important;
}

/* Fuera los textos de ayuda debajo de los campos: el patrón no los muestra. */
.change-form.model-ordencompracliente .form-row .help,
.change-form.model-ordencompracliente .form-row div.help,
.change-form.model-ordencompracliente .form-row .helptext {
    display: none;
}

/* Botones jerarquizados y alineados con la tarjeta (no pegados al borde
   izquierdo): Guardar primario azul, los otros con borde. Misma receta que
   el resto del patrón. */
.change-form.model-ordencompracliente .submit-row {
    width: min(100% - 32px, 820px);
    margin: 0 auto;
    padding: 16px 0 0;
    background: transparent;
    border: none;
    box-shadow: none;
    display: flex;
    gap: 10px;
    align-items: center;
}

.change-form.model-ordencompracliente .submit-row input[type="submit"] {
    margin: 0;
    padding: 10px 18px;
    border-radius: 9px;
    font-weight: 700;
    text-transform: none;
    letter-spacing: 0;
    box-shadow: none;
}

.change-form.model-ordencompracliente .submit-row input[name="_save"] {
    background: var(--net-action, #1a4fd6);
    color: #fff;
    border: 1px solid transparent;
}

.change-form.model-ordencompracliente .submit-row input[name="_addanother"],
.change-form.model-ordencompracliente .submit-row input[name="_continue"] {
    background: var(--net-surface);
    color: var(--net-ink);
    border: 1px solid var(--net-border);
}

.change-form.model-ordencompracliente .submit-row .deletelink-box {
    margin-left: auto;
}

/* "+ Agregar otro ítem": botón secundario (outline) con el ícono +, a tono
   con el resto, en vez de un link de texto plano. */
.change-form.model-ordencompracliente .add-row {
    border: none;
    background: transparent;
    padding: 0;
    margin: 0 0 20px;
}

.change-form.model-ordencompracliente .add-row a {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 14px;
    border: 1px solid var(--net-border);
    border-radius: 9px;
    background: var(--net-surface);
    color: var(--net-ink);
    font-weight: 700;
    text-decoration: none;
}

.change-form.model-ordencompracliente .add-row a::before {
    content: "+";
    font-size: 15px;
    font-weight: 800;
    line-height: 1;
}

.change-form.model-ordencompracliente .add-row a:hover {
    border-color: var(--net-ink);
}

/* Reordenar en pantalla: Datos principales, ítems, Resumen de importes y
   Observaciones al final (las notas se escriben al cerrar). Django siempre
   renderiza los fieldsets antes que los inlines, así que el orden real se
   arma acá con flex-order sobre el contenedor del form. */
.change-form.model-ordencompracliente #ordencompracliente_form > div {
    display: flex;
    flex-direction: column;
}

.change-form.model-ordencompracliente #ordencompracliente_form > div > .net-oc-fs-datos {
    order: 1;
}

.change-form.model-ordencompracliente #ordencompracliente_form > div > .inline-group {
    order: 2;
}

.change-form.model-ordencompracliente #ordencompracliente_form > div > .net-oc-fs-resumen {
    order: 3;
}

.change-form.model-ordencompracliente #ordencompracliente_form > div > .observaciones-orden-compra {
    order: 4;
}

.change-form.model-ordencompracliente #ordencompracliente_form > div > .submit-row {
    order: 5;
}

/* -----------------------------------------------------
   Generar prealerta: lo propio de esa pantalla.

   Es una vista custom, no un change form de un modelo, pero se le ponen a mano
   las clases `change-form model-ordencompracliente` en el <body> y el markup que
   genera Django (fieldset.module.aligned, .form-row, .flex-container, .fieldBox),
   así que TODO el patrón de arriba le aplica igual. Acá va sólo lo que el patrón
   no tiene, que son tres cosas.

   Va scopeado a .net-prealerta-*, o sea que no toca la ficha de la Orden de
   Compra aunque comparta las clases del body.
   ----------------------------------------------------- */

/* 1) Los avisos, en tres tonos. La pantalla los tenía con colores literales
      escritos a mano; acá salen de los tokens. Los tres tonos importan: "el
      paquete ya está recibido en el depósito" es una buena noticia y no puede
      salir en rojo como si algo hubiera fallado. */
.change-form.model-ordencompracliente .net-prealerta-aviso {
    margin: 0 0 14px;
    padding: 10px 12px;
    border-radius: 10px;
    font-size: 13px;
}

.change-form.model-ordencompracliente .net-prealerta-aviso-warn {
    border: 1px solid var(--net-warn-text);
    background: var(--net-warn-bg);
    color: var(--net-warn-text);
}

.change-form.model-ordencompracliente .net-prealerta-aviso-info {
    border: 1px solid var(--net-info-text);
    background: var(--net-info-bg);
    color: var(--net-info-text);
}

.change-form.model-ordencompracliente .net-prealerta-aviso-danger {
    border: 1px solid var(--net-danger-text);
    background: var(--net-danger-bg);
    color: var(--net-danger-text);
}

/* 2) La lista de ítems que se agrupan, con su total. No es un campo editable:
      es un cuadro de lectura dentro del form. */
.change-form.model-ordencompracliente .net-prealerta-items {
    box-sizing: border-box;
    width: 100%;
    border: 1px solid var(--net-border);
    border-radius: 4px;
    background: var(--net-surface);
    overflow: hidden;
}

.change-form.model-ordencompracliente .net-prealerta-item {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding: 9px 12px;
    border-bottom: 1px solid var(--net-border);
}

.change-form.model-ordencompracliente .net-prealerta-item:last-child {
    border-bottom: 0;
}

.change-form.model-ordencompracliente .net-prealerta-item-nombre {
    color: var(--net-text);
    font-size: 13px;
}

.change-form.model-ordencompracliente .net-prealerta-item-cuenta {
    color: var(--net-muted);
    font-size: 12px;
}

.change-form.model-ordencompracliente .net-prealerta-item-monto {
    font-weight: 800;
    white-space: nowrap;
}

.change-form.model-ordencompracliente .net-prealerta-item-total {
    border-top: 2px solid var(--net-ink);
    background: var(--net-surface-2);
    font-weight: 800;
}

/* 3) Los botones. Las reglas de arriba visten `input[type="submit"]` y colorean
      por `name="_save"`, y acá los botones son <button name="accion"> porque la
      vista lee valores de máquina ("crear", "vincular", "atar_wr") y un
      <input type="submit"> mandaría el texto visible. Se les da el mismo aspecto
      que a Guardar y a Guardar y agregar otro, que son el primario y el
      secundario de la ficha. */
.change-form.model-ordencompracliente .submit-row .net-prealerta-submit {
    margin: 0;
    padding: 10px 18px;
    border: 1px solid transparent;
    border-radius: 9px;
    background: var(--net-action);
    color: #ffffff;
    font-size: 13px;
    font-weight: 700;
    /* line-height 1 y no 1.2: los botones de la ficha son <input>, que renderiza
       la caja de texto a la altura de la fuente. Con 1.2 estos quedaban en 37,6px
       contra los 35px de "Guardar" y se notaba en la misma fila. Medido. */
    line-height: 1;
    cursor: pointer;
}

.change-form.model-ordencompracliente .submit-row .net-prealerta-cancelar {
    display: inline-flex;
    align-items: center;
    margin: 0;
    padding: 10px 18px;
    border: 1px solid var(--net-border);
    border-radius: 9px;
    background: var(--net-surface);
    color: var(--net-ink);
    font-size: 13px;
    font-weight: 700;
    line-height: 1;
}

/* El subrayado NO lo saca esta regla: lo saca el role="button" del <a> en el
   template, porque el :not() de base.css excluye a los [role="button"]. Ese
   selector mide (1,1,2) -- lleva un id adentro del :not() -- y éste mide (0,4,0):
   la especificidad compara IDS PRIMERO, así que cuatro clases pierden contra un
   id. Medido en pantalla: sin el role sale subrayado igual con esta regla puesta.
   Se deja porque es la que vale si algún día se saca el role. */
.change-form.model-ordencompracliente .submit-row .net-prealerta-cancelar {
    text-decoration: none;
}

/* =====================================================
   GUÍAS (gestion_privada.CargaPrivada) - changelist al molde de la casa.
   La franja de filtros (buscador + cliente + origen + Filtrar/Limpiar en una
   sola linea) reusa el componente .fact-filter-card / .fact-filter-form del
   facturador, que el template carga desde net_sistema/facturacion.css: mismo
   precedente que el reporte operativo. Ese archivo NO se toca -- lo unico que
   va aca son los ajustes propios de esta pantalla, scopeados a
   .model-cargaprivada para no alcanzar al facturador.
   La grilla del componente ya es 1.6fr 1fr 1fr auto, que es justo
   Buscar / Cliente / Origen / acciones: no hace falta redefinirla.
   ===================================================== */

:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list :is(.net-cargaprivada-filtros, .net-cajaprivada-filtros, .net-cajaab-filtros, .net-covediario-filtros) {
    margin-bottom: 18px;
}

/* "Limpiar filtro" es un <a> y "Filtrar" un <button>: sin esto no se ven igual.
   Dos motivos, los dos medidos en pantalla:
   - base.css subraya los <a> con una regla que lleva un id adentro del :not(),
     y le gana a .fact-btn; por eso el selector de aca pasa por #changelist,
     para superarla por especificidad en vez de a los golpes con !important.
   - el <a> queda en content-box (el <button> hereda border-box), asi que el
     min-height:38px del componente se le sumaba al padding y salia de 58px. */
:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list #changelist .fact-filter-actions .fact-btn {
    box-sizing: border-box;
    text-decoration: none;
}


/* ---- Tabla al mismo molde que la del reporte operativo (BEC) ----
   Los valores (padding, tamanos, tokens de color) son LOS MISMOS de
   .gp-reporte-operativo .gp-table en admin_privado_reportes.css; se copian en
   vez de compartir selector porque aca el markup es el #result_list que arma
   Django y esta pantalla no carga aquel archivo. Todo cuelga de
   .model-cargaprivada: ningun otro changelist del admin se entera.
   OJO: .results NO lleva overflow. La tabla tiene un encabezado flotante que
   clona carga_privada_admin.js, y un overflow distinto de visible en un
   ancestro lo romperia; por eso las esquinas se redondean en las celdas de los
   extremos y no recortando el contenedor. */
:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list .results {
    border: 1px solid var(--net-border, #d7e3e8);
    border-radius: 10px;
    background: var(--net-surface, #fff);
}

:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list #result_list {
    width: 100%;
    margin: 0;
    border-collapse: collapse;
}

:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list #result_list thead th {
    padding: 11px 12px;
    border-bottom: 1px solid var(--net-border, #d7e3e8);
    background: var(--net-surface-2, #f4f7f9);
    color: var(--net-muted, #607d8b);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    text-align: left;
}

/* Las esquinas de arriba acompanan el radio de la tarjeta. Se apoya en las
   clases de columna (column-<campo>) porque la primera celda real es la del
   checkbox, que esta oculta: un :first-child apuntaria a esa. */
:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list #result_list thead th.column-fecha {
    border-top-left-radius: 10px;
}

:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list #result_list thead th.column-costo_x_kg,
:is(.model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientoangel).change-list #result_list thead th.column-observaciones {
    border-top-right-radius: 10px;
}

:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list #result_list tbody td,
:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list #result_list tbody th {
    padding: 10px 12px;
    border-bottom: 1px solid #eef3f6;
    color: var(--net-ink, #123a52);
    font-size: 13px;
    font-weight: normal;
}

:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list #result_list tbody tr:last-child td,
:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list #result_list tbody tr:last-child th {
    border-bottom: 0;
}

:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list #result_list tbody tr:nth-child(even) {
    background: #fafcfd;
}

:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list #result_list tbody tr:hover {
    background: var(--net-surface-2, #f4f7f9);
}

/* Numeros a la derecha: las mismas columnas que en BEC (kilos y los montos). */
:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list #result_list th.column-kilos,
:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list #result_list td.field-kilos,
:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list #result_list th.column-cobrado_readonly,
:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list #result_list td.field-cobrado_readonly,
:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list #result_list th.column-estimado_readonly,
:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list #result_list td.field-estimado_readonly,
:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list #result_list th.column-costo_x_kg,
:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list #result_list td.field-costo_x_kg {
    text-align: right;
}

/* Caja Gerencia: lo unico que NO comparte con Guias. Las columnas de plata se
   llaman distinto (entrada / salida / saldo acumulado) y la franja tiene cinco
   celdas en vez de cuatro, asi que la grilla del componente hay que ajustarla.
   Todo lo demas -- tarjeta, encabezado, alto de fila, acciones apagadas, boton
   de la franja -- sale de los mismos bloques que Guias. */
.model-movimientocajaprivada.change-list #result_list th.column-entrada_display,
.model-movimientocajaprivada.change-list #result_list td.field-entrada_display,
.model-movimientocajaprivada.change-list #result_list th.column-salida_display,
.model-movimientocajaprivada.change-list #result_list td.field-salida_display,
.model-movimientocajaprivada.change-list #result_list th.column-saldo_acumulado_display,
.model-movimientocajaprivada.change-list #result_list td.field-saldo_acumulado_display {
    text-align: right;
}

/* Buscar / Tipo / Moneda / Desde / Hasta / acciones. */
.model-movimientocajaprivada.change-list .fact-filter-form {
    grid-template-columns: minmax(0, 1.4fr) repeat(4, minmax(0, 1fr)) auto;
}

/* Caja AB: mismas columnas de plata que Caja Gerencia salvo el nombre
   (ingreso / egreso / saldo acumulado), y una franja de cuatro celdas --
   Buscar / Tipo / Desde / Hasta -- porque acá no hay moneda: es una sola.
   Todo lo demás sale de los bloques compartidos de más arriba. */
.model-movimientoangel.change-list #result_list th.column-ingreso_display,
.model-movimientoangel.change-list #result_list td.field-ingreso_display,
.model-movimientoangel.change-list #result_list th.column-egreso_display,
.model-movimientoangel.change-list #result_list td.field-egreso_display,
.model-movimientoangel.change-list #result_list th.column-saldo_acumulado_display,
.model-movimientoangel.change-list #result_list td.field-saldo_acumulado_display {
    text-align: right;
}

.model-movimientoangel.change-list .fact-filter-form {
    grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr)) auto;
}

/* Resumen Diario: la fila es casi toda numérica, así que van todas a la derecha
   menos la fecha. La franja tiene las mismas cuatro celdas que Caja AB
   (Buscar / Estado / Desde / Hasta). Lo demás sale de los bloques compartidos. */
.model-covediario.change-list #result_list th:not(.column-fecha),
.model-covediario.change-list #result_list td:not(.field-fecha) {
    text-align: right;
}

.model-covediario.change-list .fact-filter-form {
    grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr)) auto;
}

/* Guías no usa acciones masivas: se oculta la barra "Acción / Ejecutar / N
   seleccionados" y la columna de checkboxes por fila (solo display, la lista
   queda limpia). */
:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list .actions {
    display: none;
}

:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list th.action-checkbox-column,
:is(.model-cargaprivada, .model-movimientocajaprivada, .model-conteocambioprivado, .model-movimientodg, .model-movimientoangel, .model-covediario).change-list td.action-checkbox {
    display: none;
}

/* Caja de Cambio: lo unico que NO comparte con las otras dos. Las columnas de
   cantidad y el total se llaman distinto, y los siete chips de arriba necesitan
   un numero mas chico para entrar parejos -- antes esto vivia en un <style>
   inline del template que pisaba .gp-cards fijando columnas, y era justo lo que
   dejaba los chips descolgados. */
.model-conteocambioprivado.change-list #result_list th.column-total_cambio_display,
.model-conteocambioprivado.change-list #result_list td.field-total_cambio_display,
.model-conteocambioprivado.change-list #result_list th[class*="column-cantidad_"],
.model-conteocambioprivado.change-list #result_list td[class*="field-cantidad_"] {
    text-align: right;
}

/* Siete chips en una linea, en una pantalla de notebook: el numero del molde
   (25px, 28px el destacado) hacia que "US$ 1.420,00" y "US$ 5.900,00" se
   partieran en dos renglones y esas dos tarjetas quedaran mas altas que el
   resto. Se achica el numero y se aprieta el padding; con esto el importe mas
   largo entra en una linea y los siete quedan del mismo alto. El total sigue
   destacado por su borde azul, no por ser mas grande. */
/* OJO con el scope: el template carga admin_privado_reportes.css DESPUES de
   este archivo, asi que a igual especificidad gana aquel. Sin el
   .model-conteocambioprivado adelante, .gp-cards span (25px) le ganaba a
   .gp-cambio-cards span y los chips seguian grandes. */
.model-conteocambioprivado .gp-cambio-cards {
    /* Sigue siendo auto-fit, como el molde: solo se baja el minimo de 180px a
       150px porque aca son SIETE chips y con 180 no entraban en una fila en una
       pantalla de 1280. No es lo que rompia antes -- aquello fijaba columnas de
       anchos distintos (minmax(240px, 1.2fr) + auto-fit), y por eso quedaban
       desparejos. */
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 10px;
    margin-bottom: 18px;
}

.model-conteocambioprivado .gp-cambio-cards > div {
    padding: 10px 12px;
}

.model-conteocambioprivado .gp-cambio-cards strong {
    font-size: 10px;
}

.model-conteocambioprivado .gp-cambio-cards span {
    margin-top: 4px;
    font-size: 16px;
    white-space: nowrap;
}

/* El total sigue destacado, pero por poco: dos puntos mas y su borde azul, no
   el doble de alto. */
.model-conteocambioprivado .gp-cambio-cards .gp-card-saldo span {
    font-size: 18px;
}

.model-conteocambioprivado .gp-cambio-cantidad {
    display: block;
    margin-top: 2px;
    color: var(--net-muted);
    font-size: 11px;
    font-style: normal;
}

/* El total del form, en la tercera columna al lado de la grilla de billetes:
   una tarjeta, no un dato suelto, para que se vea de reojo mientras se cuenta.
   Reusa los colores del chip de saldo del listado. */
/* ---- La matriz de billetes: grilla de verdad, no filas flex ----
   El patron de la casa arma cada .form-row como un flex que reparte el ancho
   entre SUS elementos. Sirve para filas de uno o dos campos que no tienen que
   alinearse entre si, pero aca hay una matriz de seis mas un dato al costado:
   con tres .form-row separados, la de tres elementos daba campos de 236px y las
   de dos, de 367 -- la segunda columna quedaba corrida 131px -- y el total,
   encerrado en la primera, dejaba la tercera columna vacia debajo.

   Por eso los siete campos van en UNA sola fila (ver el fieldset en admin.py) y
   aca esa fila pasa a grid. El total se ubica explicito en la columna 3 sobre
   las tres filas; las seis cantidades se auto-ubican salteando esa celda, o sea
   2 columnas x 3 filas, alineadas. El aire vertical pasa a ser el gap, que se
   fija en un solo lugar.

   OJO con el item de la grilla: NO es el .fieldBox. Django lo envuelve en un
   <div> sin clase, que es el hijo directo del .form-multiline -- por eso el
   molde apunta a "> div" para el flex-basis. Se lo agarra con :has(), que este
   archivo ya usa para el toggle. Apuntando al .fieldBox el selector no matchea
   y el total se auto-ubica al final, que fue justo lo que paso al escribirlo.

   Scopeado a body.change-form.model-conteocambioprivado: NINGUNA otra pantalla
   del patron se entera. Verificado en pantalla en Caja Gerencia y en Agregar
   Guia, que son las dos que mas lo usan. */
body.change-form.model-conteocambioprivado .form-row.field-total_cambio_display .flex-container.form-multiline {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 14px 26px;
    align-items: start;
}

body.change-form.model-conteocambioprivado .form-row.field-total_cambio_display .flex-container.form-multiline > div:has(> .fieldBox.field-total_cambio_display) {
    grid-column: 3;
    grid-row: 1 / span 3;
    /* Sin esto la tarjeta queda arriba con su alto natural y la columna 3 vuelve
       a tener un hueco debajo: el align-items:start del contenedor manda. */
    align-self: stretch;
}

/* Angosto: el chip baja a lo ancho de la primera fila y las cantidades pasan a
   dos columnas; mas angosto todavia, todo a una sola. El chip queda SIEMPRE
   arriba de los billetes -- que es para lo que esta -- porque en el orden del
   DOM es el ultimo, y se lo trae al frente con order. */
@media (max-width: 900px) {
    body.change-form.model-conteocambioprivado .form-row.field-total_cambio_display .flex-container.form-multiline {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    body.change-form.model-conteocambioprivado .form-row.field-total_cambio_display .flex-container.form-multiline > div:has(> .fieldBox.field-total_cambio_display) {
        grid-column: 1 / -1;
        grid-row: auto;
        order: -1;
    }
}

@media (max-width: 560px) {
    body.change-form.model-conteocambioprivado .form-row.field-total_cambio_display .flex-container.form-multiline {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* OJO: la clase field-total_cambio_display esta en el .form-row Y en el
   .fieldBox (mismo gotcha que la cascada Origen/Categoria de la caja del
   backoffice). La tarjeta va en el fieldBox, que es la tercera columna; sobre
   el form-row pintaba la fila entera. */
/* El .form-row del selector no es decorativo: el molde pone los .fieldBox en
   display:block con una regla mas especifica (admin_custom.css:1799), y sin
   igualarla el flex de aca no aplicaba y el numero quedaba pegado arriba con la
   tarjeta medio vacia. */
body.change-form.model-conteocambioprivado .form-row .flex-container.fieldBox.field-total_cambio_display {
    /* Cubre las tres filas, con el numero centrado: al lado de la matriz de
       billetes, a la vista de reojo mientras se cuenta. */
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    box-sizing: border-box;
    padding: 10px 12px;
    border: 1px solid #b8d3f1;
    border-top: 4px solid #2f80ed;
    border-radius: 8px;
    background: linear-gradient(180deg, #ffffff 0%, #edf6ff 100%);
}

body.change-form.model-conteocambioprivado .fieldBox.field-total_cambio_display label {
    color: var(--net-muted);
    font-size: 10px;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

/* El :not(.gp-negative) es clave: sin el, este color le ganaba por
   especificidad al rojo del negativo y con Salida el total quedaba azul. Al
   guardar el rojo lo pone el servidor en un <span> de adentro, que tiene su
   propia regla; en vivo la clase la pone el JS sobre este mismo .readonly. */
body.change-form.model-conteocambioprivado .fieldBox.field-total_cambio_display .readonly:not(.gp-negative) {
    color: var(--net-ink);
}

body.change-form.model-conteocambioprivado .fieldBox.field-total_cambio_display .readonly {
    padding: 0;
    font-size: 20px;
    font-weight: 800;
    white-space: nowrap;
}

/* Movimiento anulado de Caja Gerencia: sigue a la vista -- el rastro es el
   punto -- pero tachado y apagado, para que se lea de un golpe que no cuenta.
   El chip es el de la casa (.fact-chip + .fact-chip-danger, en facturacion.css,
   el mismo que lleva un lote anulado): aca solo se lo separa del concepto.
   SIN scope de modelo a proposito: lo usan las DOS pantallas de esta caja, el
   listado (.model-movimientocajaprivada) y el resumen (.gp-caja-resumen), y
   scopearlo a la primera dejaria al resumen sin el tachado. Son clases propias
   (gp-caja-*), no las pisa nadie mas. */
.gp-caja-anulado {
    color: var(--net-muted);
    text-decoration: line-through;
}

.gp-caja-chip-anulado {
    margin-left: 8px;
    vertical-align: middle;
}

/* Desplegable de la barra de título. Nacio para "REPORTES" en Guias (BEC /
   CONSOL adentro) y lo reusa "AGREGAR" en DG con sus cuatro opciones: mismo
   componente, no una copia -- cada pantalla suma su clase al :is().
   El summary reusa el estilo de accion de la casa; aca solo se le agrega el
   caret y se posiciona el menu.
   OJO con el scope de DG: su listado NO es un changelist de Django (es una
   vista propia con su template), asi que el body no recibe la clase de modelo y
   hay que ponersela a mano en el bodyclass. */
:is(.model-cargaprivada.change-list, .gp-dg) .net-cargaprivada-reportes {
    position: relative;
    display: inline-flex;
}

:is(.model-cargaprivada.change-list, .gp-dg) .net-cargaprivada-reportes > summary {
    list-style: none;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

:is(.model-cargaprivada.change-list, .gp-dg) .net-cargaprivada-reportes > summary::-webkit-details-marker {
    display: none;
}

:is(.model-cargaprivada.change-list, .gp-dg) .net-cargaprivada-reportes > summary::after {
    content: "▾";
    font-size: 11px;
}

:is(.model-cargaprivada.change-list, .gp-dg) .net-cargaprivada-reportes-menu {
    position: absolute;
    z-index: 60;
    top: calc(100% + 6px);
    right: 0;
    min-width: 150px;
    padding: 6px;
    background: #fff;
    border: 1px solid var(--net-border, #d7e3e8);
    border-radius: 10px;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12);
}

:is(.model-cargaprivada.change-list, .gp-dg) .net-cargaprivada-reportes-menu a {
    display: block;
    padding: 8px 12px;
    border-radius: 8px;
    color: var(--net-ink, #123a52);
    text-decoration: none;
    font-weight: 700;
    font-size: 13px;
}

:is(.model-cargaprivada.change-list, .gp-dg) .net-cargaprivada-reportes-menu a:hover {
    background: var(--net-surface-2, #f4f7f9);
}


/* =====================================================
   ANULACIÓN: el anulado sigue a la vista, tachado
   =====================================================
   Nunca se borra un cobro ni una guía: se anula. El filtro va en el PESO
   -- no suma al saldo -- y no salteando la fila, así que el registro sigue
   en el listado y hay que poder distinguirlo de un vistazo.

   Vale para Cobros y para Cargas Courier, que son los dos que se anulan. */

:is(.model-pago, .model-carga) .net-chip-anulado {
    display: inline-flex;
    align-items: center;
    padding: 3px 10px;
    border-radius: 999px;
    background: var(--net-danger-bg, #fbecec);
    color: var(--net-danger-text, #8a1f1f);
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.03em;
    white-space: nowrap;
}

/* La fila entera del anulado, apagada y tachada: se lee "esto ya no cuenta"
   sin tener que buscar el chip. */
:is(.model-pago, .model-carga) tr:has(.net-chip-anulado) > td {
    opacity: 0.65;
    text-decoration: line-through;
}

/* El chip NO va tachado: es la etiqueta que explica por qué lo está. */
:is(.model-pago, .model-carga) tr:has(.net-chip-anulado) .net-chip-anulado {
    text-decoration: none;
    opacity: 1;
}

/* El bloque de anulación en la ficha. */
:is(.model-pago, .model-carga) .net-anulacion {
    margin: 0 0 18px;
    padding: 14px 16px;
    border: 1px solid var(--net-danger-border, #e0a3a3);
    border-radius: 12px;
    background: var(--net-danger-bg, #fbecec);
}

:is(.model-pago, .model-carga) .net-anulacion-hecha {
    border-color: var(--net-border, #d7e3e8);
    background: var(--net-surface-2, #f4f7f9);
}

:is(.model-pago, .model-carga) .net-anulacion-ayuda,
:is(.model-pago, .model-carga) .net-anulacion-detalle {
    margin: 6px 0 12px;
    color: var(--net-muted, #607d8b);
    font-size: 13px;
}

:is(.model-pago, .model-carga) .net-anulacion label {
    display: block;
    margin-bottom: 5px;
    font-weight: 800;
    font-size: 13px;
}

:is(.model-pago, .model-carga) .net-anulacion input[type="text"] {
    width: 100%;
    max-width: 520px;
    padding: 10px 12px;
    border: 1px solid var(--net-border, #d7e3e8);
    border-radius: 10px;
    font-size: 14px;
}

:is(.model-pago, .model-carga) .net-anulacion-btn {
    margin-top: 10px;
    padding: 10px 16px;
    border: 0;
    border-radius: 10px;
    background: var(--net-danger-text, #8a1f1f);
    color: #fff;
    font-weight: 800;
    cursor: pointer;
}
