﻿/* ============================================================
   InsCore — Dark Glass Design System
   1.  Design Tokens
   2.  Global Reset & Font Rendering
   3.  Animated Background Orbs
   4.  AppBar — Glass Surface
   4bis. Texto con degradado (receta única .ins-gradient-text)
   5.  Drawer — Glass Surface
   6.  Cards & Papers — Glassmorphism
   7.  Tables
   8.  Inputs & Buttons
   9.  Nav Links
   10. KPI Cards
   11. Empty State
   12. Page Entry Animations
   13. Light Mode Overrides
   14. Responsive Media Queries
   15. Reconexión del circuito (Blazor Server)
   16. Antídoto overlay de popover (MudBlazor 8.4)
   17. Pestañas: ninguna flecha que no pueda desplazar nada
   ============================================================ */

/* ── 1. Design Tokens ─────────────────────────────────────── */
:root {
    /* Glassmorphism surfaces */

    /* M-340 · La superficie de la TARJETA en oscuro. Sube por encima de su lienzo, y esa es toda la
       corrección: antes componía a rgb(12,22,48) sobre un lienzo rgb(15,23,42), o sea la tarjeta era
       MÁS OSCURA que su propia página —contraste 1,003:1, medido renderizado— y por eso el usuario
       reportó que «se mimetiza con la descripción, no hay bordes de card, tienen el mismo color».
       🏆 El eje es la SUPERFICIE y no la sombra porque es el estándar del sector para tema oscuro
       (Material: «in dark theme, elevation is expressed with lighter surface colors rather than
       shadows»): una sombra negra sobre un lienzo casi negro no la ve nadie.
       Sigue siendo cristal —semitransparente y con `--glass-blur` detrás—, solo que elevado.

       🔭 s73 · SUBE OTRA VEZ, Y EL MOTIVO ES QUE EL LIENZO NO ERA EL QUE CREÍAMOS. Medido renderizado
       el 17-ago-2026 (sonda de píxeles sobre la app en pie, Home y /analytics, los dos temas, velo de
       reconexión comprobado): en Home OSCURO el peor par tarjeta/lienzo daba **1,077:1**, por debajo del
       suelo 1,15 que esta misma casa fijó — y el guard lo daba por bueno porque componía contra
       `rgb(15,23,42)`, el lienzo PELADO. Pero encima del lienzo hay ORBES fijos declarados en esta misma
       hoja (§3), y bajo un orbe la página sube hasta `rgb(21,38,72)` medido —`rgb(23,42,79)` según el
       modelo de esta hoja—, mientras la tarjeta, que solo recibe el 28 % del orbe a través de su alfa,
       sube mucho menos. El hueco se cierra justo donde el usuario dijo «brillo».
       ⇒ El eje que se mueve es el TONO, no el alfa: subir el alfa converge la tarjeta a este mismo
       color y ni siquiera opaca llegaba a 1,15 sobre un orbe (1,103 calculado). Con este valor el par
       da 1,206:1 bajo el orbe y 1,401:1 sobre el lienzo pelado. Lo vigilan, ya contra el lienzo CON
       orbes, `ACardHasItsOwnSurfaceInBothThemesTests` y `AKpiNumberAndItsCardKeepBothContrastPairsTests`.

       ⚖️ Y EL VALOR SE RECALIBRÓ A LA BAJA DENTRO DE LA MISMA SESIÓN, que es la parte que importa. El
       primer intento fue `rgba(50,68,110,0.72)` y daba 1,318:1: cumplía de sobra el par de ABAJO
       —tarjeta contra su página— y se llevaba por delante el de ARRIBA. Con esa superficie el RÓTULO
       secundario de la tarjeta caía a 4,20:1 bajo un orbe, por debajo del 4,5 que pide un texto de
       14 px. Son suelo y techo del MISMO fondo: subirlo separa la tarjeta de su página y hunde lo que
       va escrito encima. Este valor es el que deja los DOS: 1,206:1 contra la página (suelo 1,15) y
       4,59:1 para el rótulo (suelo 4,5). Lo vigila también
       `ASecondaryLabelLiftsOffItsSurfaceTests`. */
    --glass-bg:             rgba(44, 60, 98, 0.72);
    --glass-bg-heavy:       rgba(6, 14, 30, 0.85);
    --glass-border:         rgba(148, 163, 184, 0.10);

    /* M-340 · El canto de la tarjeta, SEPARADO de `--glass-border`. Son dos papeles distintos y por eso
       dos variables: `--glass-border` peina siete sitios (barra, cajón, separadores de tabla…) donde una
       línea tenue es lo correcto; el canto de una tarjeta es lo que dice DÓNDE ACABA la tarjeta. Sobre
       lienzo oscuro un canto se ve MENOS, así que darle 0,10 —la mitad que en claro, que usa 0,20— era
       justo al revés de lo que pide la superficie. */
    --glass-border-card:    rgba(148, 163, 184, 0.22);
    --glass-border-hover:   rgba(148, 163, 184, 0.38);
    --glass-blur:           blur(20px) saturate(180%);
    --glass-blur-heavy:     blur(32px) saturate(200%);

    /* Layout */
    --app-radius-card:      18px;
    --app-radius-input:     12px;
    --app-radius-button:    10px;

    /* Shadows */
    --app-shadow-card:       0 4px 24px rgba(0, 0, 0, 0.35), 0 1px 3px rgba(0, 0, 0, 0.20);
    --app-shadow-card-hover: 0 8px 40px rgba(59, 130, 246, 0.18), 0 2px 8px rgba(0, 0, 0, 0.30);
    --app-glow-blue:         0 0 40px rgba(59, 130, 246, 0.15);
    --app-glow-violet:       0 0 40px rgba(124, 58, 237, 0.12);

    /* Animation timing */
    --anim-ease:   cubic-bezier(0.16, 1, 0.3, 1);
    --anim-fast:   180ms;
    --anim-normal: 280ms;
    --anim-slow:   500ms;

    /* Orb colors */
    --orb-blue:   rgba(59, 130, 246, 0.18);
    --orb-violet: rgba(124, 58, 237, 0.13);
    --orb-mint:   rgba(16, 185, 129, 0.10);

    /* Rampas del texto con degradado (ver §4bis .ins-gradient-text). Modo oscuro por defecto;
       body.ins-light las reescribe abajo. Declaradas como token para que la RECETA del degradado
       viva en UN solo bloque y solo cambie de color según el modo. */
    --ins-gradient-text:        linear-gradient(135deg, #e2e8f0 0%, #94a3b8 100%);
    --ins-gradient-text-accent: linear-gradient(135deg, #e2e8f0 0%, #93c5fd 100%);
    /* 💼 La CIFRA de una tarjeta KPI, sólida: es la primera parada de la rampa que sustituye, así
       que el par de contraste que su guard medía no empeora — y ahora es UN color, no dos. */
    --ins-kpi-number: #e2e8f0;
}

/* ── 2. Global Reset & Font Rendering ─────────────────────── */
html, body {
    font-feature-settings: 'cv11', 'ss01', 'liga' 1;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

body {
    background-color: var(--mud-palette-background, #050d1a);
    overflow-x: hidden;
}

/* ── 3. Animated Background Orbs ──────────────────────────── */
.app-bg-orbs {
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    overflow: hidden;
}

.app-orb {
    position: absolute;
    border-radius: 50%;
    filter: blur(80px);
    will-change: transform;
    animation-timing-function: ease-in-out;
    animation-iteration-count: infinite;
    animation-direction: alternate;
}

.app-orb--blue {
    width: clamp(400px, 60vw, 900px);
    height: clamp(400px, 60vw, 900px);
    background: radial-gradient(circle, var(--orb-blue) 0%, transparent 70%);
    top: -20%;
    right: -10%;
    animation: orbFloat 14s ease-in-out infinite alternate;
}

.app-orb--violet {
    width: clamp(300px, 45vw, 700px);
    height: clamp(300px, 45vw, 700px);
    background: radial-gradient(circle, var(--orb-violet) 0%, transparent 70%);
    bottom: -15%;
    left: -5%;
    animation: orbFloat 18s ease-in-out infinite alternate-reverse;
    animation-delay: -6s;
}

.app-orb--mint {
    width: clamp(200px, 30vw, 500px);
    height: clamp(200px, 30vw, 500px);
    background: radial-gradient(circle, var(--orb-mint) 0%, transparent 70%);
    top: 40%;
    left: 30%;
    animation: orbFloat 22s ease-in-out infinite alternate;
    animation-delay: -10s;
}

@keyframes orbFloat {
    0%   { transform: translate(0, 0) scale(1); }
    33%  { transform: translate(40px, -30px) scale(1.05); }
    66%  { transform: translate(-20px, 20px) scale(0.97); }
    100% { transform: translate(30px, 40px) scale(1.03); }
}

/* Layout layers sit above orbs — only mud-layout needs stacking context;
   AppBar/Drawer/MainContent use MudBlazor's own z-indices (1100+) */
.mud-layout {
    position: relative;
    z-index: 1;
}

/* ── 4. AppBar — Glass Surface ────────────────────────────── */
.mud-appbar {
    background: var(--glass-bg-heavy) !important;
    backdrop-filter: var(--glass-blur-heavy);
    -webkit-backdrop-filter: var(--glass-blur-heavy);
    border-bottom: 1px solid var(--glass-border) !important;
    box-shadow: none !important;
}

.mud-appbar::after {
    content: '';
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    height: 1px;
    background: linear-gradient(
        90deg,
        transparent 0%,
        rgba(59, 130, 246, 0.35) 30%,
        rgba(124, 58, 237, 0.25) 70%,
        transparent 100%
    );
    pointer-events: none;
}

/* Brand name — usa la receta única de degradado (§4bis). Aquí solo su tipografía. */
.mud-appbar .mud-typography-h6 {
    font-family: 'Syne', system-ui, sans-serif;
    font-weight: 700;
    letter-spacing: -0.01em;
}

/* ── 4bis. Texto con degradado — UNA sola receta ────────────────────────────────
   `-webkit-background-clip: text` NO recorta por `overflow`: hace que el fondo del elemento se
   pinte SOLO dentro de su PADDING BOX y que el texto sea la máscara. Todo trazo que sobresalga
   del padding box —los rabos de la «g», la «y», la «p», la «j» de Syne, que es display y los
   tiene profundos— simplemente NO SE PINTA. No hay tinta ahí, así que no hay nada que "no
   recortar": la única cura es AGRANDAR el lienzo.

   Compensación: `padding-bottom` agranda el lienzo hacia abajo y un `margin-bottom` negativo de
   la MISMA cuantía devuelve el alto, de modo que la CAJA DE MARGEN queda idéntica a la de antes.
   Consecuencia: ni el centrado vertical del AppBar (flex, centra la caja de margen) ni el flujo
   normal de las tarjetas KPI se mueven un píxel; lo único que cambia es que ahora hay pintura
   bajo la línea de base.

   Precedente en el propio repo: `InsBrandWordmark` (commit e903b1f3, «deja de recortarse
   Abi4Broker») ya demostró que un degradado de marca no obliga a recortar el nombre. Aquello se
   resolvió en un componente y no se generalizó; esto lo generaliza.

   Los CUATRO sitios que antes repetían la receta (marca del AppBar, cifras KPI y sus dos gemelos
   de modo claro) la consumen desde aquí. La clase `.ins-gradient-text` queda además disponible
   para marcado nuevo, sin volver a copiar las cuatro declaraciones.

   ⚠️ Por qué importa aunque «Abi4Broker» no tenga descendentes: el rótulo del AppBar es el NOMBRE
   COMERCIAL DEL TENANT. En cuanto una correduría se llame «Aseguradora Vega» o «Seguros Ángel»,
   el degradado le come el rabo de la «g». Es un defecto latente por dato, no por diseño. */
.ins-gradient-text,
.mud-appbar .mud-typography-h6 {
    background-image: var(--ins-gradient-text);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    padding-bottom: 0.15em;
    margin-bottom: -0.15em;
}

/* Variante con acento azul. Misma receta, distinta rampa. */
.ins-gradient-text--accent {
    background-image: var(--ins-gradient-text-accent);
}

/* ── 5. Drawer — Glass Surface ────────────────────────────── */
.mud-drawer {
    background: var(--glass-bg-heavy) !important;
    backdrop-filter: var(--glass-blur-heavy);
    -webkit-backdrop-filter: var(--glass-blur-heavy);
    border-right: 1px solid var(--glass-border) !important;
}

.mud-drawer::after {
    content: '';
    position: absolute;
    top: 0;
    right: 0;
    width: 1px;
    height: 100%;
    background: linear-gradient(
        180deg,
        transparent 0%,
        rgba(59, 130, 246, 0.40) 30%,
        rgba(124, 58, 237, 0.30) 70%,
        transparent 100%
    );
    pointer-events: none;
}

/* Drawer: el menú de navegación scrollea dentro del drawer (alto fijo bajo el AppBar),
   de forma independiente al scroll de la página — así se alcanzan los grupos del final
   (Ajustes, Manual) sin alargar la página al abrir una categoría. */
.app-drawer .mud-drawer-content {
    display: flex;
    flex-direction: column;
    height: 100%;
    min-height: 0;
}

.app-drawer .mud-navmenu {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain;
}

/* ── Barra compacta "pegajosa" de páginas de detalle (PageHeader): SOLO SU TEMA ──
   🧹 s73 · Su geometría, su ritmo y su despliegue viven en `insDetail.css` (RCL), que es el SSOT de la
   banda de detalle y lo enlazan los tres hosts. Aquí estaban las 35 líneas enteras, y las mismas 35
   estaban calcadas en el `theme.css` del backoffice y —con cuatro divergencias— en `portal.css`: tres
   copias que divergen en silencio en cuanto alguien toca una.
   Lo que se queda es lo que SÍ es de este host y el bloque neutro no puede saber: el fondo opaco de
   cristal, idéntico al de la cabecera fija de listados. */
.ins-detail-stickybar {
    background-image: linear-gradient(rgba(10, 22, 50, 0.50), rgba(10, 22, 50, 0.50));
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
}

/* 🌕 s73 · Y SU CONTRAPARTE CLARA, que no existía. La destapó medir el par barra/página en vivo antes de
   mover el bloque: en tema CLARO la barra COMPUTA `rgb(255,255,255)` pero se PINTA `rgb(132,138,152)`,
   un gris oscuro — porque el tinte navy de arriba se aplicaba también en claro, al 50 % sobre blanco.
   Es la misma clase que este carril lleva toda la sesión persiguiendo: un valor de tema oscuro que se
   filtra al claro porque nadie escribió la mitad que falta.
   🏆 No es invención: es EXACTAMENTE lo que esta hoja ya hace con la cabecera fija de listados, que
   declara su tinte claro `rgba(248,250,255,0.80)` junto al oscuro. El papel del tinte es el mismo en los
   dos temas —volver OPACA una superficie translúcida para que el contenido no se transparente al pasar
   por debajo—, así que lo que cambia es el color, no el mecanismo. */
body.ins-light .ins-detail-stickybar {
    background-image: linear-gradient(rgba(248, 250, 255, 0.80), rgba(248, 250, 255, 0.80));
}

/* ── PILA de tarjetas dentro de una columna de la ficha de detalle ────────────────
   Cierra el defecto que originó la ola 10. La rejilla de MudBlazor es `flex-wrap`: empareja por
   FILA, y la altura de una fila la fija su tarjeta más alta. Dos consecuencias, las dos medidas en
   la ficha de póliza:

   1. Una tarjeta larga ("Datos del contrato", con su tabla fiscal) al lado de una corta
      ("Renovación", 4 líneas) deja bajo la corta un hueco tan alto como la diferencia — y justo en
      la zona de MÁXIMA prioridad, la que se lee sin hacer scroll.
   2. Una tarjeta a media anchura SIN pareja (la siguiente es de anchura completa, así que salta de
      fila) deja la MITAD de una fila vacía.

   ⚠️ `align-items: start` sobre la rejilla NO lo arregla, y conviene dejarlo escrito para que no se
   vuelva a intentar: el `MudItem` sí se estira a la altura de la fila, pero el `MudPaper` de dentro
   es un bloque de altura automática y nunca la llenaba. Estirar o no el contenedor no cambia un
   pixel de lo que se ve; el hueco no es de ALINEACIÓN, es de REPARTO.

   Así que las columnas dejan de fluir por su cuenta y el reparto SE DECLARA: la columna corta se
   completa APILANDO varias tarjetas cortas —esta clase es esa pila—, en vez de esperar a que
   termine la larga de al lado. Qué tarjeta va en qué columna lo dice el markup, por prioridad de
   lectura.

   Por qué no `column-count`, que balancearía solo sin declarar nada: las secciones son PLEGABLES;
   al plegar una, el navegador reequilibraría y las tarjetas SALTARÍAN de columna bajo el cursor.
   Un reparto declarado no se mueve nunca.

   El `gap` iguala el `Spacing="3"` de la MudGrid que la contiene, para que apilar dentro de una
   columna y repartir entre columnas separen exactamente igual. */
.ins-detail-col {
    display: flex;
    flex-direction: column;
    gap: 24px;
    min-width: 0;
}

/* ── Sección plegable de una ficha (CollapsibleSection) ───────────────────────────
   La otra mitad del defecto "sábana continua": la maquetación de la sección estaba escrita como
   `style=` sueltos dentro del componente, así que la SEPARACIÓN —lo que hace que el ojo vea dónde
   acaba una sección y empieza la siguiente— no era ajustable desde ningún sitio. Aquí sí. */
.ins-section {
    border-radius: 12px;
    overflow: hidden;
}

.ins-section__head {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 14px 16px 12px;
    cursor: pointer;
    user-select: none;
}

.ins-section__actions {
    display: flex;
    align-items: center;
    gap: 4px;
    cursor: default;
}

/* Ayuda de la sección (M-047): pegada al TÍTULO, no al grupo de acciones. La distinción no es estética
   —un icono suelto entre botones se lee como un botón más—, y la única forma de que quede junto al
   título sin cambiar el resto es que en ese caso el título deje de ser quien empuja y empuje la ayuda:
   por eso el `margin-right:auto` viaja aquí y el título renuncia a crecer SOLO cuando hay ayuda. Sin
   ayuda, nada cambia y las acciones siguen alineadas a la derecha como siempre. */
.ins-section__help {
    display: flex;
    align-items: center;
    margin-right: auto;
    cursor: default;
    color: var(--mud-palette-text-secondary);
}

.ins-section__head:has(.ins-section__help) .ins-section__title {
    flex: 0 1 auto;
}

.ins-section__chevron {
    color: var(--mud-palette-text-secondary);
    flex-shrink: 0;
}

/* El contenido arranca separado del título en lugar de pegado a él: es la separación que distingue
   "de qué se habla" de "lo que se dice", y la que faltaba para que las secciones no se mimeticen.
   M-575: con el filete bajo la cabecera (insForms.css, regla compartida de los tres componentes de
   título), este padding es el AIRE de debajo de la raya — 4px la dejaban pegada al contenido. */
.ins-section__body {
    padding: 12px 16px 16px;
}

/* El título ocupa el ancho libre de la cabecera. La jerarquía (peso, color, tracking) NO se declara
   aquí: viene de `.ins-section-title` del RCL, que es el papel compartido. Lo único que se sube en
   esta superficie es el TAMAÑO — `Typo.subtitle1` es 1rem, exactamente el mismo cuerpo que el valor
   de un dato, y con el mismo cuerpo el peso solo no bastaba para separarlos. */
.ins-section__title {
    flex: 1;
    margin: 0;
    font-size: 1.0625rem;
    line-height: 1.4;
}

/* ── 6. Cards & Papers — Glassmorphism ────────────────────── */
/* M-340 · La tarjeta declara su SUPERFICIE en los dos temas, no solo en claro.
   Lo que había era asimétrico y el usuario lo cazó por el lado roto: en CLARO la tarjeta tenía canto
   (alfa 0,20) y sombra de dos capas; en OSCURO tenía la mitad de canto (0,10) y CERO sombra —`box-shadow`
   computado: `none`—. Medido renderizado sobre `/policies/{id}`: tarjeta vs lienzo daba **1,003:1** en
   oscuro contra 1,091:1 en claro.
   ⚠️ El `box-shadow` de aquí lo pisa `body.ins-light .mud-paper`, que declara el suyo: esta línea es la
   del tema OSCURO. Y `transition` menciona `box-shadow` desde antes de que existiera la sombra — una
   transición de algo que nunca se declaraba, que es justo lo que engañaba a cualquier búsqueda por
   texto. Lo vigila `ACardHasItsOwnSurfaceInBothThemesTests`. */
.mud-paper {
    background: var(--glass-bg) !important;
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    border: 1px solid var(--glass-border-card);
    border-radius: var(--app-radius-card);
    box-shadow: var(--app-shadow-card);
    transition:
        box-shadow var(--anim-normal) var(--anim-ease),
        border-color var(--anim-normal) var(--anim-ease),
        transform var(--anim-normal) var(--anim-ease);
}

.mud-card {
    box-shadow: var(--app-shadow-card);
}

.mud-card:hover,
.mud-paper.app-card-hover:hover {
    box-shadow: var(--app-shadow-card-hover);
    border-color: var(--glass-border-hover);
    transform: translateY(-2px);
}

/* Dialogs */
.mud-dialog {
    background: rgba(6, 14, 35, 0.94) !important;
    backdrop-filter: var(--glass-blur-heavy);
    -webkit-backdrop-filter: var(--glass-blur-heavy);
    border: 1px solid var(--glass-border-hover);
    border-radius: var(--app-radius-card);
    box-shadow: 0 24px 80px rgba(0, 0, 0, 0.60), var(--app-glow-blue);
}

/* Popovers / dropdowns */
.mud-popover-paper {
    background: rgba(6, 14, 35, 0.96) !important;
    backdrop-filter: var(--glass-blur-heavy);
    -webkit-backdrop-filter: var(--glass-blur-heavy);
    border: 1px solid var(--glass-border-hover);
    border-radius: var(--app-radius-input);
}

/* .ins-tall-popover (selects de lista larga) vive ahora en el RCL compartido insLayout.css —
   SSOT único para los 3 hosts; se eliminó de aquí para no duplicar. */

/* ── 7. Tables ─────────────────────────────────────────────── */
.mud-table-root .mud-table-head .mud-table-cell {
    font-family: 'Inter', system-ui, sans-serif;
    font-weight: 600;
    font-size: 0.72rem;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--mud-palette-text-secondary);
    background: rgba(10, 22, 50, 0.50) !important;
    border-bottom: 1px solid var(--glass-border);
}

.mud-table-root .mud-table-body .mud-table-row {
    transition: background-color var(--anim-fast) ease;
}

.mud-table-root .mud-table-row.app-row-hover:hover,
.mud-table-root .mud-table-body .mud-table-row:hover {
    background-color: rgba(59, 130, 246, 0.06) !important;
}

.mud-table-root .mud-table-cell {
    border-bottom: 1px solid var(--glass-border);
}

/* ── Listados: área de scroll acotada al viewport (patrón data-grid) ──
   ⚠️ LA BASE NO VIVE AQUÍ (M-137). `.ins-listado .mud-table-container` (altura acotada al viewport,
   scroll en ambos ejes, cabecera pegada) la declara el asset compartido del RCL,
   `_content/InsCore.Ui.Gadgets/insList.css`, el mismo que usan Backoffice y portal tomador. Este host
   era el único que NO lo enlazaba, así que llevaba su propia copia de estas reglas Y de las de
   `.app-list-toolbar*` — dos copias de la misma clase en dos zonas, que divergen en silencio en cuanto
   alguien toca una. El enlace está ahora en App.razor y aquí queda SOLO lo que es del broker: el tinte
   de cabecera con los colores de su tema (y su variante clara), que el asset neutro no puede saber. */

/* La cabecera fija (FixedHeader) queda pegada arriba mientras el cuerpo se
   desplaza por debajo. El tinte de cabecera de la app es translúcido (alpha
   0.50 en oscuro / 0.80 en claro), lo que dejaba TRASLUCIR las filas al pasar
   bajo ella. Lo volvemos OPACO sin cambiar su aspecto: una base sólida de
   superficie + el mismo tinte por encima (gradiente plano). Reusa los valores
   existentes, así el color es idéntico al estático. */
.ins-listado .mud-table-container .mud-table-head .mud-table-cell {
    background-color: var(--mud-palette-surface) !important;
    background-image: linear-gradient(rgba(10, 22, 50, 0.50), rgba(10, 22, 50, 0.50)) !important;
}

body.ins-light .ins-listado .mud-table-container .mud-table-head .mud-table-cell {
    background-color: var(--mud-palette-surface) !important;
    background-image: linear-gradient(rgba(248, 250, 255, 0.80), rgba(248, 250, 255, 0.80)) !important;
}

/* ── Kanban board (Trello/Salesforce) ───────────────────────────
   Columnas en UNA fila con scroll horizontal, en lugar de un grid que
   envuelve y deja la última columna colgando abajo (caso 7 estados de
   siniestros). Compartido por los tableros de siniestros y prospectos. */
.ins-kanban-board {
    display: flex;
    flex-wrap: nowrap;
    gap: 12px;
    overflow-x: auto;
    padding-bottom: 8px;
    scroll-snap-type: x proximity;
}

.ins-kanban-column {
    flex: 0 0 248px;
    min-width: 248px;
    scroll-snap-align: start;
}

/* ── Toolbar transversal de listas (ListToolbar) ─────────────────
   Los estilos base viven en el asset compartido `_content/InsCore.Ui.Gadgets/insList.css`
   (`.app-list-toolbar*`), el mismo que usan Backoffice y portal tomador — enlazado en App.razor.
   Aquí no queda ninguna copia: la que había era la mitad divergente de M-137. */

/* ── 8. Inputs & Buttons ───────────────────────────────────── */
.mud-input-outlined-border {
    border-color: var(--glass-border) !important;
    border-radius: var(--app-radius-input) !important;
    transition: border-color var(--anim-fast) ease, box-shadow var(--anim-fast) ease;
}

.mud-input-outlined:hover .mud-input-outlined-border {
    border-color: var(--glass-border-hover) !important;
}

.mud-input-outlined.mud-focused .mud-input-outlined-border {
    border-color: rgba(59, 130, 246, 0.60) !important;
    box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.12);
}

.mud-input-control .mud-input-slot {
    border-radius: var(--app-radius-input);
    background: rgba(10, 22, 50, 0.40);
}

.mud-button-root {
    border-radius: var(--app-radius-button) !important;
    text-transform: none;
    font-family: 'Inter', system-ui, sans-serif;
    font-weight: 500;
    letter-spacing: 0.02em;
    transition:
        box-shadow var(--anim-fast) var(--anim-ease),
        transform var(--anim-fast) var(--anim-ease);
}

.mud-button-filled.mud-button-filled-primary {
    background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%) !important;
    box-shadow: 0 4px 16px rgba(59, 130, 246, 0.30);
}

.mud-button-filled.mud-button-filled-primary:hover {
    box-shadow: 0 6px 24px rgba(59, 130, 246, 0.45);
    transform: translateY(-1px);
}

.mud-button-filled.mud-button-filled-primary:active {
    transform: translateY(0);
    box-shadow: 0 2px 8px rgba(59, 130, 246, 0.30);
}

/* ── 9. Nav Links ─────────────────────────────────────────── */
.mud-nav-link {
    margin: 2px 8px;
    border-radius: 10px;
    transition:
        background-color var(--anim-fast) ease,
        color var(--anim-fast) ease;
}

.mud-nav-link:hover {
    background-color: rgba(59, 130, 246, 0.08);
}

.mud-nav-link.active {
    background: linear-gradient(
        90deg,
        rgba(59, 130, 246, 0.18) 0%,
        rgba(59, 130, 246, 0.06) 100%
    );
    color: #60a5fa !important;
    border-radius: 10px;
    box-shadow: inset 3px 0 0 #3b82f6;
}

.mud-nav-link.active .mud-icon-root {
    color: #3b82f6 !important;
}

/* ── 10. KPI Cards ────────────────────────────────────────── */
/* M-572 · La tarjeta KPI se construye SOBRE la superficie de M-340, no en su lugar.
   Re-medido renderizado el 17-ago (sonda Playwright, Home y /analytics, 1440×900, tema fijado por
   preferencia + recarga): la premisa de la ficha era FALSA — el par TEXTO/TARJETA estaba sano (peor
   punto medido 5,90:1 en oscuro y 4,86:1 en claro, sobre un umbral de 3:1 para cifra h3/800). El que
   estaba roto era el par TARJETA/LIENZO: el degradado anterior terminaba en rgba(10,22,50,0.60), que
   compone POR DEBAJO del lienzo —medido en Home oscuro: 1,011:1 en la esquina oscura—, o sea la clase
   exacta de M-340 viva aquí porque este `background` con `!important` pisa el `--glass-bg` que aquel
   mandato subió. La cifra parecía «mimetizarse» porque su tarjeta entera no tenía superficie.
   🌳 Raíz: el fondo propio deja de rehacer la superficie y pasa a ser un TINTE de acento que se
   desvanece SOBRE `var(--glass-bg)` — si la superficie de M-340 se mueve, la KPI la sigue sola.
   Los dos pares juntos (texto/tarjeta ≥ suelo, tarjeta/lienzo ≥ suelo) los vigila
   `AKpiNumberAndItsCardKeepBothContrastPairsTests`: son suelo y techo del MISMO fondo. */
.app-kpi-card {
    position: relative;
    background:
        linear-gradient(
            135deg,
            rgba(59, 130, 246, 0.12) 0%,
            rgba(59, 130, 246, 0.00) 100%
        ),
        var(--glass-bg) !important;
    border: 1px solid rgba(59, 130, 246, 0.18) !important;
    box-shadow: var(--app-glow-blue), var(--app-shadow-card);
    transition:
        box-shadow var(--anim-normal) var(--anim-ease),
        transform var(--anim-normal) var(--anim-ease),
        border-color var(--anim-normal) ease;
}

/* Tarjetas navegables: acento azul claro + cursor de enlace, distinguible YA en reposo. */
.app-kpi-card--link {
    cursor: pointer;
    border-color: rgba(59, 130, 246, 0.30) !important;
}

/* Tarjetas SOLO informativas (sin destino): tono neutro y sin glow azul, para que recedan
   y el contraste con las navegables se lea de un vistazo sin necesidad de hover.
   M-572: mismo esquema que la navegable — tinte que se desvanece SOBRE `var(--glass-bg)`, nunca un
   fondo que rehaga la superficie (el anterior terminaba en rgba(10,22,50,0.55): bajo el lienzo). */
.app-kpi-card:not(.app-kpi-card--link) {
    background:
        linear-gradient(
            135deg,
            rgba(148, 163, 184, 0.06) 0%,
            rgba(148, 163, 184, 0.00) 100%
        ),
        var(--glass-bg) !important;
    border-color: rgba(148, 163, 184, 0.12) !important;
    box-shadow: var(--app-shadow-card);
}

/* Afordancia "ir a": solo las tarjetas navegables se elevan al hover e indican destino. */
.app-kpi-card--link:hover {
    box-shadow: 0 8px 40px rgba(59, 130, 246, 0.22), 0 2px 8px rgba(0, 0, 0, 0.30);
    transform: translateY(-3px);
    border-color: rgba(59, 130, 246, 0.45) !important;
}

/* Flecha "ir a": claramente visible en reposo (pastilla con fondo) y plena al hover. */
.app-kpi-card__go {
    position: absolute;
    bottom: 10px;
    right: 12px;
    opacity: 0.75;
    color: var(--mud-palette-primary);
    background: rgba(59, 130, 246, 0.12);
    border-radius: 999px;
    padding: 2px;
    transition: opacity var(--anim-normal) ease, transform var(--anim-normal) ease,
        background-color var(--anim-normal) ease;
}

.app-kpi-card--link:hover .app-kpi-card__go {
    opacity: 1;
    background: rgba(59, 130, 246, 0.22);
    transform: translate(2px, -2px);
}

/* ── 💼 LA CIFRA DE UNA TARJETA ES UN DATO DE NEGOCIO, NO UN TITULAR DE PORTADA ───────────────────
   Reportado por él en vivo (s74) sobre `/` de la app del corredor: *«el tamaño es desproporcionadamente
   grande en todas las cards de este tipo … no ese estilo todo inclinado cursivo, algo más profesional
   empresarial»*, y con el defecto medible delante: **«63 · 26.957 EUR» se partía en TRES renglones**.

   🔴 De dónde venía. La receta era «Syne display para MÁXIMO IMPACTO» a peso 800 más el degradado de
   marca recortado sobre el texto. Syne es una tipografía DISPLAY —caja alta, ejes geométricos, remates
   inclinados—: en un titular de una palabra funciona, y en un importe de quince caracteres lo que hace es
   inflarlo hasta que no cabe. Y una cifra que no cabe **se parte**, que es justo lo que M-590 y M-574
   persiguen en las tablas: *una cifra que se parte deja de ser la cifra*.

   ✅ Qué se pone, y por qué cada pieza:
   · `Inter` — la fuente de la INTERFAZ. Un número lo lee alguien que compara, no alguien que admira.
   · peso 600 y `-0.01em` — presencia sin gritar; el rótulo de encima ya va en 500.
   · `tabular-nums` — las cifras de dos tarjetas contiguas alinean sus dígitos, que es lo que permite
     compararlas de un vistazo. Es la misma decisión que ya toman las tablas de importes de la casa.
   · **sin degradado** — el recorte sobre texto obligaba a `padding-bottom` para no comerse los rabos y
     dejaba la cifra en `text-fill-color: transparent`: mucha maquinaria para decorar un dato.
   · `1.375rem` en vez de `1.5rem` — con Inter a este cuerpo, «63 · 26.957 EUR» entra en UN renglón en la
     tarjeta más estrecha. ⛔ No se pone `nowrap`: si algún día una cifra no cabe, que baje de línea es
     feo, pero recortarla **pierde el dato**, y eso no se hace nunca.
   🧹 Alcance: las **26** instancias de `KpiCard` (Inicio, Analítica de cartera y la vista 360 del
   cliente), que es lo que él vio compartiendo clase. */
.app-kpi-card .mud-typography-h3,
.app-kpi-card .mud-typography-h4 {
    font-family: 'Inter', system-ui, sans-serif;
    font-weight: 600;
    font-size: 1.375rem;
    line-height: 1.3;
    letter-spacing: -0.01em;
    font-variant-numeric: tabular-nums;
    color: var(--ins-kpi-number);
}

/* ── 11. Empty State ──────────────────────────────────────── */
.app-empty-state {
    padding: 64px 24px;
    text-align: center;
    color: var(--mud-palette-text-secondary);
}

/* `>` y no descendiente: el glifo de 64 px es el del VACÍO, el que EmptyState pinta como hijo directo.
   Sin el `>` la regla alcanzaba también al icono del BOTÓN de la salida —M-270 obliga a que todo vacío
   ofrezca una— y lo inflaba a 64 px dentro del botón. Medido en vivo (16-ago) sobre /tasks, y no era de
   esa pantalla: son las ~10 salidas con `StartIcon` de los dos hosts, que llevaban el mismo botón
   deforme. */
.app-empty-state > .mud-icon-root {
    width: 64px;
    height: 64px;
    margin-bottom: 16px;
    opacity: 0.30;
    filter: drop-shadow(0 0 12px rgba(59, 130, 246, 0.30));
}

/* ── 12. Page Entry Animations ────────────────────────────── */
.mud-main-content > .mud-container {
    animation: pageEnter var(--anim-slow) var(--anim-ease) both;
}

/* IMPORTANTE: la keyframe final NO declara `transform`. Con `animation-fill-mode: both`, si `to`
   fijara `translateY(0)` el contenedor conservaría un transform (matriz identidad) PARA SIEMPRE, y un
   transform en un ancestro convierte a `.mud-container` en bloque contenedor de los popovers
   `position:fixed` (MudSelect, tooltips, date pickers) → MudBlazor los reposiciona en bucle y las
   etiquetas flotantes "tiemblan" (mismo origen que el bug de InsDialog). Al omitir `transform` en `to`,
   tras la animación el transform vuelve a `none` y los popovers se posicionan bien. La entrada se ve igual. */
@keyframes pageEnter {
    from { opacity: 0; transform: translateY(16px); }
    to   { opacity: 1; }
}

/* Staggered grid items */
.mud-grid > .mud-item {
    animation: itemEnter var(--anim-slow) var(--anim-ease) both;
}

.mud-grid > .mud-item:nth-child(1) { animation-delay: 0ms; }
.mud-grid > .mud-item:nth-child(2) { animation-delay: 60ms; }
.mud-grid > .mud-item:nth-child(3) { animation-delay: 120ms; }
.mud-grid > .mud-item:nth-child(4) { animation-delay: 180ms; }
.mud-grid > .mud-item:nth-child(5) { animation-delay: 240ms; }
.mud-grid > .mud-item:nth-child(6) { animation-delay: 300ms; }
.mud-grid > .mud-item:nth-child(7) { animation-delay: 360ms; }
.mud-grid > .mud-item:nth-child(8) { animation-delay: 420ms; }

/* Igual que pageEnter: `to` sin `transform` para no dejar un transform residual en cada `.mud-item`
   (que también sería bloque contenedor de popovers dentro de la grid). */
@keyframes itemEnter {
    from { opacity: 0; transform: translateY(12px) scale(0.99); }
    to   { opacity: 1; }
}

/* Chips */
.mud-chip {
    border-radius: 999px !important;
    font-family: 'Inter', system-ui, sans-serif;
    font-size: 0.72rem;
    font-weight: 500;
}

/* Progress bars */
.mud-progress-linear .mud-progress-linear-bar {
    background: linear-gradient(90deg, #3b82f6, #7c3aed) !important;
    border-radius: 999px;
}

/* Snackbar */
.mud-snackbar {
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
    border: 1px solid var(--glass-border-hover);
    border-radius: var(--app-radius-input);
}

/* ── 13. Light Mode Overrides ─────────────────────────────── */
/* MudBlazor v7 does NOT add a class to <body>; we inject ins-light/ins-dark
   via JS (insCoreTheme.applyTheme) so these selectors fire reliably. */

body {
    transition: background-color 300ms ease;
}

body.ins-light {
    background-color: #f0f4ff;

    /* Modo claro: las DOS rampas del texto con degradado convergen en la misma (oscuro→azul).
       Antes esto eran dos bloques gemelos repitiendo la receta entera (marca del AppBar y cifras
       KPI); ahora solo se reescribe el token y la mecánica sigue viviendo en §4bis. */
    --ins-gradient-text:        linear-gradient(135deg, #0f172a 0%, #1e40af 100%);
    --ins-gradient-text-accent: linear-gradient(135deg, #0f172a 0%, #1e40af 100%);
    --ins-kpi-number: #0f172a;
}

body.ins-light .app-bg-orbs {
    opacity: 0.22;
}

body.ins-light .mud-paper {
    background: rgba(255, 255, 255, 0.92) !important;
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border-color: rgba(148, 163, 184, 0.20);
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.08), 0 1px 2px rgba(15, 23, 42, 0.04);
}

body.ins-light .mud-appbar {
    background: rgba(255, 255, 255, 0.90) !important;
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border-bottom-color: rgba(148, 163, 184, 0.20) !important;
}

body.ins-light .mud-appbar::after {
    opacity: 0.5;
}

body.ins-light .mud-drawer {
    background: rgba(248, 250, 255, 0.96) !important;
    border-right-color: rgba(148, 163, 184, 0.20) !important;
}

body.ins-light .mud-dialog {
    background: rgba(255, 255, 255, 0.98) !important;
    border-color: rgba(148, 163, 184, 0.25);
    box-shadow: 0 24px 80px rgba(15, 23, 42, 0.15);
}

body.ins-light .mud-popover-paper {
    background: rgba(255, 255, 255, 0.98) !important;
    border-color: rgba(148, 163, 184, 0.20);
}

body.ins-light .mud-input-control .mud-input-slot {
    background: rgba(248, 250, 252, 0.80);
}

/* 🌕 s73 · EN CLARO LA TARJETA KPI ERA UN HUECO, NO UNA SUPERFICIE. Medido renderizado el 17-ago-2026
   sobre la app en pie (sonda de píxeles, Home 1440×900, velo de reconexión comprobado): **7 de las 8
   tarjetas componían POR DEBAJO de su propia página**, peor par **1,003:1**. La causa es el TINTE: sobre
   un lienzo claro un tinte de acento solo puede RESTAR luminancia, y el lienzo `#f0f4ff` ya es azulado,
   así que tarjeta y página acababan en el mismo tono y en la misma luminancia. Es la clase de M-340
   viva en el tema claro.
   🏆 El arreglo es el estándar del sector, y es el que esta hoja YA usa para `.mud-paper` en claro: en
   tema claro la elevación NO la da la superficie —el techo físico de una tarjeta blanca sobre este
   lienzo es 1,10:1, CALCULADO, no medido: componer blanco puro sobre `#f0f4ff` no da más—, la da la
   SOMBRA. Así que el acento se muda del FONDO al CANTO (donde en claro sí se ve y no le quita luz a la
   tarjeta) y la superficie vuelve a ser la blanca del sistema.
   La sombra deja de ser un halo azul al 0,08 —invisible sobre un lienzo azulado— y pasa a ser la
   sombra NEUTRA de dos capas del resto de tarjetas claras.
   Resultado calculado: 1,096:1 sobre el lienzo pelado y 1,138:1 bajo un orbe, siempre POR ENCIMA. */
body.ins-light .app-kpi-card {
    background: rgba(255, 255, 255, 0.96) !important;
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.10), 0 4px 12px rgba(15, 23, 42, 0.06);
}

/* Modo claro: navegables con acento azul, informativas con canto pizarra. La distinción se lee en el
   CANTO y en la flecha «ir a», no en el fondo — que es de donde hubo que sacarla.
   ⚠️ El canto NO se declara en la regla base de arriba: toda tarjeta es una de estas dos, así que un
   `border-color` ahí no lo ve nadie. Lo tuvo un rato y era una declaración MUERTA con el mismo valor
   que ésta — el andamiaje también es lo que se queda repetido sin pintar nada. */
body.ins-light .app-kpi-card--link {
    border-color: rgba(59, 130, 246, 0.35) !important;
}

body.ins-light .app-kpi-card:not(.app-kpi-card--link) {
    background: rgba(255, 255, 255, 0.96) !important;
    border-color: rgba(100, 116, 139, 0.22) !important;
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.08), 0 4px 12px rgba(15, 23, 42, 0.05);
}

body.ins-light .mud-table-root .mud-table-head .mud-table-cell {
    background: rgba(248, 250, 255, 0.80) !important;
}

body.ins-light .mud-nav-link.active {
    color: #1d4ed8 !important;
    box-shadow: inset 3px 0 0 #2563eb;
}

body.ins-light .mud-nav-link.active .mud-icon-root {
    color: #2563eb !important;
}

/* ── 14. Responsive Media Queries ─────────────────────────── */

/* Mobile — < 600px */
@media (max-width: 599px) {
    .mud-main-content > .mud-container {
        padding: 12px !important;
    }

    /* Smaller orbs on mobile to save GPU */
    .app-orb {
        filter: blur(60px);
        opacity: 0.75;
    }
    .app-orb--blue   { width: 280px; height: 280px; }
    .app-orb--violet { width: 230px; height: 230px; }
    .app-orb--mint   { width: 140px; height: 140px; }

    /* Bottom sheet dialogs on mobile */
    .mud-dialog-container .mud-dialog {
        margin: 0 !important;
        border-radius: 20px 20px 0 0 !important;
        position: fixed !important;
        bottom: 0 !important;
        left: 0 !important;
        right: 0 !important;
        max-width: 100% !important;
        max-height: 92vh;
        overflow-y: auto;
    }
}

/* Tablet — 600px–959px */
@media (min-width: 600px) and (max-width: 959px) {
    .mud-main-content > .mud-container {
        padding: 16px !important;
    }

    .app-orb--blue   { width: 480px; height: 480px; }
    .app-orb--violet { width: 370px; height: 370px; }
}

/* Accessibility — reduced motion */
@media (prefers-reduced-motion: reduce) {
    .app-orb { animation: none; }

    .mud-main-content > .mud-container,
    .mud-grid > .mud-item {
        animation: none;
    }

    .mud-card,
    .mud-paper,
    .mud-button-root,
    .mud-nav-link,
    .app-kpi-card {
        transition: none;
    }
}

/* Malla de seguridad anti-desborde para tooltips de la LIBRERÍA MudBlazor: acota el ancho y permite
   wrap para que ningún popover suyo se pinte a ancho completo. La aplicación ya NO tiene ni un solo
   MudTooltip propio (canal único = InsTooltip, guardado por TooltipChannelTests); esto queda solo por
   lo que MudBlazor pueda emitir por dentro. */
.mud-tooltip {
    max-width: min(360px, 90vw);
    white-space: normal;
    overflow-wrap: anywhere;
}

/* ── 15. Reconexión del circuito (Blazor Server) ───────────────
   Overlay visible cuando se cae la conexión SignalR. Sin esto la app quedaba congelada en
   silencio (ver App.razor + insCoreReconnect en theme.js). Blazor alterna las clases
   components-reconnect-show/-failed/-rejected sobre #components-reconnect-modal. */
#components-reconnect-modal {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 20000; /* por encima de diálogos/popovers MudBlazor */
    align-items: center;
    justify-content: center;
    background: rgba(3, 8, 20, 0.72);
    backdrop-filter: var(--glass-blur);
    -webkit-backdrop-filter: var(--glass-blur);
}

#components-reconnect-modal.components-reconnect-show,
#components-reconnect-modal.components-reconnect-failed,
#components-reconnect-modal.components-reconnect-rejected {
    display: flex;
}

.ins-reconnect__box {
    background: var(--glass-bg-heavy);
    border: 1px solid var(--glass-border-hover);
    border-radius: var(--app-radius-card);
    box-shadow: 0 24px 80px rgba(0, 0, 0, 0.6);
    padding: 28px 36px;
    text-align: center;
    color: #e2e8f0;
    font-family: 'Inter', system-ui, sans-serif;
    max-width: 90vw;
}

.ins-reconnect__spinner {
    width: 36px;
    height: 36px;
    margin: 0 auto 16px;
    border: 3px solid rgba(148, 163, 184, 0.25);
    border-top-color: #3b82f6;
    border-radius: 50%;
    animation: ins-reconnect-spin 0.8s linear infinite;
}

@keyframes ins-reconnect-spin { to { transform: rotate(360deg); } }

.ins-reconnect__msg { margin: 0; font-size: 0.95rem; }

/* El bloque de fallo solo aparece cuando se agotan los reintentos o el circuito es rechazado. */
.ins-reconnect__failed { display: none; }
.components-reconnect-failed .ins-reconnect__failed,
.components-reconnect-rejected .ins-reconnect__failed { display: block; margin-top: 12px; }
/* En fallo/rechazo ocultamos SOLO el mensaje "reconectando…" (lo sustituye el bloque de
   recuperación), pero el spinner SIGUE girando: estamos auto-recargando, no muertos. */
.components-reconnect-failed .ins-reconnect__msg,
.components-reconnect-rejected .ins-reconnect__msg { display: none; }

.ins-reconnect__failed button {
    margin-top: 10px;
    padding: 8px 20px;
    border: none;
    border-radius: var(--app-radius-button);
    background: #3b82f6;
    color: #fff;
    font: inherit;
    font-weight: 600;
    cursor: pointer;
}
.ins-reconnect__failed button:hover { background: #2563eb; }

body.ins-light #components-reconnect-modal { background: rgba(15, 23, 42, 0.45); }
body.ins-light .ins-reconnect__box { background: rgba(255, 255, 255, 0.98); color: #0f172a; }

/* ── 16. Antídoto overlay de popover (MudBlazor 8.4) ───────────
   El popover de un MudSelect/MudDatePicker abierto monta un overlay a pantalla completa con
   z-index 1601 que tapa los botones del diálogo (backdrop del diálogo va a 1401). El primer clic
   en Cancelar/Aceptar lo "come" ese overlay → "el botón no hace nada / el modal no se cierra"
   (verificado en vivo: Playwright reporta "mud-overlay intercepts pointer events").

   Lo hacemos transparente a punteros: así el clic llega al botón al PRIMER intento. El cierre-al-
   clic-fuera del popover (que ese overlay daba) se restituye por JS (insCoreOverlay en theme.js),
   que dispara el cierre nativo SIN consumir el clic. Solo afecta al overlay del popover-provider,
   nunca al backdrop del diálogo. */
.mud-popover-provider > .mud-overlay {
    pointer-events: none !important;
}

/* ── 17. Pestañas: ninguna flecha que no pueda desplazar nada ───────────────────
   Reportado por el usuario en `/claims/{id}`: el contenedor de pestañas pinta «‹ ›» con solo DOS
   pestañas, que caben de sobra. «Si no queda más que avanzar, la flechita de la derecha pierde
   sentido»: un control visible que promete una acción imposible.

   MEDIDO (no supuesto): hay **11 `<MudTabs>`** en el repo y **CERO** configuran
   `ShowScrollButtons`/`AlwaysShowScrollButtons` ⇒ es el comportamiento por defecto de la librería,
   no una decisión de ninguna pantalla. Por eso NO se arregla pantalla a pantalla: 9 de esas 11
   pantallas ni siquiera pertenecen a este lote.

   Cómo lo monta MudBlazor 8.4 (verificado sobre el paquete en la caché NuGet, no de memoria):
     · Marcado — `.mud-tabs-tabbar-inner` (flex) contiene, en este orden:
       `div.mud-tabs-scroll-button` > `button.mud-icon-button` (anterior), `.mud-tabs-tabbar-content`
       y otro `div.mud-tabs-scroll-button` (siguiente).
     · Lógica — `MudTabs` (campos `_showScrollButtons`, `_prevButtonDisabled`, `_nextButtonDisabled`;
       métodos `SetScrollButtonVisibility` y `SetScrollabilityStates`) decide por MEDIDA: compara el
       ancho de todas las pestañas contra el del contenedor. Cuando hay sitio de sobra marca AMBOS
       botones como deshabilitados; cuando no lo hay, deshabilita solo el del extremo alcanzado.
     · Medida — `MudResizeObserver` usa `getBoundingClientRect()` con retardo de 200 ms
       (`staticwebassets/MudBlazor.min.js`), así que la decisión se toma sobre una foto que puede
       llegar tarde o tomarse con el elemento aún sin ancho definitivo.
     · CSS de la librería — `.mud-tabs-tabbar-content { width:100%; flex:1 1 auto }`.

   Lo que esa combinación produce, y que esta regla rompe: los propios botones ROBAN ~96 px al
   contenedor que se mide. Una vez visibles, la medida siguiente se hace sobre un contenedor ya
   encogido, que vuelve a "confirmar" que no hay sitio → el estado se ENGANCHA y no vuelve solo.
   Al no ocupar sitio los botones deshabilitados, el contenedor recupera su ancho real y la
   siguiente medida deshace el enganche: es auto-curativo, no cosmético.

   Regla: un botón de desplazamiento DESHABILITADO no se enseña. Se oculta el `<button>`, no su
   envoltorio (que sin contenido mide 0 y no necesita `:has()`, con lo que no dependemos del soporte
   de ese selector). `display:none` además lo saca del árbol de accesibilidad: ni foco, ni lectura.
   Cuando SÍ hay desbordamiento real, el botón del extremo contrario sigue visible y operativo. */
.mud-tabs-scroll-button .mud-icon-button:disabled {
    display: none;
}
