/* Shared: Base */
:root {
    /* Zonas seguras de la pantalla (v2.163.1): la muesca, la isla y la barra de
       inicio del iPhone, y las esquinas redondeadas. Con `viewport-fit=cover`
       (layouts/base.j2) la página ocupa la pantalla ENTERA, así que todo lo que
       va pegado a un borde suma su hueco. Valen 0 donde no hay nada que esquivar
       (escritorio, Android sin muesca), así que la regla no cambia nada ahí. */
    --safe-top: env(safe-area-inset-top, 0px);
    --safe-right: env(safe-area-inset-right, 0px);
    --safe-bottom: env(safe-area-inset-bottom, 0px);
    --safe-left: env(safe-area-inset-left, 0px);
    /* Primary palette */
    --primary: #1a365d;
    --primary-light: #2c5282;
    --primary-dark: #1a202c;
    --accent: #4a5568;
    --accent-dark: #2d3748;
    --teal: #38b2ac;
    --teal-dark: #2c7a7b;

    /* Semantic colors — desaturated for sophistication */
    --success: #16a34a;
    --danger: #dc2626;
    --warning: #f59e0b;
    --info: #0ea5e9;
    --violet: #7c3aed;
    /* Rampa cromática compartida (2026-10-08): tonos sin token semántico que
       usan la paleta de agendas (Calendario) y la de carpetas (Documentación).
       Pareja oscura en html[data-theme="dark"]. */
    --rampa-naranja: #ea580c; --rampa-rosa: #db2777; --rampa-indigo: #4f46e5;
    --rampa-fucsia: #c026d3;  --rampa-lima: #65a30d; --rampa-cian: #0891b2;
    --rampa-marron: #92400e;
    --metodo-star: #f5b301;
    --bs-primary: #0d6efd;
    --bs-success: #16a34a;
    --bs-danger: #dc2626;

    /* Status colors */
    --remote: #3b82f6;
    --office: #16a34a;
    --absent: #ef4444;

    /* Neutral palette */
    --gray-50: #f8fafc;
    --gray-100: #f1f5f9;
    --gray-200: #e2e8f0;
    --gray-300: #cbd5e1;
    --gray-400: #94a3b8;
    --gray-500: #64748b;
    --gray-600: #475569;
    --gray-700: #334155;
    --gray-800: #1e293b;
    --gray-900: #0f172a;

    /* Radii — refined, not bubbly */
    --radius: 8px;
    --radius-sm: 4px;
    --radius-md: 6px;
    --radius-lg: 12px;
    --radius-full: 50px;

    /* Shadows — subtle, layered */
    --shadow: 0 1px 3px rgba(0, 0, 0, 0.06), 0 1px 2px rgba(0, 0, 0, 0.04);
    --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.07), 0 2px 4px -2px rgba(0, 0, 0, 0.05);
    --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.08), 0 4px 6px -4px rgba(0, 0, 0, 0.04);
    --shadow-hover: 0 20px 25px -5px rgba(0, 0, 0, 0.08), 0 8px 10px -6px rgba(0, 0, 0, 0.04);

    /* ---- Curvas de animación (SIEMPRE cubic-bezier; nunca `ease` suelto) ----
       Cinco tokens, ni uno más: si una animación nueva "necesita" otra curva,
       casi siempre es que encaja en una de estas.
         · --ease        micro-interacciones (color, opacidad, borde). Es el
                         equivalente exacto de la palabra clave `ease`, así que
                         sustituirla no cambia el aspecto de nada.
         · --ease-gesto  movimiento con desplazamiento (desplegar, deslizar, el
                         thumb de los switches segmentados): arranca rápido y
                         frena al final.
         · --ease-entra  algo que APARECE (paneles, toasts): entra rápido y
                         aterriza suave.
         · --ease-sale   algo que DESAPARECE (colapsar, descartar): arranca
                         suave y acelera al irse. Es el espejo de --ease-entra;
                         usar la de entrada para una salida hace que el
                         elemento parezca quedarse colgado al final.
         · --ease-rebote acentos puntuales que se pasan del destino y vuelven.
       `linear` SÍ es correcto y se conserva en giros infinitos (spinners),
       cuentas atrás y VAIVENES de keyframes (shake, nudge, pulso): la curva se
       aplica
       entre cada par de keyframes, así que una asimétrica los vuelve
       nerviosos. */
    --ease: cubic-bezier(0.25, 0.1, 0.25, 1);
    --ease-gesto: cubic-bezier(0.32, 0.72, 0, 1);
    --ease-entra: cubic-bezier(0, 0, 0.2, 1);
    --ease-sale: cubic-bezier(0.4, 0, 1, 1);
    --ease-rebote: cubic-bezier(0.34, 1.56, 0.64, 1);

    /* Transitions — snappy */
    --transition: all 0.2s var(--ease);

    /* ───────────────────────────────────────────────────────────
       TOKENS SEMÁNTICOS DE TEMA (claro/oscuro)
       Úsalos SIEMPRE en componentes nuevos en vez de #fff, white o
       grises literales. Se reescriben en bloque [data-theme="dark"].
       ─────────────────────────────────────────────────────────── */
    --surface:        #ffffff;            /* tarjetas, tablas, paneles      */
    --surface-raised: #ffffff;            /* modales, dropdowns, popovers   */
    --surface-sunken: var(--gray-50);     /* fondo de página                */
    --surface-hover:  var(--gray-50);     /* hover de filas/items           */
    --border-color:   var(--gray-200);    /* bordes y separadores           */
    --border-strong:  var(--gray-300);    /* bordes con más contraste       */
    --text-color:     var(--gray-700);    /* texto base                     */
    /* Bootstrap 5.3.8 empezó a FIJAR el color del texto de los modales
       (`--bs-modal-color: var(--bs-body-color)`), que hasta la 5.3.2 quedaba
       inválido y por tanto se heredaba del `body` — o sea, de nuestro token.
       Sin esta línea, el texto de TODOS los modales se sale de la paleta del
       proyecto: en claro pasaba de #334155 a #212529. Como `--text-color` se
       redefine por tema, con declararlo aquí basta para los dos. */
    --bs-modal-color: var(--text-color);
    --text-strong:    var(--gray-900);    /* títulos                        */
    --text-muted:     var(--gray-500);    /* texto secundario               */
    --on-accent:      #ffffff;            /* texto/icono sobre color marca  */
    /* Texto seleccionado con el cursor. En claro, el realce suave de siempre. */
    --selection-bg:   rgba(26, 54, 93, 0.15);
    --selection-ink:  var(--gray-900);
    /* Texto sobre superficies ÁMBAR (franjas de aviso, chips de warning).
       NO vale --on-accent: es blanco fijo, y blanco sobre #f59e0b da 2,15:1 en
       claro y 1,67:1 en oscuro — por debajo incluso del 3:1 de texto grande.
       El ámbar es un color claro en los dos temas, así que su texto es OSCURO
       en los dos (≈7,8:1 en claro y ≈10:1 en oscuro) y por eso no se reescribe
       en el bloque de tema oscuro. */
    --on-warning:     #241a02;
    /* TINTAS para texto pequeño sobre papel. Los semánticos (`--success`,
       `--primary` en oscuro) valen para borde y fondo, pero como texto de 12 px
       no llegan a 4,5:1: `--success` claro da 3,3:1 sobre blanco. Estas sí. */
    --success-ink:    #166534;   /* 7,1:1 sobre blanco; 6,4:1 sobre la pastilla al 10 % */
    --warning-ink:    #92400e;   /* texto pequeño en ámbar: 6,4:1 sobre la pastilla; --warning a secas se queda en 2,9:1 */
    --danger-ink:     #991b1b;   /* 8,3:1 sobre papel; 7,1:1 sobre la pastilla al 10 %;
                                    6,5:1 al 16 %. `--danger` a secas da 4,8:1 sobre
                                    papel y 4,1:1 sobre su pastilla: no llega. */
    --primary-ink:    var(--primary);
    --info-ink:       #075985;   /* azul informativo como texto: `--info` a secas da 2,8:1 sobre blanco */
    /* Rampa de POTENCIA (IA → Modelos, P1…P4): azul de claro a oscuro, siempre
       azul (nunca gris) y con su texto AA. Es una escala ordinal, no un estado:
       por eso no reutiliza --primary/--success. */
    /* Un solo color por clase: es borde Y texto de la pastilla (mismo formato
       que `.plat-modelo-badge`), con el fondo al 10-28 % del mismo azul. */
    --potencia-1: #1f56dc;   /* 5,3:1 sobre su pastilla al 10 % (5,1 en hover) */
    --potencia-2: #1d4ed8;   /* 5,2:1 sobre la pastilla al 16 % */
    --potencia-3: #1e40af;   /* 6,0:1 al 22 % */
    --potencia-4: #1e3a8a;   /* 6,2:1 al 28 % */

    /* Superficies OSCURAS POR DISEÑO (nav, toast, barras de selección,
       cabeceras oscuras): se mantienen oscuras en AMBOS temas, con texto
       claro (--on-inverse). No usan la rampa de grises (que se invierte). */
    --surface-inverse:        #1e293b;
    --surface-inverse-strong: #0f172a;
    --on-inverse:             #ffffff;

    color-scheme: light;
}

/* ===============================================================
   MODO OSCURO — override de la paleta vía [data-theme="dark"]
   Se invierte la rampa de grises (los componentes que usan
   var(--gray-*) se adaptan solos) y se redefinen superficies,
   sombras y marca para contraste accesible sobre fondo oscuro.
   =============================================================== */
html[data-theme="dark"] {
    /* Rampa de grises espejada: 50 = más oscuro, 900 = casi blanco */
    --gray-50:  #0f172a;
    --gray-100: #1e293b;
    --gray-200: #334155;
    --gray-300: #475569;
    --gray-400: #64748b;
    --gray-500: #94a3b8;
    --gray-600: #cbd5e1;
    --gray-700: #e2e8f0;
    --gray-800: #f1f5f9;
    --gray-900: #f8fafc;

    /* Marca: navíos algo más luminosos para que el acento lea sobre
       superficies oscuras y el degradado de cabeceras siga siendo azul. */
    --primary:       #3b6db5;
    --primary-light: #5b8fd6;
    --primary-dark:  #24395c;
    --accent:        #94a3b8;
    --accent-dark:   #cbd5e1;

    /* Semánticos ligeramente más luminosos (legibles sobre oscuro). */
    --success: #22c55e;
    --success-ink: #22c55e;
    --warning-ink: #fbbf24;
    /* En oscuro la tinta va MÁS CLARA que el semántico, no más oscura:
       `--danger` (#f05252) se queda en 4,3:1 sobre --surface. */
    --danger-ink: #f87171;
    --primary-ink: #8ab4f0;   /* --primary oscuro da 2,5:1 sobre la pastilla */
    --info-ink: #7dd3fc;
    /* En oscuro la rampa se ACLARA con la potencia (el fondo, al densificarse,
       también aclara): así el contraste sube en vez de hundirse. Ratios sobre la
       pastilla difuminada, no sobre la superficie desnuda. */
    --potencia-1: #7fb3f5;   /* 5,9:1 (5,0 en hover) */
    --potencia-2: #93c5fd;   /* 5,9:1 */
    --potencia-3: #a8d1fe;   /* 5,6:1 */
    --potencia-4: #dbeafe;   /* 5,5:1 */
    --danger:  #f05252;
    --warning: #fbbf24;
    --info:    #38bdf8;
    --violet:  #a78bfa;
    --rampa-naranja: #fb923c; --rampa-rosa: #f472b6; --rampa-indigo: #818cf8;
    --rampa-fucsia: #e879f9;  --rampa-lima: #a3e635; --rampa-cian: #22d3ee;
    --rampa-marron: #d6a26b;
    --metodo-star: #fbbf24;
    --teal:    #2dd4bf;

    /* Superficies: tarjetas algo más claras que el fondo de página. */
    --surface:        #1b2536;
    --surface-raised: #243049;
    --surface-sunken: #0b1220;
    --surface-hover:  #243049;
    --border-color:   #334155;
    --border-strong:  #475569;
    --text-color:     #e2e8f0;
    --text-strong:    #f8fafc;
    --text-muted:     #94a3b8;
    --on-accent:      #ffffff;
    /* Selección en oscuro: el navy al 15 % sobre #1b2536 no se distinguía del
       fondo. FONDO BLANCO y letra oscura, invertida (decisión del dueño,
       2026-10-09: «la letra oscura y el fondo blanco»): ≈17:1. */
    --selection-bg:   var(--gray-900);   /* #f8fafc en oscuro */
    --selection-ink:  var(--gray-50);    /* #0f172a en oscuro */

    /* Inversas: siguen oscuras, algo más claras que la página para separarse. */
    --surface-inverse:        #2a3852;
    --surface-inverse-strong: #0d1626;
    --on-inverse:             #ffffff;

    /* Sombras más densas — en oscuro la elevación se apoya en contraste. */
    --shadow:       0 1px 3px rgba(0, 0, 0, 0.45), 0 1px 2px rgba(0, 0, 0, 0.35);
    --shadow-md:    0 4px 6px -1px rgba(0, 0, 0, 0.5), 0 2px 4px -2px rgba(0, 0, 0, 0.4);
    --shadow-lg:    0 10px 15px -3px rgba(0, 0, 0, 0.55), 0 4px 6px -4px rgba(0, 0, 0, 0.4);
    --shadow-hover: 0 20px 25px -5px rgba(0, 0, 0, 0.6), 0 8px 10px -6px rgba(0, 0, 0, 0.45);

    color-scheme: dark;
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; }

/* Fondo de nodos de toda la aplicación (particles.js, montado en base.j2).
   `z-index: -1` lo mete DEBAJO de todo el contenido, y funciona porque `html`
   no declara fondo propio: en ese caso el `background` de `body` se propaga al
   viewport y se pinta antes que cualquier descendiente, así que el lienzo queda
   entre el fondo y el contenido. Si algún día se le pone `background` a `html`,
   el body pasaría a pintar el suyo por encima y este lienzo desaparecería.
   `pointer-events: none` es la otra mitad del contrato: nunca intercepta un
   clic, así que no se superpone a nada en ningún sentido. Que no capture el
   puntero NO quiere decir que el fondo sea inerte: `particles-interaccion.js`
   escucha en el documento y le reenvía los eventos, así que el grab y el push
   funcionan igual que en el dashboard sin quitarle un clic a nadie. Devolverle
   `pointer-events` a este lienzo se comería los clics de la aplicación
   entera. */
#app-particles {
    position: fixed;
    inset: 0;
    z-index: -1;
    pointer-events: none;
}

body {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    background: var(--surface-sunken);
    min-height: 100vh;
    /* Marco de referencia del rótulo de versión (`.app-version`), que se ancla
       al fondo del DOCUMENTO y no de la ventana. No afecta a los `fixed` de la
       aplicación (nav, toasts, asistente, launcher): solo un `transform`,
       `filter` o `contain` los capturaría, nunca un `position: relative`.
       Coincide con el bloque contenedor inicial porque el reset de arriba deja
       el body sin margen ni borde: si algún día se le pone alguno, se desplazan
       a la vez el rótulo y el calendario de Flatpickr, que se inserta aquí y
       calcula coordenadas de documento. */
    position: relative;
    color: var(--text-color);
    font-size: 14px;
    line-height: 1.5;
    font-weight: 400;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    transition: background-color 0.2s var(--ease), color 0.2s var(--ease);
}

/* Mientras se alterna claro/oscuro NADA transiciona (la clase la pone y la
   quita `applyTheme`, en core.js, en el frame siguiente).

   Los tokens cambian a la vez, pero lo que cuelga de ellos llegaba a TRES
   velocidades: el fondo del documento a 0,2 s (la regla de aquí arriba), los
   controles de la nav y los botones entre 0,12 y 0,25 s, y las superficies de
   tarjeta al instante, porque no declaran transición. El tema aparecía por
   capas y lo último en llegar era el fondo, en los dos sentidos. Se veía sobre
   todo en las vistas a ancho completo con tarjetas separadas, donde hay mucho
   fondo a la vista.

   Va con `!important` y sobre todo el árbol a propósito: tiene que ganarle a
   cualquier transición declarada en cualquier componente, que es justo de lo que
   se defiende. `animation` NO se toca: los indicadores de carga que estén
   girando en ese momento deben seguir girando. */
html.tema-cambiando,
html.tema-cambiando *,
html.tema-cambiando *::before,
html.tema-cambiando *::after {
    transition: none !important;
}

h1, h2, h3, h4 {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    font-weight: 600;
    color: var(--gray-900);
    letter-spacing: -0.01em;
}

h1 { font-size: 1.5rem; }
h2 { font-size: 1.25rem; }
h3 { font-size: 1.1rem; }
h4 { font-size: 1rem; }

/* Focus ring for accessibility */
:focus-visible {
    outline: 2px solid var(--primary-light);
    outline-offset: 2px;
}

/* Smooth scrollbar */
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--gray-300); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--gray-400); }

/* Selection */
::selection {
    background: var(--selection-bg);
    color: var(--selection-ink);
}
/* Superficies oscuras por diseño o de marca: la selección se INVIERTE (papel
   claro + tinta de marca) en los dos temas. Sobre ellas el realce normal
   desaparece: en claro es marino al 15 % sobre marino. */
.top-nav,
.form-modal-header,
.facturas-selection-bar,
.toast,
.has-tooltip,
.asistente-msg--user {
    --selection-bg:  var(--on-accent);
    --selection-ink: var(--primary-dark);
}
