/* ============================================================
   Expectra — Sistema de Diseño (Despacho Jurídico · Claro)
   Paleta neutra: gris claro de fondo, accent #1F2937 (gray-800) para
   invitacion al clic, negro puro en botones primarios.
   Tipografía: Cove (todo: texto, cifras y tablas) — fontzz, OFL 1.1.
   Master de diseño: cerebro 23_Expectra_Design_Master
   ============================================================ */

/* Tipografía — Plus Jakarta Sans (principal) + Urbanist (cifras) + Lufga (marca).
   Plus Jakarta Sans y Urbanist: Google Fonts, SIL OFL 1.1, self-host (latin +
   latin-ext), variables `font-weight: 200 800` → un archivo cubre los pesos.
   Lufga: familia COMERCIAL (Adam Ladd / Fontspring). NO se empaqueta: su demo
   es solo para uso personal, así que en un producto comercial solo entra con
   licencia comprada. Mientras no exista el .woff2, el wordmark cae a Plus
   Jakarta Sans (ver la nota del @font-face, más abajo).
   Sin monoespaciada: el sistema no usa monospace en ninguna parte.
   font-display: swap ⇒ nunca bloquea el primer pintado del panel. */
@font-face {
    font-family: "Plus Jakarta Sans";
    src: url("../fonts/plus-jakarta-sans-latin.52d04440a9fa.woff2") format("woff2");
    font-weight: 200 800;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: "Plus Jakarta Sans";
    src: url("../fonts/plus-jakarta-sans-latin-ext.5ffe46eeb00d.woff2") format("woff2");
    font-weight: 200 800;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
    font-family: "Urbanist";
    src: url("../fonts/urbanist-latin.40fbb0c52f0d.woff2") format("woff2");
    font-weight: 200 800;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
    font-family: "Urbanist";
    src: url("../fonts/urbanist-latin-ext.a32c2d34c54a.woff2") format("woff2");
    font-weight: 200 800;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* Licencia Lufga: cuando exista el archivo comprado se agrega aquí su
   @font-face (familia "Lufga", `src` al .woff2 de fonts/, `font-weight: 200 800`).
   NO se deja el bloque comentado: `collectstatic` en producción reescribe las
   referencias con una REGEX que no entiende de comentarios, ve el `url()` del
   .woff2 inexistente y tumba el deploy con `MissingFileError`. */

:root {
    /* Tipografía (ver @font-face arriba).
       --font-sans:    Plus Jakarta Sans → todo el texto (principal).
       --font-alt:     Urbanist → cifras y datos (montos, IDs, ejes, claves).
       --font-display: Lufga → SOLO los wordmarks (EXPECTRA / DATA ENGINE);
                       cae a Plus Jakarta Sans mientras no haya licencia.
       Sin monoespaciada: monospace está prohibido en el sistema. Para alinear
       cifras se usa font-variant-numeric: tabular-nums. */
    --font-sans:    "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
    --font-alt:     "Urbanist", "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
    --font-display: "Lufga", "Plus Jakarta Sans", -apple-system, BlinkMacSystemFont, system-ui, sans-serif;

    /* Gráficas: --accent es SIEMPRE negro mate (fondo de CTA), así que como
       trazo desaparece en dark. Estos tokens sí invierten con el tema. */
    --chart-line:   #0F1115;
    --chart-track:  #EDEFF3;   /* carril de barras: más claro que --border */
    --chart-fill:   rgba(15, 23, 42, 0.07);
    --bg:          #f4f6fa;
    --surface:     #ffffff;
    --surface-2:   #eef2f7;
    --surface-3:   #e2e8f0;
    --border:      rgba(15, 23, 42, 0.08);
    --border-strong: rgba(15, 23, 42, 0.14);
    /* Azul glaciar — acento del sistema (botones, chips, foco, avisos).
       Elegido por contraste AA: primario sobre blanco 5.4:1, blanco sobre
       primario 5.4:1; en dark el primario sube a -400 con tinta oscura 7.5:1. */
    --ice-50:      #F1F7FB;
    --ice-100:     #E1EEF6;
    --ice-200:     #C4DEEE;
    --ice-300:     #A2CBE1;
    --ice-400:     #7FB4D0;
    --ice-500:     #5E9BBE;
    --ice-600:     #34708F;
    --ice-700:     #2F6280;
    --ice-800:     #244C64;
    --ice-900:     #1A3748;
    --accent:      #0F1115;          /* negro mate para CTAs/botones (mismo en claro y dark) */
    --accent-alt:  #1F2937;
    --accent-vivid:#000000;
    --accent-soft: rgba(15, 23, 42, 0.06);
    --accent-line: rgba(15, 23, 42, 0.22);
    --button-text: #FFFFFF;
    --text:        #0f172a;
    --text-dim:    #475569;
    --text-dim-2:  #94a3b8;
    --text-accent: #1F2937;          /* alias semantico: --accent es bg, este es text-color */
    --success:     #16a34a;
    --warning:     #d97706;
    --danger:      #dc2626;
    --danger-strong: #991B1B;       /* rojo profundo — TEXTO de peligro en claro */
    --shadow:      0 1px 2px rgba(15, 23, 42, 0.04);
    --shadow-md:   0 4px 14px rgba(15, 23, 42, 0.05);

    /* Kravio tokens (sidebar claro · off-white neutro)
       — se usan en ``.edx-sidebar*``. La paleta principal del panel
       sigue siendo la turquesa del EDX (--accent, --surface, etc.).
       v9: hover y activo son fondos distinguibles (hover más suave que
       activo), icono cambia a color principal en hover/activo y
       aparece una barra lateral accent como indicador de ruta. */
    --sidebar-bg:           #FFFFFF;
    --sidebar-bg-hover:     #F7F7F7;   /* gris muy suave — hover */
    --sidebar-bg-active:    #F0F0EE;   /* gris cálido medio — activo (Kravio bg tarjeta secundaria) */
    --sidebar-border:       #E5E5E5;
    --sidebar-border-hover: #D9D9D9;
    --sidebar-text:         #0E1118;
    --sidebar-text-muted:   #9C9C9C;
    --sidebar-muted:        #6A6B6C;
    --sidebar-accent:       #1F2937;
    --sidebar-accent-soft:  rgba(31, 41, 55, 0.10);
    --sidebar-danger:       #dc2626;
    --sidebar-danger-soft:  rgba(220, 38, 38, 0.10);
    --sidebar-radius:       10px;
    --sidebar-easing:       cubic-bezier(0.2, 0.8, 0.2, 1);
    --sidebar-duration:     220ms;
    --shell-panel-bg:       #F4F6FA;   /* lienzo único: la sidebar se funde */
    --shell-panel-border:   transparent;

    /* Gradient sutil del sidebar (modo claro: blanco arriba, casi imperceptible abajo) */
    --sidebar-bg-top:       #FFFFFF;
    --sidebar-bg-bottom:    #FCFCFD;
}

/* ───────────── DARK MODE ─────────────
   Activado por .dark-mode en <html> (anti-FOUC) o <body> (toggle script).
   Solo override de variables — todas las reglas que usan var(--xxx)
   se actualizan automáticamente. El login también la usa desde el Bloque 63
   (comparte interruptor y clave de localStorage con el panel); sus ajustes
   propios —fondo invertido, botón blanco— viven en el <style> de login.html. */
html.dark-mode,
body.dark-mode {
    /* Tokens globales dark */
    --bg:          #0F1115;          /* fondo principal (Apple/Linear style) */
    --surface:     #1A1D23;          /* cards, panels */
    --surface-2:   #232730;          /* cards hover, sub-cards */
    --surface-3:   #2D3138;          /* cards active */
    --border:      rgba(255, 255, 255, 0.08);
    --border-strong: rgba(255, 255, 255, 0.14);
    /* IMPORTANTE: --accent es el color de FONDO de los CTAs/botones primarios.
       En AMBOS modos (claro y dark) es negro mate full black.
       El texto encima es siempre blanco (var(--button-text = #FFFFFF)).
       Esto da consistencia visual: los CTAs son siempre el mismo botón
       negro en cualquier esquema de color. */
    --accent:      #0F1115;
    --accent-alt:  #050810;
    --accent-vivid:#000000;
    --accent-soft: rgba(255, 255, 255, 0.06);
    --accent-line: rgba(255, 255, 255, 0.22);
    /* Gráficas en dark: el trazo tiene que invertirse (--accent sigue negro). */
    --chart-line:   #E5E7EB;
    --chart-track:  #23272E;   /* carril de barras en dark */
    --chart-fill:   rgba(255, 255, 255, 0.08);
    --button-text: #FFFFFF;          /* texto sobre botones primarios (negro mate) */
    --text:        #E5E7EB;          /* texto principal */
    --text-dim:    #9CA3AF;
    --text-dim-2:  #6B7280;
    --text-accent: #E5E7EB;          /* alias semántico para usar como color de acento en texto */
    --success:     #4ade80;
    --warning:     #fbbf24;
    --danger:      #ef4444;          /* rojo más brillante para contraste sobre dark */
    --danger-strong: #EF4444;       /* mismo rojo, legible sobre dark */
    --shadow:      0 1px 2px rgba(0, 0, 0, 0.3);
    --shadow-md:   0 4px 14px rgba(0, 0, 0, 0.4);

    /* Tokens sidebar dark */
    --sidebar-bg:           #1A1D23;
    --sidebar-bg-hover:     #232730;
    --sidebar-bg-active:    #2D3138;
    --sidebar-border:       rgba(255, 255, 255, 0.06);
    --sidebar-border-hover: rgba(255, 255, 255, 0.12);
    --sidebar-text:         #E5E7EB;
    --sidebar-text-muted:   #6B7280;
    --sidebar-muted:        #9CA3AF;
    --sidebar-accent:       #E5E7EB;
    --sidebar-accent-soft:  rgba(229, 231, 235, 0.10);
    --sidebar-danger:       #ef4444;
    --sidebar-danger-soft:  rgba(239, 68, 68, 0.10);
    --shell-panel-bg:       #0F1115;  /* mismo color que body dark, sin distinción */
    --shell-panel-border:   rgba(255, 255, 255, 0.06);

    /* Gradient sidebar dark: arriba un poco mas claro que abajo */
    --sidebar-bg-top:       #232730;
    --sidebar-bg-bottom:    #1A1D23;

    color-scheme: dark;  /* scrollbars y form controls nativos en dark */
}

/* ───────────── DARK MODE OVERRIDES (configuracion.html) ─────────────
   El panel de Configuracion usa clases Tailwind con colores hardcoded
   (bg-white, bg-[#F1F1F1], etc.) que ignoran las variables CSS.
   Estos selectores especificos los sobrescriben en dark mode sin
   modificar el HTML, manteniendo el template intacto. */
html.dark-mode .bg-white,
body.dark-mode .bg-white {
    background-color: var(--surface) !important;
    color: var(--text) !important;
}
html.dark-mode .bg-\[\#F1F1F1\],
body.dark-mode .bg-\[\#F1F1F1\] {
    background-color: var(--surface-2) !important;
    color: var(--text) !important;
}
html.dark-mode .bg-\[\#F7F7F7\],
body.dark-mode .bg-\[\#F7F7F7\] {
    background-color: var(--surface-2) !important;
    color: var(--text) !important;
}
html.dark-mode .bg-\[\#FFF8F0\],
body.dark-mode .bg-\[\#FFF8F0\] {
    background-color: rgba(176, 109, 71, 0.10) !important;  /* warm semántico sigue */
    color: var(--text) !important;
}

/* Bordes hardcoded: aclarar en dark para que se vean sobre dark */
html.dark-mode .border-\[\#E5E5E5\],
body.dark-mode .border-\[\#E5E5E5\] {
    border-color: var(--border) !important;
}
html.dark-mode .border-\[\#F5E4D8\],
body.dark-mode .border-\[\#F5E4D8\] {
    border-color: rgba(176, 109, 71, 0.30) !important;  /* warm semántico */
}

/* Texto hardcoded: usar variables para que tengan contraste correcto */
html.dark-mode .text-\[\#11141A\],
body.dark-mode .text-\[\#11141A\] {
    color: var(--text) !important;
}
html.dark-mode .text-\[\#9C9C9C\],
body.dark-mode .text-\[\#9C9C9C\] {
    color: var(--text-dim) !important;
}
html.dark-mode .placeholder\:text-\[\#D9D9D9\]::placeholder,
body.dark-mode .placeholder\:text-\[\#D9D9D9\]::placeholder {
    color: var(--text-dim-2) !important;
}

/* ───────────── DARK MODE OVERRIDES (configuracion.html <style> local) ─────────────
   El archivo configuracion.html tiene su propio <style> block con clases
   como .krav-tabla, .action-popover, .chip, etc. con colores hex literales.
   Estos selectores especificos sobrescriben cada uno en dark mode. */
html.dark-mode .krav-tabla,
body.dark-mode .krav-tabla {
    background: var(--surface) !important;
}
html.dark-mode .krav-tabla thead th,
body.dark-mode .krav-tabla thead th {
    background: var(--surface-2) !important;
    color: var(--text-dim) !important;
    border-bottom-color: var(--border) !important;
}
html.dark-mode .krav-tabla tbody tr,
body.dark-mode .krav-tabla tbody tr {
    border-bottom-color: var(--border) !important;
}
html.dark-mode .krav-tabla tbody tr:hover,
body.dark-mode .krav-tabla tbody tr:hover {
    background: var(--surface-2) !important;
}
html.dark-mode .krav-tabla tbody td,
body.dark-mode .krav-tabla tbody td {
    color: var(--text) !important;
}
html.dark-mode .krav-tabla td.muted,
body.dark-mode .krav-tabla td.muted {
    color: var(--text-dim) !important;
}
html.dark-mode .krav-tabla .username,
body.dark-mode .krav-tabla .username {
    color: var(--text) !important;
}

/* Action popover — panel flotante. El disparador (<summary>) y los botones
   internos usan el sistema .btn (themeable), así que aquí solo va el panel. */
html.dark-mode .action-popover .popover-body,
body.dark-mode .action-popover .popover-body {
    background: var(--surface) !important;
    color: var(--text) !important;
    border-color: var(--border) !important;
}

/* Chips semánticos (tu, warn, success, danger) — mantener color semantico
   pero subir luminosidad del texto para contraste sobre dark */
html.dark-mode .chip.success,
body.dark-mode .chip.success {
    color: var(--success) !important;
}
html.dark-mode .chip.warn,
body.dark-mode .chip.warn {
    color: var(--warning) !important;
}

/* Warm callouts (separador de reset, confirmacion peligrosa) — aclara texto */
html.dark-mode .warn-text,
body.dark-mode .warn-text {
    color: var(--warning) !important;
}

/* Color-scheme: light cuando NO hay dark-mode. dark cuando sí. */
html { color-scheme: light; }
html.dark-mode { color-scheme: dark; }

* { box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
    height: 100%;
    background: var(--bg);
    color: var(--text);
    font-family: var(--font-sans);
    font-size: 16px;
    font-weight: 500;
    letter-spacing: -0.01em;
    line-height: 1.45;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow-x: hidden;
}

a { color: var(--text); text-decoration: none; }
a:hover { color: var(--accent-alt); }

img { max-width: 100%; display: block; }

::selection { background: var(--accent); color: var(--bg); }

/* Selección de texto legible en DARK. `--accent` es negro en ambos modos y en
   dark `--bg` también es #0F1115 → texto negro sobre fondo negro = invisible
   al copiar. Override: fondo claro + texto oscuro. */
html.dark-mode ::selection,
body.dark-mode ::selection { background: #E5E7EB; color: #0F1115; }

/* ───────────── Fondo claro plano (sin nebulosas) ───────────── */
.coval-app {
    background: var(--bg) !important;
    background-attachment: fixed !important;
    min-height: 100vh;
}

/* ───────────── Layout shell ───────────── */
.coval-shell {
    max-width: 1320px;
    margin: 0 auto;
    padding: 0 24px;
}
.coval-main.block-container {
    max-width: none;
    padding: 32px 0 64px 0;
}

/* ───────────── SHELL KRAVIO: SIDEBAR + PANEL ───────────── */
/* Sidebar estático v10:
   · Ancho fijo 220px (15% menos que el 260px previo).
   · Sin toggle, sin collapsed state, sin mobile drawer.
   · Sin Alpine, sin hover-expand, sin resize de width/padding. */
.edx-shell {
    display: block;
    min-height: 100vh;
    padding-left: 220px;
}
.edx-main {
    max-width: none;
    padding: 32px 0 64px 0;
}
body.edx-kravio { background: var(--shell-panel-bg); }

.edx-sidebar {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    width: 220px;
    /* Sin rail duro: el fondo ES el lienzo y el peso visual lo lleva la
       pastilla blanca del ítem activo (referencia RefPC). */
    background: var(--bg);
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    z-index: 50;
    font-family: var(--font-sans);
    /* Esquinas derechas concavas (curvan hacia adentro): dejan ver el bg
       del panel principal por detrás en las zonas top-right y bottom-right.
       La concavidad real requiere SVG mask (inset/round solo hace convexo).
       El SVG inline usa viewBox 0 0 100 100 + preserveAspectRatio=none para
       que las coordenadas escalen con la altura del sidebar en cualquier
       viewport (no asume 600px fijos como path() en CSS).
       OJO: el SVG no tiene width/height, asi que NO tiene tamaño intrinseco.
       El shorthand `mask:` deja mask-size:auto + mask-repeat:repeat → cada
       motor lo resuelve a su manera (Chrome estira la imagen al box, WebKit/
       Safari la dimensiona a ~el ancho del elemento y la REPITE: hendiduras
       repetidas cada 220px por todo el borde derecho). Sizing obligatorio
       explicito: 100% 100% + no-repeat → una sola muesca top y bottom. */
    -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'><path d='M 0 0 L 85 0 Q 100 0 100 7 L 100 93 Q 100 100 85 100 L 0 100 Z' fill='white'/></svg>");
    -webkit-mask-size: 100% 100%;
    -webkit-mask-repeat: no-repeat;
    -webkit-mask-position: 0 0;
    mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='none'><path d='M 0 0 L 85 0 Q 100 0 100 7 L 100 93 Q 100 100 85 100 L 0 100 Z' fill='white'/></svg>");
    mask-size: 100% 100%;
    mask-repeat: no-repeat;
    mask-position: 0 0;
}

.edx-sidebar-head {
    /* 28 px a cada lado = la columna del rail. El brand row va CENTRADO en
       esa columna, así el conjunto (de la C de «coveyp» a la E) queda
       centrado en el sidebar. */
    padding: 14px 28px 10px;
    flex-shrink: 0;
}

.edx-sidebar-brand {
    display: flex;
    flex-direction: row;
    align-items: center;
    /* El conjunto —logo Coveyp + «By» + E— se centra en la columna del rail:
       lo que se ve, de la C a la E, queda a la misma distancia de los dos
       bordes. */
    justify-content: center;
    gap: 9px;
    /* 5 px a la izquierda por pedido del dueño: el lockup (C de «coveyp» → E)
       se veía un pelo corrido a la derecha dentro de la columna del rail.
       `transform` mueve el bloque completo sin tocar el padding ni el hover.
       Luego pidió 5 px MÁS: hoy son -10 px (logo Coveyp + «By» + E juntos). */
    transform: translateX(-10px);
    color: var(--sidebar-text);
    padding: 2px 0;
    border-radius: var(--sidebar-radius);
    text-decoration: none;
    transition: background var(--sidebar-duration) var(--sidebar-easing);
}
.edx-sidebar-brand:hover { background: var(--sidebar-bg-hover); }
.edx-sidebar-brand:active { background: var(--sidebar-bg-active); }

/* ── Brand row: la marca del CLIENTE manda ─────────────────────────────────
   El rail lleva el logo **Coveyp** —el arte entregado por el despacho— grande
   y **pegado al margen izquierdo**, y a su derecha el co-brand
   **«By» + la E de Expectra en chico**, centrado a la **altura media** del
   logo. Se retiraron el título «Expectra» y la E grande: el peso visual lo
   lleva Coveyp. */

/* El PNG trae aire transparente alrededor del dibujo (9/16/10/18 px sobre
   256 × 288). Aquí se RECORTA para que el box mida lo que realmente se ve y
   el margen del logo sea el del rail, no el del archivo: `--h` es el alto del
   PNG y todo lo demás son proporciones de su caja.
   OJO: todo va SCOPED a `.edx-sidebar-head`. El login usa las MISMAS clases
   `.brand-coveyp(--light/--dark)` con su propio tamaño, y sin este scope el
   `position:absolute` del rail desarmaba su lockup. */
.edx-sidebar-head .brand-coveyp-box {
    --h: 78px;
    position: relative;
    flex: none;
    overflow: hidden;
    /* La caja recorta al arte para que el margen que se VE sea el del rail, pero
       recortaba EXACTAMENTE el bbox de tinta: la «p» del wordmark y el filo de
       la sombra quedaban comidos (los píxeles de antialias caen fuera al escalar
       a 78 px). Se le dan 3 px de aire por lado y el `margin` negativo devuelve
       el hueco al layout, así el conjunto no se mueve ni cambia de ancho. */
    width: calc(var(--h) * 238 / 288 + 6px);   /* 238/288: ancho de la tinta */
    height: calc(var(--h) * 255 / 288 + 6px);  /* 255/288: alto de la tinta */
    margin: -3px;
}
.edx-sidebar-head .brand-coveyp {
    position: absolute;
    left: calc(var(--h) * -9 / 288 + 3px);    /* pad izquierdo del PNG + aire */
    top: calc(var(--h) * -16 / 288 + 3px);    /* pad superior del PNG + aire */
    width: calc(var(--h) * 256 / 288);
    height: var(--h);
    /* El preflight de Tailwind pone `img{max-width:100%}`, que aplastaba el
       PNG dentro de la caja recortada (7 % más angosto y la C 0.2 px adentro). */
    max-width: none;
    max-height: none;
    display: block;
}
.edx-sidebar-head .brand-coveyp--dark { display: none; }
html.dark-mode .edx-sidebar-head .brand-coveyp--light,
body.dark-mode .edx-sidebar-head .brand-coveyp--light { display: none; }
html.dark-mode .edx-sidebar-head .brand-coveyp--dark,
body.dark-mode .edx-sidebar-head .brand-coveyp--dark { display: block; }

/* Co-brand «By» + E: **pequeño de verdad** y centrado a la altura media del
   logo (lo centra el `align-items: center` del row). La E va recortada a su
   silueta con el mismo truco del lockup grande, pero **escalada por `--e-h`**:
   el tamaño es un solo número y los offsets son proporciones del original
   (silueta 54.1 × 59.2 sobre un SVG 80 × 80 dibujado a 81.7 px). */
.brand-by {
    flex: none;
    display: inline-flex;
    align-items: center;
    gap: 4.5px;
}
.brand-by-txt {
    font-size: 11.2px;
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0.02em;
    color: var(--text-dim);
}
.brand-by-e {
    --e-h: 15.7px;
    position: relative;
    flex: none;
    /* Mismo caso que el logo: el recorte caía justo sobre la silueta de la E y
       le comía el filo de los puntos de la derecha. 2 px de aire por lado, y el
       `margin` negativo deja el layout como estaba. */
    width: calc(var(--e-h) * 0.9139 + 4px);
    height: calc(var(--e-h) + 4px);
    margin: -2px;
    overflow: hidden;   /* recorta el margen interno asimétrico del SVG 80×80 */
}
.brand-by-e svg {
    position: absolute;
    left: calc(var(--e-h) * -0.2584 + 2px);
    top: calc(var(--e-h) * -0.2939 + 2px);
    width: calc(var(--e-h) * 1.3801);
    height: calc(var(--e-h) * 1.3801);
    filter: none;
}
/* Dark: la E invierte a blanco (el logo Coveyp trae su propio archivo). */
html.dark-mode .brand-by-e svg,
body.dark-mode .brand-by-e svg {
    filter: invert(1) hue-rotate(180deg) brightness(1.1);
}

.edx-sidebar-nav {
    flex: 1 1 auto;
    overflow-y: auto;
    /* 28px = borde izquierdo del brand row − padding interno de la pastilla
       (12). Así los iconos de la nav caen en la misma columna que el logo
       Coveyp del header. Si cambia el tamaño del logo, recalcular. */
    padding: 10px 28px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-height: 0;
    /* Scrollbar invisible: sigue scrolleando, pero no pinta el riel gris. */
    scrollbar-width: none;
}
.edx-sidebar-nav::-webkit-scrollbar { width: 0; height: 0; }

/* Etiqueta de grupo del nav (Resultados · Data Engine · Administrativos ·
   Sistema). Pequeña y en caja normal: la jerarquía la dan el tamaño y el
   color, no las mayúsculas ni el peso. Alineada al borde del ICONO del link
   (12 px = su padding-left), no al texto, para que la columna se lea recta. */
.edx-nav-group {
    margin: 13px 0 3px;
    padding: 0 12px;
    font-family: var(--font-sans);
    font-size: 10.5px;
    font-weight: 600;
    line-height: 1.2;
    letter-spacing: 0.01em;
    color: var(--text-dim);
    user-select: none;
}
.edx-nav-group:first-of-type { margin-top: 2px; }

.edx-nav-link {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 11px 12px;
    /* 18 px sobre 45 de alto: pastilla claramente redonda sin volverse cápsula. */
    border-radius: 18px;
    color: var(--text-dim);
    font-family: var(--font-sans);
    font-size: 14px;
    font-weight: 500;
    letter-spacing: -0.005em;
    text-decoration: none;
    border: 1px solid transparent;
    box-shadow: none;
    transition:
        background var(--sidebar-duration) var(--sidebar-easing),
        color var(--sidebar-duration) var(--sidebar-easing),
        border-color var(--sidebar-duration) var(--sidebar-easing);
    cursor: pointer;
    /* Border-left 3px al estado active: visualmente el "pill" tiene 3px
       a ser turquesa (3px), respetando exactamente el border-radius del
       pill. Para que el texto no se mueva al aparecer el border-left,
       el padding-left se reduce en 3px (de 13 a 10). El border-radius del pill
       se hereda naturalmente porque el border-left es parte del box. */
}
.edx-nav-link:hover {
    background: var(--surface);
    color: var(--text);
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
}
.edx-nav-link:active { background: var(--surface); }
/* Activo: pastilla blanca flotando sobre el lienzo (ref). Sin barra lateral,
   sin borde: el contraste lo da la superficie + la sombra suave. */
.edx-nav-link.is-active {
    background: var(--surface);
    color: var(--text);
    font-weight: 600;
    border-color: transparent;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.05), 0 10px 24px -14px rgba(15, 23, 42, 0.35);
}
html.dark-mode .edx-nav-link:hover { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.4); }
html.dark-mode .edx-nav-link.is-active { box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5), 0 10px 24px -14px rgba(0, 0, 0, 0.8); }

.edx-nav-icon {
    font-size: 19px;
    color: var(--text-dim-2);
    flex-shrink: 0;
    line-height: 1;
    transition: color var(--sidebar-duration) var(--sidebar-easing);
}
.edx-nav-link:hover .edx-nav-icon { color: var(--text); }
.edx-nav-link.is-active .edx-nav-icon { color: var(--text); }

.edx-nav-label {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.edx-sidebar-footer {
    /* Mismo margen lateral que .edx-sidebar-nav (28px): el card del usuario
       alinea su borde con el de los ítems del menú. */
    padding: 10px 28px 14px;
    margin-top: auto;
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex-shrink: 0;
}
.edx-sidebar-user {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 5px 6px;
    border-radius: 12px;
    background: var(--surface);
    border: 1px solid transparent;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.05), 0 10px 24px -14px rgba(15, 23, 42, 0.30);
    transition: background var(--sidebar-duration) var(--sidebar-easing);
}
.edx-sidebar-user:hover { background: var(--surface-2); }

/* El avatar + nombre son un enlace a "Mi Perfil"; el resto de la card
   (dot de estado, tema, logout) queda como estaba. El :hover debe fijar el
   color en --sidebar-text: si se deja al `a:hover` global, --accent-alt es
   oscuro en ambos temas y el nombre se ve casi negro. */
.edx-sidebar-user-link {
    display: flex;
    align-items: center;
    gap: 7px;
    flex: 1 1 auto;
    min-width: 0;
    color: var(--sidebar-text);
    text-decoration: none;
    border-radius: 8px;
    transition: color var(--sidebar-duration) var(--sidebar-easing);
}
.edx-sidebar-user-link:hover,
.edx-sidebar-user-link:focus,
.edx-sidebar-user-link:active { color: var(--sidebar-text); text-decoration: none; }
.edx-sidebar-user-link:focus-visible {
    outline: 2px solid var(--sidebar-accent);
    outline-offset: 2px;
}
.edx-sidebar-user-link:active { transform: scale(0.98); }

/* El indicador verde de "sesión activa" se retiró del card: no aporta y
   parpadeaba. El estado de la sesión lo dice el propio panel. */

.edx-sidebar-avatar {
    width: 24px;
    height: 24px;
    border-radius: 9999px;
    background: linear-gradient(135deg, var(--sidebar-accent) 0%, #374151 100%);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
    font-weight: 600;
    flex-shrink: 0;
}

.edx-sidebar-username {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 12px;
    font-weight: 600;
    color: var(--sidebar-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    padding-right: 2px;
}

.edx-sidebar-logout {
    margin: 0;
    flex-shrink: 0;
}
.edx-logout-btn {
    width: 26px;
    height: 26px;
    border-radius: 8px;
    background: transparent;
    color: var(--sidebar-muted);
    border: 1px solid transparent;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background var(--sidebar-duration) var(--sidebar-easing),
                color var(--sidebar-duration) var(--sidebar-easing),
                border-color var(--sidebar-duration) var(--sidebar-easing);
}
.edx-logout-btn:hover {
    background: var(--sidebar-danger-soft);
    color: var(--sidebar-danger);
    border-color: rgba(220, 38, 38, 0.20);
}
.edx-logout-btn i { font-size: 16px; }

/* Boton de cambio de tema (luna/sol) — visual identico al logout.
   Cuando implementemos dark mode, el JS intercambia las clases
   edx-theme-icon-light / edx-theme-icon-dark para mostrar el icono correcto. */
.edx-theme-toggle-btn {
    width: 26px;
    height: 26px;
    border-radius: 8px;
    background: transparent;
    color: var(--sidebar-muted);
    border: 1px solid transparent;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    transition: background var(--sidebar-duration) var(--sidebar-easing),
                color var(--sidebar-duration) var(--sidebar-easing),
                border-color var(--sidebar-duration) var(--sidebar-easing);
    flex-shrink: 0;
    padding: 0;
    margin: 0;
}
.edx-theme-toggle-btn:hover {
    background: var(--sidebar-bg-hover);
    color: var(--sidebar-text);
    border-color: var(--sidebar-border);
}
.edx-theme-toggle-btn i { font-size: 16px; }

.edx-sidebar-version {
    display: block;
    text-align: center;
    /* Mismo estilo que .login-brand-footer ("Data Engine"):
       Cove 600 SemiBold, 10px, tracking amplio, uppercase.
       Identidad visual consistente entre el footer del sidebar y el login. */
    font-family: var(--font-sans);
    font-size: 8px;
    font-weight: 600;
    font-style: italic;
    color: #4a4a52;
    letter-spacing: 0.01em;
    padding-top: 6px;
}

/* ───────────── TOP NAV (EDX v4) ───────────── */
.topnav-edx {
    display: grid;
    grid-template-columns: minmax(160px, 1fr) 2fr minmax(220px, 0.9fr);
    gap: 24px;
    align-items: center;
    padding: 22px 8px;
    margin-bottom: 24px;
    position: relative;
}

.topnav-brand {
    display: flex;
    align-items: center;
    gap: 14px;
    color: var(--text);
    text-decoration: none;
}
.topnav-brand svg {
    /* Logo a tamaño nativo del SVG legacy (80×80, viewBox 0 0 80 80).
       Sin drop-shadow para evitar el glow inferior. */
    width: 80px; height: 80px;
    filter: none;
}
.topnav-brand-text { display: flex; flex-direction: column; line-height: 1; gap: 4px; }
.topnav-brand-text .wm {
    color: var(--text);
    font-size: 26px;
    font-weight: 600;
    letter-spacing: -0.04em;
}
.topnav-brand-text .esv {
    color: var(--text);
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.01em;
}

.topnav-pills {
    display: flex;
    gap: 10px;
    justify-content: center;
    align-items: stretch;
}
.nav-pill {
    flex: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 12px 18px;
    border-radius: 9999px;
    border: 1px solid var(--border);
    background: var(--surface);
    color: var(--text-dim);
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-decoration: none;
    transition: border-color .2s ease, background .2s ease, color .2s ease, transform .15s ease;
    white-space: nowrap;
    box-shadow: var(--shadow);
}
.nav-pill:hover {
    border-color: var(--accent-line);
    background: var(--accent-soft);
    color: var(--text);
    transform: translateY(-1px);
}
.nav-pill.is-active {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--button-text);
    box-shadow: 0 1px 2px rgba(13, 148, 136, 0.20), 0 4px 12px rgba(13, 148, 136, 0.18);
}
.nav-pill-config {
    flex: 0 0 auto;
    width: 60px;
    height: 60px;
    padding: 0;
    font-size: 26px;
}

.topnav-user {
    display: flex;
    align-items: stretch;
    gap: 0;
    border-radius: 9999px;
    border: 1px solid var(--border);
    background: var(--surface);
    overflow: hidden;
    /* Auto-sized al contenido: el pill no se estira al ancho de la
       columna 3 (eso generaba espacio vacío raro a la izquierda).
       En lugar de eso, ``justify-self: end`` lo pega al borde derecho
       de la columna sin expandir el pill. */
    width: fit-content;
    justify-self: end;
    margin-left: auto;
    box-shadow: var(--shadow);
}
.topnav-user-info {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 16px 8px 8px;
}
.topnav-avatar {
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--accent-soft);
    box-shadow: inset 0 0 0 2px var(--accent);
    color: var(--text);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 600;
    font-size: 15px;
}
.topnav-user-text { display: flex; flex-direction: column; line-height: 1; gap: 3px; }
.user-name {
    color: var(--text);
    font-weight: 600;
    font-size: 13px;
}
.user-status {
    color: var(--text-dim-2);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.01em;
    display: flex;
    align-items: center;
    gap: 4px;
}
.user-status .dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--success);
    box-shadow: 0 0 6px var(--success);
}

.topnav-power {
    margin: 0;
    border-left: 1px solid var(--border);
    display: flex;
}
.topnav-power button {
    width: 56px;
    height: auto;
    border: none;
    background: transparent;
    color: var(--text-dim);
    font-size: 20px;
    cursor: pointer;
    transition: color .2s ease, background .2s ease;
}
.topnav-power button:hover {
    color: var(--danger);
    background: rgba(220, 38, 38, 0.08);
}

.topnav-version {
    position: absolute;
    right: 8px;
    top: 88px;
    font-family: var(--font-sans);
    font-size: 10px;
    letter-spacing: 1.5px;
    color: var(--text-dim-2);
    padding: 2px 8px;
    border: 1px solid var(--border);
    border-radius: 9999px;
    background: var(--surface);
}
.topnav-version span { display: inline-block; }

/* ───────────── Page header ───────────── */
/* Page header v10 — card elevada minimalista con ícono a la izquierda.
   Estilo ejecutivo: card con fondo + borde sutil + ícono redondo.
   Padding reducido, shadow suave, hover sutil. */
.page-header-v10 {
    display: flex;
    align-items: center;
    gap: 16px;
    margin: 18px 0 26px 0;
    padding: 16px 20px;
    background: var(--surface);
    border: 1px solid transparent;
    border-radius: 18px;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04), 0 18px 40px -30px rgba(15, 23, 42, 0.45);
    transition: box-shadow .2s ease;
}
.page-header-v10:hover {
    border-color: var(--border-strong);
}
.page-header-v10-icon {
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 14px;
    background: var(--bg);
    border: 1px solid transparent;
    color: var(--text);
}
.page-header-v10-icon i {
    font-size: 18px;
}
.page-header-v10-body {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 2px;
}
.page-h1 {
    margin: 0;
    /* Título de página: escala del master (22px · 600 · -0.02em). */
    font-family: var(--font-sans);
    font-size: 22px;
    font-weight: 600;
    letter-spacing: -0.02em;
    line-height: 1.15;
    color: var(--text);
    flex-shrink: 0;
}
.page-h1-kicker {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.01em;
    color: var(--text-dim-2);
    flex-shrink: 0;
}
.page-h1-sub {
    margin: 2px 0 0;
    color: var(--text-dim);
    font-size: 13px;
    font-weight: 400;
    line-height: 1.45;
}
.page-subtitle {
    margin: 4px 0 0 0;
    color: var(--text-dim);
    font-size: 14px;
    font-weight: 500;
}
/* Meta badges a la derecha del header (ej: timestamp, status). */
.page-meta {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--text-dim-2);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.01em;
    flex-shrink: 0;
}
.page-meta .dot {
    width: 6px;
    height: 6px;
    background: var(--success);
    border-radius: 50%;
    display: inline-block;
}

/* ───────────── Cards (EDX v5) ───────────── */
.card-edx {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 16px;
    padding: 22px 26px;
    margin: 18px 0;
    box-shadow: var(--shadow), var(--shadow-md);
    position: relative;
}
.card-edx-head {
    display: flex;
    align-items: center;
    gap: 14px;
    margin: -4px 0 14px 0;
}
.card-step {
    flex: 0 0 auto;
    width: 32px; height: 32px;
    border-radius: 9999px;
    background: var(--accent-soft);
    border: 1px solid var(--accent-line);
    color: var(--text);
    font-weight: 600;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.card-edx-title {
    margin: 0;
    font-size: 20px;
    font-weight: 600;
    letter-spacing: -0.025em;
    color: var(--text);
}
.card-actions {
    display: flex;
    justify-content: flex-end;
    margin-top: 18px;
}

/* ───────────── KPI grid ───────────── */
.kpi-grid {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 18px;
    margin: 22px 0;
}
@media (max-width: 1024px) {
    .kpi-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
    .kpi-grid { grid-template-columns: 1fr; }
}
.card-kpi {
    display: flex;
    align-items: center;
    gap: 18px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 18px;
    padding: 24px 24px;
    box-shadow: var(--shadow), var(--shadow-md);
    transition: transform .2s ease, border-color .2s ease, box-shadow .2s ease;
    min-height: 110px;
}
.card-kpi:hover {
    transform: translateY(-2px);
    border-color: var(--accent-line);
    box-shadow: 0 2px 4px rgba(15, 23, 42, 0.06), 0 8px 20px rgba(15, 23, 42, 0.06);
}
.kpi-icon {
    flex: 0 0 auto;
    width: 64px;
    height: 64px;
    border-radius: 16px;
    background: var(--accent-soft);
    border: 1px solid var(--accent-line);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--text);
    font-size: 24px;
}
.kpi-icon .ico { display: inline-flex; align-items: center; justify-content: center; }
.kpi-icon .ico svg { width: 32px; height: 32px; }
.kpi-label {
    color: var(--text-dim);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.01em;
    margin-bottom: 8px;
}
.kpi-value {
    font-family: var(--font-alt);
    color: var(--text);
    font-size: 36px;
    font-weight: 600;
    letter-spacing: -0.035em;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}
.kpi-foot {
    color: var(--text-dim-2);
    font-size: 12px;
    margin-top: 6px;
}

/* ───────────── Filter chips (sub-pills) ───────────── */
.sub-pills {
    display: flex;
    gap: 8px;
    margin: 14px 0 22px 0;
    flex-wrap: wrap;
}
.filter-chip {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 16px;
    border-radius: 9999px;
    background: var(--surface);
    border: 1px solid var(--border);
    color: var(--text-dim);
    text-decoration: none;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.02em;
    transition: all .2s ease;
}
.filter-chip:hover {
    color: var(--text);
    border-color: var(--accent);
}
.filter-chip.is-active {
    color: var(--text);
    background: var(--accent-soft);
    border-color: var(--accent);
}

/* ───────────── Dropzones (file uploaders) ───────────── */
.dropzone-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 14px;
    margin-top: 12px;
}
.dropzone-pill {
    display: flex;
    flex-direction: column;
    gap: 6px;
    background: var(--surface);
    border: 1px dashed var(--accent-line);
    border-radius: 14px;
    padding: 14px 16px;
    transition: border-color .2s ease, background .2s ease;
}
.dropzone-pill:hover {
    border-color: var(--accent);
    background: var(--surface-2);
}
.dropzone-label {
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.01em;
    color: var(--text);
}
.dropzone-input {
    color: var(--text);
    background: transparent;
    border: none;
    padding: 6px 0;
    font-family: inherit;
    font-size: 13px;
}
.dropzone-input::file-selector-button {
    background: var(--accent-soft);
    border: 1px solid var(--accent-line);
    color: var(--text);
    border-radius: 9999px;
    padding: 6px 12px;
    font-family: inherit;
    font-weight: 600;
    font-size: 12px;
    margin-right: 10px;
    cursor: pointer;
}
.dropzone-hint {
    color: var(--text-dim-2);
    font-size: 11px;
}

/* ───────────── Atomic grid (Bases · 3. Carga masiva) ───────────── */
.atomic-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 18px;
    margin-top: 14px;
}
.atomic-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 14px;
    padding: 14px 16px;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.atomic-card input[type="file"],
.atomic-card input[type="number"],
.atomic-card input[type="date"] {
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 8px 10px;
    color: var(--text);
    font-family: inherit;
}
.atomic-row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.input-pill-label {
    display: block;
    color: var(--text-dim);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.01em;
    margin-bottom: 6px;
}

/* ───────────── Inputs (login + bases) ───────────── */
.input-pill {
    background: var(--surface);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border-radius: 9999px;
    border: 1px solid var(--border);
    padding: 4px 20px;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
    display: flex;
    flex-direction: column;
    gap: 0;
    transition: border-color .2s ease, box-shadow .2s ease, background .2s ease;
    margin: 8px 0;
}
.input-pill:hover {
    border-color: var(--accent-line);
    background: var(--surface-2);
}
.input-pill:focus-within {
    background: var(--surface-2);
    border-color: var(--accent);
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04), 0 4px 14px rgba(15, 23, 42, 0.05),
                
}
.input-pill label {
    /* OJO: antes era var(--accent) = #0F1115 negro mate EN AMBOS modos →
       en dark quedaba texto negro invisible. var(--text) adapta (claro:
       #0f172a ≈ igual; dark: #E5E7EB blanco). */
    color: var(--text);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.01em;
    padding: 6px 0 2px 0;
}
.input-pill input,
.input-pill select,
.input-pill textarea {
    color: var(--text);
    background: transparent;
    border: none;
    font-family: inherit;
    font-size: 15px;
    font-weight: 500;
    letter-spacing: -0.01em;
    caret-color: var(--accent);
    padding: 4px 0 8px 0;
    width: 100%;
    outline: none;
}
.input-pill input::placeholder { color: #5a5a60; font-weight: 400; }
html.dark-mode .input-pill input::placeholder,
body.dark-mode .input-pill input::placeholder { color: var(--text-dim); }

.textarea-pill {
    width: 100%;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 14px;
    padding: 12px 16px;
    color: var(--text);
    font-family: inherit;
    font-size: 14px;
}

/* ───────────── Botones ───────────── */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 12px 22px;
    border-radius: 9999px;
    background: var(--surface);
    border: 1px solid var(--border);
    color: var(--text);
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: 0.01em;
    text-decoration: none;
    cursor: pointer;
    transition: transform .15s ease, background .2s ease,
                border-color .2s ease, box-shadow .2s ease, color .2s ease;
    box-shadow: none;
}
.btn:hover { border-color: var(--accent); transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn-icon { font-size: 12px; opacity: 0.9; }

.btn.btn-primary {
    background: #000000;
    color: #ffffff;
    border-color: #000000;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.20), 0 4px 12px rgba(0, 0, 0, 0.18);
}
.btn.btn-primary:hover {
    background: #1F2937;
    color: #ffffff;
    border-color: #1F2937;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25), 0 8px 20px rgba(0, 0, 0, 0.25);
}
.btn.btn-secondary {
    background: var(--surface);
    border-color: var(--border);
    color: var(--text);
}
.btn.btn-secondary:hover {
    background: var(--surface-2);
    border-color: var(--accent-line);
    color: var(--text);
}
.btn.btn-danger {
    color: var(--danger);
    border-color: rgba(220, 38, 38, 0.30);
    background: rgba(220, 38, 38, 0.04);
}
.btn.btn-danger:hover {
    background: rgba(220, 38, 38, 0.10);
    border-color: rgba(220, 38, 38, 0.55);
    color: var(--danger);
}
.btn-block { width: 100%; }
.btn-sm { padding: 8px 14px; font-size: 11px; letter-spacing: 0.01em; }
.btn-login {
    width: 100%;
    margin-top: 24px;
    padding: 16px 24px;
    font-size: 16px;
    /* Pedido explícito de producto: este botón va en MAYÚSCULAS (única
       excepción junto a los wordmarks). En caja alta hace falta aire entre
       letras para que no se lea como un bloque. */
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-weight: 600;
    /* Full black con texto blanco — invita al clic. */
    background: #000000;
    color: #ffffff;
    border-color: #000000;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.20), 0 4px 12px rgba(0, 0, 0, 0.18);
}
.btn-login:hover {
    background: #1F2937;
    color: #ffffff;
    border-color: #1F2937;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25), 0 8px 20px rgba(0, 0, 0, 0.25);
}

/* ───────────── Tables ───────────── */
.table-wrap {
    overflow-x: auto;
    margin-top: 6px;
}
.table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
}
.table th {
    text-align: left;
    color: var(--text-dim-2);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.01em;
    padding: 10px 18px 12px;
    border-bottom: 1px solid var(--border);
    background: transparent;
}
.table th.num, .table td.num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.table td {
    padding: 15px 18px;
    border-bottom: 1px solid var(--border);
    color: var(--text);
    font-size: 13.5px;
}
.table tr:hover td {
    background: var(--surface-2);
}
.table .empty-row {
    text-align: center;
    color: var(--text-dim-2);
    padding: 24px 14px;
}
.text-dim { color: var(--text-dim); }
.text-accent { color: var(--text); }
.text-success { color: var(--success); }
.text-danger { color: var(--danger); }

/* ───────────── Alerts (avisos EN LÍNEA dentro de una card) ─────────────
   No son pop-ups: los avisos transitorios del sistema son toasts
   (`.edx-toast`). Esto es el mensaje que vive dentro del formulario que lo
   produjo (p. ej. validaciones del panel de Sanciones).
   Tinta SIEMPRE `--text`: los tintes fijos anteriores (#b8f0f3, #b6f0c4)
   eran claros sobre fondo claro y el mensaje se perdía en modo claro. */
.alert {
    margin-top: 14px;
    padding: 11px 18px;
    border-radius: 14px;
    background-color: var(--surface-2);
    border: 1px solid var(--border);
    color: var(--text);
    font-size: 13px;
    font-weight: 500;
    text-align: center;
    letter-spacing: 0.01em;
}
.alert-success {
    background-color: color-mix(in srgb, var(--success) 9%, var(--surface));
    border-color: color-mix(in srgb, var(--success) 30%, transparent);
    color: var(--text);
}
.alert-error,
.alert-danger {
    background-color: color-mix(in srgb, var(--danger) 9%, var(--surface));
    border-color: color-mix(in srgb, var(--danger) 32%, transparent);
    color: var(--text);
}
.alert-info {
    background-color: var(--surface-2);
    border-color: var(--border);
    color: var(--text);
}

/* ───────────── Login page ───────────── */
.login-page {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 32px 24px;
    min-height: calc(100vh - 60px);
    position: relative;
    overflow: hidden;
}
/* ─── Login · líneas decorativas de fondo ───────────────────────
   Tres capas de SVG (líneas verticales finas, ondas suaves y
   destello turquesa) para que el fondo no se vea plano. */
.login-page::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-image:
        /* 1) líneas verticales finas (estilo "papel rayado" muy sutil) */
        repeating-linear-gradient(
            to right,
            transparent 0,
            transparent 79px,
            rgba(15, 23, 42, 0.04) 79px,
            rgba(15, 23, 42, 0.04) 80px
        ),
        /* 2) ondas suaves con tinte turquesa */
        radial-gradient(ellipse 700px 400px at 8% 12%,
            rgba(13, 148, 136, 0.07) 0%, transparent 60%),
        radial-gradient(ellipse 600px 350px at 92% 88%,
            rgba(13, 148, 136, 0.06) 0%, transparent 60%);
    background-size: 80px 100%, 100% 100%, 100% 100%;
    background-position: 0 0, 0 0, 0 0;
    background-repeat: repeat, no-repeat, no-repeat;
}
/* Una segunda capa con un par de círculos decorativos turquesa */
.login-page::after {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-image:
        radial-gradient(circle 6px at 12% 22%, rgba(13, 148, 136, 0.20) 0%, transparent 100%),
        radial-gradient(circle 4px at 88% 18%, rgba(13, 148, 136, 0.18) 0%, transparent 100%),
        radial-gradient(circle 5px at 18% 78%, rgba(13, 148, 136, 0.16) 0%, transparent 100%),
        radial-gradient(circle 7px at 82% 82%, rgba(13, 148, 136, 0.22) 0%, transparent 100%),
        radial-gradient(circle 3px at 50% 8%,  rgba(13, 148, 136, 0.15) 0%, transparent 100%),
        radial-gradient(circle 3px at 50% 92%, rgba(13, 148, 136, 0.15) 0%, transparent 100%);
}
.login-shell {
    position: relative;
    z-index: 2;
    width: 420px;
    max-width: calc(100vw - 48px);
    margin: 0 auto;
    padding: 36px 32px;
    display: flex;
    flex-direction: column;
    animation: loginFadeIn .55s cubic-bezier(.2,.7,.2,1) both;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 24px;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04),
                0 12px 40px rgba(15, 23, 42, 0.06);
}
.login-shell::before {
    /* Acento turquesa en la parte superior del card */
    content: "";
    position: absolute;
    top: 0; left: 32px; right: 32px;
    height: 3px;
    border-radius: 0 0 9999px 9999px;
    background: linear-gradient(90deg,
        transparent 0%,
        var(--accent) 50%,
        transparent 100%);
}
@keyframes loginFadeIn {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: none; }
}
/* Lockup de marcas: la E de Expectra + el logo de Co Val · Bufete Jurídico,
   separados por una línea difuminada.
   El SVG 80×80 trae margen interno asimétrico (el contenido real mide 51×56
   en unidades del viewBox → 76.5×84 px al renderizarse a 120). Se recorta a su
   contenido para que la caja visible sea exactamente la silueta de la E y los
   márgenes del divisor sean simétricos de verdad (no de caja). */
.login-brand {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0;
    margin-bottom: 16px;
    padding: 8px 0 4px 0;
}
.login-brand .brand-e {
    flex: none;
    position: relative;
    /* La silueta de la E mide 84.15 × 92.4 px a este tamaño: la caja lleva 1 px
       de aire a cada lado para que el recorte no afeite el antialias (se veía el
       borde izquierdo e inferior cortado en plano) ni la sombra. El margen del
       divisor baja 1 px por lado, así el lockup mide y se ve igual. */
    width: 86.2px;
    height: 94.4px;
    overflow: hidden;
    filter: drop-shadow(0 1px 2px rgba(15, 23, 42, 0.10));
}
.login-brand .brand-e svg {
    position: absolute;
    left: -25.4px; /* 16/80 × 132 − 1 px de aire */
    top: -28.7px;  /* 18/80 × 132 − 1 px de aire */
    width: 132px;
    height: 132px;
}
.login-brand .brand-coveyp {
    flex: none;
    display: block;
    height: 92.4px;   /* la MISMA altura que la E: los dos logos quedan al ras */
    width: auto;
}
/* Divisor: hairline vertical con degradado que se desvanece en ambos extremos
   (difuminado), con el MISMO margen a cada lado de los dos logos. */
.login-brand .brand-split {
    flex: none;
    width: 1px;
    height: 68.2px;
    margin: 0 27.6px;   /* 28.6 − 1 px: compensa el aire de la caja de la E */
    border-radius: 9999px;
    background: linear-gradient(180deg,
        rgba(15, 23, 42, 0) 0%,
        rgba(15, 23, 42, 0.30) 50%,
        rgba(15, 23, 42, 0) 100%);
}
@media (max-width: 380px) {
    .login-brand .brand-split { margin: 0 16.6px; }
}
.login-brand .brand-text {
    display: flex;
    flex-direction: column;
    gap: 8px;
    line-height: 0.95;
    text-align: left;
}
.login-brand .wm {
    color: var(--text);
    font-size: 44px;
    font-weight: 600;
    letter-spacing: -0.045em;
}
.login-brand .esv {
    color: var(--text);
    font-size: 20px;
    font-weight: 600;
    letter-spacing: 0.01em;
}
.login-divider {
    width: 79.2px;
    height: 2px;
    border-radius: 9999px;
    background: linear-gradient(90deg,
        transparent 0%, var(--accent) 50%, transparent 100%);
    margin: 20px auto 32px auto;
}
.login-title {
    font-family: var(--font-display);
    /* Misma firma que el título del sidebar (.edx-sidebar-title):
       Cove 600 · tracking 0.32em · uppercase, +20 % de cuerpo (14.4px).
       El padding-left compensa el hueco fantasma del tracking para el
       centrado óptico. */
    color: var(--text);
    font-size: 14.4px; /* 12px × 1.2 (título del sidebar + 20 %) */
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0.32em;
    text-transform: uppercase;
    padding-left: 0.32em;
    margin: 0 0 28px 0;
    text-align: center;
}
.login-label {
    display: block;
    color: var(--text-dim);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.01em;
    margin: 14px 0 6px 4px;
}
/* ── Fila "Recuérdame" + "Mostrar contraseña" (una sola línea) ─────────────
   Preferencia a la izquierda, acción a la derecha. Altura mínima 32px en los
   dos controles para que el área táctil no quede por debajo de lo usable.
   El ojo es un <button aria-pressed>, no un checkbox: es una acción, no un
   ajuste persistente. */
.login-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px 12px;
    flex-wrap: wrap;
    margin: 12px 0 0 4px;
}
.login-remember {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 32px;
    color: var(--text-dim);
    font-family: var(--font-sans);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.02em;
    cursor: pointer;
}
/* accent-color con token: en dark --accent es negro mate y el check se
   perdería sobre la card oscura, así que se usa --text (invierte por tema). */
.login-remember input[type="checkbox"] {
    accent-color: var(--text);
    width: 15px;
    height: 15px;
    margin: 0;
    cursor: pointer;
}
.login-remember-hint {
    color: var(--text-dim-2);
    font-style: normal;
    font-weight: 400;
    margin-left: 2px;
}
.login-eye {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    min-height: 32px;
    padding: 0 10px 0 8px;
    border: 1px solid transparent;
    border-radius: 9px;
    background: transparent;
    color: var(--text-dim);
    font-family: var(--font-sans);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.02em;
    cursor: pointer;
    transition: color .15s ease, background-color .15s ease, border-color .15s ease;
}
.login-eye i {
    font-size: 15px;
    line-height: 1;
}
.login-eye:hover {
    background: var(--accent-soft);
    color: var(--text);
}
.login-eye:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
/* Estado "contraseña visible": el control se queda encendido. */
.login-eye[aria-pressed="true"] {
    background: var(--accent-soft);
    border-color: var(--border);
    color: var(--text);
}
@media (prefers-reduced-motion: reduce) {
    .login-eye { transition: none; }
}
/* A 380px los dos controles se pelean por el ancho: el hint "(30 días)" es
   prescindible, el texto del ojo no (es el que dice qué hace). */
@media (max-width: 380px) {
    .login-remember-hint { display: none; }
    .login-eye { padding: 0 8px; }
}
.login-error {
    margin-top: 16px;
    padding: 11px 18px;
    border-radius: 14px;
    background-color: rgba(220, 38, 38, 0.06);
    box-shadow: inset 0 0 0 1px rgba(220, 38, 38, 0.24), 0 1px 2px rgba(220, 38, 38, 0.10), 0 4px 12px rgba(220, 38, 38, 0.06);
    color: var(--danger);
    font-size: 13px;
    font-weight: 500;
    text-align: center;
    letter-spacing: 0.01em;
    animation: loginErrorShake .4s ease both;
}
@keyframes loginErrorShake {
    0%, 100% { transform: translateX(0); }
    25%      { transform: translateX(-4px); }
    75%      { transform: translateX(4px); }
}
.login-footer {
    margin-top: 22px;
    text-align: center;
    color: var(--text-dim-2);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.04em;
    transition: color .2s ease;
    /* Es un <button>, no un <a>: resetea el chrome nativo del botón
       para que se vea como el enlace de antes. */
    display: block;
    width: 100%;
    background: none;
    border: none;
    padding: 0;
    font-family: inherit;
    cursor: pointer;
}
.login-footer:hover { color: var(--text-dim); }

/* ───────────── "¿Olvidaste tu contraseña?" — modal de solicitud ───────────── */

/* Aviso tras enviar la solicitud (verde ok / rojo error) — misma
   geometría que .login-error para no romper la coherencia de forma. */
.login-notice {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin-top: 16px;
    padding: 11px 18px;
    border-radius: 14px;
    background-color: rgba(13, 148, 136, 0.07);
    box-shadow: inset 0 0 0 1px rgba(13, 148, 136, 0.24),
                0 1px 2px rgba(13, 148, 136, 0.08);
    color: #0b6b60;
    font-size: 13px;
    font-weight: 500;
    line-height: 1.45;
    text-align: left;
    animation: loginFadeIn .4s ease both;
}
.login-notice.is-error {
    background-color: rgba(220, 38, 38, 0.06);
    box-shadow: inset 0 0 0 1px rgba(220, 38, 38, 0.24),
                0 1px 2px rgba(220, 38, 38, 0.10);
    color: var(--danger);
}

.reset-dialog {
    width: min(420px, calc(100vw - 40px));
    padding: 0;
    border: 1px solid var(--border);
    border-radius: 24px;
    background: var(--surface);
    color: var(--text);
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.06),
                0 24px 64px rgba(15, 23, 42, 0.22);
}
.reset-dialog::backdrop {
    background: rgba(15, 17, 21, 0.42);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
}
.reset-dialog[open] {
    animation: loginFadeIn .3s cubic-bezier(.2,.7,.2,1) both;
}
.reset-form { padding: 26px 26px 24px; }
.reset-dialog-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}
.reset-dialog-head h2 {
    margin: 0;
    color: var(--text);
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -0.02em;
}
.reset-close {
    flex: none;
    width: 30px;
    height: 30px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border);
    border-radius: 9999px;
    background: var(--surface);
    color: var(--text-dim);
    font-size: 17px;
    line-height: 1;
    cursor: pointer;
    transition: border-color .2s ease, color .2s ease, background .2s ease;
}
.reset-close:hover { border-color: var(--accent); color: var(--text); }
.reset-close:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
    border-color: var(--accent);
    color: var(--text);
}
.reset-hint {
    margin: 10px 0 2px;
    color: var(--text-dim-2);
    font-size: 12.5px;
    line-height: 1.5;
}
.reset-form .login-label { margin-left: 4px; }
.reset-form .input-pill { margin: 6px 0 0; }
.reset-textarea {
    display: block;
    width: 100%;
    box-sizing: border-box;
    margin-top: 6px;
    padding: 12px 16px;
    border: 1px solid var(--border);
    border-radius: 14px;
    background: var(--surface);
    color: var(--text);
    font-family: inherit;
    font-size: 14px;
    font-weight: 500;
    resize: vertical;
    min-height: 64px;
    outline: none;
    transition: border-color .2s ease, background .2s ease;
}
.reset-textarea:focus { border-color: var(--accent); background: var(--surface-2); }
.reset-textarea::placeholder { color: #5a5a60; font-weight: 400; }
.reset-form .btn-login { margin-top: 20px; padding: 14px 22px; }
.opt {
    margin-left: 4px;
    color: var(--text-dim-2);
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: none;
}
.login-brand-footer {
    font-family: var(--font-display);
    position: fixed;
    bottom: 24px;
    left: 0; right: 0;
    text-align: center;
    color: #4a4a52;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.32em;
    text-transform: uppercase;
}

/* ───────────── Aporte form grid (asesores) ─────────────
   Los 3 campos + el botón de registrar comparten UNA fila. Las columnas `fr`
   se reparten el ancho restante, así que los campos se acortan solos para que
   el botón quepa: la fila no puede desbordarse. */
.aporte-grid {
    display: grid;
    grid-template-columns: 2fr 2fr 1fr auto;
    gap: 14px;
    align-items: end;              /* el botón se alinea con el input, no con el label */
}
/* Los pills deben poder encogerse por debajo de su ancho mínimo intrínseco
   (si no, el `<select>` fija el ancho y la fila se desborda). */
.aporte-grid > .input-pill { min-width: 0; }

/* Botón "+" del form de aportación: sólo ícono, verde (paleta Success) y
   circular. Se ESTIRA a la altura de la fila para quedar exactamente a ras de
   los campos (mismo top y mismo bottom) y `aspect-ratio` lo mantiene redondo.
   El `margin: 8px 0` replica el de los `.input-pill`; el radio 9999px es el
   MISMO lenguaje que los pills y que los botones sólo-ícono de Configuración.
   OJO: la especificidad debe superar a `.page-container .btn-sq` (2403). */
.page-container .aporte-grid .btn-sq {
    width: auto;
    height: auto;
    align-self: stretch;
    aspect-ratio: 1 / 1;
    margin: 8px 0;
    border-radius: 9999px;
}
.page-container .aporte-grid .btn-sq > i { font-size: 20px; }

.crear-grid {
    display: grid;
    grid-template-columns: 2fr 2fr 1fr auto;
    gap: 10px;
    align-items: end;
}
@media (max-width: 800px) {
    .aporte-grid, .crear-grid { grid-template-columns: 1fr; }
    /* En móvil el grid se apila: el botón pasa a fila completa (tap target
       grande). Aquí sí necesita altura explícita: al quedar solo en su fila,
       `align-self: stretch` + `aspect-ratio` no tendría de dónde tomarla. */
    .page-container .aporte-grid .btn-sq {
        width: auto;
        height: 44px;
        align-self: auto;
        aspect-ratio: auto;
        border-radius: 10px;
        justify-self: stretch;
    }
    .topnav-edx { grid-template-columns: 1fr; gap: 12px; }
    .topnav-pills { justify-content: flex-start; overflow-x: auto; }
    .topnav-version { position: static; margin-top: 8px; }
    .topnav-power button { width: 44px; }
}

/* ───────────── Badge tipo ───────────── */
.badge-tipo {
    display: inline-block;
    padding: 3px 10px;
    border-radius: 9999px;
    background: var(--accent-soft);
    border: 1px solid var(--accent-line);
    color: var(--text);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.01em;
}

/* ───────────── Resultado AJAX ───────────── */
.result {
    margin-top: 8px;
    min-height: 18px;
    font-size: 12px;
}
.result-text { font-weight: 600; letter-spacing: 0.02em; }
.form-msg { margin-top: 14px; }

/* ───────────── Switch de vistas (navegación de paneles) ─────────────
   Componente ÚNICO para cambiar de vista dentro de un panel: Métricas,
   Bases, Asesores, Planchados y el Detalle de Cliente. Reemplaza a las tabs
   con indicador deslizante para que todo el producto hable igual.

   - Centrado siempre: el wrapper centra y el nav es ``inline-flex``.
   - Peso de fuente CONSTANTE (600) en reposo y activo: si el activo pasara a
     700 el ancho cambiaría al navegar y el switch "saltaría".
   - El activo invierte los tokens (``--text`` de fondo, ``--bg`` de texto),
     igual que el resto de controles seleccionados del sistema.
   - ``:focus-visible`` con anillo de 2 px porque se maneja con teclado.
   - En pantallas angostas se desplaza en horizontal, no se corta. */
.view-switch-wrap {
    display: flex;
    justify-content: center;
    margin: 16px 0 22px;
}
.view-switch {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    max-width: 100%;
    padding: 3px;
    overflow-x: auto;
    scrollbar-width: none;
    background: var(--surface-2, #F1F1F1);
    border: 1px solid var(--border);
    border-radius: 999px;
}
.view-switch::-webkit-scrollbar { display: none; }
.view-switch-btn {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    height: 32px;
    padding: 0 18px;
    border: 0;
    border-radius: 999px;
    background: transparent;
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 600;
    letter-spacing: .01em;
    color: var(--text-dim);
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color 160ms ease, color 160ms ease;
}
.view-switch-btn:hover { color: var(--text); }
.view-switch-btn:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }
.view-switch-btn.is-active { background: var(--text); color: var(--bg); }
.view-switch-btn i { font-size: 15px; line-height: 1; }
@media (prefers-reduced-motion: reduce) {
    .view-switch-btn { transition: none; }
}
/* Fade de entrada del contenido: al cargar la página el contenido principal no
   aparece de golpe, entra con un fade corto. El <head> pone ``.edx-fade`` en
   <html> y se quita solo (ver base.html). */
html.edx-fade .edx-main {
    animation: edx-page-in .18s ease-out both;
}
@keyframes edx-page-in { from { opacity: 0; } to { opacity: 1; } }

/* ───────────── Radio / checkbox / select ───────────── */
.radio-row label,
input[type="radio"],
input[type="checkbox"] {
    color: var(--text-dim);
    cursor: pointer;
}
input[type="checkbox"], input[type="radio"] {
    accent-color: var(--accent);
}

/* ───────────── Select base ───────────── */
/* Chevron propio (IconSax ArrowDown2) en vez de la flecha del sistema: mismo
   trazo que los iconos, y el control deja de verse "de navegador viejo". */
html select {
    appearance: none;
    -webkit-appearance: none;
    /* Alto por padding, no por `height`: con `height` fijo algunos motores
       recortan el texto a la mitad (Safari). Así la caja crece con la letra. */
    min-height: 38px;
    padding: 9px 36px 9px 14px;
    background-color: var(--surface);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23667085' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'><path d='M19.92 8.95l-6.52 6.52c-.77.77-2.03.77-2.8 0L4.08 8.95'/></svg>");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 14px 14px;
    border: 1px solid var(--border);
    border-radius: 12px;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.05),
                0 10px 24px -18px rgba(15, 23, 42, 0.35);
    color: var(--text);
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 600;
    line-height: 20px;
    width: 100%;
    cursor: pointer;
    transition: box-shadow 160ms var(--sidebar-easing),
                background-color 160ms var(--sidebar-easing),
                border-color 160ms var(--sidebar-easing);
}
html select:hover {
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.07),
                0 12px 26px -16px rgba(15, 23, 42, 0.45);
}
html select:focus-visible {
    outline: none;
    border-color: var(--ice-400);
    box-shadow: 0 0 0 3px var(--accent-soft),
                0 10px 24px -18px rgba(15, 23, 42, 0.35);
}
html select:disabled { opacity: .55; cursor: not-allowed; }
html select option { background: var(--surface); color: var(--text); }
select[multiple] { height: auto; padding: 8px 10px; background-image: none; }
html.dark-mode select {
    background-color: var(--surface-2);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2394A3B8' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'><path d='M19.92 8.95l-6.52 6.52c-.77.77-2.03.77-2.8 0L4.08 8.95'/></svg>");
}

/* ───────────── Fechas / hora ───────────── */
/* Mismo cuerpo que el select: 36 px, radio 10, cifras tabulares. El indicador
   nativo se atenúa (no se oculta: es el acceso al calendario). */
html input[type="date"],
html input[type="month"],
html input[type="week"],
html input[type="time"],
input[type="datetime-local"] {
    /* `relative` lo necesita el indicador estirado de la regla de abajo. */
    position: relative;
    min-height: 38px;
    padding: 8px 32px 8px 12px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.05),
                0 10px 24px -18px rgba(15, 23, 42, 0.35);
    color: var(--text);
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 600;
    line-height: 20px;
    font-variant-numeric: tabular-nums;
    color-scheme: light;
    cursor: pointer;
    transition: box-shadow 160ms var(--sidebar-easing),
                border-color 160ms var(--sidebar-easing);
}
html input[type="date"]:hover,
html input[type="month"]:hover,
html input[type="week"]:hover,
html input[type="time"]:hover,
input[type="datetime-local"]:hover {
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.07),
                0 12px 26px -16px rgba(15, 23, 42, 0.45);
}
html input[type="date"]:focus-visible,
html input[type="month"]:focus-visible,
html input[type="week"]:focus-visible,
html input[type="time"]:focus-visible,
input[type="datetime-local"]:focus-visible {
    outline: none;
    border-color: var(--ice-400);
    box-shadow: 0 0 0 3px var(--accent-soft);
}
html.dark-mode input[type="date"],
html.dark-mode input[type="month"],
html.dark-mode input[type="week"],
html.dark-mode input[type="time"],
html.dark-mode input[type="datetime-local"] {
    background: var(--surface-2);
    color-scheme: dark;
}

/* ───────────── Barras y gráficas (componente único) ─────────────
   Un solo lenguaje para TODA barra del panel: carril `--chart-track`, relleno
   `--chart-line` (o estado), radio de cápsula y transición de 280 ms. Las
   variantes cubren lo que ya existe: progreso, meta con marca, y barra
   segmentada (apilada) con 2 px de aire entre tramos.                */
.c-bar {
    display: block;
    position: relative;
    height: 8px;
    border-radius: 999px;
    background: var(--chart-track);
    overflow: hidden;
}
.c-bar > span {
    display: block;
    height: 100%;
    border-radius: 999px;
    background: var(--chart-line);
    transition: width 280ms cubic-bezier(.4, 0, .2, 1);
}
.c-bar--md { height: 10px; }
.c-bar--lg { height: 12px; }
.c-bar--ok > span { background: var(--success); }
.c-bar--warn > span { background: var(--warning); }
.c-bar--bad > span { background: var(--danger); }
/* Marca de meta sobre el carril (no se recorta: sale por arriba y abajo). */
.c-bar--meta { overflow: visible; }
.c-bar--meta::after {
    content: "";
    position: absolute;
    top: -3px;
    bottom: -3px;
    left: var(--meta, 100%);
    width: 2px;
    border-radius: 2px;
    background: var(--text);
    opacity: .75;
}

/* Segmentada: tramos con aire, cada uno con su propia cápsula. */
.c-bar-seg {
    display: flex;
    gap: 2px;
    height: 10px;
    border-radius: 999px;
    background: var(--chart-track);
    overflow: hidden;
}
.c-bar-seg > span {
    display: block;
    height: 100%;
    min-width: 2px;
    border-radius: 999px;
    transition: width 280ms cubic-bezier(.4, 0, .2, 1);
}
.c-bar-seg > .seg-a { background: var(--chart-line); }
.c-bar-seg > .seg-ok { background: var(--success); }
.c-bar-seg > .seg-bad { background: var(--danger); }
.c-bar-seg > .seg-mute { background: var(--border-strong); }

/* Leyenda de la barra segmentada. */
.c-bar-key {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 12px;
    margin: 7px 0 0;
    padding: 0;
    list-style: none;
    font-size: 10.5px;
    color: var(--text-dim);
}
.c-bar-key li { display: flex; align-items: center; gap: 5px; }
.c-bar-key i {
    width: 7px;
    height: 7px;
    border-radius: 999px;
    background: var(--chart-line);
    flex: none;
}
.c-bar-key .k-ok i { background: var(--success); }
.c-bar-key .k-bad i { background: var(--danger); }
.c-bar-key .k-mute i { background: var(--border-strong); }
.c-bar-key b { color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }

/* ── Selector de días (pastillas con radios) ──────────────────────────
   Un solo componente para el filtro del panel de Recurrencias y el modal de
   Promesa: todos los días dibujados en una fila, selección única. La pastilla
   activa usa el par invertido del switch (--text / --bg), así que funciona
   igual en claro y dark. */
.dia-pick {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    flex-wrap: nowrap;
}
.dia-opt {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 32px;
    min-width: 40px;
    padding: 0 9px;
    border: 1px solid var(--border);
    border-radius: 9px;
    background: var(--surface);
    color: var(--text-dim);
    font-size: 11.5px;
    font-weight: 600;
    cursor: pointer;
    transition: border-color 140ms var(--sidebar-easing),
                background 140ms var(--sidebar-easing),
                color 140ms var(--sidebar-easing);
}
.dia-opt input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}
.dia-opt:has(input:checked) {
    background: var(--text);
    border-color: var(--text);
    color: var(--bg);
}
.dia-opt:has(input:focus-visible) {
    outline: 2px solid var(--text);
    outline-offset: 2px;
}

/* ───────────── Barras de progreso (Bases · CGC) ───────────── */
/* Mismo lenguaje que .c-bar: carril neutro y relleno de tinta (sin gradiente:
   el degradado competía con el dato). */
.progress-bar {
    width: 100%;
    height: 8px;
    background: var(--chart-track);
    border-radius: 999px;
    overflow: hidden;
    margin: 8px 0;
}
.progress-bar-fill {
    height: 100%;
    background: var(--chart-line);
    border-radius: inherit;
    transition: width 280ms cubic-bezier(.4, 0, .2, 1);
}

/* ───────────── Expander ───────────── */
.expander {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 14px;
    padding: 14px 18px;
    margin: 10px 0;
}
.expander-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    color: var(--text);
    font-weight: 600;
}

/* ───────────── Cardinal (numérico) ───────────── */
.metric-value {
    font-family: var(--font-alt); color: var(--text); font-size: 28px; font-weight: 600; letter-spacing: -0.03em; }
.metric-label { color: var(--text-dim); font-size: 11px; letter-spacing: 0.01em; font-weight: 600; }

/* ───────────── Card bono (dashboard) ───────────── */
.card-bono { border-color: var(--border); }

/* ───────────── Helpers ───────────── */
[hidden] { display: none !important; }
.disabled { opacity: .55; pointer-events: none; }
.center { text-align: center; }
.right { text-align: right; }
.mt-24 { margin-top: 24px; }
.mb-24 { margin-bottom: 24px; }


/* ================================================================
   PANEL COMPONENTS (Kravio v10)
   ----------------------------------------------------------------
   Componentes compartidos por TODAS las páginas de contenido. Fueron
   extraídos del panel de Configuración (que es la referencia) para
   poder reutilizarlos sin duplicar estilos ni overrides de dark mode.

   Regla de oro: al usar los MISMOS nombres de clase en todos los
   paneles, un único bloque de overrides de dark mode (al final de este
   archivo) cubre a todos. No hardcodear colores nuevos en los templates;
   usar estas clases.
   ================================================================ */

/* ── Contenedor de contenido (ancho de lectura + padding lateral) ── */
.page-container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 24px 32px 24px 32px;
}
/* Tipografía de títulos del panel: Cove + tracking cerrado. Replica lo
   que antes hacía ``.krav-cfg-panel h1, .krav-cfg-panel h2`` y mantiene la
   identidad del header (h1 en Cove). */
.page-container h1,
.page-container h2 {
    font-family: var(--font-sans);
    letter-spacing: -0.01em;
}
/* En los paneles no usamos monoespaciado: los
   elementos de código heredan Cove. Sin esto, el UA del navegador
   fuerza ``monospace`` en <code>/<kbd>/<samp>/<pre>. */
.page-container code,
.page-container kbd,
.page-container samp,
.page-container pre {
    font-family: var(--font-sans);
}

/* ── Doble card: anillo gris + interior blanco ──
   Ambas capas son FLEX COLUMN: en una fila de grid (p. ej. Card 1 de
   Configuración) las dos .panel-card se igualan de alto, y sin esto el
   .panel-card-inner más corto dejaba ver el anillo por debajo. Así el
   interior siempre llena su anillo, sin cambiar el alto del contenedor. */
.panel-card {
    display: flex;
    flex-direction: column;
    background: #F1F1F1;
    border-radius: 24px;                /* rounded-3xl */
    padding: 5px;
    overflow: hidden;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);
}
.panel-card-inner {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    min-height: 0;
    background: #fff;
    border-radius: 0.875rem;
    overflow: hidden;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03), inset 0 0 0 1px rgba(0, 0, 0, 0.02);
}
/* Variante destructiva (roja) — Card de Limpieza. */
.panel-card--danger {
    box-shadow: 0 2px 4px rgba(220, 38, 38, 0.10);
}
.panel-card--danger > .panel-card-inner {
    box-shadow: inset 0 0 0 1px rgba(220, 38, 38, 0.08), 0 1px 2px rgba(220, 38, 38, 0.04);
}
/* Variante cálida (terracota) — Card de Reset operativo. */
.panel-card--warm {
    box-shadow: 0 2px 4px rgba(245, 228, 216, 0.40);
}
.panel-card--warm > .panel-card-inner {
    box-shadow: inset 0 0 0 1px rgba(176, 109, 71, 0.10), 0 1px 2px rgba(176, 109, 71, 0.06);
}

/* ── Head de card: barra con título + meta ── */
.panel-card-head {
    padding: 12px 20px;                 /* px-5 py-3 */
    display: flex;
    align-items: center;
    justify-content: space-between;
    border-radius: 0.875rem 0.875rem 0 0;
    background: #F1F1F1;
    box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.04);
}
.panel-card-head--danger { background: rgba(220, 38, 38, 0.06); box-shadow: none; }
.panel-card-head--warm   { background: rgba(176, 109, 71, 0.08); box-shadow: none; }

.panel-card-title { display: flex; align-items: center; gap: 8px; }
.panel-card-title > i { font-size: 16px; color: #1F2937; }
.panel-card-title h2 {
    margin: 0;
    font-size: 16px;
    font-weight: 600;
    color: #11141A;
    letter-spacing: -0.01em;             /* tracking-tight */
    font-family: var(--font-sans);
}
.panel-card-title--danger > i,
.panel-card-title--danger h2 { color: var(--danger-strong); }
.panel-card-title--warm > i,
.panel-card-title--warm h2   { color: #B06D47; }
.panel-card-title--success > i { color: #0D6558; }

.panel-card-meta { font-size: 11px; font-weight: 300; color: #9C9C9C; }
.panel-card-meta--danger { color: var(--danger-strong); }
.panel-card-meta--warm   { color: #B06D47; }

/* ── Tabla de panel ── */
.krav-tabla {
    width: 100%;
    border-collapse: collapse;
    background: #fff;
}
.krav-tabla thead th {
    background: #F1F1F1;
    color: #6A6B6C;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .5px;
    padding: 12px;
    text-align: center;
    vertical-align: middle;
    border-bottom: 1px solid #E5E5E5;
}
.krav-tabla thead th.right { text-align: center; padding-right: 14px; }
.krav-tabla tbody tr { border-bottom: 1px solid #F1F1F1; transition: background .12s; }
.krav-tabla tbody tr:last-child { border-bottom: 0; }
.krav-tabla tbody tr:hover { background: #FAFAFA; }
.krav-tabla tbody td { padding: 12px; font-size: 13px; color: #11141A; vertical-align: middle; text-align: center; }
.krav-tabla td.right { text-align: center; }
.krav-tabla td.muted { color: #6A6B6C; font-weight: 300; }
.krav-tabla .username {
    font-family: var(--font-sans);
    font-weight: 600;
    color: #11141A;
}

/* ── Chips semánticos ── */
.chip {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 3px 10px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
    line-height: 1.3;
}
.chip.tu      { background: rgba(30, 58, 138, 0.12); color: #1e3a8a; border: 1px solid rgba(30, 58, 138, 0.30); }
.chip.warn    { background: rgba(245, 158, 11, 0.12); color: #92400e; border: 1px solid rgba(245, 158, 11, 0.30); }
.chip.success { background: rgba(13, 101, 88, 0.12); color: #0D6558; border: 1px solid rgba(13, 101, 88, 0.30); }
.chip.danger  { background: rgba(220, 38, 38, 0.12); color: var(--danger-strong); border: 1px solid rgba(220, 38, 38, 0.30); }
.chip.mute    { background: var(--surface-2); color: var(--text-dim); border: 1px solid var(--border); }

/* ── Status chip grande (headers de cards de mantenimiento) ── */
.krav-status-chip {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 12px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .02em;
}
.krav-status-chip--danger {
    background: rgba(220, 38, 38, 0.10);
    color: var(--danger-strong);
    border: 1px solid rgba(220, 38, 38, 0.30);
}
.krav-status-chip--warm {
    background: rgba(245, 158, 11, 0.10);
    color: #92400E;
    border: 1px solid rgba(245, 158, 11, 0.30);
}

/* ── Action popover (position: fixed con JS) ──
   El disparador (<summary>) es un .btn (ver template); aquí solo el layout. */
.action-popover { display: inline-block; position: relative; margin-left: 4px; }
.action-popover > summary { list-style: none; cursor: pointer; }
.action-popover > summary::-webkit-details-marker { display: none; }
.action-popover > summary::marker { content: ''; }

/* position: fixed evita quedar atrapado por overflow:hidden de los
   cards padre. Las coordenadas las pone el JS al abrir el details. */
.popover-body {
    position: fixed;
    background: #fff;
    border: 1px solid #E5E5E5;
    border-radius: 12px;
    box-shadow: 0 12px 32px rgba(15, 23, 42, 0.18), 0 2px 6px rgba(15, 23, 42, 0.06);
    padding: 14px;
    z-index: 9999;
    width: 320px;
    max-width: calc(100vw - 32px);
    display: none;
    animation: kravPopoverIn .14s cubic-bezier(.2,.8,.2,1);
}
.action-popover[open] > .popover-body { display: block; }
@keyframes kravPopoverIn {
    from { opacity: 0; transform: translateY(-6px) scale(0.97); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}
.popover-body label { display: flex; flex-direction: column; gap: 4px; margin-bottom: 8px; }
.popover-body label > span {
    font-size: 10px;
    font-weight: 600;
    color: #6A6B6C;
    letter-spacing: .4px;
}
.popover-body input,
.popover-body select {
    /* dentro del popover se queda compacto: hereda el resto del componente */
    min-height: 34px;
    padding: 7px 32px 7px 12px;
}
.popover-body input:focus,
.popover-body select:focus {
    outline: none;
    background: #fff;
    border-color: #1F2937;
    box-shadow: 0 0 0 3px rgba(31, 41, 55, 0.18);
}
/* Los botones del popover son .btn (block) — heredan la paleta de botones. */
.popover-body .btn { margin-top: 6px; }
.popover-body .warn-text {
    font-size: 11px;
    color: #92400e;
    background: rgba(245, 158, 11, 0.08);
    border: 1px solid rgba(245, 158, 11, 0.30);
    padding: 8px 10px;
    border-radius: 8px;
    margin: 0 0 8px;
}
.popover-body .normal-text { font-size: 11px; color: #6A6B6C; margin: 0 0 8px; }

/* ── Alerts de panel (renombrados para no chocar con ``.alert`` de
      los flash messages del shell, que tienen otro look) ── */
.panel-alert-danger {
    background: rgba(220, 38, 38, 0.08);
    border: 1px solid rgba(220, 38, 38, 0.30);
    border-radius: 10px;
    padding: 12px 14px;
    color: var(--danger-strong);
    font-size: 13px;
    margin-bottom: 12px;
    display: flex;
    align-items: center;
    gap: 8px;
}
.panel-alert-success {
    background: rgba(13, 101, 88, 0.08);
    border: 1px solid rgba(13, 101, 88, 0.30);
    border-radius: 10px;
    padding: 12px 14px;
    color: #0D6558;
    font-size: 13px;
    margin-bottom: 12px;
    display: flex;
    align-items: center;
    gap: 8px;
}

/* ── Empty state ── */
.empty-cell { padding: 40px 20px; text-align: center; color: #6A6B6C; }

/* ── Control de visibilidad por JS ── */
.krav-hidden { display: none !important; }

/* ── Scrollbar fino ── */
.custom-scrollbar::-webkit-scrollbar { width: 4px; height: 4px; }
.custom-scrollbar::-webkit-scrollbar-track { background: transparent; }
.custom-scrollbar::-webkit-scrollbar-thumb { background: #e4e4e7; border-radius: 4px; }
.custom-scrollbar::-webkit-scrollbar-thumb:hover { background: #d4d4d8; }


/* ───────────── DARK MODE — PANEL COMPONENTS ─────────────
   Replica el comportamiento previo (los overrides viejos apuntaban a las
   clases Tailwind hardcodeadas ``bg-white`` / ``bg-[#F1F1F1]`` / etc.).
   Ahora que esas superficies son clases propias, el override va aquí. */
html.dark-mode .panel-card,
body.dark-mode .panel-card { background: var(--surface-2) !important; }

html.dark-mode .panel-card-inner,
body.dark-mode .panel-card-inner { background: var(--surface) !important; }

html.dark-mode .panel-card-head,
body.dark-mode .panel-card-head { background: var(--surface-2) !important; }
html.dark-mode .panel-card-head.panel-card-head--danger,
body.dark-mode .panel-card-head.panel-card-head--danger { background: rgba(220, 38, 38, 0.06) !important; }
html.dark-mode .panel-card-head.panel-card-head--warm,
body.dark-mode .panel-card-head.panel-card-head--warm { background: rgba(176, 109, 71, 0.08) !important; }

/* El color del título/meta base se adapta a dark, PERO las variantes
   --danger / --warm conservan su color semántico en ambos modos
   (antes eran estilos inline, que ganaban siempre). */
html.dark-mode .panel-card-title:not(.panel-card-title--danger):not(.panel-card-title--warm) h2,
body.dark-mode .panel-card-title:not(.panel-card-title--danger):not(.panel-card-title--warm) h2 { color: var(--text) !important; }

html.dark-mode .panel-card-meta:not(.panel-card-meta--danger):not(.panel-card-meta--warm),
body.dark-mode .panel-card-meta:not(.panel-card-meta--danger):not(.panel-card-meta--warm) { color: var(--text-dim) !important; }

/* Iconos de cabecera de card. El gris oscuro (#1F2937) del modo claro se
   PIERDE sobre la superficie oscura (queda casi invisible) → se aclaran a
   --text, conservando la relación con el título que hay en claro. Las
   variantes semánticas mantienen su color, sólo se sube la luminosidad. */
html.dark-mode .panel-card-title:not(.panel-card-title--danger):not(.panel-card-title--warm) > i,
body.dark-mode .panel-card-title:not(.panel-card-title--danger):not(.panel-card-title--warm) > i { color: var(--text) !important; }
html.dark-mode .panel-card-title--success > i,
body.dark-mode .panel-card-title--success > i { color: #4ADE80 !important; }
html.dark-mode .panel-card-title--warm > i,
body.dark-mode .panel-card-title--warm > i { color: #E9A878 !important; }

/* Status chip cálido (terracota): el texto #92400E es ilegible sobre dark. */
html.dark-mode .krav-status-chip--warm,
body.dark-mode .krav-status-chip--warm { color: #FBBF24 !important; }

/* Grises/teal de Tailwind con hex duro que aún no tenían override y se
   usan como color de ICONO y de etiquetas en los paneles. */
html.dark-mode .text-\[\#6A6B6C\],
body.dark-mode .text-\[\#6A6B6C\] { color: var(--text-dim) !important; }
html.dark-mode .text-\[\#1F2937\],
body.dark-mode .text-\[\#1F2937\] { color: var(--text) !important; }
html.dark-mode .text-\[\#0D6558\],
body.dark-mode .text-\[\#0D6558\] { color: #4ADE80 !important; }
html.dark-mode .text-\[\#B06D47\],
body.dark-mode .text-\[\#B06D47\] { color: #E9A878 !important; }

/* Chips semánticos en dark: el azul/rojo oscuro del texto se pierde sobre
   fondo oscuro → subir luminosidad. (success/warn ya tienen override arriba.) */
html.dark-mode .chip.tu,
body.dark-mode .chip.tu {
    background: rgba(96, 165, 250, 0.16) !important;
    color: #93c5fd !important;
    border-color: rgba(147, 197, 253, 0.35) !important;
}
html.dark-mode .chip.danger,
body.dark-mode .chip.danger { color: var(--danger) !important; }

/* (El estado deshabilitado del botón "Ejecutar reset" lo maneja ahora
   el sistema .btn vía --btn-disabled-* — sin override específico.) */


/* ================================================================
   BUTTON SYSTEM (Kravio v10) — paleta de botones light + dark
   ----------------------------------------------------------------
   Jerarquía (de mayor a menor énfasis):
     1. .btn-primary    — acción principal (una por vista)
     2. .btn-secondary  — acción alternativa (outline)
     3. .btn-ghost      — acción menor / cancelar (texto, sin caja)
     4. .btn-danger     — acción DESTRUCTIVA (rojo, RESERVADO)

   Estados cubiertos por TODAS las variantes:
     hover / active (scale .97) / focus-visible (anillo) / disabled.

   Todo themeable por tokens (--btn-*). Un solo cambio de token
   re-tiñe light y dark a la vez.
   ================================================================ */

:root {
    /* 1 · Primary — color de ACCIÓN (azul) */
    --btn-primary-bg:       var(--ice-600);
    --btn-primary-fg:       #FFFFFF;
    --btn-primary-hover:    var(--ice-700);
    --btn-primary-active:   var(--ice-800);
    /* Filo del sólido: un paso más oscuro que el relleno en claro. */
    --btn-primary-border:       var(--ice-800);
    --btn-primary-border-hover: var(--ice-900);

    /* 2 · Secondary — azul tonal (relleno suave) */
    --btn-secondary-bg:     var(--ice-100);
    --btn-secondary-fg:     var(--ice-800);
    --btn-secondary-border: var(--ice-200);
    --btn-secondary-hover:  var(--ice-200);

    /* 3 · Ghost — azul texto (sin caja) */
    --btn-ghost-fg:         var(--ice-600);
    --btn-ghost-fg-strong:  var(--ice-800);
    --btn-ghost-hover:      var(--ice-50);

    /* 4 · Danger — destructivo (rojo reservado) */
    --btn-danger-bg:        #DC2626;
    --btn-danger-fg:        #FFFFFF;
    --btn-danger-hover:     #B91C1C;

    /* 5 · Success — confirmar / agregar (verde) */
    --btn-success-bg:       #16A34A;
    --btn-success-fg:       #FFFFFF;
    --btn-success-hover:    #15803D;

    /* Estados compartidos */
    --btn-focus-ring:       rgba(37, 99, 235, 0.35);
    --btn-disabled-bg:      #F1F1F1;
    --btn-disabled-fg:      #9C9C9C;
    --btn-disabled-border:  #E5E5E5;

    /* Profundidad — un solo juego de sombras para TODOS los botones.
       Reposo: una sombra corta (el botón se apoya en la superficie) + un
       filo de luz arriba (`inset`) que simula el bisel. Hover: sube 1 px y
       la sombra se abre. Activo: se hunde y el `inset` pasa a sombra
       interna. Así el botón tiene cuerpo sin dejar de ser plano. */
    --btn-lift:             -1px;
    /* Relleno de los botones SIN variante (Seguimiento, iconos sueltos): en
       claro el `.btn` base es blanco y sobre una card blanca desaparecía. */
    --btn-plain-bg:         var(--surface-2);
    --btn-plain-bg-hover:   var(--surface-3);
    /* Color del HALO de los botones sólidos, como lista RGB para poder
       teñirlo por variante: `rgba(var(--btn-glow), .5)`. El primario (azul) es
       el valor por defecto; Pago lo pinta de verde en su propia regla. */
    --btn-glow:             52, 112, 143;
    --btn-shadow-rest:      0 1px 1px rgba(15, 23, 42, .06),
                            0 2px 4px rgba(15, 23, 42, .05),
                            inset 0 1px 0 rgba(255, 255, 255, .70);
    --btn-shadow-hover:     0 2px 4px rgba(15, 23, 42, .08),
                            0 6px 14px rgba(15, 23, 42, .10),
                            inset 0 1px 0 rgba(255, 255, 255, .80);
    --btn-shadow-active:    inset 0 2px 4px rgba(15, 23, 42, .16),
                            0 1px 0 rgba(255, 255, 255, .45);
    /* Los SÓLIDOS (primary/danger/success) no llevan bisel blanco: su sombra
       exterior se tiñe de su propio color para que el relleno se lea como
       cuerpo y no como un rectángulo pegado al fondo. */
    --btn-shadow-solid-rest:  0 1px 2px rgba(15, 23, 42, .18),
                              0 3px 8px rgba(var(--btn-glow), .28),
                              inset 0 1px 0 rgba(255, 255, 255, .16);
    --btn-shadow-solid-hover: 0 2px 5px rgba(15, 23, 42, .22),
                              0 8px 18px rgba(var(--btn-glow), .34),
                              inset 0 1px 0 rgba(255, 255, 255, .22);
}

html.dark-mode,
body.dark-mode {
    /* Primary azul (se mantiene el blanco en texto; azul legible sobre dark) */
    /* En dark el texto del primario es blanco: se usa el mismo -600 (5.4:1)
       en vez del -400, que pedía tinta oscura. El hover NO sube a -500:
       #5E9BBE con blanco se queda en 3:1 y el botón se deslavaba — el
       feedback va en el filo y en la sombra teñida. */
    --btn-primary-bg:       var(--ice-600);
    --btn-primary-fg:       #FFFFFF;
    --btn-primary-hover:    var(--ice-600);
    --btn-primary-active:   var(--ice-700);
    /* Filo del sólido: en dark va un paso ARRIBA para despegarlo de la
       superficie (abajo se fundiría con el fondo). */
    --btn-primary-border:       var(--ice-400);
    --btn-primary-border-hover: var(--ice-300);

    --btn-secondary-bg:     rgba(37, 99, 235, 0.16);
    --btn-secondary-fg:     var(--ice-200);
    --btn-secondary-border: rgba(96, 165, 250, 0.35);
    --btn-secondary-hover:  rgba(37, 99, 235, 0.26);

    --btn-ghost-fg:         var(--ice-300);
    --btn-ghost-fg-strong:  var(--ice-200);
    --btn-ghost-hover:      rgba(37, 99, 235, 0.14);

    --btn-danger-bg:        #DC2626;
    --btn-danger-fg:        #FFFFFF;
    --btn-danger-hover:     #EF4444;

    --btn-success-bg:       #16A34A;
    --btn-success-fg:       #FFFFFF;
    --btn-success-hover:    #22C55E;

    --btn-focus-ring:       rgba(96, 165, 250, 0.45);
    --btn-disabled-bg:      #232730;
    --btn-disabled-fg:      #6B7280;
    --btn-disabled-border:  rgba(255, 255, 255, 0.08);

    /* Relleno de los botones sin variante: un paso ARRIBA de `--surface-2`
       (#232730 → #2A2F37). Con el gris anterior se leían «apagados» y el
       botón se confundía con la card. El hover va otro paso arriba (antes
       iba hacia abajo, que es al revés en un tema oscuro). */
    --btn-plain-bg:         #2A2F37;
    --btn-plain-bg-hover:   #343A45;

    /* Profundidad en dark: la sombra NEGRA sobre fondo negro no se ve, así que
       aquí el relieve lo da la LUZ. Tres piezas por botón:
         · filo de luz arriba (inset blanco) — el bisel iluminado;
         · costura oscura abajo (inset negro) — el canto con grosor;
         · sombra de contacto + halo, más densos que en claro.
       Sin el filo, el botón se lee plano aunque la sombra exista. */
    --btn-shadow-rest:      0 3px 8px rgba(0, 0, 0, .62),
                            0 8px 20px rgba(0, 0, 0, .42),
                            inset 0 1px 0 rgba(255, 255, 255, .32),
                            inset 0 2px 2px -1px rgba(255, 255, 255, .14),
                            inset 0 -1px 0 rgba(0, 0, 0, .65);
    --btn-shadow-hover:     0 4px 10px rgba(0, 0, 0, .66),
                            0 14px 30px rgba(0, 0, 0, .52),
                            inset 0 1px 0 rgba(255, 255, 255, .44),
                            inset 0 2px 2px -1px rgba(255, 255, 255, .18),
                            inset 0 -1px 0 rgba(0, 0, 0, .65);
    --btn-shadow-active:    inset 0 2px 6px rgba(0, 0, 0, .75),
                            inset 0 1px 0 rgba(0, 0, 0, .60),
                            0 1px 0 rgba(255, 255, 255, .06);
    /* Los sólidos tiñen su halo del acento (el negro puro no existe sobre
       fondo oscuro) y llevan el mismo par filo/costura. */
    --btn-shadow-solid-rest:  0 3px 8px rgba(0, 0, 0, .62),
                              0 8px 20px rgba(var(--btn-glow), .50),
                              inset 0 1px 0 rgba(255, 255, 255, .38),
                              inset 0 2px 2px -1px rgba(255, 255, 255, .16),
                              inset 0 -1px 0 rgba(0, 0, 0, .45);
    --btn-shadow-solid-hover: 0 4px 10px rgba(0, 0, 0, .66),
                              0 14px 30px rgba(var(--btn-glow), .60),
                              inset 0 1px 0 rgba(255, 255, 255, .46),
                              inset 0 2px 2px -1px rgba(255, 255, 255, .20),
                              inset 0 -1px 0 rgba(0, 0, 0, .45);
}

/* ── Base ──
   OJO: existe un `.btn` LEGACY (pill, uppercase) que siguen usando
   bases / asesores / dashboard / login. Estas reglas van SCOPED a
   `.page-container` para NO tocarlos. Al migrar un panel, se le pone
   `.page-container` y adopta esta paleta automáticamente. */
.page-container .btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    height: 32px;
    padding: 0 13px;
    border-radius: 9px;
    border: 1px solid transparent;
    font-family: var(--font-sans);
    font-size: 12px;
    font-weight: 600;
    line-height: 1;
    letter-spacing: normal;
    text-transform: none;
    white-space: nowrap;
    cursor: pointer;
    text-decoration: none;
    box-shadow: var(--btn-shadow-rest);
    transition: background-color .16s cubic-bezier(.23, 1, .32, 1),
                border-color .16s cubic-bezier(.23, 1, .32, 1),
                color .16s cubic-bezier(.23, 1, .32, 1),
                box-shadow .18s cubic-bezier(.23, 1, .32, 1),
                transform .12s cubic-bezier(.23, 1, .32, 1);
}
.page-container .btn > i { font-size: 14px; }
/* Hover: el botón SUBE un píxel, la sombra se abre y el color se aclara (o
   se oscurece, según la variante). Nada de relleno nuevo: el matiz va en
   `background-color` de cada variante, aquí solo el movimiento y la luz. */
.page-container .btn:hover:not(:disabled):not([aria-disabled="true"]) {
    transform: translateY(var(--btn-lift));
    box-shadow: var(--btn-shadow-hover);
}
/* Click: se hunde de verdad — vuelve al plano, encoge un 2 % y la sombra
   pasa a ser INTERNA (como si se presionara el bisel). */
.page-container .btn:active:not(:disabled):not([aria-disabled="true"]) {
    transform: translateY(0) scale(0.97);
    box-shadow: var(--btn-shadow-active);
    transition-duration: .07s;
}
.page-container .btn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--btn-focus-ring), var(--btn-shadow-rest); }
.page-container .btn:disabled,
.page-container .btn[aria-disabled="true"] {
    background: var(--btn-disabled-bg);
    color: var(--btn-disabled-fg);
    border-color: var(--btn-disabled-border);
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
}

/* ── 1 · Primary ──
   Es el ÚNICO botón con relleno sólido de acción y tiene que leerse como
   tal en los dos temas: claro lo deja sobre el glaciar profundo con un filo
   de `--ice-800` y sombra teñida; en dark el mismo relleno pero con el filo
   un paso ARRIBA (`--ice-400`) para que el bloque no se funda con la
   superficie oscura. */
.page-container .btn-primary {
    background: var(--btn-primary-bg);
    color: var(--btn-primary-fg);
    border-color: var(--btn-primary-border);
    box-shadow: var(--btn-shadow-solid-rest);
}
.page-container .btn-primary:hover:not(:disabled):not([aria-disabled="true"]) {
    background: var(--btn-primary-hover);
    border-color: var(--btn-primary-border-hover);
    box-shadow: var(--btn-shadow-solid-hover);
}
/* Al presionar, `:hover` y `:active` conviven: esta regla va DESPUÉS de la
   de hover para que gane el estado hundido (si no, el sólido se quedaba con
   la sombra de hover mientras se aplastaba). */
.page-container .btn-primary:active:not(:disabled):not([aria-disabled="true"]) {
    background: var(--btn-primary-active);
    box-shadow: var(--btn-shadow-active);
}

/* Quien apagó el movimiento sigue viendo el relieve y el cambio de color,
   pero el botón no salta ni se encoge. */
@media (prefers-reduced-motion: reduce) {
    .page-container .btn { transition: background-color .16s ease, border-color .16s ease, color .16s ease; }
    .page-container .btn:hover:not(:disabled):not([aria-disabled="true"]),
    .page-container .btn:active:not(:disabled):not([aria-disabled="true"]) { transform: none; }
}

/* ── 2 · Secondary ── */
.page-container .btn-secondary { background: var(--btn-secondary-bg); color: var(--btn-secondary-fg); border-color: var(--btn-secondary-border); }
.page-container .btn-secondary:hover:not(:disabled) { background: var(--btn-secondary-hover); }

/* ── 3 · Ghost ── */
.page-container .btn-ghost { background: transparent; color: var(--btn-ghost-fg); }
.page-container .btn-ghost:hover:not(:disabled) { background: var(--btn-ghost-hover); color: var(--btn-ghost-fg-strong); }

/* ── 4 · Danger (destructivo) ── */
.page-container .btn-danger { background: var(--btn-danger-bg); color: var(--btn-danger-fg); }
.page-container .btn-danger:hover:not(:disabled) { background: var(--btn-danger-hover); }

/* ── 5 · Success (confirmar / agregar) ── */
.page-container .btn-success { background: var(--btn-success-bg); color: var(--btn-success-fg); }
.page-container .btn-success:hover:not(:disabled) { background: var(--btn-success-hover); }

/* ── Tamaños ── */
.page-container .btn-sm { height: 26px; padding: 0 9px; font-size: 11px; gap: 5px; border-radius: 7px; }
.page-container .btn-sm > i { font-size: 12px; }
.page-container .btn-lg { height: 44px; padding: 0 20px; font-size: 13px; border-radius: 10px; }
.page-container .btn-lg > i { font-size: 16px; }
.page-container .btn-block { width: 100%; }

/* Icono que gira mientras una acción viaja al servidor (feedback de carga
   del submit). Se desactiva con `prefers-reduced-motion`. */
.btn-spin { animation: btnSpin .8s linear infinite; }
@keyframes btnSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
    .btn-spin { animation: none; }
}

/* ── Botón CUADRADO (solo ícono) ──
   Acciones compactas donde el ícono basta: crear usuario (verde) y abrir
   la lista de usuarios. El `title` + `aria-label` son obligatorios: sin
   texto visible, son la única etiqueta para teclado y lectores. */
.page-container .btn-sq {
    position: relative;
    width: 34px;
    height: 34px;
    padding: 0;
    gap: 0;
}
.page-container .btn-sq > i { font-size: 15px; }

/* Badge numérico sobre el botón (total de usuarios). Usa el "ink" del
   selector segmentado: negro en claro, claro en dark. */
.btn-badge {
    position: absolute;
    top: -6px;
    right: -6px;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
    background: var(--seg-sel-bg);
    color: var(--seg-sel-fg);
    border: 2px solid var(--surface);
    font-family: var(--font-sans);
    font-size: 10px;
    font-weight: 600;
    line-height: 1;
    font-variant-numeric: tabular-nums;
    pointer-events: none;
}

/* ── Tooltip propio (sustituye al nativo de `title`) ──
   El globo de `title` lo dibuja el navegador con ~1 s de retardo y no se
   puede configurar; éste aparece casi al instante. Se alinea al BORDE
   DERECHO y hacia ARRIBA para no salirse del `.panel-card-inner`, que
   recorta con overflow:hidden. */
.tip { position: relative; }
.tip::after {
    content: attr(data-tip);
    position: absolute;
    right: 0;
    bottom: calc(100% + 9px);
    z-index: 40;
    padding: 5px 9px;
    border-radius: 7px;
    background: var(--seg-sel-bg);
    color: var(--seg-sel-fg);
    font-family: var(--font-sans);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.01em;
    text-transform: none;
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transform: translateY(3px);
    transition: opacity .1s ease, transform .1s ease;
    transition-delay: 0s;
}
.tip:hover::after,
.tip:focus-visible::after {
    opacity: 1;
    transform: translateY(0);
}

/* ── Dialog reutilizable (top layer) ──
   El cuerpo scrollea solo; la cabecera queda fija. */
.dlg {
    width: min(940px, calc(100vw - 40px));
    padding: 0;
    border: 1px solid var(--border);
    border-radius: 20px;
    background: var(--surface);
    color: var(--text);
    overflow: hidden;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.06),
                0 24px 64px rgba(15, 23, 42, 0.24);
}
/* La entrada es SOLO opacidad a propósito: un `transform` en el <dialog>
   lo convierte en el *containing block* de los `.popover-body`
   (position: fixed) que viven dentro (las acciones por usuario), y quedarían
   posicionados respecto al dialog en vez del viewport. */
@keyframes dlgFadeIn { from { opacity: 0; } to { opacity: 1; } }
.dlg[open] {
    display: flex;
    flex-direction: column;
    max-height: 85vh;
    animation: dlgFadeIn .14s ease;
}
.dlg::backdrop {
    background: rgba(15, 17, 21, 0.42);
    backdrop-filter: blur(3px);
    -webkit-backdrop-filter: blur(3px);
}
/* El dialog recibe el foco al abrirse (tabindex=-1): sin anillo visible,
   el foco se ve en el control que el usuario tabule. */
.dlg:focus { outline: none; }
.dlg-head {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 13px 18px;
    background: var(--surface-2);
    border-bottom: 1px solid var(--border);
}
.dlg-title { display: flex; align-items: center; gap: 8px; min-width: 0; }
.dlg-title > i { font-size: 16px; color: var(--text); }
.dlg-title h2 {
    margin: 0;
    font-family: var(--font-sans);
    font-size: 15px;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--text);
}
.dlg-title .dlg-count {
    font-size: 11px;
    font-weight: 400;
    color: var(--text-dim-2);
    font-variant-numeric: tabular-nums;
}
.dlg-close {
    flex: none;
    width: 30px;
    height: 30px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border);
    border-radius: 999px;
    background: var(--surface);
    color: var(--text-dim);
    font-size: 17px;
    line-height: 1;
    cursor: pointer;
    transition: border-color .18s ease, color .18s ease, background .18s ease;
}
.dlg-close:hover { border-color: var(--border-strong); color: var(--text); background: var(--surface-3); }
.dlg-close:focus-visible { outline: 2px solid var(--btn-primary-bg); outline-offset: 2px; }
.dlg-body { flex: 1 1 auto; min-height: 0; overflow: auto; }

/* ── Confirmación del sistema (`window.edxConfirm`) ──
   El mismo <dialog> de los paneles, en versión compacta: un solo patrón para
   «¿seguro que…?» en todo el sistema (antes eran `window.confirm` nativos).
   El dialog se cuelga del <body> (no de `.page-container`), así que los
   botones se pintan aquí con los MISMOS tokens de la paleta de botones
   (§8.4.7): rojo sólido para lo destructivo, azul sólido para lo demás y un
   Cancelar sin relleno que recede. */
.dlg--confirm { width: min(430px, calc(100vw - 32px)); }
.dlg--confirm .dlg-title > i { color: var(--danger); }
.dlg--confirm--primary .dlg-title > i { color: var(--text); }
.dlg--confirm-body {
    padding: 18px 20px 2px;
    font-size: 13.5px;
    line-height: 1.55;
    color: var(--text);
}
.dlg--confirm-foot {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    padding: 16px 20px 18px;
}
.dlg--confirm-foot .btn {
    flex: 1 1 140px;
    min-height: 38px;
    padding: 0 14px;
    border-radius: 9px;
    font-size: 12px;
    font-weight: 600;
    /* La etiqueta va en UNA línea: si no cabe, los botones bajan a dos filas
       a lo ancho en vez de partir «BORRAR CORRIDA» en dos renglones. */
    white-space: nowrap;
}
@media (max-width: 420px) {
    .dlg--confirm-foot .btn { font-size: 11.5px; letter-spacing: 0.01em; }
}
.dlg--confirm [data-si] {
    background: var(--btn-danger-bg);
    color: var(--btn-danger-fg);
    border-color: transparent;
}
.dlg--confirm [data-si]:hover:not(:disabled) { background: var(--btn-danger-hover); }
.dlg--confirm--primary [data-si] {
    background: var(--btn-primary-bg);
    color: var(--btn-primary-fg);
}
.dlg--confirm--primary [data-si]:hover:not(:disabled) { background: var(--btn-primary-hover); }
.dlg--confirm [data-no] {
    background: transparent;
    color: var(--text-dim);
    border-color: var(--border-strong);
}
.dlg--confirm [data-no]:hover:not(:disabled) {
    background: var(--surface-2);
    color: var(--text);
}
.dlg--confirm .btn:focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--btn-focus-ring);
}

/* ── Resueltas: sección expandible DENTRO de la card de Peticiones ──
   Antes era una card propia que ocupaba una fila completa; ahora es la
   parte baja de la misma card (separada por una línea). */
.pj-done { border-top: 1px solid var(--border); }
.pj-done > summary {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px 20px;
    background: var(--surface-2);
    color: var(--text-dim);
    cursor: pointer;
    list-style: none;
    transition: background .16s ease;
}
.pj-done > summary::-webkit-details-marker { display: none; }
.pj-done > summary::marker { content: ''; }
.pj-done > summary:hover { background: var(--surface-3); }
.pj-done > summary > i:first-child { font-size: 14px; color: #0D6558; }
html.dark-mode .pj-done > summary > i:first-child,
body.dark-mode .pj-done > summary > i:first-child { color: #4ADE80; }
.pj-done-t {
    font-family: var(--font-sans);
    font-size: 11.5px;
    font-weight: 600;
    letter-spacing: 0.01em;
    color: var(--text);
}
.pj-done-n {
    margin-left: auto;
    font-size: 11px;
    font-weight: 400;
    color: var(--text-dim-2);
    font-variant-numeric: tabular-nums;
}
.pj-done-c { font-size: 12px; color: var(--text-dim-2); transition: transform .18s ease; }
.pj-done[open] .pj-done-c { transform: rotate(180deg); }

/* ── Lista de usuarios (dialog) ──
   Más estrecho que el dialog genérico: 3 columnas cortas no necesitan 940px
   (el espacio sobrante era el que se veía "vacío" a lo largo). */
.dlg--users { width: min(660px, calc(100vw - 40px)); }

/* Modificadores de la tabla, para no tocar .krav-tabla del resto de paneles. */
.krav-tabla--center thead th,
.krav-tabla--center tbody td,
.krav-tabla--center thead th.right,
.krav-tabla--center tbody td.right { text-align: center; }
.krav-tabla--center thead th { padding: 10px 12px; }

/* Pastilla de rol (sólo lectura: el rol ya no se edita desde aquí). */
.role-pill {
    display: inline-flex;
    align-items: center;
    padding: 3px 10px;
    border-radius: 999px;
    background: var(--surface-2);
    border: 1px solid var(--border);
    color: var(--text-dim);
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.01em;
    white-space: nowrap;
}

/* Columna Acciones: centrada y sin el margen que trae .action-popover. */
.usr-actions {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
}
.usr-actions .action-popover { margin-left: 0; }

/* ── Ojo para ver la contraseña (dentro del popover) ──
   El <span> interior de un <label> del popover hereda uppercase y tracking:
   hay que neutralizarlos o la contraseña se vería en mayúsculas. */
.pw-field {
    position: relative;
    display: block;
    text-transform: none;
    letter-spacing: normal;
    font-weight: 400;
}
.popover-body .pw-field input { padding-right: 36px; }
.pw-eye {
    position: absolute;
    top: 50%;
    right: 5px;
    transform: translateY(-50%);
    width: 26px;
    height: 26px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 0;
    border-radius: 6px;
    background: transparent;
    color: var(--text-dim-2);
    cursor: pointer;
    transition: color .15s ease, background .15s ease;
}
.pw-eye i { font-size: 14px; }
.pw-eye:hover { color: var(--text); background: var(--surface-2); }
.pw-eye:focus-visible { outline: 2px solid var(--btn-primary-bg); outline-offset: 1px; }


/* Movimiento reducido: el contenido entra sin fade. */
@media (prefers-reduced-motion: reduce) {
    html.edx-fade .edx-main { animation: none; }
}

/* Cargador de navegación: **puntitos del logo** en aro, SIN fondo y en
   color invertido por tema (sustituye a la barra de 3 px de arriba). Feedback
   inmediato al cambiar de URL (sidebar, tabs, botones) sin mover una sola coma
   del layout. Se enciende tras 110 ms para no parpadear en navegaciones
   instantáneas y se apaga en pageshow (incluye bfcache) o htmx:afterSettle.
   Los puntitos son el lenguaje de círculos de la E de Expectra (logo_svg):
   una cabeza encendida recorre el aro con una cola de dos puntos. Sin disco:
   los puntos van en --text, así que son oscuros sobre el panel claro y claros
   sobre el oscuro. */
.edx-loader {
    position: fixed;
    inset: 0;
    z-index: 70;
    display: grid;
    place-items: center;
    opacity: 0;
    pointer-events: none;
    transition: opacity .14s ease-out;
    /* Sin fondo: los puntitos se pintan con --text, que se autoinvierte por
       tema (oscuros sobre el panel claro, claros sobre el oscuro). */
    --loader-ring: var(--text);
}
.edx-loader.is-on { opacity: 1; }
/* Centrado en el ÁREA DE CONTENIDO, no en el viewport: el rail del sidebar
   (220 px) corre el centro óptico a la izquierda. En el shell móvil no hay
   rail, así que ahí se centra en la pantalla completa. */
body.edx-kravio:not(.edx-movil) .edx-loader { padding-left: 220px; }

/* Aro pelado: 54 px de caja, SIN disco ni sombra — sólo los puntitos. */
.edx-loader-dial {
    position: relative;
    width: 54px;
    height: 54px;
    border-radius: 50%;
    transform: scale(.9);
    transition: transform .2s cubic-bezier(.23, 1, .32, 1);
}
.edx-loader.is-on .edx-loader-dial { transform: none; }

/* Los 12 puntitos: mismas posiciones fijas (30° cada uno) en un aro de 18 px
   y una CABEZA que se enciende y se apaga rápido — sólo 2-3 puntos tienen luz
   a la vez, y eso es lo que hace leer el giro (con un degradado suave el aro
   parece quieto). El retardo negativo acumulativo mueve la cabeza en sentido
   horario a 0.95 s por vuelta. `linear`: movimiento continuo. */
.edx-loader-dot {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 5px;
    height: 5px;
    margin-top: -2.5px;
    margin-left: -2.5px;
    border-radius: 50%;
    background: var(--loader-ring);
    transform: rotate(calc(var(--i) * 30deg)) translateY(-19px);
    opacity: .10;
    animation: edx-loader-dot .95s linear infinite;
    animation-delay: calc(var(--i) * -0.07916666s);
    animation-play-state: paused;
}
.edx-loader.is-on .edx-loader-dot { animation-play-state: running; }
/* Cola CORTA: la cabeza (1) y dos puntos medios; el resto casi apagado. Una
   cola larga y pareja hace que el aro se lea como un anillo estático. */
@keyframes edx-loader-dot {
    0%   { opacity: 1;   scale: 1.12; }
    12%  { opacity: .45; scale: 1;    }
    32%  { opacity: .14; scale: .92;  }
    100% { opacity: .10; scale: .88;  }
}
@media (prefers-reduced-motion: reduce) {
    .edx-loader-dial,
    .edx-loader.is-on .edx-loader-dial { transform: none; transition: none; }
    /* La ola se queda: es la única señal de que algo está cargando. Sin el
       escalado, para no mover masa. */
    @keyframes edx-loader-dot {
        0%   { opacity: 1;   }
        12%  { opacity: .45; }
        32%  { opacity: .14; }
        100% { opacity: .10; }
    }
}

/* ───────────── Avisos flotantes (toasts) ─────────────
   Patrón ÚNICO para todos los avisos del sistema: la pastilla que nació en
   el toggle de Seguimiento del Detalle, ahora global (`window.edxToast`).
   Colores invertidos — pastilla con --text y tinta --bg — para que el
   mensaje se lea sobre cualquier panel y en los dos temas.
   Entrada/salida por TRANSICIÓN (no keyframes): los avisos se disparan
   seguidos y una transición sí se puede interrumpir. La salida es más
   rápida que la entrada. */
.edx-toasts {
    position: fixed;
    left: 50%;
    bottom: 26px;
    transform: translateX(-50%);
    z-index: 95;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    width: max-content;
    max-width: min(520px, calc(100vw - 32px));
    pointer-events: none;
}
.edx-toast {
    --toast-ink: var(--text);
    --toast-bg: var(--bg);
    --toast-tone: var(--toast-bg);
    display: flex;
    align-items: center;
    gap: 10px;
    max-width: 100%;
    padding: 10px 18px 10px 15px;
    border-radius: 999px;
    background: var(--toast-ink);
    color: var(--toast-bg);
    box-shadow:
        inset 0 0 0 1px rgba(255, 255, 255, .06),
        0 1px 2px rgba(9, 12, 18, .18),
        0 16px 40px rgba(9, 12, 18, .24);
    font-size: 12.5px;
    font-weight: 600;
    line-height: 1.4;
    letter-spacing: -0.005em;
    text-align: left;
    pointer-events: auto;
    cursor: default;
    opacity: 0;
    transform: translateY(10px) scale(.98);
    transition:
        opacity .18s cubic-bezier(.23, 1, .32, 1),
        transform .18s cubic-bezier(.23, 1, .32, 1);
}
.edx-toast.is-in { opacity: 1; transform: none; }
.edx-toast.is-out {
    opacity: 0;
    transform: translateY(4px) scale(.99);
    transition-duration: .12s;
}
.edx-toast__ico {
    flex: 0 0 auto;
    font-size: 15px;
    line-height: 1;
    color: var(--toast-tone);
}
.edx-toast__txt { min-width: 0; }

/* Tono: sólo el icono lleva color. Un verde/rojo saturado encima de la
   pastilla invertida pierde contraste, así que los tonos cambian con el tema
   (claros sobre pastilla oscura, profundos sobre pastilla clara). */
.edx-toast--success { --toast-tone: #22C55E; }
.edx-toast--error   { --toast-tone: #F87171; }
.edx-toast--info    { --toast-tone: var(--ice-300); }
html.dark-mode .edx-toast--success,
body.dark-mode .edx-toast--success { --toast-tone: #15803D; }
html.dark-mode .edx-toast--error,
body.dark-mode .edx-toast--error   { --toast-tone: #B91C1C; }
html.dark-mode .edx-toast--info,
body.dark-mode .edx-toast--info    { --toast-tone: var(--ice-500); }

@media (prefers-reduced-motion: reduce) {
    .edx-toast { transform: none; transition: opacity .18s ease; }
    .edx-toast.is-out { transform: none; }
}


/* ================================================================
   Búsqueda global de cliente (topbar) — barra pill + droplist.
   Vive en base.html (shell) ⇒ estilos globales acá. Todo con tokens
   para que el claro y el dark salgan del mismo markup.
   ================================================================ */
.edx-search {
    position: relative;
    width: 100%;
    /* 646 px = los 760 anteriores −15 %: deja aire a la derecha para la mini
       card de cobranza sin mover la barra, que sigue centrada. */
    max-width: 646px;
    margin: 0 auto;
}
/* ── Chip de semana (topbar) ──
   Va a la IZQUIERDA de la barra sin desplazarla: .edx-search conserva su
   `margin: 0 auto` (sigue centrada) y el chip se ancla en absoluto al borde
   izquierdo de su contenedor. Es una pista de contexto, no un control: sin
   fondo fuerte ni sombra dura, color atenuado. Desaparece en angosto para no
   estorbar (por debajo, el hueco lateral ya no da para él). */
.edx-topbar { position: relative; }

/* ── Mini card de cobranza (topbar, derecha) ──
   Óvalo de la MISMA altura que la barra (48 px), anclado en absoluto al borde
   derecho del topbar: la búsqueda sigue centrada con su `margin: 0 auto`. Sólo
   dos cifras personales (hoy · semana), sin rótulo ni selector: el espacio es
   para los números. Por debajo de 1300 px el hueco lateral ya no alcanza y se
   oculta —igual que el chip de la semana— antes que encimarse sobre la barra. */
.edx-cobranza {
    position: absolute;
    right: 0;
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    gap: 14px;
    height: 48px;
    padding: 0 20px;
    /* Tope de ancho: con cifras de 8 dígitos el óvalo crecería hasta encimarse
       sobre la barra. Se acota y el JS baja la letra de los montos hasta que
       caben (mismo criterio que fitMoney() de Sanciones). */
    max-width: 196px;
    overflow: hidden;
    border-radius: 9999px;
    background: var(--surface);
    border: 2px solid var(--border-strong);
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04);
    font-family: var(--font-sans);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    user-select: none;
}
.edx-cobranza-stat {
    display: flex;
    flex-direction: column;
    justify-content: center;
    line-height: 1;
    min-width: 0;
}
.edx-cobranza-k {
    font-size: 8px;
    font-weight: 600;
    letter-spacing: 0.01em;
    color: var(--text-dim-2);
}
.edx-cobranza-v {
    margin-top: 3px;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--text);
}
.edx-cobranza-sep {
    width: 1px;
    height: 24px;
    background: var(--border);
}
@media (max-width: 1339px) {
    .edx-cobranza { display: none; }
}

.edx-week-chip {
    position: absolute;
    left: 0;
    top: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transform: translateY(-50%);
    min-width: 46px;
    height: 34px;
    padding: 0 12px;
    border-radius: 11px;
    background: var(--surface);
    border: 1px solid var(--border);
    font-family: var(--font-sans);
    font-size: 14px;
    font-weight: 600;
    line-height: 1;
    letter-spacing: .02em;
    font-variant-numeric: tabular-nums;
    color: var(--text-dim);
    user-select: none;
}
@media (max-width: 1024px) {
    .edx-week-chip { display: none; }
}
.edx-search-form { position: relative; display: block; }
.edx-search-icon {
    position: absolute;
    left: 20px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 16px;
    color: var(--text-dim-2);
    pointer-events: none;
}
.edx-search-input {
    width: 100%;
    height: 48px;
    border-radius: 9999px;                 /* pill */
    background: var(--surface);
    border: 2px solid var(--border-strong);
    padding: 0 20px 0 48px;
    font-family: inherit;
    font-size: 14px;
    font-weight: 500;
    color: var(--text);
    outline: none;
    transition: border-color .18s var(--sidebar-easing),
                box-shadow .18s var(--sidebar-easing);
}
.edx-search-input::placeholder { color: var(--text-dim-2); }
.edx-search-input:focus {
    border-color: var(--ice-600);
    box-shadow: 0 0 0 4px rgba(37, 99, 235, 0.15);
}
/* Sin el botón nativo de limpiar en WebKit (no duplicar el ícono). */
.edx-search-input::-webkit-search-cancel-button { -webkit-appearance: none; }

/* ── Atajo dibujado dentro de la barra (⌘K · Ctrl+Alt+K) ──
   Las dos variantes viven en el DOM y el CSS enseña la de <html data-os>
   (lo fija el script del <head> antes del primer pintado). El padding
   derecho del input se reparte por plataforma para que el texto nunca pase
   por debajo de las teclas. */
html[data-os="mac"] .edx-search-input { padding-right: 78px; }
html[data-os="win"] .edx-search-input { padding-right: 128px; }

.edx-search-hint {
    position: absolute;
    right: 20px;                 /* 10px mas adentro del borde de la pill */
    top: 50%;
    transform: translateY(-50%);
    display: inline-flex;
    align-items: center;
    pointer-events: none;
    opacity: .6;                 /* pista, no contenido: no compite con el campo */
    transition: opacity .12s var(--sidebar-easing);
}
.edx-keys { display: inline-flex; align-items: center; gap: 4px; }
/* Sólo se pinta la variante del sistema actual. Si no hay data-os (JS
   apagado) no se pinta ninguna: mejor sin atajo que con el ajeno. */
html:not([data-os="mac"]) .edx-keys--mac { display: none; }
html:not([data-os="win"]) .edx-keys--win { display: none; }

.edx-key {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 22px;
    height: 22px;
    padding: 0 6px;
    border-radius: 6px;
    background: var(--surface-2);
    border: 1px solid var(--border-strong);
    border-bottom-width: 2px;              /* profundidad de tecla */
    font-family: var(--font-sans);
    font-size: 11px;
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0.02em;
    color: var(--text-dim);
}
.edx-key--word { padding: 0 7px; letter-spacing: 0.04em; }
.edx-key--sym { font-size: 13px; padding: 0 5px; }

/* Cumplido su propósito al entrar en la barra: estorba sobre el caret. */
.edx-search:focus-within .edx-search-hint { opacity: 0; }

/* Sin teclado físico (móvil/táctil) o en angosto el atajo no existe: fuera. */
@media (max-width: 720px), (hover: none) and (pointer: coarse) {
    .edx-search-hint { display: none; }
    html[data-os="mac"] .edx-search-input,
    html[data-os="win"] .edx-search-input { padding-right: 20px; }
}

.edx-search-results {
    position: absolute;
    top: calc(100% + 10px);
    left: 0;
    right: 0;
    z-index: 40;
    border-radius: 16px;
    background: var(--surface);
    border: 1px solid var(--border);
    box-shadow: 0 18px 48px rgba(0, 0, 0, 0.18);
    overflow: hidden;
}
.edx-search-results:empty { display: none; }

.edx-sr-list { list-style: none; margin: 0; padding: 6px; }
.edx-sr-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
    padding: 10px 12px;
    border-radius: 10px;
    color: var(--text);
    text-decoration: none;
    transition: background .12s var(--sidebar-easing);
}
.edx-sr-item:hover,
.edx-sr-item.is-active { background: var(--surface-2); color: var(--text); }
/* Coincidencia por teléfono: chip numérico a la izquierda del nombre para que se
   lea POR QUÉ salió esa cuenta (el número es de un tercero, la cuenta es la
   del crédito). */
.edx-sr-tel {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 2px 8px 2px 7px;
    border-radius: 9999px;
    background: var(--surface-3);
    border: 1px solid var(--border);
    font-family: var(--font-sans);
    font-size: 11px;
    font-weight: 600;
    color: var(--text-dim);
    letter-spacing: 0.01em;
}
.edx-sr-tel i { font-size: 11px; color: var(--text-dim-2); }
.edx-sr-name {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: -0.01em;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.edx-sr-id {
    flex-shrink: 0;
    font-family: var(--font-sans);
    font-size: 12px;
    font-weight: 600;
    color: var(--text-dim);
    letter-spacing: 0.02em;
}
/* Estado de cartera en el droplist: la cuenta SIGUE existiendo y se puede
   abrir; sólo se avisa que ya no viene en el AG del despacho. Neutro y con
   borde punteado (no es una alarma: Lista negra sí lo es). */
.edx-sr-ret {
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px 2px 7px;
    border: 1px dashed var(--border-strong);
    border-radius: 9999px;
    background: var(--surface-3);
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: 0.01em;
    color: var(--text-dim);
    white-space: nowrap;
}
.edx-sr-ret i { font-size: 10px; color: var(--text-dim-2); }
.edx-sr-empty {
    padding: 14px 16px;
    font-size: 13px;
    color: var(--text-dim-2);
}


/* ================================================================
   Estado "vacío / en diseño" para paneles nuevos (Reportes,
   Planchados, Métricas). Reutilizable dentro de .panel-card-inner.
   ================================================================ */
.ph-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 64px 24px;
    gap: 8px;
}
.ph-empty-badge {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 52px;
    height: 52px;
    border-radius: 14px;
    margin-bottom: 8px;
    background: var(--surface-2);
    border: 1px solid var(--border);
    color: var(--text-dim);
    font-size: 24px;
}
.ph-empty h2 {
    margin: 0;
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -0.02em;
    color: var(--text);
}
.ph-empty p {
    margin: 0;
    max-width: 460px;
    font-size: 13px;
    line-height: 1.55;
    color: var(--text-dim);
}
.ph-empty .ph-tag {
    margin-top: 12px;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 12px;
    border: 1px solid var(--border);
    border-radius: 9999px;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.01em;
    color: var(--text-dim-2);
}


/* ================================================================
   Bitácora de gestiones · Gestión de Crédito (detalle de cliente)
   ----------------------------------------------------------------
   Server-rendered (Django + Tailwind utilities del shell). Sin librería
   externa: el template pinta <table>, <thead>, <tbody> y los chips. Todo
   con tokens del proyecto, así que claro y dark salen del mismo markup.

   Clases:
     · .kg-toolbar / .kg-filtros / .kg-tabla / .kg-tbl   estructura
     · .kg-tam                                      tamaño de página
     · .kg-contador / -lbl / -num                    mini cards: Promesas pendientes ($) y Gestiones
     · .kg-col-fecha · .kg-f-dia / .kg-f-hora        celda de Fecha
     · .kg-evid                                     descarga de la evidencia
     · .kg-codes / .kg-code · .kg-code--res           chips de status
     · .kg-money                                     cifras
     · .kg-vacio / .kg-vacio-msg                     "—" y estado vacío
     · .kg-foot · .kg-page · .kg-foot-pages          paginación
   ================================================================ */

.kg-toolbar {
    padding: 12px 14px;
    border-bottom: 1px solid var(--border);
    background: var(--surface-2);
    border-top-left-radius: 0.75rem;
    border-top-right-radius: 0.75rem;
}
/* Dos niveles: el buscador ocupa TODO lo largo y, debajo, los controles
   (Filas · Promesas pendientes · Gestiones) van centrados. Misma altura en
   todos para que queden al ras; la jerarquía la dan ancho, peso y color.
   El layout no depende del largo del importe: el buscador ya no compite por
   el espacio, así que un `$99,999,999,999.90` no lo aplasta. */
.kg-filtros { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; row-gap: 10px; margin: 0; }
.kg-controles {
    display: flex;
    align-items: center;
    justify-content: center;   /* centrado en su propio renglón */
    flex-wrap: wrap;           /* si no cabe, envuelve: nunca desborda */
    gap: 10px;
    row-gap: 8px;
    flex: 1 0 100%;
    min-width: 0;
}
/* Conteo: mini card que cierra la fila. La etiqueta susurra (versalitas
   pequeñas), el número manda. Ambos en Cove. */
.kg-contador {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    height: 38px;
    padding: 0 13px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface);
    flex-shrink: 0;
}
.kg-contador-lbl {
    font-family: var(--font-sans);
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.01em;
    color: var(--text-dim-2);
}
.kg-contador-num {
    font-family: var(--font-sans);
    font-size: 17px;
    font-weight: 600;
    line-height: 1;
    color: var(--text);
    font-variant-numeric: tabular-nums;
}
.kg-tam {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    height: 38px;
    padding: 0 4px 0 12px;
    border: 1px solid var(--border);
    border-radius: 9999px;
    background: var(--surface-2);
    color: var(--text-dim);
    font-size: 11.5px;
}
.kg-tam select {
    /* la caja la dibuja .kg-tam: el select va limpio y sin chevron propio */
    min-height: 0; height: 100%; padding: 0 6px 0 0;
    background-image: none; border: 0; border-radius: 0; box-shadow: none;
    color: var(--text); font-family: inherit; font-size: 12px; font-weight: 600;
    cursor: pointer;
}
.kg-tam select:focus { outline: none; }

.kg-tabla { padding: 0 0 2px; overflow-x: auto; }
.kg-tbl {
    width: 100%;
    min-width: 980px;
    border-collapse: collapse;
    background: transparent;
    color: var(--text);
    font-family: inherit;
    font-size: 12.5px;
}
.kg-tbl thead th {
    background: var(--surface-2);
    border-bottom: 1px solid var(--border);
    color: var(--text-dim);
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: 0.01em;
    text-align: center;
    padding: 9px 12px;
    white-space: nowrap;
    border-top: 0;
}
.kg-tbl thead th.kg-der { text-align: center; }
.kg-tbl tbody tr {
    border-bottom: 1px solid var(--border);
    transition: background 120ms var(--sidebar-easing);
}
.kg-tbl tbody tr:last-child { border-bottom: 0; }
.kg-tbl tbody tr:hover { background: var(--surface-2); }
.kg-tbl tbody td {
    padding: 11px 12px;
    vertical-align: top;
    color: var(--text);
    text-align: center;
}
.kg-tbl tbody td.kg-der { text-align: center; }

/* Histórico de Pagos: 4 columnas, TODO centrado, fuente Cove y números
   un poco más grandes que el resto de la tabla. */
.kg-tbl.pg-tbl { min-width: 0; font-family: var(--font-sans); }
.kg-tbl.pg-tbl thead th,
.kg-tbl.pg-tbl thead th.kg-der { text-align: center; }
.kg-tbl.pg-tbl tbody td,
.kg-tbl.pg-tbl tbody td.kg-der { padding: 9px 12px; vertical-align: middle; text-align: center; }
.kg-tbl.pg-tbl .kg-money { font-family: inherit; font-size: 13.5px; font-weight: 600; }

/* Card FLOTANTE "Total pagado": independiente, arriba de la tabla. */
.pg-total { display: flex; justify-content: center; margin: 2px 0 16px; }
.pg-total .kg-contador {
    height: 52px;
    padding: 0 24px;
    gap: 12px;
    border-radius: 14px;
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.06), 0 12px 28px -14px rgba(15, 23, 42, 0.28);
}
.pg-total .kg-contador-lbl { font-size: 10px; }
.pg-total .kg-contador-num { font-size: 22px; }

.kg-f-dia { display: block; font-size: 12.5px; font-weight: 600; color: var(--text); }
.kg-f-hora {
    display: block;
    margin-top: 2px;
    font-family: var(--font-sans);
    font-size: 10.5px;
    color: var(--text-dim-2);
}
.kg-money, .kg-code, .kg-f-hora { font-variant-numeric: tabular-nums; }
.kg-codes { display: inline-flex; flex-wrap: wrap; gap: 4px; }
.kg-code {
    font-family: var(--font-sans);
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.02em;
    padding: 2px 6px;
    border: 1px solid var(--border);
    border-radius: 6px;
    background: var(--surface-3);
    color: var(--text-dim);
}
.kg-code--res {
    background: rgba(37, 99, 235, 0.10);
    border-color: rgba(37, 99, 235, 0.22);
    color: var(--ice-600);
}
:is(html.dark-mode, body.dark-mode) .kg-code--res,
body.dark-mode .kg-code--res {
    background: rgba(37, 99, 235, 0.18);
    border-color: rgba(37, 99, 235, 0.32);
    color: var(--ice-300);
}
/* Chip "P" de Promesa en la columna Status: VERDE mientras la promesa está
   activa, ROJO cuando está rota. El estado lo decide el servidor
   (`_gestion_json` → `promesa_estado`); aquí solo se viste. La regla de
   "rota" es provisional (fecha de promesa vencida) y se ajustará cuando se
   cierre la lógica de promesas. */
.kg-code--prom {
    background: rgba(22, 163, 74, 0.12);
    border-color: rgba(22, 163, 74, 0.28);
    color: #146C33;
}
:is(html.dark-mode, body.dark-mode) .kg-code--prom,
body.dark-mode .kg-code--prom {
    background: rgba(22, 163, 74, 0.18);
    border-color: rgba(22, 163, 74, 0.34);
    color: #4ADE80;
}
.kg-code--prom-rota {
    background: rgba(220, 38, 38, 0.12);
    border-color: rgba(220, 38, 38, 0.28);
    color: #B91C1C;
}
:is(html.dark-mode, body.dark-mode) .kg-code--prom-rota,
body.dark-mode .kg-code--prom-rota {
    background: rgba(239, 68, 68, 0.18);
    border-color: rgba(239, 68, 68, 0.34);
    color: #F87171;
}
/* Chip "C" del ROTO MASIVO (Planchados): la promesa se rompió por el botón
   de Planchados, no por el ✕ manual del Detalle. Acompaña al chip "P" rojo del
   mismo renglón; tinte ámbar para distinguir "roto por sistema". */
.kg-code--prom-c {
    background: rgba(245, 158, 11, 0.14);
    border-color: rgba(245, 158, 11, 0.34);
    color: #92400E;
}
:is(html.dark-mode, body.dark-mode) .kg-code--prom-c,
body.dark-mode .kg-code--prom-c {
    background: rgba(245, 158, 11, 0.20);
    border-color: rgba(245, 158, 11, 0.40);
    color: #FCD34D;
}
/* Promesa en PERIODO DE GRACIA o con un ABONO PARCIAL: tinte ÁMBAR — está
   viva y el reloj corre, pero ya no está en su fecha normal. El estado lo
   decide el servidor (activa · periodo_gracia · parcial_en_espera). */
.kg-code--prom-gracia,
.kg-code--prom-parcial {
    background: rgba(245, 158, 11, 0.14);
    border-color: rgba(245, 158, 11, 0.34);
    color: #92400E;
}
.kg-code--prom-gracia i,
.kg-code--prom-parcial i { font-size: 11px; }
:is(html.dark-mode, body.dark-mode) .kg-code--prom-gracia,
:is(html.dark-mode, body.dark-mode) .kg-code--prom-parcial,
body.dark-mode .kg-code--prom-gracia,
body.dark-mode .kg-code--prom-parcial {
    background: rgba(245, 158, 11, 0.20);
    border-color: rgba(245, 158, 11, 0.40);
    color: #FCD34D;
}
/* Promesa EDITADA (superada por una edición): P en GRIS — ya no está activa,
   pero la fila se conserva completa en el historial. */
.kg-code--prom-editada {
    background: rgba(107, 114, 128, 0.12);
    border-color: rgba(107, 114, 128, 0.24);
    color: #4B5563;
}
:is(html.dark-mode, body.dark-mode) .kg-code--prom-editada,
body.dark-mode .kg-code--prom-editada {
    background: rgba(148, 163, 184, 0.16);
    border-color: rgba(148, 163, 184, 0.30);
    color: #9CA3AF;
}
/* Promesa EN VERIFICACIÓN (se le registró un Pago): flecha GRIS. Espera la
   confirmación del import de pagos. */
.kg-code--prom-verif {
    background: rgba(107, 114, 128, 0.12);
    border-color: rgba(107, 114, 128, 0.24);
    color: #4B5563;
}
.kg-code--prom-verif i { font-size: 11px; }
:is(html.dark-mode, body.dark-mode) .kg-code--prom-verif,
body.dark-mode .kg-code--prom-verif {
    background: rgba(148, 163, 184, 0.16);
    border-color: rgba(148, 163, 184, 0.30);
    color: #9CA3AF;
}
/* Promesa CUMPLIDA (pago verificado): cartera con palomita en VERDE. */
.kg-code--prom-cumpl {
    background: rgba(22, 163, 74, 0.12);
    border-color: rgba(22, 163, 74, 0.28);
    color: #146C33;
}
.kg-code--prom-cumpl i { font-size: 11px; }
:is(html.dark-mode, body.dark-mode) .kg-code--prom-cumpl,
body.dark-mode .kg-code--prom-cumpl {
    background: rgba(22, 163, 74, 0.18);
    border-color: rgba(22, 163, 74, 0.34);
    color: #4ADE80;
}
/* Chip de PAGO ($): GRIS mientras la promesa ligada está en verificación,
   VERDE (is-ok) cuando ya se verificó. */
.kg-code--pago {
    display: inline-flex;
    align-items: center;
    background: rgba(107, 114, 128, 0.12);
    border-color: rgba(107, 114, 128, 0.24);
    color: #4B5563;
}
.kg-code--pago i { font-size: 11px; }
:is(html.dark-mode, body.dark-mode) .kg-code--pago,
body.dark-mode .kg-code--pago {
    background: rgba(148, 163, 184, 0.16);
    border-color: rgba(148, 163, 184, 0.30);
    color: #9CA3AF;
}
.kg-code--pago.is-ok {
    background: rgba(22, 163, 74, 0.12);
    border-color: rgba(22, 163, 74, 0.28);
    color: #146C33;
}
:is(html.dark-mode, body.dark-mode) .kg-code--pago.is-ok,
body.dark-mode .kg-code--pago.is-ok {
    background: rgba(22, 163, 74, 0.18);
    border-color: rgba(22, 163, 74, 0.34);
    color: #4ADE80;
}
/* Indicador de EDICIÓN: chip con lápiz en la fila NUEVA que produjo una
   edición de promesa (la fecha es la del momento de editar). */
.kg-code--edit {
    display: inline-flex;
    align-items: center;
    background: var(--surface-3);
    border-color: var(--border-strong);
    color: var(--text-dim);
}
.kg-code--edit i { font-size: 11px; }
/* Chip de CADENA: a qué promesa ORIGINAL pertenece una edición (↳#<raíz>).
   Borde punteado = es una referencia a otra fila, no un código. */
.kg-code--chain {
    background: transparent;
    border-style: dashed;
    border-color: var(--border-strong);
    color: var(--text-dim);
}
/* Botones de la promesa ACTIVA (✎ editar · ✕ romper): van en la barra de la
   tabla, junto al card de Gestiones, con la MISMA altura (38px) que los demás
   controles para quedar al ras. Sin promesa activa van deshabilitados. */
.kg-prom-btns {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
}
.kg-acc {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    padding: 0;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface);
    color: var(--text-dim);
    cursor: pointer;
    transition: background 120ms var(--sidebar-easing),
                color 120ms var(--sidebar-easing),
                border-color 120ms var(--sidebar-easing);
}
.kg-acc:hover { background: var(--surface-3); color: var(--text); border-color: var(--border-strong); }
.kg-acc i { font-size: 16px; }
.kg-acc:disabled { opacity: .4; cursor: not-allowed; }
.kg-acc:disabled:hover { background: var(--surface); color: var(--text-dim); border-color: var(--border); }
.kg-acc--rota:hover {
    background: rgba(220, 38, 38, 0.10);
    color: #B91C1C;
    border-color: rgba(220, 38, 38, 0.30);
}
:is(html.dark-mode, body.dark-mode) .kg-acc--rota:hover,
body.dark-mode .kg-acc--rota:hover {
    background: rgba(239, 68, 68, 0.16);
    color: #F87171;
    border-color: rgba(239, 68, 68, 0.34);
}
/* $ ROJO — cancelar el pago en verificación. En rojo de BASE (no solo hover)
   para que se lea como acción destructiva; en rojo reservado a destructivas. */
.kg-acc--pago { color: #B91C1C; border-color: rgba(220, 38, 38, 0.30); }
:is(html.dark-mode, body.dark-mode) .kg-acc--pago,
body.dark-mode .kg-acc--pago { color: #F87171; border-color: rgba(239, 68, 68, 0.34); }
.kg-acc--pago:hover {
    background: rgba(220, 38, 38, 0.10);
    color: #B91C1C;
    border-color: rgba(220, 38, 38, 0.40);
}
:is(html.dark-mode, body.dark-mode) .kg-acc--pago:hover,
body.dark-mode .kg-acc--pago:hover {
    background: rgba(239, 68, 68, 0.16);
    color: #F87171;
    border-color: rgba(239, 68, 68, 0.44);
}
.kg-money {
    font-family: var(--font-sans);
    font-size: 11.5px;
    font-weight: 600;
    color: var(--text);
}
.kg-vacio { color: var(--text-dim-2); }

/* Columna "Evidencia": botón de descarga (icono) para la imagen del pago.
   No invasiva: si la gestión no trae adjunto pinta el "—" de siempre. */
.kg-evid {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--surface);
    color: var(--text-dim);
    text-decoration: none;
    transition: background 120ms var(--sidebar-easing),
                color 120ms var(--sidebar-easing),
                border-color 120ms var(--sidebar-easing);
}
.kg-evid:hover { background: var(--surface-3); color: var(--text); border-color: var(--border-strong); }
.kg-evid i { font-size: 13px; }

.kg-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 10px;
    padding: 11px 14px;
    border-top: 1px solid var(--border);
    background: var(--surface-2);
    border-bottom-left-radius: 0.75rem;
    border-bottom-right-radius: 0.75rem;
    color: var(--text-dim);
    font-size: 11.5px;
}
.kg-foot-info b { color: var(--text); font-weight: 600; }
.kg-foot-pages { display: inline-flex; align-items: center; gap: 4px; }
.kg-page {
    min-width: 28px;
    height: 28px;
    padding: 0 8px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--surface);
    color: var(--text-dim);
    font-size: 11.5px;
    font-weight: 600;
    text-decoration: none;
    transition: background 120ms var(--sidebar-easing),
                color 120ms var(--sidebar-easing);
}
.kg-page:hover { background: var(--surface-3); color: var(--text); }
.kg-page.is-active {
    background: var(--surface-3);
    border-color: var(--border-strong);
    color: var(--text);
}
.kg-page.is-disabled { opacity: 0.42; pointer-events: none; }

.kg-vacio-msg {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 7px;
    text-align: center;
    padding: 40px 16px;
    color: var(--text-dim-2);
}
.kg-vacio-msg i { font-size: 22px; }
.kg-vacio-msg b { font-size: 13px; font-weight: 600; color: var(--text); }


/* ================================================================
   Card 5 · Mensajes rápidos (Configuración)
   ----------------------------------------------------------------
   Plantillas globales del botón SMS. Cada plantilla es una tarjeta con
   su textarea (159 máx.), contador y botón Guardar (fetch).
   ================================================================ */
.krav-msg-cat {
    display: inline-flex;
    align-items: center;
    padding: 3px 9px;
    border-radius: 9999px;
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: 0.01em;
}
.krav-msg-cat--suave  { background: rgba(22, 163, 74, 0.14);  color: #16A34A; }
.krav-msg-cat--medio  { background: rgba(245, 158, 11, 0.16); color: #B45309; }
.krav-msg-cat--fuerte { background: rgba(220, 38, 38, 0.14);  color: var(--danger-strong); }

.krav-msg { display: flex; flex-direction: column; gap: 6px; }
.krav-msg-ta {
    width: 100%;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--surface-2);
    color: var(--text);
    font-family: inherit;
    font-size: 12.5px;
    line-height: 1.45;
    padding: 10px 12px;
    resize: vertical;
}
.krav-msg-ta:focus {
    outline: none;
    border-color: var(--ice-600);
    box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15);
}
.krav-msg-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.krav-msg-len { font-size: 10.5px; color: var(--text-dim-2); font-variant-numeric: tabular-nums; }
.krav-msg-len.is-full { color: var(--danger-strong); }
.krav-msg-info { margin: 0; min-height: 14px; font-size: 11px; font-weight: 600; color: var(--danger-strong); }
.krav-msg-info.is-ok { color: var(--success); }

/* Variables de la plantilla ({nombre} · {saldo}): botones que insertan el
   marcador en el cursor. Dashed = "se agrega al texto", no acción de envío. */
.krav-msg-vars { display: flex; flex-wrap: wrap; gap: 5px; }
.krav-msg-var {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    padding: 3px 8px 3px 6px;
    border: 1px dashed var(--border-strong);
    border-radius: 7px;
    background: transparent;
    color: var(--text-dim);
    font-family: inherit;
    font-size: 10.5px;
    font-weight: 600;
    cursor: pointer;
    transition: border-color .14s ease, color .14s ease, background-color .14s ease;
}
.krav-msg-var i { font-size: 10px; }
.krav-msg-var:hover {
    border-color: var(--ice-600);
    color: var(--text);
    background: rgba(37, 99, 235, 0.06);
}
.krav-msg-code {
    padding: 1px 5px;
    border-radius: 5px;
    background: var(--surface-3);
    color: var(--text);
    font-family: var(--font-sans);
    font-size: 11px;
}

/* ================================================================
   Configuración · fila adaptable (usuarios · peticiones · claves SMS)
   y las listas compactas con popups.
   ================================================================ */
/* Fila superior de Configuración: las tres cards del MISMO tamaño.
   `.cfg-row--solo` (staff) y los cortes responsive van después para ganar
   por orden de fuente, sin !important. */
.cfg-row {
    display: grid;
    gap: 16px;
    /* Prioridad de ancho a *Agregar usuario*; las claves van al final con lo
       justo (su contenido entra desde ~190 px). */
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr) minmax(0, 0.8fr);
    /* Misma altura de inicio y fin en las tres (armonía visual): las cards ya
       son flex-column, así que estiran su contenido al alto de la más alta. */
    align-items: stretch;
    margin-bottom: 16px;
}
/* Menos de 1200px: dos columnas y las claves como franja a lo ancho. */
@media (max-width: 1200px) {
    .cfg-row { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
    .cfg-row > #claves-sms { grid-column: 1 / -1; }
    .cfg-row > #claves-sms .clave-body {
        flex-direction: row;
        flex-wrap: wrap;
        justify-content: center;
        gap: 10px 18px;
    }
}
/* Móvil / tablet chica: una columna. */
@media (max-width: 780px) {
    .cfg-row { grid-template-columns: minmax(0, 1fr); }
    .cfg-row > #claves-sms { grid-column: auto; }
}
/* Staff: una sola card, a un ancho cómodo (no ocupa toda la pantalla). */
.cfg-row--solo { grid-template-columns: minmax(0, 460px); }
.cfg-row--solo > #claves-sms { grid-column: auto; }

@media (max-width: 1200px) {
    .cfg-row--solo { grid-template-columns: minmax(0, 460px); }
}
@media (max-width: 780px) {
    .cfg-row--solo { grid-template-columns: minmax(0, 1fr); }
}
.cfg-head-actions { display: flex; align-items: center; gap: 6px; }

/* Lista de peticiones: 2 renglones a la vista; el resto, con scroll. */
.cfg-list {
    display: flex;
    flex-direction: column;
    max-height: 145px;   /* exactamente 2 renglones (72 px cada uno) */
    overflow-y: auto;
    overscroll-behavior: contain;
}
.cfg-item {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 16px;
    border-top: 1px solid var(--border);
}
.cfg-item:first-child { border-top: 0; }
.cfg-item-main { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.cfg-item-t { font-size: 12.5px; font-weight: 600; color: var(--text); }
.cfg-item-s {
    font-size: 11.5px;
    font-weight: 400;
    color: var(--text-dim);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.cfg-item-d { font-size: 10.5px; color: var(--text-dim-2); font-variant-numeric: tabular-nums; }
.cfg-empty {
    flex: 1 1 auto;              /* ocupa el alto libre de la card */
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 18px 16px;
    color: var(--text-dim);
    font-size: 13.5px;
    font-weight: 500;
    text-align: center;
    line-height: 1.3;
}
.cfg-empty i { font-size: 40px; line-height: 1; color: var(--success); }

/* Card · Claves SMS — todo centrado y sin textos de relleno: el candado de la
   cabecera dice el estado (verde = se pide la clave · rojo = sin clave). */
/* La card de claves va centrada de borde a borde: título al centro con el
   resto y sin el relleno lateral de las cards grandes. */
#claves-sms .panel-card-head {
    justify-content: center;
    padding-left: 8px;
    padding-right: 8px;
}
#claves-sms .panel-card-title { justify-content: center; }
#claves-sms .clave-body { padding-left: 8px; padding-right: 8px; }

.clave-acciones { display: flex; align-items: center; justify-content: center; gap: 6px; }
/* Botones chicos y juntos ARRIBA de la clave: la card entra en un espacio
   reducido sin perder nada. */
.clave-acciones .btn {
    width: 26px;
    height: 26px;
    min-width: 26px;
    padding: 0;
    border-radius: 8px;
}
.clave-acciones .btn i { font-size: 12px; }
/* Hover inequívoco (el cambio de fondo del token es sutil en estos botones
   chicos): además del tooltip nativo, sube el brillo. */
.clave-acciones .btn:hover:not(:disabled) { filter: brightness(1.12); }
.clave-acciones .btn:active:not(:disabled) { filter: brightness(.95); }
.clave-acciones .btn-badge {
    top: -5px;
    right: -5px;
    min-width: 14px;
    height: 14px;
    padding: 0 3px;
    font-size: 9px;
    border-width: 1.5px;
}
.clave-toggle { display: inline-flex; margin: 0; }
.clave-body {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 14px 12px;
    text-align: center;
}
.clave-code {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 6px 10px;
    border: 1px solid var(--border);
    border-radius: 12px;
    background: var(--surface-2);
    cursor: pointer;
    color: var(--text);
    transition: border-color .14s ease, background-color .14s ease;
}
.clave-code:hover { border-color: var(--border-strong); background: var(--surface); }
/* Con la restricción apagada el código sigue visible/copiable, pero se apaga
   visualmente: no es lo que se está pidiendo ahora mismo. */
.clave-code.is-off { opacity: .55; }
.clave-code.is-off:hover { opacity: 1; }
.clave-code-txt {
    font-family: var(--font-sans);
    font-size: 20px;
    font-weight: 600;
    letter-spacing: 0.01em;
    text-indent: 0.32em;
    font-variant-numeric: tabular-nums;
}
.clave-code i { font-size: 13px; color: var(--text-dim); }
.clave-usos { display: flex; align-items: center; justify-content: center; gap: 8px; flex-wrap: wrap; }
.clave-dots { display: inline-flex; gap: 4px; }
.clave-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--surface-3);
    border: 1px solid var(--border-strong);
}
.clave-dot.is-used { background: var(--text); border-color: var(--text); }
.clave-usos-txt { font-size: 11px; color: var(--text-dim); white-space: nowrap; }
.clave-usos-txt b { color: var(--text); font-variant-numeric: tabular-nums; }

/* ================================================================
   Card · Datos maestros (Configuración)
   ----------------------------------------------------------------
   UNA card con secciones apiladas (Tiendas receptoras · Verificador
   de teléfonos). Cada sección: tile de ícono + título + chip de
   estado + cargador de archivo. Todo por TOKENS (--surface-*,
   --text-*, --border*) → el modo dark funciona sin overrides.
   ================================================================ */
.dm-grid { display: grid; grid-template-columns: 1fr; }

.dm-sec { padding: 18px 20px; }
.dm-sec + .dm-sec { border-top: 1px solid var(--border); }
.dm-sec--dev { background: rgba(176, 109, 71, 0.05); }

/* Desktop: las dos secciones van LADO A LADO (separadas por una vertical). */
@media (min-width: 768px) {
    .dm-grid { grid-template-columns: 1fr 1fr; }
    .dm-sec + .dm-sec {
        border-top: 0;
        border-left: 1px solid var(--border);
    }
}

.dm-row { display: flex; align-items: center; gap: 12px; }
.dm-ico {
    flex: none;
    width: 40px;
    height: 40px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 12px;
    background: var(--surface-2);
    border: 1px solid var(--border);
    color: var(--text);
    font-size: 19px;
}
.dm-ico--dev {
    color: #B06D47;
    background: rgba(176, 109, 71, 0.10);
    border-color: rgba(176, 109, 71, 0.24);
}
html.dark-mode .dm-ico--dev,
body.dark-mode .dm-ico--dev { color: #E9A878; }

.dm-head { flex: 1 1 auto; min-width: 0; }
.dm-title { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.dm-title h3 {
    margin: 0;
    font-family: var(--font-sans);
    font-size: 14.5px;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--text);
}
.dm-sub { margin: 3px 0 0; font-size: 12px; font-weight: 400; color: var(--text-dim-2); }
.dm-sub b { color: var(--text); font-weight: 600; }

/* Chip de estado (cuánto hay cargado / si falta) */
.dm-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 10px;
    border-radius: 999px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.01em;
    font-variant-numeric: tabular-nums;
    background: var(--surface-2);
    color: var(--text-dim);
    border: 1px solid var(--border);
}
.dm-badge.is-ok {
    color: #0D6558;
    background: rgba(13, 101, 88, 0.10);
    border-color: rgba(13, 101, 88, 0.24);
}
.dm-badge.is-empty {
    color: #92400E;
    background: rgba(245, 158, 11, 0.12);
    border-color: rgba(245, 158, 11, 0.28);
}
html.dark-mode .dm-badge.is-ok,
body.dark-mode .dm-badge.is-ok {
    color: #4ADE80;
    background: rgba(74, 222, 128, 0.12);
    border-color: rgba(74, 222, 128, 0.26);
}
html.dark-mode .dm-badge.is-empty,
body.dark-mode .dm-badge.is-empty {
    color: #FBBF24;
    background: rgba(245, 158, 11, 0.16);
    border-color: rgba(245, 158, 11, 0.30);
}

/* Cargador: <input type=file> nativo oculto + etiqueta que muestra el nombre */
.dm-load { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 14px; }
.dm-file {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 9px;
    max-width: 100%;
    padding: 9px 16px 9px 14px;
    border-radius: 999px;
    background: var(--surface-2);
    border: 1px dashed var(--border-strong);
    color: var(--text-dim);
    font-size: 12.5px;
    font-weight: 600;
    cursor: pointer;
    transition: color .18s ease, background .18s ease, border-color .18s ease;
}
.dm-file > i { font-size: 15px; }
.dm-file:hover { color: var(--text); background: var(--surface-3); border-color: var(--text-dim-2); }
.dm-file:focus-within { border-color: var(--ice-600); box-shadow: 0 0 0 3px rgba(52, 112, 143, 0.16); }
.dm-file input[type="file"] {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}
.dm-file.has-file { color: var(--text); border-style: solid; border-color: var(--border-strong); }
.dm-file-txt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; }

.dm-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    flex-wrap: wrap;
    margin: 12px 0 0;
    font-size: 11px;
    color: var(--text-dim-2);
}


/* ================================================================
   Selector segmentado de rol (Card 1 · Agregar usuario)
   ----------------------------------------------------------------
   Radios REALES ocultos + <label>: funciona sin JS, se navega con las
   flechas del teclado y sigue enviando ``rol`` igual que el <select>.
   El estado elegido usa el "ink" de la app (negro en claro, claro en
   dark) para no confundirse con el CTA azul, que es la acción.
   ================================================================ */
:root {
    --seg-bg:       var(--surface-2);
    --seg-border:   var(--border);
    --seg-fg:       var(--text-dim);
    --seg-sel-bg:   #0F1115;
    --seg-sel-fg:   #FFFFFF;
}
html.dark-mode,
body.dark-mode {
    --seg-sel-bg:   #E5E7EB;
    --seg-sel-fg:   #0F1115;
}

.seg {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px;
    border-radius: 999px;
    background: var(--seg-bg);
    border: 1px solid var(--seg-border);
}
/* El radio queda oculto pero SIGUE recibiendo foco y siendo el que envía. */
.seg input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}
.seg-opt {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 15px;
    border-radius: 999px;
    font-size: 11.5px;
    font-weight: 600;
    letter-spacing: 0.01em;
    color: var(--seg-fg);
    white-space: nowrap;
    cursor: pointer;
    transition: background .18s ease, color .18s ease;
}
.seg-opt i { font-size: 14px; }
.seg-opt:hover { color: var(--text); background: var(--surface-3); }
.seg input:checked + .seg-opt {
    background: var(--seg-sel-bg);
    color: var(--seg-sel-fg);
}
.seg input:focus-visible + .seg-opt {
    outline: 2px solid var(--btn-primary-bg);
    outline-offset: 2px;
}

/* Mobile: los 3 roles reparten el ancho por igual y se ocultan los íconos
   para que no haya saltos de línea ni desbordes. */
@media (max-width: 480px) {
    .seg { width: 100%; justify-content: space-between; }
    .seg-opt {
        flex: 1 1 0;
        min-width: 0;
        justify-content: center;
        padding: 8px 6px;
        letter-spacing: 0;
    }
    .seg-opt i { display: none; }
}

/* ============================================================
   COMPONENTES COTTON (anatomía shadcn) — master: cerebro 23_Expectra_Design_Master §5
   Todo sale de tokens: un cambio de token repinta el componente.
   Markup en templates/cotton/  ·  <c-card>, <c-button>, <c-button_link>
   ============================================================ */

.c-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 16px;
    box-shadow: var(--shadow);
    overflow: hidden;
}
.c-card-header {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 16px 18px 12px;
}
.c-card-title {
    font-family: var(--font-sans);
    font-size: 15px;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--text);
    margin: 0;
}
.c-card-description {
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--text-dim);
    margin: 0;
}
.c-card-content {
    padding: 0 18px 16px;
    color: var(--text);
}
.c-card-header + .c-card-content { padding-top: 0; }
.c-card-footer {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 12px 18px;
    border-top: 1px solid var(--border);
    background: var(--surface-2);
}
.c-card-footer:empty { display: none; }

/* --- Botón ---------------------------------------------------------------
   Ctrl/⌘+click y teclado funcionan igual porque <c-button_link> es un <a>.
   El estado `loading` deshabilita y gira `ph-circle-notch` (btnSpin, arriba). */
.c-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    font-family: var(--font-sans);
    font-weight: 600;
    letter-spacing: -0.01em;
    border: 1px solid transparent;
    border-radius: 10px;
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: background-color 150ms cubic-bezier(0.2, 0.8, 0.2, 1),
                color 150ms cubic-bezier(0.2, 0.8, 0.2, 1),
                border-color 150ms cubic-bezier(0.2, 0.8, 0.2, 1),
                transform 120ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.c-btn:active:not([disabled]):not([aria-disabled="true"]) { transform: translateY(1px); }
.c-btn[disabled],
.c-btn[aria-disabled="true"] {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
}
.c-btn:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.c-btn i { font-size: 16px; line-height: 1; }
.c-btn-spin { animation: btnSpin 800ms linear infinite; }

.c-btn--sm { height: 32px; padding: 0 12px; font-size: 12.5px; }
.c-btn--md { height: 38px; padding: 0 16px; font-size: 13px; }
.c-btn--lg { height: 44px; padding: 0 20px; font-size: 14px; }

.c-btn--primary { background: var(--accent); color: var(--button-text); }
.c-btn--primary:hover:not([disabled]) { background: var(--accent-alt); }

.c-btn--secondary {
    background: var(--surface-2);
    color: var(--text);
    border-color: var(--border);
}
.c-btn--secondary:hover:not([disabled]) { background: var(--surface-3); }

.c-btn--ghost { background: transparent; color: var(--text-dim); }
.c-btn--ghost:hover:not([disabled]) { background: var(--accent-soft); color: var(--text); }

.c-btn--danger { background: var(--danger); color: #ffffff; }
.c-btn--danger:hover:not([disabled]) { background: var(--danger-strong); }

@media (prefers-reduced-motion: reduce) {
    .c-btn { transition: none; }
    .c-btn-spin { animation: none; }
}

/* ============================================================
   UTILIDAD DE NÚMEROS — cifras tabulares en Cove.
   No cambia de familia (no hay monoespaciada en el sistema): solo fija el
   ancho tabular para que una columna de dinero no baile al actualizarse.
   ============================================================ */
.num {
    font-family: var(--font-sans);
    font-variant-numeric: tabular-nums;
    letter-spacing: 0;
}

/* El preflight de Tailwind (tailwind.build.css, que se carga DESPUÉS de este
   archivo) fuerza `ui-monospace` en code/kbd/pre/samp. El sistema no usa
   monoespaciada, así que se neutraliza con más especificidad que el preflight
   para no depender del orden de carga. */
/* Sin negritas en el sistema: <b>/<strong> usan 600 como techo. */
b, strong { font-weight: 600; }

html code,
html kbd,
html pre,
html samp,
html .font-mono {
    font-family: var(--font-sans);
}

/* ============================================================
   GRÁFICAS — SVG inline server-rendered (DTL). Master: cerebro 23_Expectra_Design_Master §5.C
   Catálogo de patrones: skill expectra-design-system → references/graficas.md
   Regla: el dato se calcula en la vista; aquí solo viven estilos.
   ============================================================ */

.c-chart {
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.c-chart svg {
    width: 100%;
    height: auto;
    /* Con viewBox ancho el `height:auto` se dispara (una card de 1200px daría
       450px de alto). El tope + preserveAspectRatio="none" deja que el SVG
       llene la caja sin deformar el trazo (vector-effect de abajo). */
    max-height: 240px;
    display: block;
    overflow: visible;      /* que no recorte tooltips/etiquetas del borde */
}
.c-chart--sm svg { max-height: 120px; }
.c-chart--lg svg { max-height: 320px; }
/* preserveAspectRatio="none" estira el viewBox: sin esto el trazo engorda.
   Va sobre TODOS los hijos porque el trazo aquí se declara por clase, no con
   el atributo `stroke` (un selector `*[stroke]` no los alcanzaría). */
.c-chart svg * { vector-effect: non-scaling-stroke; }

.c-chart-cap {
    font-family: var(--font-sans);
    font-size: 11px;
    line-height: 1.4;
    color: var(--text-dim);
}
/* Ejes y marcas: Cove con cifras tabulares para que no bailen. */
.c-chart-eje {
    font-family: var(--font-sans);
    font-size: 10px;
    font-variant-numeric: tabular-nums;
    fill: var(--text-dim-2);
}
.c-chart-grid line {
    stroke: var(--border);
    stroke-width: 1;
}
.c-chart-line { fill: none; stroke: var(--chart-line); stroke-width: 2; }
.c-chart-area { fill: var(--chart-fill); }
.c-chart-bar  { fill: var(--chart-line); }
.c-chart-bar--ok   { fill: var(--success); }
.c-chart-bar--warn { fill: var(--warning); }
.c-chart-bar--bad  { fill: var(--danger); }

/* Alternativa accesible al SVG: datos para lector de pantalla. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}


/* ════════════════════════════════════════════════════════════════════════════
   CAPA AIR — lenguaje visual del panel (se complementa con el sidebar)
   ----------------------------------------------------------------------------
   Sidebar: superficies blancas, radio generoso, sombra suave, texto en slate,
   iconos atenuados, cero bordes duros en lo interactivo. Esta capa aplica lo
   mismo a cards, botones, tablas, campos y diálogos SIN tocar estructura,
   nombres de clase ni comportamiento: solo piel.

   Nota de cascada: las utilidades de Tailwind del markup tienen especificidad
   0,1,0; por eso los controles se declaran con `html` delante (0,1,1).
   ════════════════════════════════════════════════════════════════════════════ */

:root {
    --air-radius:      18px;   /* cards y diálogos */
    --air-radius-sm:   12px;   /* botones y campos */
    --air-shadow:      0 1px 2px rgba(15, 23, 42, 0.05), 0 12px 28px -22px rgba(15, 23, 42, 0.45);
    --air-shadow-soft: 0 1px 2px rgba(15, 23, 42, 0.04);
    --air-shadow-hover:0 2px 4px rgba(15, 23, 42, 0.07), 0 16px 32px -22px rgba(15, 23, 42, 0.50);
}
html.dark-mode {
    --air-shadow:      0 1px 2px rgba(0, 0, 0, 0.35), 0 12px 28px -22px rgba(0, 0, 0, 0.8);
    --air-shadow-soft: 0 1px 2px rgba(0, 0, 0, 0.3);
    --air-shadow-hover:0 2px 4px rgba(0, 0, 0, 0.45), 0 16px 32px -22px rgba(0, 0, 0, 0.9);
}

/* ── Cards: una sola superficie, cabecera con hairline ─────────────────── */
.panel-card {
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--air-radius);
    box-shadow: var(--air-shadow-soft);
    overflow: hidden;
}
.panel-card-inner {
    background: transparent;
    border: 0;
    border-radius: 0;
    box-shadow: none;
}
.panel-card-head {
    background: transparent;
    border-bottom: 1px solid var(--border);
    box-shadow: none;
    border-radius: 0;
    /* 20 px laterales = el mismo que el cuerpo (px-5); antes la cabecera iba a
       12 y el título quedaba 8 px descuadrado respecto al contenido. */
    padding: 14px 20px;
}
.panel-card-title { color: var(--text); }
.panel-card-meta  { color: var(--text-dim); }
/* Las variantes conservan su tinte, pero como acento de la cabecera, no del
   bloque entero (antes el card entero se pintaba de rojo/terracota). */
.panel-card--danger { background: var(--surface); border-color: rgba(220, 38, 38, 0.22); }
.panel-card--danger .panel-card-head { background: rgba(220, 38, 38, 0.06); }
.panel-card--warm   { background: var(--surface); border-color: rgba(180, 83, 9, 0.20); }
.panel-card--warm .panel-card-head { background: rgba(180, 83, 9, 0.07); }

/* ── Botones: misma familia que los campos (radio 12, sombra suave) ────── */
.btn {
    border-radius: var(--air-radius-sm);
    border: 1px solid var(--border);
    background: var(--surface);
    box-shadow: var(--air-shadow-soft);
    padding: 10px 16px;
    font-size: 12.5px;
    font-weight: 600;
    letter-spacing: 0;
    transition: background-color 160ms var(--sidebar-easing),
                border-color 160ms var(--sidebar-easing),
                box-shadow 160ms var(--sidebar-easing),
                color 160ms var(--sidebar-easing);
}
.btn:hover { background: var(--surface-2); box-shadow: var(--air-shadow-hover); }
.btn:active { transform: none; box-shadow: var(--air-shadow-soft); }
.btn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--accent-soft), var(--air-shadow-soft); }
.btn.btn-sm { padding: 8px 12px; font-size: 12px; border-radius: 10px; }
.btn.btn-sq { width: 34px; height: 34px; padding: 0; border-radius: 10px; }
.btn-block { width: 100%; }

.btn-primary { background: var(--ice-600); border-color: transparent; color: #FFFFFF; }
.btn-primary:hover { background: var(--ice-700); color: #FFFFFF; }
.btn-secondary { background: var(--ice-100); border-color: transparent; color: var(--ice-800); }
.btn-secondary:hover { background: var(--ice-200); color: var(--ice-900); }
.btn.btn-success { background: rgba(22, 163, 74, 0.10); border-color: transparent; color: #15803D; }
.btn.btn-success:hover { background: rgba(22, 163, 74, 0.18); color: #14532D; }
.btn-danger { background: rgba(220, 38, 38, 0.08); border-color: transparent; color: var(--danger); }
.btn-danger:hover { background: rgba(220, 38, 38, 0.16); color: var(--danger-strong); }
.btn.btn-ghost { background: transparent; border-color: transparent; box-shadow: none; color: var(--text-dim); }
.btn.btn-ghost:hover { background: var(--surface-2); color: var(--text); box-shadow: none; }
html.dark-mode .btn.btn-success { color: #4ADE80; }
html.dark-mode .btn.btn-danger  { color: #F87171; }

/* ── Campos de texto: el mismo cuerpo que select/fecha ─────────────────── */
html input[type="text"],
html input[type="password"],
html input[type="email"],
html input[type="number"],
html input[type="search"],
html input[type="tel"],
html input[type="url"],
html textarea,
html .edx-input {
    min-height: 38px;
    padding: 9px 12px;
    background: var(--surface);
    /* hairline: sobre card blanca un campo blanco sin borde desaparece */
    border: 1px solid var(--border);
    border-radius: var(--air-radius-sm);
    box-shadow: var(--air-shadow-soft);
    color: var(--text);
    font-family: inherit;
    font-size: 12.5px;
    font-weight: 500;
    line-height: 20px;
    transition: box-shadow 160ms var(--sidebar-easing),
                border-color 160ms var(--sidebar-easing),
                background-color 160ms var(--sidebar-easing);
}
html textarea { min-height: 74px; resize: vertical; }
html input[type="text"]:hover,
html input[type="password"]:hover,
html input[type="email"]:hover,
html input[type="number"]:hover,
html input[type="search"]:hover,
html input[type="tel"]:hover,
html textarea:hover { box-shadow: var(--air-shadow-hover); }
html input[type="text"]:focus,
html input[type="password"]:focus,
html input[type="email"]:focus,
html input[type="number"]:focus,
html input[type="search"]:focus,
html input[type="tel"]:focus,
html textarea:focus {
    outline: none;
    border-color: var(--ice-400);
    box-shadow: 0 0 0 3px var(--accent-soft);
}
html input::placeholder, html textarea::placeholder { color: var(--text-dim); opacity: .75; font-weight: 500; }
html.dark-mode input[type="text"],
html.dark-mode input[type="password"],
html.dark-mode input[type="email"],
html.dark-mode input[type="number"],
html.dark-mode input[type="search"],
html.dark-mode input[type="tel"],
html.dark-mode textarea { background: var(--surface-2); }

/* ── Tablas: sin rejilla, solo hairlines y hover de fila ───────────────── */
.krav-tabla {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    background: transparent !important;
    font-size: 12.5px;
}
.krav-tabla thead th {
    background: transparent !important;
    color: var(--text-dim) !important;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0;
    text-align: left;
    padding: 10px 12px;
    border: 0 !important;
    border-bottom: 1px solid var(--border) !important;
    white-space: nowrap;
}
.krav-tabla tbody td {
    padding: 11px 12px;
    border: 0 !important;
    border-bottom: 1px solid var(--border) !important;
    color: var(--text);
    vertical-align: middle;
}
.krav-tabla tbody tr:last-child td { border-bottom: 0 !important; }
.krav-tabla tbody tr { transition: background-color 120ms var(--sidebar-easing); }
.krav-tabla tbody tr:hover td { background: var(--surface-2); }
.krav-tabla--center tbody td, .krav-tabla--center thead th { text-align: center; }

/* ── Diálogos ──────────────────────────────────────────────────────────── */
.dlg {
    border: 1px solid var(--border);
    border-radius: 20px;
    background: var(--surface);
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.06), 0 32px 64px -32px rgba(15, 23, 42, 0.45);
}
.dlg-head {
    background: transparent;
    border-bottom: 1px solid var(--border);
    padding: 14px 18px;
}
.dlg-close {
    width: 30px;
    height: 30px;
    border-radius: 10px;
    border: 1px solid transparent;
    background: transparent;
    color: var(--text-dim);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color 140ms var(--sidebar-easing), color 140ms var(--sidebar-easing);
}
.dlg-close:hover { background: var(--surface-2); color: var(--text); }
.dlg-foot {
    background: transparent;
    border-top: 1px solid var(--border);
    padding: 14px 18px;
}

/* ── Chips y píldoras: tinte suave, sin borde duro ─────────────────────── */
.chip, .krav-status-chip {
    border-radius: 999px;
    border-color: transparent;
    box-shadow: none;
}

/* ── Segmentado: la misma pastilla blanca del sidebar ───────────────────── */
:root {
    --seg-bg:      var(--surface-2);
    --seg-border:  transparent;
    --seg-sel-bg:  var(--surface);
    --seg-sel-fg:  var(--text);
}
html.dark-mode {
    --seg-sel-bg:  #2A2F37;
    --seg-sel-fg:  #F1F5F9;
}
.seg { border-radius: var(--air-radius-sm); box-shadow: inset 0 0 0 1px var(--border); }
.seg-opt { border-radius: 9px; }
.seg input:checked + .seg-opt {
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.08), 0 8px 18px -14px rgba(15, 23, 42, 0.5);
}
html.dark-mode .seg input:checked + .seg-opt {
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.45), 0 8px 18px -14px rgba(0, 0, 0, 0.9);
}

/* ── Piezas sueltas de Configuración que seguían con caja dura ──────────── */
.clave-code {
    border: 1px solid var(--border);
    border-radius: var(--air-radius-sm);
    background: var(--surface);
    box-shadow: var(--air-shadow-soft);
    font-variant-numeric: tabular-nums;
}
.krav-msg {
    border: 1px solid var(--border);
    border-radius: var(--air-radius-sm);
    background: var(--surface);
    box-shadow: var(--air-shadow-soft);
}
.krav-msg:hover { box-shadow: var(--air-shadow-hover); }
.krav-msg-ta { background: transparent; border: 0; box-shadow: none; }
.krav-msg-var {
    border: 1px solid var(--border);
    border-radius: 8px;
    background: var(--surface-2);
    color: var(--text-dim);
}
.krav-msg-var:hover { background: var(--ice-50); color: var(--ice-800); border-color: var(--ice-200); }

/* ── Modales de acción (.crm-modal): mismo cuerpo que .dlg ──────────────── */
.crm-modal {
    border: 1px solid var(--border);
    border-radius: 20px;
    background: var(--surface);
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.06), 0 32px 64px -32px rgba(15, 23, 42, 0.45);
}
.crm-modal-head { background: transparent; border-bottom: 1px solid var(--border); }
.crm-modal-x {
    width: 30px; height: 30px;
    border-radius: 10px;
    border: 1px solid transparent;
    background: transparent;
    color: var(--text-dim);
    display: inline-flex; align-items: center; justify-content: center;
    transition: background-color 140ms var(--sidebar-easing), color 140ms var(--sidebar-easing);
}
.crm-modal-x:hover { background: var(--surface-2); color: var(--text); }
.crm-modal-foot { background: transparent; border-top: 1px solid var(--border); }
.crm-modal-ico { border-radius: 12px; }

/* El rojo de "Eliminar" era sólido: en Air va en tinte (el peso lo da el texto) */
html .btn.btn-danger { background: rgba(220, 38, 38, 0.08); color: var(--danger); border-color: transparent; }
html .btn.btn-danger:hover { background: rgba(220, 38, 38, 0.16); color: var(--danger-strong); }
html.dark-mode .btn.btn-danger { background: rgba(248, 113, 113, 0.14); color: #FCA5A5; }
html.dark-mode .btn.btn-danger:hover { background: rgba(248, 113, 113, 0.22); color: #FECACA; }

/* El conmutador de vistas (Métricas, Reportes) usa el mismo track que .seg:
   pastilla blanca sobre carril tenue, no el bloque negro de antes. */
.view-switch {
    border-radius: var(--air-radius-sm);
    background: var(--surface-2);
    box-shadow: inset 0 0 0 1px var(--border);
    border: 0;
}
.view-switch-btn { border-radius: 9px; color: var(--text-dim); }
.view-switch-btn:hover { color: var(--text); }
.view-switch-btn.is-active {
    background: var(--surface);
    color: var(--text);
    box-shadow: 0 1px 2px rgba(15, 23, 42, 0.08), 0 8px 18px -14px rgba(15, 23, 42, 0.5);
}
html.dark-mode .view-switch-btn.is-active {
    background: #2A2F37; color: #F1F5F9;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.45), 0 8px 18px -14px rgba(0, 0, 0, 0.9);
}

/* ════════════════════════════════════════════════════════════════════════════
   AIR · ajustes de Configuración (márgenes, desbordes y "switches")
   ════════════════════════════════════════════════════════════════════════════ */

/* El buscador del topbar necesita 48 px a la izquierda para su lupa: la regla
   global de campos le quitaba ese hueco y la lupa se montaba sobre el texto. */
/* Especificidad: la regla de macOS (html[data-os="mac"] .edx-search-input)
   pesa (0,2,1); esta necesita más para devolverle el hueco a la lupa. */
html body .edx-search-input.edx-search-input {
    padding: 0 84px 0 48px;
    border-radius: 999px;
    box-shadow: var(--air-shadow-soft);
    /* La regla global de campos (`html input[type="search"]`) también le ganaba
       en tamaño: el buscador del topbar quedaba en 12.5 px en vez de los 14 de
       su componente. Sólo se repone el tipo; borde/foco siguen por sus reglas. */
    font-size: 14px;
    font-weight: 500;
}
html .edx-search-input:focus { border-color: var(--ice-600); box-shadow: 0 0 0 4px var(--accent-soft); }
.edx-search-icon { pointer-events: none; }

/* Badges de conteo: el botón debe ser el anclaje (antes flotaban fuera). */
.btn { position: relative; }
.btn-badge {
    top: -5px;
    right: -5px;
    min-width: 17px;
    height: 17px;
    padding: 0 4px;
    font-size: 9.5px;
    font-weight: 600;
    border-radius: 999px;
    border: 1.5px solid var(--surface);
    box-shadow: none;
}
.clave-acciones .btn-badge { top: -5px; right: -5px; }

/* Segmentados tipo interruptor: tramos del MISMO ancho y forma de píldora
   (antes cada uno medía lo que su texto y parecía descuadrado). */
.seg { border-radius: 999px; padding: 3px; gap: 3px; }
.seg-opt {
    flex: 1 1 0;
    justify-content: center;
    border-radius: 999px;
    padding: 7px 14px;
    min-width: 0;
}
.seg input:checked + .seg-opt { border-radius: 999px; }
.view-switch { border-radius: 999px; padding: 3px; }
.view-switch-btn { border-radius: 999px; }

/* Casillas: el control nativo IGNORA border-radius, así que se dibuja a mano
   (`appearance:none`) para que sea redondeada y del acento del sistema. */
html input[type="checkbox"]:not([role="switch"]) {
    appearance: none;
    -webkit-appearance: none;
    width: 17px;
    height: 17px;
    flex: none;
    border: 1.5px solid var(--border-strong);
    border-radius: 6px;
    background: var(--surface);
    box-shadow: var(--air-shadow-soft);
    cursor: pointer;
    position: relative;
    transition: background-color 140ms var(--sidebar-easing),
                border-color 140ms var(--sidebar-easing);
}
html input[type="checkbox"]:not([role="switch"]):hover { border-color: var(--text-dim-2); }
html input[type="checkbox"]:not([role="switch"]):checked {
    background: var(--ice-600);
    border-color: var(--ice-600);
}
html input[type="checkbox"]:not([role="switch"]):checked::after {
    content: "";
    position: absolute;
    inset: 0;
    background-color: #FFFFFF;
    -webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><path d='M5 12.5l4.5 4.5L19 7.5'/></svg>") center / 11px no-repeat;
    mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'><path d='M5 12.5l4.5 4.5L19 7.5'/></svg>") center / 11px no-repeat;
}
html input[type="checkbox"]:not([role="switch"]):focus-visible {
    outline: none;
    box-shadow: 0 0 0 3px var(--accent-soft);
}
/* En un bloque destructivo la casilla confirmada va en rojo. */
.panel-card--danger input[type="checkbox"]:not([role="switch"]):checked,
.cl-chip--negra input[type="checkbox"]:checked { background: var(--danger); border-color: var(--danger); }
html.dark-mode input[type="checkbox"]:not([role="switch"]):checked { background: var(--ice-500); border-color: var(--ice-500); }

/* Botones icono-cuadro: mismo cuadrado que los campos y centrado real. */
.btn.btn-sq { width: 36px; height: 36px; border-radius: var(--air-radius-sm); }
.btn.btn-sm.btn-sq { width: 32px; height: 32px; }

/* ════════════════════════════════════════════════════════════════════════════
   AIR · Configuración: cards parejas
   Antes la fila repartía 1.6 / 1 / 0.8 ⇒ tres cards de anchos distintos con el
   mismo alto: se leía sucio. Ahora tercios iguales y el contenido arranca en
   la misma x en todas (cabecera 20 px + cuerpo 20 px).
   ════════════════════════════════════════════════════════════════════════════ */
.cfg-empty { padding: 16px 20px; }
.clave-body { padding: 16px 20px; }
.dm-grid { padding: 16px 20px; }
.dm-grid > * { padding: 0; }

/* El cuerpo de card siempre con el mismo aire: 16 arriba/abajo, 20 laterales. */
.panel-card-inner > .px-5 { padding: 16px 20px; }
.panel-card-title { align-items: center; }
.panel-card-title h2 { line-height: 1.2; }

/* ── Modo oscuro: la capa Air también ───────────────────────────────────── */
html.dark-mode .panel-card {
    background: var(--surface);
    border-color: rgba(255, 255, 255, 0.07);
}
html.dark-mode .panel-card-head { background: transparent; border-bottom-color: rgba(255, 255, 255, 0.07); }
html.dark-mode .panel-card-inner { background: transparent; }
html.dark-mode .btn {
    background: var(--btn-plain-bg);
    border-color: rgba(255, 255, 255, 0.09);
    color: var(--text);
}
html.dark-mode .btn:hover { background: var(--btn-plain-bg-hover); border-color: rgba(255, 255, 255, 0.16); }
/* El PRIMARIO no se pinta de gris en dark. La regla de arriba
   (`html.dark-mode .btn`, específicidad 0,2,1) le gana a
   `.page-container .btn-primary` (0,2,0) y lo dejaba idéntico a un botón
   neutro: el relleno de ACCIÓN desaparecía justo en el tema oscuro. Se
   re-declara con `html` delante —misma específicidad, gana por orden— y con
   la sombra de sólido, para que el botón se lea como cuerpo y no como
   rectángulo pegado al fondo. */
html.dark-mode .page-container .btn-primary {
    background: var(--btn-primary-bg);
    color: var(--btn-primary-fg);
    border-color: var(--btn-primary-border);
    box-shadow: var(--btn-shadow-solid-rest);
}
html.dark-mode .page-container .btn-primary:hover:not(:disabled):not([aria-disabled="true"]) {
    background: var(--btn-primary-hover);
    border-color: var(--btn-primary-border-hover);
    box-shadow: var(--btn-shadow-solid-hover);
    transform: translateY(var(--btn-lift));
}
html.dark-mode .page-container .btn-primary:active:not(:disabled):not([aria-disabled="true"]) {
    background: var(--btn-primary-active);
    box-shadow: var(--btn-shadow-active);
    transform: translateY(0) scale(0.97);
}
html.dark-mode .btn.btn-secondary { background: rgba(127, 180, 208, 0.16); color: var(--ice-200); border-color: transparent; }
html.dark-mode .btn.btn-secondary:hover { background: rgba(127, 180, 208, 0.26); color: #FFFFFF; }
html.dark-mode .btn.btn-success { background: rgba(34, 197, 94, 0.16); color: #86EFAC; border-color: transparent; }
html.dark-mode .btn.btn-success:hover { background: rgba(34, 197, 94, 0.26); }
html.dark-mode .btn.btn-ghost { background: transparent; border-color: transparent; color: var(--text-dim); }
html.dark-mode .btn.btn-ghost:hover { background: var(--surface-2); color: var(--text); }
html.dark-mode .krav-tabla tbody td { border-bottom-color: rgba(255, 255, 255, 0.07) !important; }
html.dark-mode .krav-tabla tbody tr:hover td { background: rgba(255, 255, 255, 0.04); }
html.dark-mode .dlg, html.dark-mode .crm-modal {
    background: var(--surface);
    border-color: rgba(255, 255, 255, 0.08);
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5), 0 32px 64px -32px rgba(0, 0, 0, 0.9);
}
html.dark-mode .dlg-head, html.dark-mode .dlg-foot,
html.dark-mode .crm-modal-head, html.dark-mode .crm-modal-foot { border-color: rgba(255, 255, 255, 0.08); }
html.dark-mode .seg { background: var(--surface-2); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.07); }
html.dark-mode .krav-msg { background: var(--surface-2); border-color: rgba(255, 255, 255, 0.07); }
html.dark-mode .clave-code { background: var(--surface-2); border-color: rgba(255, 255, 255, 0.08); }

/* El segmentado no debe forzar su propia línea: con `width:100%` empujaba los
   botones de acción a un renglón suelto debajo. Ancho por contenido y, si no
   cabe, encoge antes de tirar al siguiente renglón. */
.seg { width: auto; flex: 0 1 auto; max-width: 100%; }
@media (max-width: 560px) { .seg { width: 100%; } }

/* ════════════════════════════════════════════════════════════════════════════
   AIR · correcciones sobre lo reportado
   ════════════════════════════════════════════════════════════════════════════ */

/* 1) El CTA del login: la capa Air pisaba `.btn-login` (misma especificidad y
   más abajo) y el botón quedaba blanco sobre blanco. Se restituye. */
html .btn.btn-login {
    background: #000000;
    border-color: #000000;
    color: #FFFFFF;
    border-radius: 999px;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.20), 0 4px 12px rgba(0, 0, 0, 0.18);
}
html .btn.btn-login:hover {
    background: #1F2937;
    border-color: #1F2937;
    color: #FFFFFF;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25), 0 8px 20px rgba(0, 0, 0, 0.25);
}

/* 2) Hover: nada de rellenos fuertes. El estado se insinúa con tinte + sombra. */
html .btn:hover { background: var(--surface-2); color: var(--text); box-shadow: var(--air-shadow-hover); }
html .btn.btn-secondary:hover { background: var(--ice-100); color: var(--ice-900); }
html .btn.btn-success:hover { background: rgba(22, 163, 74, 0.14); color: #14532D; }
html .btn.btn-danger:hover { background: rgba(220, 38, 38, 0.12); color: var(--danger-strong); }
html .btn.btn-ghost:hover { background: var(--surface-2); color: var(--text); box-shadow: none; }
html.dark-mode .btn:hover { background: #2A2F37; }
html.dark-mode .btn.btn-secondary:hover { background: rgba(127, 180, 208, 0.22); }
html.dark-mode .btn.btn-success:hover { background: rgba(34, 197, 94, 0.22); color: #BBF7D0; }
html.dark-mode .btn.btn-danger:hover { background: rgba(248, 113, 113, 0.20); color: #FECACA; }

/* 3) Cajas de texto: el hairline al 8 % no se veía. Borde de campo real. */
html input[type="text"], html input[type="password"], html input[type="email"],
html input[type="number"], html input[type="search"], html input[type="tel"],
html input[type="url"], html textarea {
    border-color: var(--border-strong);
    box-shadow: inset 0 1px 2px rgba(15, 23, 42, 0.04);
}
html input[type="text"]:hover, html input[type="password"]:hover, html input[type="email"]:hover,
html input[type="number"]:hover, html input[type="search"]:hover, html input[type="tel"]:hover,
html textarea:hover { border-color: var(--text-dim-2); }
html.dark-mode input[type="text"], html.dark-mode input[type="password"], html.dark-mode input[type="email"],
html.dark-mode input[type="number"], html.dark-mode input[type="search"], html.dark-mode input[type="tel"],
html.dark-mode textarea {
    border-color: rgba(255, 255, 255, 0.12);
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.35);
}

/* 4) El textarea de los mensajes rápidos era invisible: se lee como texto
   suelto. Vuelve a ser un campo dentro de su tarjeta. */
.krav-msg-ta {
    background: var(--surface-2);
    border: 1px solid var(--border-strong);
    border-radius: 10px;
    padding: 10px 12px;
    box-shadow: none;
    color: var(--text);
    min-height: 92px;
}
.krav-msg-ta:focus {
    outline: none;
    border-color: var(--ice-400);
    box-shadow: 0 0 0 3px var(--accent-soft);
}
html.dark-mode .krav-msg-ta { background: rgba(255, 255, 255, 0.04); border-color: rgba(255, 255, 255, 0.12); }
.krav-msg { padding: 12px; }
.krav-msg-foot { padding: 0 2px; }
.krav-msg-len { color: var(--text-dim); }

/* 5) Cabecera de card con chip: el chip se montaba sobre el título. */
.panel-card-head { display: flex; align-items: center; gap: 12px; }
.panel-card-head > .panel-card-title { flex: 1 1 auto; min-width: 0; }
.panel-card-head > :not(.panel-card-title) { flex: none; }
.panel-card-title h2 { margin: 0; }

/* 6) Interruptores: colores INVERSOS (pastilla oscura sobre carril claro). */
:root {
    --seg-bg:     var(--surface);
    --seg-border: var(--border-strong);
    --seg-sel-bg: var(--text);
    --seg-sel-fg: var(--bg);
}
html.dark-mode {
    --seg-bg:     var(--surface-2);
    --seg-sel-bg: #F1F5F9;
    --seg-sel-fg: #0F1115;
}
.view-switch { background: var(--surface); box-shadow: inset 0 0 0 1px var(--border-strong); }
.view-switch-btn.is-active { background: var(--text); color: var(--bg); }
html.dark-mode .view-switch { background: var(--surface-2); box-shadow: inset 0 0 0 1px rgba(255,255,255,.10); }
html.dark-mode .view-switch-btn.is-active { background: #F1F5F9; color: #0F1115; }

/* Campos dentro de una caja que ya dibuja el contorno (login `.input-pill`,
   buscador del topbar, rangos de fecha): la capa Air les añadía un segundo
   borde y un segundo radio ⇒ se veían "rotas" (doble anillo). Aquí se limpian
   y el borde lo sigue poniendo el wrapper. */
html .input-pill input,
html .input-pill textarea,
html .rango-ctl input[type="date"],
html .rep-rango input[type="date"],
html .bl-rango input[type="date"] {
    border: 0;
    border-radius: inherit;
    background: transparent;
    box-shadow: none;
    min-height: 0;
    font-size: inherit;
    font-weight: inherit;
}
html .input-pill input:focus {
    border: 0;
    box-shadow: none;
}

/* ── El anillo blanco de las cards ────────────────────────────────────────
   `.panel-card` venía con `padding: 5px` del diseño viejo (card gris con una
   card blanca dentro). Con una sola superficie eso dejaba un marco blanco de
   5 px entre el borde y la cabecera — el "margen exterior" que se veía, sobre
   todo en la card destructiva, donde la banda roja flotaba dentro. */
html .panel-card { padding: 0; }
html .panel-card .panel-card-inner { border-radius: inherit; }
html .panel-card .panel-card-head { border-radius: 17px 17px 0 0; }

/* ── CTA del login: más grande ─────────────────────────────────────────── */
html .btn.btn-login {
    padding: 20px 28px;
    font-size: 17px;
    letter-spacing: 0.09em;
    min-height: 60px;
    margin-top: 28px;
    border-radius: 999px;
}

/* ── Hover de los botones de estado (claro) ───────────────────────────────
   `.page-container .btn-success:hover:not(:disabled)` usaba `--btn-success-hover`
   (verde sólido #15803D) y lo mismo el rojo: el botón se "pintaba" entero al
   pasar el ratón. Los tokens se redefinen como TINTE (el peso del estado ya lo
   lleva el texto) y se dejan reglas explícitas por si algún bloque los pisa. */
:root {
    --btn-success-hover:  rgba(22, 163, 74, 0.14);
    --btn-danger-hover:   rgba(220, 38, 38, 0.12);
    --btn-secondary-hover: var(--ice-100);
}
html .page-container .btn-success:hover:not(:disabled) {
    background: rgba(22, 163, 74, 0.14);
    color: #14532D;
    box-shadow: var(--air-shadow-hover);
}
html .page-container .btn-danger:hover:not(:disabled) {
    background: rgba(220, 38, 38, 0.12);
    color: var(--danger-strong);
    box-shadow: var(--air-shadow-hover);
}
html.dark-mode .page-container .btn-success:hover:not(:disabled) {
    background: rgba(34, 197, 94, 0.22); color: #BBF7D0;
}
html.dark-mode .page-container .btn-danger:hover:not(:disabled) {
    background: rgba(248, 113, 113, 0.20); color: #FECACA;
}

/* ── Botón de guardar: check de validación en verde ────────────────────── */
.ph-floppy-disk { color: var(--success); }
html.dark-mode .ph-floppy-disk { color: #4ADE80; }

/* ── X de cerrar de los diálogos ──────────────────────────────────────────
   Era TEXTO (`×`) dentro de un flex con `line-height` heredado: el glifo caía
   por debajo del centro. Se centra por grid + line-height 1, y el foco deja de
   pintarse azul (usaba `--btn-primary-bg`, que ahora es el glaciar) — al dar
   Enter se veía azul. */
html .dlg-close,
html .crm-modal-x {
    display: grid;
    place-items: center;
    padding: 0;
    line-height: 1;
    font-size: 17px;
    color: var(--text-dim);
    border: 1px solid transparent;
    background: transparent;
    border-radius: 10px;
}
html .dlg-close:hover,
html .crm-modal-x:hover { background: var(--surface-2); color: var(--text); }
html .dlg-close:focus,
html .dlg-close:focus-visible,
html .crm-modal-x:focus,
html .crm-modal-x:focus-visible {
    outline: none;
    color: var(--text);
    box-shadow: 0 0 0 3px var(--accent-soft);
}
html.dark-mode .dlg-close:hover,
html.dark-mode .crm-modal-x:hover { background: rgba(255, 255, 255, 0.08); }

/* Los botones de guardar de los mensajes (data-save) llevan el check en verde. */
[data-save] i, .krav-msg-foot .btn i { color: var(--success); }
html.dark-mode [data-save] i, html.dark-mode .krav-msg-foot .btn i { color: #4ADE80; }

/* ── Selector "Filas" del timeline (`Gestión de Crédito`) ─────────────────
   El CONTROL es la píldora entera, no el numerito. `.kg-tam` muestra la
   etiqueta + el valor y el `<select>` se estira por ENCIMA de toda la caja,
   transparente: así el despliegue abre desde cualquier punto del botón y sólo
   hay UN chevron (el `.kg-tam::after`).
   Ojo con la cascada: `html.dark-mode select` (más abajo) repone el chevron
   nativo como `background-image` y con `.kg-tam select` había EMPATE de
   especificidad ganando por orden ⇒ en dark salían DOS selectores. Por eso
   estas reglas van con `html body`. */
html body .kg-tam {
    position: relative;
    height: 30px;
    padding: 0 24px 0 10px;
    gap: 5px;
    font-size: 10.5px;
}
html body .kg-tam-val {
    color: var(--text);
    font-size: 11px;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    min-width: 14px;
}
html body .kg-tam select {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    opacity: 0;
    appearance: none;
    -webkit-appearance: none;
    background: none;
    background-color: transparent;
    background-image: none;
    border: 0;
    border-radius: inherit;
    box-shadow: none;
    color: var(--text);
    cursor: pointer;
}
html.dark-mode body .kg-tam { background: rgba(255, 255, 255, 0.06); border-color: rgba(255, 255, 255, 0.12); }
html body .kg-tam:focus-within {
    border-color: var(--ice-400);
    box-shadow: 0 0 0 3px var(--accent-soft);
}
html body .kg-tam::after {
    content: "";
    position: absolute;
    right: 9px;
    top: 50%;
    width: 10px;
    height: 10px;
    margin-top: -5px;
    background-color: currentColor;
    opacity: 0.55;
    pointer-events: none;
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 9.5l6 6 6-6' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/contain no-repeat;
            mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 9.5l6 6 6-6' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center/contain no-repeat;
}

/* El check de guardar va VERDE sólo sobre botones claros: sobre el azul glaciar
   y sobre los sólidos, el icono debe quedar del color del texto (blanco). */
.ph-floppy-disk { color: inherit; }
html .btn-secondary .ph-floppy-disk,
html .btn-ghost .ph-floppy-disk,
html .btn-light .ph-floppy-disk,
html [data-save] i { color: var(--success); }
html.dark-mode .btn-secondary .ph-floppy-disk,
html.dark-mode .btn-ghost .ph-floppy-disk,
html.dark-mode [data-save] i { color: #4ADE80; }
html.dark-mode .ph-floppy-disk { color: inherit; }

/* Divisor de Datos maestros: la vertical caía casi sobre "Verificador de
   teléfonos". Se separa con aire a cada lado. */
@media (min-width: 1024px) {
    html .dm-sec { padding: 18px 20px; }
    html .dm-sec:first-child { padding-right: 28px; }
    html .dm-sec + .dm-sec { padding-left: 30px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   SHELL ESTABLE — la barra de búsqueda, el chip de semana y la fila de cards
   de arriba NO cambian de sitio ni de tamaño al cambiar de vista.

   1) El carril de la barra de scroll se reserva SIEMPRE (`both-edges`), así
      una vista corta y una larga miden lo mismo y lo centrado no se corre.
   2) La búsqueda deja de ser `width:100%`: ancho fijo, no negociado con los
      hermanos.
   3) El chip de semana ya era absoluto; se ancla al borde izquierdo de la
      barra (calculado desde el centro) para que no dependa del contenedor.
   4) Las filas de cards toman alto mínimo y columnas iguales, sin que una
      tarjeta con más texto estire a las demás.
   ═══════════════════════════════════════════════════════════════════════════ */
html { scrollbar-gutter: stable both-edges; }

html .edx-search {
    flex: 0 0 auto;
    width: 646px;
    max-width: min(646px, calc(100% - 32px));
}

html .edx-week-chip {
    right: calc(50% + 323px + 14px);
    left: auto;
}

html .kpi-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    align-items: stretch;
}
html .kpi-grid > * { min-width: 0; }

/* ── Cobranza pegada a la barra ────────────────────────────────────────────
   Estaba anclada a `right: 0` del topbar, o sea al borde del contenedor: entre
   la barra y el óvalo quedaba un hueco de ~300 px. Ahora cuelga del borde
   derecho de la barra (646 px, centrada), así que el aire es siempre el mismo
   sin importar el ancho del panel. */
html .edx-cobranza {
    right: auto;
    left: calc(50% + 323px + 16px);
}
@media (max-width: 1339px) {
    html .edx-cobranza { display: none; }
}

/* La barra de scroll SIEMPRE reservada también por `overflow-y: scroll`: en
   Safari `scrollbar-gutter` no reserva simétrico y el contenedor medía 951 px
   en una vista larga y 966 en una corta — eso era lo que redimensionaba las
   cards de arriba al cambiar de panel. */
html { overflow-y: scroll; }

/* El panel largo scrollea en `.edx-shell` y el corto no: ese fue el 15 px que
   redimensionaba las 3 cards y el topbar entre paneles. Se reserva el carril en
   el contenedor que de verdad scrollea. */
html .edx-shell { scrollbar-gutter: stable both-edges; }
html .edx-main  { scrollbar-gutter: stable both-edges; }

/* El scroll lo lleva el SHELL, no el documento: se declara aquí para que el
   carril quede reservado siempre y el contenido no cambie de ancho entre un
   panel largo y uno corto. */
html .edx-shell {
    overflow-y: auto;
    scrollbar-gutter: stable;
    height: 100vh;
}
html body { overflow: hidden; }

/* CTA del login: un poco más chico (venía de 64 px de alto). */
html .btn.btn-login {
    padding: 16px 26px;
    font-size: 16px;
    min-height: 54px;
    margin-top: 24px;
}

/* ── La X de cerrar, un solo estilo (referencia: el popup de Tiendas) ──────
   Todos los cierres usan el MISMO botón: 30×30, radio 10, sin borde ni fondo,
   icono IconSax `x` de 16 px, hover `--surface-2` y foco neutro. Antes los
   `.dlg-close` pintaban la letra `×` y los `.crm-modal-x` el icono: se veían
   distintos. */
html .dlg-close,
html .crm-modal-x {
    width: 30px;
    height: 30px;
    display: grid;
    place-items: center;
    padding: 0;
    border: 1px solid transparent;
    border-radius: 10px;
    background: transparent;
    color: var(--text-dim);
    line-height: 1;
    transition: background-color 140ms var(--sidebar-easing), color 140ms var(--sidebar-easing);
}
html .dlg-close i,
html .crm-modal-x i { font-size: 16px; line-height: 1; }
html .dlg-close:hover,
html .crm-modal-x:hover { background: var(--surface-2); color: var(--text); }
html.dark-mode .dlg-close:hover,
html.dark-mode .crm-modal-x:hover { background: rgba(255, 255, 255, 0.08); }

/* El cierre del panel de "Recuperar contraseña" del login, igual que los demás. */
html .reset-close {
    display: grid;
    place-items: center;
    width: 30px;
    height: 30px;
    padding: 0;
    line-height: 1;
    border: 1px solid transparent;
    border-radius: 10px;
    background: transparent;
    color: var(--text-dim);
}
html .reset-close i { font-size: 16px; line-height: 1; }
html .reset-close:hover { background: var(--surface-2); color: var(--text); }

/* ═══════════════════════════════════════════════════════════════════════════
   DARK · controles nativos sin "caja gris" ni flechas propias
   Los `select` mostraban un rectángulo gris interno con dos flechas: es el
   indicador NATIVO del motor (spinner de number y picker de fecha), que en
   oscuro se pinta con el gris del sistema. Se apagan los nativos y se deja
   sólo el chevron dibujado por el sistema.
   ═══════════════════════════════════════════════════════════════════════════ */
html.dark-mode { color-scheme: dark; }

/* Flechas del input numérico */
html input[type="number"] { -moz-appearance: textfield; }
html input[type="number"]::-webkit-inner-spin-button,
html input[type="number"]::-webkit-outer-spin-button {
    -webkit-appearance: none;
    appearance: none;
    margin: 0;
}

/* ── Selector de fecha: el icono se ve en los dos temas ───────────────────
   El indicador nativo (::-webkit-calendar-picker-indicator) se estira sobre
   el campo para que el glifo del calendario caiga en el borde derecho de la
   caja; su dibujo propio (el que pinta el motor) se sustituye por un SVG con
   el trazo de cada tema. En dark el nativo se pintaba con el gris del sistema
   y el `invert()` que había lo dejaba casi negro — invisible sobre
   --surface-2. Un solo dibujo, dos colores.
   OJO: el indicador estirado NO recibe los clics (se comprobó con clic real:
   cae en el segmento de texto). Quien abre el calendario desde cualquier
   punto del campo es `js/fechas.js` con `showPicker()`.
   El campo de móvil (`body.edx-movil`) queda fuera: movil.css deshace esta
   posición absoluta, porque ahí el indicador vive dentro de una fila flex. */
html body input[type="date"],
html body input[type="month"],
html body input[type="week"],
html body input[type="datetime-local"] {
    position: relative;
}

html body input[type="date"]::-webkit-calendar-picker-indicator,
html body input[type="month"]::-webkit-calendar-picker-indicator,
html body input[type="week"]::-webkit-calendar-picker-indicator,
html body input[type="datetime-local"]::-webkit-calendar-picker-indicator {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    opacity: 1;
    cursor: pointer;
    background-color: transparent;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23475569' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'><rect x='3' y='4.5' width='18' height='16' rx='3'/><path d='M8 2.5v4M16 2.5v4M3 9.5h18'/></svg>");
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-size: 15px 15px;
}
html.dark-mode body input[type="date"]::-webkit-calendar-picker-indicator,
html.dark-mode body input[type="month"]::-webkit-calendar-picker-indicator,
html.dark-mode body input[type="week"]::-webkit-calendar-picker-indicator,
html.dark-mode body input[type="datetime-local"]::-webkit-calendar-picker-indicator {
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23A9B2BF' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'><rect x='3' y='4.5' width='18' height='16' rx='3'/><path d='M8 2.5v4M16 2.5v4M3 9.5h18'/></svg>");
}

/* `time` conserva su indicador nativo SIN estirar: el glifo del reloj es el
   propio indicador, así que al ocupar toda la caja se dibujaba un reloj
   gigante encima del texto. Con `color-scheme: dark` ya se pinta claro. */
html body input[type="time"] { position: relative; }

/* `select`: el nativo fuera, el chevron del sistema dentro — también cuando una
   regla de página pisa el fondo con el shorthand `background`. */
html.dark-mode select {
    -webkit-appearance: none;
    appearance: none;
    background-color: var(--surface-2);
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%239CA3AF' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9.5l6 6 6-6'/></svg>");
    background-repeat: no-repeat;
    background-position: right 12px center;
    background-size: 14px;
    padding-right: 36px;
    color: var(--text);
}
html.dark-mode select::-ms-expand { display: none; }
html.dark-mode select option { background: #232730; color: #E7E9EC; }

/* ── Login: la píldora es el campo, no hay caja dentro ─────────────────────
   `.input-pill` seguía con el fondo claro que traía (rgb 239,239,239) y el
   `input` de dentro pintaba además su propio fondo: en oscuro eso se leía como
   un CUADRO GRIS metido dentro del campo. Aquí el wrapper es la superficie y el
   input queda transparente, en los dos temas. */
html body .input-pill { background: var(--surface); border-color: var(--border-strong); }
html body .input-pill:focus-within {
    background: var(--surface);
    border-color: var(--ice-400);
    box-shadow: 0 0 0 3px var(--accent-soft);
}
html body .input-pill input,
html body .input-pill textarea {
    background-color: transparent;
    background-image: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    -webkit-appearance: none;
    appearance: none;
    color: var(--text);
    caret-color: var(--text);
    width: 100%;
}
html body .input-pill input::placeholder { color: var(--text-dim-2); }
/* Autofill de Chrome/Safari: sin el lavado amarillo ni la caja interna */
html body .input-pill input:-webkit-autofill,
html body .input-pill input:-webkit-autofill:hover,
html body .input-pill input:-webkit-autofill:focus {
    -webkit-text-fill-color: var(--text);
    -webkit-box-shadow: 0 0 0 100px var(--surface-2) inset;
    transition: background-color 9999s ease-out;
}
html.dark-mode body .input-pill { background: #232730; border-color: rgba(255, 255, 255, 0.14); }
html.dark-mode body .input-pill:focus-within { background: rgba(255, 255, 255, 0.10); }
html.dark-mode body .input-pill input:-webkit-autofill,
html.dark-mode body .input-pill input:-webkit-autofill:focus {
    -webkit-box-shadow: 0 0 0 100px #232730 inset;
}

/* La página de login define `.input-pill` en su propio <style> (con la paleta
   del cristal) y gana por orden a la hoja global: aquí se fuerza, sólo para
   estas dos propiedades, que la píldora sea la superficie y el input no pinte
   caja dentro. Sin `!important` no hay forma de ganarle desde edx.css. */
html body .input-pill { background: var(--surface) !important; }
html.dark-mode body .input-pill { background: #232730 !important; border-color: rgba(255,255,255,.14) !important; }
html body .input-pill input,
html body .input-pill textarea {
    background: transparent !important;
    background-image: none !important;
    border: 0 !important;
    box-shadow: none !important;
}

/* Ajustes del login: el CTA 2 px más bajo y las etiquetas un punto más chicas. */
html .btn.btn-login { padding: 15px 26px; min-height: 52px; }
html .input-pill-label { font-size: 10px; font-weight: 500; margin-bottom: 5px; }

/* "Ingresa tu usuario" / "Ingresa tu contraseña" son PLACEHOLDERS: se bajan
   un punto sin tocar la letra que se escribe dentro del campo. */
html body .input-pill input::placeholder,
html body .input-pill input::-webkit-input-placeholder { font-size: 14px; }

/* ── Tabla "Cuentas en periodo vacacional" (Planchados) más compacta ─────── */
html .vac-lista-head { padding: 9px 12px; }
html .vac-lista-head > span:first-child { font-size: 12px; }
html .vac-count { min-width: 20px; height: 17px; padding: 0 7px; font-size: 10px; }
html .vac-tbl th { padding: 6px 10px; font-size: 9.5px; letter-spacing: 0.04em; }
html .vac-tbl td { padding: 6px 10px; font-size: 11.5px; }
html .vac-id { font-size: 11px; }
html .vac-asesor { font-size: 11.5px; }
html .vac-fecha { font-size: 11px; }
html .vac-tbl th:last-child,
html .vac-tbl td:last-child { width: 38px; }
html .vac-quitar { width: 24px; height: 24px; border-radius: 7px; }
html .vac-quitar > i { font-size: 12px; }
html .vac-empty { padding: 14px 12px; font-size: 11.5px; }


/* ═══════════════════════════════════════════════════════════════════════════
   CABECERA DE VISTA más compacta (la "top card" del título)
   Aplica a todas las vistas MENOS el Detalle de Cliente, que tiene su propia
   cabecera y no se toca: se excluye con `:has(#panel-credito)`.
   ═══════════════════════════════════════════════════════════════════════════ */
body:not(:has(#panel-credito)) .page-header-v10 {
    gap: 12px;
    margin: 12px 0 18px 0;
    padding: 11px 14px;
    border-radius: 14px;
}
body:not(:has(#panel-credito)) .page-header-v10-icon {
    width: 34px;
    height: 34px;
    border-radius: 10px;
}
body:not(:has(#panel-credito)) .page-header-v10-icon i { font-size: 17px; }
body:not(:has(#panel-credito)) .page-h1 { font-size: 18px; letter-spacing: -0.015em; }
body:not(:has(#panel-credito)) .page-h1-sub { font-size: 11.5px; margin-top: 1px; }

/* ── Barra de búsqueda: borde más grueso y acento del sistema al enfocar ───
   Antes: 2 px y al enfocar usaba `--ice-600` con un anillo azul genérico.
   Ahora: 2.5 px de borde y el foco se pinta con el ACENTO glaciar (#34708F)
   en claro y en oscuro, con halo suave del mismo tono. */
html .edx-search-input {
    border: 2.5px solid var(--border-strong);
    transition: border-color .18s var(--sidebar-easing),
                box-shadow .18s var(--sidebar-easing),
                background-color .18s var(--sidebar-easing);
}
html .edx-search-input:hover { border-color: var(--text-dim-2); }
html .edx-search-input:focus,
html .edx-search:focus-within .edx-search-input {
    border-color: var(--ice-600);
    box-shadow: 0 0 0 4px rgba(52, 112, 143, 0.18);
}
html.dark-mode .edx-search-input { border-color: rgba(255, 255, 255, 0.18); }
html.dark-mode .edx-search-input:hover { border-color: rgba(255, 255, 255, 0.30); }
html.dark-mode .edx-search-input:focus,
html.dark-mode .edx-search:focus-within .edx-search-input {
    border-color: #5E9DBB;
    box-shadow: 0 0 0 4px rgba(94, 157, 187, 0.28);
}

/* Borde de la barra de búsqueda con especificidad suficiente para ganar al
   reset de campos y al foco por defecto. */
html body .edx-search-input {
    border: 2.5px solid var(--border-strong);
}
html body .edx-search-input:hover { border-color: var(--text-dim-2); }
html body .edx-search-input:focus,
html body .edx-search:focus-within .edx-search-input {
    border: 2.5px solid var(--ice-600);
    box-shadow: 0 0 0 4px rgba(52, 112, 143, 0.18);
}
html.dark-mode body .edx-search-input { border-color: rgba(255, 255, 255, 0.18); }
html.dark-mode body .edx-search-input:hover { border-color: rgba(255, 255, 255, 0.30); }
html.dark-mode body .edx-search-input:focus,
html.dark-mode body .edx-search:focus-within .edx-search-input {
    border-color: #5E9DBB;
    box-shadow: 0 0 0 4px rgba(94, 157, 187, 0.28);
}

/* ── Dark: la barra de búsqueda NO tiene relleno propio ────────────────────
   Pintaba `--surface` (#1A1D23) dentro de un shell `--bg` (#0F1115) y se leía
   como un bloque gris encima del fondo. Con el borde de 2.5 px el campo ya
   está definido; el relleno vuelve sólo al enfocar, como acuse del foco. */
html.dark-mode .edx-search-input,
html.dark-mode body .edx-search-input,
body.dark-mode .edx-search-input {
    background-color: transparent;
}
html.dark-mode .edx-search-input:focus,
html.dark-mode body .edx-search-input:focus,
html.dark-mode .edx-search:focus-within .edx-search-input {
    background-color: rgba(255, 255, 255, 0.04);
}

/* ═══════════════════════════════════════════════════════════════════════════
   ANUNCIO A PANTALLA COMPLETA (base.html · anuncios.js)
   ───────────────────────────────────────────────────────────────────────────
   Overlay que se abre a TODO el equipo cuando un anuncio está en su franja.
   El cierre es una salida fluida (opacidad + escala) y se desactiva con
   `prefers-reduced-motion`. Una sola superficie (`.anuncio-shell`) con el
   archivo grande y el botón de cerrar en la cabecera: sin `×` de carácter,
   icono IconSax como en el resto de los diálogos.
   ═══════════════════════════════════════════════════════════════════════════ */
.anuncio-overlay {
    position: fixed; inset: 0; z-index: 90;
    display: grid; place-items: center; padding: 24px;
    background: rgba(6, 8, 12, .70);
    -webkit-backdrop-filter: blur(10px) saturate(.9);
    backdrop-filter: blur(10px) saturate(.9);
    opacity: 0;
    transition: opacity 260ms cubic-bezier(.2, .8, .2, 1);
}
html.dark-mode .anuncio-overlay,
body.dark-mode .anuncio-overlay { background: rgba(0, 0, 0, .82); }
.anuncio-overlay.is-in { opacity: 1; }
.anuncio-overlay.is-out { opacity: 0; }

.anuncio-shell {
    position: relative; display: flex; flex-direction: column;
    width: min(1100px, 94vw); max-height: 92vh;
    background: var(--surface); color: var(--text);
    border: 1px solid var(--border-strong); border-radius: 20px;
    box-shadow: 0 40px 90px rgba(4, 8, 16, .45),
                inset 0 0 0 1px rgba(255, 255, 255, .06);
    overflow: hidden;
    transform: translateY(14px) scale(.965); opacity: 0;
    transition: transform 320ms cubic-bezier(.2, .8, .2, 1), opacity 240ms ease;
}
.anuncio-overlay.is-in .anuncio-shell { transform: none; opacity: 1; }
.anuncio-overlay.is-out .anuncio-shell {
    transform: translateY(10px) scale(.972); opacity: 0;
    transition-duration: 200ms;
}
html.dark-mode .anuncio-shell,
body.dark-mode .anuncio-shell {
    box-shadow: 0 40px 90px rgba(0, 0, 0, .65),
                inset 0 1px 0 rgba(255, 255, 255, .10);
}

.anuncio-head {
    display: flex; align-items: center; gap: 10px;
    padding: 12px 14px 12px 16px;
    border-bottom: 1px solid var(--border);
}
.anuncio-tag {
    display: inline-flex; align-items: center; gap: 7px;
    font-size: 10.5px; font-weight: 600; color: var(--text-dim);
}
.anuncio-tag i { color: var(--ice-600); font-size: 14px; }
html.dark-mode .anuncio-tag i { color: var(--ice-200); }

.anuncio-close {
    margin-left: auto; display: grid; place-items: center;
    width: 34px; height: 34px; border-radius: 10px;
    border: 1px solid transparent; background: transparent;
    color: var(--text); font-size: 16px; cursor: pointer;
    transition: background 140ms var(--sidebar-easing),
                border-color 140ms var(--sidebar-easing), transform 120ms ease;
}
.anuncio-close:hover { background: var(--surface-2); border-color: var(--border); }
.anuncio-close:active { transform: scale(.94); }
.anuncio-close:focus-visible {
    outline: none; border-color: var(--border-strong);
    box-shadow: 0 0 0 3px var(--accent-soft);
}

/* El archivo manda: `anuncios.js` mide su proporción real y fija `--an-w` /
   `--an-h` en el shell, así el marco se ajusta a la imagen (un póster vertical
   queda vertical, sin franjas negras a los lados). El ancho es el de la MEDIA,
   no el de la pantalla. */
.anuncio-media {
    display: block; flex: none; min-height: 0; margin: 0; padding: 0;
    width: 100%; height: var(--an-h, 320px);
    background: var(--surface-2); overflow: hidden; line-height: 0;
}
.anuncio-media img {
    display: block; width: 100%; height: 100%;
    object-fit: contain; object-position: center; border-radius: 0;
}
.anuncio-media iframe {
    display: block; width: 100%; height: 100%; border: 0; border-radius: 0;
    background: var(--surface);
}

/* Título y descripción comparten el ancho del archivo. En tarjetas angostas
   (póster) bajan un paso para no robar alto a la imagen; en cualquier caso se
   limitan a 2 y 3 renglones para que el marco nunca desborde la pantalla. */
.anuncio-foot { padding: 12px 18px 16px; border-top: 1px solid var(--border); }
.anuncio-foot h2 {
    margin: 0; font-size: 16px; font-weight: 600; line-height: 1.3;
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden;
}
.anuncio-foot p {
    margin: 4px 0 0; font-size: 12.5px; line-height: 1.5; color: var(--text-dim);
    display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
    overflow: hidden;
}
.anuncio-shell--angosto .anuncio-head { padding: 10px 12px 10px 15px; }
.anuncio-shell--angosto .anuncio-tag { font-size: 10.5px; }
.anuncio-shell--angosto .anuncio-close { width: 30px; height: 30px; font-size: 15px; }
.anuncio-shell--angosto .anuncio-foot { padding: 12px 16px 15px; }
.anuncio-shell--angosto .anuncio-foot h2 { font-size: 15.5px; }
.anuncio-shell--angosto .anuncio-foot p { font-size: 12px; -webkit-line-clamp: 2; }
body.anuncio-abierto { overflow: hidden; }

@media (max-width: 640px) {
    .anuncio-overlay { padding: 10px; }
    .anuncio-shell {
        max-width: calc(100vw - 20px);
        max-height: calc(100dvh - 20px);
        border-radius: 16px;
    }
    .anuncio-foot { padding: 10px 14px 13px; }
    .anuncio-foot h2 { font-size: 14.5px; }
    .anuncio-foot p { font-size: 11.5px; -webkit-line-clamp: 2; }
}

@media (prefers-reduced-motion: reduce) {
    .anuncio-overlay, .anuncio-shell { transition: opacity 120ms linear; }
    .anuncio-shell,
    .anuncio-overlay.is-in .anuncio-shell,
    .anuncio-overlay.is-out .anuncio-shell { transform: none; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   DESCARGA EN PANTALLA (descargas.js · enlaces con `data-descarga`)
   ───────────────────────────────────────────────────────────────────────────
   Las descargas del servidor (Accionamiento, Comportamiento del portafolio:
   ~125 k filas / 20 s) se generan antes de mandar el primer byte, así que el
   navegador no da ninguna señal y parecía que el botón no hacía nada. Esta
   tarjeta vive mientras el archivo se arma y se mueve: barra indeterminada
   mientras el servidor genera, porcentaje real cuando empiezan a llegar
   bytes. Una sola superficie, tokens del sistema, se retira sola al guardar
   el archivo.
   ═══════════════════════════════════════════════════════════════════════════ */
.edx-dl {
    position: fixed; inset: 0; z-index: 95;
    display: grid; place-items: center; padding: 24px;
    background: rgba(6, 8, 12, .55);
    -webkit-backdrop-filter: blur(8px) saturate(.9);
    backdrop-filter: blur(8px) saturate(.9);
    opacity: 0;
    transition: opacity 220ms cubic-bezier(.2, .8, .2, 1);
}
html.dark-mode .edx-dl { background: rgba(0, 0, 0, .70); }
.edx-dl.is-in { opacity: 1; }

.edx-dl-card {
    display: flex; align-items: flex-start; gap: 14px;
    width: min(400px, 92vw);
    padding: 18px 20px 17px;
    background: var(--surface);
    border: 1px solid var(--border-strong);
    border-radius: 18px;
    box-shadow: 0 30px 70px rgba(4, 8, 16, .38),
                inset 0 0 0 1px rgba(255, 255, 255, .06);
    transform: translateY(10px) scale(.98);
    transition: transform 260ms cubic-bezier(.2, .8, .2, 1);
}
.edx-dl.is-in .edx-dl-card { transform: none; }
html.dark-mode .edx-dl-card {
    box-shadow: 0 30px 70px rgba(0, 0, 0, .6),
                inset 0 1px 0 rgba(255, 255, 255, .10);
}

.edx-dl-ico {
    flex: none; display: grid; place-items: center;
    width: 38px; height: 38px; border-radius: 12px;
    background: var(--ice-100); color: var(--ice-700);
    border: 1px solid var(--border);
    font-size: 19px;
}
html.dark-mode .edx-dl-ico {
    background: rgba(255, 255, 255, .06);
    color: var(--ice-200);
    border-color: var(--border-strong);
}
.edx-dl-ico i { animation: edx-dl-spin 900ms linear infinite; }
.edx-dl.is-error .edx-dl-ico { background: rgba(220, 38, 38, .12); color: var(--danger); }
.edx-dl.is-error .edx-dl-ico i { animation: none; }

.edx-dl-body { flex: 1 1 auto; min-width: 0; }
.edx-dl-title {
    margin: 1px 0 0; font-size: 13.5px; font-weight: 600;
    color: var(--text); line-height: 1.35;
}
.edx-dl-msg {
    margin: 3px 0 0; font-size: 11.8px; font-weight: 500;
    color: var(--text-dim); line-height: 1.45;
}

.edx-dl-bar {
    position: relative; height: 6px; margin: 12px 0 0;
    border-radius: 999px; background: var(--chart-track); overflow: hidden;
}
.edx-dl-bar > span {
    display: block; height: 100%; width: 0;
    border-radius: 999px; background: var(--ice-600);
    transition: width 240ms cubic-bezier(.4, 0, .2, 1);
}
html.dark-mode .edx-dl-bar > span { background: var(--ice-300); }
/* Sin bytes todavía ⇒ barra indeterminada (el servidor está generando). */
.edx-dl-bar.is-indi > span {
    width: 38%;
    animation: edx-dl-slide 1.15s cubic-bezier(.5, 0, .5, 1) infinite;
}

.edx-dl-meta {
    display: flex; align-items: baseline; gap: 6px;
    margin: 7px 0 0; font-size: 10.5px; font-weight: 600;
    color: var(--text-dim-2);
    font-variant-numeric: tabular-nums;
}
.edx-dl-pct { color: var(--text-dim); }

@keyframes edx-dl-spin { to { transform: rotate(360deg); } }
@keyframes edx-dl-slide {
    0%   { transform: translateX(-100%); }
    100% { transform: translateX(320%); }
}
@media (prefers-reduced-motion: reduce) {
    .edx-dl, .edx-dl-card { transition: opacity 100ms linear; transform: none; }
    .edx-dl-ico i { animation: none; }
    .edx-dl-bar.is-indi > span { animation: none; width: 100%; opacity: .5; }
}

/* Reintento del overlay de descarga: sólo aparece si la generación falló. */
.edx-dl.is-error .edx-dl-bar { display: none; }
.edx-dl-acciones { display: flex; align-items: center; gap: 8px; margin-top: 12px; }
.edx-dl-retry,
.edx-dl-cerrar {
    display: inline-flex; align-items: center; justify-content: center;
    padding: 7px 12px; border-radius: 10px;
    background: var(--surface-2); color: var(--text);
    border: 1px solid var(--border-strong);
    font-family: inherit; font-size: 11.5px; font-weight: 600;
    text-decoration: none; cursor: pointer;
    transition: background 140ms var(--sidebar-easing),
                border-color 140ms var(--sidebar-easing);
}
.edx-dl-retry:hover,
.edx-dl-cerrar:hover { background: var(--surface-3); border-color: var(--text-dim-2); }
.edx-dl-cerrar { background: transparent; color: var(--text-dim); }
