/* Brújula · tokens — fuente única del sistema de diseño
   ─────────────────────────────────────────────────────────────────────────
   QUÉ ES: el vocabulario de diseño de la plataforma (la Brújula) en un solo
   archivo: el NÚCLEO. Define la paleta estándar, la tipografía, el
   espaciado, los radios, las sombras y el movimiento como variables CSS. Toda página o componente nuevo debe construirse SOLO con
   estos tokens — nunca con valores "a mano".

   COMPATIBILIDAD: los nombres y valores de --gold, --bg, --surface, --ink,
   --muted, --border*, --shadow, --danger, --tex-* son IDÉNTICOS a los que ya
   declaran index.html y assets/ui.css. Por eso este archivo es drop-in: puede
   cargarse antes del CSS inline de cualquier módulo sin cambiar su render. Lo
   que añade son las ESCALAS que faltaban (espacio, tipografía, radio, z-index,
   movimiento), que hoy estaban repartidas a ojo por cada página.

   ORDEN DE CARGA recomendado en una página nueva:
     <script src="/assets/theme.js"></script>   (en <head>, fija data-theme)
     <link rel="stylesheet" href="/assets/tokens.css">
     <link rel="stylesheet" href="/assets/anim.css">
     <link rel="stylesheet" href="/assets/ui.css">
     ...luego el CSS propio de la página.

   AL EDITAR: es asset de /assets/ → subir VERSION en sw.js para invalidar caché. */

/* ═══ LA PALETA ESTÁNDAR: BRÚJULA ════════════════════════════════════════
   30 sep 2026, decisión de Samuel: el diseño base del portal es el de la
   BRÚJULA —el paquete del manual de marca—: niebla y blanco de día, grafito de
   noche, y el ultramar como la señal. Sustituye al estándar anterior, que se
   retiró entero con su nombre.

   ESTO ES EL NÚCLEO. La marca del CLIENTE va aparte, en assets/tema.css, y se
   carga después: redefine estos mismos nombres. Hoy el único cliente es
   Amoramar y todas las páginas enlazan su tema, así que lo que se ve en el
   portal es Amoramar; esto es lo que se ve sin tema.

   Los NOMBRES son los de siempre (`--gold` es «el acento», aunque en la Brújula
   sea ultramar): cambiarlos tocaría miles de reglas, y lo que importa es que
   cada tema los llene todos. Lo cuida tests/el-tema-del-cliente.test.mjs.
   Los valores salen del manual (§3 Color): #F4F5F7 · #FFFFFF · #1C1E21 ·
   #3548FF de día y #1C1E21 · #232529 · #E8EAED · #4F62FF de noche. */
:root, :root[data-theme="light"]{
  --gold:#3548ff;
  /* El color del PAPEL (número, reglas y títulos del documento que se imprime).
     Sale del acento de cada empresa; Amoramar lo fija en su tema. Si la ficha
     trae su propio `acento`, ese manda (`POSDoc.acento`). */
  --doc-acento:var(--gold);
  /* El canto del kit (manual de marca §8): el filete oscuro de 1 px bajo una
     pieza que se pulsa. Sale del fondo, así que sigue al tema solo. */
  --canto:color-mix(in srgb, #000 11%, var(--bg));
  /* El acero: la cuarta pieza del símbolo (el cuarto), en gris. Solo lo usa el
     logo; un tema de cliente puede darle su segundo color. */
  --acero:#8a8f96;
  /* La hoja: la pieza del símbolo que es del cliente (manual §10). En la
     Brújula es la señal; un tema la redefine con su color. */
  --marca-hoja:#3548ff;
  --gold-soft:#5a6bff;
  --gold-text:color-mix(in srgb, var(--gold) 55%, var(--ink));
  /* El aviso que se puede LEER: --warn a secas como texto se queda en 2,68:1
     sobre la arena (3,62:1 en la niebla de la Brújula). Mezclado al 60 % con la tinta llega
     a 5,3:1 o más en los cuatro temas y sigue viéndose naranja. --warn se queda
     para puntos, bordes y rellenos. */
  --warn-text:color-mix(in srgb, var(--warn) 60%, var(--ink));
  --bg:#f4f5f7;
  --surface:#ffffff;
  --surface-2:rgba(244,245,247,.6);
  --ink:#1c1e21;
  --muted:#5a5e65;
  --fondo-trazo:#5a5e65;          /* las líneas del fondo animado (kit «Marca animada») */
  /* El tercer gris del manual de marca (§8): fechas, unidades, rótulos de
     columna — lo que se lee después de todo lo demás. Y el «apagado»: la pista
     de un interruptor sin encender, un paso de la ruta que aún no llega. */
  /* OSCURECIDO el 10 oct 2026 (decisión de Samuel): era #80858c y daba
     3,2–3,7:1 sobre los fondos de día, por debajo de 4,5, y el kit lo usa como
     texto en ayudas, unidades, direcciones y cabeceras. #686c72 da 4,6–5,3:1 y
     sigue por debajo de `--muted` (6,0). Amoramar tiene el suyo en tema.css. */
  --meta:#686c72;
  /* El aviso del manual (§8 «Toast») es oscuro en los dos modos: grafito con
     su tinta clara. De noche el diseño base lo sube a la superficie elevada. */
  --aviso-fondo:#1c1e21;
  --aviso-tinta:#e8eaed;
  --apagado:#e1e4e8;
  --border:rgba(28,30,33,.16);
  --border-2:rgba(28,30,33,.15);
  --border-3:rgba(28,30,33,.2);
  --tex-1:rgba(53,72,255,.12);
  --tex-2:rgba(28,30,33,.06);
  --shadow:rgba(28,30,33,.24);
  --danger:#c8372d;
  --danger-bg:rgba(200,55,45,.08);
  --gold-bg:rgba(53,72,255,.1);
  --ok:#1e8e5a;
  --ok-bg:rgba(30,142,90,.1);
  --info:#2f5f8a;
  --info-bg:rgba(47,95,138,.1);
  --warn:#c2690a;
  --warn-bg:rgba(194,105,10,.1);
  --chip:rgba(53,72,255,.08);
  --topbar:rgba(244,245,247,.8);
  --row-stripe:rgba(28,30,33,.03);
  --on-gold:#ffffff;
  /* Lo que va SIEMPRE oscuro con tinta clara encima, en los dos modos: --tip es el
     globo de ayuda de las gráficas y --on-velo, la tinta sobre un velo, un globo o
     una cabecera oscura (P11 b: retiran el crema escrito a mano en las pantallas). */
  --tip:#1c1e21; --on-velo:#f4f5f7;
  --on-danger:#fff;
  --on-ok:#fff;
  --on-info:#fff;
  --glow-gold:rgba(53,72,255,.35);
  --borde-control:color-mix(in srgb, var(--ink) 26%, transparent);
  --surface-raised:#ffffff;
  --surface-sunken:#edeff2;
  --ink-soft:#3a3d42;
  --coral:#c96f4a;
  --coral-text:#a5522f;
  --coral-bg:rgba(201,111,74,.1);
  --hairline:rgba(28,30,33,.12);
  --glass-chrome:rgba(255,255,255,.62);
  --glass-float:rgba(255,255,255,.74);
  --glass-soft:rgba(255,255,255,.5);
  --glass-ink:rgba(28,30,33,.6);
  --glass-edge:rgba(255,255,255,.4);
  --labio:rgba(28,30,33,.09);
  --sombra-contacto:rgba(28,30,33,.14);
  --sombra-ambiente:rgba(28,30,33,.12);
  --sombra-hundido:rgba(28,30,33,.08);
  --glass-line:rgba(53,72,255,.22);
  --glass-shadow:0 10px 40px -14px rgba(28,30,33,.26), 0 2px 8px -4px rgba(28,30,33,.12);
  --glass-chrome-solid:rgba(244,245,247,.96);
  --glass-float-solid:#ffffff;
}

/* ── Brújula · Modo mar (grafito) ── */
:root[data-theme="dark"]{
  --gold:#4f62ff;
  --doc-acento:var(--gold);
  --canto:color-mix(in srgb, #000 18%, var(--bg));
  --acero:#6e737a;
  --marca-hoja:#4f62ff;
  --gold-soft:#7282ff;
  --bg:#1c1e21;
  --surface:#232529;
  --surface-2:rgba(35,37,41,.55);
  --ink:#e8eaed;
  --muted:#a3a8af;
  --fondo-trazo:#a3a8af;
  --aviso-fondo:#1c1e21;
  --aviso-tinta:#e8eaed;
  --meta:#90959c;   /* era #7d828a (3,5–4,3:1); #90959c da 4,5–5,5:1 */
  --apagado:#3a3d43;
  --border:rgba(232,234,237,.16);
  --border-2:rgba(232,234,237,.14);
  --border-3:rgba(232,234,237,.18);
  --tex-1:rgba(79,98,255,.14);
  --tex-2:rgba(232,234,237,.05);
  --shadow:rgba(0,0,0,.55);
  --danger:#f0968d;
  --danger-bg:rgba(240,150,141,.1);
  --chip:rgba(79,98,255,.12);
  --gold-bg:rgba(79,98,255,.14);
  --row-stripe:rgba(232,234,237,.03);
  --ok:#6fcf9f;
  --ok-bg:rgba(111,207,159,.12);
  --info:#8fbfe0;
  --info-bg:rgba(143,191,224,.12);
  --warn:#f0a73a;
  --warn-bg:rgba(240,167,58,.12);
  --topbar:rgba(28,30,33,.78);
  --velo:rgba(0,0,0,.55);
  --velo-suave:rgba(0,0,0,.45);
  --velo-visor:rgba(0,0,0,.9);
  --tgl-off:#3a3d43;
  --tgl-knob:#c9cdd2;
  --on-danger:#3b1414;
  --on-ok:#0c2a1a;
  --on-info:#0a2233;
  --on-gold:#ffffff;
  --tip:#2b2e33; --on-velo:#e8eaed;
  --glow-gold:rgba(79,98,255,.35);
  --surface-raised:#2b2e33;
  --surface-sunken:#17191b;
  --brass:linear-gradient(180deg,#4f62ff,#4f62ff);
  --ring:0 0 0 3px rgba(79,98,255,.35);
  --ink-soft:#c9cdd2;
  --coral:#e08a63;
  --coral-text:#e08a63;
  --coral-bg:rgba(224,138,99,.12);
  --hairline:rgba(232,234,237,.12);
  --glass-chrome:rgba(35,37,41,.5);
  --glass-float:rgba(35,37,41,.62);
  --glass-soft:rgba(35,37,41,.4);
  --glass-ink:rgba(17,18,20,.66);
  --glass-edge:rgba(232,234,237,.07);
  --marco:color-mix(in srgb, var(--gold) 30%, transparent);
  --labio:rgba(0,0,0,.25);
  --sombra-contacto:rgba(0,0,0,.42);
  --sombra-ambiente:rgba(0,0,0,.36);
  --sombra-hundido:rgba(0,0,0,.25);
  --glass-line:rgba(79,98,255,.22);
  --glass-shadow:0 12px 44px -14px rgba(0,0,0,.65), 0 2px 8px -4px rgba(0,0,0,.4);
  --glass-chrome-solid:rgba(30,32,35,.96);
  --glass-float-solid:#232529;
}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --gold:#4f62ff;
    --doc-acento:var(--gold);
    --canto:color-mix(in srgb, #000 18%, var(--bg));
    --acero:#6e737a;
    --marca-hoja:#4f62ff;
    --gold-soft:#7282ff;
    --bg:#1c1e21;
    --surface:#232529;
    --surface-2:rgba(35,37,41,.55);
    --ink:#e8eaed;
    --muted:#a3a8af;
    --fondo-trazo:#a3a8af;
    --aviso-fondo:#1c1e21;
    --aviso-tinta:#e8eaed;
    --meta:#90959c;
    --apagado:#3a3d43;
    --border:rgba(232,234,237,.16);
    --border-2:rgba(232,234,237,.14);
    --border-3:rgba(232,234,237,.18);
    --tex-1:rgba(79,98,255,.14);
    --tex-2:rgba(232,234,237,.05);
    --shadow:rgba(0,0,0,.55);
    --danger:#f0968d;
    --danger-bg:rgba(240,150,141,.1);
    --chip:rgba(79,98,255,.12);
    --gold-bg:rgba(79,98,255,.14);
    --row-stripe:rgba(232,234,237,.03);
    --ok:#6fcf9f;
    --ok-bg:rgba(111,207,159,.12);
    --info:#8fbfe0;
    --info-bg:rgba(143,191,224,.12);
    --warn:#f0a73a;
    --warn-bg:rgba(240,167,58,.12);
    --topbar:rgba(28,30,33,.78);
    --velo:rgba(0,0,0,.55);
    --velo-suave:rgba(0,0,0,.45);
    --velo-visor:rgba(0,0,0,.9);
    --tgl-off:#3a3d43;
    --tgl-knob:#c9cdd2;
    --on-danger:#3b1414;
    --on-ok:#0c2a1a;
    --on-info:#0a2233;
    --on-gold:#ffffff;
    --tip:#2b2e33; --on-velo:#e8eaed;
    --glow-gold:rgba(79,98,255,.35);
    --surface-raised:#2b2e33;
    --surface-sunken:#17191b;
    --brass:linear-gradient(180deg,#4f62ff,#4f62ff);
    --ring:0 0 0 3px rgba(79,98,255,.35);
    --ink-soft:#c9cdd2;
    --coral:#e08a63;
    --coral-text:#e08a63;
    --coral-bg:rgba(224,138,99,.12);
    --hairline:rgba(232,234,237,.12);
    --glass-chrome:rgba(35,37,41,.5);
    --glass-float:rgba(35,37,41,.62);
    --glass-soft:rgba(35,37,41,.4);
    --glass-ink:rgba(17,18,20,.66);
    --glass-edge:rgba(232,234,237,.07);
    --marco:color-mix(in srgb, var(--gold) 30%, transparent);
    --labio:rgba(0,0,0,.25);
    --sombra-contacto:rgba(0,0,0,.42);
    --sombra-ambiente:rgba(0,0,0,.36);
    --sombra-hundido:rgba(0,0,0,.25);
    --glass-line:rgba(79,98,255,.22);
    --glass-shadow:0 12px 44px -14px rgba(0,0,0,.65), 0 2px 8px -4px rgba(0,0,0,.4);
    --glass-chrome-solid:rgba(30,32,35,.96);
    --glass-float-solid:#232529;
  }
}

/* ── La marca de la PLATAFORMA (no cambia con el cliente) ─────────────────
   Los colores de la Brújula como MARCA, no como paleta: con ellos se pinta su
   símbolo y su ficha en el manual. Ningún tema de cliente los redefine —si lo
   hiciera, el logo de la plataforma saldría con los colores de otra empresa—,
   así que no se usan para pintar el portal: para eso están --gold, --bg y los
   demás. Son los del manual de marca, §3. */
:root{
  --brujula-niebla:#f4f5f7;       /* el fondo de día */
  --brujula-tecla:#ffffff;        /* la tecla de día */
  --brujula-grafito:#1c1e21;      /* la tinta de día y el fondo de noche */
  --brujula-tinta-noche:#e8eaed;  /* la tinta de noche */
  --brujula-acero:#8a8f96;        /* el cuarto */
  --brujula-ultramar:#3548ff;     /* la señal de día */
  --brujula-ultramar-noche:#4f62ff; /* la señal de noche: un punto más de luz */
  /* Sin tema de cliente, el tema puesto es el estándar. */
  --tema-nombre:"Brújula";
  --tema-letras:"Geist y Syne";
}

/* ── Escalas (independientes del tema) ────────────────────────────────────
   Estas no cambian entre playa y mar; viven en :root global. */
:root{
  /* ── El sitio que se reserva para la barra del teléfono ──────────────────
     CERO por defecto, y a propósito: sin barra no hay nada que reservar. El
     valor de verdad lo pone `assets/nav-movil.css` dentro de su media query,
     y esa hoja SOLO la inyecta theme.js cuando la barra se pinta —si no hay
     sesión, si `/api/barra` falla o si estamos en escritorio, no existe—.
     Vive aquí para que el token tenga siempre una definición alcanzable: una
     variable sin fallback y sin dueño es un hueco que desaparece en silencio,
     y eso es justo lo que esta reserva no puede permitirse. */
  --amr-bar-hueco: 0px;

  /* Liquid Glass: intensidades de blur/saturación (no cambian por tema) */
  /* Estos cuatro se escribieron a la vez que el resto del vocabulario de
     vidrio, y el portal nunca los usó: construyó su vidrio a mano, 223 veces.
     Al medir esas 223 salió que ya había convenio —blur(16px) saturate(1.5)
     en las 44 barras superiores— distinto del que decían los tokens (18/1.6).
     Manda lo que el portal hace, no lo que el token dice: se bajan a 16/1.5
     y así estrenarlos NO cambia un píxel. Un token que obliga a repintar
     para adoptarse no se adopta. */
  --glass-blur-chrome:16px;   /* barras superiores: las 44 ya iban así */
  --glass-blur-float:28px;    /* flotantes (aún sin usar: ver CAPA-MOVIL.md) */
  --glass-blur-soft:12px;
  --glass-sat:1.5;

  /* Tipografía · familias --------------------------------------------------
     El portal usa la sans de sistema (Montserrat en Apple) para títulos y
     UI. EB Garamond itálica es el toque editorial/elegante (subtítulos, citas).
     IntroRust y CanvaSans solo viven en el lienzo del catálogo (no en la UI). */
  /* LAS FAMILIAS VIVEN EN `assets/fonts.css`, junto a sus `@font-face`, y no
     aquí. Estaban declaradas en las DOS hojas con valores distintos —cuatro
     fallbacks allí y siete aquí— y como fonts.css se carga DESPUÉS ganaba la
     suya: este bloque llevaba meses muerto y el portal caía a la fuente del
     sistema antes de lo que su propio canon decía. Un token declarado dos
     veces no es un token: es una apuesta sobre el orden de los <link>.
     Aquí se quedan `--font-num` y `--font-mono`, que no se duplican. */
  /* Monoespaciada. Existía de hecho —17 declaraciones en cinco stacks
     distintos, todos empezando por `ui-monospace`— y no tenía token, así que
     cada quien escribía su cadena y alguna se dejaba fallbacks. Es para
     código e identificadores: las cifras de dinero van con `--font-num`. */
  --font-mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,monospace;
  --font-num:-apple-system,BlinkMacSystemFont,"Helvetica Neue",Arial,sans-serif; /* tabular-nums para cifras */
  /* La mono de la MARCA (manual §4 «Letra»: Geist Mono): fechas en versalita,
     números de documento, cifras de tabla y unidades. Mientras su archivo no
     viaje con el portal, cae a la mono del sistema. */
  --font-mono-marca:"Geist Mono",ui-monospace,SFMono-Regular,"SF Mono",Menlo,monospace;
  /* El canto del acento (manual §8 «Botones»): el filete oscuro bajo el botón
     primario. Sale del acento, así que sigue al tema y al cliente solo. */
  --acento-canto:color-mix(in srgb, var(--gold) 70%, #000);

  /* ══ TIPOGRAFÍA · LA ESCALA ═════════════════════════════════════════════
     Diez pasos con los nombres de iOS. Decisión de Samuel (26 ago 2026) dentro
     del rediseño: «la escala iOS de verdad».

     POR QUÉ ESTOS DIEZ Y NO OTROS. Se midieron las 3.534 declaraciones de
     `font-size` del portal contra cuatro escalas candidatas:

       escala                    se mueven   >1px
       los 8 tokens de antes     2.316 (66%)  404
       esos 8 + 11 y 12          1.454 (42%)  165
       ESTA (iOS calibrada)      1.748 (50%)  142   ← la que menos ROMPE
       solo quitar medios píxeles 1.080 (31%)   0   (ya hecho, otra tanda)

     La de antes tenía dos problemas. Uno: sus ocho pasos dejaban fuera los DOS
     tamaños más usados del portal —11px (18,7%) y 12px (18,2%)—, así que
     adoptarla movía el 66%. Y dos: sus nombres no dicen para qué sirve cada uno.
     `--text-sm` no significa nada; `--text-nota` sí.

     LOS NOMBRES VAN EN ESPAÑOL porque el repo va en español, pero la escala es
     la de iOS paso por paso, así que se anota su equivalente al lado: quien
     venga de las Human Interface Guidelines la reconoce.

     QUÉ CAMBIA AL ADOPTARLA. El cuerpo del portal sube de 11-13px a 15-17. Es
     más legible y menos denso: cabe menos por pantalla, y eso es una decisión
     tomada, no un efecto secundario. Por eso NO se migra en un barrido — va
     pantalla por pantalla, empezando por las tres que son el 53% del uso
     (rutas-activas, pedidos-flash, lotes). Ver `docs/DESIGN-SYSTEM.md`.
     ═══════════════════════════════════════════════════════════════════════ */
  --text-micro:10px;    /* caption2  · badges, micro-etiquetas */
  --text-mini:11px;     /* caption1  · eyebrow y kicker en mayúsculas */
  --text-nota:12px;     /* footnote  · pies, notas al margen */
  --text-apoyo:13px;    /* subhead   · descripciones de tarjeta, texto de apoyo */
  --text-guia:15px;     /* callout   · etiquetas de campo, botones */
  --text-cuerpo:17px;   /* body      · el texto que se LEE, y el mínimo de un
                                       campo: iOS amplía la página por debajo de 16 */
  --text-titulo3:20px;  /* title3    · título de fila, cifra de tarjeta */
  --text-titulo2:22px;  /* title2    · encabezado de sección */
  --text-titulo1:28px;  /* title1    · título de pantalla */
  --text-portada:34px;  /* largeTitle· saludo del Inicio, portada de módulo */

  /* Los dos de marca, que NO son escala de lectura: el wordmark y el H1 del
     Inicio. Se quedan por su nombre porque son piezas, no pasos. */
  --text-wordmark:38px;
  --text-hero:88px;
  --text-display:clamp(30px,4.2vw,40px);

  /* ── Los nombres de antes, mientras quedan pantallas sin migrar ──────────
     32 usos repartidos por el portal. Apuntan al paso MÁS CERCANO de la escala
     nueva, así que una pantalla sin migrar no se rompe — se mueve como mucho un
     píxel. Se retiran cuando `tests/tipografia-escala-ios.test.mjs` diga que ya
     no los usa nadie. */
  --text-2xs:var(--text-micro);
  --text-xs:var(--text-micro);
  --text-sm:var(--text-apoyo);
  --text-base:var(--text-guia);
  --text-md:var(--text-cuerpo);
  --text-lg:var(--text-titulo3);
  --text-xl:var(--text-titulo2);
  --text-2xl:var(--text-wordmark);

  /* Tipografía · pesos y interletraje --------------------------------------
     El rasgo distintivo de Brújula: MAYÚSCULAS con tracking amplio para
     eyebrows, etiquetas, CTA y nombre de marca. */
  --weight-regular:400;
  --weight-medium:500;
  --weight-semibold:600;
  --weight-bold:700;
  /* EL TECHO ES 700, Y NO POR GUSTO: es el peso más gordo que `fonts.css`
     carga. Este token valió 800 desde jul 2026 «para KPIs y montos», y 415
     declaraciones lo pedían — medido en el navegador, la misma cadena a 40px
     ocupa 547,52px con 700, con 800 y con 900: CERO píxeles de diferencia (el
     control 600 vs 700 sí mueve 8.122 píxeles). O sea que el énfasis fuerte que
     el canon legitimó no existía en pantalla y nadie podía verlo. Bajó a 700 el
     30 ago 2026 (decisión de Samuel) en vez de añadir la cara de 800, que sí se
     vería y cambiaría 43 archivos de golpe. El nombre se queda para no tocar
     415 sitios; lo que cambia es la promesa. */
  --weight-extrabold:700;
  --track-tight:0;
  /* LOS TRES ESPACIADOS DE UN RÓTULO EN VERSALITAS (tanda 5, 23 sep 2026):
     había 596 rótulos con 29 espaciados distintos. Ahora hay tres, uno por
     familia, y ninguno se movió más de .05em:
       wide    · chips, insignias y botones en versalitas (antes .01–.08)
       wider   · rótulos de campo y cabeceras de tabla     (antes .09–.16)
       widest  · antetítulos (eyebrows) sobre un título     (antes .18–.25)
     Lo de .28em en adelante es espaciado de MARCA (--track-brand). */
  --track-wide:.06em;
  --track-wider:.12em;
  --track-widest:.2em;
  --track-brand:.45em;    /* wordmark grande del home */
  --leading-tight:1.02;   /* títulos grandes */
  --leading-snug:1.2;     /* títulos de tarjeta */
  --leading-normal:1.55;  /* cuerpo */

  /* Espaciado · escala de 4px ---------------------------------------------- */
  --space-1:4px;
  --space-2:8px;
  --space-3:12px;
  /* Cerrados a la rejilla de 4 el 26 ago 2026. Estos cuatro estaban FUERA de su
     propia escala (14, 18, 22) y eso convierte el canon en una sugerencia: quien
     mide con él nunca cuadra con quien mide a ojo.
     Se corrige AHORA porque los --space-* se usan 37 veces en todo el portal y
     estos cuatro solo 8: mover ocho sitios 2px es barato. Después de propagar la
     escala habría que mover miles. --space-7 pasa a 28 para no chocar con el
     nuevo --space-6; lo usa un solo sitio. */
  --space-4:16px;   /* gap base del portal (grids, topbar) */
  --space-5:20px;
  --space-6:24px;   /* padding interno de tarjeta */
  --space-7:28px;   /* padding de topbar / sección */
  --space-8:32px;   /* padding de frame / página */
  --space-10:48px;  /* padding lateral de frame en escritorio */

  /* Radios -----------------------------------------------------------------
     Tono moderno: esquinas suavemente redondeadas. Controles con radio chico,
     tarjetas/paneles con radio medio, superficies grandes con radio amplio.
     Las barras a borde completo (topbar) siguen rectas; chips/badges = píldora. */
  --radius-none:0;        /* barras a borde completo (topbar), separadores */
  --radius-sm:8px;        /* botones, inputs, selects (kit del manual, 30 sep 2026; era 12) */
  --radius-md:12px;       /* tarjetas, paneles, toast, cajas de icono, menús (kit; era 16) */
  --radius-panel:16px;    /* ventanas y diálogos (kit del manual, §8 «Diálogo») */
  --radius-lg:24px;       /* superficies grandes / lienzo (frame) */
  --radius-pill:999px;    /* etiquetas / chips redondeados, badges numéricos */
  /* SILUETA ORGÁNICA (21 sep 2026, orden de Samuel: «que el diseño sea más
     divertido, con profundidad, orgánico»). Cuatro esquinas DISTINTAS, y esa es
     toda la idea: una pieza que flota sobre el contenido con las cuatro iguales
     se lee como un recorte del marco de la ventana; desiguales se lee como un
     objeto puesto encima, y además dice hacia qué lado se abre. Viven aquí y no
     a mano en la hoja del carril porque un radio es un token —y porque el día
     que otra pieza flote va a querer el mismo perfil, no uno parecido. */
  --radius-organico:22px 56px 44px 28px;     /* superficies flotantes (paneles) */
  /* Re-ajustado el 21 sep 2026 al crecer la zona de activación: con la pestaña
     a 30 px de ancho, un radio de 22 se comía el 73% de su anchura y la esquina
     dejaba de ser una esquina. A 16 son el 53%: sigue siendo claramente
     desigual y vuelve a leerse como una pieza. */
  --radius-organico-sm:3px 14px 16px 5px;    /* piezas pequeñas (la pestaña) */

  /* Bordes · grosores ------------------------------------------------------ */
  --stroke:1px;           /* todo el portal es de trazo fino de 1px */

  /* Sombras · elevación -----------------------------------------------------
     Difusas y suaves (tono moderno): blur amplio, opacidad baja. */
  /* v2: DOS capas — contacto (nítida, cortita) + ambiente (amplia, tenue).
     La tarjeta "toca" el fondo en vez de flotar borrosa. */
  --elev-1:inset 0 1px 0 var(--glass-edge), 0 1px 2px rgba(28,30,33,.05), 0 10px 28px -14px var(--shadow);   /* tarjeta en hover */
  --elev-2:inset 0 1px 0 var(--glass-edge), 0 2px 4px rgba(28,30,33,.06), 0 24px 56px -18px var(--shadow);   /* menú / popover */
  --elev-3:inset 0 1px 0 var(--glass-edge), 0 6px 16px rgba(28,30,33,.08), 0 28px 60px -20px var(--shadow);   /* flotante (modal/popover rico) — v4 */

  /* ══ PLANO CON PROFUNDIDAD (23 sep 2026, decisión de Samuel) ═══════════════
     «Diseño plano pero con profundidad: los botones y demás tienen colores
     uniformes pero con efecto de profundidad». Eligió la intensidad «táctil»
     entre tres, viendo la propuesta en los dos temas.

     NINGÚN OBJETO LLEVA DEGRADADO NI TEXTURA — fue lo que se descartó el 6 sep
     por convencional—. El relieve sale de capas finas sobre un color sólido:
       · canto de luz de 1 px arriba (`--glass-edge`, que estaba escrito y sin
         usar): lo que más relieve da por menos;
       · labio de 1 px abajo, más oscuro: asienta el objeto;
       · sombra de contacto pegada, y una ambiente corta.

     UNA REGLA PARA SABER CUÁL VA DÓNDE:
       lo que se PULSA sube  → `--relieve` (botones)
       lo que se LLENA se hunde → `--hundido` (campos, buscador, pista de pestañas)
       lo que INFORMA es plano → nada (chips, estados, rótulos: no se tocan)
     y las superficies —tarjetas, paneles— llevan `--relieve-tarjeta`: la luz y
     la sombra, sin el labio, que es cosa de lo que se aprieta. */
  /* EL KIT DEL MANUAL (30 sep 2026, decisión de Samuel: «vestir las piezas
     actuales»). La pieza que se pulsa es una TECLA: un canto oscuro de 1 px
     debajo (`--canto`) y una sombra corta de contacto, en lugar del canto de
     luz arriba y el labio. Al apretarla baja 1 px y pierde la sombra. Las
     superficies llevan además su hilo (`--hairline`). La regla de siempre se
     queda: lo que se pulsa sube, lo que se llena se hunde, lo que informa es
     plano. Las `--elev-*` de lo que FLOTA no cambian. */
  --relieve:0 1px 0 var(--canto), 0 1px 2px var(--sombra-contacto);
  --relieve-pulsado:0 0 #0000;   /* apretado: baja 1 px y pierde la sombra */
  /* Las sombras del kit del manual de marca (§8), para el rediseño de la
     Brújula: el canto oscuro del botón primario, la pestaña elegida que es una
     tecla dentro de su bandeja, y la ventana que flota. */
  --relieve-primario:0 1px 0 var(--acento-canto), 0 1px 2px var(--sombra-contacto);
  --relieve-pieza:0 0 0 1px var(--hairline), 0 1px 2px var(--sombra-contacto);
  --elev-dialogo:0 0 0 1px var(--hairline), 0 24px 48px -16px var(--sombra-ambiente);
  --relieve-bien:0 1px 0 color-mix(in srgb, var(--ok) 70%, #000), 0 1px 2px var(--sombra-contacto);   /* la acción que confirma (Entregado) */
  --relieve-tarjeta:inset 0 0 0 1px var(--hairline), 0 1px 0 var(--canto), 0 1px 2px var(--sombra-contacto);
  /* La tecla GRANDE del manual (§6, «En el producto»): las fichas de módulo del
     Inicio. Canto de 2 y una sombra ambiente que apenas se nota; apretada, baja
     2 y se queda solo con su hilo. */
  --relieve-tecla-alta:inset 0 0 0 1px var(--hairline), 0 2px 0 var(--canto), 0 8px 18px -12px var(--sombra-ambiente);
  --relieve-tecla-hundida:inset 0 0 0 1px var(--hairline), 0 0 0 var(--canto);
  --hundido:inset 0 1px 2px var(--sombra-hundido);
  /* LO QUE SE PINTA SOBRE EL FONDO VIVO ES SÓLIDO (23 sep 2026, Samuel: «los
     widgets deben de dejar de ser translúcidos»). `--chip` es un 10 % de dorado
     TRANSPARENTE: en el plan se veía sobre un fondo quieto, y en el Inicio va
     encima de las olas, que se le ven a través. Este es el mismo tono ya
     mezclado con la arena (o el mar): se lee igual y no deja pasar nada. */
  --chip-solido:color-mix(in srgb, var(--gold) 12%, var(--bg));
  /* El marco dorado de una tarjeta de módulo: el dorado entero es el del hover,
     este es el de reposo — se ve el marco sin que grite. En Modo mar baja al
     30 % (se redefine en sus dos bloques): al 55 % sobre el azul contrastaba
     de más. */
  --marco:color-mix(in srgb, var(--gold) 55%, transparent);
  /* La medalla de un icono: sin aro, con relieve. Es `--relieve` sin la sombra
     ambiente —una marca de 48 px no flota, se asienta en su tarjeta—. */
  --relieve-marca:0 1px 0 var(--canto), 0 1px 2px var(--sombra-contacto);
  /* Latón pulido (primarios) + anillo de foco — evolución v4. Los temas ajustan. */
  --brass:linear-gradient(180deg,#3548ff,#3548ff);
  --ring:0 0 0 3px rgba(53,72,255,.28);
  --elev-toast:inset 0 1px 0 rgba(255,255,255,.08), 0 2px 4px rgba(28,30,33,.06), 0 12px 34px -10px var(--shadow); /* toast flotante: su canto es blanco fijo, porque su fondo es la TINTA */
  /* El segmento ACTIVO de un control segmentado (§8 «Tabs»): la pestaña elegida
     no se rellena de tinta, se LEVANTA de la pista. Una sombra corta y cercana
     —no la de una tarjeta, que flotaría dentro de su propio contenedor—. Estaba
     escrita a mano en `design-system.html` y en Rutas activas con el mismo
     valor; sube aquí porque ahora la usan las once pestañas del portal. */
  --elev-seg:0 0 0 1px var(--hairline), 0 1px 2px var(--sombra-contacto);   /* la pestaña elegida: un hilo y una sombra corta (kit del manual, 30 sep 2026) */

  /* Movimiento (espejo de anim.css; reúsalos para coherencia) --------------
     LOS CUATRO PASOS SON ESTOS. Cualquier duración nueva sale de aquí.

     `--amr-dur-view` y `--amr-dur-lento` se USABAN sin existir: nav.css los
     escribía 6 veces y las tres pantallas de Seguimiento 3, siempre con valor
     de reserva —`var(--amr-dur-view,.28s)`—, así que el token era decorativo y
     mandaba siempre la reserva. Se definen aquí CON SU VALOR EFECTIVO ACTUAL
     (280 y 340 ms), para que definirlos no mueva un píxel: lo que cambia es
     que a partir de ahora se pueden ajustar en un sitio en vez de en nueve. */
  /* LOS TIEMPOS Y LAS CURVAS DEL MANUAL DE MARCA (30 sep 2026, §6 «Movimiento»).
     Cuatro pasos —toque 140, estado 220, llega 300, techo 340— y tres curvas:
     «vivo» (un resorte que pasa un pelo y se asienta), «suave» (frena largo) y
     «sale» (acelera al irse, que lo que se va no se queda mirando). Donde el
     navegador sabe dibujar un resorte de verdad (`linear()`), se usa el
     resorte; donde no, su aproximación con `cubic-bezier`. Revoca 130/200 y el
     rebote de 1,56, que en un interruptor se leía como goma. */
  --amr-dur-fast:140ms;   /* toque: lo que responde al dedo */
  --amr-dur:220ms;        /* estado: lo que cambia de estado */
  --amr-dur-view:280ms;   /* cambio de vista dentro de una pantalla */
  --amr-dur-enter:300ms;  /* llega: lo que entra */
  --amr-dur-lento:340ms;  /* TECHO. Nada del portal debe pasar de aquí */
  --amr-ease:cubic-bezier(.22,.61,.36,1);    /* salida suave estándar */
  --amr-ease-out:cubic-bezier(.22,1,.36,1);  /* «suave»: frena largo */
  --amr-ease-spring:cubic-bezier(.3,.7,.4,1.12); /* «vivo»: resorte que se asienta */
  --amr-ease-press:cubic-bezier(.3,.7,.4,1.12);  /* «vivo», al soltar */
  --amr-ease-sale:cubic-bezier(.4,0,1,1);    /* «sale»: lo que se va acelera */
  --amr-ease-fun:cubic-bezier(.34,1.5,.55,1);     /* rebote visible, medido */
  --amr-rise:10px;        /* desplazamiento de entrada de <main> */

  /* La transición de un control, sin `all` ---------------------------------
     El portal escribía `transition:var(--amr-tr-ui, all .15s)` en 208 sitios —
     casi siempre el mismo botón, el mismo toggle de tema y el mismo chip,
     copiados de módulo en módulo. `all` no es "lo que cambie": es LITERALMENTE
     toda propiedad animable, incluidas las de layout. Basta que un estado toque
     el `padding`, el `height`, el `font-size` o el `gap` —y varios lo hacen— para
     que el navegador tenga que RE-MEDIR la página en cada fotograma de un hover.
     Es la clase de animación que nadie pidió y que solo se nota como tirón.

     Esta lista es lo que un control sí quiere transicionar: color, marco,
     sombra, opacidad, el gesto (transform) y el brillo. Nada que mueva el
     layout. `transform` va dentro a propósito — sacarlo dejaría el press sin
     transición, porque una declaración de `transition` reemplaza a la de
     anim.css, no se suma a ella.

     Se usa como `transition:var(--amr-tr-ui, all .15s)`: el valor de reserva
     mantiene el comportamiento de antes en una página que no cargue tokens.css. */
  --amr-tr-ui:
    background-color var(--amr-dur-fast), color var(--amr-dur-fast),
    border-color var(--amr-dur-fast), box-shadow var(--amr-dur-fast),
    opacity var(--amr-dur-fast), transform var(--amr-dur-fast),
    filter var(--amr-dur-fast), fill var(--amr-dur-fast), stroke var(--amr-dur-fast);

  /* Capas (z-index) -------------------------------------------------------- */
  --z-base:1;
  --z-card-accent:2;
  --z-topbar:1000;
  --z-popover:100;
  --z-overlay:2000;
  /* Hoja/modal del kit (.ui-modal lo referencia). POR ENCIMA de la navegación:
     el rail y la barra inferior viven en 1200 y las hojas propias de nav.js en
     1300, así que con 1200 empataba con la barra del móvil y —al montarse esta
     después en el <body>— la barra tapaba el pie del diálogo: en un teléfono el
     botón de guardar quedaba debajo de «Hoy · Rutas · Mostrador». Un diálogo
     bloquea la pantalla; si algo se tapa, se tapa la navegación. */
  --z-modal:1400;
  /* LOS TRES VELOS (tanda 3, 23 sep 2026): había 58 reglas de velo con 26
     valores distintos para la misma idea. Ahora son tres, por lo que tapan:
       --velo-suave · menús, cajones y avisos que dejan ver lo de detrás;
       --velo       · una ventana (modal) que pide atención;
       --velo-visor · un visor de fotos o un calendario a pantalla completa.
     En claro, del color de la tinta del tema; en oscuro, negro (la tinta es
     clara y no sirve de velo). */
  --velo-suave:rgba(17,18,20,.4);
  --velo:rgba(17,18,20,.5);
  --velo-visor:rgba(17,18,20,.9);
  /* Los interruptores: la pista apagada y la perilla (anim.css los pinta). */
  --tgl-off:#d9dde2;
  --tgl-knob:#1c1e21;
  /* La verificación en dos pasos (assets/verificar-cangrejo.js) va POR ENCIMA de
     la hoja que la abre, y las hojas de módulo suben mucho más que `--z-modal`:
     la lista del Modo Entrega —donde vive el borrado en el celular— está en
     9600, y los overlays de Rutas activas llegan a 10100. Con el valor de un
     modal normal la ventana se pintaba DETRÁS y el borrado parecía no responder.
     Por debajo de la alarma y del logro a pantalla completa (99998/99999), que
     sí deben ganarle a todo. */
  --z-verificacion:10600;
  --z-toast:9999;

  /* Layout ----------------------------------------------------------------- */
  --maxw-frame:1600px;    /* ancho máximo del lienzo del portal */
  --maxw-read:680px;      /* ancho máximo cómodo de lectura */
  /* Objetivo táctil mínimo. Era 42 y pasa a 44 (ago 2026) por dos razones: es
     lo que ya decía `--alto-control-movil` justo abajo —había dos números para
     la misma idea— y es contra 44 contra lo que se mide. El cambio no mueve
     nada hoy: este token no lo usaba ni un selector del portal, que es
     exactamente el defecto. Los controles medidos a 390 px iban de 20 a 39 px. */
  /* ── EL NOTCH, con nombre ────────────────────────────────────────────────
     `env(safe-area-inset-*)` se escribía a mano 208 veces en 53 archivos y en
     DIEZ formas distintas, sin un solo token. Aquí están los cuatro lados.

     Y una advertencia que cuesta una pantalla entender: `max(14px, env(top))`
     NO deja 14px de aire bajo la isla dinámica — deja CERO. En un iPhone el
     inset superior vale 59px, así que el max() se queda con 59 y el contenido
     arranca justo en el borde de la isla, pegado. Lo que deja aire es SUMAR:
     `calc(env(top) + 14px)`. En un teléfono sin notch env() vale 0 y las dos
     formas dan exactamente 14px, así que cambiar de una a otra no mueve nada
     donde no hay notch y arregla justo donde lo hay.

     Abajo es distinto y por eso `max()` SÍ vale ahí: el inset inferior (34px en
     los iPhone con gesto) es la franja del indicador, que ya está vacía. Ponerse
     a 34px es apoyarse en su borde, no meterse debajo. */
  --safe-top:env(safe-area-inset-top, 0px);
  --safe-bottom:env(safe-area-inset-bottom, 0px);
  --safe-left:env(safe-area-inset-left, 0px);
  --safe-right:env(safe-area-inset-right, 0px);

  --tap-min:44px;

  /* Aire que una tarjeta necesita alrededor para que su sombra no se recorte
     contra el borde de un panel con scroll. Lo usaban anim.css y
     barra-controles.css con reserva `,14px`, sin que el token existiera. */
  --tarjeta-aire:14px;

  /* Canalón lateral · el margen a los lados de TODA pantalla -----------------
     UN solo par de valores para el aire lateral del portal: el marco de la
     página (`main`/`.wrap`/`.main`), la topbar, las barras fijas (paginador,
     acciones) y los filtros del kit se alinean con él. Se ajusta AQUÍ y cambia
     el portal entero; ningún módulo vuelve a escribir su canalón a mano.

     Ago 2026 (orden de Samuel): el aire lateral se estrecha mucho y el lienzo
     se ensancha. Eran DOS márgenes distintos confundidos en uno:

     · El CANALÓN (padding del marco): 24px en escritorio y 12–16 en móvil,
       repetido a mano en 47 páginas. Pasa a 12 y 10. Es el que se ve en un
       portátil, donde la ventana mide menos que el lienzo y el padding ES todo
       el margen.
     · El LIENZO (--maxw-frame): topado en 1280px. En un monitor de 1920 dejaba
       320px muertos a CADA lado y bajar el canalón ahí no cambiaba nada,
       porque el margen no lo ponía el padding sino el tope de ancho. Sube a
       1600px, que es lo que de verdad estira el contenido en pantalla grande.

     Las dos cosas a la vez: en portátil se gana por el canalón, en monitor por
     el lienzo. Tocar solo una deja la mitad del portal igual que estaba. */
  --pad-x:12px;           /* canalón lateral en escritorio (antes 24, a mano) */
  --pad-x-movil:10px;     /* canalón lateral en móvil (antes 12–16, a mano) */

  /* Puntos de corte ---------------------------------------------------------
     LOS TRES DE ABAJO SON LOS ÚNICOS PARA PANTALLAS NUEVAS. No se inventan más.

     Los tres coinciden con los que ya usa la mayoría del portal (520 en 65
     reglas, 760 en 48, 1100 en 11), así que no imponen nada nuevo: recogen lo
     que ya se decidió a base de repetirlo.

     PERO el portal tiene hoy 16 cortes reales, no 3, y la diferencia no es
     descuido en su mayoría (jul 2026, al ir a unificarlos):

     · Los pares n / n+1 —640/641, 760/761, 720/721, 980/981, 899/900,
       1023/1024, 1100/1101, 1180/1181— son CORRECTOS: así las dos reglas no se
       solapan en el píxel de frontera. Contarlos como duplicados fue un error
       de lectura de la primera auditoría, repetido en la segunda.
     · 600 (16 reglas), 720 (12), 820 (6), 900 (15), 420 (3) tienen peso propio:
       son decisiones de diseño de pantallas concretas, no despistes.
     · 380 es «móvil pequeño» de verdad (iPhone SE/mini). Subirlo a 420
       apretaría el layout de un iPhone 14, que mide 390. Se queda.
     · 680 y 1400 son de `etiquetas-producto`, declarada EXCEPCIÓN por Samuel:
       dibuja etiquetas en milímetros y el token de pantalla no le aplica.

     Bajar de 16 a 3 no es limpiar: es rediseñar dónde rompe cada pantalla, y
     hacerlo a ciegas descuadra el portal en anchos que nadie mira hasta que un
     usuario los sufre. Lo que sí se hizo fue absorber los HUÉRFANOS —los que
     aparecían una o dos veces sin razón—: 559→560, 1000→980, 400→420, 620→640. */
  --breakpoint-mobile:520px;
  --breakpoint-tablet:760px;
  --breakpoint-wide:1100px;

  /* Anchos de bloque interno ------------------------------------------------
     La auditoría encontró 63 anchos distintos, 37 de ellos usados UNA sola vez.
     El de PÁGINA ya estaba resuelto (1280 en las 41); el desorden estaba
     dentro: 520, 560, 640, 720, 760, 900… para lo mismo.

     DOS, no tres (decisión de Samuel, jul 2026). La propuesta eran tres
     —diálogo 480 / formulario 640 / detalle 960—; se eligió reducir a dos para
     que al construir una pantalla nueva no haya que decidir nada. El precio
     aceptado: un formulario de una columna queda más ancho de lo ideal para
     leer. Si algún día molesta, se corta con --maxw-read (680) sin tocar esto.

     EL DIÁLOGO ES 520, no 480 (ajustado al aplicarlo). Se eligió 480 sobre una
     lista de valores, sin el desglose delante; al tokenizar los once diálogos
     del portal apareció el dato: 520 es lo que ya usaban DIECISÉIS reglas y 480
     solo tres. O sea que 520 no es una preferencia, es lo que el portal decidió
     a base de repetirlo, y es lo que el equipo lleva tiempo viendo. Estrechar
     once diálogos 40 px no le daba nada a nadie.

     Que cambiarlo haya sido editar ESTA línea, y no once archivos, es
     exactamente para lo que se tokeniza. */
  --maxw-dialogo:520px;    /* confirmar, avisar: una frase y dos botones */
  --maxw-contenido:900px;  /* todo lo demás: formulario, detalle, tabla */

  /* Alturas de control ------------------------------------------------------
     Densidad: compacta en escritorio (se ve más de un vistazo), cómoda en móvil
     (se trabaja con prisa y con el pulgar). Nunca por debajo de --tap-min.    */
  --alto-control:36px;    /* botón, campo, select en escritorio */
  --alto-control-movil:44px;
  --alto-fila:36px;       /* fila de tabla en escritorio */
  --alto-fila-movil:44px;

  /* Foco --------------------------------------------------------------------
     El anillo del portal es `--ring`, definido arriba con los dos temas y usado
     por el kit y los módulos. Aquí vivía además `--foco-anillo`, con la misma
     idea y otro número (38 % contra el 28 % de `--ring`), y sin que lo llamara
     ni un selector: dos nombres para lo mismo, que es como acaban existiendo
     dos anillos distintos. Se retira; el que manda es `--ring`.

     El anillo de TECLADO no se dibuja con esto, sino con la regla `!important`
     de `anim.css` (§3a-bis), que gana a los `outline:none` que cada módulo
     escribió por su cuenta. Eso es a propósito y está comprobado con Tab real:
     ninguna pantalla del portal se queda sin señal de foco. */
}

/* ── El canalón se estrecha SOLO en el token, no en 29 pantallas ───────────
   `--pad-x-movil` existía desde ago 2026 y cada pantalla tenía que acordarse de
   bajarse a él en su media query. La cuenta al revisarlo (ago 2026): de 52
   páginas, 23 lo aplicaban solo a la topbar —el marco se quedaba en los 12 de
   escritorio— y 6 no lo nombraban nunca. O sea que el canalón de móvil valía
   para menos de la mitad del portal, y la diferencia no se ve pero se acumula:
   son 4 px de ancho útil en la pantalla donde menos sobra.

   Redefinir el token aquí lo arregla de una vez y para lo que venga: TODA regla
   que ya escribe `var(--pad-x)` —las 43 topbars y los 45 marcos— se estrecha
   sola en móvil, sin tocar una sola pantalla. Las que ya nombran
   `--pad-x-movil` en su media query siguen igual: piden el mismo valor.

   Se puede porque `--pad-x` NO tiene otro uso: las 100 apariciones del portal
   son canalón horizontal (topbar o marco). Se comprobó una a una antes de
   moverlo; si algún día se usa para otra cosa, esto deja de valer.

   El corte es 760 —el `--breakpoint-tablet` de arriba, que es el que ya usan 26
   de las 46 páginas que lo aplican— y no se escribe con la variable porque una
   media query no puede leer una custom property. */
@media (max-width:760px){
  :root{ --pad-x:var(--pad-x-movil); }
}

/* ═══════════════════════════════════════════════════════════════════════════
   BASE MÍNIMA
   Esto NO son tokens, y va aquí a propósito: `tokens.css` es la única hoja que
   cargan las 41 páginas. `ui.css` falta en 16, así que una regla puesta allí
   dejaría fuera justo a las que peor están.

   El foco de teclado no se veía en 34 de 41 páginas (defecto D-03). Quien no usa
   ratón —o usa el portal desde un teclado en el mostrador— no sabía dónde estaba
   parado. `:focus-visible` solo se dibuja cuando el navegador entiende que el
   foco viene del teclado, así que no ensucia el clic con el ratón.
   ═══════════════════════════════════════════════════════════════════════════ */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible{
  outline:2px solid var(--gold);
  outline-offset:2px;
  border-radius:var(--radius-sm,8px);
}

/* ── Rebote y pull-to-refresh (ago 2026) ──────────────────────────────────
   37 de 49 páginas no declaraban `overscroll-behavior` en ningún sitio. En la
   PWA instalada eso son dos cosas molestas: el pull-to-refresh del navegador se
   dispara al arrastrar hacia abajo en una lista que ya está arriba, y el rebote
   de un panel interno se encadena a la página de detrás.

   `contain` corta las dos y NO estorba al pull-to-refresh propio del portal:
   ese está hecho con `touchmove` + `preventDefault` (ver `app-ios.js`), no con
   el rebote nativo. Lo que se apaga es el del navegador, que es el que sobra.

   SOLO el eje Y, a propósito: `overscroll-behavior-x:contain` en la raíz apaga
   el gesto de «atrás» del sistema en Android, que es navegación que la gente
   usa. El eje X se contiene donde toca —en el contenedor con scroll de una
   tabla— y eso va en la pantalla, no aquí (ver §14.4 del sistema de diseño). */
html{ overscroll-behavior-y:contain; }
/* `:where()` tiene especificidad CERO: cualquier regla de página que ya defina
   su propio foco sigue mandando. Esto solo cubre a quien no tenía ninguno. */

/* Los resortes del manual, dibujados de verdad donde el navegador sabe
   (`linear()`): los mismos que usa el manual de marca. */
@supports (transition-timing-function: linear(0, 1)){:root{
  --amr-ease-spring:linear(0, 0.0307, 0.1096, 0.2192, 0.3448, 0.4748, 0.6004, 0.7155, 0.8162, 0.9005, 0.9679, 1.0191, 1.0553, 1.0786, 1.091, 1.0948, 1.092, 1.0846, 1.0743, 1.0624, 1.0501, 1.0382, 1.0272, 1.0176, 1.0096, 1.0032, 0.9983, 0.9948, 0.9926, 0.9914, 0.991, 0.9913, 0.992, 0.9929, 0.9941, 0.9952, 0.9964, 0.9974, 0.9983, 0.9991, 0.9997, 1.0002, 1.0005, 1.0007, 1);
  --amr-ease-press:var(--amr-ease-spring);
  --amr-ease-out:linear(0, 0.0229, 0.0809, 0.1609, 0.2526, 0.3486, 0.4435, 0.5334, 0.616, 0.69, 0.7548, 0.8104, 0.8573, 0.896, 0.9274, 0.9523, 0.9717, 0.9864, 0.9972, 1.0049, 1.01, 1.0131, 1.0147, 1.0152, 1.0148, 1.014, 1.0128, 1.0114, 1.0099, 1.0085, 1.0071, 1.0059, 1.0047, 1.0038, 1.0029, 1.0022, 1.0016, 1.0011, 1.0007, 1.0004, 1.0002, 1, 0.9999, 0.9999, 1);
}}
