/* /Components/Layout/MainLayout.razor.rz.scp.css */
#blazor-error-ui[b-mmw2qponqc] {
    color-scheme: light only;
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss[b-mmw2qponqc] {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }
/* /Components/Layout/ReconnectModal.razor.rz.scp.css */
.components-reconnect-first-attempt-visible[b-50fpfz0m1x],
.components-reconnect-repeated-attempt-visible[b-50fpfz0m1x],
.components-reconnect-failed-visible[b-50fpfz0m1x],
.components-pause-visible[b-50fpfz0m1x],
.components-resume-failed-visible[b-50fpfz0m1x],
.components-rejoining-animation[b-50fpfz0m1x] {
    display: none;
}

#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible[b-50fpfz0m1x],
#components-reconnect-modal.components-reconnect-show .components-rejoining-animation[b-50fpfz0m1x],
#components-reconnect-modal.components-reconnect-paused .components-pause-visible[b-50fpfz0m1x],
#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible[b-50fpfz0m1x],
#components-reconnect-modal.components-reconnect-retrying[b-50fpfz0m1x],
#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible[b-50fpfz0m1x],
#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation[b-50fpfz0m1x],
#components-reconnect-modal.components-reconnect-failed[b-50fpfz0m1x],
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible[b-50fpfz0m1x] {
    display: block;
}


#components-reconnect-modal[b-50fpfz0m1x] {
    background-color: white;
    width: 20rem;
    margin: 20vh auto;
    padding: 2rem;
    border: 0;
    border-radius: 0.5rem;
    box-shadow: 0 3px 6px 2px rgba(0, 0, 0, 0.3);
    opacity: 0;
    transition: display 0.5s allow-discrete, overlay 0.5s allow-discrete;
    animation: components-reconnect-modal-fadeOutOpacity-b-50fpfz0m1x 0.5s both;
    &[open]

{
    animation: components-reconnect-modal-slideUp-b-50fpfz0m1x 1.5s cubic-bezier(.05, .89, .25, 1.02) 0.3s, components-reconnect-modal-fadeInOpacity-b-50fpfz0m1x 0.5s ease-in-out 0.3s;
    animation-fill-mode: both;
}

}

#components-reconnect-modal[b-50fpfz0m1x]::backdrop {
    background-color: rgba(0, 0, 0, 0.4);
    animation: components-reconnect-modal-fadeInOpacity-b-50fpfz0m1x 0.5s ease-in-out;
    opacity: 1;
}

@keyframes components-reconnect-modal-slideUp-b-50fpfz0m1x {
    0% {
        transform: translateY(30px) scale(0.95);
    }

    100% {
        transform: translateY(0);
    }
}

@keyframes components-reconnect-modal-fadeInOpacity-b-50fpfz0m1x {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

@keyframes components-reconnect-modal-fadeOutOpacity-b-50fpfz0m1x {
    0% {
        opacity: 1;
    }

    100% {
        opacity: 0;
    }
}

.components-reconnect-container[b-50fpfz0m1x] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

#components-reconnect-modal p[b-50fpfz0m1x] {
    margin: 0;
    text-align: center;
}

#components-reconnect-modal button[b-50fpfz0m1x] {
    border: 0;
    background-color: #6b9ed2;
    color: white;
    padding: 4px 24px;
    border-radius: 4px;
}

    #components-reconnect-modal button:hover[b-50fpfz0m1x] {
        background-color: #3b6ea2;
    }

    #components-reconnect-modal button:active[b-50fpfz0m1x] {
        background-color: #6b9ed2;
    }

.components-rejoining-animation[b-50fpfz0m1x] {
    position: relative;
    width: 80px;
    height: 80px;
}

    .components-rejoining-animation div[b-50fpfz0m1x] {
        position: absolute;
        border: 3px solid #0087ff;
        opacity: 1;
        border-radius: 50%;
        animation: components-rejoining-animation-b-50fpfz0m1x 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
    }

        .components-rejoining-animation div:nth-child(2)[b-50fpfz0m1x] {
            animation-delay: -0.5s;
        }

@keyframes components-rejoining-animation-b-50fpfz0m1x {
    0% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    4.9% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    5% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 1;
    }

    100% {
        top: 0px;
        left: 0px;
        width: 80px;
        height: 80px;
        opacity: 0;
    }
}
/* /Components/Pages/Accounting/Periodos.razor.rz.scp.css */
/* Feature 015 / US4 (T034) — "Parqueos sin período contable abierto".

   No new alert style and no colour of its own: the container is the site's own
   .alert / .alert--warn, which is already written entirely in theme tokens
   (--warn-bg / --warn-text) and redefined for dark, so both themes are covered by the
   theme itself. What this file adds is only WEIGHT and LAYOUT — the same shape
   OperationTrace.razor.css gives its own banner, kept local to this component because
   scoped CSS does not travel between components. */

.period-banner[b-2wfvj2i9dx] {
    padding: 16px 18px;
    font-weight: 500;
    line-height: 1.55;
}

/* A headline the reader cannot skim past: the parkings named below cannot post today,
   and that is the sentence the rest of the paragraph explains. */
.period-banner__title[b-2wfvj2i9dx] {
    display: block;
    font-size: 15px;
    font-weight: 800;
    margin-bottom: 4px;
}

.period-banner__list[b-2wfvj2i9dx] {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 6px 14px;
    margin-top: 10px;
}

/* A real button, not a span with a click handler: it is operable by keyboard and it is
   announced as an action. It LOOKS like a link because that is what it does — it moves
   the screen onto that parking's book, it does not submit anything. */
.period-banner__link[b-2wfvj2i9dx] {
    appearance: none;
    background: none;
    border: 0;
    padding: 0;
    font: inherit;
    font-weight: 700;
    color: inherit;
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
}

.period-banner__link:hover[b-2wfvj2i9dx] {
    text-decoration-thickness: 2px;
}

.period-banner__link:focus-visible[b-2wfvj2i9dx] {
    outline: 2px solid currentColor;
    outline-offset: 3px;
    border-radius: 3px;
}
/* /Components/Pages/Accounting/Settlements.razor.rz.scp.css */
/* 026/T064 — el motivo de "no se puede liquidar" tiene que envolver.

   La regla global de las tablas del sitio (.data-table td en admin.css) impone
   white-space: nowrap, y esa herencia le gana al max-width que esta celda ya
   pedia: un motivo real (563px) no se cortaba y empujaba la tabla entera a
   desplazarse. Este selector, mas especifico que .data-table td por venir de
   scoped CSS, levanta el nowrap A PROPOSITO solo para este bloque — el texto
   es el corazon de la pantalla (le dice al contador que reparar) y tiene que
   leerse completo en dos o tres renglones, no a los pedazos por scroll
   horizontal. No tocar la regla global: la comparten todas las pantallas. */
.settlement-reason[b-xyj1k2zlas] {
    white-space: normal;
    max-width: 260px;
    font-size: 12px;
    margin-top: 4px;
}

/* 026/T027 — the "Transferir" button lives inside a table cell, next to an 8px badge dot.
   The site's default .btn padding is sized for page headers and modal footers; unscaled, it
   makes every settleable row noticeably taller than its neighbours for no reason. This trims
   ONLY this button's own padding/font-size — .btn itself, shared by every other screen, is
   untouched. */
.settle-action[b-xyj1k2zlas] {
    padding: 4px 10px;
    font-size: 12px;
}

/* 026/T028 — la celda del nombre del parqueo es el ENCABEZADO DE SU FILA.

   Sin <th scope="row"> nada asocia los siete numeros de la fila con el parqueo del que
   hablan: un lector de pantalla lee "6.102,00" sin decir de quien es. Poner el <th> trae
   consigo el estilo de .data-table th (11px, mayusculas, banda gris #fafbfc), que es el de
   un encabezado de COLUMNA y aca queda fuera de lugar, asi que se neutraliza.

   ⚠️ EL SELECTOR LLEVA .data-table A PROPOSITO, y no es adorno. Scoped CSS agrega el atributo
   del componente al ULTIMO elemento, asi que esto compila a `.data-table .cell-row-head[b-xxx]`
   = (0,3,0). Sin el `.data-table` delante seria (0,2,0), que le gana a `.data-table th` (0,1,1)
   en tema CLARO pero PIERDE contra `:root[data-theme="dark"] .data-table th` (0,2,1): la celda
   se pintaria con la banda del encabezado solo en tema oscuro. Una variante se mide en LOS DOS
   temas o no se midio.
   ⛔ No tocar la regla global: la comparten decenas de pantallas y el encabezado de columna
   del resto del sitio es una brecha aparte, con casilla propia. */
.data-table .cell-row-head[b-xyj1k2zlas] {
    padding: 13px 20px;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: normal;
    text-transform: none;
    color: inherit;
    background: transparent;
    border-bottom: 1px solid var(--border-softer);
    vertical-align: middle;
}

/* 026/T028 — datos VIEJOS mientras llega el reemplazo.

   La grilla no se desmonta al recargar (eso haria saltar el acomodo en cada cambio de
   pagina), asi que mientras la consulta viaja los montos en pantalla siguen siendo los del
   libro anterior. Atenuarlos y bloquear el clic los marca como no vigentes; aria-busy dice
   lo mismo a quien no ve la atenuacion. La transicion es corta a proposito: contra la base
   local la respuesta vuelve en menos de 150 ms y un fundido lento se leeria como un parpadeo. */
.grid-refreshing[b-xyj1k2zlas] {
    opacity: .5;
    pointer-events: none;
    transition: opacity .12s linear;
}

/* ============================================================================
   026/T100 — los tres niveles del detalle, ahora filas de UNA sola tabla.

   Al aplanar, lo unico que distingue un nivel de otro es la SANGRIA de su
   columna de identidad (col 2) y una banda de sub-encabezado; a proposito no
   hay fondo por fila, porque un fondo propio le ganaria al `:hover` de
   .data-table tbody tr y las filas anidadas dejarian de responder al mouse.

   ⚠️ Los sub-encabezados llevan .cell-row-head A PROPOSITO. Es la unica clase
   que el remap de tema oscuro de admin.css ya excluye por nombre
   (`:root[data-theme="dark"] .data-table th:not(.cell-row-head)`), asi que
   heredan la neutralizacion de la banda gris en LOS DOS temas sin tocar la
   hoja global ni pelear especificidad. Las reglas de abajo van con
   `.data-table` delante por el mismo motivo que .cell-row-head: sin el, el
   selector queda por debajo del remap oscuro y la variante se ve bien en claro
   y rota en oscuro. Una variante se mide en los dos temas o no se midio. */
.data-table .cell-row-head.cell-subhead[b-xyj1k2zlas] {
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .5px;
    text-transform: uppercase;
    color: var(--text-2);
    padding-top: 14px;
    padding-bottom: 6px;
    border-bottom: 1px solid var(--border-soft);
}

/* La identidad de una fila anidada sigue siendo el encabezado DE SU FILA
   (<th scope="row">), pero no compite con el nombre del parqueo: mismo tamano,
   peso normal. Lo que dice "esto cuelga de la fila de arriba" es la sangria. */
.data-table .cell-row-head.settle-sub-name[b-xyj1k2zlas] {
    font-weight: 500;
}

.data-table .settle-indent-1[b-xyj1k2zlas] {
    padding-left: 44px;
}

.data-table .settle-indent-2[b-xyj1k2zlas] {
    padding-left: 72px;
}

/* La regla global .data-table td impone white-space: nowrap, que es lo correcto
   para una celda de datos y lo contrario de lo que necesita una fila de texto
   corrido a nueve columnas de ancho (la nota de las fechas, un mensaje de error
   de servicio, un vacio explicado). Se levanta SOLO para esas filas. */
.data-table .settle-note__text[b-xyj1k2zlas] {
    white-space: normal;
}

/* 026/T107 — la aclaracion de por que las dos fechas no coinciden. Es una nota,
   no una alarma: misma tinta que el resto del texto secundario y el icono al
   tamano del renglon, para que no compita con los montos. */
.data-table .settle-note[b-xyj1k2zlas] {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    font-size: 12px;
    color: var(--text-2);
    max-width: 720px;
}

/* ::deep — el glifo lo dibuja <AppIcon>, que es OTRO componente, asi que no lleva
   el atributo de alcance de este y el CSS scoped no lo alcanza sin esto. Mismo
   precedente que Feriados.razor.css (.notice ::deep .msi) y
   PaymentGateway.razor.css (.gw-status ::deep .msi). */
.settle-note[b-xyj1k2zlas]  .msi {
    font-size: 16px;
    flex: none;
    margin-top: 1px;
}

/* 026/T103 — insignia de orden FIJO junto a "Espera (dias)" (ver el apartamiento
   declarado en el .razor, arriba de la tabla). Reusa el color de acento de
   `.grid__sort.is-active` (PagedGrid, admin.css) para que se LEA igual que un
   orden activo en el resto del sitio, pero sin cursor de boton ni :hover: no es
   clicable, porque el servidor no tiene otro orden que ofrecer. */
.settle-sort-badge[b-xyj1k2zlas] {
    display: inline-flex;
    align-items: center;
    color: var(--accent);
}

.settle-sort-badge[b-xyj1k2zlas]  .msi {
    font-size: 16px;
}

/* 026/T108 — el pie de la grilla de adentro, con su rotulo.
   El <td> cede su relleno: el rotulo y el GridFooter traen el suyo, y el
   componente ya se dibuja con su propio borde superior. */
.data-table .settle-foot-cell[b-xyj1k2zlas] {
    padding: 0;
    white-space: normal;
}

.settle-foot-label[b-xyj1k2zlas] {
    padding: 12px 20px 0 72px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .5px;
    text-transform: uppercase;
    color: var(--text-2);
}
/* /Components/Pages/Integrations/Hacienda.razor.rz.scp.css */
/* 006/T001-T003 · La grilla de credenciales de Hacienda.

   Todo el color sale de las variables del sitio (admin.css / app.css), definidas para el
   tema claro y el oscuro: aca NO hay ni un color literal, asi que la pantalla cambia de
   tema sin una sola regla propia de tema. */

/* La mascara de la contraseña. La calcula la BASE y llega hecha en PasswordMasked: esta
   regla es solo tipografia, jamas la mascara (mismo criterio que PaymentGateway.razor.css
   ./gw-secret, con su propio nombre porque el CSS aislado de Blazor no cruza componentes). */
.hacienda-secret[b-ahxzfbv7d3] {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    letter-spacing: .06em;
}

/* T002 -el icono que ocupa el lugar exacto del boton "Probar conexion" de la pasarela,
   pero sin parecer un boton: no tiene fondo, no tiene borde y el cursor no cambia. */
.hacienda-no-probar[b-ahxzfbv7d3] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    color: var(--text-2);
    cursor: default;
}

.hacienda-no-probar[b-ahxzfbv7d3]  .msi {
    font-size: 16px;
    color: var(--text-3);
}

/* T002 -la explicacion completa, debajo de la grilla, mismo criterio que la tarjeta
   "Sobre la clave secreta" de la pasarela (PaymentGateway.razor.css ./gw-explain). */
.hacienda-explain[b-ahxzfbv7d3] {
    margin-top: 18px;
}

.hacienda-explain__title[b-ahxzfbv7d3] {
    font-size: 12.5px;
    font-weight: 700;
    color: var(--text);
    margin-bottom: 8px;
}

.hacienda-explain p[b-ahxzfbv7d3] {
    font-size: 13px;
    line-height: 1.6;
    color: var(--text-2);
    margin: 0 0 8px;
    max-width: 90ch;
}

.hacienda-explain p:last-child[b-ahxzfbv7d3] {
    margin-bottom: 0;
}

/* T001a -texto de los dos modales de confirmacion (usar ambiente / retirar), mismo
   criterio que PaymentGateway.razor.css ./gw-confirm__text -con su propio nombre porque
   el CSS aislado de Blazor no cruza componentes. */
.hacienda-confirm__text[b-ahxzfbv7d3] {
    font-size: 13.5px;
    line-height: 1.6;
    color: var(--text-2);
    margin: 12px 0 0;
}

/* "El parqueo está usando estas credenciales.": no es un boton, y no tiene que parecerlo
   -mismo criterio que PaymentGateway.razor.css ./gw-inuse. */
.hacienda-inuse[b-ahxzfbv7d3] {
    display: inline-flex;
    align-items: center;
    color: var(--ok-text);
}

.hacienda-inuse[b-ahxzfbv7d3]  .msi {
    font-size: 18px;
}

/* T001a -el boton "usar este ambiente" se muestra DESHABILITADO CON EL MOTIVO cuando
   falta el permiso de produccion, nunca escondido (DECR-164 R4): .icon-action de
   admin.css no trae su propio estado disabled porque en el resto del sitio esa accion
   se oculta en vez de apagarse. Alcance por CSS aislado: solo afecta a esta pantalla. */
.icon-action:disabled[b-ahxzfbv7d3] {
    opacity: .45;
    cursor: not-allowed;
}

.icon-action:disabled:hover[b-ahxzfbv7d3] {
    background: transparent;
    color: var(--text-2);
}
/* /Components/Pages/Integrations/PaymentGateway.razor.rz.scp.css */
/* 004/T002 · Pantalla de credenciales de la pasarela.

   Todo el color sale de las variables del sitio (admin.css / app.css), que ya estan
   definidas para el tema claro y el oscuro: aca NO hay ni un color literal, asi que la
   pantalla cambia de tema sin una sola regla propia de tema. Lo unico que este archivo
   aporta es la DISTRIBUCION — dos tarjetas lado a lado en pantalla ancha, que es como se
   usa el sitio de staff. */

/* El estado de arriba: un renglon con el ambiente en uso y su explicacion. */
.gw-status[b-p87jjdh8nz] {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-bottom: 18px;
}

.gw-status__label[b-p87jjdh8nz] {
    font-size: 11.5px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--text-2);
}

.gw-status__value[b-p87jjdh8nz] {
    font-size: 18px;
    font-weight: 800;
    color: var(--text);
    white-space: nowrap;
}

.gw-status__text[b-p87jjdh8nz] {
    font-size: 13px;
    color: var(--text-2);
    border-left: 1px solid var(--border-soft);
    padding-left: 16px;
    flex: 1;
    min-width: 240px;
}

/* Las dos tarjetas: pruebas y produccion, siempre las dos, siempre en ese orden.
   auto-fit + minmax deja las dos al lado en escritorio y las apila cuando no caben. */
.gw-cards[b-p87jjdh8nz] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(430px, 1fr));
    gap: 18px;
    align-items: start;
}

.gw-card__head[b-p87jjdh8nz] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 16px;
}

.gw-card__title[b-p87jjdh8nz] {
    font-size: 16px;
    font-weight: 800;
    color: var(--text);
}

.gw-card__sub[b-p87jjdh8nz] {
    font-size: 12px;
    color: var(--text-2);
    margin-top: 3px;
}

/* La ficha de la credencial. Dos columnas anchas: los identificadores de la pasarela son
   largos y partirlos en tres columnas los deja ilegibles. */
.gw-details[b-p87jjdh8nz] {
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}

.gw-value[b-p87jjdh8nz] {
    font-size: 13.5px;
    font-weight: 600;
    color: var(--text);
    word-break: break-all;
}

/* La mascara del secreto. La calcula la BASE y llega hecha en SecretMasked: esta regla es
   solo tipografia, jamas la mascara. */
.gw-secret[b-p87jjdh8nz] {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    letter-spacing: .06em;
}

.gw-when[b-p87jjdh8nz] {
    display: inline-block;
    margin-left: 8px;
    font-size: 12.5px;
    font-weight: 500;
    color: var(--text-2);
}

.gw-actions[b-p87jjdh8nz] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin-top: 18px;
}

/* "El sistema esta cobrando con estas credenciales.": no es un boton, y no tiene que
   parecerlo. */
.gw-inuse[b-p87jjdh8nz] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12.5px;
    font-weight: 700;
    color: var(--ok-text);
}

/* El MOTIVO de un boton deshabilitado. Va debajo y visible, nunca solo en el tooltip:
   un control gris sin explicacion es la mitad del defecto que DECR-164 R4 evita. */
.gw-note[b-p87jjdh8nz] {
    font-size: 12px;
    line-height: 1.5;
    color: var(--text-2);
    margin-top: 10px;
}

.gw-note--guard[b-p87jjdh8nz] {
    border-left: 2px solid var(--border);
    padding-left: 10px;
}

/* La tarjeta sin credenciales: el primer estado que ve el dueno, porque hoy no hay
   ninguna cargada. Dice que hacer, no solamente que no hay nada. */
.gw-empty[b-p87jjdh8nz] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    text-align: center;
    padding: 26px 12px;
    border: 1px dashed var(--border);
    border-radius: var(--r-card);
    background: var(--app-bg);
}

.gw-empty__text[b-p87jjdh8nz] {
    font-size: 13.5px;
    color: var(--text-2);
    max-width: 34ch;
}

.gw-explain[b-p87jjdh8nz] {
    margin-top: 18px;
}

.gw-explain__title[b-p87jjdh8nz] {
    font-size: 12.5px;
    font-weight: 700;
    color: var(--text);
    margin-bottom: 8px;
}

.gw-explain p[b-p87jjdh8nz] {
    font-size: 13px;
    line-height: 1.6;
    color: var(--text-2);
    margin: 0 0 8px;
    max-width: 90ch;
}

.gw-explain p:last-child[b-p87jjdh8nz] {
    margin-bottom: 0;
}

.gw-explain__frozen code[b-p87jjdh8nz] {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 12.5px;
}

.gw-confirm__text[b-p87jjdh8nz] {
    font-size: 13.5px;
    line-height: 1.6;
    color: var(--text-2);
    margin: 12px 0 0;
}

/* El icono del renglon de estado y el de la tarjeta vacia los dibuja <AppIcon>, que es
   otro componente: sin ::deep el CSS con alcance no los alcanza. */
.gw-status[b-p87jjdh8nz]  .msi {
    font-size: 30px;
    color: var(--accent);
}

/* 🔴 PRODUCCION EN USO. El aviso lo cargan el ICONO del renglon y el nombre del ambiente,
   tenidos con --danger-text, que app.css define para el tema claro Y para el oscuro: por eso
   aca no hay ni un color literal ni una regla de tema. ⛔ Antes esto lo hacia un emoji 🔴
   metido en el texto — el unico emoji en copy real de todo el sitio —, y un emoji NO se tine
   con las variables: ignoraba el tema y rendia distinto en cada sistema.
   Va DESPUES de .gw-status ::deep .msi a proposito: misma especificidad, gana el ultimo. */
.gw-status--live[b-p87jjdh8nz]  .msi {
    color: var(--danger-text);
}

.gw-status--live .gw-status__value[b-p87jjdh8nz] {
    color: var(--danger-text);
}

.gw-empty[b-p87jjdh8nz]  .msi {
    font-size: 30px;
    color: var(--text-3);
}
/* /Components/Pages/Parking/CatalogoFiscal.razor.rz.scp.css */
/* El catálogo global de conceptos fiscales (023-prepaid-ticket-toll, Tramo 0/4, T051).

   🔴 LO QUE ESTE ARCHIVO TIENE QUE LOGRAR: que la tasa de IVA y el código CABYS se vean como UNA
   sola decisión, nunca como dos datos que se puedan desparejar mirándolos.

   .taxcell junta los dos en una fila flexible con el MISMO peso tipográfico (mismo font-weight,
   mismo tamaño) para las dos mitades -- lo único que cambia con el tercer estado es el COLOR y un
   ícono de aviso, nunca el peso, porque bajar el peso de la parte pendiente la leería como un
   dato menos importante en vez de una decisión distinta que hay que resolver.

   .txc-fiscal-block agrupa esos dos campos del FORMULARIO en un bloque con borde propio, para que
   la misma idea -- "esto es una sola decisión fiscal" -- se sostenga tanto en la grilla como al
   editar. */

/* ------------------------------------------------------------- La celda combinada --- */

.taxcell[b-r2uxe8futc] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    font-weight: 500;
    color: var(--text);
}

.taxcell__vat[b-r2uxe8futc] {
    white-space: nowrap;
}

.taxcell__dot[b-r2uxe8futc] {
    color: var(--text-3);
}

.taxcell__cabys[b-r2uxe8futc] {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* El tercer estado: mismo peso, mismo tamaño que .taxcell__vat -- sólo cambia el tono (aviso, no
   error) y un ícono, porque es una decisión documentada esperando al contador, no un dato roto. */
.taxcell__cabys--pending[b-r2uxe8futc] {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    color: var(--warn-text);
}

.taxcell__cabys--pending[b-r2uxe8futc]  .msi {
    font-size: 15px;
}

/* 🔴 Hallazgo del ux-reviewer (2026-09-05), MEDIDO con la fórmula WCAG sobre los colores
   computados, no a ojo: --warn-text #d97706 sobre el fondo blanco de la tarjeta (--card-bg
   #ffffff, no --warn-bg -- esta celda no lleva chip de color) da 3,19:1, bajo el piso de 4,5:1
   que le toca por ser TEXTO ("CABYS pendiente" se lee, no es decorativo). En OSCURO mide
   10,75:1 -- perfecto, y es justo el defecto inverso al que suele escaparse: el estado que el
   diseño pide leer como "decisión documentada, no error" es el que peor se lee en el tema que
   usa la mayoría.

   Se suma al MISMO patrón que admin.css ya fijó para .badge--warn / .alert--warn / ahora
   .kpi__icon--warn: mismo color de reemplazo #92400e (acá da 7,09:1 sobre blanco, por encima
   del piso con margen), mismo par de selectores por los mismos TRES estados de tema (el :root
   SIN data-theme, antes de que theme.js estampe, cae bajo prefers-color-scheme). El token
   --warn-text no se toca: también pinta KPIs, chips e íconos por todo el sitio; se corrige LA
   VARIANTE, con el scope de esta pantalla nada más (CSS isolation ya le agrega el atributo del
   componente al selector). */
:root[data-theme="light"] .taxcell__cabys--pending[b-r2uxe8futc] {
    color: #92400e;
}

@media (prefers-color-scheme: light) {
    :root:not([data-theme="dark"]) .taxcell__cabys--pending[b-r2uxe8futc] {
        color: #92400e;
    }
}

/* ------------------------------------------------------- Las dos marcas del catálogo --- */

/* 023/T060 -- "Por defecto" / "Concepto de la comisión", junto al nombre en la fila de un
   concepto que se ofrece. flex-wrap: las etiquetas nunca estiran la columna -- se acomodan
   debajo del nombre si no entran en el min-width:200px del encabezado. */
.txc-name-cell[b-r2uxe8futc] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
}

/* --------------------------------------------------- Botón "Retirar" bloqueado (T060) --- */

/* admin.css no trae un estado atenuado para .icon-action: sin esta regla, un ícono en rojo
   que no reacciona al clic se leería como un defecto visual, no como una guarda explicada por
   su title. Se atenúa SOLO en esta pantalla, con CSS aislado -- no se toca admin.css.

   [aria-disabled="true"] y NO :disabled (ux-reviewer, 2026-09-13): el botón real queda
   enfocable -- el motivo en title/aria-label sólo lo veía un mouse -- y esta rama nunca lleva
   @onclick, así que ni Enter ni Espacio disparan nada. */
.icon-action[aria-disabled="true"][b-r2uxe8futc] {
    opacity: .45;
    cursor: not-allowed;
}

.icon-action[aria-disabled="true"]:hover[b-r2uxe8futc] {
    background: transparent;
    color: var(--danger-text);
}

/* -------------------------------------------------------- El bloque del formulario --- */

.txc-fiscal-block[b-r2uxe8futc] {
    margin: 4px 0 14px;
    padding: 14px 14px 6px;
    border: 1px solid var(--border);
    border-radius: var(--r-control);
    background: var(--border-softer);
}

.txc-fiscal-block__title[b-r2uxe8futc] {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
    font-size: 12.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--text-2);
}

.txc-fiscal-block__title[b-r2uxe8futc]  .msi {
    font-size: 17px;
    color: var(--accent);
}

.txc-fiscal-block__vatrow[b-r2uxe8futc] {
    display: flex;
    align-items: center;
    gap: 8px;
    max-width: 200px;
}

.txc-fiscal-block__vatrow .input[b-r2uxe8futc] {
    flex: 1 1 auto;
}

.txc-fiscal-block__pct[b-r2uxe8futc] {
    font-weight: 600;
    color: var(--text-2);
}

.txc-fiscal-block__why[b-r2uxe8futc] {
    margin: 6px 0 8px;
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--text-2);
}

/* -------------------------------------------------------------------- Los diálogos --- */

/* .input mide 40px de alto por diseño (campos de una línea); un textarea tiene que deshacerlo o
   rows="2" no hace nada -- mismo ajuste que Feriados.razor.css (.hol__area). */
.txc-area[b-r2uxe8futc] {
    height: auto;
    min-height: 62px;
    padding: 10px 12px;
    line-height: 1.5;
    resize: vertical;
}

.txc-confirm[b-r2uxe8futc] {
    margin: 12px 0;
    font-size: 13.5px;
    line-height: 1.6;
    color: var(--text-2);
}

.txc-confirm strong[b-r2uxe8futc] {
    color: var(--text);
}
/* /Components/Pages/Parking/Credenciales.razor.rz.scp.css */
/* Service credentials screen (US7, P-044). Desktop staff site: the two jobs this screen does
   — issuing a credential and re-pointing one at its aguja — sit SIDE BY SIDE on a wide screen
   and stack on a narrow one. Nothing here invents a colour or a component: every value is an
   existing theme token, so both themes follow the site. */

.cred-grid[b-qw2ejq2skn] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(420px, 1fr));
    gap: var(--grid-gap);
    align-items: start;
}

/* Lead paragraph under a card heading: the same voice as .field__hint, one step larger. */
.cred-lead[b-qw2ejq2skn] {
    font-size: 13.5px;
    color: var(--text-2);
    margin: 0 0 12px;
}

.cred-hint[b-qw2ejq2skn] {
    font-size: 13px;
    color: var(--text-2);
    margin: 2px 0 0;
}

/* The one-time secret panel: a single column of labelled values, wide enough for a 64-char
   secret to break without turning into a wall. */
.cred-secret[b-qw2ejq2skn] {
    padding: 18px;
    display: grid;
    gap: 14px;
    max-width: 760px;
}

.cred-value[b-qw2ejq2skn] {
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    font-size: 14px;
    color: var(--text);
    word-break: break-all;
}

.cred-copy-row[b-qw2ejq2skn] {
    display: flex;
    gap: 8px;
    align-items: flex-start;
}

.cred-code[b-qw2ejq2skn] {
    flex: 1;
    font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
    font-size: 14px;
    color: var(--text);
    background: var(--app-bg);
    border: 1px solid var(--border-soft);
    padding: 10px 12px;
    border-radius: 8px;
    word-break: break-all;
}

.cred-actions[b-qw2ejq2skn] {
    margin-top: 14px;
    display: flex;
    justify-content: flex-end;
}

/* "obligatorio para este permiso" beside a field label. It is a HINT about what the server is
   going to demand, not a client-side rule, so it is worded and toned as a note — not as the
   red of a validation failure that has not happened yet. */
.cred-required[b-qw2ejq2skn] {
    margin-left: 6px;
    font-size: 11.5px;
    font-weight: 600;
    text-transform: none;
    letter-spacing: 0;
    color: var(--text-2);
}
/* /Components/Pages/Parking/Feriados.razor.rz.scp.css */
/* El calendario nacional de feriados (016-B, tramo 0 — T004).

   🔴 LO QUE ESTE ARCHIVO TIENE QUE LOGRAR: que los CUATRO estados del aviso se vean distintos
   entre sí. No dos. El backend graduó a propósito en Ok / Warning / Critical / Expired y no dejó
   ninguna propiedad booleana de conveniencia; si el CSS los pintara con dos colores, el atajo que
   el backend evitó volvería por la puerta de atrás.

   Cada estado cambia CUATRO cosas a la vez, no solo el color:
     · el ancho y el color de la franja izquierda,
     · el color del ícono,
     · la píldora de calificación (fondo y texto), que dice el estado CON PALABRAS,
     · y el tono del botón (primario en los tres estados con problema, secundario en Ok),
       que se decide en el .razor.
   Así el estado se lee sin depender del color: quien no distingue rojo de naranja igual lee
   «Crítico» y «Vencido», y quien navega por lector de pantalla recibe role="alert" en los tres
   estados de problema y role="status" en el que está al día.

   EL FONDO DE LA TARJETA ES NEUTRO (--card-bg) a propósito, y no el tinte del estado: el aviso
   tiene tres párrafos de texto largo, y el texto de contenido sobre un tinte fuerte pierde
   contraste en uno de los dos temas. El color lo cargan la franja, el ícono y la píldora, que son
   superficies chicas y de alto contraste. Todos los colores salen de las variables del tema, así
   que claro y oscuro son UNA definición y no dos que se separan.

   El texto que es CONTENIDO usa --text-2; --text-3 queda para lo que es adorno (medido: --text-3
   sobre tarjeta clara da 2,56:1, por debajo del piso de 4,5:1).

   El sitio de staff se usa en ESCRITORIO: el aviso ocupa el ancho y pone su botón a la derecha,
   donde la vista termina de leer la frase. Por debajo de 900px se apila conservando el orden de
   lectura — primero qué pasa, después qué hacer. */

/* --------------------------------------------------------------------- El aviso --- */

.notice[b-59fzohc2sb] {
    display: flex;
    gap: 14px;
    align-items: flex-start;
    padding: 16px 18px;
    margin-bottom: 18px;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    border-left: 5px solid var(--text-3);
    border-radius: var(--r-card);
    box-shadow: var(--shadow-card);
}

/* ::deep — el glifo lo dibuja <AppIcon>, que es otro componente, así que el CSS con alcance no
   lo alcanza sin esto. */
.notice[b-59fzohc2sb]  .msi {
    font-size: 28px;
    flex: none;
    line-height: 1;
    color: var(--text-3);
}

.notice__body[b-59fzohc2sb] {
    flex: 1 1 auto;
    min-width: 0;
}

/* La calificación EN PALABRAS. Es lo que hace que los cuatro estados se distingan sin color. */
.notice__grade[b-59fzohc2sb] {
    display: inline-block;
    font-size: 11.5px;
    font-weight: 800;
    letter-spacing: .04em;
    text-transform: uppercase;
    padding: 3px 9px;
    border-radius: var(--r-pill);
    background: var(--off-bg);
    color: var(--off-text);
    margin-bottom: 8px;
}

/* El mensaje del servidor: es la frase que dice qué hacer y nombra el año, así que va con la
   tinta más fuerte y el cuerpo más grande del bloque. */
.notice__message[b-59fzohc2sb] {
    margin: 0 0 8px;
    font-size: 14.5px;
    font-weight: 700;
    line-height: 1.5;
    color: var(--text);
    max-width: 90ch;
}

/* El porqué de la calificación: días restantes, hasta cuándo llega y los umbrales que el
   procedimiento devolvió. Es contenido, no pie de página. */
.notice__why[b-59fzohc2sb] {
    margin: 0 0 6px;
    font-size: 13px;
    line-height: 1.6;
    color: var(--text-2);
    max-width: 90ch;
}

.notice__meta[b-59fzohc2sb] {
    margin: 0;
    font-size: 12px;
    line-height: 1.55;
    color: var(--text-2);
}

.notice__action[b-59fzohc2sb] {
    flex: none;
    padding-top: 2px;
}

/* ---- Ok: al día. Franja fina; es el único estado sin alarma. ---- */
.notice--ok[b-59fzohc2sb] {
    border-left-color: var(--ok-text);
}

.notice--ok[b-59fzohc2sb]  .msi {
    color: var(--ok-text);
}

.notice--ok .notice__grade[b-59fzohc2sb] {
    background: var(--ok-bg);
    color: var(--ok-text);
}

/* ---- Warning: hay que cargar el año siguiente, con tiempo de sobra. ---- */
.notice--warning[b-59fzohc2sb] {
    border-left-width: 6px;
    border-left-color: var(--warn-text);
}

.notice--warning[b-59fzohc2sb]  .msi {
    color: var(--warn-text);
}

.notice--warning .notice__grade[b-59fzohc2sb] {
    background: var(--warn-bg);
    color: var(--warn-text);
}

/* ---- Critical: el calendario se acaba y la fecha ya se puede nombrar. ---- */
.notice--critical[b-59fzohc2sb] {
    border-left-width: 8px;
    border-left-color: var(--danger-text);
}

.notice--critical[b-59fzohc2sb]  .msi {
    color: var(--danger-text);
}

.notice--critical .notice__grade[b-59fzohc2sb] {
    background: var(--danger-bg);
    color: var(--danger-text);
}

/* ---- Expired: YA no se está cobrando el recargo. Comparte la paleta con Critical porque las
   dos son rojas de verdad, así que la diferencia NO se deja al color: el borde entero se tiñe,
   la franja se duplica y la píldora se dibuja con contorno además de fondo. Sumado al ícono
   distinto (block en vez de error) y a la calificación escrita, los dos estados rojos no se
   confunden ni en blanco y negro. ---- */
.notice--expired[b-59fzohc2sb] {
    border-color: var(--danger-text);
    border-left-width: 12px;
    border-left-color: var(--danger-text);
    background: var(--danger-bg);
}

.notice--expired[b-59fzohc2sb]  .msi {
    color: var(--danger-text);
}

.notice--expired .notice__grade[b-59fzohc2sb] {
    background: var(--danger-bg);
    color: var(--danger-text);
    border: 1px solid var(--danger-text);
}

/* Sobre el tinte de Expired el texto de contenido necesita la tinta fuerte: --text-2 sobre
   --danger-bg pierde contraste en el tema claro. */
.notice--expired .notice__why[b-59fzohc2sb],
.notice--expired .notice__meta[b-59fzohc2sb] {
    color: var(--text);
}

/* ------------------------------------------------------------------ La tabla --- */

.hol__lead[b-59fzohc2sb] {
    margin: 0;
    padding: 14px 20px 0;
    font-size: 12.5px;
    line-height: 1.55;
    color: var(--text-2);
    max-width: 100ch;
}

/* Separador de año. Es un <th scope="colgroup">, no un <td> disfrazado: para un lector de
   pantalla el año encabeza las filas que siguen. Se pega arriba porque en escritorio la tabla
   crece con cada año cargado y el año es el dato que ordena la lectura. */
.hol__yearrow th[b-59fzohc2sb] {
    background: var(--off-bg);
    text-align: left;
    padding: 8px 14px;
    border-top: 1px solid var(--border);
    font-weight: 700;
}

.hol__year[b-59fzohc2sb] {
    font-size: 13px;
    color: var(--text);
    margin-right: 10px;
}

/* Cuántos feriados tiene ese año y si son menos de los que el servidor considera un calendario
   completo. El número del mínimo viene del DTO, nunca escrito acá. */
.hol__yearcount[b-59fzohc2sb] {
    font-size: 12px;
    font-weight: 600;
    color: var(--text-2);
}

/* Un feriado retirado se ve retirado a simple vista, además de decirlo su insignia: la fila baja
   de intensidad, pero NO se esconde. Esconderla haría que un retiro equivocado se confundiera con
   un día que nunca se cargó, que es el silencio que este tramo vino a cerrar. */
.hol__row--off td[b-59fzohc2sb] {
    color: var(--text-2);
}

/* 026/T105 — la fecha de una fila retirada ahora es su <th scope="row"> (era <td>), y
   .data-table th.cell-row-head (admin.css) fija `color: inherit` a (0,2,1). Sin el prefijo
   `.data-table` este selector compila a (0,2,1) también — empate que depende del orden de
   carga, la misma trampa medida en Settlements.razor.css (026/T100). Con el prefijo queda en
   (0,3,1) y gana siempre, en los dos temas. */
.data-table .hol__row--off th[b-59fzohc2sb] {
    color: var(--text-2);
}

/* ------------------------------------------------------------------ Los diálogos --- */

/* Una fecha es un dato corto: a todo el ancho del diálogo el campo se lee como si esperara una
   frase. ::deep: 022/T054 movió el input a DateField.razor (un componente hijo), y el
   aislamiento de CSS de Blazor no alcanza el <input> propio de un hijo sin este combinador. */
[b-59fzohc2sb] .hol__date {
    max-width: 190px;
}

/* .input mide 40px de alto por diseño (es para campos de una línea); un textarea tiene que
   deshacerlo o rows="2" no hace nada. */
.hol__area[b-59fzohc2sb] {
    height: auto;
    min-height: 62px;
    padding: 10px 12px;
    line-height: 1.5;
    resize: vertical;
}

.hol__confirm[b-59fzohc2sb] {
    margin: 12px 0;
    font-size: 13.5px;
    line-height: 1.6;
    color: var(--text-2);
}

.hol__confirm strong[b-59fzohc2sb] {
    color: var(--text);
}

@media (max-width: 900px) {
    .notice[b-59fzohc2sb] {
        flex-wrap: wrap;
    }

    .notice__action[b-59fzohc2sb] {
        flex: 1 1 100%;
        padding-top: 4px;
    }
}
/* /Components/Pages/Parking/VehicleCatalog.razor.rz.scp.css */
/* Vehicle make/model catalog (011, US1). Master–detail spacing for the models panel
   below the makes grid. Colors/tokens come from the global admin theme; only the
   detail header and the "selected make" affordance are scoped here. */

.catalog-detail[b-d7giwhb8nn] {
    margin-top: 22px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

.catalog-detail__head[b-d7giwhb8nn] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
}

.catalog-detail__title[b-d7giwhb8nn] {
    font-size: 15px;
    font-weight: 650;
    color: var(--text);
}

.catalog-detail__title strong[b-d7giwhb8nn] {
    font-weight: 800;
}

/* Highlight the "Modelos" action of the currently selected make. */
.icon-action.is-active[b-d7giwhb8nn] {
    color: var(--brand, #2f6fed);
    background: var(--brand-ghost, rgba(47, 111, 237, .12));
}
/* /Components/Pages/Reports/EjecutarReporte.razor.rz.scp.css */
/* Report generation screen (009-reports, US2/US3). Scoped styles only; the shared card,
   field, btn and data-table styles come from the global admin theme. */

.report-crumbs[b-1bn5wfljqg] {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 12.5px;
    color: var(--text-2);
    margin-bottom: 4px;
}

.report-crumbs a[b-1bn5wfljqg] {
    color: var(--text-2);
    text-decoration: none;
}

.report-crumbs a:hover[b-1bn5wfljqg] {
    color: var(--accent);
    text-decoration: underline;
}

.filter-card[b-1bn5wfljqg] {
    padding: 18px 20px 20px;
    margin-bottom: 18px;
}

.filter-grid[b-1bn5wfljqg] {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 4px 16px;
    margin-top: 12px;
}

.filter-card__actions[b-1bn5wfljqg] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    margin-top: 18px;
    padding-top: 16px;
    border-top: 1px solid var(--border);
}

.field__req[b-1bn5wfljqg] {
    color: var(--danger, #d64545);
    margin-left: 2px;
    font-weight: 700;
}

.report-result-meta[b-1bn5wfljqg] {
    display: flex;
    justify-content: flex-end;
    margin: 4px 2px 8px;
}

/* `.cell-num` / `.cell-num__text` USED TO LIVE HERE, and that was the whole bug: two
   Reports screens owned a utility the accounting grids also needed, so Mayor and Diario
   rendered their money flush LEFT with no way to fix it short of copying the rule a third
   time. It now lives in wwwroot/admin.css as a shared utility. Do not redefine it here. */
/* /Components/Pages/Reports/HistorialReportes.razor.rz.scp.css */
/* Report execution history (009-reports, US2). Scoped styles; the grid, badge and card
   styles come from the global admin theme. */

.report-crumbs[b-1wyjdgjjv3] {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 12.5px;
    color: var(--text-2);
    margin-bottom: 4px;
}

.report-crumbs a[b-1wyjdgjjv3] {
    color: var(--text-2);
    text-decoration: none;
}

.report-crumbs a:hover[b-1wyjdgjjv3] {
    color: var(--accent);
    text-decoration: underline;
}

.cell-name__sub[b-1wyjdgjjv3] {
    display: block;
    font-size: 11.5px;
    color: var(--text-2);
    font-family: monospace;
}

/* `.cell-num` / `.cell-num__text` moved to wwwroot/admin.css: it is a shared table utility,
   not this screen's. Keeping a scoped copy would give the site two definitions of the same
   rule. Do not redefine it here. */
/* /Components/Pages/Security/DiagnosticLog.razor.rz.scp.css */
/* Feature 014 / US1 — "Fallas del sistema". Only what the global admin theme does not
   already provide: the two button groups of the toolbar, and the clipping of the long
   technical values in the table.
   Every colour comes from a theme token, so light and dark are both covered. */

/* Toolbar button groups (quick ranges, and the "todo / solo fallas reales" switch).
   The buttons sit flush against each other so the pair reads as one control. */
.diag-group[b-w5c30m1hjr] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}

.diag-hint[b-w5c30m1hjr] {
    font-size: 12px;
    max-width: 320px;
    white-space: normal;
}

/* The table stays one line per row (that is what makes a long log scannable): the long
   technical values are clipped here and read whole in the detail dialog. */
.diag-clip[b-w5c30m1hjr] {
    display: inline-block;
    max-width: 260px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
}

.diag-clip--wide[b-w5c30m1hjr] {
    max-width: 420px;
}

.diag-mono[b-w5c30m1hjr] {
    font-family: ui-monospace, 'Cascadia Code', 'Consolas', monospace;
    font-size: 12px;
}

/* The technical module name next to its Spanish label: present so the column filter is
   discoverable, quiet so it does not compete with the label. */
.diag-raw[b-w5c30m1hjr] {
    font-size: 11px;
    opacity: .75;
}

/* A failure with no module was born outside the database — a fact, not a missing value. */
.diag-outside[b-w5c30m1hjr] {
    font-style: italic;
}

/* The read-only value blocks of the detail dialog moved to DiagnosticFailureDetail with the
   markup that uses them: Blazor scoped CSS only reaches the elements of its own component. */

/* ---- 014 / US5 (T051): the maintenance strip and its CSS MOVED OUT (T058) ----
   The purge markup now lives in DiagnosticMaintenance.razor, and Blazor scoped CSS only
   reaches the elements of its own component: the .diag-purge rules travelled with it, to
   DiagnosticMaintenance.razor.css. Nothing here styles them any more. */
/* /Components/Pages/Security/DiagnosticMaintenance.razor.rz.scp.css */
/* Feature 014 / US4 (T058) — "Mantenimiento del diagnóstico".

   Layout only, and NOT one line of new global CSS: the badges, the alerts, the table, the
   card and the three button variants all come from the site's design system, so light and
   dark are both already covered. Every colour here is a theme token (--text-2, --text-3,
   --warn-text, --border-soft...), which is the only way a new screen can be theme-safe
   without touching admin.css.

   ⚠️ Nothing declares a button variant. The dark theme remaps NEUTRAL buttons with
   `:root[data-theme="dark"] .btn:not(.btn--primary):not(.btn--danger)`, so any new variant
   would be flattened to the neutral fill in dark — the defect that was just fixed for
   .btn--danger / .btn--primary and must not be revived. */

/* ------------------------------------------------------ The switch table --- */

/* The permanent explanation: three facts that must be readable as a list, not as a
   paragraph — "se apaga solo", "tarda hasta N segundos" and "las fallas se registran
   igual" are the three things people get wrong about this screen. */
.tsw-how__list[b-xdpvokjivr] {
    margin: 8px 0 0;
    padding-left: 18px;
    font-weight: 500;
    line-height: 1.55;
}

.tsw-how__list li[b-xdpvokjivr] {
    margin-bottom: 6px;
}

.tsw-how__list li:last-child[b-xdpvokjivr] {
    margin-bottom: 0;
}

/* The delay note under the "ya quedó guardado" line: the same sentence at the exact moment
   it matters, quieter than the headline. */
.tsw-note[b-xdpvokjivr] {
    display: block;
    margin-top: 4px;
    font-weight: 600;
    opacity: .9;
}

/* Live count in the card head. It sits opposite the title, so it wraps under it on a
   narrow window instead of squeezing the title. */
.tsw-summary[b-xdpvokjivr] {
    font-size: 12.5px;
    font-weight: 600;
    color: var(--text-2);
    text-align: right;
}

/* The technical module name beside its Spanish label — present so the value used by the
   log's module filter is discoverable, quiet so it does not compete with the label. */
.tsw-raw[b-xdpvokjivr] {
    font-family: ui-monospace, 'Cascadia Code', 'Consolas', monospace;
    font-size: 11px;
    color: var(--text-3);
}

/* "Se apagó solo" carries a clock glyph instead of the plain dot of the other two badges:
   the third state is the one nobody expects, and the icon is what makes it read as
   different at a glance rather than as another shade of the same pill.
   ::deep because the glyph is rendered by <AppIcon>, a child component — the scope
   attribute never reaches another component's elements. */
.badge[b-xdpvokjivr]  .tsw-badge-icon {
    font-size: 14px;
}

/* The delay, as a fact about THIS process rather than a sentence about processes in
   general. Deliberately small: it is a footnote to the state, not a second state. */
.tsw-pending[b-xdpvokjivr] {
    display: flex;
    align-items: center;
    gap: 4px;
    margin-top: 5px;
    font-size: 11.5px;
    color: var(--text-3);
}

.tsw-pending[b-xdpvokjivr]  .tsw-pending__icon {
    font-size: 14px;
}

/* "quedan 3 h 12 min" / "se venció solo", under the expiry instant. */
.tsw-left[b-xdpvokjivr] {
    margin-top: 3px;
    font-size: 11.5px;
    color: var(--text-3);
}

.tsw-noperm[b-xdpvokjivr] {
    font-size: 12px;
}

/* Foot of the table: when this site last refreshed its own copy, and — for whoever can only
   read — which permission the buttons need. */
.tsw-foot[b-xdpvokjivr] {
    padding: 12px 20px 14px;
    border-top: 1px solid var(--border-soft);
    font-size: 12.5px;
    color: var(--text-3);
    line-height: 1.5;
}

.tsw-foot code[b-xdpvokjivr] {
    font-family: ui-monospace, 'Cascadia Code', 'Consolas', monospace;
    font-size: 11.5px;
}

/* ------------------------------------------- The purge strip (T051 / US5) ---
   Moved here verbatim from DiagnosticLog.razor.css together with the markup it styles:
   Blazor scoped CSS only reaches the elements of its own component, so the rules travel
   with the screen or they stop applying. */

.diag-purge[b-xdpvokjivr] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 18px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}

.diag-purge__body[b-xdpvokjivr] {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    flex: 1 1 520px;
}

.diag-purge__body[b-xdpvokjivr]  .diag-purge__icon {
    font-size: 22px;
    color: var(--warn-text);
    flex: none;
}

.diag-purge__title[b-xdpvokjivr] {
    font-size: 14px;
    font-weight: 800;
    margin-bottom: 4px;
}

.diag-purge__text[b-xdpvokjivr] {
    font-size: 13px;
    color: var(--text-2);
    line-height: 1.5;
    max-width: 780px;
}

.diag-purge__text--quiet[b-xdpvokjivr] {
    margin-top: 6px;
    font-size: 12.5px;
    color: var(--text-3);
}

.diag-purge__actions[b-xdpvokjivr] {
    display: flex;
    align-items: center;
    gap: 10px;
    flex: none;
}

/* Detail of the last pass: the counters BELOW the sentence, not inside it. */
.diag-purge__hint[b-xdpvokjivr] {
    display: block;
    margin-top: 4px;
    font-weight: 600;
    opacity: .9;
}

.diag-purge__result[b-xdpvokjivr] {
    margin-bottom: 16px;
}

.diag-purge__again[b-xdpvokjivr] {
    margin-top: 14px;
}

/* Body of the confirmation dialog. */
.diag-purge__p[b-xdpvokjivr] {
    font-size: 13.5px;
    color: var(--text-2);
    line-height: 1.55;
    margin: 0 0 10px;
}

.diag-purge__p--quiet[b-xdpvokjivr] {
    font-size: 12.5px;
    color: var(--text-3);
    margin-bottom: 0;
}

.diag-purge__list[b-xdpvokjivr] {
    font-size: 13.5px;
    color: var(--text-2);
    line-height: 1.55;
    margin: 0 0 10px;
    padding-left: 20px;
}

.diag-purge__list li[b-xdpvokjivr] {
    margin-bottom: 4px;
}
/* /Components/Pages/Security/LocalEntryStatusBadge.razor.rz.scp.css */
/* El indicador «entrada apagada» en la grilla (016-a1-parking-profile / T036).

   Mismo molde que LocationCompletenessBadge.razor.css (T023): dos renglones apilados, el
   veredicto arriba y el detalle abajo, para que la columna se lea en vertical de un vistazo.
   Todos los colores salen de las variables del tema (.badge--warn/.badge--off/.badge--ok, ya
   definidas en admin.css) — cero hex acá, claro y oscuro son UNA definición. */

.entry-status[b-nf8qfzud1m] {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
}

/* Angosta a propósito, igual que .completeness__why: el detalle acompaña al veredicto, no
   compite con el nombre del parqueo ni empuja la columna de acciones fuera de la pantalla.

   --text-2 y NO --text-3 (medido igual que en LocationCompletenessBadge.razor.css: --text-3 no
   llega a 4.5:1 en claro con este tamaño). Es contenido primario de la columna, no un adorno. */
.entry-status__why[b-nf8qfzud1m] {
    font-size: 11.5px;
    line-height: 1.35;
    color: var(--text-2);
    max-width: 220px;
    white-space: normal;
}
/* /Components/Pages/Security/LocationCompletenessBadge.razor.rz.scp.css */
/* El indicador «parqueo incompleto» (016-A1/T023 = 019/T023).

   Dos renglones apilados: el veredicto arriba, la causa abajo. La causa va en el mismo lugar
   siempre, así que la columna se lee en vertical de un vistazo — que es lo que hace falta cuando
   la página trae cien parqueos. Todos los colores salen de las variables del tema: claro y
   oscuro son UNA definición y no hay un solo hex acá. */

.completeness[b-s07rok6u02] {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
}

/* Angosta a propósito: la razón acompaña al veredicto, no compite con el nombre del parqueo ni
   empuja la columna de acciones fuera de la pantalla.

   --text-2 and NOT --text-3: measured, #94a3b8 on the card is 2.56:1, under the 4.5:1 AA floor,
   and 11.5px does not qualify as large text. --text-2 (#64748b) measures 4.76:1 on light and
   7.93:1 on dark, so both themes clear AA. This line is not secondary text: every row of the
   column reads "Incompleto" with the same dot, so WHAT is missing is the only thing that tells
   one row from another — it is the column's primary content. */
.completeness__why[b-s07rok6u02] {
    font-size: 11.5px;
    line-height: 1.35;
    color: var(--text-2);
    max-width: 190px;
    white-space: normal;
}
/* /Components/Pages/Security/LocationOwnerDialog.razor.rz.scp.css */
/* Dueño del parqueo (019 / T022).

   El cuadro responde tres cosas en este orden: quién es hoy, quién puede ser, y por qué se
   cambia. El orden es el de la decisión, no el del formulario. Todos los colores salen de las
   variables del tema, así que claro y oscuro son UNA definición. */

.owner-now[b-x1q67l9ts0] {
    border: 1px solid var(--border);
    border-radius: var(--r-card);
    padding: 14px 16px;
    margin-bottom: 18px;
}

.owner-now__label[b-x1q67l9ts0] {
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--text-3);
    margin-bottom: 8px;
}

.owner-now__name[b-x1q67l9ts0] {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 14.5px;
    font-weight: 700;
    color: var(--text);
}

.owner-pick__actions[b-x1q67l9ts0] {
    display: flex;
    gap: 8px;
    margin-bottom: 14px;
}

/* La lista de resultados es corta a propósito: un selector es para elegir, no para navegar.
   Con altura fija, el pie del cuadro —donde están «Asignar» y «Quitar»— no se va de la
   pantalla cuando la búsqueda trae muchos. */
.owner-list[b-x1q67l9ts0] {
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: 260px;
    overflow-y: auto;
    border: 1px solid var(--border);
    border-radius: var(--r-card);
    padding: 6px;
}

.owner-list__item[b-x1q67l9ts0] {
    display: flex;
    flex-direction: column;
    gap: 2px;
    width: 100%;
    text-align: left;
    padding: 9px 11px;
    border: 1px solid transparent;
    border-radius: var(--r-control);
    background: transparent;
    font-family: inherit;
    cursor: pointer;
    transition: background .12s, border-color .12s;
}

.owner-list__item:hover[b-x1q67l9ts0] {
    background: var(--side-hover);
}

.owner-list__item:focus-visible[b-x1q67l9ts0] {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
}

/* La fila elegida se marca con borde Y con fondo: solo con color no la distingue quien no
   distingue colores. */
.owner-list__item.is-picked[b-x1q67l9ts0] {
    border-color: var(--accent);
    background: var(--accent-soft);
}

.owner-list__name[b-x1q67l9ts0] {
    font-size: 13.5px;
    font-weight: 600;
    color: var(--text);
}

.owner-list__meta[b-x1q67l9ts0] {
    font-size: 12px;
    color: var(--text-3);
}

/* .input mide 40px de alto porque está hecho para campos de una línea; un textarea tiene que
   deshacer eso o rows="2" no hace nada. */
.owner-just[b-x1q67l9ts0] {
    height: auto;
    min-height: 60px;
    padding: 10px 12px;
    line-height: 1.5;
    resize: vertical;
}
/* /Components/Pages/Security/LocationProfileDialog.razor.rz.scp.css */
/* Ficha del parqueo (016-a1 / T020).

   TWO COLUMNS on purpose. The ficha has five blocks; stacked in one column they make a dialog
   twice as tall, so side by side is what keeps it readable at the width this site is used at
   (escritorio, DECR-014). Below 1000px it collapses to one column and the blocks keep their
   reading order: dónde está → cómo se llega → cómo es → contacto → horario.

   ⚠️ TWO COLUMNS IS NOT "NO SCROLL". This comment used to claim the whole ficha fits without
   scrolling; that was true of the WIDTH and false of the HEIGHT. The five blocks are asymmetric,
   and on a 900px-tall laptop the dialog does need to scroll. That is why the panel opts into
   .modal--scroll-body (admin.css): the body scrolls and the head and the foot stay, so the
   title and the "Cerrar" button never leave the screen together.

   Every colour is a theme variable, so light and dark are ONE definition and not two that
   drift. */

.ficha[b-q1ocmlr0br] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 18px;
    align-items: start;
}

.ficha__col[b-q1ocmlr0br] {
    display: flex;
    flex-direction: column;
    gap: 18px;
    min-width: 0;
}

.ficha__block[b-q1ocmlr0br] {
    border: 1px solid var(--border);
    border-radius: var(--r-card);
    padding: 16px 18px 14px;
    /* Transparent, not a colour of its own: the block sits ON the modal, and in both themes the
       hairline is what separates it. A second background here would have to be defined twice. */
    background: transparent;
}

/* Amenidades (016-a2 / T017). PLACEMENT ONLY — no colour, no border, no type: the block is the
   same .ficha__block as the other five and looks identical in both themes. What this adds is that
   it spans the WHOLE grid instead of sitting in one of the two columns, because the dual-list
   inside it is itself two panels and half a ficha cuts the long names ("Zona de carga y
   descarga") in half. 1 / -1 keeps working when the grid collapses to one column below 1000px. */
.ficha__block--wide[b-q1ocmlr0br] {
    grid-column: 1 / -1;
}

.ficha__title[b-q1ocmlr0br] {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 6px;
    font-size: 13.5px;
    font-weight: 700;
    color: var(--text);
}

.ficha__lead[b-q1ocmlr0br] {
    margin: 0 0 14px;
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--text-2);
}

/* Nota al PIE de un bloque, no una segunda bajada. Existe porque el bloque 7 abría con
   .ficha__lead y cerraba con .ficha__lead, y el párrafo final se leía como una entrada más.
   El color lo pone .text-muted (--text-2, 4.76:1 claro / 7.93:1 oscuro sobre la tarjeta):
   acá sólo va el tamaño y la separación.
   REGLA ÚNICA: .ficha__note estaba declarada DOS veces en este archivo. La primera pedía
   `margin-top: 16px` para separar el editor de matices del dual-list de arriba; ésta, doce
   líneas más abajo, usaba la forma corta `margin`, que reescribe los cuatro lados y por lo
   tanto anulaba aquélla sin que nada lo avisara -- el comentario de la primera explicaba una
   intención que el propio archivo pisaba. Se unifican acá, y el margen superior sube a los
   16px que la primera pedía, que es el valor que efectivamente se quería. */
.ficha__note[b-q1ocmlr0br] {
    margin: 16px 0 0;
    font-size: 12px;
    line-height: 1.5;
}

/* Segunda línea del estado vacío: la explicación de por qué la lista puede estar vacía va
   DENTRO de la caja de la respuesta y no en un aviso azul aparte más grande que ella.
   Hereda el color de .state (--text-2), así que sólo se la separa y se la achica. */
.state__note[b-q1ocmlr0br] {
    margin: 8px auto 0;
    max-width: 62ch;
    font-size: 12px;
    line-height: 1.5;
}

/* Cantón and distrito are two short fields that belong together: side by side they read as one
   answer, stacked they read as two unrelated questions. */
.ficha__row2[b-q1ocmlr0br] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
}

/* .input is 40px tall by design (it is built for one-line fields); a textarea has to undo that
   or rows="3" has no effect at all. */
.ficha__area[b-q1ocmlr0br] {
    height: auto;
    min-height: 76px;
    padding: 10px 12px;
    line-height: 1.5;
    resize: vertical;
}

/* What the pasted text was read as, before it is saved. Reads as data, not as a warning. */
.ficha__read[b-q1ocmlr0br] {
    display: flex;
    flex-direction: column;
    gap: 4px;
    margin-bottom: 12px;
    font-size: 12.5px;
}

.ficha__read .cell-id[b-q1ocmlr0br] {
    margin-right: 8px;
}

/* Amenidades DERIVADAS (016-a2 / T018).

   🔴 POR QUÉ ESTO NO REUSA .dual-list__item, QUE ES LO QUE MÁS SE LE PARECE: esa clase trae
   `cursor: pointer` y una regla de hover, y las dos afirman «esto se puede tocar». Acá NO se
   puede tocar NUNCA — no hay escritor, no hay nada que apagar—, así que heredar el gesto sería
   heredar una mentira. Tampoco se reusa `.dual-list__item:disabled` (opacity .55): un
   deshabilitado dice «ahora no», y además atenuar el texto lo baja del piso de contraste.

   ⛔ Y NO SE REUSA .role-chip, que también es una fila estática: fija `background: #fff` a
   mano y NO tiene contraparte oscura, así que en tema oscuro sería una isla blanca. (Eso es un
   defecto vivo de Users.razor, anotado acá porque se midió al buscar qué reusar; no se toca
   desde esta tarea.)

   ⭐ LO QUE SÍ SE REUSA: la CHAPA del contenedor es la misma que .dual-list__panel —hairline
   var(--border) sobre var(--card-bg)—, a propósito. La sección tiene que leerse como PARIENTE
   de los dos paneles de arriba y a la vez estar claramente fuera de ellos: mismo material,
   otro lugar. Todo color sale de tokens, así que claro y oscuro son UNA definición. */
.derived[b-q1ocmlr0br] {
    list-style: none;
    margin: 0;
    padding: 6px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    border: 1px solid var(--border);
    border-radius: var(--r-control);
    background: var(--card-bg);
}

/* Sin hover, sin cursor y sin foco: no es un control, es una afirmación. */
.derived__item[b-q1ocmlr0br] {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border-radius: 8px;
}

.derived__icon[b-q1ocmlr0br] {
    flex: none;
    display: inline-flex;
    color: var(--text-2);
}

/* ::deep — el glifo lo dibuja <AppIcon>, que es otro componente: sin ::deep el CSS con alcance
   no lo alcanza. .msi no fija tamaño propio, así que hereda del padre si nadie se lo dice. */
.derived__icon[b-q1ocmlr0br]  .msi {
    font-size: 20px;
}

.derived__body[b-q1ocmlr0br] {
    flex: 1;
    min-width: 0;
}

/* --text y NO --accent: el azul del acento es lo que en este sitio significa «clickeable»
   (.dual-list__item-code lo usa justamente para los ítems que sí se mueven). Acá sería una
   invitación falsa. Sobre --card-bg mide 16,30:1 en claro y 12,76:1 en oscuro. */
.derived__name[b-q1ocmlr0br] {
    display: block;
    font-weight: 700;
    font-size: 12.5px;
    color: var(--text);
}

/* --text-2 y NO --text-3, medido sobre --card-bg, que es la superficie real de esta lista:
   --text-2 da 4,76:1 en claro y 7,93:1 en oscuro; --text-3 daría 2,56:1 / 4,53:1, bajo el piso
   de 4,5:1. Es el mismo par que ya eligió .dual-list__empty por la misma razón. */
.derived__meta[b-q1ocmlr0br] {
    display: block;
    font-size: 11.5px;
    color: var(--text-2);
    margin-top: 1px;
}

/* LA MARCA DE «AUTOMÁTICA», Y SU FORMA ES UNA DECISIÓN MEDIDA.
   ⛔ No usa .badge--info ni .badge--ok: los badges del sitio llevan el color como parte del
   mensaje y, medidos, varios quedan bajo 4,5:1 (--accent sobre --accent-soft da 4,19:1 en
   oscuro; --ok-text sobre --ok-bg, 3,00:1 en claro). Un aviso que se apoya en un color que no
   se lee bien no avisa.
   ⭐ Por eso esta chapa NO lleva color propio: es un contorno hairline con tinta --text-2 —el
   mismo par medido dos reglas más arriba— y dice lo que significa con ÍCONO Y PALABRA. El
   candado va EN LUGAR del .badge__dot, nunca además: un punto de color es él mismo una marca
   de puro color, que es exactamente lo que WCAG 1.4.1 no acepta. */
.derived__flag[b-q1ocmlr0br] {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    border: 1px solid var(--border);
    border-radius: var(--r-pill);
    font-size: 11px;
    font-weight: 700;
    color: var(--text-2);
    white-space: nowrap;
}

.derived__flag[b-q1ocmlr0br]  .msi {
    font-size: 14px;
}

/* La hora de la lectura a la izquierda y el botón a la derecha: el texto explica por qué el
   botón existe, así que se leen juntos. Envuelve en pantallas angostas en vez de apretarse. */
.derived__foot[b-q1ocmlr0br] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 12px;
    font-size: 12px;
    line-height: 1.5;
}

/* El apagado virtual de la entrada (T033) se mudó a la pestaña «Horario»
   (LocationSettingsHoursTab.razor.css tiene su propia .hours-tab__shutdown-actions,
   DECR-403 R6/R8, 016-a1/T058 pieza 3): .ficha__shutdown-actions ya no se usa acá. */

/* El mapa VISUAL de Google (016-a1/T057, DECR-402). Altura FIJA y no un aspect-ratio: Google Maps
   mide el contenedor una sola vez al construirse (google.maps.Map) y, si en ese instante el div
   todavía mide 0px de alto -- lo que pasa con un aspect-ratio que depende del ancho final del
   layout de dos columnas -- el mapa se pinta colapsado y sólo se arregla con un resize manual.
   var(--r-card)/var(--border), igual que .ficha__block, para que el mapa se lea como parte de la
   ficha y no como un iframe pegado encima. El color de adentro lo pone Google: no hay token de
   este sitio que se le aplique, y no hace falta -- el mapa se ve igual en los dos temas del sitio
   porque es contenido de otro origen, no un componente del sistema de diseño. */
.ficha__map[b-q1ocmlr0br] {
    width: 100%;
    height: 260px;
    border: 1px solid var(--border);
    border-radius: var(--r-card);
    overflow: hidden;
    margin-bottom: 10px;
}

/* El campo de texto queda plegado por defecto cuando el mapa está configurado (DECR-402 R4: "el
   campo queda como alternativa", no el control principal). <details> es HTML nativo -- foco y
   teclado (Enter/Espacio abren y cierran <summary>) sin escribir una línea de JS para esto. */
.ficha__map-fallback[b-q1ocmlr0br] {
    margin-top: 4px;
}

.ficha__map-fallback summary[b-q1ocmlr0br] {
    cursor: pointer;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-2);
    padding: 4px 0;
}

.ficha__map-fallback[open] summary[b-q1ocmlr0br] {
    margin-bottom: 8px;
}

/* La foto del parqueo (016-a1/T059, DECR-418). Mismo var(--r-card)/var(--border) que .ficha__map
   y .ficha__block, para que la vista previa se lea como parte de la ficha. max-width: 100% evita
   que una foto de 1 MB, que puede llegar con dimensiones grandes, se salga de la columna. */
.ficha__photo-preview[b-q1ocmlr0br] {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 10px;
}

.ficha__photo-img[b-q1ocmlr0br] {
    max-width: 100%;
    max-height: 220px;
    width: auto;
    border: 1px solid var(--border);
    border-radius: var(--r-card);
    object-fit: contain;
    background: var(--card-bg);
}

/* Right-aligned y con gap, mismo criterio que .ficha__shutdown-actions -- y misma razón para no
   reusar ESA clase: "quitar foto" es una acción propia de este bloque, no del apagado de la
   entrada, y el CSS aislado de Blazor no cruza de un bloque a otro por compartir un nombre. */
.ficha__photo-actions[b-q1ocmlr0br] {
    display: flex;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 4px;
}

@media (max-width: 1000px) {
    .ficha[b-q1ocmlr0br] {
        grid-template-columns: 1fr;
    }

    .ficha__row2[b-q1ocmlr0br] {
        grid-template-columns: 1fr;
    }
}
/* /Components/Pages/Security/Locations.razor.rz.scp.css */
/* 023/T065 — la insignia «Sin tarifa de respaldo» se apila DEBAJO de LocalEntryStatusBadge,
   en la misma celda-estado de la columna «Entrada»: no es una columna aparte.

   Mismo molde que .entry-status (LocalEntryStatusBadge.razor.css): apilado vertical, alineado
   a la izquierda, con el mismo espaciado — pero definido ACÁ porque ese archivo es CSS con
   ámbito de componente (Blazor scoped CSS) y no llega a un elemento que esta página dibuja
   directamente. Cero color literal: .badge/.badge--warn/.badge__dot ya salen de admin.css. */
.fallback-warning-stack[b-g5thx6mqeg] {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
}

/* 023/T065 — REVISIÓN VISUAL 2026-09-13: la explicación del rechazo vivía sólo en el `title`
   de la insignia (inalcanzable por teclado, sin nodo de accesibilidad propio). Mismo molde que
   .entry-status__why (LocalEntryStatusBadge.razor.css): texto siempre visible debajo de la
   insignia, nunca dependiente de hover. Definido ACÁ, no ahí, por la misma razón que
   .fallback-warning-stack: ese archivo es CSS con ámbito de componente y no llega a un span que
   esta página dibuja directamente. Mismos valores exactos que .entry-status__why (mismo
   contraste ya medido, mismo max-width) para que el ancho de celda no crezca más que con la
   explicación de "Entrada apagada": el texto envuelve en más líneas, no en más columna. */
.fallback-warning__why[b-g5thx6mqeg] {
    font-size: 11.5px;
    line-height: 1.35;
    color: var(--text-2);
    max-width: 220px;
    white-space: normal;
}
/* /Components/Pages/Security/LocationSettings.razor.rz.scp.css */
/* Feature 015 / US3 (T019) — per-parking settings, sibling screen of Mantenimiento Parqueos.

   Everything here is built on the design tokens of app.css, so both themes are covered by
   construction: no literal colour appears below. The row itself reuses the GLOBAL .setting-row /
   .switch pattern of "Configuración del sistema" — only the two pieces this screen adds (the
   trail and the identity summary) live here, plus the read-only variant of the row's editor. */

/* ------------------------------------------------------------ Breadcrumb --- */
.crumbs[b-qsrf6co9po] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    font-size: 12px;
    color: var(--text-3);
    margin-bottom: 6px;
}

.crumbs a[b-qsrf6co9po] {
    color: var(--text-2);
    text-decoration: none;
}

.crumbs a:hover[b-qsrf6co9po] {
    color: var(--accent);
    text-decoration: underline;
}

.crumbs a:focus-visible[b-qsrf6co9po] {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-radius: 4px;
}

.crumbs__sep[b-qsrf6co9po] {
    color: var(--text-3);
}

.crumbs__current[b-qsrf6co9po] {
    color: var(--text);
    font-weight: 600;
    /* Long parking-lot names must not push the trail into a second screen width. */
    max-width: 46ch;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ------------------------------------------------------- Identity summary --- */
/* Read-only, and deliberately the first thing under the title: what is decided below touches
   money and legal regime, so which parking lot this is has to be unmistakable before anything
   is touched. */
.loc-id-card[b-qsrf6co9po] {
    padding: var(--card-pad);
    margin-bottom: 16px;
}

.loc-id-card__head[b-qsrf6co9po] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 10px;
    margin-bottom: 14px;
}

.loc-id-card__name[b-qsrf6co9po] {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 18px;
    font-weight: 700;
    color: var(--text);
    min-width: 0;
}

/* ::deep — the glyph is rendered by the AppIcon child component, so it does not carry this
   component's scope attribute. */
.loc-id-card__name[b-qsrf6co9po]  .msi {
    font-size: 22px;
    color: var(--text-3);
    flex: none;
}

.loc-id-card__note[b-qsrf6co9po] {
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid var(--border);
    font-size: 12.5px;
    color: var(--text-2);
}

/* ---------------------------------------------------- The type, and its trigger --- */
/* 022/T005 — the ONE editable value inside the otherwise read-only identity card (see the
   markup comment where this class is used). Row and not stacked, because the value alone is
   short ("Parqueo público") and stacking would leave the button floating with nothing to align
   against on a wide desktop screen. */
.loc-id-card__type[b-qsrf6co9po] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
}

/* Shrinks the shared .btn (40px tall, built for a toolbar) down to something that reads as a
   small inline trigger next to a one-line value instead of a second toolbar action. */
.loc-id-card__type-btn[b-qsrf6co9po] {
    height: 28px;
    min-height: 28px;
    padding: 0 10px;
    font-size: 12px;
}

.loc-id-card__type-btn[b-qsrf6co9po]  .msi {
    font-size: 15px;
}

/* --------------------------------------------- Row editor, read-only mode --- */
/* Read permission without write permission: the row STAYS and the control becomes text. A switch
   the server is going to refuse reads as a broken system instead of as a restriction. */
.setting-row__readonly[b-qsrf6co9po] {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 6px;
    max-width: 320px;
}

.setting-row__noperm[b-qsrf6co9po] {
    font-size: 11.5px;
    color: var(--text-3);
    text-align: right;
    line-height: 1.5;
}

.setting-row__noperm code[b-qsrf6co9po] {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 11px;
    color: var(--text-2);
}

.setting-row__readonly-state[b-qsrf6co9po] {
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
    justify-content: flex-end;
}

/* --------------------------------------- Switches that name their OPTION --- */
/* DECR-071 / DECR-077 — the text beside these two switches is the name of the option in force
   ("Nosotros liquidamos" / "El parqueo liquida"), not "Activado/Desactivado". The global
   .switch__text reserves 76px, which is enough for a boolean and not for these: without a
   floor the whole editor column jumps sideways every time the switch is flipped, because the
   two names are of different length. nowrap keeps each one on a single line. */
.switch--named .switch__text[b-qsrf6co9po] {
    min-width: 160px;
    white-space: nowrap;
}

/* The "En revisión" flag sits UNDER the state, right-aligned with it, so the risk stays
   signalled for somebody who never read the warning paragraph. Stacked and not inline because
   the option names are long: beside the control the badge fell off its line and dangled. The
   min-width above is what keeps the switch from sliding sideways when the flag appears. */
.setting-row__editor-stack[b-qsrf6co9po] {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 8px;
}

/* ------------------------------------------------ Commission editor --- */
/* DECR-070 / DECR-108 R1 (018, T012) — the only row of this screen that is not a switch: a mode
   and a value that are meaningless apart. Laid out as one line — mode, number, unit, Guardar —
   with the hint underneath, so the unit is READ BEFORE the button is reached. Colours come from
   the tokens of app.css, so both themes are covered by construction. */
.commission-editor[b-qsrf6co9po] {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 6px;
}

.commission-editor__fields[b-qsrf6co9po] {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 8px;
}

.commission-editor__mode[b-qsrf6co9po] {
    width: 190px;
}

/* Right-aligned, like every amount in the site's tables: the digits line up with the unit. */
.commission-editor__value[b-qsrf6co9po] {
    width: 110px;
    text-align: right;
}

/* The floor is what keeps "Guardar" from jumping sideways when the mode changes: "% de cada
   cobro" and "colones por cobro" are of different length. */
.commission-editor__unit[b-qsrf6co9po] {
    font-size: 12.5px;
    color: var(--text-2);
    white-space: nowrap;
    min-width: 118px;
}

/* DECR-120 — "Se calcula sobre", the visible label of the base. The other two controls carry
   only an aria-label because a percentage beside a "%" needs no caption; this one does: read
   alone, a list of two figures does not say what is being decided. */
.commission-editor__base-label[b-qsrf6co9po] {
    font-size: 12.5px;
    color: var(--text-2);
    white-space: nowrap;
}

/* Wide enough for the longer of the two options ON ONE LINE, arrow included: a base clipped to
   "…IVA incluid" is exactly the ambiguity this control exists to remove. Measured, not guessed —
   the long option is 260px of text at 13.5px Manrope, plus the field's own padding and the arrow.
   Fixed and not auto: without the floor the whole second line — and "Guardar" with it — slides
   sideways every time the base is changed. */
.commission-editor__base[b-qsrf6co9po] {
    width: 330px;
}

/* Prints the number that is actually going to be stored — the ÷100 is never a secret.
   --text-2 and NOT --text-3: measured, #94a3b8 on the card is 2.56:1, under the 4.5:1 AA floor,
   and this line is the one sentence that stops "10" from being read as "0,100000" right before
   money is agreed. It is not metadata like a timestamp, so it does not get the metadata ink. */
.commission-editor__hint[b-qsrf6co9po] {
    font-size: 11.5px;
    color: var(--text-2);
    text-align: right;
    max-width: 380px;
}

/* DECR-120 — shown ONLY under "Monto fijo", where the base multiplies nothing. The control stays
   live (a term is recorded in one write, never in two), so this is what keeps it from reading as
   a choice that moves money today.

   Hint and note now share --text-2 because both are below the AA floor at --text-3, so the ink
   can no longer carry the difference between them. It is carried by SIZE + WEIGHT (12px/500 vs
   11.5px/400) and, above all, by PLACE: the note was moved up against the base control it
   corrects, while the hint stays under the whole editor confirming what gets stored. Weight and
   not a stronger colour, because --text is the ink of the row's own labels and the note would
   start out-shouting them. */
.commission-editor__note[b-qsrf6co9po] {
    font-size: 12px;
    font-weight: 500;
    color: var(--text-2);
    text-align: right;
    max-width: 380px;
    line-height: 1.5;
}

/* ------------------------------------------------------ Type-change dialog --- */
/* 022/T005 — the mandatory reason box inside "Cambiar tipo de parqueo". .input alone is a fixed
   40px meant for one-line fields; a <textarea> needs its height freed and its own padding, same
   fix LocationProfileDialog.razor.css already applies to its own reason box (.ficha__area) —
   duplicated here rather than shared because Blazor's CSS isolation scopes each .razor.css file
   to its own component, so a class name repeated in two files styles nothing across the pair. */
.type-dialog__area[b-qsrf6co9po] {
    height: auto;
    min-height: 76px;
    padding: 10px 12px;
    line-height: 1.5;
    resize: vertical;
}

/* ---------------------------------------------- Standing legal warning --- */
/* DECR-077 — ALWAYS on screen, not only once the option under review is picked, and between the
   description and the control so it is read before anything is touched. It lives inside the
   left column of the row, which is what puts it ahead of the switch in reading order. Colours
   come from .alert--warn (admin.css), so both themes are covered by construction. */
.setting-row__legal[b-qsrf6co9po] {
    margin-top: 10px;
    margin-bottom: 8px;
    /* Legal prose is long; on a wide desktop an unbounded line would run the width of the card
       and become hard to track back. */
    max-width: 78ch;
    font-size: 12.5px;
    line-height: 1.55;
    align-items: flex-start;
}

/* The stroke of the warning glyph must not be dragged down by the paragraph's line-height. */
.setting-row__legal[b-qsrf6co9po]  .msi {
    margin-top: 1px;
}

/* The staff site is used on wide desktop screens, but the three widths are covered: below the
   tablet breakpoint the editor drops under its label instead of squeezing the description. */
@media (max-width: 720px) {
    .setting-row__readonly[b-qsrf6co9po] {
        align-items: flex-start;
        max-width: none;
    }

    .setting-row__readonly-state[b-qsrf6co9po] {
        justify-content: flex-start;
    }

    .setting-row__noperm[b-qsrf6co9po] {
        text-align: left;
    }

    .switch--named .switch__text[b-qsrf6co9po] {
        min-width: 0;
    }

    .commission-editor[b-qsrf6co9po] {
        align-items: flex-start;
    }

    .commission-editor__fields[b-qsrf6co9po] {
        justify-content: flex-start;
    }

    .commission-editor__hint[b-qsrf6co9po],
    .commission-editor__note[b-qsrf6co9po] {
        text-align: left;
    }

    /* Below this width the fixed select would push "Guardar" off the card. */
    .commission-editor__base[b-qsrf6co9po] {
        width: 100%;
        max-width: 330px;
    }
}
/* /Components/Pages/Security/LocationSettingsTabs/LocationSettingsHoursTab.razor.rz.scp.css */
/* Pestaña "Horario" (016-a1/T058, DECR-403 R6/R8, pieza 3 de 6).

   El CSS de Blazor es AISLADO POR COMPONENTE: no cruza de Horario.razor.css ni de
   LocationProfileDialog.razor.css a este archivo, aunque el markup que se mudó acá sea el
   mismo. Estas reglas repiten, con nombres propios de este componente (prefijo hours-tab__),
   sólo lo que esas dos pantallas tenían para ese mismo markup — no es un diseño nuevo. Todo
   color sale de tokens, así que claro y oscuro son UNA definición. */

.hours-tab[b-um9g2kbwqq] {
    display: grid;
    grid-template-columns: minmax(0, 1.65fr) minmax(320px, 1fr);
    gap: 18px;
    align-items: start;
}

.hours-tab__block[b-um9g2kbwqq] {
    min-width: 0;
}

/* El apagado de la entrada es un tercer bloque, distinto de los dos de arriba, y ocupa el
   ancho completo debajo de ellos en vez de competir por una de las dos columnas (mismo criterio
   que .ficha__block--wide / .parking-tab__block--wide en sus componentes). */
.hours-tab__block--wide[b-um9g2kbwqq] {
    grid-column: 1 / -1;
}

.hours-tab__lead[b-um9g2kbwqq] {
    margin: 0 0 14px;
    font-size: 12.5px;
    line-height: 1.5;
}

/* Notas de contenido dentro de un bloque —qué pasa si no configurás, qué significa apagar el
   corte—, no pie de página: por eso llevan .text-muted (--text-2) en el markup y acá sólo el
   tamaño y la separación. */
.hours-tab__hint[b-um9g2kbwqq] {
    margin: 6px 0 14px;
    font-size: 12px;
    line-height: 1.55;
}

/* Nota al PIE de un bloque (mismo criterio que .ficha__note / .parking-tab__note en sus
   componentes): el bloque de la entrada abre con .hours-tab__lead y cierra con un párrafo que
   explica la asimetría de los dos botones; sin esta clase se leería como una entrada más. */
.hours-tab__note[b-um9g2kbwqq] {
    margin: 16px 0 0;
    font-size: 12px;
    line-height: 1.5;
}

.hours-tab__bulk[b-um9g2kbwqq] {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin-bottom: 14px;
}

.hours-tab__detail[b-um9g2kbwqq] {
    margin-bottom: 16px;
}

/* El campo de la hora de corte es UN dato: a todo el ancho de la tarjeta se lee como si esperara
   una frase. */
.hours-tab__time[b-um9g2kbwqq] {
    max-width: 160px;
}

.hours-tab__switch[b-um9g2kbwqq] {
    margin-bottom: 2px;
}

/* .switch__text reserva 76px, que alcanza para «Activado» y no para una frase. */
.hours-tab__switch-text[b-um9g2kbwqq] {
    min-width: 0;
}

/* .input mide 40px de alto por diseño (es para campos de una línea); un textarea tiene que
   deshacerlo o rows="2" no hace nada. */
.hours-tab__area[b-um9g2kbwqq] {
    height: auto;
    min-height: 62px;
    padding: 10px 12px;
    line-height: 1.5;
    resize: vertical;
}

/* El apagado de la entrada (T033). Right-aligned y con gap, mismo criterio que
   .ficha__shutdown-actions -- esa clase no cruza a este archivo (CSS aislado de Blazor), así
   que este bloque, que dibuja DOS botones con DOS estados de error en vez de uno, necesita su
   propia regla en vez de reusar el nombre. */
.hours-tab__shutdown-actions[b-um9g2kbwqq] {
    display: flex;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 4px;
}

/* ------------------------------------------------------------- La semana --- */

.hours-tab__week[b-um9g2kbwqq] {
    border: 1px solid var(--border);
    border-radius: var(--r-card);
    overflow: hidden;
    margin-bottom: 12px;
}

.hours-tab__week-head[b-um9g2kbwqq],
.hours-tab__week-row[b-um9g2kbwqq] {
    display: grid;
    grid-template-columns: 108px 190px 116px 116px minmax(0, 1fr);
    gap: 10px;
    align-items: center;
    padding: 8px 12px;
}

.hours-tab__week-head[b-um9g2kbwqq] {
    font-size: 11.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .03em;
    color: var(--text-2);
    background: var(--border-softer, transparent);
}

.hours-tab__week-row[b-um9g2kbwqq] {
    border-top: 1px solid var(--border);
}

.hours-tab__week-day[b-um9g2kbwqq] {
    font-size: 13px;
    font-weight: 700;
    color: var(--text);
    margin: 0;
}

/* El hueco de las horas cuando el día es cerrado o de 24 horas. Marca el lugar sin fingir que
   hay un campo deshabilitado: no hay nada que escribir ahí. */
.hours-tab__week-na[b-um9g2kbwqq] {
    color: var(--text-3);
    text-align: center;
    font-size: 13px;
}

.hours-tab__week-read[b-um9g2kbwqq] {
    font-size: 12.5px;
    line-height: 1.45;
    color: var(--text-2);
}

@media (max-width: 1200px) {
    .hours-tab[b-um9g2kbwqq] {
        grid-template-columns: 1fr;
    }
}

@media (max-width: 900px) {
    .hours-tab__week-head[b-um9g2kbwqq] {
        display: none;
    }

    .hours-tab__week-row[b-um9g2kbwqq] {
        grid-template-columns: 1fr 1fr;
        row-gap: 8px;
    }

    .hours-tab__week-day[b-um9g2kbwqq] {
        grid-column: 1 / -1;
    }

    .hours-tab__week-read[b-um9g2kbwqq] {
        grid-column: 1 / -1;
    }

    .hours-tab__week-na[b-um9g2kbwqq] {
        display: none;
    }
}
/* /Components/Pages/Security/LocationSettingsTabs/LocationSettingsMunicipalFineTab.razor.rz.scp.css */
/* 016-a1/T058e — pestaña «Multa municipal». Prefijo fine-tab__ para no chocar con el resto del
   shell (molde de LocationSettingsSpacesTab.razor.css). */

/* Lo que está vigente, antes del campo de edición. Se lee como dato, no como advertencia —
   mismo criterio que .ficha__read en LocationProfileDialog.razor.css (bloque de origen). */
.fine-tab__read[b-dwfvx4k2wi] {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 12.5px;
}

.fine-tab__read .cell-id[b-dwfvx4k2wi] {
    margin-right: 8px;
}
/* /Components/Pages/Security/LocationSettingsTabs/LocationSettingsParkingTab.razor.rz.scp.css */
/* Pestaña "Parqueo" (016-a1/T058, DECR-403 R4/R8, pieza 2 de 6).

   El CSS de Blazor es AISLADO POR COMPONENTE: no cruza de LocationProfileDialog.razor.css a
   este archivo aunque el markup que se mudó acá sea el mismo. Estas reglas repiten, con nombres
   propios de este componente, sólo lo que "Ficha del parqueo" tenía para ese mismo markup — no
   son un diseño nuevo. Todo color sale de tokens, así que claro y oscuro son UNA definición. */

.parking-tab__block[b-89lvu24asc] {
    margin-bottom: 16px;
}

/* ---- Fila "Tipo de parqueo": mismas dos clases que LocationSettings.razor.css define para
   TODAS las filas de sólo-lectura de "Ajustes del parqueo" (.setting-row / .setting-row__info /
   etc. son globales en admin.css; estas dos NO lo son). Este componente tiene su PROPIO scope
   de CSS aislado (por tener su propio .razor.css), así que ya no hereda el del cascarón — se
   repiten acá con los mismos valores, no es un diseño nuevo. ---- */
.setting-row__readonly[b-89lvu24asc] {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 6px;
    max-width: 320px;
}

.setting-row__noperm[b-89lvu24asc] {
    font-size: 11.5px;
    color: var(--text-3);
    text-align: right;
    line-height: 1.5;
}

.setting-row__noperm code[b-89lvu24asc] {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 11px;
    color: var(--text-2);
}

@media (max-width: 720px) {
    .setting-row__readonly[b-89lvu24asc] {
        align-items: flex-start;
        max-width: none;
    }

    .setting-row__noperm[b-89lvu24asc] {
        text-align: left;
    }
}

.parking-tab__block--wide[b-89lvu24asc] {
    /* Nombre heredado del que traía la ficha (.ficha__block--wide): el dual-list ya son dos
       paneles y una columna angosta corta los nombres largos a la mitad. Esta pestaña es de
       una sola columna, así que acá sólo documenta la intención — no cambia el ancho. */
}

.parking-tab__lead[b-89lvu24asc] {
    margin: 0 0 14px;
    font-size: 12.5px;
    line-height: 1.5;
}

/* Segunda línea del estado vacío de las amenidades automáticas: la explicación de por qué la
   lista puede estar vacía va DENTRO de la caja de la respuesta (mismo criterio que .state__note
   traía en LocationProfileDialog.razor.css). Hereda el color de .state (--text-2). */
.parking-tab__state-note[b-89lvu24asc] {
    margin: 8px auto 0;
    max-width: 62ch;
    font-size: 12px;
    line-height: 1.5;
}

/* .input mide 40px de alto porque es para campos de una línea; la descripción y el motivo del
   cambio de tipo son multilínea (mismo criterio que .ficha__area / .owner-just / .hours__area). */
.parking-tab__area[b-89lvu24asc] {
    height: auto;
    min-height: 76px;
    padding: 10px 12px;
    line-height: 1.5;
    resize: vertical;
}

/* Nota al PIE de un bloque, no una segunda bajada (mismo criterio que .ficha__note). */
.parking-tab__note[b-89lvu24asc] {
    margin: 16px 0 0;
    font-size: 12px;
    line-height: 1.5;
}

/* ---- Amenidades automáticas: mismo tratamiento que .derived* traía en LocationProfileDialog.
   Sin hover, sin cursor y sin foco: no es un control, es una afirmación (no hay escritor). ---- */
.parking-tab__derived[b-89lvu24asc] {
    list-style: none;
    margin: 0;
    padding: 6px;
    display: flex;
    flex-direction: column;
    gap: 2px;
    border: 1px solid var(--border);
    border-radius: var(--r-control);
    background: var(--card-bg);
}

.parking-tab__derived-item[b-89lvu24asc] {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 10px;
    border-radius: 8px;
}

.parking-tab__derived-icon[b-89lvu24asc] {
    flex: none;
    display: inline-flex;
    color: var(--text-2);
}

.parking-tab__derived-icon[b-89lvu24asc]  .msi {
    font-size: 20px;
}

.parking-tab__derived-body[b-89lvu24asc] {
    flex: 1;
    min-width: 0;
}

.parking-tab__derived-name[b-89lvu24asc] {
    display: block;
    font-weight: 700;
    font-size: 12.5px;
    color: var(--text);
}

.parking-tab__derived-meta[b-89lvu24asc] {
    display: block;
    font-size: 11.5px;
    color: var(--text-2);
    margin-top: 1px;
}

/* Contorno hairline con tinta --text-2, medido en LocationProfileDialog.razor.css como el par
   que cumple 4,5:1 en los dos temas — nunca un badge de color propio (WCAG 1.4.1). */
.parking-tab__derived-flag[b-89lvu24asc] {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    border: 1px solid var(--border);
    border-radius: var(--r-pill);
    font-size: 11px;
    font-weight: 700;
    color: var(--text-2);
    white-space: nowrap;
}

.parking-tab__derived-flag[b-89lvu24asc]  .msi {
    font-size: 14px;
}

.parking-tab__derived-foot[b-89lvu24asc] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 12px;
    font-size: 12px;
    line-height: 1.5;
}
/* /Components/Pages/Security/LocationSettingsTabs/LocationSettingsSpacesTab.razor.rz.scp.css */
/* Pestaña "Espacios" (016-a1/T058d, DECR-403 R6/R8, pieza 4 de 6).

   El CSS de Blazor es AISLADO POR COMPONENTE (mismo criterio que hours-tab.razor.css): estas
   reglas repiten, con nombres propios de este componente (prefijo spaces-tab__), lo que las
   pantallas sueltas mudadas ya tenían para ese mismo markup. Todo color sale de tokens, así que
   claro y oscuro son UNA definición.

   A diferencia de "Horario" (dos columnas), acá los tres bloques van en UNA sola columna: cada
   uno trae su propia grilla ancha (PagedGrid) que no cabría partida en dos columnas de escritorio
   sin volverse angosta. */

.spaces-tab[b-zshrtlo16d] {
    display: flex;
    flex-direction: column;
    gap: 18px;
}

.spaces-tab__block[b-zshrtlo16d] {
    min-width: 0;
}

.spaces-tab__lead[b-zshrtlo16d] {
    margin: 0 0 14px;
    font-size: 12.5px;
    line-height: 1.5;
}
/* /Components/Pages/Security/LocationSettingsTabs/LocationSpotsPanel.razor.rz.scp.css */
/* Bloque «Características» del diálogo de EDICIÓN de la plaza (016-a2-amenities, slice 4, T316),
   mudado desde Plazas.razor.css (016-a1/T058d). El CSS de Blazor es AISLADO POR COMPONENTE: no
   cruza de Plazas.razor.css a este archivo aunque el markup mudado sea el mismo, así que estas
   reglas se repiten acá, con el mismo nombre de clase (no hay colisión: el scope de Blazor las
   distingue). El dual-list en sí (.dual-list / .dual-list__panel / ...) sigue siendo global
   (admin.css). */

.spot-features[b-3pkk77lzyh] {
    margin-top: 20px;
    padding-top: 16px;
    border-top: 1px solid var(--border-soft);
}

.spot-features__title[b-3pkk77lzyh] {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 6px;
    font-size: 13.5px;
    font-weight: 700;
    color: var(--text);
}

.spot-features__lead[b-3pkk77lzyh] {
    margin: 0 0 14px;
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--text-2);
}

/* Reserva el alto de una fila de .alert (016-a2/T316, ux-reviewer): vacío, ocupa lo mismo que
   con el aviso adentro, así el dual-list y el resto del diálogo no saltan ~35px cuando el clic
   dispara el mensaje de resultado. */
.spot-features__feedback[b-3pkk77lzyh] {
    min-height: 44px;
    margin-bottom: 16px;
}

.spot-features__feedback .alert[b-3pkk77lzyh] {
    margin-bottom: 0;
}
/* /Components/Pages/Security/NotificationTemplates.razor.rz.scp.css */
/* Textos de los avisos (025 / T042). Solo lo que el sistema de diseño no cubre: el alto del
   textarea, la fila elegida de la grilla, y la retícula de dos columnas del editor. Todo lo demás
   —.card, .data-table, .badge, .alert, .field, .input, .dual-list__panel— sale de admin.css sin
   una sola regla nueva. Colores por token: los dos temas siguen solos. */

.tpl__lead[b-qf1shtr8hv] {
    margin: 0;
    padding: 0 20px 16px;
    font-size: 12.5px;
    color: var(--text-2);
}

/* La fila abierta tiene que quedar visible mientras se mira el editor de abajo, o se pierde de
   vista cuál se está editando. Barra a la izquierda además del fondo: el color solo no alcanza
   para quien no lo distingue. */
.tpl__row--on > td[b-qf1shtr8hv] {
    background: var(--accent-soft);
}

.tpl__row--on > td:first-child[b-qf1shtr8hv] {
    box-shadow: inset 3px 0 0 var(--accent);
}

/* 026/T105 — la primera celda de la fila ahora es su <th scope="row"> (era <td>), así que
   ninguna de las dos reglas de arriba la alcanza más: "> td" ya no matchea, y "> td:first-child"
   tampoco, porque el primer hijo dejó de ser un td. El prefijo `.data-table` en el fondo
   compila a (0,3,1) y le gana a `.data-table th.cell-row-head` (admin.css, (0,2,1)) sin
   depender del orden de carga (misma trampa medida en Settlements.razor.css, 026/T100); el
   box-shadow no compite con nada global, así que no necesita el mismo empuje. */
.data-table .tpl__row--on > th[b-qf1shtr8hv] {
    background: var(--accent-soft);
}

.tpl__row--on > th:first-child[b-qf1shtr8hv] {
    box-shadow: inset 3px 0 0 var(--accent);
}

/* ------------------------------------------------------------------- El editor --- */

.tpl__head[b-qf1shtr8hv] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 14px;
    flex-wrap: wrap;
    margin-bottom: 16px;
}

/* Escritorio: los canales a la izquierda y la paleta a la derecha, a la vista mientras se
   escribe — que es lo que evita que alguien teclee un marcador mal escrito. La paleta se queda
   pegada arriba porque los textos de correo son largos. */
.tpl__editor[b-qf1shtr8hv] {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: 20px;
    align-items: start;
}

.tpl__channels[b-qf1shtr8hv] {
    display: flex;
    flex-direction: column;
    gap: 18px;
    min-width: 0;
}

.tpl__channel[b-qf1shtr8hv] {
    border: 1px solid var(--border);
    border-radius: var(--r-card);
    padding: 16px;
    background: var(--card-bg);
}

.tpl__channel-head[b-qf1shtr8hv] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 14px;
}

.tpl__channel-title[b-qf1shtr8hv] {
    font-size: 14px;
    font-weight: 800;
}

.tpl__palette[b-qf1shtr8hv] {
    position: sticky;
    top: 0;
    min-width: 0;
}

/* .dual-list__items reserva 220px porque en su casa (el diálogo de permisos) la lista es larga y
   se compara contra la de al lado. Acá una paleta son tres o seis marcadores: el hueco reservado
   se leería como «faltan». */
.tpl__palette .dual-list__items[b-qf1shtr8hv] {
    min-height: 0;
}

.tpl__hint[b-qf1shtr8hv] {
    margin: 12px 0 0;
    font-size: 11.5px;
    color: var(--text-2);
}

/* .dual-list__item-desc recorta con puntos suspensivos porque está hecho para nombres de una
   línea; la naturaleza del marcador es una frase y hay que poder leerla entera. */
.tpl__marker-note[b-qf1shtr8hv] {
    display: block;
    font-size: 11.5px;
    color: var(--text-2);
    margin-top: 2px;
    white-space: normal;
}

/* .input mide 40px de alto por diseño (es para campos de una línea); un textarea tiene que
   deshacerlo o rows="10" no hace nada. */
.tpl__area[b-qf1shtr8hv] {
    height: auto;
    min-height: 140px;
    padding: 10px 12px;
    line-height: 1.55;
    resize: vertical;
}

@media (max-width: 1100px) {
    .tpl__editor[b-qf1shtr8hv] {
        grid-template-columns: 1fr;
    }

    .tpl__palette[b-qf1shtr8hv] {
        position: static;
    }
}
/* /Components/Pages/Security/OperationTrace.razor.rz.scp.css */
/* Feature 014 / US3 — "Rastro de una operación". Only what the global admin theme does not
   already provide: the identifier bar, the state banner, the duration bars of the chain and
   the cut that closes a truncated trail.

   No new global CSS and no colour of its own: every value comes from a theme token, so light
   and dark are both covered by the theme that already styles the alerts and the table. */

/* --- The identifier bar --------------------------------------------------- */

.trace-search[b-nt5nqoszj8] {
    display: flex;
    align-items: flex-end;
    gap: 14px;
    flex-wrap: wrap;
}

.trace-search__go[b-nt5nqoszj8] {
    padding-bottom: 2px;
}

/* The operation number is 32 hexadecimal characters: monospaced so it can be compared
   character by character against the one the person was shown. */
.trace-input[b-nt5nqoszj8] {
    font-family: ui-monospace, 'Cascadia Code', 'Consolas', monospace;
    letter-spacing: .04em;
}

/* --- 🔴 FR-010: the state of the trail ------------------------------------ */

/* Not a new alert style: it reuses .alert / .alert--warn / .alert--ok / .alert--info, which
   are already themed. What this adds is weight — a headline the reader cannot skim past,
   because a truncated trail drawn quietly is worse than no trail at all. */
.trace-banner[b-nt5nqoszj8] {
    padding: 16px 18px;
    font-weight: 500;
    line-height: 1.55;
}

.trace-banner__title[b-nt5nqoszj8] {
    display: block;
    font-size: 15px;
    font-weight: 800;
    margin-bottom: 4px;
}

/* The sentence that stops the reader from trusting a chain of green steps. */
.trace-banner__warn[b-nt5nqoszj8] {
    display: block;
    margin-top: 8px;
    font-weight: 700;
}

/* An incomplete trail carries a thick left rail, so it is told apart from the ordinary
   warnings of the site at a glance and from across the desk. */
.trace-banner--cut[b-nt5nqoszj8] {
    border-left: 5px solid var(--warn-text);
}

.trace-head-note[b-nt5nqoszj8] {
    font-size: 12px;
    font-weight: 500;
    max-width: 460px;
    text-align: right;
    white-space: normal;
}

/* --- The chain ------------------------------------------------------------ */

/* A step that failed, and a failure of this operation: the rail is where the eye lands when
   scanning a long chain. */
.trace-row--failed td:first-child[b-nt5nqoszj8] {
    box-shadow: inset 4px 0 0 0 var(--danger-text);
}

/* 026/T105 — both tables' first cell is now their row's <th scope="row"> (was <td>): the
   step's "Paso" and the failure's "Fecha" no longer match ":first-child" as a td. No global
   rule sets box-shadow on .cell-row-head, so this one needs no `.data-table` specificity
   boost — it only needs to select the element that exists now. */
.trace-row--failed th:first-child[b-nt5nqoszj8] {
    box-shadow: inset 4px 0 0 0 var(--danger-text);
}

/* Entry and closing are the BORDERS of the operation, not part of what it did. */
.trace-row--edge td[b-nt5nqoszj8] {
    background: var(--border-softer);
}

/* 026/T105 — same conversion as above, on the steps table's "Paso" column: this needs the
   `.data-table` prefix because it competes on `background` with .data-table th.cell-row-head
   (admin.css, background: transparent, specificity (0,2,1)) — without the prefix this rule
   ties at (0,2,1) too and the winner depends on load order (the trap already measured in
   Settlements.razor.css, 026/T100). With it, this compiles to (0,3,1) and always wins. */
.data-table .trace-row--edge th[b-nt5nqoszj8] {
    background: var(--border-softer);
}

.trace-op[b-nt5nqoszj8] {
    display: inline-block;
    max-width: 340px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
    font-family: ui-monospace, 'Cascadia Code', 'Consolas', monospace;
    font-size: 12px;
}

.trace-op--wide[b-nt5nqoszj8] {
    max-width: 520px;
    font-family: inherit;
    font-size: 13px;
}

.trace-outside[b-nt5nqoszj8] {
    font-style: italic;
}

/* --- 🔴 The duration, which is what the diagnosis is read from ------------- */

/* The bar is proportional to the SLOWEST DATABASE CALL of this operation, so the step that
   ate the time pops out of the chain instead of having to be found by comparing numbers. */
.trace-dur[b-nt5nqoszj8] {
    display: flex;
    align-items: center;
    gap: 9px;
}

.trace-dur__bar[b-nt5nqoszj8] {
    flex: 1;
    min-width: 60px;
    height: 7px;
    border-radius: 4px;
    background: var(--border-softer);
    overflow: hidden;
}

.trace-dur__bar > span[b-nt5nqoszj8] {
    display: block;
    height: 100%;
    border-radius: 4px;
    background: var(--accent);
}

.trace-dur__value[b-nt5nqoszj8] {
    font-variant-numeric: tabular-nums;
    font-size: 12.5px;
    white-space: nowrap;
}

.trace-dur--peak .trace-dur__bar > span[b-nt5nqoszj8] {
    background: var(--warn-text);
}

.trace-dur--peak .trace-dur__value[b-nt5nqoszj8] {
    font-weight: 800;
}

.trace-dur__tag[b-nt5nqoszj8] {
    font-size: 10.5px;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: .04em;
    color: var(--warn-text);
    white-space: nowrap;
}

/* The whole-operation time, carried by the closing step: a total, never comparable to the
   duration of a single step, so it gets no bar. */
.trace-total[b-nt5nqoszj8] {
    font-variant-numeric: tabular-nums;
    font-size: 12.5px;
    font-weight: 700;
}

.trace-nodur[b-nt5nqoszj8] {
    font-style: italic;
}

/* --- 🔴 FR-010 again, at the end of the chain ------------------------------ */

/* The place whoever scrolls to the bottom is actually looking at: the trail ends in a cut,
   not in a closing step. */
.trace-cut td[b-nt5nqoszj8] {
    background: var(--warn-bg);
    color: var(--warn-text);
    font-weight: 700;
    border-top: 2px dashed var(--warn-text);
    white-space: normal;
}

/* ::deep because the glyph is rendered by <AppIcon>, a child component: the scope attribute
   of this page never lands on it. */
.trace-cut td[b-nt5nqoszj8]  .msi {
    vertical-align: middle;
    margin-right: 8px;
    font-size: 20px;
}

/* --- Step detail dialog --------------------------------------------------- */

.trace-block[b-nt5nqoszj8] {
    font-family: ui-monospace, 'Cascadia Code', 'Consolas', monospace;
    font-size: 12.5px;
    line-height: 1.55;
    color: var(--text);
    background: var(--border-softer);
    border: 1px solid var(--border);
    border-radius: var(--r-control);
    padding: 10px 12px;
    max-height: 220px;
    overflow: auto;
    white-space: pre-wrap;
    word-break: break-word;
}

.trace-mono[b-nt5nqoszj8] {
    font-family: ui-monospace, 'Cascadia Code', 'Consolas', monospace;
    font-size: 12px;
}
/* /Components/Pages/Security/Settings.razor.rz.scp.css */
/* Feature 023/T012 retired the VAT rate editor (the row is now read-only history; DECR-167 R1),
   which was the only reason this screen needed shapes of its own. Everything left on it uses the
   GLOBAL .setting-row / .switch / .input pattern of admin.css. Empty on purpose: kept so a future
   custom row on this screen has a scoped file to reach for, per the pattern LocationSettings.razor
   also follows. */
/* /Components/Pages/Security/UserLocations.razor.rz.scp.css */
/* Parqueos por usuario (026/T1029). El mismo gesto de buscador que LocationOwnerDialog.razor
   (buscar por texto, lista corta con "hay más"), copiado acá porque el CSS con ámbito de
   Blazor no cruza de un componente a otro. Los dos buscadores de esta pantalla — el de
   usuario arriba, el de parqueos a la izquierda del dual-list — comparten estas reglas. */

.picker-actions[b-fp8bht160f] {
    display: flex;
    gap: 8px;
    margin: 10px 0 14px;
}

/* La lista de resultados es corta a propósito: un buscador es para elegir, no para navegar
   el directorio entero (por eso el servidor nunca contesta más de un puñado). */
.picker-list[b-fp8bht160f] {
    display: flex;
    flex-direction: column;
    gap: 2px;
    max-height: 260px;
    overflow-y: auto;
    border: 1px solid var(--border);
    border-radius: var(--r-card);
    padding: 6px;
}

.picker-list__item[b-fp8bht160f] {
    display: flex;
    flex-direction: column;
    gap: 2px;
    width: 100%;
    text-align: left;
    padding: 9px 11px;
    border: 1px solid transparent;
    border-radius: var(--r-control);
    background: transparent;
    font-family: inherit;
    cursor: pointer;
    transition: background .12s, border-color .12s;
}

.picker-list__item:hover[b-fp8bht160f] {
    background: var(--side-hover);
}

.picker-list__item:focus-visible[b-fp8bht160f] {
    outline: 2px solid var(--accent);
    outline-offset: 1px;
}

/* La fila elegida se marca con borde Y con fondo: solo con color no la distingue quien no
   distingue colores. */
.picker-list__item.is-picked[b-fp8bht160f] {
    border-color: var(--accent);
    background: var(--accent-soft);
}

.picker-list__name[b-fp8bht160f] {
    font-size: 13.5px;
    font-weight: 600;
    color: var(--text);
}

.picker-list__meta[b-fp8bht160f] {
    font-size: 12px;
    color: var(--text-3);
}

/* El buscador de parqueos vive DENTRO del panel izquierdo del dual-list, así que su propio
   padding reemplaza al de .dual-list__panel para no duplicarlo. */
.dual-list__search[b-fp8bht160f] {
    display: flex;
    gap: 8px;
    padding: 10px;
    border-bottom: 1px solid var(--border);
}

.dual-list__search .input[b-fp8bht160f] {
    flex: 1;
}
/* /Components/Shared/BlockFooter.razor.rz.scp.css */
/* The save row of a self-contained block. Right-aligned so the eye lands on it after the
   fields, and separated by a hairline so a block never bleeds into the next one. Colours come
   from the theme variables, so light and dark are one definition. */
.block-footer[b-ee4ly9f6o2] {
    display: flex;
    justify-content: flex-end;
    gap: 8px;
    margin-top: 4px;
}
/* /Components/Shared/DiagnosticFailureDetail.razor.rz.scp.css */
/* Feature 014 — read-only value blocks of a failure detail. Blazor scoped CSS only reaches
   the elements of THIS component, so the two rules the block needs live here rather than in
   the stylesheet of whichever screen opens it. Every colour comes from a theme token, so
   light and dark are both covered. */

.dfd-block[b-yn9g446es4] {
    font-family: ui-monospace, 'Cascadia Code', 'Consolas', monospace;
    font-size: 12.5px;
    line-height: 1.55;
    color: var(--text);
    background: var(--border-softer);
    border: 1px solid var(--border);
    border-radius: var(--r-control);
    padding: 10px 12px;
    max-height: 220px;
    overflow: auto;
    white-space: pre-wrap;
    word-break: break-word;
}

.dfd-mono[b-yn9g446es4] {
    font-family: ui-monospace, 'Cascadia Code', 'Consolas', monospace;
    font-size: 12px;
}
/* /Components/Shared/PageFailureAlert.razor.rz.scp.css */
/* Only what the global .alert--error does not already provide: the second line with the
   operation identifier. No colour of its own — it inherits the alert's, so light and dark
   are both covered by the theme that already styles the alert. */

.pf-op[b-f4wy5jn364] {
    display: block;
    margin-top: 4px;
    font-weight: 500;
    opacity: .85;
}

/* Monospaced and selectable: this is meant to be read out loud on the phone and pasted
   into the "Operación N.º" filter of "Fallas del sistema". */
.pf-op__id[b-f4wy5jn364] {
    font-family: ui-monospace, 'Cascadia Code', 'Consolas', monospace;
    font-size: 12px;
    letter-spacing: .02em;
    user-select: all;
    word-break: break-all;
}
/* /Components/Shared/TabStrip.razor.rz.scp.css */
/* First tab strip of the site (DECR-404). Every colour comes from the shared tokens in
   app.css (--accent, --border, --text-2...), never a literal, so light and dark are one
   definition and a future theme change repaints this for free. */

.tab-strip__wrap[b-8byz7apaif] {
    border-bottom: 1px solid var(--border);
    margin-bottom: 18px;
    /* Desktop density (this site is a keyboard-and-mouse, wide-screen tool, never
       mobile-first): the strip scrolls sideways instead of wrapping when a lot has every
       conditional tab at once, so the fixed header above never has to fight for height. */
    overflow-x: auto;
}

.tab-strip[b-8byz7apaif] {
    display: flex;
    gap: 4px;
    min-width: max-content;
}

.tab-strip__tab[b-8byz7apaif] {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 10px 16px;
    border: none;
    border-bottom: 3px solid transparent;
    background: transparent;
    color: var(--text-2);
    font: inherit;
    font-size: 13.5px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    border-radius: var(--r-control) var(--r-control) 0 0;
}

.tab-strip__tab .msi[b-8byz7apaif] {
    font-size: 18px;
}

.tab-strip__tab:hover[b-8byz7apaif] {
    color: var(--text);
    background: var(--border-soft);
}

.tab-strip__tab:focus-visible[b-8byz7apaif] {
    outline: 2px solid var(--accent);
    outline-offset: -2px;
}

/* The active tab is NEVER color-only (DECR-404 R2): the underline bar AND the bolder,
   full-ink text both change, so it still reads as "selected" without relying on hue. */
.tab-strip__tab--active[b-8byz7apaif] {
    color: var(--text);
    border-bottom-color: var(--accent);
    font-weight: 700;
}
