/* ═══════════════════════════════════════════════════════════════════════
   OMNIS TOKENS — la ÚNICA fuente de color, espacio, tipografía y tiempo
   del sistema. La cargan los DOS stacks:

     moderno  -> layout/app.php, antes que omnis-core y omnis-module
     legado   -> assets_helper.php, antes que variables.css

   Antes vivían dentro de omnis-core.css, que el legado no carga: por eso el
   legado tenía su propio juego en variables.css (--brand-primary, --gray-*,
   --spacing-*) con los mismos colores escritos por segunda vez. Dos fuentes
   para el mismo color es un sistema visual partido: variables.css deriva
   ahora de aquí y no declara ningún hex de marca propio.

   Va en `@layer omnis.tokens`, la capa más baja: no puede ganarle a nada.
   ═══════════════════════════════════════════════════════════════════════ */

@layer omnis.tokens {
  :root {
    font-size: 16px;

    /* ── TIPOGRAFÍA ──────────────────────────────────────────────────
       El sistema se leía con DOS tipografías: el catálogo y el stack
       moderno en `system-ui`, y el legado en `Helvetica Neue` escrita a
       mano en 26 sitios de 8 hojas. Medido el 2026-10-02 comparando el
       catálogo contra el mostrador: misma pantalla, dos letras.

       No es una preferencia estética: en macOS `system-ui` es la letra del
       sistema operativo, así que el legado se veía como «otra aplicación»
       dentro de la misma ventana. Vive aquí por el mismo motivo que los
       colores — una fuente única, y el legado la lee por variables.css.

       Para volver atrás se cambia ESTA línea, y sólo ésta. */
    --tipo-base: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;

    /* Marca */
    --brand:            #e8400f;
    --brand-hover:      #ff512b;
    --brand-contrast:   #ffffff;
    /* Los usa el legado (variables.css): pulsado y fondo lavado de marca. */
    --brand-press:      #b81f00;
    --brand-wash:       #fff1ec;
    --ink:              #1c1917;

    /* ── Superficies y texto (claro) ─────────────────────────────────
       UNA SOLA FAMILIA EN LOS DOS MODOS (2026-10-05).

       Gerry: «si está mal en oscuro, viene de un patrón mal en claro; si
       un botón no funciona en un modo, no funciona en el otro».

       Esta escala era PIEDRA CÁLIDA (#f5f5f4, #1c1917, #57534e) mientras
       el marco de la aplicación —barra lateral y superior— lleva años en
       `#111827`, azul pizarra. Dos familias: por eso al poner las dos
       juntas en oscuro se veía marrón contra azul, y por eso en claro el
       gris de las tarjetas nunca terminaba de pegar con el menú.

       Ahora las dos salen del color del sistema. Lo bonito del cruce: el
       `#111827` del marco es la SUPERFICIE en oscuro y el TEXTO en claro.
       Es el mismo color haciendo los dos papeles, que es lo que hace que
       una interfaz parezca de una pieza.

       Los valores son la escala fría estándar, la misma de la que ya salía
       `--nav-bg`. No se inventa nada: se termina de aplicar lo que el
       marco ya usaba. */
    --bg:               #f3f4f6;
    --surface:          #ffffff;
    --surface-2:        #f9fafb;
    --border:           #e5e7eb;
    --border-strong:    #d1d5db;
    --text:             #111827;
    --text-soft:        #4b5563;
    --text-mute:        #6b7280;

    /* Estado */
    /* ── Los cuatro estados: dos niveles, según el trabajo del color ──
       CADA estado tiene dos tonos, y la diferencia no es estética:

         --<estado>          4.70:1   el color que COMUNICA
                                      texto, iconos, bordes, acentos finos
         --<estado>-solid    6.70:1   el color que SOSTIENE TEXTO
                                      fondos con letra blanca encima

       Por qué no un solo valor para todo: a 4.70 el color conserva su
       identidad —el ámbar se ve ámbar— y es donde más superficie de color
       ve el usuario, así que subirlo lo apaga (a 6.70 el ámbar se lee
       marrón y el verde casi negro). Pero cuando el color es FONDO y lleva
       texto pequeño encima, esa identidad importa menos que leer la
       palabra: ahí conviene el tono más profundo, que roza AAA.

       Los `-solid` son iguales en los dos temas: su contraste es contra el
       blanco de su propio texto, no contra el fondo de la página.

       ── Y todos al MISMO nivel entre sí ──────────────────────────────
       Todos empatan 4.70:1 sobre blanco, el del carmesí #e11d48 que Gerry
       tomó como referencia. Antes cada uno iba por su cuenta —5.02, 5.02 y
       6.70— y se veían desparejos: el azul, casi negro al lado del rojo.
       Se calcularon buscando, para el matiz de cada familia y la misma
       saturación del carmesí (77%), la luz exacta que da ese contraste. */
    --ok:               #11853c;   /* 4.70:1 */
    --ok-solid:         #0e6a30;   /* 6.70:1 — lleva texto blanco encima */
    --ok-hover:         #0c5b29;   /* 8.20:1 — el hover PROFUNDIZA, nunca aclara */
    --ok-bg:            #dcfce7;
    --warn:             #a86316;   /* 4.70:1 */
    --warn-solid:       #854f11;   /* 6.70:1 */
    --warn-hover:       #73440f;   /* 8.20:1 */
    --warn-bg:          #fef3c7;
    /* ── Rojo: la familia carmesí (rose), a pedido de Gerry ───────────
       Se parte de #e11d48, el rojo que el legado ya usaba. Ese tono da
       4.70:1 sobre blanco —pasa AA por poco— así que se toma el siguiente
       de su misma familia, #be123c, que sube a 6.29:1 sin cambiar de color.

       Van DOS tokens porque ningún tono sirve para los dos usos: un rojo
       que se lee como TEXTO sobre fondo oscuro (claro) no vale como FONDO
       de botón con texto blanco encima (necesita ser oscuro).
         --danger        texto, iconos, bordes   → cambia con el tema
         --danger-solid  fondo con texto blanco  → igual en los dos temas */
    --danger:           #e11d48;   /* 4.70:1 — la referencia de la escala */
    --danger-solid:     #b41739;   /* 6.70:1 */
    --danger-hover:     #9c1432;   /* 8.20:1 — el hover PROFUNDIZA, nunca aclara */
    /* El botón principal: carbón de base, rojo al pasar por encima
       (decisión de Gerry, 2026-09-18). No usa --brand porque el naranja de
       marca con texto blanco se queda en 4.06:1 y no llega a AA. La marca
       sigue siendo el naranja en títulos, enlaces y acentos. */
    --primary-bg:       var(--ink);
    --primary-fg:       #ffffff;

    /* ── TABLA DE DATOS Y CONTROLES — MIGRADOS, NO INVENTADOS ─────────
       Esta familia NO es nueva: llevaba meses funcionando en `ALTER.css`
       (líneas 1690-1708) y el stack moderno no tenía NINGUNO de estos
       nombres. Es el caso exacto de lo que pide Gerry: el viejo ya tiene
       un orden y medidas que funcionan — se extraen y se migran, y mejorar
       viene después.

       Se trae el VALOR EXACTO que hoy se ve en pantalla, no el que al kit
       le gustaría. Equivalencias comprobadas en /sales con el navegador:

           --white            #ffffff  ≡ --surface
           --brand-primary    #e8400f  ≡ --brand
           --brand-primary-dark #b81f00 ≡ --brand-press

       Y dos que NO son equivalentes, así que viajan con su literal o la
       migración dejaría de ser invisible:

           --gray-100  #f5f5f5   vs  --bg      #f5f5f4
           --gray-200  #e5e5e5   vs  --border  #e7e5e4

       Son grises NEUTROS; la paleta del kit es cálida (stone). Cambiarlos
       aquí sería «mejorar» en el mismo movimiento que migrar, y eso es lo
       que rompió el mostrador esta misma sesión. Si algún día se unifican,
       será con Gerry mirando la pantalla. */
    --table-header-bg:    color-mix(in srgb, var(--surface) 95%, transparent);
    --table-row-zebra:    color-mix(in srgb, #f5f5f5 55%, transparent);
    --table-row-hover:    color-mix(in srgb, var(--brand) 5%, transparent);
    --table-row-selected: color-mix(in srgb, var(--brand) 10%, transparent);
    --table-cell-border:  color-mix(in srgb, #e5e5e5 60%, transparent);

    /* Alturas de control del legado. El kit sólo tenía `--touch-target`
       (44 px); el viejo distingue tres tamaños y los usa. */
    --control-h-sm:       30px;
    --control-h-lg:       46px;
    --control-px:         12px;

    --focus-ring:         0 0 0 3px color-mix(in srgb, var(--brand) 22%, transparent);
    --focus-ring-danger:  0 0 0 3px color-mix(in srgb, var(--danger-solid) 22%, transparent);

    /* Fondo del renglón SELECCIONADO en cualquier lista desplegable. */
    --menu-selected:      var(--brand-press);

    /* ── Puente con omnis-module.css ──────────────────────────────────
       `.omnis` redefine sus colores como `var(--o-<algo>, <claro fijo>)`.
       Ese respaldo existe por el legado CI3, que no tiene tokens: allí un
       módulo `.omnis` tiene que traer los suyos. Pero aquí, en el stack
       moderno, ese valor fijo PISABA el tema — el fondo de la página se
       oscurecía y las tarjetas seguían blancas con texto carbón invisible.

       Publicando los nombres que `.omnis` consulta, las dos hojas dejan de
       competir: esta manda el tema, aquella lo recibe. Y como apuntan al
       token vivo, el modo oscuro de más abajo llega solo, sin repetir nada. */
    --o-surface:        var(--surface);
    --o-surface-2:      var(--surface-2);
    --o-border:         var(--border);
    --o-border-strong:  var(--border-strong);
    --o-text:           var(--text);
    --o-text-soft:      var(--text-soft);
    --o-text-mute:      var(--text-mute);
    --o-brand:          var(--brand);
    --o-brand-hover:    var(--brand-hover);
    --o-ok:             var(--ok);       --o-ok-bg:     var(--ok-bg);
    --o-warn:           var(--warn);     --o-warn-bg:   var(--warn-bg);
    --o-danger:         var(--danger);   --o-danger-bg: var(--danger-bg);
    --o-info:           var(--info);     --o-info-bg:   var(--info-bg);
    --danger-bg:        #ffe4e6;   /* el lavado, de la misma familia */
    --info:             #356de5;   /* 4.70:1 */
    --info-solid:       #1a53cb;   /* 6.70:1 */
    --info-hover:       #1747af;   /* 8.20:1 */
    --info-bg:          #dbeafe;

    /* Escala tipográfica fluida (misma que ALTER.css) */
    --fluid-xs:   clamp(0.625rem, 0.5rem + 0.5vw, 0.75rem);
    --fluid-sm:   clamp(0.75rem, 0.625rem + 0.5vw, 0.875rem);
    --fluid-base: clamp(0.8125rem, 0.6875rem + 0.5vw, 0.9375rem);
    --fluid-md:   clamp(0.875rem, 0.75rem + 0.5vw, 1rem);
    --fluid-lg:   clamp(1rem, 0.875rem + 0.5vw, 1.125rem);
    --fluid-xl:   clamp(1.125rem, 0.875rem + 1vw, 1.375rem);
    --fluid-2xl:  clamp(1.375rem, 1rem + 1.25vw, 1.75rem);
    --fluid-3xl:  clamp(1.75rem, 1.25rem + 2vw, 2.5rem);

    /* Espaciado fluido (misma que ALTER.css) */
    --space-xs:  clamp(0.25rem, 0.125rem + 0.5vw, 0.5rem);
    --space-sm:  clamp(0.375rem, 0.25rem + 0.5vw, 0.75rem);
    --space-md:  clamp(0.625rem, 0.5rem + 0.5vw, 1rem);
    --space-lg:  clamp(0.75rem, 0.5rem + 1vw, 1.25rem);
    --space-xl:  clamp(1rem, 0.75rem + 1vw, 1.75rem);
    --space-2xl: clamp(1.25rem, 0.75rem + 2vw, 2.5rem);

    --shadow-xs: 0 1px 2px rgb(0 0 0 / 0.04);
    --shadow-sm: 0 1px 3px rgb(0 0 0 / 0.06), 0 1px 2px rgb(0 0 0 / 0.04);
    --shadow-md: 0 4px 6px rgb(0 0 0 / 0.06), 0 2px 4px rgb(0 0 0 / 0.04);
    --shadow-lg: 0 10px 15px rgb(0 0 0 / 0.08), 0 4px 6px rgb(0 0 0 / 0.04);

    --radius:    10px;
    --radius-sm: 6px;
    --radius-lg: 16px;

    /* Terminal táctil: ningún control interactivo baja de aquí */
    --touch-target: 44px;

    /* ── EL INTERRUPTOR ───────────────────────────────────────────────
       La pieza más repetida del sistema: 518 controles en 51 vistas, más
       los del catálogo. Estaba definida DOS veces —36x20 en el legado,
       42x24 en el stack nuevo— y ya se había partido antes: el comentario
       de ALTER.css registra una fusión anterior de 34x18 contra 36x20.
       Tres medidas distintas para el mismo interruptor, en un año.

       Mandan los 36x20, que son los que la gente ve hoy en Configuración,
       en los permisos de Empleados y en los selectores de columna.

       ⚠️ PENDIENTE DE DECISIÓN, no de arreglo silencioso. El catálogo dice
       que «el área táctil la da la etiqueta que lo envuelve». Medida: la
       etiqueta mide 23 px, no 44. O sea que el interruptor es el único
       control del sistema por debajo del mínimo del mostrador, y son 518.
       Subirlo cambia el alto de fila en las rejillas densas (permisos de
       Empleados, selectores de columna); agrandar sólo el área con un
       pseudo-elemento hace que dos casillas vecinas se solapen y el toque
       caiga en la de al lado. Las dos salidas tienen coste visible en 518
       sitios: lo decide Gerry, no yo.
       ─────────────────────────────────────────────────────────────────── */
    --switch-w:      36px;
    --switch-h:      20px;
    --switch-thumb:  16px;
    --switch-viaje:  16px;   /* ancho - pulgar - 2 de holgura */

    /* ── EL MARCO Y EL MENÚ ───────────────────────────────────────────
       Una sola medida por concepto, para los DOS stacks. Antes había dos
       vocabularios para la misma barra y no coincidían: el legado medía
       220/56/42 px (`--sidebar-width`, `--topbar-height`, `--menu-row-h`)
       y el moderno 248/60/44 (`--sidebar-w`, `--topbar-h`,
       `--touch-target`). El mismo sistema salía 28 px más ancho y 4 más
       alto según por dónde se entrara. Manda lo que ya está en uso —los
       220 px los pidió Gerry el 11/09/2026—; `variables.css` ahora lee de
       aquí en vez de repetirlo.
       ─────────────────────────────────────────────────────────────────── */
    --topbar-h:   56px;
    --sidebar-w:  220px;
    --sidebar-sm: 64px;
    /* El renglón del menú NO es `--touch-target`: es más bajo a propósito
       (42 px) porque el menú se recorre con la vista y se pulsa una vez,
       mientras que el mostrador se toca a ciegas. Es el alto que ya tiene
       el sistema y el que gobierna los dos niveles del árbol. */
    --menu-row-h: 42px;

    /* Colores del menú. Son los del sistema en uso, no una paleta nueva:
       fondo oscuro fijo (no cambia con el tema: la barra es oscura en
       claro y en oscuro), texto al 65 %, icono al 40 %, y el ACTUAL se
       marca con un lavado de marca al 16 % más una barra de 3 px a la
       izquierda —nunca con el naranja sólido, que sobre texto blanco se
       queda en 4.06:1 y no llega a AA. */
    --nav-bg:          #111827;
    --nav-text:        rgb(255 255 255 / 0.65);
    --nav-text-hover:  #ffffff;
    --nav-icon:        rgb(255 255 255 / 0.40);
    --nav-icon-hover:  rgb(255 255 255 / 0.85);
    --nav-hover:       rgb(255 255 255 / 0.06);
    --nav-current:     rgb(232 64 15 / 0.16);
    --nav-rule:        rgb(255 255 255 / 0.08);

    --t-fast: 120ms;
    --t-base: 200ms;
  }


  /* ══ VOCABULARIO DEL LEGADO — MIGRADO DESDE variables.css ════════
     2026-10-05. Gerry: «el viejo sistema ya tiene un orden, medidas,
     reglas que funcionan. Extrae lo que funciona y MIGRA YA».

     Estas 120 definiciones vivían en `variables.css`, que sólo carga el
     legado. El stack moderno no tenía ninguna. Se mueven TAL CUAL —
     mismo nombre, mismo valor— para que las dos pilas lean de una sola
     fuente. La migración no cambia un píxel; mejorar viene después.

     El registro completo —origen, línea, usos y por qué— está en
     `docs/MIGRACION_TOKENS.md`. Ahí está lo que haya que recordar el
     día que alguien se pregunte de dónde salió un valor. */
  :root {
    --font-base:               var(--tipo-base, 'Helvetica Neue', 'Nunito', sans-serif);   /* variables.css:2 · 9 usos */
    --brand-primary:           var(--brand, #e8400f);   /* variables.css:3 · 173 usos */
    --brand-primary-dark:      var(--brand-press, #b81f00);   /* variables.css:3 · 33 usos */
    --brand-primary-light:     var(--brand-hover, #ff512b);   /* variables.css:3 · 18 usos */
    --brand-primary-lighter:   var(--brand-wash, #fff1ec);   /* variables.css:4 · 14 usos */
    --brand-accent:            #ef4444;   /* variables.css:5 · 0 usos */
    --brand-accent-dark:       #dc2626;   /* variables.css:5 · 0 usos */
    --brand-accent-light:      #f87171;   /* variables.css:6 · 0 usos */
    --brand-accent-lighter:    #fef2f2;   /* variables.css:6 · 0 usos */
    --brand-success:           var(--ok, #10b981);   /* variables.css:7 · 36 usos */
    --brand-success-dark:      var(--ok-hover, #059669);   /* variables.css:7 · 4 usos */
    --brand-success-light:     var(--ok-bg, #d1fae5);   /* variables.css:8 · 4 usos */
    --brand-success-deep:      #047857;   /* variables.css:9 · 1 usos */
    --brand-danger:            var(--danger-solid, #e11d48);   /* variables.css:9 · 47 usos */
    --brand-danger-dark:       var(--danger-hover, #be123c);   /* variables.css:10 · 8 usos */
    --brand-danger-light:      var(--danger-bg, #ffe4e6);   /* variables.css:11 · 6 usos */
    --brand-danger-deep:       #a02005;   /* variables.css:12 · 0 usos */
    --brand-warning:           var(--warn, #f59e0b);   /* variables.css:12 · 20 usos */
    --brand-warning-dark:      #d97706;   /* variables.css:14 · 4 usos */
    --brand-warning-light:     var(--warn-bg, #fef3c7);   /* variables.css:14 · 4 usos */
    --brand-warning-deep:      #b45309;   /* variables.css:15 · 1 usos */
    --brand-info:              var(--info, #06b6d4);   /* variables.css:16 · 6 usos */
    --brand-info-dark:         #0891b2;   /* variables.css:17 · 4 usos */
    --brand-info-light:        var(--info-bg, #cffafe);   /* variables.css:17 · 4 usos */
    --brand-info-deep:         #2563eb;   /* variables.css:19 · 1 usos */
    --white:                   #ffffff;   /* variables.css:20 · 136 usos */
    --gray-50:                 #fafafa;   /* variables.css:20 · 22 usos */
    --gray-100:                #f5f5f5;   /* variables.css:21 · 40 usos */
    --gray-200:                #e5e5e5;   /* variables.css:22 · 38 usos */
    --gray-300:                #d4d4d4;   /* variables.css:23 · 24 usos */
    --gray-400:                #a3a3a3;   /* variables.css:23 · 18 usos */
    --gray-500:                #737373;   /* variables.css:25 · 6 usos */
    --gray-600:                #525252;   /* variables.css:25 · 7 usos */
    --gray-700:                #404040;   /* variables.css:25 · 40 usos */
    --gray-800:                #262626;   /* variables.css:25 · 23 usos */
    --gray-900:                #171717;   /* variables.css:25 · 6 usos */
    --black:                   #0a0a0a;   /* variables.css:26 · 4 usos */
    --text-primary:            #171717;   /* variables.css:26 · 60 usos */
    --text-secondary:          #525252;   /* variables.css:26 · 41 usos */
    --text-muted:              #a3a3a3;   /* variables.css:27 · 54 usos */
    --text-inverse:            #ffffff;   /* variables.css:27 · 41 usos */
    --bg-primary:              #ffffff;   /* variables.css:28 · 12 usos */
    --bg-secondary:            #fafafa;   /* variables.css:28 · 5 usos */
    --bg-tertiary:             #f5f5f5;   /* variables.css:28 · 17 usos */
    --bg-sidebar:              var(--nav-bg, #111827);   /* variables.css:30 · 20 usos */
    --bg-topbar:               #111827;   /* variables.css:30 · 3 usos */
    --bg-dark:                 #0f172a;   /* variables.css:31 · 0 usos */
    --border-light:            #f5f5f5;   /* variables.css:31 · 10 usos */
    --border-default:          #e5e5e5;   /* variables.css:31 · 58 usos */
    --border-medium:           #d4d4d4;   /* variables.css:32 · 10 usos */
    --border-dark:             #525252;   /* variables.css:32 · 0 usos */
    --module-customers:        #10b981;   /* variables.css:34 · 0 usos */
    --module-items:            #ef4444;   /* variables.css:34 · 0 usos */
    --module-price-rules:      #8b5cf6;   /* variables.css:35 · 0 usos */
    --module-item-kits:        #f59e0b;   /* variables.css:35 · 0 usos */
    --module-suppliers:        #3b82f6;   /* variables.css:36 · 0 usos */
    --module-reports:          #f59e0b;   /* variables.css:36 · 0 usos */
    --module-receivings:       #ef4444;   /* variables.css:37 · 0 usos */
    --module-sales:            #10b981;   /* variables.css:38 · 0 usos */
    --module-deliveries:       #8b5cf6;   /* variables.css:38 · 0 usos */
    --module-expenses:         #3b82f6;   /* variables.css:39 · 0 usos */
    --module-employees:        #10b981;   /* variables.css:40 · 0 usos */
    --module-giftcards:        #ef4444;   /* variables.css:40 · 0 usos */
    --module-config:           #f59e0b;   /* variables.css:40 · 0 usos */
    --module-locations:        #8b5cf6;   /* variables.css:41 · 0 usos */
    --module-messages:         #3b82f6;   /* variables.css:43 · 0 usos */
    --module-timeclocks:       #3b82f6;   /* variables.css:43 · 0 usos */
    --shadow-xl:               0 20px 25px rgba(15, 23, 42, 0.10), 0 8px 10px rgba(15, 23, 42, 0.04);   /* variables.css:48 · 3 usos */
    --shadow-ring:             0 0 0 3px rgba(255, 81, 43, 0.15);   /* variables.css:50 · 1 usos */
    --font-family-base:        'Inter', 'Nunito', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;   /* variables.css:51 · 4 usos */
    --font-family-mono:        'JetBrains Mono', 'SF Mono', 'Fira Code', monospace;   /* variables.css:55 · 0 usos */
    --font-size-xs:            11px;   /* variables.css:56 · 5 usos */
    --font-size-sm:            12px;   /* variables.css:57 · 16 usos */
    --font-size-base:          13px;   /* variables.css:57 · 23 usos */
    --font-size-md:            14px;   /* variables.css:59 · 8 usos */
    --font-size-lg:            16px;   /* variables.css:60 · 8 usos */
    --font-size-xl:            18px;   /* variables.css:60 · 3 usos */
    --font-size-2xl:           22px;   /* variables.css:61 · 2 usos */
    --font-size-3xl:           28px;   /* variables.css:62 · 0 usos */
    --font-weight-normal:      400;   /* variables.css:62 · 5 usos */
    --font-weight-medium:      500;   /* variables.css:63 · 13 usos */
    --font-weight-semibold:    600;   /* variables.css:65 · 22 usos */
    --font-weight-bold:        700;   /* variables.css:65 · 6 usos */
    --line-height-tight:       1.25;   /* variables.css:66 · 3 usos */
    --line-height-normal:      1.5;   /* variables.css:67 · 4 usos */
    --line-height-relaxed:     1.625;   /* variables.css:68 · 1 usos */
    --letter-spacing-normal:   0.015em;   /* variables.css:70 · 6 usos */
    --letter-spacing-wide:     0.025em;   /* variables.css:71 · 1 usos */
    --spacing-xs:              4px;   /* variables.css:73 · 2 usos */
    --spacing-sm:              8px;   /* variables.css:74 · 10 usos */
    --spacing-md:              12px;   /* variables.css:75 · 11 usos */
    --spacing-lg:              16px;   /* variables.css:76 · 19 usos */
    --spacing-xl:              20px;   /* variables.css:77 · 7 usos */
    --spacing-2xl:             24px;   /* variables.css:79 · 0 usos */
    --spacing-3xl:             32px;   /* variables.css:79 · 1 usos */
    --spacing-4xl:             40px;   /* variables.css:80 · 0 usos */
    --radius-md:               6px;   /* variables.css:82 · 68 usos */
    --radius-xl:               12px;   /* variables.css:85 · 2 usos */
    --radius-full:             9999px;   /* variables.css:85 · 22 usos */
    --transition-fast:         150ms cubic-bezier(0.4, 0, 0.2, 1);   /* variables.css:86 · 47 usos */
    --transition-normal:       200ms cubic-bezier(0.4, 0, 0.2, 1);   /* variables.css:88 · 4 usos */
    --transition-slow:         300ms cubic-bezier(0.4, 0, 0.2, 1);   /* variables.css:90 · 0 usos */
    --transition-spring:       400ms cubic-bezier(0.34, 1.56, 0.64, 1);   /* variables.css:93 · 0 usos */
    --z-dropdown:              100;   /* variables.css:96 · 0 usos */
    --z-sticky:                200;   /* variables.css:96 · 0 usos */
    --z-fixed:                 300;   /* variables.css:97 · 1 usos */
    --z-modal-backdrop:        400;   /* variables.css:99 · 1 usos */
    --z-modal:                 500;   /* variables.css:100 · 1 usos */
    --z-popover:               600;   /* variables.css:100 · 0 usos */
    --z-tooltip:               700;   /* variables.css:101 · 0 usos */
    --sidebar-width:           var(--sidebar-w, 220px);   /* variables.css:102 · 1 usos */
    --sidebar-collapsed:       var(--sidebar-sm, 64px);   /* variables.css:103 · 2 usos */
    --sidebar-item-height:     44px;   /* variables.css:105 · 0 usos */
    --topbar-height:           var(--topbar-h, 56px);   /* variables.css:106 · 7 usos */
    --space-3xl:               clamp(1.5rem, 1rem + 2vw, 3rem);   /* variables.css:126 · 4 usos */
    --space-4xl:               clamp(2rem, 1rem + 3vw, 4rem);   /* variables.css:126 · 0 usos */
    --font-family-labels:      var(--font-family-serif, Georgia, 'Times New Roman', serif);   /* variables.css:135 · 0 usos */
    --validation-success-color: var(--brand-success);   /* variables.css:139 · 0 usos */
    --validation-error-color:  var(--brand-danger);   /* variables.css:140 · 0 usos */
    --validation-warning-color: var(--brand-warning);   /* variables.css:143 · 0 usos */
  }

  /* Modo oscuro por tokens: ningún componente lo conoce. */
  @media (prefers-color-scheme: dark) {
    /* `:has(body.omnis)` acota el oscuro AUTOMÁTICO al stack moderno. Sin
       eso alcanzaba también al legado, que no tiene modo oscuro por
       preferencia del sistema —lo activa con la clase `.dark-mode`— y sus
       pantallas, que siguen siendo blancas, recibían los tonos claros del
       tema oscuro: 3.70:1 sobre blanco, peor que antes de tocar nada. */
    :root:not([data-theme="light"]):has(body.omnis) {
      /* EL OSCURO SALE DEL COLOR DEL SISTEMA, NO DE UNA PALETA CÁLIDA.
         Gerry: «el tono oscuro rompe con el color del sistema» y «modo
         oscuro diferente al usado en topbar y sidebar». El marco es
         `--nav-bg: #111827` —azul pizarra, el color de OneBox de toda la
         vida— y estos tokens traían piedra cálida (#1c1917, #262322).
         Puestas juntas, las tarjetas se ven marrones contra un marco
         azul. Se deriva la escala del marco: la tarjeta ES el color de
         la barra, y la página un paso por debajo. */
      --bg:            #0d131f;
      --surface:       #111827;
      --surface-2:     #1f2937;
      --border:        #374151;
      --border-strong: #4b5563;
      /* El texto también sale de la familia del sistema. Dejarlo en piedra
          cálida (#fafaf9/#d6d3d1/#938b84) sobre superficies azules daba
          4,38:1 en el apagado —lo cazó `test_contraste.php`— además de
          verse sucio: gris cálido sobre azul. */
      --text:          #f9fafb;
      --text-soft:     #d1d5db;
      --text-mute:     #9ca3af;
      --ok-bg:         #052e16;
      --warn-bg:       #431407;
      /* En oscuro el rojo tiene que ACLARARSE para leerse: el de claro daba
         2.70:1 sobre la superficie y aquí no se redefinía — texto de error
         que no se leía. El sólido no cambia: contrasta contra el blanco de
         su propio texto, no contra el fondo. */
      /* Mismo 4.70:1, aquí medido contra la superficie oscura. El sólido
         se queda con el tono de claro: contrasta contra el blanco de su
         propio texto, no contra el fondo de la página. */
      --danger:        #e84b6d;
      --ok:            #149945;
      --warn:          #c07219;
      --info:          #5181e8;
      /* Los `-solid` NO se redefinen en oscuro: su contraste es contra el
         blanco de su propio texto, no contra el fondo de la página. Un
         botón de error es el mismo en los dos temas. */
      /* En oscuro la superficie ya es carbón: un botón carbón encima sería
         invisible. El principal se invierte — claro sobre oscuro — que es
         el mismo gesto de "máximo contraste" que el carbón sobre blanco. */
      --primary-bg:    #fafaf9;
      --primary-fg:    #1c1917;
      --danger-bg:     #4c0519;
      --info-bg:       #172554;
    }
  }
  /* Elegido a mano: el toggle del stack moderno, o la clase del legado. */
  :root[data-theme="dark"],
  html.dark-mode,
  /* EL LEGADO MARCA EL BODY, NO EL HTML — y por eso nunca entraba.
     `dark.css` pone la clase en `<body>` (`body.dark-mode`), así que este
     bloque, que miraba `html.dark-mode`, no se activaba JAMÁS en las 299
     pantallas del legado: la paleta oscura existía y no la usaba nadie.

     Medido antes del arreglo en /items con la clase puesta: OCHO fondos
     distintos y DOCE colores de texto en una sola pantalla —tarjeta
     #262626, tabla #ffffff, campo #404040, marco #111827— y dos
     combinaciones ilegibles: texto #171717 sobre tarjeta #262626 (1,1:1,
     invisible) y #a3a3a3 sobre tabla blanca (2,5:1).

     Con esta línea la paleta cambia UNA vez y todo lo que lee tokens va
     coherente, en vez de 304 reglas eligiendo cada una su gris. */
  :root:has(body.dark-mode) {
    /* Misma escala que el bloque de arriba: el oscuro es el azul del
       marco (#111827), no la piedra cálida. Ver la nota de allí. */
    --bg:            #0d131f;
    --surface:       #111827;
    --surface-2:     #1f2937;
    --border:        #374151;
    --border-strong: #4b5563;
    /* Misma familia que las superficies; ver la nota del bloque de arriba. */
    --text:          #f9fafb;
    --text-soft:     #d1d5db;
    --text-mute:     #9ca3af;
    /* Este bloque es el que gana cuando el usuario ELIGE el tema oscuro a
       mano; el @media de arriba sólo cubre a quien lo trae del sistema. Lo
       que se redefina para el oscuro tiene que estar en los dos, o el tema
       elegido a mano se queda con los valores del claro. */
    --danger:        #e84b6d;
    --ok:            #149945;
    --warn:          #c07219;
    --info:          #5181e8;
    /* Los `-solid` NO se redefinen en oscuro: su contraste es contra el
       blanco de su propio texto, no contra el fondo de la página. Un
       botón de error es el mismo en los dos temas. */
    --danger-bg:     #4c0519;
    --primary-bg:    #fafaf9;
    --primary-fg:    #1c1917;
  }
}

/* ═══ BASE ═════════════════════════════════════════════════════════════ */
