/* ===========================================================================
   alier-tokens.css — Capa de tokens AGNÓSTICA DE TEMA
   ---------------------------------------------------------------------------
   REGLA FUNDAMENTAL DE ESTE ARCHIVO:
   Aquí NO se declara ni un solo color absoluto (nada de #RRGGBB, rgb(), ni
   nombres de color). Todo color se DERIVA del tema activo mediante las
   variables que ya publican Bootstrap/Bootswatch (--bs-*) y DevExpress
   (--dxbl-*). Así el rediseño sobrevive a los 19 temas sin tocarse.

   Si añades un color literal a este archivo, rompes la compatibilidad con
   los temas oscuros (Cyborg, Solar, Superhero, Blazing Dark, Default Dark).

   Carga: DESPUÉS de bootstrap y del tema, ANTES de los .razor.css.
   =========================================================================== */

:root {
  /* --- Espaciado: escala de 4px, un solo sistema para toda la app --------- */
  --al-space-1: 0.25rem;   /*  4px */
  --al-space-2: 0.5rem;    /*  8px */
  --al-space-3: 0.75rem;   /* 12px */
  --al-space-4: 1rem;      /* 16px */
  --al-space-5: 1.5rem;    /* 24px */
  --al-space-6: 2rem;      /* 32px */
  --al-space-7: 3rem;      /* 48px */

  /* --- Cromo del layout: alturas fijas conocidas ------------------------- */
  --al-header-h: 3.5rem;   /* 56px */
  --al-sidebar-w: 16rem;   /* 256px */
  --al-sidebar-w-collapsed: 3.5rem;
  --al-pageheader-h: 3.5rem;
  --al-actionbar-h: 3rem;
  --al-footer-h: 2rem;     /* 32px — sustituye al bloque negro de ~90px */

  /* --- Densidad de tabla: 3 modos, el usuario elige y se persiste --------
     Valor por defecto = "normal". Se sobrescribe con [data-density] abajo. */
  --al-row-h: 2.25rem;     /* 36px */
  --al-row-pad-y: var(--al-space-2);
  --al-row-pad-x: var(--al-space-3);
  --al-row-font: 0.875rem;

  /* --- Radios: por ROL, no uno para todo -------------------------------- */
  --al-radius-control: 0.25rem;  /* inputs, botones */
  --al-radius-surface: 0.5rem;   /* tarjetas, paneles */
  --al-radius-pill: 100px;       /* chips de estado */

  /* --- Anchos de campo POR TIPO DE DATO ---------------------------------
     Sustituye a los 11 anchos arbitrarios del formulario actual.
     Un campo nunca elige su ancho: lo hereda de lo que contiene. */
  --al-field-code: 9rem;    /* NIF, matrícula, código postal, nº autorización */
  --al-field-date: 10rem;   /* fecha, fecha+hora */
  --al-field-num: 7rem;     /* peso, bultos, precio */
  --al-field-short: 20rem;  /* nombre, población, referencia */
  --al-field-long: 100%;    /* dirección, descripción, observaciones */

  /* --- Tipografía: escala modular, sin tamaños sueltos ------------------- */
  --al-text-xs: 0.75rem;
  --al-text-sm: 0.8125rem;
  --al-text-base: 0.875rem;
  --al-text-md: 1rem;
  --al-text-lg: 1.25rem;
  --al-text-xl: 1.5rem;
  --al-leading-tight: 1.25;
  --al-leading-normal: 1.5;

  /* =======================================================================
     COLOR DERIVADO — todo sale del tema activo
     ======================================================================= */

  /* Superficies. --bs-body-bg cambia solo con el tema; color-mix nos da
     escalones intermedios que funcionan igual en claro y en oscuro. */
  --al-surface:        var(--bs-body-bg, #fff);
  --al-surface-sunken: color-mix(in srgb, var(--bs-body-bg) 94%, var(--bs-body-color));
  --al-surface-raised: color-mix(in srgb, var(--bs-body-bg) 98%, var(--bs-body-color));

  /* Texto: tres niveles desde la LUMINANCIA DEL FONDO, no desde
     --bs-body-color ni --bs-emphasis-color.

     Cyborg, Superhero, Solar, Default Dark y Blazing Dark publican el
     color de cuerpo YA apagado; mezclarlo otra vez con el fondo lo deja
     a ~1,3:1. --bs-emphasis-color a veces no viaja al cambiar de hoja
     (queda el negro del tema claro anterior) y pinta tinta oscura sobre
     fondo oscuro.

     oklch(from) sobre --bs-body-bg pinta oscuro si el fondo es claro y
     claro si el fondo es oscuro. calc() con `? :` NO: en Chromium 148
     cualquier ternaria se queda en la primera rama (medido: 0,6 >= 0,62
     devolvía 0,16). El snap es clamp + infinity. */
  --al-text:        oklch(from var(--bs-body-bg) clamp(0.22, calc((0.55 - l) * infinity), 0.96) 0.03 h);
  --al-text-muted:  color-mix(in srgb, var(--al-text) 78%, var(--bs-body-bg));
  --al-text-subtle: color-mix(in srgb, var(--al-text) 64%, var(--bs-body-bg));

  /* Bordes: dos pesos. El hairline es el que separa filas.
     NO usamos --bs-border-color directamente: varios temas oscuros
     (Cyborg, Superhero, Solar) lo definen casi igual que su propio fondo
     —medido: borde rgb(40,40,40) sobre fondo rgb(33,37,41)— y los campos
     de formulario se quedan sin caja visible. Derivando del color de TEXTO
     garantizamos contraste en los 19 temas. */
  --al-border:          color-mix(in srgb, var(--bs-body-color) 24%, transparent);
  --al-border-hairline: color-mix(in srgb, var(--bs-body-color) 12%, transparent);

  /* Acento = color primario DEL TEMA. Nunca lo fijamos nosotros.

     --al-on-accent es el texto ENCIMA del acento sólido (botón primario).
     NO puede ser --bs-primary-bg-subtle: esa variable es un tinte de FONDO,
     claro en tema claro y oscuro en tema oscuro. Medido en Default Dark:
     texto rgb(3,22,51) sobre botón rgb(13,110,253) — parece negro sobre azul.
     En Minty o Solar el primario es claro y el tinte sutil encima desaparece.

     La luminancia del primario manda, no el esquema del tema: oklch(from)
     pinta texto claro si el relleno es oscuro y oscuro si el relleno es
     claro. Una sola fórmula para los 19. El hover del relleno se mezcla
     hacia el opuesto del texto, no hacia el color de cuerpo. */
  --al-accent:        var(--bs-primary);
  --al-accent-quiet:  color-mix(in srgb, var(--bs-primary) 12%, transparent);
  --al-accent-hover:  color-mix(in srgb, var(--bs-primary) 20%, transparent);
  /* Relleno de botón sólido: el primario a veces cae en la zona muerta
     (~L 0,50–0,62) donde ni el blanco ni el negro llegan a 4,5:1
     (medido: #0d6efd con texto oscuro 4,32:1; el blanco sobre Yeti
     #008cba 3,9:1). Se hace snap de L a 0,40 o 0,76; el matiz se
     conserva. --al-accent (enlaces, tintes) no se toca. */
  --al-accent-fill: oklch(from var(--bs-primary) clamp(0.40, calc(0.40 + (l - 0.62) * infinity), 0.76) c h);
  --al-on-accent:   oklch(from var(--al-accent-fill) clamp(0.16, calc((0.62 - l) * infinity), 0.98) 0.02 h);
  --al-accent-fill-hover: color-mix(in srgb, var(--al-accent-fill) 90%, oklch(from var(--al-on-accent) calc(1 - l) 0 0));
  --al-danger-fill: oklch(from var(--bs-danger) clamp(0.40, calc(0.40 + (l - 0.62) * infinity), 0.76) c h);
  --al-on-danger:   oklch(from var(--al-danger-fill) clamp(0.16, calc((0.62 - l) * infinity), 0.98) 0.02 h);
  --al-danger-fill-hover: color-mix(in srgb, var(--al-danger-fill) 90%, oklch(from var(--al-on-danger) calc(1 - l) 0 0));

  /* Color SEMÁNTICO — independiente del acento, también del tema.
     Se usa SOLO para estado, nunca decorativo. */
  /* Medido sobre el chip de estado, que es donde estos colores se leen a
     12 px sobre su propio tinte: con los valores anteriores ninguno llegaba
     al 4,5:1 de AA —tránsito 2,73, entregado 2,86, cancelado 3,28, pendiente
     3,77—. La cura es la misma que ya se aplicaba al amarillo: mezclar con
     el color de CUERPO, que oscurece en claro y aclara en oscuro, así que
     una sola fórmula sirve para los 19 temas. El tono se reconoce igual;
     lo que cambia es que ahora se lee. */
  --al-ok:       color-mix(in srgb, var(--bs-success) 45%, var(--al-text));
  --al-ok-bg:    color-mix(in srgb, var(--bs-success) 16%, var(--bs-body-bg));
  /* El amarillo de aviso de Bootstrap sobre fondo claro da ~1,6:1.
     Se mezcla con --al-text (tinta ya contrastada con el fondo), no con
     --bs-body-color: en Cyborg ese color es el gris apagado y el chip
     quedaba a ~1,0:1. El fondo del chip es opaco sobre el body, para
     que el contraste no dependa de lo que haya debajo. */
  --al-warn:     color-mix(in srgb, var(--bs-warning) 42%, var(--al-text));
  --al-warn-bg:  color-mix(in srgb, var(--bs-warning) 18%, var(--bs-body-bg));
  --al-danger:   color-mix(in srgb, var(--bs-danger) 48%, var(--al-text));
  --al-danger-bg:color-mix(in srgb, var(--bs-danger) 14%, var(--bs-body-bg));
  --al-info:     color-mix(in srgb, var(--bs-info) 45%, var(--al-text));
  --al-info-bg:  color-mix(in srgb, var(--bs-info) 16%, var(--bs-body-bg));

  /* Selección de fila: tinte del acento, NO el acento a plena saturación.
     El problema actual es que la fila seleccionada se pinta en cian sólido
     y el texto pierde contraste. */
  --al-row-selected:  var(--al-accent-quiet);
  --al-row-hover:     color-mix(in srgb, var(--bs-body-color) 5%, transparent);
  --al-row-stripe:    color-mix(in srgb, var(--bs-body-color) 3%, transparent);

  /* Foco: visible siempre, derivado del acento. */
  --al-focus-ring: 0 0 0 2px var(--bs-body-bg), 0 0 0 4px var(--bs-primary);

  /* Elevación: sombra derivada del color de texto, así no se ve gris sucio
     sobre fondos oscuros. */
  --al-shadow-1: 0 1px 2px color-mix(in srgb, var(--bs-body-color) 8%, transparent);
  --al-shadow-2: 0 4px 12px color-mix(in srgb, var(--bs-body-color) 12%, transparent);

  /* Movimiento: cuota y tema expanden el chip al click (DEC-017). */
  --al-duration-expand: 240ms;
  --al-ease-expand: cubic-bezier(0.22, 1, 0.36, 1);
}

/* --- Modos de densidad -----------------------------------------------------
   Se aplica en <html data-density="compact|normal|comfortable">.
   Persistir en localStorage + preferencia de usuario en servidor. */
:root[data-density="compact"] {
  --al-row-h: 1.75rem;     /* 28px — operador experto, máximo de filas */
  --al-row-pad-y: var(--al-space-1);
  --al-row-font: var(--al-text-sm);
}
:root[data-density="comfortable"] {
  --al-row-h: 2.75rem;     /* 44px — táctil, almacén con guantes */
  --al-row-pad-y: var(--al-space-3);
  --al-row-font: var(--al-text-md);
}

/* --- Fallback para navegadores sin color-mix() ------------------------------
   color-mix tiene soporte desde Chrome 111 / Firefox 113 / Safari 16.2.
   Si hay que dar soporte a versiones anteriores, estos valores son el plan B:
   opacos y sin derivación, pero legibles en ambos temas. */
@supports not (color: color-mix(in srgb, red 50%, blue)) {
  :root {
    --al-surface-sunken: var(--bs-secondary-bg, #f8f9fa);
    --al-text-muted:     var(--bs-secondary-color, #6c757d);
    --al-text-subtle:    var(--bs-secondary-color, #6c757d);
    --al-border-hairline:var(--bs-border-color, #dee2e6);
    --al-accent-quiet:   var(--bs-primary-bg-subtle, #cfe2ff);
    --al-row-selected:   var(--bs-primary-bg-subtle, #cfe2ff);
    --al-row-hover:      var(--bs-tertiary-bg, #f8f9fa);
    --al-row-stripe:     var(--bs-tertiary-bg, #fcfcfd);
  }
}

/* oklch(from) llega más tarde que color-mix. Sin él, el texto sobre el
   relleno usa el fondo de la página: correcto en claro con primario oscuro,
   peor en oscuro. El camino principal cubre Chromium 119+ / Safari 16.4. */
@supports not (color: oklch(from red l c h)) {
  :root {
    --al-text: var(--bs-body-color);
    --al-accent-fill: var(--bs-primary);
    --al-danger-fill: var(--bs-danger);
    --al-on-accent: var(--bs-body-bg);
    --al-on-danger: var(--bs-body-bg);
    --al-accent-fill-hover: color-mix(in srgb, var(--bs-primary) 80%, var(--bs-body-color));
    --al-danger-fill-hover: color-mix(in srgb, var(--bs-danger) 80%, var(--bs-body-color));
  }
}

/* --- Respeto a preferencias del sistema ----------------------------------- */
@media (prefers-reduced-motion: reduce) {
  :root { --al-transition: none; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
