/* =====================================================================
   SISTEMA DE DISENO — TOKENS Y TEMA
   ---------------------------------------------------------------------
   Tres estados de tema:
     1. Sin preferencia declarada  -> sigue al sistema (prefers-color-scheme)
     2. data-theme="light"          -> claro forzado
     3. data-theme="dark"           -> oscuro forzado

   El modo oscuro NO es una inversion: se disena aparte. Invertir produce
   blancos que deslumbran y primarios saturados que vibran sobre negro.
   Aqui las superficies suben en luminosidad con la elevacion (como en
   Material) y los acentos se desaturan para que no quemen.
   ===================================================================== */

:root{
  /* ------------------------- ESCALA TIPOGRAFICA ---------------------- */
  --text-xs:.78rem; --text-sm:.875rem; --text-base:1rem;
  --text-lg:1.125rem; --text-xl:1.35rem; --text-2xl:1.7rem;
  --text-3xl:2.15rem; --text-4xl:2.8rem; --text-5xl:3.6rem;

  /* ------------------------- ESPACIADO (base 4) ---------------------- */
  --space-1:.25rem; --space-2:.5rem;  --space-3:.75rem; --space-4:1rem;
  --space-5:1.5rem; --space-6:2rem;   --space-7:3rem;   --space-8:4rem;
  --space-9:6rem;

  /* --------------------------- PUNTOS DE CORTE ----------------------- */
  --bp-xs:320px; --bp-sm:375px; --bp-md:768px;
  --bp-lg:1024px; --bp-xl:1280px; --bp-2xl:1440px;

  /* ---------------------------- MOVIMIENTO --------------------------- */
  --dur-instant:80ms; --dur-fast:150ms; --dur-base:250ms;
  --dur-slow:400ms;   --dur-slower:650ms;
  --ease-standard:cubic-bezier(.2,0,0,1);
  --ease-decel:cubic-bezier(.05,.7,.1,1);
  --ease-accel:cubic-bezier(.3,0,.8,.15);
  --ease-spring:cubic-bezier(.34,1.56,.64,1);
}

/* =====================================================================
   TEMA CLARO (predeterminado)
   ===================================================================== */
:root,
:root[data-theme="light"]{
  color-scheme:light;

  --bg:#f6f8fb;
  --bg-elevated:#ffffff;
  --surface:#ffffff;
  --surface-2:#fbfcfe;
  --surface-3:#f1f5f9;
  --surface-inset:#eef2f7;

  --border:#e2e8f0;
  --border-strong:#cbd5e1;
  --border-subtle:#eef2f7;

  --text:#0f172a;
  --text-2:#475569;
  /* Medidos en el navegador sobre --bg y sobre tarjetas: los valores
     anteriores (#64748b y #94a3b8) daban 4.47:1 y 2.50:1, por debajo del
     minimo AA de 4.5:1 para texto normal. */
  --text-3:#576578;
  --text-muted:#57677d;   /* #64748b daba 4.47:1 sobre --bg y 3.86 sobre --surface-3 */
  --text-invert:#ffffff;

  /* --primary sirve para TEXTO sobre el fondo del tema y cambia de
     luminancia entre modos. Una superficie solida que lleva texto blanco
     encima no puede usarlo: en oscuro se aclara y el blanco deja de leerse.
     Por eso existen tokens separados para "superficie solida de marca" y
     para su color de texto. */
  --primary-solid:#1e40af; --on-primary:#ffffff;
  --danger-solid:#b91c1c;  --on-danger:#ffffff;
  --success-solid:#047857; --on-success:#ffffff;
  --accent-solid:#0d9488;  --on-accent:#ffffff;
  --violet:#6d28d9;
  --violet-soft:#faf5ff;    /* fondo tenue de la accion combinada */
  /* Texto sobre los fondos tenues de aviso. Van aparte de --danger y
     compania porque esos son el tono del BORDE y del icono, no del texto. */
  --on-danger-bg:#7f1d1d; --on-warning-bg:#78350f; --on-success-bg:#065f46;
  --avatar-end:#0f766e;   /* #0d9488 daba 3.74:1 con el texto blanco */
  --violet-border:#e9d5ff;
  /* Brillo diagonal de las tarjetas de accion. En claro puede ser franco;
     sobre una superficie oscura, el mismo blanco al 14% se lee como un
     velo gris que apaga el texto. */
  --sheen:rgba(255,255,255,.14);
  /* Fijo en ambos temas: acompana fondos blancos que no cambian (botones
     sobre el hero oscuro, lienzo de firma, comprobantes impresos). */
  --ink-on-white:#1e3a8a;

  /* Color al que se apaga el pie del hero.
     En claro se apaga contra su PROPIO tono: fundirlo hacia el fondo de la
     pagina seria un degradado a blanco y deja un manchon gris enorme.
     En oscuro se apaga contra el fondo de la pagina, que es casi el mismo
     color, y la union desaparece. */
  --hero-fade-to:#0d1b2e;

  --primary:#1e40af; --primary-50:#eff6ff; --primary-100:#dbeafe;
  --primary-200:#bfdbfe; --primary-500:#3b82f6; --primary-600:#2563eb;
  --primary-700:#1d4ed8; --primary-800:#1e3a8a; --primary-900:#172554;

  --accent:#0d9488; --accent-50:#f0fdfa; --accent-100:#ccfbf1;
  --accent-600:#0d9488; --accent-700:#0f766e;

  --success:#059669; --success-bg:#ecfdf5; --success-bd:#a7f3d0;
  --warning:#d97706; --warning-bg:#fffbeb; --warning-bd:#fde68a;
  --danger:#dc2626;  --danger-bg:#fef2f2;  --danger-bd:#fecaca;
  --info:#2563eb;    --info-bg:#eff6ff;    --info-bd:#bfdbfe;

  --shadow-xs:0 1px 2px rgba(15,23,42,.05);
  --shadow-sm:0 1px 3px rgba(15,23,42,.08),0 1px 2px rgba(15,23,42,.04);
  --shadow:0 4px 12px rgba(15,23,42,.07),0 2px 4px rgba(15,23,42,.04);
  --shadow-lg:0 12px 28px rgba(15,23,42,.10),0 4px 10px rgba(15,23,42,.05);
  --shadow-xl:0 24px 48px rgba(15,23,42,.16);

  --scrim:rgba(15,23,42,.55);
  --glass:rgba(255,255,255,.72);
}

/* =====================================================================
   TEMA OSCURO
   Superficies mas claras a mayor elevacion; acentos desaturados.
   ===================================================================== */
/* =====================================================================
   PALETA OSCURA
   ---------------------------------------------------------------------
   Los mismos valores en dos sitios, por fuerza: uno responde a la
   preferencia del sistema y el otro a la eleccion explicita del usuario,
   y CSS no permite compartir un bloque entre una consulta de medios y un
   selector suelto.

   Que esten duplicados es fragil —ya se desincronizaron una vez, y el
   modo oscuro forzado se quedo sin la mitad de los tokens sin que nada
   avisara—, asi que el grupo 22 de tests/SecurityTest.php comprueba que
   sigan siendo identicos. Si edita uno, edite el otro.
   ===================================================================== */
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    color-scheme:dark;

    --bg:#0a0f1a;
    --bg-elevated:#111827;
    --surface:#131b2b;
    --surface-2:#182133;
    --surface-3:#1e293b;
    --surface-inset:#0d1420;

    --border:#243044;
    --border-strong:#33415c;
    --border-subtle:#1b2536;

    /* No se usa blanco puro: reduce el deslumbramiento en pantallas OLED. */
    --text:#e8edf7;
    --text-2:#b2bfd4;
    --text-3:#8798b4;
    --text-muted:#8b9bb4;   /* #64748b daba 3.38:1 sobre --surface-3 */
    --text-invert:#0a0f1a;

    --primary-solid:#2563eb; --on-primary:#ffffff;
    --danger-solid:#c62828;  --on-danger:#ffffff;
    --success-solid:#0f766e; --on-success:#ffffff;
    --accent-solid:#0f766e;  --on-accent:#ffffff;
    --violet:#a78bfa;
  --violet-soft:#1e1b4b;
  --on-danger-bg:#fecaca; --on-warning-bg:#fde68a; --on-success-bg:#a7f3d0;
  --avatar-end:#0f766e;
  --violet-border:#4c1d95;
  --sheen:rgba(255,255,255,.045);
    --violet-soft:#1e1b4b;
    --on-danger-bg:#fecaca; --on-warning-bg:#fde68a; --on-success-bg:#a7f3d0;
    --avatar-end:#0f766e;
    --violet-border:#4c1d95;
    --sheen:rgba(255,255,255,.045);
    --ink-on-white:#1e3a8a;
    --hero-fade-to:#0a0f1a;   /* = --bg: la union con el hero desaparece */

    --primary:#60a5fa; --primary-50:#0f1e3a; --primary-100:#152a4d;
    --primary-200:#1e3a6b; --primary-500:#3b82f6; --primary-600:#60a5fa;
    --primary-700:#93c5fd; --primary-800:#bfdbfe; --primary-900:#dbeafe;

    --accent:#2dd4bf; --accent-50:#0c2a28; --accent-100:#113936;
    --accent-600:#2dd4bf; --accent-700:#5eead4;

    --success:#34d399; --success-bg:#0c2a20; --success-bd:#14532d;
    --warning:#fbbf24; --warning-bg:#2c1f08; --warning-bd:#78350f;
    --danger:#f87171;  --danger-bg:#2c1214;  --danger-bd:#7f1d1d;
    --info:#60a5fa;    --info-bg:#0f1e3a;    --info-bd:#1e3a6b;

    /* En oscuro la sombra separa poco: la elevacion la da el color. */
    --shadow-xs:0 1px 2px rgba(0,0,0,.4);
    --shadow-sm:0 1px 3px rgba(0,0,0,.45),0 1px 2px rgba(0,0,0,.3);
    --shadow:0 4px 12px rgba(0,0,0,.5),0 2px 4px rgba(0,0,0,.35);
    --shadow-lg:0 12px 28px rgba(0,0,0,.55),0 4px 10px rgba(0,0,0,.4);
    --shadow-xl:0 24px 48px rgba(0,0,0,.65);

    --scrim:rgba(0,0,0,.68);
    --glass:rgba(19,27,43,.78);
  }
}

/* Modo oscuro forzado por el usuario: mismos valores, mayor prioridad. */
:root[data-theme="dark"]{
  color-scheme:dark;

  --bg:#0a0f1a;
  --bg-elevated:#111827;
  --surface:#131b2b;
  --surface-2:#182133;
  --surface-3:#1e293b;
  --surface-inset:#0d1420;

  --border:#243044;
  --border-strong:#33415c;
  --border-subtle:#1b2536;

  /* No se usa blanco puro: reduce el deslumbramiento en pantallas OLED. */
  --text:#e8edf7;
  --text-2:#b2bfd4;
  --text-3:#8798b4;
  --text-muted:#8b9bb4;   /* #64748b daba 3.38:1 sobre --surface-3 */
  --text-invert:#0a0f1a;

  --primary-solid:#2563eb; --on-primary:#ffffff;
  --danger-solid:#c62828;  --on-danger:#ffffff;
  --success-solid:#0f766e; --on-success:#ffffff;
  --accent-solid:#0f766e;  --on-accent:#ffffff;
  --violet:#a78bfa;
  --violet-soft:#1e1b4b;
  --on-danger-bg:#fecaca; --on-warning-bg:#fde68a; --on-success-bg:#a7f3d0;
  --avatar-end:#0f766e;
  --violet-border:#4c1d95;
  --sheen:rgba(255,255,255,.045);
  --ink-on-white:#1e3a8a;
  --hero-fade-to:#0a0f1a;   /* = --bg: la union con el hero desaparece */

  --primary:#60a5fa; --primary-50:#0f1e3a; --primary-100:#152a4d;
  --primary-200:#1e3a6b; --primary-500:#3b82f6; --primary-600:#60a5fa;
  --primary-700:#93c5fd; --primary-800:#bfdbfe; --primary-900:#dbeafe;

  --accent:#2dd4bf; --accent-50:#0c2a28; --accent-100:#113936;
  --accent-600:#2dd4bf; --accent-700:#5eead4;

  --success:#34d399; --success-bg:#0c2a20; --success-bd:#14532d;
  --warning:#fbbf24; --warning-bg:#2c1f08; --warning-bd:#78350f;
  --danger:#f87171;  --danger-bg:#2c1214;  --danger-bd:#7f1d1d;
  --info:#60a5fa;    --info-bg:#0f1e3a;    --info-bd:#1e3a6b;

  /* En oscuro la sombra separa poco: la elevacion la da el color. */
  --shadow-xs:0 1px 2px rgba(0,0,0,.4);
  --shadow-sm:0 1px 3px rgba(0,0,0,.45),0 1px 2px rgba(0,0,0,.3);
  --shadow:0 4px 12px rgba(0,0,0,.5),0 2px 4px rgba(0,0,0,.35);
  --shadow-lg:0 12px 28px rgba(0,0,0,.55),0 4px 10px rgba(0,0,0,.4);
  --shadow-xl:0 24px 48px rgba(0,0,0,.65);

  --scrim:rgba(0,0,0,.68);
  --glass:rgba(19,27,43,.78);
}

/* ------------------- AJUSTES PROPIOS DEL MODO OSCURO ----------------
   Componentes que en claro dependen de un valor fijo y en oscuro hay que
   rehacer. Van DUPLICADOS por la misma razon que la paleta: uno responde
   a la preferencia del sistema y otro a la eleccion explicita.

   Cuatro de estos ajustes solo existian en el bloque de la eleccion
   explicita. Quien tuviera el sistema en oscuro y no hubiera tocado el
   conmutador —el caso mas comun— se quedaba con la barra de navegacion
   clara, las cabeceras de tabla claras y el esqueleto lanzando destellos
   blancos. El grupo 22 de tests/SecurityTest.php ahora tambien compara
   estos selectores.
   -------------------------------------------------------------------- */
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    /* El lienzo de firma se mantiene blanco: la firma se exporta como PNG
       y debe verse igual en el comprobante impreso. */
    .signature-canvas{background:#ffffff}

    .pubnav,
    .topbar{background:var(--surface)}

    .table thead th{background:var(--surface-3);color:var(--text-3)}
    .table tbody tr:hover{background:var(--surface-2)}

    /* El destello del esqueleto era #e8eef5: sobre fondo oscuro, un fogonazo. */
    .skeleton{
      background:linear-gradient(90deg,var(--surface-2) 25%,var(--surface-3) 37%,var(--surface-2) 63%);
      background-size:400% 100%;
    }
  }
}

:root[data-theme="dark"]{
  /* El lienzo de firma se mantiene blanco: la firma se exporta como PNG
     y debe verse igual en el comprobante impreso. */
  .signature-canvas{background:#ffffff}

  .pubnav,
  .topbar{background:var(--surface)}

  .table thead th{background:var(--surface-3);color:var(--text-3)}
  .table tbody tr:hover{background:var(--surface-2)}

  /* El destello del esqueleto era #e8eef5: sobre fondo oscuro, un fogonazo. */
  .skeleton{
    background:linear-gradient(90deg,var(--surface-2) 25%,var(--surface-3) 37%,var(--surface-2) 63%);
    background-size:400% 100%;
  }
}

/* --------------------------- CONMUTADOR ----------------------------- */
/* Un solo boton con dos iconos superpuestos que se relevan girando.
   Se muestra el icono del tema AL QUE SE CAMBIARIA, no el del tema
   actual: es lo que el usuario espera obtener al pulsarlo, y coincide con
   la etiqueta accesible que escribe theme.js ("Cambiar a modo claro").

   El estado lo decide el tema activo por CSS, no una clase de JavaScript:
   asi el icono correcto ya esta pintado en el primer cuadro. */
.theme-toggle{
  position:relative;width:38px;height:38px;border-radius:var(--radius-xs);
  border:1px solid var(--border);background:transparent;cursor:pointer;
  display:grid;place-items:center;color:var(--text-2);
  transition:background var(--dur-fast) var(--ease-standard),
             color var(--dur-fast) var(--ease-standard),
             border-color var(--dur-fast) var(--ease-standard);
}
.theme-toggle:hover{background:var(--surface-3);color:var(--text)}
.theme-toggle__sun,.theme-toggle__moon{position:absolute;display:grid;place-items:center}
.theme-toggle svg{
  width:19px;height:19px;display:block;
  transition:transform var(--dur-base) var(--ease-spring),opacity var(--dur-fast);
}

/* Tema claro activo -> se ofrece pasar a oscuro -> luna. */
.theme-toggle__moon{opacity:1;transform:rotate(0) scale(1)}
.theme-toggle__sun {opacity:0;transform:rotate(-45deg) scale(.6)}

/* Tema oscuro activo -> se ofrece pasar a claro -> sol. */
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]) .theme-toggle__moon{opacity:0;transform:rotate(45deg) scale(.6)}
  :root:not([data-theme="light"]) .theme-toggle__sun {opacity:1;transform:rotate(0) scale(1)}
}
:root[data-theme="dark"] .theme-toggle__moon{opacity:0;transform:rotate(45deg) scale(.6)}
:root[data-theme="dark"] .theme-toggle__sun {opacity:1;transform:rotate(0) scale(1)}

/* Eleccion explicita de tema claro: gana sobre la preferencia del sistema. */
:root[data-theme="light"] .theme-toggle__moon{opacity:1;transform:rotate(0) scale(1)}
:root[data-theme="light"] .theme-toggle__sun {opacity:0;transform:rotate(-45deg) scale(.6)}

/* =====================================================================
   CAMBIO DE TEMA SIN BARRIDO
   Mientras se conmuta el tema, theme.js marca la raiz con esta clase: sin
   ella, cada superficie interpola su color por su cuenta y el cambio se
   percibe como un barrido sucio en vez de un corte limpio.
   ===================================================================== */
html.theme-switching,
html.theme-switching *,
html.theme-switching *::before,
html.theme-switching *::after{
  transition:none !important;
}
