/* ============================================================
   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: Satoshi display (Fontshare, 300-900 para jerarquía).
   ============================================================ */

/* Satoshi desde Fontshare (https://www.fontshare.com/fonts/satoshi).
   Fuente display geometrica de Indian Type Foundry, moderna y versatil.
   Estrategia de pesos:
     300 Light    - etiquetas uppercase pequenas, hint text, .muted
     400 Regular  - cuerpo (parrafos, body)
     500 Medium   - texto con emphasis sutil (.user-name)
     600 SemiBold - nav links, botones, thead
     700 Bold     - titulos (h1, h2), mensajes flash
     800 ExtraBold- wordmark "Expectra" en el sidebar
     900 Black    - logo del login (impacto visual) */
@import url('https://api.fontshare.com/v2/css?f[]=satoshi@300;400;500;600;700;800;900&display=swap');

:root {
    --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);
    --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:       #C4C7CB;
    --shell-panel-border:   #E5E5E5;

    /* 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);
    --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: "Satoshi", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
    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;
    background:
        linear-gradient(180deg, var(--sidebar-bg-top) 0%, var(--sidebar-bg-bottom) 100%),
        var(--sidebar-bg);
    border-bottom: 1px solid var(--sidebar-border);
    box-sizing: border-box;
    display: flex;
    flex-direction: column;
    z-index: 50;
    font-family: "Satoshi", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
    /* 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 {
    padding: 16px 14px 14px;
    border-bottom: 1px solid var(--sidebar-border);
    flex-shrink: 0;
}

.edx-sidebar-brand {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    color: var(--sidebar-text);
    padding: 6px 8px 8px;
    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); }

/* Título del rail: Satoshi 600 · 12px · tracking 0.32em · uppercase
   (la misma firma tipográfica que usaba el wordmark y el footer del login).
   Es el ÚNICO texto del bloque: los logos van debajo, sin copy. */
.edx-sidebar-title {
    font-size: 12px;
    font-weight: 600;
    line-height: 1;
    color: var(--sidebar-text);
    letter-spacing: 0.32em;
    text-transform: uppercase;
    white-space: nowrap;
    /* el tracking deja un hueco fantasma tras la última letra: se compensa
       para que el título quede ópticamente centrado, no de caja */
    padding-left: 0.32em;
    transition: color var(--sidebar-duration) var(--sidebar-easing);
}

/* Lockup de las dos marcas — MISMAS proporciones que el del login
   (.login-brand: E recortada a su silueta · divisor difuminado · logo Coveyp),
   escalado ×0.619 para caber en el rail de 220 px (150 × 57 px).
   Si cambia el tamaño del login, recalcular con el mismo factor. */
.edx-sidebar-lockup {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0;
}
.edx-sidebar-lockup .lockup-e {
    position: relative;
    flex: none;
    /* Silueta 52.08 × 57.19 px: +1 px de aire por lado para no afeitar el
       antialias del borde izquierdo/inferior (el divisor baja 1 px por lado). */
    width: 54.1px;
    height: 59.2px;
    overflow: hidden; /* recorta el margen interno asimétrico del SVG 80×80 */
}
.edx-sidebar-lockup .lockup-e svg {
    position: absolute;
    left: -15.3px;  /* 16/80 × 81.7 − 1 px de aire */
    top: -17.4px;   /* 18/80 × 81.7 − 1 px de aire */
    width: 81.7px;
    height: 81.7px;
    filter: none;
}
.edx-sidebar-lockup .lockup-coveyp {
    flex: none;
    display: block;
    height: 57.2px;   /* la MISMA altura que la E: los dos logos quedan al ras */
    width: auto;
}
/* El logo Coveyp es arte raster entregado por el despacho (carbón + verde
   salvia, con su propia sombra), así que el tema elige el archivo: claro =
   tinta oscura sobre fondo claro, dark = tinta clara sobre fondo oscuro.
   Sin placa ni filtros: cada PNG ya está dibujado para su fondo.
   Se generan con `scripts/gen_marca_coveyp.py`. */
.edx-sidebar-lockup .lockup-coveyp--dark { display: none; }
html.dark-mode .edx-sidebar-lockup .lockup-coveyp--light,
body.dark-mode .edx-sidebar-lockup .lockup-coveyp--light { display: none; }
html.dark-mode .edx-sidebar-lockup .lockup-coveyp--dark,
body.dark-mode .edx-sidebar-lockup .lockup-coveyp--dark { display: block; }
.edx-sidebar-lockup .lockup-split {
    flex: none;
    width: 1px;
    height: 42.2px;
    margin: 0 16.7px;   /* 17.7 − 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%);
}

/* Dark mode: la E pasa a blanco y el divisor invierte a blanco translúcido.
   El logo Coveyp no necesita nada: tiene su propio archivo oscuro. */
html.dark-mode .edx-sidebar-lockup .lockup-e svg,
body.dark-mode .edx-sidebar-lockup .lockup-e svg {
    filter: invert(1) hue-rotate(180deg) brightness(1.1);
}
html.dark-mode .edx-sidebar-lockup .lockup-split,
body.dark-mode .edx-sidebar-lockup .lockup-split {
    background: linear-gradient(180deg,
        rgba(255, 255, 255, 0) 0%,
        rgba(255, 255, 255, 0.30) 50%,
        rgba(255, 255, 255, 0) 100%);
}

.edx-sidebar-nav {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 12px 10px;
    border-bottom: 1px solid var(--sidebar-border);
    display: flex;
    flex-direction: column;
    gap: 11px;
    min-height: 0;
}
.edx-sidebar-nav::-webkit-scrollbar { width: 6px; }
.edx-sidebar-nav::-webkit-scrollbar-track { background: transparent; }
.edx-sidebar-nav::-webkit-scrollbar-thumb {
    background: var(--sidebar-border-hover);
    border-radius: 9999px;
}

.edx-nav-link {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 9px 10px 9px 13px;
    border-radius: var(--sidebar-radius);
    color: var(--sidebar-muted);
    font-size: 13px;
    font-weight: 500;
    text-decoration: none;
    border: 1px solid transparent;
    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(--sidebar-bg-hover);
    color: var(--sidebar-text);
}
.edx-nav-link:active {
    background: var(--sidebar-bg-active);
}
.edx-nav-link.is-active {
    background: var(--sidebar-bg-active);
    color: var(--sidebar-text);
    font-weight: 600;
    border-color: var(--sidebar-border);
    border-left-color: var(--sidebar-accent);
    border-left-width: 3px;
    padding-left: 10px;
}

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

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

.edx-sidebar-footer {
    border-top: 1px solid var(--sidebar-border);
    padding: 10px;
    margin-top: auto;
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex-shrink: 0;
}
.edx-sidebar-user {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 6px 10px;
    border-radius: var(--sidebar-radius);
    background: var(--sidebar-bg-hover);
    border: 1px solid transparent;
    transition: background var(--sidebar-duration) var(--sidebar-easing);
}
.edx-sidebar-user:hover { background: var(--sidebar-bg-active); }

/* 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: 8px;
    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); }

.edx-sidebar-status-dot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 8px;
    height: 8px;
    flex-shrink: 0;
}
.edx-sidebar-status-dot .dot {
    display: inline-block;
    width: 6px;
    height: 6px;
    border-radius: 9999px;
    background: var(--success);
    box-shadow: 0 0 0 2px rgba(22, 163, 74, 0.18);
}

.edx-sidebar-avatar {
    width: 26px;
    height: 26px;
    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: 700;
    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: 4px;
}

.edx-sidebar-logout {
    margin: 0;
    flex-shrink: 0;
}
.edx-logout-btn {
    width: 28px;
    height: 28px;
    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: 28px;
    height: 28px;
    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 0 0 6px;
}
.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"):
       Satoshi 600 SemiBold, 10px, tracking amplio, uppercase.
       Identidad visual consistente entre el footer del sidebar y el login. */
    font-family: "Satoshi", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
    font-size: 8px;
    font-weight: 600;
    font-style: italic;
    color: #4a4a52;
    letter-spacing: 0.32em;
    text-transform: uppercase;
    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: 800;
    letter-spacing: -0.04em;
}
.topnav-brand-text .esv {
    color: var(--text);
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.26em;
    text-transform: uppercase;
}

.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: 800;
    font-size: 15px;
}
.topnav-user-text { display: flex; flex-direction: column; line-height: 1; gap: 3px; }
.user-name {
    color: var(--text);
    font-weight: 700;
    font-size: 13px;
}
.user-status {
    color: var(--text-dim-2);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    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: 'JetBrains Mono', monospace;
    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: 16px 0 28px 0;
    padding: 14px 20px;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 12px;
    transition: border-color .2s ease, transform .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: 40px;
    height: 40px;
    border-radius: 10px;
    background: var(--bg);
    border: 1px solid var(--border);
    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;
    /* Estilo monoespaciado tipo "version badge" del topnav:
       JetBrains Mono, tracking ligero, uppercase. */
    font-family: 'JetBrains Mono', 'SF Mono', Consolas, monospace;
    font-size: 13px;
    font-weight: 500;
    letter-spacing: 0.20em;
    text-transform: uppercase;
    color: var(--text);
    flex-shrink: 0;
}
.page-h1-kicker {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--text-dim-2);
    flex-shrink: 0;
}
.page-h1-sub {
    margin: 0;
    color: var(--text-dim);
    font-size: 13px;
    font-weight: 400;
    line-height: 1.4;
}
.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: 700;
    letter-spacing: 0.10em;
    text-transform: uppercase;
    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: 800;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.card-edx-title {
    margin: 0;
    font-size: 20px;
    font-weight: 800;
    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: 700;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    margin-bottom: 8px;
}
.kpi-value {
    color: var(--text);
    font-size: 36px;
    font-weight: 800;
    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: 700;
    letter-spacing: 0.16em;
    color: var(--text);
    text-transform: uppercase;
}
.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: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    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: 700;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    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: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    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: 
}
.btn:hover { border-color: var(--accent); transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn-icon { font-size: 12px; opacity: 0.9; }

.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-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-secondary {
    background: var(--surface);
    border-color: var(--border);
    color: var(--text);
}
.btn-secondary:hover {
    background: var(--surface-2);
    border-color: var(--accent-line);
    color: var(--text);
}
.btn-danger {
    color: var(--danger);
    border-color: rgba(220, 38, 38, 0.30);
    background: rgba(220, 38, 38, 0.04);
}
.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.10em; }
.btn-login {
    width: 100%;
    margin-top: 24px;
    padding: 16px 24px;
    font-size: 14px;
    letter-spacing: 0.18em;
    /* 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);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    padding: 14px 18px;
    border-bottom: 1px solid var(--border);
    background: var(--surface-2);
}
.table th.num, .table td.num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}
.table td {
    padding: 14px 18px;
    border-bottom: 1px solid var(--border);
    color: var(--text);
}
.table tr:hover td {
    background: var(--accent-soft);
}
.table .empty-row {
    text-align: center;
    color: var(--text-dim-2);
    padding: 24px 14px;
}
.font-mono {
    font-family: 'JetBrains Mono', 'SF Mono', Consolas, monospace;
    font-size: 12px;
    color: var(--text-dim);
}
.text-dim { color: var(--text-dim); }
.text-accent { color: var(--text); }
.text-success { color: var(--success); }
.text-danger { color: var(--danger); }

/* ───────────── Alerts ───────────── */
.alert {
    margin-top: 14px;
    padding: 11px 18px;
    border-radius: 14px;
    background-color: var(--accent-soft);
    box-shadow: inset 0 0 0 1px var(--accent-line), 0 1px 2px rgba(15, 23, 42, 0.04), 0 4px 12px rgba(15, 23, 42, 0.04);
    color: #b8f0f3;
    font-size: 13px;
    font-weight: 500;
    text-align: center;
    letter-spacing: 0.01em;
}
.alert-success {
    background-color: rgba(48, 209, 88, 0.08);
    box-shadow: inset 0 0 0 1px rgba(48, 209, 88, 0.32),
                0 4px 12px rgba(48, 209, 88, 0.06);
    color: #b6f0c4;
}
.alert-error,
.alert-danger {
    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);
}

/* ───────────── 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: 800;
    letter-spacing: -0.045em;
}
.login-brand .esv {
    color: var(--text);
    font-size: 20px;
    font-weight: 700;
    letter-spacing: 0.25em;
    text-transform: uppercase;
}
.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 {
    /* Misma firma que el título del sidebar (.edx-sidebar-title):
       Satoshi 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: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    margin: 14px 0 6px 4px;
}
.login-show-pwd {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 14px;
    margin-left: 4px;
    color: var(--text-dim);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.04em;
    cursor: pointer;
}

/* "Recuérdame" — checkbox turquesa + hint secundario */
.login-remember {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 10px;
    margin-left: 4px;
    color: var(--text-dim);
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.04em;
    cursor: pointer;
}
.login-remember input[type="checkbox"] {
    accent-color: var(--accent);
    width: 16px;
    height: 16px;
    cursor: pointer;
}
.login-remember-hint {
    color: var(--text-dim-2);
    font-style: normal;
    font-weight: 400;
    margin-left: 2px;
}
.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: 700;
    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 {
    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: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
}

/* ───────────── 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 ───────────── */
select {
    background: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: 10px;
    padding: 10px 12px;
    color: var(--text);
    font-family: inherit;
    font-size: 14px;
    width: 100%;
}
select option { background: var(--surface-2); color: var(--text); }

/* ───────────── Messages (Django messages framework) ───────────── */
.messages {
    list-style: none;
    padding: 0;
    margin: 0 0 16px 0;
    max-width: 380px;   /* el flash no ocupa todo el ancho */
}
.messages li {
    margin-bottom: 8px;
    text-align: left;
}

/* ───────────── Barras de progreso (Bases · CGC) ───────────── */
.progress-bar {
    width: 100%;
    height: 6px;
    background: var(--surface);
    border-radius: 9999px;
    overflow: hidden;
    margin: 8px 0;
}
.progress-bar-fill {
    height: 100%;
    background: linear-gradient(90deg, var(--accent), var(--accent-vivid));
    border-radius: inherit;
    transition: width .4s ease;
}

/* ───────────── 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: 700;
}

/* ───────────── Cardinal (numérico) ───────────── */
.metric-value { color: var(--text); font-size: 28px; font-weight: 800; letter-spacing: -0.03em; }
.metric-label { color: var(--text-dim); font-size: 11px; text-transform: uppercase; letter-spacing: 0.16em; font-weight: 700; }

/* ───────────── 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: Satoshi + tracking cerrado. Replica lo
   que antes hacía ``.krav-cfg-panel h1, .krav-cfg-panel h2`` y mantiene la
   identidad del header (h1 en Satoshi, no en JetBrains Mono). */
.page-container h1,
.page-container h2 {
    font-family: 'Satoshi', -apple-system, BlinkMacSystemFont, sans-serif;
    letter-spacing: -0.01em;
}
/* En los paneles no usamos monoespaciado (JetBrains/monospace): los
   elementos de código heredan Satoshi. 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: 'Satoshi', sans-serif;
}

/* ── 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: 700;
    color: #11141A;
    letter-spacing: -0.01em;             /* tracking-tight */
    font-family: 'Satoshi', sans-serif;
}
.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: 700;
    text-transform: uppercase;
    letter-spacing: .5px;
    padding: 12px;
    text-align: left;
    vertical-align: middle;
    border-bottom: 1px solid #E5E5E5;
}
.krav-tabla thead th.right { text-align: right; 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; }
.krav-tabla td.right { text-align: right; }
.krav-tabla td.muted { color: #6A6B6C; font-weight: 300; }
.krav-tabla .username {
    font-family: 'Satoshi', sans-serif;
    font-weight: 700;
    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: 700;
    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: 700;
    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: 700;
    color: #6A6B6C;
    text-transform: uppercase;
    letter-spacing: .4px;
}
.popover-body input,
.popover-body select {
    padding: 6px 10px;
    background: #F7F7F7;
    border: 1px solid #E5E5E5;
    border-radius: 8px;
    font-size: 13px;
    color: #11141A;
    font-weight: 500;
}
.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:       #2563EB;
    --btn-primary-fg:       #FFFFFF;
    --btn-primary-hover:    #1D4ED8;
    --btn-primary-active:   #1E40AF;

    /* 2 · Secondary — azul tonal (relleno suave) */
    --btn-secondary-bg:     #EFF6FF;
    --btn-secondary-fg:     #1D4ED8;
    --btn-secondary-border: #BFDBFE;
    --btn-secondary-hover:  #DBEAFE;

    /* 3 · Ghost — azul texto (sin caja) */
    --btn-ghost-fg:         #2563EB;
    --btn-ghost-fg-strong:  #1D4ED8;
    --btn-ghost-hover:      #EFF6FF;

    /* 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;
}

html.dark-mode,
body.dark-mode {
    /* Primary azul (se mantiene el blanco en texto; azul legible sobre dark) */
    --btn-primary-bg:       #2563EB;
    --btn-primary-fg:       #FFFFFF;
    --btn-primary-hover:    #3B82F6;
    --btn-primary-active:   #1D4ED8;

    --btn-secondary-bg:     rgba(37, 99, 235, 0.16);
    --btn-secondary-fg:     #93C5FD;
    --btn-secondary-border: rgba(96, 165, 250, 0.35);
    --btn-secondary-hover:  rgba(37, 99, 235, 0.26);

    --btn-ghost-fg:         #93C5FD;
    --btn-ghost-fg-strong:  #BFDBFE;
    --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);
}

/* ── 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: 'Satoshi', sans-serif;
    font-size: 12px;
    font-weight: 700;
    line-height: 1;
    letter-spacing: normal;
    text-transform: none;
    white-space: nowrap;
    cursor: pointer;
    text-decoration: none;
    box-shadow: none;
    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),
                transform .1s ease;
}
.page-container .btn > i { font-size: 14px; }
.page-container .btn:hover { transform: none; }
.page-container .btn:active { transform: scale(0.97); }
.page-container .btn:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--btn-focus-ring); }
.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 ── */
.page-container .btn-primary { background: var(--btn-primary-bg); color: var(--btn-primary-fg); }
.page-container .btn-primary:hover:not(:disabled) { background: var(--btn-primary-hover); }
.page-container .btn-primary:active:not(:disabled) { background: var(--btn-primary-active); }

/* ── 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: 'Satoshi', sans-serif;
    font-size: 10px;
    font-weight: 800;
    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: 'Satoshi', sans-serif;
    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: 'Satoshi', sans-serif;
    font-size: 15px;
    font-weight: 700;
    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; }

/* ── 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: 'Satoshi', sans-serif;
    font-size: 11.5px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    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: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    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; }
}

/* Barra de progreso de navegación (3px, arriba). Feedback inmediato al
   cambiar de URL (sidebar, tabs, botones). Retardo mínimo para no parpadear
   en navegaciones instantáneas. Se resetea en pageshow (incluye bfcache). */
.edx-progress {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 3px;
    z-index: 60;
    background: linear-gradient(90deg, #2563EB 0%, #60A5FA 100%);
    border-radius: 0 3px 3px 0;
    transform: scaleX(0);
    transform-origin: left center;
    opacity: 0;
    pointer-events: none;
}
.edx-progress.is-on {
    opacity: 1;
    transform: scaleX(0.85);
    transition: transform 1.2s cubic-bezier(.23, 1, .32, 1), opacity .1s ease;
}


/* ================================================================
   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: 'Satoshi', inherit;
    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: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--text-dim-2);
}
.edx-cobranza-v {
    margin-top: 3px;
    font-size: 13px;
    font-weight: 700;
    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: 'Satoshi', inherit;
    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: #2563EB;
    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: 'JetBrains Mono', 'SF Mono', Consolas, monospace;
    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 mono 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: 'JetBrains Mono', 'SF Mono', Consolas, monospace;
    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: 'JetBrains Mono', 'SF Mono', Consolas, monospace;
    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: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    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: 700;
    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: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    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 Satoshi. */
.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: 'Satoshi', -apple-system, BlinkMacSystemFont, sans-serif;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--text-dim-2);
}
.kg-contador-num {
    font-family: 'Satoshi', -apple-system, BlinkMacSystemFont, sans-serif;
    font-size: 17px;
    font-weight: 700;
    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 {
    height: 100%;
    background: transparent;
    border: 0;
    color: var(--text);
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    padding-right: 6px;
    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: 700;
    letter-spacing: 0.13em;
    text-transform: uppercase;
    text-align: left;
    padding: 9px 12px;
    white-space: nowrap;
    border-top: 0;
}
.kg-tbl thead th.kg-der { text-align: right; }
.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);
}
.kg-tbl tbody td.kg-der { text-align: right; }

/* Histórico de Pagos: 4 columnas, TODO centrado, fuente Satoshi y números
   un poco más grandes que el resto de la tabla. */
.kg-tbl.pg-tbl { min-width: 0; font-family: 'Satoshi', -apple-system, BlinkMacSystemFont, sans-serif; }
.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: 700; }

/* 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: 700; color: var(--text); }
.kg-f-hora {
    display: block;
    margin-top: 2px;
    font-family: 'JetBrains Mono', 'SF Mono', Consolas, monospace;
    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: 'JetBrains Mono', 'SF Mono', Consolas, monospace;
    font-size: 10.5px;
    font-weight: 700;
    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: #1D4ED8;
}
: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: #93C5FD;
}
/* 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 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): flecha 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;
}
/* Selector de la promesa objetivo cuando hay VARIAS abiertas (Bloque 73).
   Misma altura (38px) que los iconos para quedar al ras; ancho acotado para no
   empujar los contadores de la barra. */
.kg-prom-sel select {
    height: 38px;
    max-width: 230px;
    padding: 0 26px 0 10px;
    font: 600 12px/1 var(--font-primary);
    color: var(--text);
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: 10px;
    cursor: pointer;
}
.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: 'JetBrains Mono', 'SF Mono', Consolas, monospace;
    font-size: 11.5px;
    font-weight: 700;
    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: 700; }
.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: 700; 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: 800;
    letter-spacing: 0.12em;
    text-transform: uppercase;
}
.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: #2563EB;
    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: 700;
    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: #2563EB;
    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: 'JetBrains Mono', 'SF Mono', Consolas, monospace;
    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: 700; 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: 'JetBrains Mono', 'SF Mono', Consolas, monospace;
    font-size: 20px;
    font-weight: 700;
    letter-spacing: 0.32em;
    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: 'Satoshi', sans-serif;
    font-size: 14.5px;
    font-weight: 700;
    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: 700;
    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: #2563EB; box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15); }
.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: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    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; }
}

