﻿:root {
    --ci-primary: var(--mud-palette-primary);
    --ci-primary-dark: #EA6D0D;
    --ci-primary-soft: var(--mud-palette-primary-lighten);
    --ci-secondary: var(--mud-palette-secondary);
    --ci-secondary-soft: rgba(100, 116, 139, 0.14);
    --ci-bg: var(--mud-palette-background);
    --ci-surface: var(--mud-palette-surface);
    --ci-surface-soft: var(--mud-palette-table-striped);
    --ci-outline: var(--mud-palette-lines-default);
    --ci-text: var(--mud-palette-text-primary);
    --ci-text-muted: var(--mud-palette-text-secondary);
    --ci-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);

    /* Shell measurements. They live here and not scattered across the
       .razor files because the layout needs them in C# (LayoutProperties
       passes them straight through as var(...)) and the menu CSS needs
       them in three more places. One number per measurement is what stops
       the rail and the space reserved for it from drifting apart. */
    --monitor-rail-width: clamp(72px, 5.4vw, 92px);
    --monitor-nav-width: clamp(260px, 20vw, 320px);
    --monitor-topbar-height: 56px;

    /* Naranja Sypply: en el menu y la barra (azul noche) marca donde estas. */
    --monitor-accent: #F97316;
}

html, body {
    font-family: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif;
    font-feature-settings: "tnum" 1;
    background: var(--ci-bg);
    color: var(--ci-text);
}

/*  ============================================================
    NEUTRALIZAR LOS COLORES FIJOS DE LA PLANTILLA BOOTSTRAP

    ESTA ES LA CAUSA DE QUE "LA LETRA DEJE DE VERSE" AL CAMBIAR DE TEMA, y
    conviene dejarla escrita porque no se deduce mirando el CSS propio.

    App.razor carga css/sb-admin-2.min.css, que es una plantilla de
    Bootstrap 4 pensada para fondo claro. Su reboot pinta ETIQUETAS DESNUDAS
    con hexadecimales literales:

        pre     { color: #3a3b45 }    gris oscuro
        code    { color: #e83e8c }    rosa
        a:hover { color: #224abe }    azul

    Un hexadecimal literal no participa en la cascada de --mud-palette-*, asi
    que NO se recalcula cuando MudThemeProvider reescribe :root al cambiar de
    tema. En modo oscuro -- el modo por defecto de esta aplicacion -- un
    bloque de codigo quedaba con texto #3a3b45 sobre un fondo de ~#263342:
    1.09:1. El texto esta ahi y se puede seleccionar, pero no se lee ni una
    letra.

    Se arregla por ORDEN, no por especificidad: las dos reglas pesan (0,0,1)
    y app.css se enlaza despues que sb-admin-2 en App.razor. Si alguna vez se
    invierte ese orden de <link>, esto deja de funcionar en silencio.

    kbd NO entra en la lista, a proposito: Bootstrap le da
    kbd{color:#fff;background-color:#3a3b45}, y forzarlo a inherit dejaria la
    tecla en texto oscuro sobre fondo oscuro -- se cambiaria un fallo por
    otro.
    ============================================================ */
pre, code {
    color: inherit;
}

/*  El azul de Bootstrap al pasar el raton. a:hover pesa (0,1,1) y le gana al
    'a' de MudBlazor (0,0,1), asi que cualquier enlace de la aplicacion se
    volvia azul #224abe al pasar por encima -- un color que no esta en
    ninguna paleta de esta aplicacion. */
a:hover {
    color: inherit;
}

.btn-primary {
    color: #fff;
    background-color: var(--ci-primary);
    border-color: var(--ci-primary-dark);
}

.btn-primary:hover {
    background-color: var(--ci-primary-dark);
    border-color: var(--ci-primary-dark);
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
    box-shadow: 0 0 0 0.12rem var(--ci-surface), 0 0 0 0.28rem rgba(249, 115, 22, 0.32);
}

.content {
    padding-top: 1.1rem;
}

.mud-main-content {
    background: var(--ci-bg);
}

.mud-theme-dark .mud-main-content {
    background: var(--ci-bg);
}

/* The drawer paints nothing of its own: the gradient and everything else
   belong to NavMenu, which is what knows what is inside. All that happens
   here is stripping the background and padding MudBlazor gives it, which
   showed up as a strip of a different colour underneath the menu. */
.mud-drawer.monitor-drawer {
    background: transparent !important;
    border: 0 !important;
    /* The menu is always drawn at full width and it is the drawer that
       clips it when collapsing. That way the panel slides out instead of
       reflowing its text down to 90px for the length of the animation. */
    overflow: hidden !important;
}

.mud-drawer.monitor-drawer .mud-drawer-content,
.monitor-drawer .mud-drawer-content {
    display: block !important;
    height: 100% !important;
    min-height: 0 !important;
    padding: 0 !important;
    overflow: hidden !important;
}



.mud-paper {
    border: 1px solid var(--ci-outline);
    background-color: var(--ci-surface);
    box-shadow: var(--ci-shadow) !important;
}

.mud-card {
    border: 1px solid var(--ci-outline);
}

.mud-table,
.mud-data-grid {
    border-radius: 10px;
    overflow: hidden;
}

.mud-table thead,
.mud-data-grid-header {
    background: var(--ci-surface-soft);
}

.mud-table-row:hover,
.mud-data-grid-row:hover {
    background-color: rgba(249, 115, 22, 0.09) !important;
}

.universal-grid-clickable-row {
    cursor: pointer;
}

.universal-grid-shell {
    display: flex;
    flex-direction: column;
    min-width: 0;
    min-height: 0;
    overflow: hidden;
    border-radius: 10px;
}

.universal-grid-toolbar-root {
    display: flex;
    flex: 0 0 auto;
    flex-direction: column;
    width: 100%;
    min-width: 0;
    gap: 0.5rem;
    padding: clamp(0.45rem, 0.6vw, 0.7rem);
    border-bottom: 1px solid var(--ci-outline);
    background: var(--ci-surface);
}

/* Always wraps, not only below 960px. At 150% zoom the usable width
   halves without crossing any breakpoint, and a row that does not wrap
   pushes the buttons outside the card. */
.universal-grid-toolbar-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    width: 100%;
    min-width: 0;
    gap: 0.5rem;
    min-height: 36px;
}

.universal-grid-title-block {
    /* Grows with whatever is there, but can shrink away entirely: a
       min-width in px is what broke the row under zoom. The basis stays
       small: the row wraps on bases, and 16rem sent three buttons onto a
       line of their own under an empty half of the toolbar. */
    flex: 1 1 9rem;
    min-width: 0;
}

.universal-grid-title-block .mud-typography {
    overflow-wrap: anywhere;
}

.universal-grid-search {
    flex: 1 1 12rem;
    width: auto;
    max-width: 21rem;
    min-width: 0;
}

.universal-grid-toolbar-button {
    white-space: nowrap;
}

.universal-grid-column-menu {
    min-width: 240px;
    padding: 0.35rem 0;
}

/* Says what the checkboxes under it are for. The menu holds the exports too, and
   without a heading the column names read as three more things to export. */
.universal-grid-column-heading {
    padding: 0.25rem 1rem 0.35rem;
    color: var(--mud-palette-text-secondary);
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.universal-grid-column-option {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    min-height: 32px;
}

.universal-grid-column-option .mud-checkbox {
    margin: 0;
}

.universal-grid-actions {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin-left: auto;
}

/* A switch in the toolbar carries MudBlazor's own side margins, which pushed the
   group wider than it looks. */
.universal-grid-actions .mud-switch {
    margin: 0;
}

.universal-grid-filter-panel {
    width: 100%;
    min-width: 0;
    padding: clamp(0.45rem, 0.6vw, 0.7rem);
    border: 1px solid var(--ci-outline);
    border-radius: 8px;
    background: color-mix(in srgb, var(--ci-surface-soft) 62%, var(--ci-surface));
}

.universal-grid-filter-grid {
    align-items: center;
}

.universal-grid-filter-panel .mud-input-control {
    margin-top: 0;
}

.universal-grid-table {
    border-radius: 0 !important;
}

.universal-grid-table .mud-table-toolbar {
    display: none !important;
}

@media (max-width: 960px) {
    .universal-grid-toolbar-row {
        align-items: stretch;
    }

    .universal-grid-title-block,
    .universal-grid-search {
        flex: 1 1 100%;
        max-width: none;
        min-width: 0;
    }

    .universal-grid-actions {
        width: 100%;
    }
}

.mud-input-control .mud-input-outlined-border {
    border-color: var(--ci-outline);
}

.mud-button-filled-primary {
    background: linear-gradient(135deg, #F97316 0%, #EA6D0D 100%) !important;
    box-shadow: 0 2px 6px rgba(249, 115, 22, 0.22) !important;
    font-weight: 700;
}

.mud-button-filled-primary:hover {
    background: linear-gradient(135deg, #1A2332 0%, #0F172A 100%) !important;
    box-shadow: 0 4px 10px rgba(249, 115, 22, 0.26) !important;
}

.mud-button-outlined-primary {
    color: var(--ci-primary) !important;
    border-color: var(--ci-outline) !important;
    background-color: var(--ci-surface);
    font-weight: 700;
}

/* A text button is one line, on every screen. Squeezed into a narrow column its label
   used to break in two ("REGISTRAR / NUEVO"), and the button ended up twice as tall as
   the one beside it. Now it keeps its width and the row wraps instead; a container that
   cannot wrap is the one to fix, not the label. Icon buttons are .mud-icon-button and
   are not touched. */
.mud-button {
    white-space: nowrap;
    flex-shrink: 0;
}

.mud-button .mud-button-label {
    white-space: nowrap;
}

/* The other half of it: a grid column that lines its buttons up in a row (the toolbar
   next to the filters, on almost every list) lets them drop to a second row instead of
   spilling out of the column. Only the MudItem columns; a flex row elsewhere keeps what
   it says. */
.mud-grid-item.d-flex {
    flex-wrap: wrap;
}

.new-customer-detail-card .mud-icon-root,
.new-customer-metric-card .mud-icon-root,
.new-customer-section-title .mud-icon-root {
    color: var(--mud-palette-primary) !important;
}

.new-customer-detail-row {
    display: flex !important;
    justify-content: space-between !important;
    gap: 1rem !important;
    padding: 0.42rem 0 !important;
    border-bottom: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 48%, transparent) !important;
}

.new-customer-detail-row:last-child {
    border-bottom: 0 !important;
}

.new-customer-detail-row span {
    flex: 0 0 42% !important;
    color: var(--mud-palette-text-secondary) !important;
}

.new-customer-detail-row strong {
    flex: 1 1 auto !important;
    min-width: 0 !important;
    max-width: 58% !important;
    color: var(--mud-palette-text-primary) !important;
    text-align: right !important;
    overflow-wrap: anywhere !important;
}

.new-customer-detail-card {
    min-width: 0 !important;
    height: auto !important;
    overflow: visible !important;
    padding: 1rem 1.1rem !important;
    border: 1px solid color-mix(in srgb, var(--mud-palette-primary) 18%, var(--mud-palette-lines-default)) !important;
    border-radius: 8px !important;
    background: color-mix(in srgb, var(--mud-palette-surface) 90%, var(--mud-palette-background)) !important;
    box-shadow: 0 10px 26px rgba(0, 0, 0, 0.12) !important;
}

.new-customer-info-list {
    display: grid !important;
    gap: 0.15rem !important;
}

.new-customer-audit-grid {
    display: grid !important;
    grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
    gap: 0.65rem !important;
}

.new-customer-audit-tile {
    min-width: 0 !important;
    padding: 0.8rem !important;
    border: 1px solid color-mix(in srgb, var(--mud-palette-primary) 14%, var(--mud-palette-lines-default)) !important;
    border-radius: 8px !important;
    background: color-mix(in srgb, var(--mud-palette-primary) 4%, var(--mud-palette-surface)) !important;
    box-shadow: 0 7px 18px rgba(0, 0, 0, 0.095) !important;
}

.new-customer-audit-tile span {
    display: block !important;
    margin-bottom: 0.2rem !important;
    color: var(--mud-palette-text-secondary) !important;
    font-size: 0.75rem !important;
}

.new-customer-audit-tile strong {
    display: block !important;
    color: var(--mud-palette-text-primary) !important;
    overflow-wrap: anywhere !important;
}

.new-customer-card-header {
    display: flex !important;
    align-items: flex-start !important;
    justify-content: space-between !important;
    gap: 0.75rem !important;
    margin-bottom: 0.75rem !important;
}

.new-customer-contact-card {
    border-left: 3px solid var(--mud-palette-primary) !important;
}

.new-customer-metric-grid {
    display: grid !important;
    grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
    gap: 0.65rem !important;
    margin-bottom: 1rem !important;
}

.new-customer-metric-card {
    display: flex !important;
    align-items: flex-start !important;
    gap: 0.75rem !important;
    min-height: 84px !important;
    padding: 0.95rem 1rem !important;
    min-width: 0 !important;
    overflow: visible !important;
    border: 1px solid color-mix(in srgb, var(--mud-palette-primary) 18%, var(--mud-palette-lines-default)) !important;
    border-radius: 8px !important;
    background: color-mix(in srgb, var(--mud-palette-surface) 90%, var(--mud-palette-background)) !important;
    box-shadow: 0 10px 26px rgba(0, 0, 0, 0.12) !important;
}

.new-customer-metric-card::after {
    display: none !important;
}

.new-customer-metric-icon-shell {
    width: 32px !important;
    height: 32px !important;
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    flex: 0 0 auto !important;
    border-radius: 8px !important;
    background: color-mix(in srgb, var(--mud-palette-primary) 10%, var(--mud-palette-surface)) !important;
}

.new-customer-detail-hero {
    padding: 0.85rem 0 1rem !important;
    margin-bottom: 0.75rem !important;
    border-bottom: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 70%, transparent) !important;
    color: var(--mud-palette-text-primary) !important;
    background: transparent !important;
}

.new-customer-detail-location {
    color: var(--mud-palette-primary) !important;
    background: color-mix(in srgb, var(--mud-palette-primary) 8%, var(--mud-palette-surface)) !important;
}

.new-customer-detail-location .mud-icon-root {
    color: var(--mud-palette-primary) !important;
}

.new-customer-document-card {
    max-width: 860px !important;
}

.new-customer-document-viewer {
    width: 100% !important;
    aspect-ratio: 16 / 10 !important;
    min-height: 320px !important;
    max-height: 520px !important;
    overflow: hidden !important;
    display: flex !important;
    align-items: center !important;
    justify-content: center !important;
    border: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 76%, transparent) !important;
    border-radius: 8px !important;
    background: color-mix(in srgb, var(--mud-palette-background) 78%, var(--mud-palette-surface)) !important;
}

.new-customer-document-preview,
.new-customer-document-frame {
    width: 100% !important;
    height: 100% !important;
    border: 0 !important;
    background: transparent !important;
}

.new-customer-document-preview {
    object-fit: contain !important;
}

.new-customer-dialog .mud-dialog-title,
.new-customer-dialog .mud-dialog-content {
    padding-left: 1.5rem !important;
    padding-right: 1.5rem !important;
}

.new-customer-dialog .mud-dialog {
    overflow: hidden !important;
}

.new-customer-dialog .mud-dialog-content {
    padding-bottom: 1.25rem !important;
}

.new-customer-detail-tabs {
    overflow: visible !important;
    margin-top: 0.65rem !important;
}

.new-customer-detail-tabs .mud-tabs-toolbar {
    min-height: 46px !important;
    margin-bottom: 0 !important;
    border-bottom: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 72%, transparent) !important;
}

.new-customer-detail-tabs .mud-tabs-panels,
.new-customer-detail-tabs .mud-tab-panel,
.new-customer-detail-tabs .mud-tabs-panel {
    overflow: visible !important;
}

.new-customer-detail-tabs .mud-tab-panel,
.new-customer-detail-tabs .mud-tabs-panel {
    padding: 0 !important;
}

.new-customer-detail-tabs .mud-grid {
    row-gap: 0.9rem !important;
}

.new-customer-tab-content {
    padding: 1rem 0.15rem 0.5rem !important;
    overflow: visible !important;
}

.new-customer-detail-tabs .mud-tab {
    min-height: 44px !important;
    text-transform: uppercase !important;
    font-size: 0.82rem !important;
    font-weight: 800 !important;
    letter-spacing: 0.02rem !important;
}

.new-customer-detail-tabs .mud-tab.mud-tab-active {
    color: var(--mud-palette-primary) !important;
}

/* ------------------------------------------------- el expediente del prospecto

   Las tres pestañas que contestan quien cambio la ficha, si el sello de la firma
   cuadra y que declaraciones acepto. Todo el color sale de la paleta de
   MudBlazor, asi que claro y oscuro salen los dos sin una segunda regla. */

.new-customer-audit-filters {
    display: flex !important;
    flex-wrap: wrap !important;
    align-items: center !important;
    gap: 0.75rem !important;
    margin-bottom: 0.75rem !important;
}

.new-customer-audit-search {
    flex: 0 1 260px !important;
    margin-left: auto !important;
}

/* La leyenda del NULL contra la cadena vacia. Va dentro de una caja y no como un
   texto mas: es la instruccion de lectura de la tabla, y suelta se pierde entre
   los filtros. */
.new-customer-audit-legend {
    display: flex !important;
    align-items: flex-start !important;
    gap: 0.5rem !important;
    margin-bottom: 0.75rem !important;
    padding: 0.55rem 0.7rem !important;
    border-left: 3px solid color-mix(in srgb, var(--mud-palette-info) 60%, transparent) !important;
    border-radius: 6px !important;
    background: color-mix(in srgb, var(--mud-palette-info) 7%, var(--mud-palette-surface)) !important;
    color: var(--mud-palette-text-secondary) !important;
    font-size: 0.78rem !important;
    line-height: 1.45 !important;
}

.new-customer-audit-legend .mud-icon-root {
    flex: 0 0 auto !important;
    color: var(--mud-palette-info) !important;
}

/* Los tres valores del historial. El de verdad se lee como texto normal; los dos
   sustitutos NO se pueden parecer entre si, porque «le borraron el RNC» y «nunca
   tuvo RNC» es justo lo que esta tabla existe para poder distinguir. Se separan
   por tres cosas a la vez --color, subrayado y fondo-- para que la diferencia
   sobreviva a una impresion en blanco y negro y a quien no distingue colores. */
.new-customer-change-value {
    overflow-wrap: anywhere !important;
}

.new-customer-change-null em,
.new-customer-change-blank em {
    display: inline-block !important;
    padding: 0 0.3rem !important;
    border-radius: 4px !important;
    font-style: italic !important;
    font-size: 0.78rem !important;
    white-space: nowrap !important;
    cursor: help !important;
}

/* Nunca tuvo valor: gris y hueco, con el borde cortado. */
.new-customer-change-null em {
    border: 1px dashed color-mix(in srgb, var(--mud-palette-text-secondary) 45%, transparent) !important;
    background: transparent !important;
    color: var(--mud-palette-text-secondary) !important;
}

/* Se dejo en blanco: alguien lo hizo, asi que lleva tono de aviso y relleno. */
.new-customer-change-blank em {
    border: 1px solid color-mix(in srgb, var(--mud-palette-warning) 55%, transparent) !important;
    background: color-mix(in srgb, var(--mud-palette-warning) 14%, var(--mud-palette-surface)) !important;
    color: var(--mud-palette-warning) !important;
    font-weight: 600 !important;
}

.new-customer-change-origin {
    display: grid !important;
    gap: 0.15rem !important;
    font-size: 0.75rem !important;
    color: var(--mud-palette-text-secondary) !important;
}

.new-customer-change-origin a {
    color: var(--mud-palette-primary) !important;
    overflow-wrap: anywhere !important;
}

.new-customer-change-request {
    justify-self: start !important;
    padding: 0 0.35rem !important;
    border-radius: 4px !important;
    background: color-mix(in srgb, var(--mud-palette-secondary) 14%, var(--mud-palette-surface)) !important;
    color: var(--mud-palette-text-primary) !important;
}

/* El sello de la firma. El borde de la izquierda es ancho a proposito: es lo
   primero que se ve al abrir la pestaña, antes de leer una palabra. */
.new-customer-seal {
    --nc-seal-tone: var(--mud-palette-text-secondary);
    border-left: 5px solid var(--nc-seal-tone) !important;
    background: color-mix(in srgb, var(--nc-seal-tone) 6%, var(--mud-palette-surface)) !important;
}

.new-customer-seal.is-ok {
    --nc-seal-tone: var(--mud-palette-success);
}

.new-customer-seal.is-bad {
    --nc-seal-tone: var(--mud-palette-error);
}

.new-customer-seal-head {
    display: flex !important;
    align-items: flex-start !important;
    gap: 0.9rem !important;
}

/* Gana al `.new-customer-detail-card .mud-icon-root` de arriba, que pinta todos
   los iconos de las tarjetas en el color primario: aqui el icono ES el veredicto
   y no puede salir del mismo color cuadre o no cuadre. */
.new-customer-seal .new-customer-seal-head > .mud-icon-root {
    color: var(--nc-seal-tone) !important;
}

.new-customer-seal.is-bad .new-customer-seal-head .mud-typography-h6 {
    color: var(--mud-palette-error) !important;
}

.new-customer-hash-row {
    display: grid !important;
    gap: 0.15rem !important;
    padding: 0.42rem 0 !important;
    border-bottom: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 48%, transparent) !important;
}

.new-customer-hash-row:last-of-type {
    border-bottom: 0 !important;
}

.new-customer-hash-row > span {
    font-size: 0.75rem !important;
}

/* Monoespaciada y entero. Un hash en proporcional no se compara de un vistazo, y
   uno recortado no se compara en absoluto. */
.new-customer-hash {
    padding: 0.25rem 0.4rem !important;
    border-radius: 4px !important;
    background: color-mix(in srgb, var(--mud-palette-text-primary) 7%, var(--mud-palette-surface)) !important;
    color: var(--mud-palette-text-primary) !important;
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace !important;
    font-size: 0.78rem !important;
    letter-spacing: 0.01rem !important;
    overflow-wrap: anywhere !important;
}

/* El texto de la declaracion, tal como se acepto: los saltos de linea del cuerpo
   son parte del documento, asi que se respetan. */
.new-customer-declaration-body {
    max-height: 340px !important;
    overflow-y: auto !important;
    padding: 0.75rem 0.9rem !important;
    border: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 70%, transparent) !important;
    border-radius: 6px !important;
    background: color-mix(in srgb, var(--mud-palette-surface) 92%, var(--mud-palette-background)) !important;
    color: var(--mud-palette-text-primary) !important;
    font-size: 0.85rem !important;
    line-height: 1.55 !important;
    white-space: pre-wrap !important;
    overflow-wrap: anywhere !important;
}

@media (max-width: 700px) {
    .new-customer-detail-row {
        flex-direction: column !important;
        gap: 0.2rem !important;
    }

    .new-customer-detail-row strong {
        max-width: none !important;
        text-align: left !important;
    }

    .new-customer-detail-row span {
        flex: 0 0 auto !important;
    }

    .new-customer-audit-grid {
        grid-template-columns: 1fr !important;
    }

    .new-customer-metric-grid {
        grid-template-columns: 1fr !important;
    }

    .new-customer-document-viewer {
        min-height: 240px !important;
    }

    /* El buscador del historial deja de empujarse a la derecha y ocupa su
       propia linea: a 360 px, al lado de los chips, no caben ni los chips ni
       el buscador. */
    .new-customer-audit-search {
        flex: 1 1 100% !important;
        margin-left: 0 !important;
    }
}

@media (min-width: 701px) and (max-width: 1100px) {
    .new-customer-metric-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
    }
}

h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}




/* Beautiful Login Design */
.login-wrapper {
    height: 100vh;
    width: 100vw;
    margin: 0;
    overflow: hidden;
}
.login-brand-side {
    /* Azul noche corporativo con un halo del naranja Sypply: el mismo marco
       oscuro que el menu y la barra del portal. */
    background:
        radial-gradient(circle at 18% 12%, rgba(249, 115, 22, 0.30) 0, transparent 42%),
        radial-gradient(circle at 85% 90%, rgba(249, 115, 22, 0.14) 0, transparent 38%),
        linear-gradient(160deg, #1A2332 0%, #0F172A 100%);
    color: #FFFFFF;
    position: relative;
}
.login-brand-side::before {
    content: '';
    position: absolute;
    top: 0; left: 0; right: 0; bottom: 0;
    background-image: radial-gradient(circle at 2px 2px, rgba(255,255,255,0.1) 1px, transparent 0);
    background-size: 32px 32px;
    opacity: 0.5;
}
.login-form-side {
    background-color: var(--mud-palette-background);
}
.login-paper {
    background-color: var(--mud-palette-surface);
    backdrop-filter: blur(10px);
}

/* ============================================================
   Tabs legibles en todas las pantallas.

   POR QUE HACE FALTA ESTO
   -----------------------
   MudBlazor NO le pone color a `.mud-tab`. Lo comprobe en su
   propia hoja: la regla trae padding, peso, transform y nada de
   color -- el texto de una pestana inactiva es lo que herede del
   ancestro. En una app solo-MudBlazor eso da igual, porque el
   unico que pinta el body es MudBlazor.

   Aqui no estamos solos: sb-admin-2 y Bootstrap se cargan en la
   misma pagina y tambien pintan `body`. Hoy gana MudBlazor por
   orden de carga, pero es una herencia que depende de una linea
   del App.razor: mover un <link> deja las pestanas del color de
   Bootstrap (#858796) sobre superficie oscura, y sus nombres
   dejan de leerse sin que nada falle.

   Se fija el color aqui y deja de depender de eso.
   ============================================================ */

.mud-tabs .mud-tab {
    /* Legible, pero claramente por debajo de la activa. La jerarquia
       la lleva el contraste, no el tamano: todas miden igual. */
    color: var(--mud-palette-text-primary) !important;
    opacity: 0.72;
    font-weight: 600 !important;
    letter-spacing: 0.03em !important;
    transition: opacity 140ms ease, color 140ms ease;
}

.mud-tabs .mud-tab:hover {
    opacity: 1;
}

.mud-tabs .mud-tab.mud-tab-active {
    color: var(--mud-palette-primary) !important;
    opacity: 1;
    font-weight: 800 !important;
}

/* La franja de pestanas necesita un suelo. Sin el, sobre una
   superficie del mismo color que el panel, no se ve donde acaba
   la barra y empieza el contenido -- y las pestanas quedan
   flotando sobre nada. */
.mud-tabs .mud-tabs-tabbar {
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

/* El subrayado de la activa, mas grueso que el de fabrica: es la
   unica senal de en cual estas cuando hay cinco. */
.mud-tabs .mud-tab-slider {
    height: 3px !important;
    border-radius: 3px 3px 0 0;
}

/* ============================================================
   FULL HEIGHT AND FLUID WIDTH

   THE PROBLEM
   -----------
   The screen was drawn with automatic height: every block took
   what it needed and whatever was left down to the bottom edge
   stayed empty. With ten rows in the table that was half a
   screen of background. And the other way round: raising the
   zoom made the same content stop fitting and put the whole page
   into scroll, dragging the header and the filter bar out of
   sight.

   HOW IT IS FIXED
   ---------------
   The shell measures exactly the viewport. Inside, it is a flex
   column: the header and the filters take what they need, and
   the table keeps ALL of the surplus -- a lot or a little. When
   it does not fit, the table scrolls inside itself, with its own
   header and pager standing still.

   That leaves no pixel height to recalculate when the monitor or
   the zoom changes: flexbox does the sharing every time.
   ============================================================ */

html,
body {
    height: 100%;
}

/* dvh and not vh: on mobile, vh counts the browser bar even while it is
   visible, leaving the last stretch of the table underneath it. */
.mud-layout {
    height: 100dvh;
    overflow: hidden;
}

.mud-main-content.monitor-main {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-width: 0;
    box-sizing: border-box;
    /* MudMainContent reserves the height of a MudAppBar at the top, and
       there is none here. Without removing it, the white top bar would
       start 64px below the edge and leave a strip of background above it. */
    padding-top: 0;
    overflow: hidden;
}

.monitor-page-shell {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    width: 100%;
    min-height: 0;
    min-width: 0;
    box-sizing: border-box;
    /* Elastic margins: 0.75rem when the screen is a phone or the zoom is
       at 200%, 2rem when there is room to spare. Fixed padding is wasted
       air in the narrow case and a mean strip in the wide one. */
    padding: clamp(0.75rem, 1.1vw, 1.5rem) clamp(0.75rem, 1.4vw, 2rem);
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
}

/* Screen titles tied to the available width: at high zoom a 2.125rem h4
   used up two lines on its own. */
.monitor-page-shell > .mud-typography-h4 {
    font-size: clamp(1.35rem, 2vw, 2.125rem);
    line-height: 1.2;
}

.monitor-page-shell > .mud-typography-h5 {
    font-size: clamp(1.15rem, 1.6vw, 1.5rem);
    line-height: 1.25;
}

/* A full-width container block, for screens that wrap all their content
   in a div of their own. */
.monitor-page-block {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    width: 100%;
    min-width: 0;
}

/* The main block of the page keeps the leftover height. It applies to
   the table card and to any block marked as filler -- not to the text or
   the alerts, which must keep measuring what they need.

   The 24rem floor is not decorative: these blocks carry an overflow other
   than visible, and by flexbox rule that makes their automatic minimum
   size ZERO. With no floor, a screen with a tall header (metrics,
   filters, notices) would squash the table down to nothing instead of
   letting the page scroll. */
.monitor-page-shell > .universal-grid-shell,
.monitor-page-shell > .monitor-fill,
.monitor-page-block > .universal-grid-shell,
.monitor-page-block > .monitor-fill {
    flex: 1 1 auto;
    min-height: min(24rem, 55vh);
}

/* ------------------------------------------------------------
   Screens built on tabs: the tab box takes the full height and
   scrolls the active panel, rather than leaving the page
   background showing underneath.
   ------------------------------------------------------------ */

.monitor-page-shell > .mud-tabs,
.monitor-page-block > .mud-tabs {
    flex: 1 1 auto;
    min-height: min(24rem, 55vh);
}

.monitor-page-shell > .mud-tabs > .mud-tabs-panels,
.monitor-page-block > .mud-tabs > .mud-tabs-panels {
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
}

/* ------------------------------------------------------------
   Inside the table: header pinned at the top, pager pinned at
   the bottom, and only the rows move.
   ------------------------------------------------------------ */

.universal-grid-fill .universal-grid-table {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    min-height: 0;
}

.universal-grid-fill .universal-grid-table .mud-table-container {
    flex: 1 1 auto;
    min-height: 0;
    max-height: none !important;
    overflow-y: auto !important;
    overflow-x: auto !important;
}

.universal-grid-fill .universal-grid-table .mud-table-pagination {
    flex: 0 0 auto;
    border-top: 1px solid var(--ci-outline);
    background: var(--ci-surface);
}

/* The sticky header inherits the surface background; without this the
   rows underneath show through it while scrolling. */
.universal-grid-fill .mud-table-head .mud-table-cell {
    background-color: var(--ci-surface) !important;
}

/* The per-column filter strip is pinned too: if the header stays put and
   this does not, scrolling separates them and the filter stops reading as
   belonging to its column. */
.universal-grid-fill .mud-table-head .filter-header-cell {
    background-color: var(--ci-surface) !important;
}

/* An empty grid, or one with two rows, must not leave half the card
   blank: the no-data message centres itself in the surplus. */
.universal-grid-fill .mud-table-container .mud-table-root {
    min-width: 100%;
}

/* ------------------------------------------------------------
   Same treatment for screens that put a bare MudDataGrid inside
   a card, without going through UniversalGrid.
   ------------------------------------------------------------ */

.monitor-fill-grid {
    display: flex;
    flex-direction: column;
    min-height: 0;
    min-width: 0;
    overflow: hidden;
}

.monitor-fill-grid > .mud-data-grid {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    min-height: 0;
}

.monitor-fill-grid > .mud-data-grid .mud-table-container {
    flex: 1 1 auto;
    min-height: 0;
    max-height: none !important;
    overflow-y: auto !important;
    overflow-x: auto !important;
}

.monitor-fill-grid > .mud-data-grid .mud-table-pagination {
    flex: 0 0 auto;
    border-top: 1px solid var(--ci-outline);
    background: var(--ci-surface);
}

.monitor-fill-grid .mud-table-head .mud-table-cell {
    background-color: var(--ci-surface) !important;
}

/* ------------------------------------------------------------
   External frames (module iframes) at whatever height is left.
   ------------------------------------------------------------ */

.monitor-embed-frame {
    display: flex;
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
    border-radius: 8px;
}

.monitor-embed-frame > iframe {
    flex: 1 1 auto;
    width: 100%;
    min-height: 0;
    border: 0;
}

/* ------------------------------------------------------------
   Dialogs: never wider than the window.

   MudBlazor already caps the height. It does not cap the width:
   at high zoom a Large dialog runs off the sides and its buttons
   end up out of reach, with no scrollbar to get to them.
   ------------------------------------------------------------ */

.mud-dialog {
    max-width: calc(100vw - 1.5rem);
}

/* ------------------------------------------------------------
   Filter forms on narrow screens, or under zoom.
   ------------------------------------------------------------ */

.universal-grid-filter-panel .mud-grid {
    margin: 0;
    width: 100%;
}

.universal-grid-filter-panel .mud-input-control,
.universal-grid-filter-panel .mud-select {
    min-width: 0;
}

@media (max-width: 599px) {
    .monitor-page-shell {
        padding-left: 0.6rem;
        padding-right: 0.6rem;
    }

    .universal-grid-fill .universal-grid-table .mud-table-pagination {
        font-size: 0.8rem;
    }
}

/* ============================================================
   LOADING SCREEN

   Covers the stretch between "the HTML is painted" and "the
   application responds". In Blazor Server those are not the same
   moment: the server sends the whole page immediately, but until
   the circuit connects not one click works. With nothing over
   it, that stretch looks like a loaded application ignoring what
   you press -- and the normal reaction is to press again, or
   reload.

   It uses no MudBlazor variable: it paints before
   MudThemeProvider has ever existed. Light or dark is decided by
   the data-boot-theme attribute that app-shell.js sets from the
   stored preference.
   ============================================================ */

#app-splash {
    position: fixed;
    inset: 0;
    /* Above everything MudBlazor draws (the library's highest z-index is
       the snackbar, at 1400). */
    z-index: 4000;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.85rem;
    background: #F8FAFC;
    color: #1E293B;
    transition: opacity 380ms ease, visibility 380ms ease;
}

:root[data-boot-theme="dark"] #app-splash {
    background: #0F172A;
    color: #F8FAFC;
}

#app-splash.is-gone {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
}

.app-splash-mark {
    display: grid;
    place-items: center;
    width: 66px;
    height: 66px;
    border-radius: 16px;
    overflow: hidden;
    box-shadow: 0 14px 34px rgba(249, 115, 22, 0.30);
    animation: app-splash-pulse 1.7s ease-in-out infinite;
}

.app-splash-mark img {
    display: block;
    width: 100%;
    height: 100%;
}

.app-splash-name span {
    color: #F97316;
}

.app-splash-name {
    font-size: 1.02rem;
    font-weight: 800;
    letter-spacing: 0.24em;
    text-indent: 0.24em;
}

.app-splash-bar {
    position: relative;
    width: min(220px, 54vw);
    height: 3px;
    border-radius: 3px;
    background: currentColor;
    /* The track, in the same colour as the text but almost switched off:
       two different greys here read as two elements, and this is one. */
    opacity: 0.16;
    overflow: hidden;
}

.app-splash-bar span {
    position: absolute;
    inset: 0 auto 0 0;
    display: block;
    width: 38%;
    border-radius: 3px;
    background: #F97316;
    animation: app-splash-slide 1.15s ease-in-out infinite;
}

:root[data-boot-theme="dark"] .app-splash-bar span {
    background: #FB923C;
}

.app-splash-hint {
    font-size: 0.78rem;
    opacity: 0.6;
}

@keyframes app-splash-slide {
    0% { transform: translateX(-110%); }
    100% { transform: translateX(330%); }
}

@keyframes app-splash-pulse {
    0%, 100% { transform: scale(1); }
    50% { transform: scale(1.06); }
}

/* Whoever asks for less motion still gets the loading screen; what they
   do not get is the pulse or the bar running. */
@media (prefers-reduced-motion: reduce) {
    .app-splash-mark,
    .app-splash-bar span {
        animation: none;
    }

    .app-splash-bar span {
        width: 100%;
        opacity: 0.7;
    }
}

/* ============================================================
   LANDING PAGES (dashboards)

   These classes live in the global stylesheet and not in a
   scoped .razor.css on purpose: the module landing pages are
   compiled inside the plugin assemblies, and a scoped sheet
   there would never reach the bundle of the host. One single
   vocabulary, so the home of the platform and the home of a
   module look like the same product.
   ============================================================ */

.dash {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    min-width: 0;
}

/* ---------------------------------------------- hero */

.dash-hero {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 1rem;
    min-width: 0;
    padding: clamp(1rem, 1.6vw, 1.5rem);
    border-radius: 12px;
    color: #ffffff;
    background: linear-gradient(120deg,
        var(--monitor-menu-top, #1A2332) 0%,
        var(--monitor-menu-bottom, #0F172A) 100%);
    box-shadow: 0 10px 26px rgba(0, 0, 0, 0.16);
}

.dash-hero-mark {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 62px;
    height: 62px;
    border-radius: 16px;
    overflow: hidden;
    box-shadow: 0 10px 24px rgba(249, 115, 22, 0.30);
}

.dash-hero-mark .mud-icon-root {
    color: #ffffff;
    font-size: 2rem;
}

.dash-hero-text {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    flex: 1 1 18rem;
    min-width: 0;
}

.dash-hero-text h1 {
    margin: 0;
    font-size: clamp(1.15rem, 1.9vw, 1.6rem);
    font-weight: 800;
    line-height: 1.2;
    overflow-wrap: anywhere;
}

.dash-hero-text p {
    margin: 0;
    max-width: 64ch;
    color: rgba(255, 255, 255, 0.78);
    font-size: 0.88rem;
    line-height: 1.45;
    overflow-wrap: anywhere;
}

.dash-badges {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-top: 0.15rem;
}

.dash-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.15rem 0.65rem;
    border: 1px solid rgba(255, 255, 255, 0.34);
    border-radius: 999px;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.03em;
}

.dash-badge .mud-icon-root {
    color: currentColor;
    font-size: 0.95rem;
}

/* The environment is the one badge that must not read as decoration: a
   screen showing production data looks exactly like one showing test
   data, and that is the mistake this colour exists to prevent. */
.dash-badge-env {
    border-color: transparent;
    background: #ffffff;
    color: var(--monitor-menu-bottom, #0F172A);
}

.dash-badge-env.is-dev {
    background: #FFD65A;
    color: #4A3200;
}

.dash-badge-env.is-staging {
    background: #7ED0F5;
    color: #06344A;
}

/* Same reasoning as the environment badge, for the other thing that changes
   which data is on screen without changing how the screen looks: the App7Ci
   installation the session was switched to. Solid and not an outline, because
   these badges sit on the coloured hero and a tinted border disappears into it. */
.dash-badge.is-warn {
    border-color: transparent;
    background: #FFD65A;
    color: #4A3200;
}

/* ---------------------------------------------- stat tiles */

.dash-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(11.5rem, 100%), 1fr));
    gap: 0.75rem;
}

.dash-stat {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    min-width: 0;
    padding: 0.8rem 0.9rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 12px;
    background: var(--mud-palette-surface);
}

.dash-stat-icon {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 38px;
    height: 38px;
    border-radius: 10px;
    background: color-mix(in srgb, var(--mud-palette-primary) 12%, transparent);
}

.dash-stat-icon .mud-icon-root {
    color: var(--mud-palette-primary);
    font-size: 1.15rem;
}

.dash-stat.tone-success .dash-stat-icon { background: color-mix(in srgb, var(--mud-palette-success) 14%, transparent); }
.dash-stat.tone-success .dash-stat-icon .mud-icon-root { color: var(--mud-palette-success); }
.dash-stat.tone-warning .dash-stat-icon { background: color-mix(in srgb, var(--mud-palette-warning) 16%, transparent); }
.dash-stat.tone-warning .dash-stat-icon .mud-icon-root { color: var(--mud-palette-warning); }
.dash-stat.tone-error .dash-stat-icon { background: color-mix(in srgb, var(--mud-palette-error) 14%, transparent); }
.dash-stat.tone-error .dash-stat-icon .mud-icon-root { color: var(--mud-palette-error); }
.dash-stat.tone-info .dash-stat-icon { background: color-mix(in srgb, var(--mud-palette-info) 14%, transparent); }
.dash-stat.tone-info .dash-stat-icon .mud-icon-root { color: var(--mud-palette-info); }

.dash-stat-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    line-height: 1.2;
}

.dash-stat-value {
    font-size: 1.35rem;
    font-weight: 800;
    color: var(--mud-palette-text-primary);
    overflow-wrap: anywhere;
}

.dash-stat-label {
    color: var(--mud-palette-text-secondary);
    font-size: 0.76rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    overflow-wrap: anywhere;
}

.dash-stat-hint {
    margin-top: 0.1rem;
    color: var(--mud-palette-text-secondary);
    font-size: 0.7rem;
    opacity: 0.85;
    overflow-wrap: anywhere;
}

/* ---------------------------------------------- cards */

/* Cards are stretched, never packed to the top of their row: side by side
   they must read as one band of the same height, whatever each one holds
   inside. That is why there is no align-items: start here. */
.dash-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(22rem, 100%), 1fr));
    gap: 1rem;
    align-items: stretch;
}

/* The floor is what keeps a card with two facts from looking like a
   fragment next to one with a full list; from there each row grows to
   whatever its tallest card needs. */
.dash-card {
    display: flex;
    flex-direction: column;
    gap: 0.8rem;
    min-width: 0;
    min-height: 15.5rem;
    padding: clamp(0.9rem, 1.3vw, 1.25rem);
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 12px;
    background: var(--mud-palette-surface);
}

/* The links of a card are its actions and they always sit at the bottom
   edge, aligned with those of the card beside it. */
.dash-card > .dash-links {
    margin-top: auto;
}

/* A card spanning the whole width is an index of links, not a data block:
   it takes the height of its content and no floor is imposed on it. */
.dash-card-wide {
    grid-column: 1 / -1;
    min-height: 0;
}

/* On a phone the grid is a single column: the floor would only add empty
   space to scroll through, so there the cards are worth what they hold. */
@media (max-width: 599px) {
    .dash-card {
        min-height: 0;
    }
}

.dash-card-title {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    color: var(--mud-palette-text-primary);
    font-size: 0.78rem;
    font-weight: 800;
    letter-spacing: 0.07em;
    text-transform: uppercase;
}

.dash-card-title .mud-icon-root {
    color: var(--mud-palette-primary);
}

.dash-card-title small {
    margin-left: auto;
    color: var(--mud-palette-text-secondary);
    font-size: 0.68rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: none;
}

.dash-text {
    margin: 0;
    color: var(--mud-palette-text-secondary);
    font-size: 0.86rem;
    line-height: 1.5;
}

.dash-text strong {
    color: var(--mud-palette-text-primary);
}

.dash-steps {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.dash-steps li {
    display: flex;
    gap: 0.55rem;
    align-items: flex-start;
    color: var(--mud-palette-text-secondary);
    font-size: 0.84rem;
    line-height: 1.45;
}

.dash-steps li .mud-icon-root {
    flex: 0 0 auto;
    margin-top: 0.1rem;
    color: var(--mud-palette-primary);
    font-size: 1.05rem;
}

.dash-steps strong {
    color: var(--mud-palette-text-primary);
}

/* ---------------------------------------------- fact list */

.dash-facts {
    display: flex;
    flex-direction: column;
    margin: 0;
}

.dash-facts > div {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.42rem 0;
    border-bottom: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 55%, transparent);
}

.dash-facts > div:last-child {
    border-bottom: 0;
}

.dash-facts dt {
    flex: 0 0 42%;
    margin: 0;
    color: var(--mud-palette-text-secondary);
    font-size: 0.8rem;
}

.dash-facts dd {
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    color: var(--mud-palette-text-primary);
    font-size: 0.84rem;
    font-weight: 600;
    text-align: right;
    overflow-wrap: anywhere;
}

/* ---------------------------------------------- application list */

.dash-apps {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(19rem, 100%), 1fr));
    gap: 0.8rem;
}

.dash-app {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-width: 0;
    padding: 0.85rem 0.95rem;
    border: 1px solid color-mix(in srgb, var(--mud-palette-primary) 16%, var(--mud-palette-lines-default));
    border-radius: 11px;
    background: color-mix(in srgb, var(--mud-palette-primary) 4%, var(--mud-palette-surface));
}

.dash-app-head {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    min-width: 0;
}

.dash-app-head .mud-icon-root {
    color: var(--mud-palette-primary);
}

.dash-app-name {
    flex: 1 1 auto;
    min-width: 0;
    color: var(--mud-palette-text-primary);
    font-weight: 700;
    overflow-wrap: anywhere;
}

.dash-app-desc {
    margin: 0;
    color: var(--mud-palette-text-secondary);
    font-size: 0.8rem;
    line-height: 1.4;
}

.dash-app-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
}

.dash-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.12rem 0.55rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 999px;
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-secondary);
    font-size: 0.71rem;
    font-weight: 600;
    white-space: nowrap;
}

.dash-chip.is-ok {
    border-color: color-mix(in srgb, var(--mud-palette-success) 45%, transparent);
    color: var(--mud-palette-success);
}

.dash-chip.is-warn {
    border-color: color-mix(in srgb, var(--mud-palette-warning) 50%, transparent);
    color: var(--mud-palette-warning);
}

.dash-chip.is-off {
    border-color: color-mix(in srgb, var(--mud-palette-error) 45%, transparent);
    color: var(--mud-palette-error);
}

/* ---------------------------------------------- link chips */

.dash-links {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
}

.dash-link {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.3rem 0.7rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 999px;
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    font-size: 0.8rem;
    font-weight: 600;
    text-decoration: none;
    transition: border-color 140ms ease, color 140ms ease, background-color 140ms ease;
}

.dash-link .mud-icon-root {
    color: var(--mud-palette-text-secondary);
    font-size: 1rem;
}

.dash-link:hover,
.dash-link:focus-visible {
    border-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 8%, var(--mud-palette-surface));
    outline: none;
}

.dash-link:hover .mud-icon-root,
.dash-link:focus-visible .mud-icon-root {
    color: var(--mud-palette-primary);
}

/* A whole tile that is a link: the applications on the platform home. */
.dash-link-block {
    text-decoration: none;
    color: inherit;
    transition: border-color 140ms ease, box-shadow 140ms ease;
}

.dash-link-block:hover,
.dash-link-block:focus-visible {
    border-color: var(--mud-palette-primary);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.1);
    outline: none;
}

/* ---------------------------------------------- ranked rows */

.dash-rows {
    display: flex;
    flex-direction: column;
    gap: 0.45rem;
}

.dash-row {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    min-width: 0;
    padding: 0.45rem 0.6rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 9px;
}

.dash-row-name {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 0.84rem;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dash-row-value {
    flex: 0 0 auto;
    color: var(--mud-palette-text-secondary);
    font-size: 0.78rem;
    font-weight: 600;
    white-space: nowrap;
}

.dash-row-bar {
    flex: 0 0 5.5rem;
    height: 6px;
    border-radius: 3px;
    background: color-mix(in srgb, var(--mud-palette-text-secondary) 20%, transparent);
    overflow: hidden;
}

.dash-row-bar span {
    display: block;
    height: 100%;
    border-radius: 3px;
    background: var(--mud-palette-primary);
}

/* ---------------------------------------------- empty / unavailable */

.dash-empty {
    margin: 0;
    padding: 0.7rem 0.8rem;
    border: 1px dashed var(--mud-palette-lines-default);
    border-radius: 9px;
    color: var(--mud-palette-text-secondary);
    font-size: 0.82rem;
    line-height: 1.45;
}

/* ============================================================
   AYUDA

   El HTML de estas reglas no lo escribe una plantilla: lo produce
   Markdig a partir de los .md, asi que aqui se le da estilo a
   etiquetas desnudas (h2, pre, table) y no a clases. Todo cuelga
   de .monitor-help-body para no pisar el resto de la aplicacion,
   que si usa clases.
   ============================================================ */

.monitor-help-card {
    transition: border-color 140ms ease, transform 140ms ease;
}

.monitor-help-card:hover {
    border-color: var(--ci-primary) !important;
    transform: translateY(-2px);
}

.monitor-help-body {
    line-height: 1.65;
    /* Una medida, no todo el ancho del monitor: pasadas las noventa
       caracteres el ojo pierde el renglon al volver. */
    max-width: 68rem;
}

.monitor-help-body > :first-child {
    margin-top: 0;
}

.monitor-help-body h1,
.monitor-help-body h2,
.monitor-help-body h3 {
    margin: 1.8rem 0 0.6rem;
    font-weight: 700;
    line-height: 1.25;
    /* Compensa la barra superior fija cuando se llega por el indice:
       sin esto el titulo al que se salta queda debajo de ella. */
    scroll-margin-top: calc(var(--monitor-topbar-height) + 1rem);
}

.monitor-help-body h1 { font-size: 1.5rem; }
.monitor-help-body h2 { font-size: 1.2rem; }
.monitor-help-body h3 { font-size: 1.02rem; }

.monitor-help-body h2 {
    padding-bottom: 0.35rem;
    border-bottom: 1px solid var(--ci-outline);
}

.monitor-help-body p,
.monitor-help-body ul,
.monitor-help-body ol {
    margin: 0.7rem 0;
}

.monitor-help-body li {
    margin: 0.3rem 0;
}

/*  El color va aqui y no se hereda de la regla global de 'a'.

    MudBlazor.min.css se carga DESPUES de app.css y trae
    a{color:var(--mud-palette-text-primary)}, asi que una regla 'a' de
    app.css (0,0,1) esta muerta. Estos selectores pesan (0,1,1) y ganan por
    especificidad, que es lo unico que no depende del orden de los <link>.

    El rojo de marca a secas da 2.96:1 sobre la superficie oscura -- por
    debajo del minimo legible de 4.5:1. Mezclado hacia el color del texto
    sube a 4.96:1 en oscuro y 10.94:1 en claro con UNA sola expresion, sin
    duplicar la regla por tema. Si se toca el porcentaje, vuelve a medirse:
    por debajo del 70% en oscuro se baja de 4.5:1 otra vez. */
.monitor-help-body a {
    color: color-mix(in srgb, var(--ci-primary) 65%, var(--ci-text));
    text-decoration: none;
    border-bottom: 1px solid color-mix(in srgb, currentColor 40%, transparent);
}

.monitor-help-body a:hover {
    color: color-mix(in srgb, var(--ci-primary) 55%, var(--ci-text));
    border-bottom-color: currentColor;
}

/*  Codigo en linea. Fondo tenue y no un recuadro completo: dentro de un
    parrafo, un borde por palabra lo vuelve ilegible.

    El color se declara AQUI y no se hereda: sin el, gana el
    code{color:#e83e8c} de la plantilla Bootstrap y todo el codigo en linea
    sale rosa fijo, igual en tema claro que en oscuro. Ver la nota sobre
    sb-admin-2 al principio de este archivo. */
.monitor-help-body code {
    color: var(--ci-text);
    padding: 0.12rem 0.35rem;
    border-radius: 5px;
    background: color-mix(in srgb, var(--ci-text) 8%, transparent);
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 0.86em;
}

.monitor-help-body pre {
    /* Igual que el codigo en linea: sin esta declaracion gana el
       pre{color:#3a3b45} de Bootstrap y el bloque entero queda a 1.09:1
       sobre el fondo oscuro -- invisible. */
    color: var(--ci-text);
    margin: 0.9rem 0;
    padding: 0.9rem 1rem;
    /* Los bloques de codigo son lo unico aqui que puede no caber: se
       desplazan dentro de si mismos en vez de estirar la pagina. */
    overflow-x: auto;
    border: 1px solid var(--ci-outline);
    border-radius: 10px;
    background: color-mix(in srgb, var(--ci-text) 5%, transparent);
}

.monitor-help-body pre code {
    padding: 0;
    background: none;
    font-size: 0.82rem;
    line-height: 1.55;
}

.monitor-help-body table {
    display: block;
    width: 100%;
    margin: 1rem 0;
    overflow-x: auto;
    border-collapse: collapse;
    font-size: 0.88rem;
}

.monitor-help-body th,
.monitor-help-body td {
    padding: 0.5rem 0.7rem;
    border: 1px solid var(--ci-outline);
    text-align: left;
    vertical-align: top;
}

.monitor-help-body th {
    background: color-mix(in srgb, var(--ci-text) 6%, transparent);
    font-weight: 700;
}

.monitor-help-body blockquote {
    margin: 1rem 0;
    padding: 0.6rem 1rem;
    border-left: 3px solid var(--ci-primary);
    border-radius: 0 8px 8px 0;
    background: color-mix(in srgb, var(--ci-primary) 7%, transparent);
    color: var(--ci-text);
}

.monitor-help-body blockquote > :first-child { margin-top: 0; }
.monitor-help-body blockquote > :last-child { margin-bottom: 0; }

/* Las capturas y diagramas: nunca mas anchos que la columna, y con
   borde para que se distingan del fondo de la pagina. */
.monitor-help-body img {
    max-width: 100%;
    height: auto;
    margin: 0.9rem 0;
    border: 1px solid var(--ci-outline);
    border-radius: 10px;
}

.monitor-help-body hr {
    margin: 1.6rem 0;
    border: 0;
    border-top: 1px solid var(--ci-outline);
}

/* ---------------------------------------------- el numero del paso */

.monitor-help-step-number {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: var(--ci-primary);
    color: #ffffff;
    font-size: 0.9rem;
    font-weight: 800;
}

/* ------------------------------------------------- indice lateral */

.monitor-help-toc {
    position: sticky;
    top: calc(var(--monitor-topbar-height) + 1rem);
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.monitor-help-toc-link {
    padding: 0.3rem 0.6rem;
    border-left: 2px solid var(--ci-outline);
    /* El gris secundario a secas da 4.36:1 en tema claro, justo por debajo del
       minimo. Una pizca del color de texto lo sube a 6.12:1 sin que deje de
       leerse como texto secundario. */
    color: color-mix(in srgb, var(--ci-text-muted) 70%, var(--ci-text));
    font-size: 0.82rem;
    text-decoration: none;
    transition: color 140ms ease, border-color 140ms ease;
}

.monitor-help-toc-link:hover {
    border-left-color: var(--ci-primary);
    color: var(--ci-primary);
}

.monitor-help-toc-link.is-sub {
    padding-left: 1.4rem;
    font-size: 0.78rem;
}

/* ------------------------------------------------- help by application

   The badge of an application inside Ayuda. Same icon the rail uses, on a
   tinted tile: the section of Cisapp has to be recognisable as the same
   thing as the Cisapp button on the left, or it reads as a second,
   unrelated place. */
.monitor-help-app-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    border-radius: 11px;
    background: color-mix(in srgb, var(--mud-palette-primary) 12%, var(--mud-palette-surface));
    color: var(--mud-palette-primary);
}

.monitor-help-app-mark.is-large {
    width: 52px;
    height: 52px;
    border-radius: 14px;
}

/* The titles previewed inside an application's card. They are not links: the
   whole card already goes to the section, and three competing click targets
   inside one card only make people aim. */
.monitor-help-app-list {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
}

.monitor-help-app-doc {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    color: var(--mud-palette-text-secondary);
    font-size: 0.82rem;
    /* One line each: a long title must not make one card taller than the two
       beside it. */
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.monitor-help-app-doc .mud-icon-root {
    font-size: 1rem;
}

.monitor-help-app-doc.is-more {
    padding-left: 1.45rem;
    font-style: italic;
}

/* ============================================================
   Panels and stat cards
   ============================================================ */

/* The bordered panel that 28 screens were hand-rolling with the same inline
   style. One class, so the border, the radius and the surface are decided
   once instead of being retyped and drifting. */
.app-panel {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 12px;
    background: var(--mud-palette-surface);
}

/* A stat card is a panel that has to match the ones beside it. Same rule as
   .dash-card above and for the same reason: a row of them reads as one band,
   so they stretch to the tallest and share a floor. Without this each card was
   only as tall as its own content and the row came out ragged - which is what
   happened to "Configuradas" between "Zonas" and "Clientes".

   The column flex is also what fixes that card's second problem: MudTooltip
   wraps its child in an inline element, which had dropped the number onto the
   label's line. Direct children of a flex container are blockified, so the
   wrapper stops changing the layout of whatever it is put around. */
.stat-card {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 0.15rem;
    height: 100%;
    min-height: 5.5rem;
}

/* The number. Long values (a customer count in six figures) wrap rather than
   widening the card and pushing the row out of shape. */
.stat-card .mud-typography-h5 {
    overflow-wrap: anywhere;
}


/* ============================================================
   Query filter
   ============================================================ */

/* The parameters of one operation, framed as a block. Loose fields over a flat
   surface read as a form somebody abandoned half-built; a frame says these
   belong together and are filled in before the button beside them is pressed. */
.query-filter {
    padding: 0.9rem 1rem 0.5rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 10px;
    background: color-mix(in srgb, var(--mud-palette-primary) 3%, var(--mud-palette-surface));
}

.query-filter-title {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    margin-bottom: 0.85rem;
    color: var(--mud-palette-text-secondary);
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

/* Every field reserves the same height for its helper line. Without it a row
   that mixes fields carrying help with fields that carry none comes out with
   its boxes at different heights, which is what made this form look ragged. */
.query-filter .mud-input-helper-text {
    min-height: 1.15rem;
    margin-top: 0.2rem;
}

/* The actions belong at the right end and the run button goes last: the eye
   finishes the form exactly where the thing that runs it is. Clearing sits
   beside it because it is the other thing one does with a form - outlined and
   not filled, because it is never the button you want to hit by accident. */
.query-actions {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-top: 1rem;
}

.query-actions-end {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-left: auto;
}

/* ============================================================
   DIALOGS: the shell every form dialog shares

   Before this, a dialog was a string title in the default type
   size, a stack of outlined boxes and two buttons floating over
   the same white as the fields. Nothing said where the form
   started, what it was about, or which parts belonged together --
   and the row of red "es obligatorio" lines that MudBlazor paints
   the moment the form registers its required fields made an empty
   form look like a form somebody had already got wrong.

   The pieces below are what replaces that. They are anchored on
   :has() and not on a class of our own, on purpose: MudDialog puts
   its Class on the container, so a descendant selector can style
   what is inside the paper but never the paper's own corners,
   which is exactly what a header that bleeds to the edges needs.
   :has() also carries the specificity to beat MudBlazor's own
   padding, which matters here because MudBlazor.min.css is linked
   AFTER app.css in App.razor.
   ============================================================ */

.mud-dialog:has(.app-dialog-hero) {
    overflow: hidden;
    border-radius: 16px;
    border: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 65%, transparent);
    box-shadow: 0 24px 48px -12px rgba(15, 23, 42, 0.28), 0 0 0 1px rgba(15, 23, 42, 0.04);
}

/* The header IS the hero: no padding of MudBlazor's own survives, or the
   colour band would sit inset with white margins around three of its sides. */
.mud-dialog:has(.app-dialog-hero) .mud-dialog-title {
    padding: 0;
    margin: 0;
}

.mud-dialog:has(.app-dialog-hero) .mud-dialog-content {
    padding: 1.35rem 1.5rem 0.5rem;
}

/* ------------------------------------------------------------
   The hero header
   ------------------------------------------------------------ */

.app-dialog-hero {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.95rem;
    padding: 1.15rem 1.4rem;
    overflow: hidden;
    color: #fff;
    background: linear-gradient(135deg,
        var(--mud-palette-primary) 0%,
        color-mix(in srgb, var(--mud-palette-primary) 58%, #0B1220) 100%);
}

/* One soft light source in the top right corner. It is what keeps a flat
   band of brand red from reading like a coloured rectangle. */
.app-dialog-hero::after {
    content: "";
    position: absolute;
    top: -140px;
    right: -60px;
    width: 300px;
    height: 300px;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(255, 255, 255, 0.18), transparent 68%);
    pointer-events: none;
}

.app-dialog-hero-icon {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 46px;
    height: 46px;
    border-radius: 13px;
    color: #fff;
    background: rgba(255, 255, 255, 0.16);
    border: 1px solid rgba(255, 255, 255, 0.3);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25);
}

.app-dialog-hero-text {
    position: relative;
    min-width: 0;
}

.app-dialog-hero-eyebrow {
    display: block;
    font-size: 0.64rem;
    font-weight: 800;
    letter-spacing: 0.13em;
    text-transform: uppercase;
    opacity: 0.8;
}

.app-dialog-hero-title {
    margin: 0.1rem 0 0;
    font-size: 1.14rem;
    font-weight: 700;
    line-height: 1.2;
}

.app-dialog-hero-sub {
    margin: 0.18rem 0 0;
    font-size: 0.78rem;
    line-height: 1.35;
    opacity: 0.86;
}

/* ------------------------------------------------------------
   Sections

   A form of nine fields is not nine questions, it is three: who
   it is, where it lives, what it says. The rules carry the
   grouping so the eye can stop reading labels one by one.
   ------------------------------------------------------------ */

.app-dialog-section + .app-dialog-section {
    margin-top: 1.25rem;
}

.app-dialog-section-title {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.7rem;
    color: var(--mud-palette-text-secondary);
    font-size: 0.68rem;
    font-weight: 800;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

.app-dialog-section-title::after {
    content: "";
    flex: 1 1 auto;
    height: 1px;
    background: color-mix(in srgb, var(--mud-palette-lines-default) 80%, transparent);
}

/* ------------------------------------------------------------
   The permission strip

   The four permissions a view generates were a sentence inside an
   alert, which is the one shape in the interface that means
   "something went wrong or nearly did". They are not a warning:
   they are the reason the screen exists, so they are drawn as
   what they are -- four things that will be created.
   ------------------------------------------------------------ */

.app-perm-strip {
    padding: 0.85rem 0.9rem;
    border-radius: 13px;
    border: 1px solid color-mix(in srgb, var(--mud-palette-primary) 22%, transparent);
    background:
        radial-gradient(120% 140% at 0% 0%, color-mix(in srgb, var(--mud-palette-primary) 9%, transparent), transparent 60%),
        var(--mud-palette-surface);
}

.app-perm-strip-head {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    margin-bottom: 0.7rem;
    color: var(--mud-palette-text-primary);
    font-size: 0.79rem;
    line-height: 1.35;
}

.app-perm-strip-head .mud-icon-root {
    flex: 0 0 auto;
    color: var(--mud-palette-primary);
}

.app-perm-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0.45rem;
}

.app-perm-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.28rem;
    padding: 0.55rem 0.3rem;
    border-radius: 10px;
    border: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 75%, transparent);
    background: color-mix(in srgb, var(--mud-palette-background) 45%, var(--mud-palette-surface));
    color: var(--mud-palette-text-secondary);
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.02em;
    text-align: center;
    /* Staggered by --i below: the four cards arrive left to right, which
       reads as "these get created" rather than as decoration. */
    animation: app-perm-pop 320ms cubic-bezier(0.34, 1.56, 0.64, 1) backwards;
    animation-delay: calc(var(--i, 0) * 55ms);
}

.app-perm-card .mud-icon-root {
    color: var(--mud-palette-primary);
}

@keyframes app-perm-pop {
    from {
        opacity: 0;
        transform: translateY(6px) scale(0.94);
    }
}

@media (prefers-reduced-motion: reduce) {
    .app-perm-card {
        animation: none;
    }
}

/* ------------------------------------------------------------
   Live preview of the menu entry

   The three fields that decide how a view shows up in the sidebar
   -- name, group and route -- were three boxes whose result you
   could only see after saving and reloading the menu. Now the
   result is drawn beside them as it is typed.
   ------------------------------------------------------------ */

.app-nav-preview {
    padding: 0.75rem 0.85rem;
    border-radius: 12px;
    border: 1px dashed color-mix(in srgb, var(--mud-palette-lines-default) 90%, transparent);
    background: color-mix(in srgb, var(--mud-palette-background) 70%, var(--mud-palette-surface));
}

.app-nav-preview-label {
    margin-bottom: 0.5rem;
    color: var(--mud-palette-text-secondary);
    font-size: 0.64rem;
    font-weight: 800;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

.app-nav-preview-group {
    margin-bottom: 0.3rem;
    padding-left: 0.15rem;
    color: var(--mud-palette-text-secondary);
    font-size: 0.63rem;
    font-weight: 800;
    letter-spacing: 0.11em;
    text-transform: uppercase;
    opacity: 0.85;
}

.app-nav-preview-item {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    padding: 0.45rem 0.6rem;
    border-radius: 9px;
    border-left: 3px solid var(--monitor-accent);
    background: var(--mud-palette-surface);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
    font-size: 0.84rem;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
}

.app-nav-preview-item .mud-icon-root {
    color: var(--mud-palette-primary);
}

.app-nav-preview-route {
    margin-left: auto;
    max-width: 48%;
    padding: 0.1rem 0.4rem;
    border-radius: 6px;
    background: color-mix(in srgb, var(--mud-palette-background) 80%, var(--mud-palette-surface));
    color: var(--mud-palette-text-secondary);
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 0.7rem;
    font-weight: 500;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.app-nav-preview-empty {
    color: var(--mud-palette-text-secondary);
    font-style: italic;
    font-weight: 400;
}

/* ------------------------------------------------------------
   The footer

   Its own surface and a rule above it: the buttons stop floating
   over the last field, and the primary action always sits in the
   same corner of every dialog in the application.
   ------------------------------------------------------------ */

.mud-dialog:has(.app-dialog-hero) .mud-dialog-actions {
    margin: 0;
    padding: 0.85rem 1.4rem;
    gap: 0.5rem;
    border-top: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 70%, transparent);
    background: color-mix(in srgb, var(--mud-palette-background) 60%, var(--mud-palette-surface));
}

/* A dialog that reports what it is still missing does it here, at the left
   end of the footer, where the eye goes after a button that will not press. */
.app-dialog-hint {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    margin-right: auto;
    color: var(--mud-palette-text-secondary);
    font-size: 0.74rem;
}

/* Every field keeps the same room for its helper line, so a row mixing a
   field that has help with one that has none does not come out ragged. */
.app-dialog-section .mud-input-helper-text {
    min-height: 1.1rem;
}

@media (max-width: 599px) {
    .app-perm-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .app-dialog-hero {
        padding: 1rem 1.1rem;
    }

    .mud-dialog:has(.app-dialog-hero) .mud-dialog-content,
    .mud-dialog:has(.app-dialog-hero) .mud-dialog-actions {
        padding-left: 1.1rem;
        padding-right: 1.1rem;
    }
}

/* ------------------------------------------------------------
   Choice cards

   A closed list of four options that decides how something
   behaves is not a dropdown: everything it can be fits on
   screen, and hiding three of the four behind a click is what
   makes people pick whatever was already selected. Drawn as
   cards, the choice is made once and never reopened.
   ------------------------------------------------------------ */

.app-choice-grid {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 0.5rem;
}

.app-choice-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.3rem;
    padding: 0.7rem 0.4rem;
    border-radius: 12px;
    border: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 80%, transparent);
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-secondary);
    font-size: 0.72rem;
    font-weight: 700;
    text-align: center;
    cursor: pointer;
    transition: border-color 140ms ease, background-color 140ms ease,
                color 140ms ease, transform 140ms ease, box-shadow 140ms ease;
}

.app-choice-card:hover {
    border-color: color-mix(in srgb, var(--mud-palette-primary) 45%, transparent);
    transform: translateY(-1px);
}

.app-choice-card:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

.app-choice-card .mud-icon-root {
    color: var(--mud-palette-text-secondary);
    transition: color 140ms ease;
}

.app-choice-card.is-active {
    border-color: var(--mud-palette-primary);
    color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 8%, var(--mud-palette-surface));
    box-shadow: 0 0 0 1px var(--mud-palette-primary) inset,
                0 6px 14px -8px color-mix(in srgb, var(--mud-palette-primary) 70%, transparent);
}

.app-choice-card.is-active .mud-icon-root {
    color: var(--mud-palette-primary);
}

/* The code a permission will be keyed by, shown as what it is: a literal
   string that has to match somewhere else, not prose. */
.app-code-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.15rem 0.45rem;
    border-radius: 6px;
    border: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 80%, transparent);
    background: color-mix(in srgb, var(--mud-palette-background) 75%, var(--mud-palette-surface));
    color: var(--mud-palette-text-primary);
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
    font-size: 0.74rem;
    word-break: break-all;
}

.app-code-pill.is-empty {
    color: var(--mud-palette-text-secondary);
    font-style: italic;
}

@media (max-width: 599px) {
    .app-choice-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* ==========================================================================
   Published product photos

   The gallery of a published image package. The photos arrive as data URIs --
   the API keeps its container private and streams the package instead of
   handing out signed URLs -- so what these rules style is bytes already in
   the page, not something the browser is going to fetch.
   ========================================================================== */

.market-gallery-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
}

.market-gallery-search {
    flex: 1 1 18rem;
    min-width: 0;
}

.market-gallery {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(9.5rem, 100%), 1fr));
    gap: 0.85rem;
}

/* A button and not a div: opening a photo is an action, and this way it is
   reachable with the keyboard like every other one on the screen. */
.market-thumb {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.55rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 12px;
    background: var(--mud-palette-surface);
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
    transition: border-color 120ms ease, box-shadow 120ms ease, transform 120ms ease;
}

.market-thumb:hover,
.market-thumb:focus-visible {
    border-color: var(--mud-palette-primary);
    box-shadow: 0 8px 18px -12px rgba(0, 0, 0, 0.45);
    transform: translateY(-1px);
    outline: none;
}

/* The frame keeps its height whatever the photo is: a catalog mixes squares
   with tall packaging shots, and without this the grid moves under the
   cursor as each row loads. */
.market-thumb-frame {
    position: relative;
    display: grid;
    place-items: center;
    aspect-ratio: 1 / 1;
    overflow: hidden;
    border-radius: 8px;
    background: color-mix(in srgb, var(--mud-palette-background) 70%, var(--mud-palette-surface));
}

.market-thumb-frame img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

.market-thumb-frame .mud-icon-root {
    color: var(--mud-palette-text-secondary);
    opacity: 0.5;
}

.market-thumb-meta {
    display: flex;
    flex-direction: column;
    min-width: 0;
    line-height: 1.25;
}

.market-thumb-sku {
    color: var(--mud-palette-text-primary);
    font-size: 0.82rem;
    font-weight: 700;
    overflow-wrap: anywhere;
}

.market-thumb-hint {
    color: var(--mud-palette-text-secondary);
    font-size: 0.7rem;
}

/* A magnifier over the thumbnail, on hover and on focus: that a photo opens
   bigger is not something a 9 rem square says by itself. */
.market-thumb-zoom {
    position: absolute;
    right: 0.35rem;
    bottom: 0.35rem;
    display: grid;
    place-items: center;
    padding: 0.15rem;
    border-radius: 999px;
    background: color-mix(in srgb, var(--mud-palette-surface) 85%, transparent);
    color: var(--mud-palette-text-secondary);
    opacity: 0;
    transition: opacity 120ms ease;
}

.market-thumb:hover .market-thumb-zoom,
.market-thumb:focus-visible .market-thumb-zoom {
    opacity: 1;
}

/* ==========================================================================
   The viewer

   One published photo, big, with the rest of the page behind it. The reason
   the photo is worth zooming is that what arrives is the catalog file itself
   and not a thumbnail: at 1:1 this is the pixel the store ends up showing.

   The stage is a window and the photo moves inside it under a transform that
   JavaScript owns (js/image-viewer.js). Nothing here sets that transform --
   these rules only give the window a size, and the size is what the fit is
   computed from.
   ========================================================================== */

.market-viewer {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    gap: 1rem;
}

.market-viewer-main {
    position: relative;
    flex: 1 1 26rem;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.market-viewer-title {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    min-width: 0;
}

.market-viewer-title-text {
    min-width: 0;
    overflow-wrap: anywhere;
}

/* The neutral ground is the same one the thumbnails sit on: these are cut-outs
   with transparency, and a white box would hide their edges.

   overflow:hidden and not auto -- panning is the drag, not a scrollbar, and a
   scrollbar here would fight the wheel, which is zoom. */
.market-viewer-stage {
    position: relative;
    overflow: hidden;
    height: min(62vh, 34rem);
    min-height: 16rem;
    display: grid;
    place-items: center;
    border-radius: 12px;
    background: color-mix(in srgb, var(--mud-palette-background) 70%, var(--mud-palette-surface));

    /* The drag is a pointer gesture; without this the browser scrolls the page
       with it on a touch screen. */
    touch-action: none;
    cursor: zoom-in;
}

.market-viewer-stage:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

.market-viewer-stage.can-pan {
    cursor: grab;
}

.market-viewer-stage.can-pan.is-panning {
    cursor: grabbing;
}

/* Anchored at the middle of the stage: JavaScript translates from there, so a
   photo with no zoom is centered without having to measure anything. */
.market-viewer-stage img {
    position: absolute;
    opacity: 0;
    top: 50%;
    left: 50%;
    max-width: none;
    max-height: none;
    transform: translate(-50%, -50%);
    transform-origin: center center;
    user-select: none;
    -webkit-user-drag: none;
}

.market-viewer-stage.is-ready img {
    opacity: 1;
}

.market-viewer-nav {
    position: absolute;
    top: calc(min(62vh, 34rem) / 2);
    transform: translateY(-50%);
    background: color-mix(in srgb, var(--mud-palette-surface) 80%, transparent);
}

.market-viewer-nav.prev {
    left: 0.5rem;
}

.market-viewer-nav.next {
    right: 0.5rem;
}

.market-viewer-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.25rem;
}

.market-viewer-zoom {
    min-width: 3.5rem;
    color: var(--mud-palette-text-primary);
    font-size: 0.8rem;
    font-variant-numeric: tabular-nums;
    text-align: center;
}

/* The gestures are written down once, quietly: a viewer that only works if
   somebody already knows it works is half a viewer. */
.market-viewer-hint {
    white-space: nowrap;
}

@media (max-width: 60rem) {
    .market-viewer-hint {
        display: none;
    }
}

.market-viewer-side {
    flex: 0 1 19rem;
    min-width: 0;
}

.market-viewer-facts td {
    padding: 0.3rem 0.5rem;
    vertical-align: top;
}

.market-viewer-file {
    overflow-wrap: anywhere;
}

/* A count with a sample of the names behind it, on one line of a grid cell.

   The number keeps the weight because it is what the column sorts and filters by;
   the names are the evidence for it and read as secondary. Only the names are cut
   -- the count must never be the part that turns into an ellipsis -- and the whole
   line travels in the tooltip.

   The colon is drawn here and not written into the text: a send whose names could
   not be resolved shows the count alone instead of ending in a dangling separator. */
.grid-count {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    max-width: 300px;
    vertical-align: middle;
}

.grid-count-value {
    flex: none;
    color: var(--mud-palette-text-primary);
    font-size: 0.9rem;
    font-weight: 700;
    /* Digits of one width, so the numbers of a column line up against each other. */
    font-variant-numeric: tabular-nums;
}

.grid-count-names {
    /* min-width on a flex child is auto, and without this the names refuse to
       shrink and push the column wide instead of ellipsising. */
    min-width: 0;
    color: var(--mud-palette-text-secondary);
    font-size: 0.78rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.grid-count-names::before {
    content: ":";
    /* Symmetric around the colon: the flex gap already puts space before it, so
       only the matching space after it is written here. */
    margin-right: 0.3rem;
    opacity: 0.55;
}

/* ------------------------------------------------------------------- grid density

   Every grid of the back office, not one screen: these rules were scoped to the
   notifications history first and the spacing problem they fix is not its own.

   MudDataGrid ships 16px on all four sides of a cell. On a row carrying two lines
   -- a date over "hace 3 h", a title over its excerpt -- that is a band of empty
   space taller than the text inside it, and it is the same 16px on a row of bare
   numbers. What follows is one rhythm for both. */

.universal-grid-table .mud-table-cell {
    padding: 0.4rem 0.7rem;
    /* Every cell as tall as the tallest of its row. Without this the one-line ones
       hang from the top of a two-line neighbour, which is the gap that reads as
       "the table has a hole in it". */
    vertical-align: middle;
}

.universal-grid-table thead .mud-table-cell {
    text-transform: uppercase;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    color: var(--mud-palette-text-secondary);
}

.universal-grid-table tbody .mud-table-cell {
    border-bottom: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 48%, transparent);
}

/* An accent down the left of the row under the pointer. A row can be two lines
   tall, and a background tint alone is easy to lose while reading across one. */
.universal-grid-table tbody tr:hover {
    box-shadow: inset 3px 0 0 var(--mud-palette-primary);
}

.universal-grid-table .mud-progress-linear {
    border-radius: 999px;
    margin-top: 0.2rem;
}

/* The type, as a filled pill.

   Fixed colours and not palette variables on purpose: these are categories, and a
   category that changes colour with the theme stops being recognisable at a
   glance. All five are dark enough to carry white text in either theme. */
.type-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.25rem 0.65rem;
    vertical-align: middle;
    border-radius: 999px;
    color: #fff;
    font-size: 0.72rem;
    font-weight: 700;
    line-height: 1.45;
    white-space: nowrap;
}

.type-pill .mud-icon-root {
    font-size: 0.95rem;
}

.type-pill.tone-system { background: #2563eb; }
.type-pill.tone-order { background: #0891b2; }
.type-pill.tone-billing { background: #b45309; }
.type-pill.tone-promo { background: #7c3aed; }
.type-pill.tone-security { background: #be123c; }
.type-pill.tone-delivery { background: #0d9488; }
.type-pill.tone-payment { background: #b45309; }
.type-pill.tone-assignment { background: #7c3aed; }

/* The date over "hace 3 h", with one calendar to the left of both. */
.grid-when {
    display: inline-flex;
    align-items: flex-start;
    gap: 0.4rem;
}

.grid-when .mud-icon-root {
    margin-top: 0.12rem;
    color: var(--mud-palette-text-secondary);
    font-size: 1rem;
}

.grid-when-date {
    color: var(--mud-palette-text-primary);
    font-size: 0.82rem;
    font-weight: 600;
    line-height: 1.3;
    white-space: nowrap;
}

.grid-when-age {
    color: var(--mud-palette-text-secondary);
    font-size: 0.72rem;
    line-height: 1.3;
}

/* What the count counts, drawn once instead of repeated in every row as a word. */
.grid-count-icon {
    flex: none;
    /* Tighter to the number than the number is to the names: the icon says what
       the number counts, so the two read as one unit. */
    margin-right: -0.05rem;
    color: var(--mud-palette-text-secondary);
    font-size: 1rem !important;
}

/* The header of the card: a title and one line under it, not a page heading. Left
   at h6 metrics it was taller than the row of controls beside it, and the toolbar
   inherited that height. */
.universal-grid-title-block .mud-typography-h6 {
    margin: 0;
    font-size: 1rem;
    line-height: 1.35;
}

/* Master-table picker: icon + table name over what the table holds, so the
   option list reads as a menu of sections instead of a bare word list. */
.masters-table-option {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    min-height: 40px;
    padding: 0.2rem 0;
}

.masters-table-option .mud-icon-root {
    margin-top: 0.15rem;
    color: var(--mud-palette-primary);
    flex: 0 0 auto;
}

.masters-table-option-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    line-height: 1.3;
}

.masters-table-option-title {
    font-weight: 600;
}

.masters-table-option-description {
    font-size: 0.72rem;
    color: var(--mud-palette-text-secondary);
    white-space: normal;
}

/* The CLOSED select, which reuses the option template as its value: MudSelect renders
   the matching item's fragment rather than its text whenever the value is found among
   the items (see MudSelect.CanRenderValue). So the two-line option landed inside a
   dense input, where the second line does not fit and gets clipped. Only the icon and
   the name survive here; the list below keeps both lines.

   Scoped to the select itself and not to a MudBlazor internal class: the popover is
   rendered outside this element by the popover provider, so it is untouched. */
.masters-table-select .masters-table-option {
    align-items: center;
    min-height: 0;
    padding: 0;
}

.masters-table-select .masters-table-option-description {
    display: none;
}

.masters-table-popover .mud-list-item {
    align-items: flex-start;
}

.masters-table-popover .mud-list-item-text {
    white-space: normal;
}

/* ==========================================================================
   Seller route — /admin-7ci/recorrido

   One seller's day read top to bottom. The stops are a timeline and the metres
   are drawn on the connector that joins two of them, which is where that
   number belongs: as a column it looked like a property of the stop, and the
   first row's empty cell looked like missing data.
   ========================================================================== */

/* -------------------------------------------------------------- filter bar */

/* One row of controls and, pushed to the far end, what the chosen day holds.
   A grid of columns left the button floating below its own row at the widths
   where the select wrapped. */
.track-filters {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
}

.track-filters .track-filter-date {
    flex: 1 1 11rem;
    max-width: 14rem;
}

.track-filters .track-filter-seller {
    flex: 2 1 16rem;
    max-width: 24rem;
}

.track-filters-spacer {
    flex: 1 1 0;
}

.track-filters-count {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    color: var(--mud-palette-text-secondary);
    font-size: 0.78rem;
    font-weight: 600;
    white-space: nowrap;
}

.track-filters-count .mud-icon-root {
    color: var(--mud-palette-text-secondary);
}

/* The separator between two facts on one line. Dimmer than either of them, so
   it groups instead of counting as a third thing. */
.track-dot {
    margin: 0 0.15rem;
    opacity: 0.45;
}

/* ------------------------------------------------------- list beside route */

/* The sellers on the left and the open route on the right, each pane with its
   own scroll. With the route under the list, picking a seller meant scrolling
   past the forty of them to see what they did. */
.track-layout {
    display: grid;
    grid-template-columns: minmax(20rem, 26rem) minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr);
    gap: 1rem;
    min-height: 0;
}

.track-list,
.track-detail {
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain;
}

.track-list {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    padding: 0.4rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 12px;
    background: var(--mud-palette-surface);
}

.track-detail {
    padding-right: 0.25rem;
}

.track-list-empty,
.track-detail-empty {
    padding: 1.5rem 1rem;
    color: var(--mud-palette-text-secondary);
    font-size: 0.85rem;
    text-align: center;
}

.track-detail-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    padding-top: 4rem;
}

/* The quick filters and the order, pinned to the top of the list: the list
   scrolls under them, so the answer to "who has not closed" is always one
   click away instead of a scroll back to the top. */
.track-list-tools {
    position: sticky;
    top: -0.4rem;
    z-index: 2;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    margin: -0.4rem -0.4rem 0;
    padding: 0.5rem 0.55rem;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    background: var(--mud-palette-surface);
}

.track-chip-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem;
}

.track-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.2rem 0.5rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 999px;
    background: transparent;
    color: var(--mud-palette-text-secondary);
    font: inherit;
    font-size: 0.72rem;
    font-weight: 700;
    line-height: 1.6;
    cursor: pointer;
    transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}

.track-chip:hover {
    background: color-mix(in srgb, var(--mud-palette-text-secondary) 8%, transparent);
}

.track-chip:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 1px;
}

.track-chip .mud-icon-root {
    font-size: 0.9rem;
}

/* The chosen one is filled, not merely outlined: on a dark surface a border
   in the tone colour is the difference between reading the filter at a
   glance and hunting for it. */
.track-chip.is-on {
    border-color: transparent;
    background: color-mix(in srgb, var(--mud-palette-info) 22%, transparent);
    color: var(--mud-palette-info);
}

.track-chip.is-on.tone-success {
    background: color-mix(in srgb, var(--mud-palette-success) 22%, transparent);
    color: var(--mud-palette-success);
}

.track-chip.is-on.tone-warning {
    background: color-mix(in srgb, var(--mud-palette-warning) 22%, transparent);
    color: var(--mud-palette-warning);
}

.track-chip-count {
    padding-left: 0.15rem;
    font-variant-numeric: tabular-nums;
    opacity: 0.75;
}

.track-sort-row {
    display: flex;
    align-items: center;
    gap: 0.3rem;
}

.track-sort-row .track-sort-select {
    flex: 1 1 auto;
    min-width: 0;
}

/* One seller: who, how the shift stands, and the day in three figures plus
   the stretch of the clock they covered. A button, so the keyboard reaches it. */
.track-item {
    display: flex;
    flex-direction: column;
    gap: 0.55rem;
    align-items: stretch;
    width: 100%;
    padding: 0.65rem 0.75rem;
    border: 1px solid transparent;
    border-radius: 10px;
    background: transparent;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
    transition: background-color 0.12s ease, border-color 0.12s ease;
}

.track-item:hover {
    background: color-mix(in srgb, var(--mud-palette-text-secondary) 7%, transparent);
}

.track-item:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 1px;
}

/* How the day stands, said in colour on the edge of the card: green for the
   shift that closed -- the day is complete -- blue for the one still running
   and amber for visits with no shift behind them. The tag says the same in
   words; this is what makes it readable while scrolling a list of twenty. */
.track-item.is-done {
    box-shadow: inset 3px 0 0 var(--mud-palette-success);
}

.track-item.is-running {
    box-shadow: inset 3px 0 0 var(--mud-palette-info);
}

.track-item.is-unopened {
    box-shadow: inset 3px 0 0 var(--mud-palette-warning);
}

/* The finished day also carries the tint, so "completada" reads as a state of
   the card and not only as a stripe. */
.track-item.is-done {
    background: color-mix(in srgb, var(--mud-palette-success) 6%, transparent);
}

.track-item.is-done .track-seller-mark {
    background: color-mix(in srgb, var(--mud-palette-success) 16%, transparent);
    color: var(--mud-palette-success);
}

/* An accent down the left and not only a tint: the item is four lines tall,
   and a background alone is easy to lose halfway across it. The one being
   looked at keeps the primary edge over its state colour. */
.track-item.is-open {
    border-color: color-mix(in srgb, var(--mud-palette-primary) 35%, transparent);
    background: color-mix(in srgb, var(--mud-palette-primary) 9%, transparent);
    box-shadow: inset 3px 0 0 var(--mud-palette-primary);
}

.track-item-top {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    min-width: 0;
}

.track-item-top .track-seller-text {
    flex: 1 1 auto;
}

.track-item-top .track-tag {
    flex: 0 0 auto;
}

.track-item-metrics {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.4rem;
}

.track-metric {
    display: flex;
    flex-direction: column;
    gap: 0.05rem;
    padding: 0.35rem 0.5rem;
    border-radius: 8px;
    background: color-mix(in srgb, var(--mud-palette-text-secondary) 8%, transparent);
    line-height: 1.2;
}

.track-metric-value {
    font-size: 0.95rem;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.track-metric-label {
    color: var(--mud-palette-text-secondary);
    font-size: 0.66rem;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}

.track-metric.tone-success .track-metric-value {
    color: var(--mud-palette-success);
}

.track-metric.tone-warning .track-metric-value {
    color: var(--mud-palette-warning);
}

.track-window-times .mud-icon-root {
    margin-right: 0.3rem;
    color: var(--mud-palette-text-secondary);
    font-size: 1rem;
}

.track-seller {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    min-width: 0;
}

/* Initials instead of a photo: the monitor has none, and a first column that is
   only text makes every seller look like the one above. */
.track-seller-mark {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--mud-palette-primary) 14%, transparent);
    color: var(--mud-palette-primary);
    font-size: 0.72rem;
    font-weight: 800;
    letter-spacing: 0.02em;
}

.track-seller-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    line-height: 1.25;
}

.track-seller-name {
    font-size: 0.86rem;
    font-weight: 700;
    overflow-wrap: anywhere;
}

.track-seller-code {
    color: var(--mud-palette-text-secondary);
    font-size: 0.72rem;
}

.track-count {
    font-size: 0.95rem;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
}

/* The stretch of the day each seller covered, all of them on the same clock, so
   one row can be read against the one above without doing arithmetic on four
   times. */
.track-window {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    min-width: 8rem;
}

.track-window-times {
    display: inline-flex;
    align-items: center;
    font-size: 0.8rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.track-arrow {
    margin: 0 0.35rem;
    color: var(--mud-palette-text-secondary);
    opacity: 0.7;
}

.track-window-bar {
    position: relative;
    display: block;
    height: 5px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--mud-palette-lines-default) 70%, transparent);
}

.track-window-fill {
    position: absolute;
    top: 0;
    bottom: 0;
    border-radius: 999px;
    background: var(--mud-palette-primary);
}

/* --------------------------------------------------------------- the seller */

.track-hero {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 0.9rem;
}

.track-hero-mark {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 42px;
    height: 42px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--mud-palette-primary) 14%, transparent);
    color: var(--mud-palette-primary);
    font-size: 0.9rem;
    font-weight: 800;
}

.track-hero-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    line-height: 1.25;
}

.track-hero-name {
    font-size: 1.15rem;
    font-weight: 800;
    overflow-wrap: anywhere;
}

.track-hero-sub {
    color: var(--mud-palette-text-secondary);
    font-size: 0.8rem;
}

/* The denominator of a ratio tile, kept smaller than the number it divides:
   "49 / 49" at one size reads as two separate figures. */
.dash-stat-of {
    margin-left: 0.2rem;
    color: var(--mud-palette-text-secondary);
    font-size: 0.95rem;
    font-weight: 700;
}

/* ------------------------------------------------------------- the timeline */

.track-stops-head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.6rem;
}

.track-stops-title {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.95rem;
    font-weight: 700;
}

.track-stops-title .mud-icon-root {
    color: var(--mud-palette-primary);
}

.track-stops-note {
    color: var(--mud-palette-text-secondary);
    font-size: 0.78rem;
}

.track-timeline {
    margin: 0;
    padding: 0;
    list-style: none;
}

.track-stop {
    display: flex;
    align-items: stretch;
    gap: 0.75rem;
}

.track-stop-rail {
    display: flex;
    flex: 0 0 2.25rem;
    justify-content: center;
    align-items: flex-start;
    padding-top: 0.55rem;
}

/* The order of the stop, on the rail rather than in a column of its own: it is
   the thread of the route, not a field of the visit. */
.track-stop-seq {
    display: grid;
    place-items: center;
    width: 1.85rem;
    height: 1.85rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 50%;
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-secondary);
    font-size: 0.72rem;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
}

.track-stop.tone-success .track-stop-seq {
    border-color: color-mix(in srgb, var(--mud-palette-success) 55%, transparent);
    background: color-mix(in srgb, var(--mud-palette-success) 14%, var(--mud-palette-surface));
    color: var(--mud-palette-success);
}

.track-stop.tone-warning .track-stop-seq {
    border-color: color-mix(in srgb, var(--mud-palette-warning) 55%, transparent);
    background: color-mix(in srgb, var(--mud-palette-warning) 16%, var(--mud-palette-surface));
    color: var(--mud-palette-warning);
}

.track-stop-card {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    flex: 1 1 auto;
    min-width: 0;
    padding: 0.6rem 0.75rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 12px;
    background: var(--mud-palette-surface);
}

.track-stop.tone-warning .track-stop-card {
    border-color: color-mix(in srgb, var(--mud-palette-warning) 35%, var(--mud-palette-lines-default));
}

.track-stop-time {
    flex: 0 0 auto;
    padding-top: 0.05rem;
    font-size: 0.92rem;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.track-stop-main {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    flex: 1 1 auto;
    min-width: 0;
}

.track-stop-client {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.45rem;
    min-width: 0;
}

.track-stop-name {
    font-size: 0.86rem;
    font-weight: 700;
    line-height: 1.3;
    overflow-wrap: anywhere;
}

.track-stop-code {
    color: var(--mud-palette-text-secondary);
    font-size: 0.72rem;
    font-variant-numeric: tabular-nums;
}

.track-stop-tags {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem 0.7rem;
    min-width: 0;
}

.track-stop-actions {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    flex: 0 0 auto;
}

.track-stop-actions .track-order-chip {
    margin: 0;
    font-variant-numeric: tabular-nums;
}

.track-stop-actions .mud-icon-button {
    color: var(--mud-palette-text-secondary);
}

.track-stop-actions .mud-icon-button:hover {
    color: var(--mud-palette-primary);
}

/* What happened at the stop, as a pill. Neutral by default: only a sale and a
   visit that produced nothing earn a colour, so colour keeps meaning something
   in a list of forty rows. */
.track-tag {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.12rem 0.55rem;
    border-radius: 999px;
    background: color-mix(in srgb, var(--mud-palette-text-secondary) 14%, transparent);
    color: var(--mud-palette-text-primary);
    font-size: 0.72rem;
    font-weight: 700;
    line-height: 1.5;
    white-space: nowrap;
}

.track-tag .mud-icon-root {
    color: currentColor;
    font-size: 0.9rem;
}

.track-tag.tone-success {
    background: color-mix(in srgb, var(--mud-palette-success) 16%, transparent);
    color: var(--mud-palette-success);
}

.track-tag.tone-warning {
    background: color-mix(in srgb, var(--mud-palette-warning) 18%, transparent);
    color: var(--mud-palette-warning);
}

.track-tag.tone-info {
    background: color-mix(in srgb, var(--mud-palette-info) 16%, transparent);
    color: var(--mud-palette-info);
}

.track-note {
    display: inline-flex;
    align-items: center;
    gap: 0.28rem;
    min-width: 0;
    color: var(--mud-palette-text-secondary);
    font-size: 0.75rem;
    overflow-wrap: anywhere;
}

.track-note .mud-icon-root {
    flex: 0 0 auto;
    color: var(--mud-palette-text-secondary);
    font-size: 0.95rem;
}

/* The leg between two stops: a dashed line because the straight-line distance
   is not the road that was driven, and the label sits on it. */
.track-leg {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    min-height: 1.9rem;
}

.track-leg-rail {
    display: flex;
    flex: 0 0 2.25rem;
    justify-content: center;
    align-self: stretch;
}

.track-leg-line {
    width: 0;
    border-left: 2px dashed color-mix(in srgb, var(--mud-palette-lines-default) 85%, transparent);
}

.track-leg-label {
    color: var(--mud-palette-text-secondary);
    font-size: 0.72rem;
    font-variant-numeric: tabular-nums;
}

.track-leg-unknown {
    font-style: italic;
    opacity: 0.75;
}

/* ------------------------------------------------------------- route on a map */

/* The map of a route, above the stops that make it up. Leaflet brings its own
   stylesheet from the CDN; what is here is the frame around it, the pins and
   the popups -- everything that has to agree with the rest of the monitor and
   has to work in both themes.

   Lives in app.css and not beside the component because the plugins' scoped
   stylesheets are not served: a .razor.css under a plugin never reaches the
   browser. */
.route-map {
    /* The colour of the line joining the stops, read from JavaScript so light
       and dark are decided once, here. Deliberately a low-chroma grey and not
       a palette hue: the line is the thread of the route, not one more outcome,
       and a coloured one would be read as meaning something. */
    --route-line: #5a6472;

    margin-bottom: 1rem;
}

.mud-theme-dark .route-map {
    --route-line: #8b94a3;
}

.route-map-head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

.route-map-title {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.85rem;
    font-weight: 700;
}

.route-map-note {
    color: var(--mud-palette-text-secondary);
    font-size: 0.78rem;
}

.route-map-actions {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin-left: auto;
}

/* Full screen. A plain button and not a MudButton, because its click is caught
   in the browser: the full-screen API only answers a gesture the browser can
   vouch for, and one that went to the server and came back is not one. Dressed
   here to sit level with the MudButtons beside it. */
.route-map-fs {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.3rem 0.65rem;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--mud-palette-primary);
    font: inherit;
    font-size: 0.8125rem;
    font-weight: 500;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    cursor: pointer;
}

.route-map-fs:hover {
    background: color-mix(in srgb, var(--mud-palette-primary) 10%, transparent);
}

.route-map-fs .mud-icon-root {
    font-size: 1.1rem;
}

/* The block goes full screen whole -- header, map and legend -- because a map
   with six colours and no legend is a map with no colours.

   .is-fullscreen is put on by route-map.js and is what actually carries the
   layout: the pseudo-class is spelled differently from browser to browser and
   is missing altogether in some embedded ones, and a block that goes full
   screen without growing is the failure this is for. */
.route-map:fullscreen,
.route-map:-webkit-full-screen,
.route-map.is-fullscreen {
    display: flex;
    flex-direction: column;
    padding: 1rem 1.25rem;
    background: var(--mud-palette-surface);
}

/* Only the class needs this. The element the browser put in full screen is
   already the size of the screen -- that is the user agent's doing, not ours --
   but a block that is only wearing the class has nothing telling it how tall to
   be, and a column of flex children with no height collapses to nothing. */
.route-map.is-fullscreen {
    position: fixed;
    /* The four insets and no width or height: that fills the viewport whatever
       box-sizing is in play. With height:100% the padding is added on top of
       the screen and the legend falls off the bottom edge. */
    inset: 0;
    z-index: 1500;
    border-radius: 0;
}

.route-map:fullscreen .route-map-stage,
.route-map:-webkit-full-screen .route-map-stage,
.route-map.is-fullscreen .route-map-stage {
    flex: 1 1 auto;
    height: auto !important;
}

/* The label follows the state, in CSS: .NET does not get told when the browser
   leaves full screen on Escape, and a button reading "Pantalla completa" while
   already in it would be lying. */
.route-map-fs-out {
    display: none;
}

.route-map:fullscreen .route-map-fs-in,
.route-map:-webkit-full-screen .route-map-fs-in,
.route-map.is-fullscreen .route-map-fs-in {
    display: none;
}

.route-map:fullscreen .route-map-fs-out,
.route-map:-webkit-full-screen .route-map-fs-out,
.route-map.is-fullscreen .route-map-fs-out {
    display: inline-flex;
}

/* The frame. A stacking context of its own, because Leaflet lifts its controls
   to z-index 1000 and without this they would climb over the app bar and over
   any dialog the map happens to be inside. */
.route-map-stage {
    position: relative;
    z-index: 0;
    width: 100%;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 12px;
    background: var(--mud-palette-background-gray);
    overflow: hidden;
}

/* Folded away when the map is not coming at all: an empty box the size of a
   map, sitting over the message that explains why, reads as broken twice. The
   canvas stays in the tree behind it so a retry has somewhere to draw. */
.route-map-stage.is-blank {
    height: 0 !important;
    border: 0;
}

.route-map-canvas {
    position: absolute;
    inset: 0;
}

.route-map-wait {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    color: var(--mud-palette-text-secondary);
    font-size: 0.8rem;
}

.route-map-legend {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-top: 0.45rem;
    color: var(--mud-palette-text-secondary);
    font-size: 0.72rem;
}

/* Every entry is the switch that leaves its own colour on the map: six colours
   is more than colour alone can carry where any two pins can touch, and asking
   about one leaves a single colour in play. */
.route-map-key {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.2rem 0.55rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 999px;
    background: transparent;
    color: var(--mud-palette-text-secondary);
    font: inherit;
    font-size: 0.72rem;
    cursor: pointer;
}

.route-map-key:hover {
    border-color: var(--mud-palette-text-secondary);
}

.route-map-key.is-on {
    border-color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 12%, transparent);
    color: var(--mud-palette-text-primary);
    font-weight: 700;
}

.route-map-key.is-off {
    opacity: 0.55;
}

/* The shift marks are not an outcome and there is nothing to isolate. */
.route-map-key.is-static {
    cursor: default;
    border-style: dashed;
}

.route-key-count {
    font-variant-numeric: tabular-nums;
    font-weight: 700;
}

.route-key-mark {
    flex: 0 0 auto;
    width: 0.75rem;
    height: 0.75rem;
    border-radius: 50%;
    background: var(--route-cat);
}

.route-key-mark.shape-square {
    border-radius: 3px;
}

.route-key-mark.shape-diamond {
    border-radius: 2px;
    transform: rotate(45deg);
}

.route-key-mark.shape-ring {
    box-shadow: inset 0 0 0 2px color-mix(in srgb, #fff 80%, transparent);
}

.route-key-flag {
    width: 0.7rem;
    height: 0.7rem;
    border: 2px solid var(--mud-palette-info);
    border-radius: 3px;
    background: color-mix(in srgb, var(--mud-palette-info) 35%, var(--mud-palette-surface));
}

.route-map-hint {
    margin-top: 0.35rem;
    color: var(--mud-palette-text-secondary);
    font-size: 0.72rem;
    opacity: 0.85;
}

/* --------------------------------------------------------- what came of it */

/* A colour per outcome: the sale in green, and every reason a visit did not
   end in one with a hue of its own.

   The hues are the validated categorical order, taken in its fixed slot order
   and never cycled. Two of the eight slots are deliberately unused: yellow,
   documented as too close to orange to sit beside it, and the palette's own
   green, which next to the green of a sale would be a second green meaning
   something else. Green itself is the status colour for "good", which is what
   a sale is -- it is not one of the series.

   The dark column is the same hues stepped for a dark surface, not an
   automatic flip of the light ones. */
.route-cat-sale {
    --route-cat: #0ca30c;
}

.route-cat-1 {
    --route-cat: #2a78d6;
}

.route-cat-2 {
    --route-cat: #eb6834;
}

.route-cat-3 {
    --route-cat: #1baf7a;
}

.route-cat-4 {
    --route-cat: #e87ba4;
}

.route-cat-5 {
    --route-cat: #4a3aa7;
}

.route-cat-6 {
    --route-cat: #e34948;
}

/* Past six outcomes the rest share one grey rather than wear a hue invented
   for them, which nobody could tell from the six that mean something. */
.route-cat-other {
    --route-cat: #6b6b66;
}

.mud-theme-dark .route-cat-1 {
    --route-cat: #3987e5;
}

.mud-theme-dark .route-cat-2 {
    --route-cat: #d95926;
}

.mud-theme-dark .route-cat-3 {
    --route-cat: #199e70;
}

.mud-theme-dark .route-cat-4 {
    --route-cat: #d55181;
}

.mud-theme-dark .route-cat-5 {
    --route-cat: #9085e9;
}

.mud-theme-dark .route-cat-6 {
    --route-cat: #e66767;
}

.mud-theme-dark .route-cat-other {
    --route-cat: #96968f;
}

/* -------------------------------------------------------------------- pins */

/* The stop, filled with the colour of what came of it and carrying its number.
   Filled and not outlined: the colour is the thing being read here, and an
   outline of it on a map of roofs and streets is not enough to read at a
   glance. The ring is the surface, which keeps two pins on top of each other
   from melting into one blob. */
.route-pin {
    display: grid;
    place-items: center;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: var(--route-cat, #6b6b66);
    box-shadow: 0 0 0 2px var(--mud-palette-surface), 0 1px 4px rgb(0 0 0 / 40%);
    color: #fff;

    /* The numbers sit on six different fills, and white alone is not readable
       on the lighter of them. */
    text-shadow: 0 1px 1px rgb(0 0 0 / 55%);
    font-size: 0.66rem;
    font-weight: 800;
    font-style: normal;
    font-variant-numeric: tabular-nums;
    line-height: 1;
    transition: opacity 0.15s ease;
}

.route-pin i {
    font-style: normal;
}

/* The second channel. Colour is doing identity work for six values on a canvas
   where any two pins can end up side by side, which is past what colour carries
   on its own -- so the shape carries it too, and the same shape is only ever
   reused on a hue far away from it (square on orange and violet, diamond on
   aqua and red). */
.route-pin.shape-square {
    border-radius: 5px;
}

.route-pin.shape-diamond {
    border-radius: 4px;
    transform: rotate(45deg);
}

.route-pin.shape-diamond i {
    transform: rotate(-45deg);
}

.route-pin.shape-ring {
    box-shadow: 0 0 0 2px var(--mud-palette-surface),
                inset 0 0 0 3px color-mix(in srgb, #fff 75%, transparent),
                0 1px 4px rgb(0 0 0 / 40%);
}

/* Asked about one outcome, the rest stay on the map but step back: taking them
   away would leave a route with holes in it and no way to see that the asked-for
   one is all in one corner. */
.route-pin.is-dim {
    opacity: 0.18;
}

/* Zoomed out, eighty numbered discs are a smudge: they drop to dots, and the
   numbers come back on the way in. The shapes stay. */
.route-map-canvas.is-far .route-pin {
    width: 13px;
    height: 13px;
}

.route-map-canvas.is-far .route-pin i {
    display: none;
}

/* Where the shift was opened and where it was closed. Squarer than a stop,
   because they are not stops. */
.route-mark {
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    border: 2px solid var(--mud-palette-info);
    border-radius: 8px;
    background: color-mix(in srgb, var(--mud-palette-info) 20%, var(--mud-palette-surface));
    box-shadow: 0 1px 5px rgb(0 0 0 / 40%);
    color: var(--mud-palette-info);
    font-size: 0.8rem;
}

.route-mark.tone-success {
    border-color: var(--mud-palette-success);
    background: color-mix(in srgb, var(--mud-palette-success) 20%, var(--mud-palette-surface));
    color: var(--mud-palette-success);
}

/* ------------------------------------------------------------------ popups */

.route-pop {
    min-width: 11rem;
    font-size: 0.78rem;
    line-height: 1.35;
}

.route-pop-top {
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
}

.route-pop-name {
    font-weight: 700;
    font-size: 0.83rem;
}

.route-pop-code,
.route-pop-meta {
    color: var(--mud-palette-text-secondary);
    font-size: 0.72rem;
}

.route-pop-tags {
    margin-top: 0.15rem;
}

.route-pop-order {
    margin-top: 0.2rem;
    color: var(--mud-palette-success);
    font-weight: 700;
}

.route-pop-warn {
    margin-top: 0.2rem;
    color: var(--mud-palette-warning);
}

.route-pop-link {
    display: inline-block;
    margin-top: 0.35rem;
}

/* Leaflet paints its popups and controls white; in dark mode they have to
   follow the theme like everything else. */
.mud-theme-dark .route-map-canvas .leaflet-popup-content-wrapper,
.mud-theme-dark .route-map-canvas .leaflet-popup-tip,
.mud-theme-dark .route-map-canvas .leaflet-control-zoom a,
.mud-theme-dark .route-map-canvas .leaflet-control-attribution {
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
}

.mud-theme-dark .route-map-canvas .leaflet-control-zoom a {
    border-color: var(--mud-palette-lines-default);
}

/* The tiles come in one flavour only, so dark mode is made here. Only the tile
   pane is touched: inverting the whole map would flip the pins and the popups
   along with it. */
.mud-theme-dark .route-map-canvas .leaflet-tile-pane {
    filter: invert(1) hue-rotate(180deg) brightness(0.92) contrast(0.92);
}

/* ------------------------------------------------------------------ narrow */

/* Below this the two panes do not fit side by side: they stack, the list keeps
   a bounded height of its own and the page scrolls as a whole again. */
@media (max-width: 960px) {
    .track-layout {
        display: flex;
        flex: 0 0 auto;
        flex-direction: column;
    }

    .track-list {
        max-height: 45vh;
    }

    .track-detail {
        overflow: visible;
    }
}

@media (max-width: 700px) {
    .track-filters .track-filter-date,
    .track-filters .track-filter-seller {
        flex: 1 1 100%;
        max-width: none;
    }

    .track-filters-spacer {
        display: none;
    }

    /* The card stacks instead of shrinking: at this width the time and the
       actions squeezed the client name down to two letters per line. */
    .track-stop-card {
        flex-wrap: wrap;
    }

    .track-stop-actions {
        width: 100%;
        justify-content: flex-end;
    }
}

/* ==================================================================
   7CI - approval request detail (ApprovalRequestDetailDialog)

   Here and not in a .razor.css: the Host never links a plugin's scoped
   bundle, and the dialog renders in MudBlazor's provider, outside the
   page. Every colour comes from the palette, so the same rules serve the
   light and the dark theme. The tone-* classes are the one mapping from a
   state to a colour, shared by the status pill, chips, steps and dots.
   ================================================================== */

/* FIXED SIZE. The dialog does not follow its content: opening another tab or a
   longer history used to resize it and move everything under the pointer. It
   takes most of the screen, and what does not fit scrolls inside its own area --
   the tab panel on the left, the decision panel on the right. The summary and
   the tab bar never scroll away. */
.mud-dialog.apr-dialog {
    width: min(1680px, 96vw);
    max-width: none;
    height: 92vh;
    display: flex;
    flex-direction: column;
}

.apr-dialog .mud-dialog-content {
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
    padding-bottom: 1rem;
}

.apr-dialog .apr-layout {
    height: 100%;
    align-items: stretch;
}

.apr-dialog .apr-column {
    min-height: 0;
}

.apr-dialog .apr-column > .apr-card:first-child {
    flex: 0 0 auto;
}

.apr-dialog .apr-tabs-card {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.apr-dialog .apr-tabs {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.apr-dialog .apr-tabs .mud-tabs-panels {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding-right: 0.4rem;
}

.apr-dialog .apr-side {
    overflow-y: auto;
    padding-right: 0.2rem;
}

.apr-title {
    display: flex;
    align-items: center;
    gap: 0.9rem;
    padding-right: 2.5rem; /* room for MudBlazor's close button */
}

.apr-title-icon {
    display: inline-grid;
    place-items: center;
    width: 2.6rem;
    height: 2.6rem;
    flex: 0 0 auto;
    border-radius: 10px;
    background: var(--mud-palette-info);
}

.apr-title-icon .mud-icon-root { color: #fff; }

.apr-title-text {
    font-size: 1.45rem;
    font-weight: 800;
    letter-spacing: -0.01em;
}

.apr-layout {
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    gap: 1rem;
    align-items: start;
}

.apr-column {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    min-width: 0;
}

.apr-card {
    padding: 1rem 1.1rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 12px;
    background: color-mix(in srgb, var(--mud-palette-surface) 94%, var(--mud-palette-background));
}

.apr-card-head {
    display: flex;
    align-items: center;
    gap: 0.65rem;
    margin-bottom: 0.85rem;
}

.apr-card-head > .mud-icon-root { color: var(--mud-palette-info); }

.apr-card-title {
    flex: 1 1 auto;
    min-width: 0;
    margin: 0;
    font-size: 1.05rem;
    font-weight: 700;
}

.apr-card-title-lg {
    font-size: 1.3rem;
    font-weight: 800;
}

.apr-head-icon {
    display: inline-grid;
    place-items: center;
    width: 2.2rem;
    height: 2.2rem;
    flex: 0 0 auto;
    border-radius: 8px;
    background: color-mix(in srgb, var(--mud-palette-info) 18%, transparent);
}

.apr-head-icon .mud-icon-root { color: var(--mud-palette-info); }

/* ------------------------------------------------------------ tones */

:is(.apr-dialog, .aprt-dialog) .tone-warning { --apr-tone: var(--mud-palette-warning); }
:is(.apr-dialog, .aprt-dialog) .tone-info { --apr-tone: var(--mud-palette-info); }
:is(.apr-dialog, .aprt-dialog) .tone-success { --apr-tone: var(--mud-palette-success); }
:is(.apr-dialog, .aprt-dialog) .tone-error { --apr-tone: var(--mud-palette-error); }
:is(.apr-dialog, .aprt-dialog) .tone-primary { --apr-tone: var(--mud-palette-primary); }
:is(.apr-dialog, .aprt-dialog) .tone-secondary { --apr-tone: var(--mud-palette-secondary); }
:is(.apr-dialog, .aprt-dialog) .tone-default { --apr-tone: var(--mud-palette-text-secondary); }

.apr-status {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.4rem 0.9rem;
    border-radius: 999px;
    font-size: 0.9rem;
    font-weight: 700;
    white-space: nowrap;
    color: #fff;
    background: var(--apr-tone);
}

/* Amber carries dark text: white on it fails contrast in both themes. */
.apr-status.tone-warning { color: #1f1400; }

.apr-status .mud-icon-root { color: inherit; }

.apr-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.2rem 0.6rem;
    border: 1px solid color-mix(in srgb, var(--apr-tone) 55%, transparent);
    border-radius: 999px;
    font-size: 0.8rem;
    color: var(--mud-palette-text-primary);
    background: color-mix(in srgb, var(--apr-tone) 10%, transparent);
}

.apr-chip .mud-icon-root {
    font-size: 1rem;
    color: var(--apr-tone);
}

/* ------------------------------------------------------------ facts */

.apr-facts {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: 1.5rem;
}

.apr-fact {
    display: flex;
    gap: 0.85rem;
    min-width: 0;
    padding: 0.85rem 0;
    border-bottom: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 70%, transparent);
}

.apr-fact-wide { grid-column: 1 / -1; }

.apr-fact-icon.mud-icon-root {
    flex: 0 0 auto;
    margin-top: 0.15rem;
    color: var(--mud-palette-info);
}

.apr-fact-label {
    margin-bottom: 0.15rem;
    font-size: 0.85rem;
    color: var(--mud-palette-info);
}

.apr-fact-value {
    font-size: 0.98rem;
    overflow-wrap: anywhere;
}

.apr-fact-hint {
    margin-top: 0.1rem;
    font-size: 0.82rem;
    color: var(--mud-palette-text-secondary);
}

.apr-mono {
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    letter-spacing: 0.01em;
}

.apr-block {
    display: flex;
    gap: 0.85rem;
    padding: 0.9rem 0;
    border-bottom: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 70%, transparent);
}

.apr-block:last-child {
    padding-bottom: 0.2rem;
    border-bottom: 0;
}

.apr-block-body {
    flex: 1 1 auto;
    min-width: 0;
}

.apr-block-title {
    margin-bottom: 0.25rem;
    font-weight: 600;
}

.apr-block-text {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.apr-code {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    margin-top: 0.35rem;
    padding: 0.55rem 0.4rem 0.55rem 0.8rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    background: color-mix(in srgb, var(--mud-palette-background) 55%, var(--mud-palette-surface));
}

.apr-code pre {
    flex: 1 1 auto;
    margin: 0;
    padding-top: 0.2rem;
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    font-size: 0.85rem;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

/* ------------------------------------------------------------ documents */

.apr-count {
    padding: 0.15rem 0.65rem;
    border-radius: 999px;
    font-size: 0.85rem;
    font-weight: 700;
    background: color-mix(in srgb, var(--mud-palette-text-primary) 10%, transparent);
}

.apr-required {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin: 0.2rem 0 0.75rem;
}

.apr-docs {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.apr-doc {
    display: flex;
    align-items: center;
    gap: 1rem;
    padding: 0.6rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 10px;
}

.apr-doc-thumb {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 8.5rem;
    height: 6.9rem;
    padding: 0;
    overflow: hidden;
    border: 0;
    border-radius: 8px;
    cursor: pointer;
    color: var(--mud-palette-text-secondary);
    background: color-mix(in srgb, var(--mud-palette-text-primary) 6%, transparent);
}

.apr-doc-thumb img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.apr-doc-thumb:focus-visible {
    outline: 2px solid var(--mud-palette-info);
    outline-offset: 2px;
}

.apr-doc-info {
    flex: 1 1 auto;
    min-width: 0;
}

.apr-doc-name {
    overflow: hidden;
    font-weight: 600;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.apr-doc-meta {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    margin-top: 0.2rem;
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary);
}

.apr-doc-actions {
    display: flex;
    align-items: center;
    flex: 0 0 auto;
}

.apr-zoom {
    max-width: 90vw;
    max-height: 85vh;
    border-radius: 6px;
}

.apr-empty {
    font-size: 0.9rem;
    color: var(--mud-palette-text-secondary);
}

/* ------------------------------------------------------------ steps */

.apr-steps {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.apr-step {
    display: flex;
    gap: 0.6rem;
}

.apr-step-icon.mud-icon-root {
    margin-top: 0.15rem;
    color: var(--apr-tone);
}

.apr-step-body {
    flex: 1 1 auto;
    min-width: 0;
}

.apr-step-name { font-weight: 600; }

.apr-step-meta {
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary);
}

.apr-step .apr-required { margin: 0.4rem 0 0.2rem; }

.apr-vote {
    display: flex;
    align-items: flex-start;
    gap: 0.3rem;
    margin-top: 0.25rem;
    font-size: 0.82rem;
}

.apr-vote .mud-icon-root {
    font-size: 1rem;
    color: var(--apr-tone);
}

/* ------------------------------------------------------------ decide */

.apr-waiting {
    display: flex;
    gap: 0.75rem;
    padding: 0.85rem 1rem;
    border: 1px solid color-mix(in srgb, var(--mud-palette-info) 45%, transparent);
    border-radius: 12px;
    background: color-mix(in srgb, var(--mud-palette-info) 10%, transparent);
}

.apr-waiting > .mud-icon-root { color: var(--mud-palette-info); }

.apr-field-label {
    margin-bottom: 0.35rem;
    font-weight: 500;
}

.apr-ask-doc {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin-top: 0.75rem;
    padding: 0.15rem 0.2rem 0.15rem 0.85rem;
    border: 1px solid var(--mud-palette-lines-inputs);
    border-radius: 8px;
}

.apr-ask-doc-icon.mud-icon-root { color: var(--mud-palette-info); }

.apr-ask-doc-input {
    flex: 1 1 auto;
    margin: 0 !important;
}

.apr-ask-doc-add.mud-icon-button {
    border-left: 1px solid var(--mud-palette-lines-default);
    border-radius: 0 6px 6px 0;
}

.apr-switch { margin-top: 0.6rem; }

.apr-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
    margin-top: 0.9rem;
}

.apr-btn.mud-button-root {
    min-height: 2.6rem;
    padding-inline: 1rem;
    border-radius: 8px;
    font-weight: 600;
}

.apr-step-hint {
    margin-top: 0.85rem;
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary);
}

/* ------------------------------------------------------------ timeline */

.apr-timeline {
    position: relative;
    margin: 0;
    padding: 0 0 0 2.6rem;
    list-style: none;
}

/* The rail the dots sit on. */
.apr-timeline::before {
    content: "";
    position: absolute;
    top: 0.3rem;
    bottom: 0.3rem;
    left: 0.95rem;
    width: 2px;
    border-radius: 2px;
    background: var(--mud-palette-lines-default);
}

.apr-event {
    position: relative;
    padding-bottom: 1rem;
}

.apr-event:last-child { padding-bottom: 0; }

.apr-event-dot {
    position: absolute;
    top: 0.2rem;
    left: -2.1rem;
    width: 0.95rem;
    height: 0.95rem;
    border-radius: 50%;
    background: var(--apr-tone);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--apr-tone) 22%, var(--mud-palette-surface));
}

.apr-event-title { font-weight: 600; }

.apr-event-meta {
    margin-top: 0.1rem;
    font-size: 0.82rem;
    color: var(--mud-palette-text-secondary);
}

.apr-event-text {
    margin-top: 0.3rem;
    white-space: pre-wrap;
    overflow-wrap: anywhere;
}

.apr-event-file {
    display: flex;
    align-items: flex-start;
    gap: 0.3rem;
    margin-top: 0.35rem;
    font-size: 0.82rem;
    color: var(--mud-palette-text-secondary);
    overflow-wrap: anywhere;
}

.apr-event-file .mud-icon-root {
    flex: 0 0 auto;
    font-size: 1rem;
}

/* ------------------------------------------------------------ summary + tabs */

.apr-layout-single { grid-template-columns: minmax(0, 1fr); }

.apr-reason { padding-top: 0.85rem; }

/* A long reason shows three lines until asked for the rest. */
.apr-clamp {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.apr-more.mud-button-root {
    margin-top: 0.2rem;
    margin-left: -0.5rem;
}

.apr-tabs-card { padding: 0.25rem 1.1rem 1rem; }

.apr-tabs .mud-tabs-tabbar {
    border-bottom: 1px solid var(--mud-palette-lines-default);
    background: transparent;
}

.apr-tabs .mud-tab {
    min-width: 0;
    padding-inline: 0.9rem;
    text-transform: none;
    font-weight: 600;
    letter-spacing: 0;
}

.apr-tabs .mud-tab.mud-tab-active { color: var(--mud-palette-info); }

.apr-tab-body { padding-top: 1rem; }

.apr-list {
    display: grid;
    grid-template-columns: minmax(8rem, auto) minmax(0, 1fr);
    gap: 0.55rem 1.25rem;
    margin: 0;
}

.apr-list dt {
    font-size: 0.85rem;
    color: var(--mud-palette-info);
}

.apr-list dd {
    margin: 0;
    overflow-wrap: anywhere;
}

.apr-btn-main.mud-button-root { flex: 1 1 100%; }

.apr-step-hint {
    display: flex;
    align-items: flex-start;
    gap: 0.4rem;
}

.apr-step-hint .mud-icon-root {
    flex: 0 0 auto;
    color: var(--mud-palette-warning);
}

/* ------------------------------------------------------------ narrow */

/* ==================================================================
   7CI - approval request TYPE editor (ApprovalRequestTypeDialog)

   Reuses the apr- cards, chips, tabs and title. Fixed size for the same
   reason as the detail: switching between General, Documentos and
   Aprobación must not resize the dialog. Only the open tab scrolls; the
   tab bar and the Guardar button stay put.
   ================================================================== */

.mud-dialog.aprt-dialog {
    width: min(1280px, 96vw);
    max-width: none;
    height: 90vh;
    display: flex;
    flex-direction: column;
}

.aprt-dialog .mud-dialog-content {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.aprt-dialog .aprt-tabs {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

.aprt-dialog .aprt-tabs .mud-tabs-panels {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    padding-right: 0.4rem;
}

.aprt-dialog .mud-dialog-actions {
    border-top: 1px solid var(--mud-palette-lines-default);
    padding: 0.75rem 1.5rem;
}

.aprt-title-text {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-width: 0;
    line-height: 1.2;
}

.aprt-title-code {
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary);
}

.aprt-panel {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    padding: 1rem 0 0.5rem;
}

.aprt-section-head {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    margin-bottom: 1rem;
}

.aprt-section-head > .mud-icon-root {
    margin-top: 0.1rem;
    color: var(--mud-palette-info);
}

.aprt-section-head h3 {
    margin: 0;
    font-size: 1.02rem;
    font-weight: 700;
}

.aprt-section-head p,
.aprt-panel-head p {
    margin: 0.1rem 0 0;
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary);
}

.aprt-panel-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.75rem 1.5rem;
}

.aprt-panel-head p {
    flex: 1 1 22rem;
    margin: 0;
}

/* Fields sit on a grid instead of MudGrid: the helper texts under a row no
   longer push one field lower than its neighbour. */
.aprt-grid {
    display: grid;
    gap: 0.25rem 1rem;
    align-items: start;
}

.aprt-grid .mud-input-control { margin-top: 0; }

.aprt-grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.aprt-grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.aprt-grid-doc { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr) minmax(0, 1.6fr) minmax(7rem, 0.6fr); }
.aprt-grid-step { grid-template-columns: minmax(6rem, 0.5fr) minmax(0, 2fr) minmax(0, 1fr) minmax(0, 1.2fr); }

.aprt-span-2 { grid-column: span 2; }
.aprt-span-all { grid-column: 1 / -1; }

.aprt-mono input {
    font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
    letter-spacing: 0.02em;
}

/* The three switches as cards: each says what being on means, so nobody has
   to guess what "Requiere aprobación" off actually does. */
.aprt-toggles {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.75rem;
}

.aprt-toggle {
    display: flex;
    align-items: flex-start;
    gap: 0.35rem;
    padding: 0.6rem 0.75rem 0.7rem 0.35rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 10px;
    transition: border-color 0.15s, background-color 0.15s;
}

.aprt-toggle.on {
    border-color: color-mix(in srgb, var(--mud-palette-info) 45%, transparent);
    background: color-mix(in srgb, var(--mud-palette-info) 7%, transparent);
}

.aprt-toggle .mud-switch { margin: 0; }

.aprt-toggle-title {
    padding-top: 0.45rem;
    font-weight: 600;
}

.aprt-toggle-hint {
    margin-top: 0.1rem;
    font-size: 0.82rem;
    color: var(--mud-palette-text-secondary);
}

.aprt-item { padding-top: 0.75rem; }

.aprt-item-head {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    margin-bottom: 0.85rem;
}

.aprt-number {
    display: inline-grid;
    place-items: center;
    flex: 0 0 auto;
    width: 1.8rem;
    height: 1.8rem;
    border-radius: 8px;
    font-weight: 800;
    font-size: 0.9rem;
    color: var(--mud-palette-info);
    background: color-mix(in srgb, var(--mud-palette-info) 16%, transparent);
}

.aprt-number-step {
    border-radius: 50%;
    color: #fff;
    background: var(--mud-palette-info);
}

.aprt-item-title {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    font-weight: 700;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.aprt-item-switch { margin: 0; }

.aprt-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.5rem;
    padding: 2.5rem 1rem;
    border: 1px dashed var(--mud-palette-lines-default);
    border-radius: 12px;
    text-align: center;
    color: var(--mud-palette-text-secondary);
}

.aprt-steps {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.aprt-step.is-invalid { border-color: color-mix(in srgb, var(--mud-palette-error) 60%, transparent); }

.aprt-subhead {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    margin: 0.75rem 0 0.5rem;
    padding-top: 0.75rem;
    border-top: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 70%, transparent);
    font-weight: 600;
}

.aprt-subhead > .mud-icon-root { color: var(--mud-palette-info); }

.aprt-hint {
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary);
}

.aprt-approvers {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(19rem, 1fr));
    gap: 0.5rem;
}

.aprt-approver {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    min-width: 0;
    padding: 0.35rem 0.35rem 0.35rem 0.5rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 10px;
}

.aprt-avatar {
    display: inline-grid;
    place-items: center;
    flex: 0 0 auto;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    background: color-mix(in srgb, var(--mud-palette-info) 16%, transparent);
}

.aprt-avatar .mud-icon-root { color: var(--mud-palette-info); }

.aprt-approver-text {
    flex: 1 1 auto;
    min-width: 0;
}

.aprt-approver-name,
.aprt-approver-meta {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.aprt-approver-name { font-weight: 600; }

.aprt-approver-meta {
    font-size: 0.8rem;
    color: var(--mud-palette-text-secondary);
}

.aprt-rule {
    display: flex;
    align-items: flex-start;
    gap: 0.45rem;
    margin-top: 0.6rem;
    padding: 0.55rem 0.75rem;
    border-radius: 8px;
    font-size: 0.85rem;
    background: color-mix(in srgb, var(--apr-tone) 10%, transparent);
}

.aprt-rule .mud-icon-root {
    flex: 0 0 auto;
    color: var(--apr-tone);
}

.aprt-add-approver {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem 0.75rem;
    margin-top: 0.75rem;
    padding: 0.6rem 0.75rem;
    border: 1px dashed var(--mud-palette-lines-inputs);
    border-radius: 10px;
}

.aprt-add-approver .mud-input-control { margin-top: 0; }

.aprt-add-type { flex: 0 0 8.5rem; }

.aprt-add-who { flex: 1 1 18rem; }

.aprt-footer {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
}

.aprt-footer-warn {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.85rem;
    color: var(--mud-palette-warning);
}

.aprt-footer-warn .mud-icon-root { color: inherit; }

/* Narrow screens stack the columns, so the fixed height goes: the dialog scrolls
   as a whole again instead of squeezing two scroll areas into one phone. */
@media (max-width: 960px) {
    .apr-layout { grid-template-columns: minmax(0, 1fr); }

    .mud-dialog.apr-dialog { height: auto; max-height: 96vh; }

    .apr-dialog .mud-dialog-content { overflow-y: auto; }

    .apr-dialog .apr-layout { height: auto; }

    .apr-dialog .apr-tabs .mud-tabs-panels,
    .apr-dialog .apr-side { overflow: visible; }

    .aprt-grid-3,
    .aprt-grid-doc,
    .aprt-grid-step,
    .aprt-toggles { grid-template-columns: repeat(2, minmax(0, 1fr)); }

    .aprt-span-2 { grid-column: 1 / -1; }
}

@media (max-width: 600px) {
    .mud-dialog.aprt-dialog { height: 96vh; }

    .aprt-grid-2,
    .aprt-grid-3,
    .aprt-grid-doc,
    .aprt-grid-step,
    .aprt-toggles { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 600px) {
    .apr-facts { grid-template-columns: minmax(0, 1fr); }

    .apr-list { grid-template-columns: minmax(0, 1fr); }

    .apr-list dd { margin-bottom: 0.4rem; }

    .apr-doc-thumb {
        width: 5.5rem;
        height: 4.5rem;
    }

    .apr-title-text { font-size: 1.15rem; }
}

/* ===================================================================
   Soporte remoto (7CI > Dispositivos): DeviceCommandsPanel.razor.
   Global on purpose: the host does not reference the plugin assemblies,
   so a plugin's .razor.css bundle is never served.
   =================================================================== */
.dc-root .dc-tile {
    cursor: pointer;
    transition: border-color .15s ease, background-color .15s ease;
}

.dc-root .dc-tile:hover,
.dc-root .dc-tile-on {
    border-color: var(--mud-palette-primary);
}

.dc-root .dc-tile-on {
    background: color-mix(in srgb, var(--mud-palette-primary) 8%, var(--mud-palette-surface));
}

.dc-root .dc-card {
    border-radius: 14px;
}

.dc-root .dc-card-head {
    display: flex;
    align-items: center;
    gap: .75rem;
    flex-wrap: wrap;
}

.dc-root .dc-card-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 10px;
    flex: 0 0 auto;
    color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 12%, transparent);
}

.dc-root .dc-card-title {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.dc-root .dc-count {
    display: inline-block;
    min-width: 1.6rem;
    margin-left: .35rem;
    padding: 0 .45rem;
    border-radius: 999px;
    font-size: .75rem;
    font-weight: 700;
    line-height: 1.4rem;
    text-align: center;
    vertical-align: middle;
    color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 12%, transparent);
}

/* Numbered steps of "Nueva solicitud". */
.dc-root .dc-step {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
    margin: 1.1rem 0 .6rem;
}

.dc-root .dc-step-num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.35rem;
    height: 1.35rem;
    border-radius: 50%;
    font-size: .75rem;
    font-weight: 700;
    color: var(--mud-palette-primary-text);
    background: var(--mud-palette-primary);
}

/* What to ask for: a check group. "Todas" on top, one card per kind. */
.dc-root .dc-checkgroup {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 12px;
    padding: .35rem .75rem .75rem;
}

.dc-root .dc-checkall {
    padding-bottom: .35rem;
    margin-bottom: .6rem;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.dc-root .dc-checkall-label {
    font-weight: 700;
    font-size: .9rem;
}

.dc-root .dc-checkall-count {
    margin-left: .5rem;
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
}

.dc-root .dc-kinds {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
    gap: .75rem;
}

.dc-root .dc-kind {
    border: 1.5px solid var(--mud-palette-lines-default);
    border-radius: 12px;
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    transition: border-color .15s ease, background-color .15s ease, box-shadow .15s ease;
}

.dc-root .dc-kind:hover,
.dc-root .dc-kind:focus-within {
    border-color: var(--mud-palette-primary);
}

/* The MudCheckBox fills the card, so the whole card is its label. */
.dc-root .dc-kind .mud-input-control,
.dc-root .dc-kind .mud-input-control > *,
.dc-root .dc-kind label {
    width: 100%;
    margin: 0;
}

.dc-root .dc-kind label {
    display: flex;
    align-items: center;
    gap: .35rem;
    padding: .7rem .9rem .7rem .3rem;
    cursor: pointer;
}

.dc-root .dc-kind-on {
    border-color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 10%, var(--mud-palette-surface));
    box-shadow: 0 0 0 1px var(--mud-palette-primary) inset;
}

/* Only the history table keeps the icon as a tile of its own. On the cards it
   sits inside the title instead: between the checkbox and the text it was a
   third block competing with both, and the eye had to cross it to reach the
   words that say what the option does. */
.dc-root .dc-kind-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.9rem;
    height: 1.9rem;
    border-radius: 8px;
    flex: 0 0 auto;
    color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 12%, transparent);
}

.dc-root .dc-kind-text {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-width: 0;
    line-height: 1.3;
}

.dc-root .dc-kind-title {
    display: flex;
    align-items: center;
    gap: .4rem;
    font-weight: 700;
    font-size: .92rem;
}

.dc-root .dc-kind-title .mud-icon-root {
    flex: 0 0 auto;
    color: var(--mud-palette-primary);
    font-size: 1.15rem;
}

.dc-root .dc-kind-desc {
    font-size: .78rem;
    color: var(--mud-palette-text-secondary);
}

.dc-root .dc-send {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 1rem;
    flex-wrap: wrap;
    margin-top: 1rem;
    padding-top: 1rem;
    border-top: 1px solid var(--mud-palette-lines-default);
}

/* History. */
.dc-root .dc-person {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .2rem .35rem;
    margin: -.2rem -.35rem;
    border: 0;
    border-radius: 8px;
    background: transparent;
    color: inherit;
    text-align: left;
    font: inherit;
    cursor: pointer;
}

.dc-root .dc-person:hover {
    background: color-mix(in srgb, var(--mud-palette-primary) 8%, transparent);
}

.dc-root .dc-avatar {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    flex: 0 0 auto;
    font-size: .72rem;
    font-weight: 700;
    color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 14%, transparent);
}

.dc-root .dc-person-text {
    display: flex;
    flex-direction: column;
    min-width: 0;
    line-height: 1.3;
}

.dc-root .dc-person-name {
    font-weight: 600;
    font-size: .875rem;
}

.dc-root .dc-person-sub {
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
}

.dc-root .dc-actions {
    display: inline-flex;
    align-items: center;
    justify-content: flex-end;
    gap: .25rem;
}

.dc-root .dc-file-gone {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
}

.dc-root .dc-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .4rem;
    padding: 2rem 1rem;
    color: var(--mud-palette-text-secondary);
}

.dc-root .dc-table .mud-table-cell {
    vertical-align: top;
    padding-top: .7rem;
    padding-bottom: .7rem;
}

@media (max-width: 600px) {
    .dc-root .dc-send { justify-content: stretch; }
    .dc-root .dc-send .mud-button-root { width: 100%; }
}

/* ============================================================

   Controles de la app (7CI > Configuración): SalesSettings.razor,
   ZoneRulesPanel.razor y CustomerReasonsPanel.razor.
   Global on purpose: the host does not serve a plugin's .razor.css bundle.
   =================================================================== */
.cfg-root .cfg-page-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 12px;
    color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 12%, transparent);
}

.cfg-root .cfg-card {
    height: 100%;
    display: flex;
    flex-direction: column;
    border-radius: 14px;
    transition: border-color .15s ease, box-shadow .15s ease;
}

.cfg-root .cfg-card:hover {
    border-color: color-mix(in srgb, var(--mud-palette-primary) 45%, var(--mud-palette-lines-default));
    box-shadow: 0 2px 10px rgba(0, 0, 0, .06);
}

/* Lo que se aparta de lo de fábrica o de la regla general, marcado en el borde. */
.cfg-root .cfg-card-own {
    border-left: 4px solid var(--mud-palette-warning);
}

.cfg-root .cfg-card-head {
    display: flex;
    align-items: flex-start;
    gap: .75rem;
}

.cfg-root .cfg-card-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 10px;
    flex: 0 0 auto;
    color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 12%, transparent);
}

.cfg-root .cfg-card-title {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
/* ============================================================
   ROLE PERMISSIONS DIALOG (/core/roles)
   ------------------------------------------------------------
   The picker used to print every module with every one of its
   screens expanded, one checkbox per line: a role like Admin ran
   past twenty screens of scroll and the dialog grew taller than
   the window, pushing its own buttons out of reach.

   Collapsible cards fixed the height and left a new problem: a
   column of identical checkboxes in the brand colour, no
   hierarchy between a module and a screen inside it, and a
   counter marooned at the far right of an empty row.

   What this layout does about it:

     - a module is an object, not a row -- a tinted icon tile, its
       name, its coverage as a badge beside the name (not stranded
       across the width) and its code on the right;
     - the screens flow in newspaper columns, so twenty-six of them
       take six lines of height instead of twenty-six;
     - every screen carries an icon, which is what lets the eye
       find one without reading all of them;
     - the group the sidebar files them under rides in the same
       flow, in caps, as its own toggle.
   ============================================================ */

/* ---------------------------------------------- title bar */

.role-title {
    display: flex;
    align-items: center;
    gap: .75rem;
    width: 100%;
}

.role-title-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.5rem;
    height: 2.5rem;
    flex: 0 0 auto;
    border-radius: .75rem;
    background: color-mix(in srgb, var(--mud-palette-primary) 18%, transparent);
    color: var(--mud-palette-primary);
}

.role-title-text {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 1.15rem;
    font-weight: 700;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The X is ours and not MudBlazor's on purpose: this one runs through
   the same guard as Cancelar, so it cannot drop unsaved changes. */
.role-title-close {
    flex: 0 0 auto;
}

/* ---------------------------------------------- shell */

.role-perm {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

/* Una descripción larga muestra tres líneas; el resto en el tooltip del título. */
.cfg-root .cfg-detail {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.cfg-root .cfg-value {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .5rem .75rem;
    border-radius: 10px;
    background: var(--mud-palette-background-gray);
}

.cfg-root .cfg-zones {
    border-top: 1px dashed var(--mud-palette-lines-default);
    padding-top: .5rem;
}

.cfg-root .cfg-toggle {
    width: 100%;
}

/* Cómo lee el vendedor el mensaje del motivo. */
.cfg-root .cfg-preview {
    border-radius: 10px;
    padding: .5rem .75rem;
    background: var(--mud-palette-background-gray);
    border-left: 3px solid var(--mud-palette-primary);
}

.cfg-root .cfg-tone-hide .cfg-card-icon { color: var(--mud-palette-dark); background: color-mix(in srgb, var(--mud-palette-dark) 12%, transparent); }
.cfg-root .cfg-tone-block .cfg-card-icon { color: var(--mud-palette-error); background: color-mix(in srgb, var(--mud-palette-error) 12%, transparent); }
.cfg-root .cfg-tone-warn .cfg-card-icon { color: var(--mud-palette-warning); background: color-mix(in srgb, var(--mud-palette-warning) 14%, transparent); }
.cfg-root .cfg-tone-ok .cfg-card-icon { color: var(--mud-palette-success); background: color-mix(in srgb, var(--mud-palette-success) 12%, transparent); }

.role-perm-bar {
    display: flex;
    align-items: center;
    gap: .5rem;
    flex-wrap: wrap;
}

.role-perm-search {
    flex: 1 1 18rem;
    min-width: 0;
    margin-top: 0;
}

.role-perm-actions {
    display: flex;
    align-items: center;
    gap: .4rem;
    flex: 0 0 auto;
}

.role-perm-summary {
    display: flex;
    align-items: center;
    gap: .4rem;
    font-size: .78rem;
    color: var(--mud-palette-text-secondary);
    padding: .6rem .15rem .5rem;
}

.role-perm-summary .mud-icon-root {
    color: var(--mud-palette-text-secondary);
}

/* The one box that scrolls. Capped against the viewport so the dialog
   keeps its fields and its buttons on screen at any zoom. */
.role-perm-scroll {
    max-height: min(56vh, 36rem);
    min-height: 8rem;
    overflow-y: auto;
    overflow-x: hidden;
    padding-right: .4rem;
}

.role-perm-note {
    margin-bottom: .5rem;
}

.role-perm-empty {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .4rem;
    padding: 1.75rem 1rem;
    font-size: .8125rem;
    color: var(--mud-palette-text-secondary);
}

.role-sect {
    font-size: .64rem;
    font-weight: 700;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
    margin: .85rem 0 .4rem;
}

.role-sect:first-child {
    margin-top: 0;
}

/* ---------------------------------------------- module card */

.role-card {
    position: relative;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: .75rem;
    margin-bottom: .5rem;
    overflow: hidden;
    transition: border-color .15s ease, box-shadow .15s ease;
}

.role-card.is-open {
    border-color: color-mix(in srgb, var(--mud-palette-primary) 40%, var(--mud-palette-lines-default));
    box-shadow: 0 0 0 1px color-mix(in srgb, var(--mud-palette-primary) 12%, transparent);
}

/* The card that changed since the dialog opened wears one amber edge;
   the screen that caused it wears the same amber dot. */
.role-card.has-changes::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: var(--mud-palette-warning);
    z-index: 1;
}

.role-card-head {
    display: flex;
    align-items: center;
    gap: .65rem;
    padding: .5rem .75rem;
    cursor: pointer;
    user-select: none;
}

.role-card.is-open .role-card-head {
    background: color-mix(in srgb, var(--mud-palette-primary) 8%, transparent);
}

.role-card-head:hover {
    background: color-mix(in srgb, var(--mud-palette-text-primary) 5%, transparent);
}

.role-card.is-open .role-card-head:hover {
    background: color-mix(in srgb, var(--mud-palette-primary) 13%, transparent);
}

.role-card-check {
    display: inline-flex;
    flex: 0 0 auto;
    cursor: default;
}

/* A tinted tile per module. The tone is derived from the module code, so
   a module keeps its colour from one visit to the next without the host
   having to keep a table of colours for modules that are not its own. */
.role-tile {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    flex: 0 0 auto;
    border-radius: .65rem;
}

.role-tile.tone-0 { background: rgba(59, 130, 246, .18); color: #60a5fa; }
.role-tile.tone-1 { background: rgba(16, 185, 129, .18); color: #34d399; }
.role-tile.tone-2 { background: rgba(139, 92, 246, .18); color: #a78bfa; }
.role-tile.tone-3 { background: rgba(245, 158, 11, .18); color: #fbbf24; }
.role-tile.tone-4 { background: rgba(6, 182, 212, .18); color: #22d3ee; }

.role-card-name {
    flex: 0 1 auto;
    min-width: 0;
    font-size: .95rem;
    font-weight: 700;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* Beside the name, not across the width: the count belongs to the module,
   and a number parked at the far edge of an empty row belongs to nobody. */
.role-badge {
    flex: 0 0 auto;
    padding: .1rem .55rem;
    border-radius: 999px;
    font-size: .72rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-secondary);
    background: color-mix(in srgb, var(--mud-palette-text-primary) 9%, transparent);
}

.role-badge.is-on {
    color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 15%, transparent);
}

.role-card-chevron {
    flex: 0 0 auto;
    color: var(--mud-palette-text-secondary);
    transition: transform .15s ease;
}

.role-card.is-open .role-card-chevron {
    transform: rotate(180deg);
}

.role-card-spacer {
    flex: 1 1 auto;
}

/* The code IdentityHub actually stores, which is what an admin ends up
   asking for when a permission does not behave. */
.role-code {
    flex: 0 0 auto;
    padding: .12rem .5rem;
    border-radius: .4rem;
    border: 1px solid var(--mud-palette-lines-default);
    font-size: .68rem;
    font-weight: 600;
    letter-spacing: .04em;
    color: var(--mud-palette-text-secondary);
}

.role-card-body {
    border-top: 1px solid var(--mud-palette-lines-default);
    padding: .6rem .85rem .75rem;
}

/* ---------------------------------------------- screen columns */

/* Newspaper columns, not a grid: a grid leaves ragged holes when a group
   ends mid-row, columns just keep flowing. */
.role-grid {
    columns: 3;
    column-gap: 1.75rem;
}

.role-row {
    display: flex;
    align-items: center;
    gap: .45rem;
    padding: .1rem .3rem;
    border-radius: .4rem;
    cursor: pointer;
    break-inside: avoid;
    -webkit-column-break-inside: avoid;
}

.role-row:hover {
    background: color-mix(in srgb, var(--mud-palette-text-primary) 6%, transparent);
}

/* Every click on the row is the row's: the checkbox is there to be read,
   not to be aimed at. */
.role-row .mud-checkbox {
    margin: 0;
    min-width: 0;
    pointer-events: none;
}

.role-row .mud-checkbox > .mud-button-root {
    padding: .2rem;
}

.role-row-icon {
    flex: 0 0 auto;
    color: var(--mud-palette-text-secondary);
    opacity: .75;
}

.role-row-text {
    flex: 1 1 auto;
    min-width: 0;
    font-size: .82rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.role-row.is-on .role-row-text {
    color: var(--mud-palette-text-primary);
}

.role-row.is-on .role-row-icon {
    color: var(--mud-palette-primary);
    opacity: 1;
}

/* The group rides in the same flow, in caps. It is a heading and a switch
   at once, which is why it is not a separate full-width bar. */
.role-row.is-group {
    margin-top: .35rem;
}

.role-row.is-group .role-row-text {
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.role-row.is-group.is-on .role-row-text {
    color: var(--mud-palette-text-primary);
}

.role-row.is-changed {
    position: relative;
}

.role-row.is-changed::after {
    content: "";
    position: absolute;
    right: .35rem;
    top: 50%;
    width: .4rem;
    height: .4rem;
    margin-top: -.2rem;
    border-radius: 50%;
    background: var(--mud-palette-warning);
}

/* ---------------------------------------------- Core matrix */

/* Here the checkbox is aimed at after all: two columns over one row per
   screen is a real grid, and the row is not a single yes/no. */
.role-core-body {
    padding: .35rem .85rem .75rem;
}

.role-core-row {
    display: grid;
    grid-template-columns: minmax(7rem, 1fr) 4.5rem 7rem;
    align-items: center;
    gap: .25rem;
}

.role-core-head {
    font-size: .64rem;
    font-weight: 700;
    letter-spacing: .09em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
    padding: .5rem 0 .3rem;
    border-bottom: 1px solid var(--mud-palette-lines-default);
}

.role-core-name {
    display: flex;
    align-items: center;
    gap: .45rem;
    font-size: .82rem;
    overflow: hidden;
    white-space: nowrap;
}

.role-core-na {
    font-size: .8125rem;
    color: var(--mud-palette-text-disabled);
    padding-left: .8rem;
}

.role-core-body .mud-checkbox {
    margin: 0;
    min-width: 0;
}

.role-core-body .mud-checkbox > .mud-button-root {
    padding: .25rem;
}

/* ---------------------------------------------- pending changes */

.role-dirty {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    margin-left: auto;
    padding-left: .5rem;
    color: var(--mud-palette-warning);
    font-weight: 600;
}

.role-discard {
    margin-right: auto;
    padding-left: .5rem;
    font-size: .8125rem;
    color: var(--mud-palette-warning);
}

/* ---------------------------------------------- copy menu */

.role-copy-item {
    display: flex;
    align-items: center;
    gap: 1.25rem;
    min-width: 11rem;
}

.role-copy-count {
    margin-left: auto;
    font-size: .72rem;
    font-variant-numeric: tabular-nums;
    color: var(--mud-palette-text-secondary);
}

@media (max-width: 1100px) {
    .role-grid {
        columns: 2;
    }
}

@media (max-width: 700px) {
    .role-grid {
        columns: 1;
    }

    .role-code {
        display: none;
    }

    .role-core-row {
        grid-template-columns: minmax(5rem, 1fr) 3.5rem 5rem;
    }
}

/* ------------------------------------------------------------
   The Acceso column of the roles grid: a few names and a count,
   not one chip per permission code.
   ------------------------------------------------------------ */

.role-access {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .25rem;
}

.role-access-screens {
    font-size: .72rem;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

/* ---------------------------------------------------------------- offers

   The detail of a missed offer: the rule told step by step, and the order line that
   made its condition true.

   Here and not in a plugin's .razor.css: scoped styles from plugins are not served
   -- the Host does not bundle them -- so there they would paint nothing. */
.offer-rule {
    margin: 0;
    padding-left: 1.25rem;
    display: flex;
    flex-direction: column;
    gap: .4rem;
}

.offer-rule li {
    line-height: 1.45;
}

/* The line that counted towards the condition, marked in the table: without this you
   are left comparing codes by hand between the rule and the order. */
.offer-line-counts {
    background: color-mix(in srgb, var(--mud-palette-success) 10%, transparent);
}

/* ------------------------------------------------------- prize wheel history

   The changed fields inside a cell of the wheel's history grid: one line per
   field, "was -> is" when there is a previous value.

   Here and not in the plugin's .razor.css, for the same reason as the block
   above: scoped styles from plugins are not served. */
.wheel-history-fields {
    display: flex;
    flex-direction: column;
    gap: .15rem;
}

.wheel-history-field {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: .4rem;
    font-size: .78rem;
    line-height: 1.35;
}

/* The label is the part you skim past to find the value, so it stays quiet. */
.wheel-history-label {
    color: var(--mud-palette-text-secondary);
}

.wheel-history-label::after {
    content: ":";
}

.wheel-history-value {
    font-weight: 600;
}

/* Struck through, not just greyed: what an audit trail is read for is the
   difference, and the eye finds a crossed-out number without reading it. */
.wheel-history-before {
    color: var(--mud-palette-text-secondary);
    text-decoration: line-through;
}

.wheel-history-arrow {
    color: var(--mud-palette-text-secondary);
}

/* The cell puts the fields on the left and the "see all of them" on the right: the
   fields are of different lengths, and a link glued under them sits somewhere
   different on every row. */
.wheel-history-cell {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
}

.wheel-history-more {
    display: inline-flex;
    align-items: center;
    gap: .15rem;
    white-space: nowrap;
    flex-shrink: 0;
}

.wheel-history-when,
.wheel-history-who {
    display: flex;
    align-items: center;
    gap: .5rem;
}

/* ------------------------------------------------ prize wheel template preview

   The prizes of a past campaign, next to the wheel it had, in the dialog that
   copies one. */
.wheel-template-prize {
    display: flex;
    align-items: flex-start;
    gap: .5rem;
    padding: .25rem 0;
}

/* The wedge's own colour, so the list and the drawing are read as one thing. */
.wheel-template-color {
    width: .65rem;
    height: .65rem;
    border-radius: 50%;
    margin-top: .35rem;
    flex-shrink: 0;
}

/* ---------------------------------------------------------- date range filter

   The range a screen is looking at, in the open above its numbers.

   THE PRESETS ARE THE FILTER AND THE DATE BOXES ARE THE EXCEPTION. They used to
   share the row: two outlined MudDatePickers with floating labels, each as wide
   as the space let it, next to five small chips -- the rarest control on the
   screen taking four fifths of it. Now they only render behind «Rango».

   AND THEY ARE 186px AND NOT 148px. A dd/MM/yyyy date, its calendar button and a
   clear button do not fit in less, and what a too-narrow box does is not wrap: it
   clips, so the field reads "22/09/2..." and the year -- the one part somebody is
   checking -- is the part that goes.

   Own chips and not MudChip: MudChip renders a button whose padding and font
   come from the theme, and a row of them next to a dense input never lined up. */

.day-range-filter {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .55rem;
}

.day-range-filter-icon {
    color: var(--mud-palette-text-secondary);
}

.day-range-filter-presets {
    display: flex;
    flex-wrap: wrap;
    gap: .3rem;
}

.day-range-chip {
    display: inline-flex;
    align-items: center;
    gap: .25rem;
    padding: .18rem .65rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 999px;
    background: transparent;
    color: var(--mud-palette-text-secondary);
    font: inherit;
    font-size: .78rem;
    line-height: 1.5;
    cursor: pointer;
    transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}

.day-range-chip .mud-icon-root {
    font-size: .9rem;
}

.day-range-chip:hover {
    border-color: color-mix(in srgb, var(--mud-palette-primary) 55%, transparent);
    color: var(--mud-palette-text-primary);
}

.day-range-chip.is-active {
    border-color: transparent;
    background: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
    font-weight: 600;
}

/*  «Rango» is not a sixth preset: it opens the boxes for whatever range is
    already applied. Filling it like an active preset lit two chips at once --
    Hoy AND Rango -- and read as two filters fighting. Outlined says "this panel
    is open" without claiming to be the filter. */
.day-range-chip.is-open {
    border-color: color-mix(in srgb, var(--mud-palette-primary) 70%, transparent);
    color: var(--mud-palette-primary);
    font-weight: 600;
}

.day-range-filter-dates {
    display: flex;
    align-items: center;
    gap: .35rem;
}

/*  On the MudPicker root, not on the input: Class lands on the picker wrapper,
    and clamping only the inner field left the wrapper stretching the flex row --
    which is how the two boxes came to be 600px wide. */
.day-range-filter-dates .mud-picker {
    flex: 0 0 auto;
    width: 186px;
    min-width: 0;
}

.day-range-filter-dash {
    color: var(--mud-palette-text-secondary);
}

/* ------------------------------------------------------- solicitudes: the inbox

   The tone token each block paints itself with. Same names as the dialogs use,
   scoped to this screen so a chip here and a chip in the detail dialog cannot
   drift apart. */

.apr-inbox .tone-warning { --apr-tone: var(--mud-palette-warning); }
.apr-inbox .tone-info { --apr-tone: var(--mud-palette-info); }
.apr-inbox .tone-success { --apr-tone: var(--mud-palette-success); }
.apr-inbox .tone-error { --apr-tone: var(--mud-palette-error); }
.apr-inbox .tone-primary { --apr-tone: var(--mud-palette-primary); }
.apr-inbox .tone-default { --apr-tone: var(--mud-palette-text-secondary); }

/* ---------------------------------------------------- solicitudes: selection

   The bar only exists while something is picked, so it never sits empty above
   the grid. Sticky because a selection made at row 3 is acted on after reading
   row 40, and a bar that scrolled away would mean scrolling back up to use it. */

.apr-bulkbar {
    position: sticky;
    top: .5rem;
    z-index: 3;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
    padding: .45rem .75rem;
    margin-bottom: .6rem;
    border: 1px solid color-mix(in srgb, var(--mud-palette-primary) 45%, transparent);
    border-radius: 10px;
    background: color-mix(in srgb, var(--mud-palette-primary) 12%, var(--mud-palette-surface));
    box-shadow: 0 6px 16px rgb(0 0 0 / .18);
}

.apr-bulkbar-count {
    font-weight: 700;
}

.apr-bulkbar-note {
    font-size: .78rem;
    color: var(--mud-palette-text-secondary);
}

.apr-bulkbar-spacer {
    flex: 1 1 auto;
}

/*  The rules say so while they are running, in the colour of a warning and not
    of a success: deciding without reading is a thing you should notice you left
    switched on. */
.apr-auto-banner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
    padding: .45rem .75rem;
    margin-bottom: .6rem;
    border: 1px solid color-mix(in srgb, var(--mud-palette-warning) 55%, transparent);
    border-radius: 10px;
    background: color-mix(in srgb, var(--mud-palette-warning) 12%, var(--mud-palette-surface));
    font-size: .8rem;
}

.apr-auto-banner .mud-icon-root {
    color: var(--mud-palette-warning);
}

.apr-auto-banner-text {
    flex: 1 1 auto;
    min-width: 12rem;
}

/* --------------------------------------------------------- solicitudes: a batch */

.apr-bulk-line {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .35rem 0;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    font-size: .85rem;
}

.apr-bulk-line:last-child {
    border-bottom: 0;
}

.apr-bulk-line-id {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-weight: 700;
    min-width: 3.5rem;
}

.apr-bulk-line.is-error {
    color: var(--mud-palette-error);
}

.apr-bulk-list {
    max-height: 240px;
    overflow: auto;
    margin-top: .5rem;
}

/* ----------------------------------------------------- solicitudes: the rules

   The automation panel and the editor of one rule. Both are tall forms in a
   dialog, so both get a fixed height with the scroll inside: a dialog that grows
   with what you type moves its own buttons out from under the pointer. */

.apr-auto-dialog .mud-dialog-content,
.apr-rule-dialog .mud-dialog-content {
    max-height: min(68vh, 640px);
    overflow-y: auto;
}

.apr-rule-hint {
    margin: .1rem 0 0;
    font-size: .74rem;
    line-height: 1.35;
    color: var(--mud-palette-text-secondary);
}

/*  Two buttons and not a select: what a rule DOES is the one field somebody has
    to be sure about before reading anything else, and a closed dropdown showing
    "Aprobar" is read as a label rather than as a choice that could say the other
    thing. */
.apr-rule-decision {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: .5rem;
}

.apr-rule-choice {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .55rem .75rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 10px;
    background: transparent;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
    transition: border-color .15s ease, background-color .15s ease;
}

.apr-rule-choice .mud-icon-root {
    color: var(--apr-tone);
}

.apr-rule-choice span {
    display: flex;
    flex-direction: column;
}

.apr-rule-choice small {
    font-size: .72rem;
    color: var(--mud-palette-text-secondary);
}

.apr-rule-choice:hover {
    border-color: color-mix(in srgb, var(--apr-tone) 55%, transparent);
}

.apr-rule-choice.is-active {
    border-color: var(--apr-tone);
    background: color-mix(in srgb, var(--apr-tone) 14%, transparent);
}

/* ---------------------------------------------------------------- the list */

.apr-rule-list {
    display: flex;
    flex-direction: column;
    gap: .4rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.apr-rule-row {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .4rem .5rem .4rem .6rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-left: 3px solid var(--apr-tone);
    border-radius: 9px;
    background: color-mix(in srgb, var(--mud-palette-surface) 94%, var(--mud-palette-background));
}

/*  A rule switched off keeps its place in the order -- it is coming back -- but
    it stops looking like something that is deciding anything. */
.apr-rule-row.is-off {
    opacity: .5;
    border-left-color: var(--mud-palette-lines-default);
}

.apr-rule-order {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.4rem;
    height: 1.4rem;
    flex: 0 0 auto;
    border-radius: 50%;
    background: color-mix(in srgb, var(--mud-palette-text-secondary) 18%, transparent);
    font-size: .72rem;
    font-weight: 700;
}

.apr-rule-body {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-width: 0;
}

.apr-rule-decision-label {
    font-size: .78rem;
    font-weight: 700;
    color: var(--apr-tone);
}

.apr-rule-when {
    font-size: .76rem;
    color: var(--mud-palette-text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/*  How many of the requests open right now this rule would take. It is the
    column that turns a list of conditions into something you can check. */
.apr-rule-hits {
    flex: 0 0 auto;
    min-width: 1.75rem;
    text-align: center;
    font-weight: 700;
    color: var(--apr-tone);
}

.apr-rule-empty {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .75rem;
    padding: .75rem;
    border: 1px dashed var(--mud-palette-lines-default);
    border-radius: 10px;
}

.apr-rule-empty > div {
    flex: 1 1 14rem;
}

.apr-rule-empty p {
    margin: .15rem 0 0;
    font-size: .78rem;
    color: var(--mud-palette-text-secondary);
}

.apr-rule-empty .mud-icon-root {
    color: var(--mud-palette-text-secondary);
}

/* ----------------------------------------------------------- the simulation */

.apr-rule-preview {
    border-left: 3px solid var(--apr-tone);
}

.apr-rule-preview-head {
    display: flex;
    align-items: baseline;
    gap: .4rem;
}

.apr-rule-preview-count {
    font-size: 1.4rem;
    font-weight: 800;
    color: var(--apr-tone);
}

.apr-sim-row {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: .5rem;
}

.apr-sim-cell {
    display: flex;
    flex-direction: column;
    padding: .45rem .6rem;
    border: 1px solid color-mix(in srgb, var(--apr-tone) 35%, transparent);
    border-radius: 9px;
    background: color-mix(in srgb, var(--apr-tone) 9%, transparent);
}

.apr-sim-cell b {
    font-size: 1.25rem;
    line-height: 1.15;
    color: var(--apr-tone);
}

.apr-sim-cell small {
    font-size: .7rem;
    color: var(--mud-palette-text-secondary);
}

/*  Chrome paints an autofilled field in its own yellow, which on a dark dialog
    is a mustard block where a password box should be. The inset shadow is the
    only way to override it: background-color is ignored on :-webkit-autofill. */
.apr-auto-dialog input:-webkit-autofill,
.apr-auto-dialog input:-webkit-autofill:hover,
.apr-auto-dialog input:-webkit-autofill:focus {
    -webkit-box-shadow: 0 0 0 1000px var(--mud-palette-surface) inset;
    -webkit-text-fill-color: var(--mud-palette-text-primary);
    caret-color: var(--mud-palette-text-primary);
}

/* ------------------------------------------------ solicitudes: the automation

   The panel is tabbed -- rules, history, settings -- so each tab gets the same
   height and switching one does not move the buttons under the pointer. */

.apr-auto-panel {
    padding-top: .75rem;
}

/*  What the robot has done, newest first. A log is read by scanning the left
    edge, so time, number and outcome are fixed-width columns and only the
    description flows. */

.apr-log {
    display: flex;
    flex-direction: column;
    max-height: 46vh;
    overflow-y: auto;
}

.apr-log-row {
    display: flex;
    align-items: baseline;
    gap: .6rem;
    padding: .4rem .2rem;
    border-bottom: 1px solid var(--mud-palette-lines-default);
    font-size: .8rem;
}

.apr-log-row:last-child {
    border-bottom: 0;
}

.apr-log-when {
    flex: 0 0 auto;
    min-width: 6.5rem;
    color: var(--mud-palette-text-secondary);
}

.apr-log-id {
    flex: 0 0 auto;
    min-width: 3rem;
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-weight: 700;
}

.apr-log-outcome {
    flex: 0 0 auto;
    min-width: 5.5rem;
    font-weight: 700;
    color: var(--apr-tone);
}

.apr-log-what {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-width: 0;
}

.apr-log-type {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/*  The rule that decided it -- or, on a failure, why it could not. Second line
    and dimmer: you scan the outcomes and read the reason only for the one you
    stopped at. */
.apr-log-rule {
    color: var(--mud-palette-text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ==========================================================================
   USER DIALOG  (7CI > Administración de Usuarios)

   The dialog that creates and edits a user of App7CI, built to the layout the
   screen was designed against: a round avatar and the title on the dialog's own
   surface -- no coloured band --, every field labelled ABOVE its box with the
   icon that names it, the boxes grouped into panels, and the roles as cards
   with a checkbox, an icon and what the role is for.

   Two decisions worth writing down.

   The accent is var(--mud-palette-primary) everywhere and never a literal
   colour. The portal lets a person pick the accent (granate, indigo, teal,
   cobre, grafito) and the mock was drawn in blue: hard-coding blue would have
   made this the one screen that ignores that choice.

   The labels are ours, not MudBlazor's. A MudTextField with a Label floats it
   into a notch in the border, which is a different design from the one asked
   for -- so the fields are given no Label at all, carry their hint in the
   placeholder, and the label lives above the box where it can hold an icon,
   the asterisk and, for the password, the button that invents one.
   ========================================================================== */

.mud-dialog.usr-dialog {
    overflow: hidden;
    border-radius: 20px;
    border: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 60%, transparent);
    background-image: radial-gradient(
        120% 90% at 50% 0%,
        color-mix(in srgb, var(--mud-palette-primary) 5%, transparent),
        transparent 60%);
    box-shadow:
        0 34px 68px -24px rgba(0, 0, 0, 0.6),
        0 0 0 1px color-mix(in srgb, var(--mud-palette-primary) 10%, transparent);
}

/* --------------------------------------------------------------------------
   The head: the band

   The screen went through two designs that disagreed about exactly one thing:
   whether the title sits on a coloured band or on the dialog's own surface. It
   keeps the band -- and the band keeps the pill, so the state of the account is
   readable from the top, beside the name, while the switch down in Acceso is
   what moves it.

   The band is drawn with the shell's own .app-dialog-hero classes, the ones the
   module dialogs use, and only re-dressed here: three layers instead of one
   flat colour -- a highlight where the light falls, a diagonal sheen at four per
   cent that gives the colour a surface, and a gradient ending in a near-black
   maroon so the right side has depth.
   -------------------------------------------------------------------------- */

.mud-dialog.usr-dialog .mud-dialog-title {
    padding: 0;
    margin: 0;
}

.usr-dialog .app-dialog-hero {
    gap: 1rem;
    padding: 1.3rem 1.5rem;
    background: linear-gradient(
        118deg,
        color-mix(in srgb, var(--mud-palette-primary) 92%, #FFFFFF) 0%,
        var(--mud-palette-primary) 42%,
        color-mix(in srgb, var(--mud-palette-primary) 45%, #0B1220) 100%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.22),
                inset 0 -1px 0 rgba(0, 0, 0, 0.22);
}

.usr-dialog .app-dialog-hero::before {
    content: "";
    position: absolute;
    inset: 0;
    opacity: 0.35;
    pointer-events: none;
    background: repeating-linear-gradient(
        118deg,
        rgba(255, 255, 255, 0.04) 0 3px,
        transparent 3px 14px);
}

.usr-dialog .app-dialog-hero::after {
    top: -190px;
    right: -90px;
    width: 380px;
    height: 380px;
    background: radial-gradient(circle, rgba(255, 255, 255, 0.24), transparent 66%);
}

/* The avatar of the row this was opened from, promoted: same initial, same
   colour, so the dialog is visibly about the person that was clicked. */
.usr-dialog .app-dialog-hero-icon {
    width: 54px;
    height: 54px;
    border-radius: 50%;
    color: var(--mud-palette-primary);
    background: #fff;
    border: 0;
    box-shadow:
        0 0 0 4px rgba(255, 255, 255, 0.18),
        0 6px 14px -8px rgba(0, 0, 0, 0.5);
}

.usr-dialog .app-dialog-hero-icon .mud-icon-root {
    margin: 0;
    font-size: 1.6rem;
}

.usr-hero-initial {
    font-size: 1.45rem;
    font-weight: 800;
    line-height: 1;
}

.usr-dialog .app-dialog-hero-title {
    font-size: 1.3rem;
    letter-spacing: -0.015em;
}

.usr-dialog .app-dialog-hero-sub {
    font-size: 0.82rem;
    font-variant-numeric: tabular-nums;
}

/* The state of the account, said in the band and driven by the switch below:
   flip it and this changes with it, so the consequence of the switch is read
   where the name is instead of a section further down. */
.usr-hero-status {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    flex: 0 0 auto;
    margin-left: auto;
    padding: 0.28rem 0.65rem 0.28rem 0.5rem;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, 0.35);
    background: rgba(255, 255, 255, 0.14);
    color: #fff;
    font-size: 0.7rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    white-space: nowrap;
}

.usr-hero-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.28);
}

/* Inactive is not an error, it is a state -- but it is the one that has to be
   noticed on the way past, so it gets the only colour in the band that is not
   the brand's. */
.usr-hero-status.is-off {
    border-color: rgba(255, 255, 255, 0.5);
    background: rgba(15, 23, 42, 0.35);
}

.usr-hero-status.is-off .usr-hero-dot {
    background: var(--mud-palette-warning);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--mud-palette-warning) 35%, transparent);
}

/* MudBlazor's own close button is drawn in the title's text colour, which over
   the band comes out as a dark mark in the corner: the dialog is opened with
   CloseButton=false and puts this one inside the band instead. */
.usr-head-close.mud-icon-button {
    position: relative;
    flex: 0 0 auto;
    margin-left: 0.15rem;
    color: rgba(255, 255, 255, 0.85);
}

.usr-head-close.mud-icon-button:hover {
    color: #fff;
    background-color: rgba(255, 255, 255, 0.16);
}

/* --------------------------------------------------------------------------
   Sections inside a panel

   The panel says these fields belong together; the section says which question
   they answer. The icon gets a tinted square of its own -- a small thing, but
   it is what turns three grey words into a heading: the eye lands on the mark,
   not on the letters.
   -------------------------------------------------------------------------- */

.usr-dialog .app-dialog-section + .app-dialog-section {
    margin-top: 1.35rem;
}

.usr-dialog .app-dialog-section-title {
    gap: 0.55rem;
    margin-bottom: 0.85rem;
}

.usr-dialog .app-dialog-section-title > .mud-icon-root {
    margin: 0;
    padding: 4px;
    border-radius: 8px;
    color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 13%, transparent);
    font-size: 1.45rem;
}

/* --------------------------------------------------------------------------
   Panels

   The nine things this dialog asks for are two questions: the account, and what
   it is allowed to do. One panel each, and the grouping is the whole reason the
   form can be read without going label by label.
   -------------------------------------------------------------------------- */

.mud-dialog.usr-dialog .mud-dialog-content {
    padding: 1.3rem 1.5rem 0.25rem;
    overflow-x: hidden;
}

/* The panel is LIGHTER than the paper and the boxes inside it are darker than
   both: page, dialog, panel, field, four steps in one direction. Built the other
   way round -- panels darker than the dialog -- the groups read as holes. */
.usr-panel {
    padding: 1.15rem 1.2rem 1.25rem;
    border-radius: 16px;
    border: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 55%, transparent);
    background: color-mix(in srgb, var(--mud-palette-text-primary) 4%, var(--mud-palette-surface));
}

.usr-panel + .usr-panel {
    margin-top: 0.9rem;
}

.usr-panel-head {
    display: flex;
    align-items: center;
    gap: 0.8rem;
    margin-bottom: 1rem;
}

.usr-panel-icon {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 42px;
    height: 42px;
    border-radius: 50%;
    color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 14%, transparent);
    border: 1px solid color-mix(in srgb, var(--mud-palette-primary) 28%, transparent);
}

.usr-panel-icon .mud-icon-root {
    margin: 0;
    font-size: 1.3rem;
}

.usr-panel-title {
    margin: 0;
    font-size: 1.02rem;
    font-weight: 700;
    line-height: 1.2;
}

.usr-panel-sub {
    margin: 0.15rem 0 0;
    color: var(--mud-palette-text-secondary);
    font-size: 0.78rem;
    line-height: 1.3;
}

/* --------------------------------------------------------------------------
   Fields
   -------------------------------------------------------------------------- */

.usr-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(290px, 1fr));
    gap: 0.9rem 1.1rem;
}

.usr-field {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    min-width: 0;
}

.usr-label {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    min-width: 0;
    color: var(--mud-palette-text-primary);
    font-size: 0.83rem;
    font-weight: 600;
    line-height: 1.25;
    /* One line. The label, its hint and the Generar button share a row, and
       wrapping "Nueva Contraseña" onto two lines to fit them was the form
       losing its alignment to an optional word. */
    white-space: nowrap;
}

.usr-label > .mud-icon-root {
    flex: 0 0 auto;
    margin: 0;
    font-size: 1.15rem;
    color: var(--mud-palette-text-secondary);
}

/* The hint is what gives way when the row is tight: it shrinks and clips,
   while the field's own name keeps its width. */
.usr-label-hint {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    color: var(--mud-palette-text-secondary);
    font-weight: 400;
}

.usr-req {
    color: var(--mud-palette-error);
    font-style: normal;
}

/* MudBlazor's outlined box, given a fill. Empty boxes on a panel that is itself
   a box left three shades of the same grey stacked on each other; filling the
   input is what separates "where you type" from "what it sits on". */
.usr-dialog .mud-input-control {
    margin: 0;
}

.usr-dialog .mud-input.mud-input-outlined {
    border-radius: var(--mud-default-borderradius);
    background: color-mix(in srgb, var(--mud-palette-background) 80%, var(--mud-palette-surface));
}

.usr-dialog .mud-input-outlined-border {
    border-color: color-mix(in srgb, var(--mud-palette-lines-default) 75%, transparent);
}

.usr-dialog .mud-input.mud-input-outlined .mud-input-adornment .mud-icon-root {
    color: var(--mud-palette-text-secondary);
}

/* Read-only, not disabled: greyed out, the one field that says WHICH account is
   open looked broken, and it could not be selected to copy the username from. */
.usr-dialog .usr-locked .mud-input.mud-input-outlined {
    background: color-mix(in srgb, var(--mud-palette-background) 45%, transparent);
}

.usr-dialog .usr-locked .mud-input-outlined-border {
    border-style: dashed;
}

/* The button that invents a password, parked at the end of that field's label. */
.usr-mini-action {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    margin-left: auto;
    padding: 0.18rem 0.55rem;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 75%, transparent);
    background: transparent;
    color: var(--mud-palette-text-secondary);
    font: inherit;
    font-size: 0.7rem;
    font-weight: 700;
    cursor: pointer;
    transition: color 140ms ease, border-color 140ms ease, background-color 140ms ease;
}

.usr-mini-action .mud-icon-root {
    margin: 0;
    font-size: 0.95rem;
}

.usr-mini-action:hover {
    border-color: color-mix(in srgb, var(--mud-palette-primary) 45%, transparent);
    background: color-mix(in srgb, var(--mud-palette-primary) 10%, transparent);
    color: var(--mud-palette-primary);
}

.usr-mini-action:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

/* --------------------------------------------------------------------------
   State of the account

   The switch, and under it what it means -- because on this screen the switch
   is the only control whose effect happens to somebody else: it is what cuts a
   person's access while they are working.
   -------------------------------------------------------------------------- */

.usr-state {
    display: flex;
    align-items: center;
    gap: 0.9rem;
    height: 100%;
    min-height: 3.4rem;
    padding: 0.6rem 0.95rem;
    border-radius: 12px;
    border: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 55%, transparent);
    border-left: 3px solid var(--mud-palette-success);
    background:
        radial-gradient(130% 160% at 0% 50%,
            color-mix(in srgb, var(--mud-palette-success) 12%, transparent),
            transparent 60%),
        color-mix(in srgb, var(--mud-palette-background) 70%, var(--mud-palette-surface));
    transition: border-color 160ms ease;
}

.usr-state.is-off {
    border-left-color: var(--mud-palette-warning);
    background:
        radial-gradient(130% 160% at 0% 50%,
            color-mix(in srgb, var(--mud-palette-warning) 14%, transparent),
            transparent 60%),
        color-mix(in srgb, var(--mud-palette-background) 70%, var(--mud-palette-surface));
}

.usr-state .mud-switch {
    flex: 0 0 auto;
    margin: 0 0 0 -0.75rem;
}

.usr-state-text {
    min-width: 0;
}

.usr-state-title {
    display: block;
    font-size: 0.94rem;
    font-weight: 700;
    line-height: 1.2;
}

.usr-state-note {
    margin: 0.15rem 0 0;
    color: var(--mud-palette-text-secondary);
    font-size: 0.76rem;
    line-height: 1.35;
}

/* --------------------------------------------------------------------------
   Roles
   -------------------------------------------------------------------------- */

.usr-role-count {
    flex: 0 0 auto;
    margin-left: auto;
    padding: 0.2rem 0.6rem;
    border-radius: 999px;
    border: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 75%, transparent);
    background: color-mix(in srgb, var(--mud-palette-background) 60%, var(--mud-palette-surface));
    color: var(--mud-palette-text-secondary);
    font-size: 0.68rem;
    font-weight: 800;
    letter-spacing: 0.06em;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* None picked is the one count worth interrupting for: it is what the API
   refuses on an update, and what produces a user who logs in and sees nothing. */
.usr-role-count.is-empty {
    border-color: color-mix(in srgb, var(--mud-palette-warning) 45%, transparent);
    background: color-mix(in srgb, var(--mud-palette-warning) 12%, transparent);
    color: var(--mud-palette-warning);
}

.usr-role-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(238px, 1fr));
    grid-auto-rows: 1fr;
    gap: 0.6rem;
}

/* A <button>, not a div with a click handler: the keyboard and the focus ring
   come with it, and aria-pressed says out loud what the box is drawing. A
   button also centres its content by default, which is what has to be undone
   here or no two cards in a row start at the same place. */
.usr-role-card {
    display: flex;
    justify-content: flex-start;
    align-items: center;
    gap: 0.7rem;
    padding: 0.7rem 0.85rem;
    border-radius: 13px;
    border: 1px solid color-mix(in srgb, var(--mud-palette-lines-default) 60%, transparent);
    background: color-mix(in srgb, var(--mud-palette-background) 55%, var(--mud-palette-surface));
    color: var(--mud-palette-text-primary);
    font: inherit;
    text-align: left;
    cursor: pointer;
    transition: border-color 150ms ease, background-color 150ms ease,
                transform 150ms ease, box-shadow 150ms ease;
    animation: usr-role-in 280ms cubic-bezier(0.34, 1.4, 0.64, 1) backwards;
    animation-delay: calc(var(--i, 0) * 30ms);
}

.usr-role-card:hover {
    border-color: color-mix(in srgb, var(--mud-palette-primary) 40%, transparent);
    transform: translateY(-1px);
}

.usr-role-card:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 2px;
}

.usr-role-card.is-on {
    border-color: color-mix(in srgb, var(--mud-palette-primary) 32%, transparent);
    background: color-mix(in srgb, var(--mud-palette-primary) 5%, var(--mud-palette-surface));
}

/* The box that says given or not given. Square, like a checkbox, because that
   is what it is -- the card around it is only a bigger place to click. */
.usr-role-box {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    border-radius: 6px;
    border: 1.5px solid color-mix(in srgb, var(--mud-palette-text-secondary) 60%, transparent);
    color: transparent;
    transition: background-color 140ms ease, border-color 140ms ease, color 140ms ease;
}

.usr-role-box .mud-icon-root {
    margin: 0;
    font-size: 0.86rem;
}

.usr-role-card.is-on .usr-role-box {
    border-color: var(--mud-palette-primary);
    background: var(--mud-palette-primary);
    color: #fff;
}

.usr-role-icon.mud-icon-root {
    flex: 0 0 auto;
    margin: 0;
    font-size: 1.35rem;
    color: var(--mud-palette-text-secondary);
    transition: color 140ms ease;
}

.usr-role-card.is-on .usr-role-icon.mud-icon-root {
    color: var(--mud-palette-primary);
}

.usr-role-body {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
}

.usr-role-name {
    font-size: 0.86rem;
    font-weight: 700;
    line-height: 1.25;
}

/* Two lines and no more. The descriptions run from three words to three lines,
   and a row of cards each choosing its own height is what makes a grid look
   broken; the full text stays in the title attribute. */
.usr-role-desc {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    color: var(--mud-palette-text-secondary);
    font-size: 0.73rem;
    font-weight: 400;
    line-height: 1.3;
}

@keyframes usr-role-in {
    from {
        opacity: 0;
        transform: translateY(6px) scale(0.98);
    }
}

@media (prefers-reduced-motion: reduce) {
    .usr-role-card {
        animation: none;
    }
}

/* --------------------------------------------------------------------------
   Inline notes

   What happens when this is saved, said where the decision is taken instead of
   in a snackbar afterwards. The warning tone is a tinted panel and not amber
   text: amber on a light surface is the one colour that fails to be read.
   -------------------------------------------------------------------------- */

.usr-note {
    display: flex;
    align-items: flex-start;
    gap: 0.45rem;
    margin-top: 0.8rem;
    color: var(--mud-palette-text-secondary);
    font-size: 0.76rem;
    line-height: 1.4;
}

.usr-note .mud-icon-root {
    flex: 0 0 auto;
    margin: 0.05rem 0 0;
    font-size: 1.1rem;
}

.usr-note.is-warn {
    padding: 0.6rem 0.75rem;
    border-radius: 11px;
    border: 1px solid color-mix(in srgb, var(--mud-palette-warning) 32%, transparent);
    background: color-mix(in srgb, var(--mud-palette-warning) 9%, transparent);
    color: var(--mud-palette-text-primary);
}

.usr-note.is-warn .mud-icon-root {
    color: var(--mud-palette-warning);
}

/* --------------------------------------------------------------------------
   The footer
   -------------------------------------------------------------------------- */

.mud-dialog.usr-dialog .mud-dialog-actions {
    gap: 0.6rem;
    margin: 0;
    padding: 1rem 1.5rem 1.35rem;
}

/* What is still missing, at the left end, where the eye goes after a button
   that will not press. */
.usr-dialog .app-dialog-hint {
    margin-right: auto;
}

.usr-dialog .mud-dialog-actions .mud-button-root {
    padding-inline: 1.15rem;
    border-radius: 11px;
    text-transform: none;
    font-size: 0.9rem;
    letter-spacing: 0;
}

.usr-dialog .mud-dialog-actions .mud-button-filled-primary {
    box-shadow: 0 10px 22px -12px color-mix(in srgb, var(--mud-palette-primary) 90%, transparent);
}

@media (max-width: 599px) {
    .usr-head,
    .mud-dialog.usr-dialog .mud-dialog-content,
    .mud-dialog.usr-dialog .mud-dialog-actions {
        padding-left: 1.05rem;
        padding-right: 1.05rem;
    }

    .usr-role-grid {
        grid-template-columns: 1fr;
    }

    .usr-head-icon {
        width: 46px;
        height: 46px;
        font-size: 1.25rem;
    }

    .usr-head-title {
        font-size: 1.15rem;
    }
}

/* Las pestañas de Zonas y Vendedores en modo lista. */
.cfg-root .cfg-tabla th {
    font-size: .78rem;
    font-weight: 700;
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.cfg-root .cfg-tabla td {
    vertical-align: middle;
}

/* =============================================================================
   Tareas en segundo plano (/core/tareas)

   Built on the dash-* language of the Sistema home -- hero, stat tiles, wide
   cards, chips -- so that it reads as one more screen of that family. What is
   added here is only what that family has no word for: a task inside its
   application segment, its facts with an icon each, the result band and the
   interval editor.
   ============================================================================= */

/* The hero controls sit on the red gradient, so they are white like the badges. */
.bgt-hero-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .25rem .75rem;
    margin-left: auto;
    color: #ffffff;
}

.bgt-hero-actions .mud-switch,
.bgt-hero-actions .mud-switch .mud-typography,
.bgt-hero-actions .mud-button-root {
    color: #ffffff;
}

.bgt-hero-actions .mud-button-outlined {
    border-color: rgba(255, 255, 255, 0.55);
}

.bgt-filters {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .5rem 1.25rem;
}

/* An application segment: a wide card whose title carries the counts. */
.bgt-app .dash-card-title {
    flex-wrap: wrap;
}

.bgt-app-chips {
    display: inline-flex;
    flex-wrap: wrap;
    gap: .3rem;
    margin-left: .35rem;
}

.bgt .dash-chip.is-info {
    border-color: color-mix(in srgb, var(--mud-palette-info) 50%, transparent);
    color: var(--mud-palette-info);
}

/* ---------------------------------------------- one task */

.bgt-task {
    display: flex;
    flex-direction: column;
    gap: .9rem;
    min-width: 0;
    padding: .95rem 1.05rem;
    border: 1px solid color-mix(in srgb, var(--mud-palette-primary) 16%, var(--mud-palette-lines-default));
    border-radius: 11px;
    background: color-mix(in srgb, var(--mud-palette-primary) 3%, var(--mud-palette-surface));
}

.bgt-task.tone-info    { border-color: color-mix(in srgb, var(--mud-palette-info) 45%, var(--mud-palette-lines-default)); }
.bgt-task.tone-warning { border-color: color-mix(in srgb, var(--mud-palette-warning) 40%, var(--mud-palette-lines-default)); }
.bgt-task.tone-error   { border-color: color-mix(in srgb, var(--mud-palette-error) 40%, var(--mud-palette-lines-default)); }

.bgt-head {
    display: flex;
    align-items: flex-start;
    flex-wrap: wrap;
    gap: .9rem;
}

.bgt-mark {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 46px;
    height: 46px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--mud-palette-primary) 12%, transparent);
}

.bgt-mark .mud-icon-root {
    color: var(--mud-palette-primary);
    font-size: 1.4rem;
}

.bgt-mark.tone-success { background: color-mix(in srgb, var(--mud-palette-success) 14%, transparent); }
.bgt-mark.tone-success .mud-icon-root { color: var(--mud-palette-success); }
.bgt-mark.tone-warning { background: color-mix(in srgb, var(--mud-palette-warning) 16%, transparent); }
.bgt-mark.tone-warning .mud-icon-root { color: var(--mud-palette-warning); }
.bgt-mark.tone-error   { background: color-mix(in srgb, var(--mud-palette-error) 14%, transparent); }
.bgt-mark.tone-error .mud-icon-root { color: var(--mud-palette-error); }
.bgt-mark.tone-info    { background: color-mix(in srgb, var(--mud-palette-info) 14%, transparent); }
.bgt-mark.tone-info .mud-icon-root { color: var(--mud-palette-info); }

.bgt-title {
    display: flex;
    flex-direction: column;
    gap: .3rem;
    flex: 1 1 18rem;
    min-width: 0;
}

.bgt-title-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .5rem;
}

.bgt-name {
    color: var(--mud-palette-text-primary);
    font-size: 1.05rem;
    font-weight: 800;
    line-height: 1.2;
    overflow-wrap: anywhere;
}

.bgt-title-row .dash-chip .mud-icon-root {
    font-size: .9rem;
}

.bgt-actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .5rem;
    margin-left: auto;
}

/* ---------------------------------------------- facts */

.bgt-facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(13rem, 100%), 1fr));
    gap: .6rem;
    padding: .75rem .9rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 10px;
    background: var(--mud-palette-surface);
}

.bgt-fact {
    display: flex;
    align-items: center;
    gap: .65rem;
    min-width: 0;
    padding: .2rem 0;
}

.bgt-fact + .bgt-fact {
    padding-left: .9rem;
    border-left: 1px solid var(--mud-palette-lines-default);
}

.bgt-fact-icon {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--mud-palette-primary) 12%, transparent);
}

.bgt-fact-icon .mud-icon-root {
    color: var(--mud-palette-primary);
    font-size: 1.15rem;
}

.bgt-fact-icon.tone-success { background: color-mix(in srgb, var(--mud-palette-success) 14%, transparent); }
.bgt-fact-icon.tone-success .mud-icon-root { color: var(--mud-palette-success); }
.bgt-fact-icon.tone-warning { background: color-mix(in srgb, var(--mud-palette-warning) 16%, transparent); }
.bgt-fact-icon.tone-warning .mud-icon-root { color: var(--mud-palette-warning); }
.bgt-fact-icon.tone-error   { background: color-mix(in srgb, var(--mud-palette-error) 14%, transparent); }
.bgt-fact-icon.tone-error .mud-icon-root { color: var(--mud-palette-error); }
.bgt-fact-icon.tone-info    { background: color-mix(in srgb, var(--mud-palette-info) 14%, transparent); }
.bgt-fact-icon.tone-info .mud-icon-root { color: var(--mud-palette-info); }

.bgt-fact-text {
    display: flex;
    flex-direction: column;
    gap: .05rem;
    min-width: 0;
    line-height: 1.2;
}

.bgt-fact-label {
    color: var(--mud-palette-text-secondary);
    font-size: .7rem;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
}

.bgt-fact-value {
    color: var(--mud-palette-text-primary);
    font-size: 1.15rem;
    font-weight: 800;
    /* Tabular digits: a countdown that changes width every second makes the row jitter. */
    font-variant-numeric: tabular-nums;
    overflow-wrap: anywhere;
}

.bgt-fact-note {
    color: var(--mud-palette-text-secondary);
    font-size: .76rem;
    overflow-wrap: anywhere;
}

/* On a phone the facts stack, and the dividers between them go horizontal. */
@media (max-width: 599px) {
    .bgt-fact + .bgt-fact {
        padding-left: 0;
        padding-top: .5rem;
        border-left: 0;
        border-top: 1px solid var(--mud-palette-lines-default);
    }
}

/* ---------------------------------------------- last result */

.bgt-last {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .55rem .8rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 10px;
    font-size: .9rem;
    color: var(--mud-palette-text-primary);
    background: color-mix(in srgb, var(--mud-palette-text-primary) 4%, var(--mud-palette-surface));
}

.bgt-last-icon {
    display: grid;
    place-items: center;
    flex: 0 0 auto;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--mud-palette-text-primary) 14%, transparent);
}

.bgt-last-icon .mud-icon-root {
    font-size: 1rem;
    color: var(--mud-palette-text-primary);
}

.bgt-last.tone-success {
    border-color: color-mix(in srgb, var(--mud-palette-success) 40%, transparent);
    background: color-mix(in srgb, var(--mud-palette-success) 12%, var(--mud-palette-surface));
}

.bgt-last.tone-success .bgt-last-icon { background: var(--mud-palette-success); }
.bgt-last.tone-success .bgt-last-icon .mud-icon-root { color: #ffffff; }

.bgt-last.tone-error {
    border-color: color-mix(in srgb, var(--mud-palette-error) 40%, transparent);
    background: color-mix(in srgb, var(--mud-palette-error) 12%, var(--mud-palette-surface));
}

.bgt-last.tone-error .bgt-last-icon { background: var(--mud-palette-error); }
.bgt-last.tone-error .bgt-last-icon .mud-icon-root { color: #ffffff; }

/* ---------------------------------------------- interval editor */

.bgt-interval {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .75rem 1rem;
    padding-top: .75rem;
    border-top: 1px solid var(--mud-palette-lines-default);
}

.bgt-history-toggle {
    align-self: flex-start;
}

/* ---------------------------------------------- history tables */

.bgt-history td,
.bgt-history th {
    font-size: .85rem;
    vertical-align: top;
}

.bgt-history td .dash-chip {
    margin-left: .35rem;
}

.bgt-history tr.tone-error .bgt-outcome { color: var(--mud-palette-error); font-weight: 700; }
.bgt-history tr.tone-success .bgt-outcome { color: var(--mud-palette-success); font-weight: 700; }
.bgt-history tr.tone-default .bgt-outcome { color: var(--mud-palette-text-secondary); font-weight: 700; }

@keyframes bgt-spin {
    to { transform: rotate(360deg); }
}

.bgt-spin {
    animation: bgt-spin 1.6s linear infinite;
}


/* ============================================================
   Notificaciones (/core/notificaciones)

   Built on the dash-* language of Sistema: hero, stat tiles and
   wide cards. What is added here is the list itself: one row per
   notification (tinted tile, title with the source beside it, the
   detail, the instant and person underneath), grouped under a day
   heading. The tile colours are the four severities, the same four
   the bell uses, so a row here looks like the row that rang.
   ============================================================ */

.notif-hero-actions {
    display: flex;
    align-items: center;
    gap: .5rem;
    margin-left: auto;
    color: #ffffff;
}

.notif-hero-actions .mud-button-root {
    color: #ffffff;
}

.notif-hero-actions .mud-button-outlined {
    border-color: rgba(255, 255, 255, 0.55);
}

/* The filter bar: one row, fields with a width of their own, chips in between.
   MudBlazor inputs grow to fill a flex row unless told not to, and a search box
   that grows to the height of the row is the shape this used to have. */
.notif-filters {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: .75rem 1rem;
    min-height: 0;
}

.notif-filters .notif-search {
    flex: 1 1 18rem;
    min-width: 14rem;
    max-width: 32rem;
}

.notif-filters .notif-source {
    flex: 0 1 16rem;
    min-width: 12rem;
}

.notif-filters .notif-severities {
    flex: 0 0 auto;
}

.notif-empty {
    align-items: center;
    gap: 0.6rem;
    min-height: 0;
    padding: 2rem 1rem;
    color: var(--ci-text-muted);
    text-align: center;
}

.notif-empty .mud-icon-root {
    color: var(--ci-text-muted);
    opacity: .7;
}

.notif-empty.tone-warning {
    border-color: color-mix(in srgb, var(--mud-palette-warning) 45%, transparent);
}

.notif-empty.tone-warning .mud-icon-root {
    color: var(--mud-palette-warning);
    opacity: 1;
}

.notif-list {
    gap: 0;
    min-height: 0;
    padding: .35rem .5rem;
}

.notif-day {
    display: flex;
    align-items: center;
    gap: .4rem;
    padding: .7rem .5rem .35rem;
    color: var(--mud-palette-text-secondary);
    font-size: .74rem;
    font-weight: 800;
    letter-spacing: .07em;
    text-transform: uppercase;
}

.notif-day .mud-icon-root {
    color: var(--mud-palette-primary);
}

.notif-day small {
    padding: .05rem .5rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 999px;
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: 0;
}

.notif-row {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: start;
    gap: 0.85rem;
    padding: 0.7rem 0.75rem;
    border-left: 3px solid transparent;
    border-radius: 10px;
    transition: background-color 140ms ease;
}

.notif-row:hover {
    background: color-mix(in srgb, var(--mud-palette-text-primary) 4%, transparent);
}

.notif-row + .notif-row {
    border-top: 1px solid var(--ci-outline);
    border-radius: 0;
}

/* A tinted edge per severity, so a red row is findable while scrolling a long day. */
.notif-row.tone-error { border-left-color: var(--mud-palette-error); }
.notif-row.tone-warning { border-left-color: var(--mud-palette-warning); }
.notif-row.tone-success { border-left-color: color-mix(in srgb, var(--mud-palette-success) 55%, transparent); }
.notif-row.tone-info { border-left-color: color-mix(in srgb, var(--mud-palette-info) 45%, transparent); }

.notif-tile {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    margin-top: 0.1rem;
    border-radius: 10px;
    background: color-mix(in srgb, var(--tono) 16%, transparent);
    color: var(--tono);
}

.notif-tile.tone-info { --tono: var(--mud-palette-info); }
.notif-tile.tone-success { --tono: var(--mud-palette-success); }
.notif-tile.tone-warning { --tono: var(--mud-palette-warning); }
.notif-tile.tone-error { --tono: var(--mud-palette-error); }

.notif-tile .mud-icon-root { color: var(--tono); }

.notif-body {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
    min-width: 0;
}

.notif-title-row {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.4rem;
}

.notif-title {
    font-weight: 700;
    overflow-wrap: anywhere;
}

.notif-message {
    font-size: 0.88rem;
    overflow-wrap: anywhere;
    white-space: pre-line;
}

.notif-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem 0.9rem;
    color: var(--ci-text-muted);
    font-size: 0.76rem;
    font-weight: 600;
}

.notif-meta span {
    display: inline-flex;
    align-items: center;
    gap: .25rem;
}

.notif-meta .mud-icon-root {
    font-size: .9rem;
    color: var(--ci-text-muted);
}

/* A note with an icon under a field of the automation dialog: what the field means or
   what its value implies. Bordered like the fact bands of the tasks screen, so a note
   and a warning read as the same family. */
.apr-note {
    display: flex;
    align-items: flex-start;
    gap: .55rem;
    padding: .55rem .8rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 10px;
    font-size: .88rem;
    line-height: 1.4;
    color: var(--mud-palette-text-secondary);
    background: color-mix(in srgb, var(--mud-palette-text-primary) 4%, var(--mud-palette-surface));
}

.apr-note .mud-icon-root {
    flex: 0 0 auto;
    margin-top: .1rem;
    color: var(--mud-palette-info);
}

.apr-note b {
    color: var(--mud-palette-text-primary);
}

.apr-note.is-warn {
    border-color: color-mix(in srgb, var(--mud-palette-warning) 45%, transparent);
    background: color-mix(in srgb, var(--mud-palette-warning) 10%, var(--mud-palette-surface));
}

.apr-note.is-warn .mud-icon-root {
    color: var(--mud-palette-warning);
}

.bgt-last.tone-warning {
    border-color: color-mix(in srgb, var(--mud-palette-warning) 45%, transparent);
    background: color-mix(in srgb, var(--mud-palette-warning) 10%, var(--mud-palette-surface));
}

.bgt-last.tone-warning .bgt-last-icon { background: var(--mud-palette-warning); }
.bgt-last.tone-warning .bgt-last-icon .mud-icon-root { color: #ffffff; }

/* The interval editor keeps its fields together instead of letting the inputs spread
   across the card: MudBlazor inputs grow to fill a flex row unless told not to. */
.bgt-interval .mud-input-control,
.bgt-interval > .mud-button-root {
    flex: 0 0 auto;
}

.bgt-interval > .bgt-fact-note {
    flex: 1 1 16rem;
}

.bgt-history td .dash-chip.is-info {
    margin-left: .45rem;
}

/* The installation the automation dialog is about, under its title: the rules and the
   clock are per installation, and a dialog that did not say which one would be read
   as the only one. */
.apr-title-text small {
    display: block;
    margin-top: .1rem;
    font-size: .78rem;
    font-weight: 600;
    letter-spacing: .02em;
    color: var(--mud-palette-text-secondary);
}

/* ---------------------------------------------------------------- operations monitor filters
   The filter block of the Monitor Operacional. Labels above the boxes, an icon on the left
   of every box, the two buttons level with the boxes and the auto refresh under them;
   the advanced filters below a divider. Palette variables only, so it follows the theme. */
.om-filters {
    padding: 20px 24px 24px;
    border: 1px solid var(--ci-outline);
    border-radius: 16px;
    background: var(--ci-surface);
}

.om-filters-head {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-bottom: 18px;
    color: var(--ci-text);
}

.om-filters-head .mud-icon-root {
    font-size: 1.9rem;
}

.om-filters-title {
    position: relative;
    padding-bottom: 8px;
    font-size: 1.15rem;
    font-weight: 600;
}

.om-filters-title::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 56px;
    height: 3px;
    border-radius: 2px;
    background: var(--ci-primary);
}

.om-filters-row {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr)) auto;
    gap: 16px 24px;
    align-items: start;
}

.om-filters-row-more {
    grid-template-columns: repeat(3, minmax(0, 1fr)) auto;
}

.om-field {
    min-width: 0;
}

.om-label {
    display: block;
    margin-bottom: 8px;
    font-size: .9rem;
    font-weight: 600;
    color: var(--ci-text);
}

.om-filters .mud-input-control {
    margin: 0 !important;
}

.om-filters .mud-input.mud-input-outlined {
    min-height: 46px;
}

.om-filters .mud-input-outlined-border {
    border-radius: 10px;
}

/* The icon of a box that has no adornment of its own (the date pickers use theirs). */
.om-input {
    position: relative;
}

.om-input-icon.mud-icon-root {
    position: absolute;
    left: 14px;
    top: 50%;
    transform: translateY(-50%);
    z-index: 1;
    pointer-events: none;
    color: var(--ci-text-muted);
}

.om-input .mud-input-slot {
    padding-left: 44px !important;
}

.om-actions {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
}

.om-buttons {
    display: flex;
    gap: 16px;
}

.om-filters .om-buttons .mud-button,
.om-filters .om-clear.mud-button {
    min-height: 46px;
    padding: 0 22px;
    border-radius: 10px;
}

/* «Más filtros» while the advanced row is open. */
.om-filters .om-toggle-on.mud-button {
    box-shadow: 0 0 0 3px rgba(249, 115, 22, 0.30) !important;
}

.om-clear.mud-button {
    color: var(--ci-text);
    border-color: var(--ci-outline);
    background: var(--ci-surface-soft);
    font-weight: 700;
}

.om-refresh {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 6px;
    margin-top: 12px;
}

.om-refresh .mud-switch {
    margin: 0;
}

.om-refresh-interval {
    max-width: 130px;
}

.om-info {
    color: var(--ci-text-muted);
    cursor: help;
}

.om-filters-divider {
    height: 1px;
    margin: 20px 0;
    background: var(--ci-outline);
}

@media (max-width: 1279px) {
    .om-filters-row,
    .om-filters-row-more {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }

    .om-actions {
        grid-column: 1 / -1;
    }

    .om-label-spacer {
        display: none;
    }
}

@media (max-width: 599px) {
    .om-filters {
        padding: 16px;
    }

    .om-filters-row,
    .om-filters-row-more {
        grid-template-columns: minmax(0, 1fr);
    }

    .om-actions,
    .om-buttons {
        align-items: stretch;
        width: 100%;
    }

    .om-buttons .mud-button {
        flex: 1 1 0;
    }
}

/* ---------------------------------------------------------------- price survey alert strip
   Levantamiento de precios: the warnings as a strip of cards. Fixed-width cards in one
   row; more than fit scroll sideways (snapping to a card), never wrap into a wall.
   Tone classes: .ps-alert-error / -warning / -info. */
.ps-alerts {
    padding: 14px 16px 16px;
    border: 1px solid var(--ci-outline);
    border-radius: 14px;
    background: var(--ci-surface);
}

.ps-alerts-head {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 12px;
    color: var(--ci-text);
}

.ps-alerts-title {
    font-weight: 600;
}

.ps-alerts-hidden-count {
    font-size: .8rem;
    color: var(--ci-text-muted);
}

.ps-alerts-toggle.mud-button {
    border-color: var(--ci-outline);
    color: var(--ci-text);
    text-transform: none;
}

.ps-alerts-strip {
    display: flex;
    gap: 14px;
    overflow-x: auto;
    padding-bottom: 6px;
    scroll-snap-type: x proximity;
    scrollbar-width: thin;
}

.ps-alert-card {
    --ps-tone: var(--mud-palette-error);
    flex: 0 0 clamp(260px, 31%, 360px);
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 14px 16px;
    border: 1px solid var(--ps-tone);
    border-radius: 12px;
    background: color-mix(in srgb, var(--ps-tone) 9%, var(--ci-surface));
    scroll-snap-align: start;
}

.ps-alert-error   { --ps-tone: var(--mud-palette-error); }
.ps-alert-warning { --ps-tone: var(--mud-palette-warning); }
.ps-alert-info    { --ps-tone: var(--mud-palette-info); }

.ps-alert-open {
    box-shadow: 0 0 0 2px var(--ps-tone);
}

.ps-alert-top {
    display: flex;
    align-items: center;
    gap: 10px;
    min-width: 0;
}

.ps-alert-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--ps-tone) 22%, transparent);
    color: var(--ps-tone);
}

.ps-alert-icon .mud-icon-root {
    font-size: 1.15rem;
}

.ps-alert-count {
    font-size: 1.6rem;
    font-weight: 700;
    line-height: 1;
    color: var(--ps-tone);
}

.ps-alert-label {
    min-width: 0;
    font-size: .8rem;
    font-weight: 600;
    color: var(--ps-tone);
}

.ps-alert-summary {
    flex: 1 1 auto;
    margin: 0;
    font-size: .82rem;
    line-height: 1.35;
    color: var(--ci-text);
}

.ps-alert-actions {
    display: flex;
    justify-content: flex-end;
}

.ps-alert-more.mud-button {
    border-color: var(--ps-tone);
    color: var(--ps-tone);
    border-radius: 999px;
    text-transform: none;
}

.ps-alert-detail {
    --ps-tone: var(--mud-palette-error);
    margin-top: 12px;
    padding: 12px 16px;
    border-left: 3px solid var(--ps-tone);
    border-radius: 8px;
    background: color-mix(in srgb, var(--ps-tone) 7%, var(--ci-surface));
}

.ps-alert-items {
    color: var(--ci-text-muted);
}

@media (max-width: 599px) {
    .ps-alert-card {
        flex-basis: 82%;
    }
}

/*  ============================================================
    SYPPLYPOS: TOKENS DE LA GUIA DE DISENO Y COMPONENTES POS

    Fuente: docs/paleta-de-colores-y-diseno-sistema.md. Los colores
    de marca, semanticos y de superficie ya llegan como
    --mud-palette-* desde ThemePreferenceService (claro y oscuro);
    aqui van los que la paleta de MudBlazor no tiene: los de los
    componentes especializados del punto de venta (seccion 6) y
    las medidas (seccion 7). Cualquier micro-frontend los usa con
    las clases sp-* de abajo, sin repetir hexadecimales.
    ============================================================ */

:root {
    --sp-primary: #F97316;
    --sp-primary-darken: #EA6D0D;
    --sp-primary-lighten: #FB923C;
    --sp-secondary: #1A2332;
    --sp-secondary-darken: #0F172A;
    --sp-secondary-lighten: #263342;

    --sp-success: #22C55E;
    --sp-success-strong: #16A34A;
    --sp-warning: #F59E0B;
    --sp-error: #EF4444;
    --sp-info: #3B82F6;

    --sp-radius: 8px;
    --sp-radius-control: 6px;
    --sp-drawer-width: 260px;
    --sp-appbar-height: 56px;

    /* POS Facil */
    --sp-easy-bar: #22C55E;
    --sp-easy-shortcut-bg: rgba(255, 255, 255, 0.18);
    --sp-cart-selected-bg: #F0FDF4;

    /* Dialogo de cobro */
    --sp-denomination-border: #D1D5DB;

    /* Badges fiscales */
    --sp-ecf-bg: #E0F2FE;
    --sp-ecf-border: #7DD3FC;
    --sp-ecf-text: #0369A1;
    --sp-ncf-bg: #F3E8FF;
    --sp-ncf-border: #D8B4FE;
    --sp-ncf-text: #6B21A8;
}

.mud-theme-dark,
:root[data-boot-theme="dark"] {
    --sp-cart-selected-bg: rgba(34, 197, 94, 0.12);
    --sp-denomination-border: #334155;
    --sp-ecf-bg: rgba(14, 165, 233, 0.14);
    --sp-ecf-border: rgba(125, 211, 252, 0.45);
    --sp-ecf-text: #7DD3FC;
    --sp-ncf-bg: rgba(168, 85, 247, 0.14);
    --sp-ncf-border: rgba(216, 180, 254, 0.45);
    --sp-ncf-text: #D8B4FE;
}

/* Radio de controles (inputs y botones): 6px, el de las tarjetas es 8px. */
.mud-button-root.mud-button,
.mud-input.mud-input-outlined .mud-input-outlined-border {
    border-radius: var(--sp-radius-control);
}

/* --- Teclas de atajo [F1]..[F12] -------------------------------- */
.sp-kbd {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2rem;
    padding: 0.1rem 0.4rem;
    border: 1px solid color-mix(in srgb, var(--sp-info) 45%, transparent);
    border-radius: 4px;
    background: color-mix(in srgb, var(--sp-info) 12%, transparent);
    color: var(--sp-info);
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.3;
    font-variant-numeric: tabular-nums;
}

/* --- Badges fiscales: e-CF (electronico) y NCF (tradicional) ------ */
.sp-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.15rem 0.55rem;
    border: 1px solid transparent;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.3;
}

.sp-badge-ecf {
    background: var(--sp-ecf-bg);
    border-color: var(--sp-ecf-border);
    color: var(--sp-ecf-text);
}

.sp-badge-ncf {
    background: var(--sp-ncf-bg);
    border-color: var(--sp-ncf-border);
    color: var(--sp-ncf-text);
}

/* --- Barra superior de POS Facil ---------------------------------- */
.sp-easy-bar {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    min-height: var(--sp-appbar-height);
    padding: 0.5rem 1rem;
    border-radius: var(--sp-radius);
    background: linear-gradient(135deg, var(--sp-easy-bar) 0%, var(--sp-success-strong) 100%);
    color: #FFFFFF;
}

.sp-easy-shortcut {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.35rem 0.7rem;
    border: 0;
    border-radius: 4px;
    background: var(--sp-easy-shortcut-bg);
    color: #FFFFFF;
    font: inherit;
    font-size: 0.8125rem;
    font-weight: 600;
    cursor: pointer;
    transition: background-color 120ms ease;
}

.sp-easy-shortcut:hover,
.sp-easy-shortcut:focus-visible {
    background: rgba(255, 255, 255, 0.28);
}

.sp-easy-shortcut .sp-kbd {
    border-color: rgba(255, 255, 255, 0.45);
    background: rgba(255, 255, 255, 0.15);
    color: #FFFFFF;
}

/* --- Carrito: fila seleccionada ---------------------------------- */
.sp-cart-row {
    border-left: 3px solid transparent;
    transition: background-color 120ms ease;
}

.sp-cart-row.is-selected {
    background: var(--sp-cart-selected-bg);
    border-left-color: var(--sp-easy-bar);
}

/* --- Dialogo de cobro ------------------------------------------- */
.sp-total {
    color: var(--sp-primary);
    font-size: 1.5rem;
    font-weight: 800;
    line-height: 1.2;
    font-variant-numeric: tabular-nums;
}

.sp-denomination {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 5.5rem;
    min-height: 3rem;
    padding: 0.5rem 0.9rem;
    border: 1px solid var(--sp-denomination-border);
    border-radius: var(--sp-radius);
    background: var(--mud-palette-surface);
    color: var(--mud-palette-text-primary);
    font: inherit;
    font-weight: 700;
    cursor: pointer;
    transition: transform 120ms ease, border-color 120ms ease, box-shadow 120ms ease;
}

.sp-denomination:hover,
.sp-denomination:focus-visible {
    transform: translateY(-1px);
    border-color: var(--sp-primary);
    box-shadow: 0 4px 12px rgba(249, 115, 22, 0.16);
}

/* Boton Confirmar Cobro [F10]: verde solido, ancho completo. */
.sp-confirm.mud-button-root {
    width: 100%;
    min-height: 3rem;
    background-color: var(--sp-success-strong);
    color: #FFFFFF;
    font-weight: 700;
}

.sp-confirm.mud-button-root:hover {
    background-color: color-mix(in srgb, var(--sp-success-strong) 88%, #000000);
}

/* Muestras de color (pagina de demostracion de la paleta). */
.sp-swatch {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    min-width: 0;
}

.sp-swatch-chip {
    height: 56px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: var(--sp-radius);
}

.sp-swatch-name {
    font-weight: 600;
    font-size: 0.8125rem;
}

.sp-swatch-hex {
    color: var(--mud-palette-text-secondary);
    font-size: 0.75rem;
    font-family: ui-monospace, "Cascadia Code", Consolas, monospace;
}

/* Lado de marca del inicio de sesion. */
.login-brand-mark {
    width: 7rem;
    height: 7rem;
    border-radius: 24px;
    box-shadow: 0 18px 40px rgba(249, 115, 22, 0.35);
}

.login-brand-name {
    color: #FFFFFF;
    font-size: clamp(2.4rem, 4vw, 3.4rem);
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.1;
}

.login-brand-name span {
    color: var(--sp-primary);
}

.login-brand-tagline {
    max-width: 30rem;
    color: rgba(255, 255, 255, 0.78);
    font-size: 1.0625rem;
    line-height: 1.6;
    text-align: center;
}

.login-brand-chips {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.5rem;
}

.login-brand-chips span {
    padding: 0.3rem 0.75rem;
    border: 1px solid rgba(255, 255, 255, 0.16);
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.06);
    color: rgba(255, 255, 255, 0.86);
    font-size: 0.75rem;
    font-weight: 600;
}

/* Empresa y pantalla completa permanecen accesibles en escritorio y caja táctil. */
.monitor-company { max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; font-size: .8rem; }
.monitor-fullscreen { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 44px; width: 44px; height: 44px; border: 0; border-radius: 50%; color: inherit; background: transparent; cursor: pointer; }
.monitor-fullscreen:hover, .monitor-fullscreen:focus-visible { background: var(--mud-palette-action-default-hover); outline: 2px solid var(--mud-palette-primary); }
.fullscreen-exit { display: none; }
:fullscreen .fullscreen-enter { display: none; }
:fullscreen .fullscreen-exit { display: inline-flex; }
@media (max-width: 700px) { .monitor-company { display: none; } }
