/* avsal.css — 🎨 LA cara de AVSAL: los tokens del dashboard y de Brújula en UN solo archivo (fase 5 del plan maestro,
   tanda 1, 2026-09-16). Lo cargan los dos HTML con <link rel="stylesheet" href="/avsal.css"> ANTES de su <style>, igual que
   sesion.js. Regla de la casa: un token se define UNA vez y vive acá; ningún HTML vuelve a tener un :root con tokens
   (scripts/cara-check.js lo vigila en el gate del deploy y los golden tests leen 10 tokens congelados).
   Orden: (1) :root = los 49 tokens del dashboard copiados en bloque, mismos nombres y valores, + --sidebar-rail;
   (2) alias de Brújula: sus nombres apuntan al token del dashboard, así brujula.html no se reescribe y un color se cambia una vez
   para las dos apps; lo que no tiene par en el dashboard (chat, WhatsApp, marca, familias tipográficas) conserva el valor que
   Brújula ya tenía; (3) tema claro bajo html.light, body.light (el dashboard pone la clase en body y Brújula en html: los dos
   selectores para que nadie renombre nada) con los 36 tokens claros del dashboard + los alias que necesitan valor claro;
   (4) la base compartida y (5) los COMPONENTES que las dos apps pintan igual (tanda 2, 2026-09-16): pastilla, botones, vacío,
   globo de gráfico, el «?» que explica, «hace X min», el segmento de tema, el lockup de la marca y la pantalla de entrada. Un
   componente vive UNA vez, acá: los dos HTML borraron sus copias (cara-check.js lo vigila). Sin morado: --ia es el azul de --info.
   Sin !important en tokens. Referencia histórica: design-system-avsal.html. */

/* ── (1) Los tokens del dashboard — AVSAL Design System v3, base oscura, verde como acento ── */
:root{
  /* ── AVSAL Design System v3 — dark base · OKLCH→hex · verde acento ── */
  --bg:#080c0a;
  --bg2:#0f1411;
  --bg3:#181d1a;
  --bg4:#202622;

  --border:rgba(255,255,255,0.07);
  --border2:rgba(255,255,255,0.13);
  --ink-rgb:255,255,255;   /* ☀️ 2026-09-13: el blanco translúcido del oscuro; en claro es negro translúcido */
  --brillo:rgba(255,255,255,0.3);   /* 🏆 el brillo que cruza la pastilla de un logro (5-oct); en claro, blanco más firme */
  --border-focus:rgba(20,202,128,0.55);

  --text:#eef3f0;
  --text2:#9fa7a2;
  --text3:#858d88;  /* ♿ M-29 (tanda 8 de AVSAL Chat, 22-oct): de #7a827d (4,32:1 sobre --bg3, los rótulos de 10-11 px dentro de las tarjetas) a 5,0:1 sobre --bg3 · 5,8 sobre --bg (WCAG AA) */
  --text4:#4e5451;

  --accent:#14ca80;
  /* Tokens semánticos de los módulos 2026-06 (antes hex sueltos repetidos ~90 veces) */
  --info:#60a5fa;
  --info-rgb:96,165,250;                 /* el mismo azul en canal (para rgba(var(--info-rgb),α)) */
  /* 🚫 Sin morado (tanda 2, 2026-09-16): lo de IA se pinta con el azul de --info. --ia-dim es su suave y --ia-rgb su canal
     (los 90 rgba(167,139,250,α) del dashboard tenían 20 opacidades distintas: el suave cubre la de .12 y el canal las demás). */
  --ia:var(--info);
  --ia-rgb:var(--info-rgb);
  --ia-dim:rgba(var(--ia-rgb),.12);
  --warn:#eeb154;
  --hot:#f3a83a;
  --soft-red:#ff6b6b;
  --accent-hi:#3cde93;
  --accent-ink:#091a11;
  --accent-dim:rgba(20,202,128,0.12);
  --accent-gradient:linear-gradient(135deg,#1cd488 0%,#0ea96b 100%);

  --green:#14ca80;
  --green-dim:rgba(20,202,128,0.12);
  --green-gradient:linear-gradient(135deg,#1cd488 0%,#0ea96b 100%);
  /* ♿ El TEXTO de los tonos del semáforo (tanda 8): en oscuro es el mismo tono; el tema claro trae uno más oscuro que pasa 4,5:1.
     Puntos, barras, rellenos y bordes siguen con --green / --warn / --red. */
  --green-txt:var(--green);
  --warn-txt:var(--warn);
  --red-txt:var(--red);

  --red:#e8605b;
  --red-dim:rgba(232,96,91,0.12);
  --red-gradient:linear-gradient(135deg,#ed6f6a 0%,#d94b45 100%);

  --yellow:var(--warn);
  --yellow-dim:rgba(238,177,84,0.12);

  --blue:#63a8cf;
  --blue-dim:rgba(99,168,207,0.12);

  --purple:var(--ia);                    /* 🚫 sin morado: los 8 var(--purple) del dashboard pintan el azul de --ia */
  --purple-dim:var(--ia-dim);

  --gray:var(--text2);
  --sidebar-w:248px;
  --radius:10px;
  --radius-sm:6px;
  --radius-lg:14px;
  /* ⭐ Sistema de movimiento (pulido 2026-07-16; una sola curva desde el 4-oct, reglas de Emil Kowalski y Apple en
     .claude/skills): 180 ms y UNA curva fuerte, --ease-out, que arranca rápido (el ojo ve la respuesta de inmediato).
     --ease es la misma curva; los cajones que se deslizan usan --ease-drawer (la de iOS). ⛔ Nunca ease-in ni
     transition:all en la interfaz: se nombran las propiedades (como --transition). */
  --dur:180ms;
  /* El chevron de línea como máscara (para un ::after, donde no entra un <svg>). */
  --chev-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  --dur-fast:120ms;
  --ease:var(--ease-out);
  --ease-drawer:cubic-bezier(0.32, 0.72, 0, 1);

  --glow-shadow:0 0 0 1px rgba(20,202,128,0.30), 0 6px 20px rgba(20,202,128,0.12);
  --glow-shadow-green:0 0 0 1px rgba(20,202,128,0.30), 0 6px 20px rgba(20,202,128,0.12);
  --glow-shadow-red:0 0 0 1px rgba(232,96,91,0.30), 0 6px 20px rgba(232,96,91,0.10);
  --card-shadow:0 1px 2px rgba(3,8,5,0.5), 0 2px 8px rgba(3,8,5,0.32);
  --card-glass:#0f1411;

  --transition:background-color .16s var(--ease-out),border-color .16s var(--ease-out),color .16s var(--ease-out),fill .16s var(--ease-out),
    stroke .16s var(--ease-out),box-shadow .16s var(--ease-out),transform .16s var(--ease-out),opacity .16s var(--ease-out),filter .16s var(--ease-out);
  --ease-out:cubic-bezier(0.16, 1, 0.3, 1);
  /* Barra lateral contraída a riel de íconos (2026-09-13, al estilo de VoltyChat) */
  --sidebar-rail:68px;
  /* Degradado del título de la vista (tanda 4b). En claro vale «none» y el título se pinta plano:
     ⚠️ si este token se queda sin definir, el título se vuelve INVISIBLE (lleva -webkit-text-fill-color:transparent). */
  --titulo-grad:linear-gradient(130deg,#eef0f4 0%,#14ca80 55%,#8b95a8 100%);
  /* ── La cara profesional, tanda 1 (2026-09-23): los canales que faltaban, las escalas y la superficie ──
     El verde se escribía a mano 418 veces como rgba(20,202,128,·) porque no existía su canal: rgba(var(--accent-rgb),α)
     sigue al tema (en claro es el verde oscuro). Lo mismo para el rojo, el ámbar y el azul. */
  --accent-rgb:20,202,128;
  --red-rgb:232,96,91;
  --warn-rgb:238,177,84;
  --blue-rgb:99,168,207;
  /* Escala de espacios: de a 4 px. Un relleno o un hueco nuevo usa una de estas, no un número suelto. */
  --s-1:4px; --s-2:8px; --s-3:12px; --s-4:16px; --s-5:20px; --s-6:24px; --s-8:32px; --s-10:40px;
  /* Radios con nombre: tarjeta 12 · botón 8 · pastilla redonda. (--radius-sm 6, --radius 10 y --radius-lg 14 siguen igual.) */
  --radius-card:12px;
  --radius-btn:8px;
  --radius-pill:99px;
  /* Escala de letra: rótulo 10 · dato chico 12 · cuerpo 13 · título de tarjeta 16 · número 40 / 26 / 20. */
  --fs-label:10px;
  --fs-meta:12px;
  --fs-body:13px;
  --fs-title:16px;
  --fs-kpi-hero:40px;
  --fs-kpi:26px;
  --fs-kpi-sm:18px;   /* la compacta de las dos apps (lienzo v2: 18) */
  /* La superficie de TODA tarjeta de las dos apps: plana, borde de 1 px y, solo en claro, una sombra suave. */
  --surface:var(--bg2);
  --surface-shadow:none;
  /* Un solo modal (tanda 3): el velo que oscurece detrás y la sombra de la caja, iguales en las dos apps. */
  --modal-bg:rgba(3,6,4,0.66);
  --modal-shadow:0 24px 64px rgba(0,0,0,0.45);
  /* Gráficos (el kit de la tanda 2): cuadrícula, ejes y las tres barras neutras. El color va solo cuando avisa algo. */
  --grid:rgba(var(--ink-rgb),0.06);
  --axis:rgba(var(--ink-rgb),0.24);
  --bar-main:#8f9893;
  --bar-soft:#3b433e;
  --bar-faint:rgba(var(--ink-rgb),0.05);
  /* Las categorías (cuando el color solo dice «cuál es cuál»: a dónde fue la plata, los movimientos de la billetera).
     Cinco tonos SIN morado, en este orden, validados con el script de la skill dataviz (daltonismo, visión normal y contraste,
     en oscuro sobre --bg2 y en claro sobre blanco). Una sexta categoría no inventa color: va a «otros» (--bar-main). */
  --cat-1:#3987e5; --cat-2:#d95926; --cat-3:#1fa2b8; --cat-4:#d55181; --cat-5:#c98500;
}

/* ── (2) Alias de Brújula: cada nombre suyo apunta al token del dashboard ── */
:root{
  --line:var(--border);
  --line2:var(--border2);
  --r:var(--radius);
  --r-sm:var(--radius-sm);
  --r-lg:var(--radius-lg);
  --bad:var(--red);
  --bad-soft:var(--red-dim);
  --warn-soft:var(--yellow-dim);
  --info-dim:rgba(var(--info-rgb),.12);  /* el suave de --info (el dashboard no lo tenía) */
  --info-soft:var(--info-dim);
  --accent-soft:var(--accent-dim);
  --accent-line:rgba(20,202,128,0.35);   /* nuevo: borde en acento (Brújula lo usa en 3 sitios) */
  --ia-soft:var(--ia-dim);               /* el suave de --ia: en claro sigue solo a --info-rgb */
  --sb:var(--sidebar-w);
  --shadow:var(--card-shadow);
  /* Propios de Brújula, sin par en el dashboard. (--top, el alto de su barra de arriba, se fue con la barra en la tanda 4b.) */
  --wa:#25d366;
  --bub-in:#1a201d;
  --bub-out:#0e3526;
  --chat-bg:#0c100e;
  --sans:"Geist",ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
  --mono:"Geist Mono",ui-monospace,"SF Mono",Menlo,monospace;
  /* Marca AVSAL (identidad 2026-09-13): Bosque y Menta */
  --bosque:#0a3d2b;
  --menta:#bff3da;
}

/* ── (3) Tema claro — SalesOps neutral light. html.light (Brújula) y body.light (dashboard): los mismos valores ── */
html.light, body.light{
  --bg:#f8f9f5;
  --cat-1:#2a78d6; --cat-3:#1591a6;   /* los pasos claros de la paleta de categorías (el resto sirve igual en los dos) */
  --cat-2:#eb6834;
  --bg2:#ffffff;
  --bg3:#f1f3eb;
  --bg4:#e3e6de;
  --border:rgba(0,0,0,0.09);
  --border2:rgba(0,0,0,0.15);
  --ink-rgb:0,0,0;
  --brillo:rgba(255,255,255,0.85);
  --text4:#9aa195;   /* faltaba: heredaba el del oscuro y quedaba MÁS oscuro que --text3 */
  --border-focus:rgba(0,142,62,0.55);
  --text:#202318;
  --text2:#5c6356;
  --text3:#5f665a;  /* ♿ M-29 (tanda 8, 22-oct): de #666d60 (4,8:1 sobre --bg3 y 4,2 sobre --bg4) a 5,3 y 4,7; antes #828a7c */
  --accent:#007331;   /* ♿ M-29 (tanda 8, 22-oct): de #008e3e (4,02:1 sobre --bg; blanco encima 4,25) a 5,7:1 sobre --bg, 4,9 en un ítem elegido y 6,0 con blanco encima (WCAG AA) */
  --accent-ink:#ffffff;   /* el lienzo: texto blanco sobre el verde en claro (botón primario, segmento elegido) */
  --accent-dim:rgba(0,142,62,0.10);
  --accent-gradient:linear-gradient(135deg,#007331 0%,#006323 100%);
  /* 🚦 El semáforo claro (puntos, barras, rellenos y bordes): los tonos de siempre, que se distinguen entre sí también con daltonismo
     (rojo-verde: ámbar contra rojo 7,8 de distancia) y pasan 3:1 contra el fondo. Su TEXTO va con --green-txt / --warn-txt / --red-txt
     (tanda 8, revisión del 22-oct: oscurecerlos todos para el texto los dejaba casi con la misma luz y el ámbar y el rojo se confundían). */
  --green:#008e3e;
  --green-dim:rgba(0,142,62,0.10);
  --red:#e7000b;
  --red-dim:rgba(231,0,11,0.09);
  --yellow:#c2820d;
  --yellow-dim:rgba(194,130,13,0.10);
  /* ♿ M-29 (tanda 8): el TEXTO de esos tonos en claro, más oscuro para pasar 4,5:1 (también en su pastilla): 5,7 · 5,3 · 5,7 sobre --bg */
  --green-txt:#007331;
  --warn-txt:#8f5d00;
  --red-txt:#c8000a;
  --blue:#2563eb;
  --blue-dim:rgba(37,99,235,0.10);
  /* Tokens semánticos 2026-06 — variantes oscurecidas para fondo claro (--ia, --purple y sus suaves siguen a --info solos) */
  --info:#2563eb;
  --info-rgb:37,99,235;
  --warn:#a8690f;
  --hot:#c05f0a;
  --soft-red:#d4332a;
  --card-glass:#ffffff;
  --card-shadow:0 1px 2px rgba(0,0,0,0.04), 0 2px 8px rgba(0,0,0,0.05), 0 0 0 1px rgba(0,0,0,0.04);
  --glow-shadow:0 0 0 1px rgba(0,142,62,0.28), 0 6px 18px rgba(0,142,62,0.12);
  --glow-shadow-green:0 0 0 1px rgba(0,142,62,0.28), 0 6px 18px rgba(0,142,62,0.12);
  --green-gradient:linear-gradient(135deg,#008e3e 0%,#006323 100%);
  --glow-shadow-red:0 0 0 1px rgba(212,51,42,0.30), 0 4px 14px rgba(212,51,42,0.12);
  --titulo-grad:none;   /* en claro el título de la vista va plano, en --text */
  /* La cara profesional (tanda 1): los canales en su versión clara y la sombra suave que eleva la tarjeta sobre el fondo */
  --accent-rgb:0,142,62;   /* los tintes (rellenos, bordes, halos) siguen con el verde de siempre: solo el --accent macizo (texto y botón con texto encima) se oscureció en la tanda 8 */
  --red-rgb:231,0,11;
  --warn-rgb:168,105,15;
  --blue-rgb:37,99,235;
  --surface-shadow:0 1px 2px rgba(0,0,0,0.04), 0 4px 16px rgba(0,0,0,0.05);
  --modal-bg:rgba(18,26,21,0.32);
  --modal-shadow:0 24px 64px rgba(16,24,19,0.18);
  --bar-main:#6b7266;
  --bar-soft:#d5d9cf;
}

/* Alias de Brújula que necesitan su propio valor claro (los que apuntan a var(--x) siguen solos al token) */
html.light, body.light{
  --accent-line:rgba(0,142,62,0.35);
  --bub-in:#ffffff;
  --bub-out:#e2f6eb;   /* ♿ tanda 8: un punto más claro (era #d9f4e6) para que los botones azules del mensaje pasen 4,5:1 */
  --chat-bg:#eef1ec;
}

/* ── (4) Base compartida ── */
/* Un cuadro sin transiciones al cambiar de tema (lo pone AVSAL_UI.tema.aplicar() dos frames): si no, los colores se «arrastran». */
html.tema-cambiando *,html.tema-cambiando *::before,html.tema-cambiando *::after{transition:none!important}
/* 📱 Que se sienta app en el celular (4-oct): sin el recuadro gris que pintan iPhone y Android sobre lo que tocas (el botón
   ya se hunde al tocarlo) y sin la espera de doble toque en lo que se presiona. */
html{-webkit-tap-highlight-color:transparent}
button,a,[role=button],summary,label,.btn,.nav-item,.nav-sub,.nav-group-hdr{touch-action:manipulation}

/* ── (5) Componentes: cada uno vive UNA vez, acá. Los dos HTML borraron sus copias (scripts/cara-check.js falla si vuelven). ── */

/* Pastilla de estado: punto de color + texto. Tonos ok · warn · bad · info · ia · neutral · soon. El punto es el ::before
   (Brújula lo traía como <i></i> explícito: se esconde para no ver dos). */
.pill{display:inline-flex;align-items:center;gap:6px;height:20px;padding:0 9px;border-radius:99px;font-size:10.5px;font-weight:700;letter-spacing:.02em;white-space:nowrap;
  border:1px solid color-mix(in srgb,currentColor 28%,transparent);background:color-mix(in srgb,currentColor 10%,transparent);color:var(--text2)}
.pill::before{content:'';width:6px;height:6px;border-radius:50%;background:currentColor;flex:none}
.pill>i{display:none}
.pill.ok{color:var(--green-txt)} .pill.warn{color:var(--warn-txt)} .pill.bad{color:var(--red-txt)} .pill.info{color:var(--info)} .pill.ia{color:var(--ia)} .pill.neutral{color:var(--text3)}
.pill.soon{color:var(--text3);background:transparent;border-color:var(--border2)}
.pill.sin-punto::before,.pill.soon::before{display:none}
.pill.lg{height:24px;padding:0 12px;font-size:11.5px}
/* 🚦 El punto de la pastilla va en el tono del semáforo (el texto, en el suyo para leerse: tanda 8). */
.pill.ok::before{background:var(--green)} .pill.warn::before{background:var(--yellow)} .pill.bad::before{background:var(--red)}
.pill.mono{font-family:'Geist Mono',ui-monospace,monospace;font-variant-numeric:tabular-nums}
@media print{.pill{background:none!important;border-color:currentColor!important}}

/* Botones. Alias de Brújula: .btn.pri ≡ .btn-primary · .btn.ghost ≡ .btn-secondary · .btn.sm ≡ .btn-sm (.inv y .block siguen siendo suyos). */
/* Lienzo v2 (fase P, 2026-09-24): alto 34 (30 .btn-sm · 28 .btn-xs), radio 8, ícono de línea 15. En el celular el dashboard lo sube a 42. */
.btn{min-height:34px;padding:0 14px;border-radius:var(--radius-btn);font-size:13px;font-weight:700;cursor:pointer;border:1px solid transparent;transition:var(--transition);
  display:inline-flex;align-items:center;justify-content:center;gap:7px;outline:none;letter-spacing:0}
.btn:active{transform:scale(0.96)}
/* Un .btn sin variante era el botón blanco del navegador (19 en el dashboard, «Traer de la extensión»): ahora es el neutro. */
.btn:where(:not(.btn-primary,.pri,.btn-danger,.btn-secondary,.ghost,.inv,.btn-fantasma)){background:rgba(var(--ink-rgb),0.04);color:var(--text2);border-color:rgba(var(--ink-rgb),0.09)}
.btn:where(:not(.btn-primary,.pri,.btn-danger,.btn-secondary,.ghost,.inv,.btn-fantasma)):hover{background:rgba(var(--ink-rgb),0.07);border-color:rgba(var(--ink-rgb),0.15);color:var(--text)}
/* El primario: relleno verde plano, sin degradado ni resplandor (lienzo). Uno por vista. */
.btn-primary,.btn.pri{background:var(--accent);color:var(--accent-ink);border-color:var(--accent);box-shadow:none;font-weight:700;
  transition:filter .2s ease}
.btn-primary:hover,.btn.pri:hover{filter:brightness(1.06);box-shadow:none;transform:none}
/* Peligro: el rojo suave del tema, sin borde. */
.btn-danger{background:var(--red-dim);color:var(--red-txt);border:1px solid transparent}
.btn-danger:hover{background:rgba(var(--red-rgb),.16);border-color:transparent;box-shadow:none}
/* El secundario (lienzo kit.btn 'secondary'): fondo --bg2, borde --border2 y el texto en --text 600. Se ve también sobre --bg3
   (la caja de Atención); el gris translúcido de antes casi desaparecía ahí. */
.btn-secondary,.btn.ghost{background:var(--bg2);color:var(--text);border:1px solid var(--border2);font-weight:600}
.btn-secondary:hover,.btn.ghost:hover{background:var(--bg3);border-color:var(--border2);color:var(--text)}
.btn-sm,.btn.sm{min-height:30px;padding:0 12px;font-size:12.5px;border-radius:var(--radius-btn)}
.btn-xs{min-height:28px;padding:0 10px;font-size:12px;border-radius:7px;gap:5px}   /* el botón de una fila densa (tarjetas del Catálogo, del Scout, del Tracker) */
/* Un filtro o una opción que se prende y se apaga (chips del Scout, del Tracker, de Meta Profundo…): el secundario, y prendido con el tinte verde. */
.btn-secondary.on,.btn.ghost.on{background:var(--accent-dim);border-color:rgba(var(--accent-rgb),.4);color:var(--text)}
.btn:disabled{opacity:.45;cursor:not-allowed;transform:none;box-shadow:none}   /* apagado: se ve y no engaña */
.btn.loading{opacity:.55;pointer-events:none}                                  /* mientras trabaja (el Radar le pone .loading) */
/* El ícono de línea dentro de un botón, el fantasma (acción de fila: «Deshacer», «Ver detalle»), el solo-ícono y el contador. */
.btn svg{width:15px;height:15px;stroke:currentColor;stroke-width:1.8;fill:none;stroke-linecap:round;stroke-linejoin:round;flex:none}
.btn-fantasma{background:transparent;border-color:transparent;color:var(--text2);font-weight:600}
.btn-fantasma:hover{background:rgba(var(--ink-rgb),.05);color:var(--text)}
.btn-fantasma.peligro{color:var(--red-txt)} .btn-fantasma.peligro:hover{background:var(--red-dim);color:var(--red-txt)}
.btn-ico{width:34px;padding:0;justify-content:center} .btn-ico.btn-sm,.btn-ico.sm{width:30px} .btn-ico.btn-xs{width:28px}
.btn .c{font:500 11px/1 'Geist Mono',ui-monospace,monospace;color:var(--text3);margin-left:2px}
/* El link «Ver detalle →» (se mudó de brujula.html: las dos apps lo usan). Sirve en un <a> o en un <button> sin borde ni fondo. */
.lnk{color:var(--accent);font-weight:600;font-size:12.5px;text-decoration:none;display:inline-flex;align-items:center;gap:4px;
  background:none;border:0;padding:0;cursor:pointer;font-family:inherit}
.lnk:hover{text-decoration:underline;text-underline-offset:3px}
.lnk.peligro{color:var(--red-txt);font-size:12px}
.sec-r .lnk{white-space:nowrap}   /* el link de la cabecera de sección no se parte; en el cuerpo sí puede */

/* Vacío que explica: qué falta, qué hacer y el botón. Nunca un recuadro en blanco. Alias de Brújula: .ic (ícono en caja), b, p. */
.vacio{border:1px dashed var(--border2);border-radius:var(--radius);padding:28px 16px;display:flex;flex-direction:column;align-items:center;text-align:center;gap:8px;background:transparent;color:var(--text2)}
.vacio-ic{font-size:18px;line-height:1;opacity:.85}
.vacio .ic{width:44px;height:44px;border-radius:12px;display:grid;place-items:center;background:var(--bg3);color:var(--text2)}
.vacio-t,.vacio>b{font-size:15px;font-weight:700;color:var(--text);text-wrap:balance;margin-top:6px}
.vacio-x,.vacio>p{font-size:13px;color:var(--text3);line-height:1.55;max-width:64ch;margin:0 auto}
.vacio .btn{margin-top:8px}
.vacio.compacto{padding:14px 16px;gap:5px}
.vacio.compacto .vacio-t{font-size:13px}

/* UN globo para todos los gráficos: fecha arriba, cuadrito de color, nombre y valor alineado (chartTipShow / _ctAttr). */
#chart-tip{position:fixed;z-index:99999;pointer-events:none;min-width:150px;max-width:280px;background:var(--bg2);border:1px solid var(--border2);border-radius:10px;
  box-shadow:0 12px 30px rgba(0,0,0,.45);padding:9px 11px;font-size:12px;color:var(--text2);opacity:0;transform:translateY(3px);transition:opacity .1s ease,transform .1s ease}
#chart-tip.on{opacity:1;transform:none}
html.light #chart-tip,body.light #chart-tip{box-shadow:0 12px 30px rgba(0,0,0,.14)}
.ct-t{font-size:11px;font-weight:700;color:var(--text);margin-bottom:6px}
.ct-r{display:flex;align-items:center;gap:8px;padding:2px 0}
.ct-r i{width:9px;height:9px;border-radius:2px;flex:none}
.ct-r span{flex:1;min-width:0;color:var(--text3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ct-r b{font-family:'Geist Mono',ui-monospace,monospace;font-weight:500;color:var(--text);font-variant-numeric:tabular-nums;white-space:nowrap}
.ct-n{margin-top:6px;padding-top:6px;border-top:1px solid var(--border);font-size:11px;color:var(--text3);line-height:1.45;white-space:normal}
.ct-r.tenue b{color:var(--text3)}
.ct-barra{display:flex;height:6px;border-radius:3px;overflow:hidden;background:var(--red);margin:0 0 7px}
.ct-barra i{background:var(--green)}
.ct-tot{margin-top:5px;padding-top:6px;border-top:1px solid var(--border)}
.ct-tot span{color:var(--text);font-weight:700}
.ct-tot b{font-size:13.5px;font-weight:700}
@media (prefers-reduced-motion:reduce){#chart-tip{transition:none}}

/* El «?» que explica un campo una vez (mouse, clic y teclado). El globo se ancla a la FILA (.q-anchor o .ci-lbl), nunca al iconito. */
.q-anchor{position:relative}
.ci-q{display:inline-flex;align-items:center;justify-content:center;width:15px;height:15px;margin-left:1px;border-radius:50%;border:1px solid var(--border2);background:var(--bg3);color:var(--text3);
  font-size:9.5px;font-weight:800;line-height:1;letter-spacing:0;cursor:help;flex:0 0 auto;user-select:none;transition:var(--transition)}
.ci-q:hover,.ci-q.on{border-color:var(--accent);color:var(--accent)}
.ci-q:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
.ci-q-pop{display:none;position:absolute;left:0;right:0;top:calc(100% + 6px);z-index:60;background:var(--bg2);border:1px solid var(--border2);border-radius:9px;box-shadow:0 10px 28px rgba(0,0,0,.5);
  padding:9px 11px;font-size:11px;font-weight:500;line-height:1.5;letter-spacing:0;text-transform:none;color:var(--text2);cursor:auto}
.ci-q:hover .ci-q-pop,.ci-q:focus .ci-q-pop,.ci-q.on .ci-q-pop{display:block}
.ci-q-pop b{color:var(--text);font-weight:700}

/* «Actualizado hace X min»: <span class="fresco" data-fresco="<ts>" data-fresco-pre="Meta · " data-fresco-post=".">. AVSAL_UI.fresco() lo repinta
   cada 30 s y pasada una hora lo pone en ámbar; AVSAL_UI.frescoHTML(ts, { pre, post, clase }) arma el markup ya pintado. .en-linea va DENTRO de una
   frase (hereda letra, color y salto), .viejo manda igual sobre las dos. */
.fresco{font-size:11px;color:var(--text3);white-space:nowrap;font-variant-numeric:tabular-nums}
.fresco.en-linea{font-size:inherit;color:inherit;white-space:inherit}
.fresco.viejo{color:var(--warn-txt)}

/* Segmento de tema: Oscuro · Claro · Sistema (AVSAL_UI.tema.pintar() marca el elegido). */
.tm-seg{margin-left:auto;display:inline-flex;gap:2px;padding:2px;border-radius:8px;background:var(--bg3);border:1px solid var(--border)}
.tm-seg button{background:none;border:0;border-radius:6px;padding:3px 7px;font:inherit;font-size:11px;font-weight:600;color:var(--text3);cursor:pointer;height:auto;width:auto}
.tm-seg button:hover{color:var(--text)}
.tm-seg button.on{background:var(--bg2);color:var(--text);box-shadow:0 1px 2px rgba(0,0,0,.2)}
.tm-seg button:focus-visible{outline:2px solid var(--accent);outline-offset:1px}

/* Lockup de la marca (menú lateral): el logotipo ΛVSΛL (<use href="#avsal-wm">) y, si la app lo lleva, su nombre en mono chiquito. */
.logo-word{display:flex;align-items:center;gap:7px;min-width:0;white-space:nowrap}
.logo-wm{height:14px;width:auto;display:block;color:var(--text);flex:none}
.logo-word span{font-family:'Geist Mono',ui-monospace,monospace;font-size:8.5px;font-weight:500;letter-spacing:.32em;color:var(--text3)}

/* Pantalla de entrada (la misma en las dos apps; la lógica de la sesión es de cada una). Con tokens, así existe en claro. */
#lock-overlay{position:fixed;inset:0;z-index:99999;display:flex;align-items:center;justify-content:center;background:var(--bg);overflow:hidden}
#lock-overlay.hidden{display:none}
.lock-card{display:flex;width:min(1000px,96vw);height:min(580px,94vh);background:var(--bg2);border:1px solid var(--border);border-radius:24px;overflow:hidden;
  box-shadow:0 60px 160px rgba(0,0,0,.9),0 0 0 1px rgba(var(--ink-rgb),.04);position:relative}
html.light .lock-card,body.light .lock-card{box-shadow:0 30px 80px rgba(0,0,0,.16),0 0 0 1px rgba(0,0,0,.04)}
.lock-left{flex:0 0 42%;padding:56px 52px;display:flex;flex-direction:column;justify-content:safe center;overflow-y:auto;position:relative;z-index:2}   /* safe center: si no cabe (pantalla baja), arranca arriba y se desplaza en vez de recortarse */
.lock-right{flex:1;position:relative;overflow:hidden;background:var(--bg);display:flex;align-items:center;justify-content:center}
@keyframes spotlight-in{0%{opacity:0;transform:translate(-50%,-60%) scale(.6)}100%{opacity:1;transform:translate(-50%,-50%) scale(1)}}
.lock-spotlight-svg{position:absolute;top:0;left:0;width:100%;height:100%;pointer-events:none;z-index:0;animation:spotlight-in 1.8s ease forwards}
.lock-cursor-glow{position:fixed;width:240px;height:240px;border-radius:50%;background:radial-gradient(circle,rgba(20,202,128,.08) 0%,transparent 70%);pointer-events:none;z-index:99998;transform:translate(-50%,-50%);transition:opacity .2s;opacity:0}
.lock-logo-mark{width:44px;height:44px;border-radius:12px;background:var(--bosque);display:flex;align-items:center;justify-content:center;margin-bottom:28px;box-shadow:0 4px 20px rgba(20,202,128,.3);--mk1:#14CA80;--mk2:#BFF3DA;--mkn:#0A3D2B}
.lock-logo-mark svg{width:30px;height:30px;display:block}
.lock-title{font-size:clamp(28px,3.5vw,42px);font-weight:700;letter-spacing:-.03em;line-height:1.1;color:var(--text);margin-bottom:8px}
.lock-brand{display:flex;flex-direction:column;gap:12px}
.lock-wm{width:min(290px,70vw);height:auto;display:block;color:var(--text)}
.lock-brand span{font-family:'Geist Mono',ui-monospace,monospace;font-size:13px;font-weight:500;letter-spacing:.44em;color:var(--text3)}
.lock-sub{font-size:12px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:rgba(var(--ink-rgb),.3);margin-bottom:36px}
.lock-input-wrap{position:relative;margin-bottom:14px}
.lock-input{width:100%;background:rgba(var(--ink-rgb),.05);border:1px solid rgba(var(--ink-rgb),.1);border-radius:12px;padding:14px 48px 14px 18px;font-size:16px;font-weight:700;color:var(--text);
  font-family:inherit;outline:none;box-sizing:border-box;transition:border-color .2s,box-shadow .2s;letter-spacing:.1em}
.lock-input:focus{border-color:rgba(20,202,128,.5);box-shadow:0 0 0 3px rgba(20,202,128,.08)}
.lock-input.error{border-color:rgba(244,63,94,.6);animation:lock-shake .3s ease}
#lock-email{letter-spacing:0;font-weight:600}
@keyframes lock-shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-6px)}75%{transform:translateX(6px)}}
.lock-eye{position:absolute;right:14px;top:50%;transform:translateY(-50%);cursor:pointer;color:rgba(var(--ink-rgb),.3);background:none;border:none;padding:4px;line-height:0;transition:color .2s}
.lock-eye:hover{color:rgba(var(--ink-rgb),.7)}
.lock-btn{width:100%;background:var(--accent-gradient);color:var(--accent-ink);font-weight:700;font-size:14px;border:none;border-radius:12px;padding:15px;cursor:pointer;letter-spacing:.04em;transition:opacity .2s,transform .1s;margin-bottom:16px}
.lock-btn:hover{opacity:.9}
.lock-btn:active{transform:scale(.98)}
.lock-btn:disabled{opacity:.6;cursor:wait}
.lock-error{font-size:12px;color:var(--red-txt);text-align:center;min-height:16px;font-weight:600;line-height:1.45}
.lock-error.ok{color:var(--accent)}
.lock-hint{font-size:10px;color:rgba(var(--ink-rgb),.15);text-align:center;letter-spacing:.06em;text-transform:uppercase;margin-top:24px}
.lock-links{display:flex;justify-content:center;align-items:center;gap:10px;margin-top:4px;font-size:13px;color:rgba(var(--ink-rgb),.25);flex-wrap:wrap}
.lock-lnk{background:none;border:none;padding:0;cursor:pointer;font:inherit;font-size:13px;font-weight:600;color:rgba(var(--ink-rgb),.55);text-decoration:underline dotted;text-underline-offset:3px}
.lock-lnk:hover{color:var(--accent)}
.lock-lnk:disabled{opacity:.5;cursor:default}
/* 🔑 M-40 (tanda 8 de AVSAL Chat, 22-oct): los enlaces de la entrada a 13 px (antes 12 · 11 medidos) en las dos apps, y en AVSAL Chat una línea para quien entra invitado. */
.lock-invitado{margin:-26px 0 26px;font-size:13px;line-height:1.45;color:rgba(var(--ink-rgb),.55)}   /* bajo «Entra con tu cuenta», a la vista sin desplazar */
.lock-o{display:flex;align-items:center;gap:10px;margin:14px 0 2px;font-size:11px;color:rgba(var(--ink-rgb),.35)}
.lock-o::before,.lock-o::after{content:'';flex:1;height:1px;background:rgba(var(--ink-rgb),.14)}
.lock-google{display:flex;align-items:center;justify-content:center;gap:10px;width:100%;padding:11px 14px;border-radius:10px;border:1px solid rgba(var(--ink-rgb),.18);background:rgba(var(--ink-rgb),.06);
  color:var(--text);font:inherit;font-size:14px;font-weight:600;cursor:pointer;transition:background .15s,border-color .15s}
.lock-google:hover{background:rgba(var(--ink-rgb),.11);border-color:rgba(var(--ink-rgb),.3)}
.lock-google:disabled{opacity:.5;cursor:default}
.lock-google svg{width:18px;height:18px;flex:none}
@media (max-width:768px){
  .lock-card{flex-direction:column;width:100vw;height:100dvh;border-radius:0;border:none}
  .lock-right{width:100%!important;height:38vh!important;flex-shrink:0;order:-1}
  .lock-left{flex:1;padding:28px 28px calc(36px + env(safe-area-inset-bottom,0px));justify-content:flex-start;overflow-y:auto}
  .lock-logo-mark{width:36px;height:36px;margin-bottom:16px}
  .lock-title{font-size:clamp(24px,6.5vw,34px);margin-bottom:4px;word-break:break-word}
  .lock-sub{margin-bottom:24px;font-size:11px}
  .lock-invitado{margin:-14px 0 20px}   /* el mismo aire de 10 px bajo «Entra con tu cuenta» que en el computador (con -26 quedaba a 2 px a 390) */
  .lock-btn{padding:14px}
  .lock-spotlight-svg{display:none}
}

/* ══════════════════════════════════════════════════════════════════════════════════════════════════════════
   (6) ESQUELETO — la barra lateral (fase 5, tanda 4a, 2026-09-17)
   Los nombres son los del DASHBOARD, la casa madre; Brújula los adoptó para que las dos barras sean la misma.
   Acá vive la PIEZA (fondo, borde, relleno, cómo se apila por dentro). La COLOCACIÓN se queda en cada HTML —el
   dashboard la fija a la izquierda con .app/.main, Brújula es una columna de su grid—: unificarla rompe el scroll
   de una de las dos. Vocabulario del menú, y nada más: sección · ítem · ítem-grupo · sub-ítem.
   ══════════════════════════════════════════════════════════════════════════════════════════════════════════ */
.sidebar{background:var(--bg2);border-right:1px solid var(--border);display:flex;flex-direction:column;min-width:0;min-height:0}
html.light .sidebar,body.light .sidebar{box-shadow:4px 0 32px rgba(0,0,0,0.09), 1px 0 0 rgba(0,0,0,0.05)}
/* La barra se desliza, pero sin la barrita de scroll a la derecha */
.sidebar,.sidebar-nav{scrollbar-width:none}
.sidebar::-webkit-scrollbar,.sidebar-nav::-webkit-scrollbar{display:none}
/* Bloque del logo: 60 px de alto (los mismos de la barra de arriba), marca + lockup ΛVSΛL y un hilo verde abajo. */
.sidebar-logo{height:60px;flex:none;display:flex;align-items:center;gap:11px;padding:0 18px;position:relative;border-bottom:1px solid var(--border)}
.logo-mark{width:28px;height:28px;flex:none;display:block}
.ir-inicio{cursor:pointer}   /* 🏠 el logo de la barra lleva al inicio en las dos apps (3-oct) */
.sidebar-nav{flex:1;min-height:0;padding:0 10px 12px;display:flex;flex-direction:column;gap:1px;overflow-y:auto;overflow-x:hidden}
.sidebar-footer{flex:none;padding:12px;border-top:1px solid var(--border)}
/* Contraer o expandir la barra: dentro de la fila del logo, a la derecha (lienzo). En el riel sigue colgando del borde (apartado 10). */
.sb-rail-btn{position:static;margin-left:auto;z-index:3;width:28px;height:28px;flex:none;border-radius:7px;border:1px solid var(--border);
  background:transparent;color:var(--text3);display:flex;align-items:center;justify-content:center;cursor:pointer;
  box-shadow:none;transition:color .15s,border-color .15s}
.sb-rail-btn:hover{color:var(--text);border-color:var(--accent)}
.sb-rail-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.sb-rail-btn svg{width:15px;height:15px;stroke:currentColor;stroke-width:1.8;fill:none;stroke-linecap:round;stroke-linejoin:round;transition:transform .2s}
html.light :is(.app.sb-collapsed,.app.rail) .sb-rail-btn,body.light :is(.app.sb-collapsed,.app.rail) .sb-rail-btn{box-shadow:0 2px 8px rgba(0,0,0,.08)}
/* Volver a mostrar la barra cuando está escondida del todo (solo el dashboard la esconde así). */
.sb-show-btn{position:fixed;top:20px;left:12px;z-index:200;display:none;width:32px;height:32px;border-radius:10px;
  background:var(--bg2);border:1px solid var(--border2);cursor:pointer;color:var(--text2);align-items:center;justify-content:center;
  box-shadow:0 2px 12px rgba(0,0,0,0.4);transition:var(--transition)}
.sb-show-btn:hover{color:var(--text);border-color:var(--accent)}

/* ── (7) El menú: sección · ítem · ítem-grupo · sub-ítem ── */
/* Sección: agrupa destinos que no tienen nada que ver entre sí. Como <button class="nav-section-label" data-grp> se pliega. */
.nav-section-label{flex:none;font-size:9px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--text3);padding:14px 14px 5px;margin-top:2px}
button.nav-section-label{display:flex;align-items:center;gap:6px;width:100%;background:none;border:0;font-family:inherit;line-height:inherit;text-align:left;cursor:pointer}
button.nav-section-label:hover{color:var(--text2)}
.nav-section-arr{margin-left:auto;flex:none;width:10px;height:10px;stroke:currentColor;stroke-width:2.5;fill:none;stroke-linecap:round;stroke-linejoin:round;
  transition:transform var(--dur) var(--ease)}
.nav-section-label.closed .nav-section-arr{transform:rotate(-90deg)}
.nav-section-label.closed + .nav-section-body{display:none}
.nav-section-body{display:flex;flex-direction:column;flex:none;gap:1px}
/* 🔑 Fase 4, tanda 2: lo que el rol de quien entró no ve (el servidor lo garantiza; esto solo lo esconde) */
.rol-oculto{display:none!important}
/* 🌎 «Todas las tiendas» solo tiene sentido con 2 o más tiendas (lo alterna _navTodasTiendas; aparte de rol-oculto, que es del rol) */
.una-sola{display:none!important}
/* Ítem: un destino. El alto (37,5 px) sale del RELLENO, nunca de un alto fijo, y flex:none impide que se aplaste
   cuando la lista no cabe (medido en Brújula: 34 px a 1400 de alto, 26 a 900 y 20 a 860). */
.nav-item{display:flex;align-items:center;gap:11px;flex:none;padding:9px 12px;border-radius:8px;cursor:pointer;font-size:13px;font-weight:500;
  color:var(--text2);text-decoration:none;white-space:nowrap;position:relative;
  transition:background .15s var(--ease-out),color .15s var(--ease-out)}
.nav-item:hover{background:rgba(var(--ink-rgb),0.05);color:var(--text)}
.nav-item.active{background:var(--accent-dim);color:var(--accent);font-weight:600;box-shadow:none}
.nav-item.active::before{content:'';display:block;position:absolute;left:-10px;top:7px;bottom:7px;width:2px;border-radius:0 2px 2px 0;background:var(--accent)}
html.light .nav-item,body.light .nav-item{color:var(--text3)}
.nav-icon{display:flex;align-items:center;justify-content:center;width:17px;height:17px;flex-shrink:0}
.nav-icon svg{width:17px;height:17px;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round;fill:none;transition:var(--transition)}
.nav-item.active .nav-icon svg{stroke:var(--accent)}
/* Ítem-grupo: UN destino que se abre en varios. Los hijos van con la guía vertical. */
.nav-group-hdr{display:flex;align-items:center;gap:11px;flex:none;padding:9px 12px;border-radius:8px;cursor:pointer;color:var(--text2);font-size:13px;
  font-weight:500;white-space:nowrap;user-select:none;transition:background .15s var(--ease-out),color .15s var(--ease-out)}
.nav-group-hdr:hover{background:rgba(var(--ink-rgb),0.05);color:var(--text)}
.nav-group-hdr.open{color:var(--text)}
.nav-group-arr{margin-left:auto;flex:none;width:14px;height:14px;stroke:currentColor;stroke-width:2.5;fill:none;stroke-linecap:round;stroke-linejoin:round;
  color:var(--text3);transform:rotate(-90deg);transition:transform var(--dur) var(--ease)}
.nav-group-hdr.open .nav-group-arr{transform:none}
.nav-group-items{position:relative;flex:none;overflow:hidden;transition:max-height .26s var(--ease-out)}
.nav-group-items::before{content:'';position:absolute;left:20px;top:6px;bottom:6px;width:1px;background:var(--border)}
/* Sub-ítem: un destino dentro de un ítem-grupo. */
.nav-sub{display:flex;align-items:center;gap:9px;flex:none;padding:7px 10px 7px 34px;border-radius:8px;cursor:pointer;font-size:13px;color:var(--text3);
  text-decoration:none;white-space:nowrap;position:relative;transition:background .15s var(--ease-out),color .15s var(--ease-out)}
.nav-sub:hover{background:var(--bg3);color:var(--text2)}
.nav-sub.active{background:var(--accent-dim);color:var(--accent);font-weight:700}
.nav-sub-dot{width:5px;height:5px;border-radius:50%;background:currentColor;flex-shrink:0;opacity:.6}
.nav-sub.active .nav-sub-dot{opacity:1}
.nav-sub-ic{display:flex;width:15px;height:15px;flex-shrink:0;opacity:.8}
.nav-sub-ic svg{width:15px;height:15px;stroke:currentColor;stroke-width:1.7;fill:none;stroke-linecap:round;stroke-linejoin:round}
.nav-sub.active .nav-sub-ic,.nav-sub:hover .nav-sub-ic{opacity:1}
/* La app hermana (Brújula ↗ en el dashboard, Dashboard ↗ en Brújula): tarjeta con borde, ARRIBA del nav.
   ⛔ Jamás .nav-item: activateSub('resumen', document.querySelector('.nav-item')) toma el PRIMER ítem del documento. */
.nav-app{display:flex;align-items:center;gap:11px;flex:none;padding:9px 12px;margin:0 2px 8px;border-radius:8px;font-size:13px;font-weight:600;
  color:var(--text);text-decoration:none;white-space:nowrap;border:1px solid var(--border2);background:var(--bg2);
  transition:background .15s var(--ease-out),border-color .15s var(--ease-out)}
.nav-app:hover{border-color:var(--accent);background:var(--accent-dim)}
.nav-app .nav-icon svg{width:18px;height:18px}
.nav-app .nav-app-ext{margin-left:auto;display:inline-flex;opacity:.55}
.nav-app .nav-app-ext svg{width:12px;height:12px;stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round}
/* 📱 En el celular las dos apps comparten la ventana (AVSAL_UI.irA): la flecha de «se abre en otra pestaña» no dice la verdad. */
@media (hover:none) and (pointer:coarse){.nav-app .nav-app-ext{display:none}}
/* Etiquetas del ítem: UNA clase con cinco tonos (antes iban en línea, una a una, en el markup).
   ia = azul de --info · acc = verde · neutral = gris · num = contador relleno (el único en mono: es un número) · soon = «pronto». */
.nav-badge{margin-left:auto;flex:none;display:inline-flex;align-items:center;justify-content:center;gap:4px;padding:1px 6px;border-radius:10px;
  font-size:9px;font-weight:800;letter-spacing:.06em;line-height:1.7;text-transform:uppercase;white-space:nowrap;border:1px solid transparent}
.nav-badge + .nav-badge{margin-left:4px}
.nav-badge.ia{color:var(--ia);background:var(--ia-dim);border-color:rgba(var(--ia-rgb),.2)}
.nav-badge.acc{color:var(--accent);background:var(--accent-dim);border-color:color-mix(in srgb,var(--accent) 30%,transparent)}
.nav-badge.neutral{color:var(--text3);background:var(--bg3)}
.nav-badge.num{min-width:18px;height:18px;padding:0 5px;border-radius:9px;background:var(--accent);color:var(--accent-ink);border-color:transparent;
  font-family:'Geist Mono',ui-monospace,monospace;font-size:10.5px;font-weight:600;letter-spacing:0;line-height:1;font-variant-numeric:tabular-nums}
.nav-badge.num.rojo{background:var(--red);color:#fff}
.nav-badge.num.ambar{background:var(--warn-txt);color:var(--accent-ink)}
.nav-badge.soon{color:var(--text3);background:transparent;   /* ♿ tanda 8 (22-oct): «después» / «pronto» en --text3 (con --text4 medía 2,4:1) */
border-color:var(--border2);border-radius:5px;padding:3px 5px;line-height:1}
.nav-badge .pt{width:5px;height:5px;border-radius:50%;background:currentColor;flex:none;animation:nav-badge-pulso 1.2s ease-in-out infinite}
@keyframes nav-badge-pulso{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.5;transform:scale(1.4)}}
@media (prefers-reduced-motion:reduce){.nav-badge .pt{animation:none}}

/* ── (8) La tienda y la cuenta ── */
/* Selector de tienda, bajo el logo. Misma pieza en las dos apps; la acción no es la misma (el dashboard cambia la
   tienda contable, Brújula filtra chats y pedidos) y por eso el subtítulo lo dice. */
.store-pill{display:flex;align-items:center;gap:10px;margin:12px 12px 10px;padding:10px 12px;background:var(--bg3);border:1px solid var(--border2);
  border-radius:10px;cursor:pointer;text-align:left;width:calc(100% - 24px);transition:var(--transition)}
.store-pill:hover{border-color:var(--accent);background:var(--bg4)}
.store-pill-flag{font-size:20px;line-height:1;flex-shrink:0}
.store-pill-info{flex:1;min-width:0;display:block;text-align:left}
.store-pill-name{display:block;font-size:12px;font-weight:800;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.store-pill-sub{display:block;font-size:10.5px;color:var(--text2);font-weight:500;letter-spacing:0;margin-top:1px}
.store-pill-arr{color:var(--text3);flex-shrink:0;width:13px;height:13px;stroke:currentColor;stroke-width:2.5;fill:none;stroke-linecap:round;stroke-linejoin:round}
/* Buscador visible: el ⌘K de 39 destinos existía y un usuario no técnico jamás lo descubría. */
.sb-search{display:flex;align-items:center;gap:8px;margin:0 12px 12px;padding:8px 12px;background:var(--bg);border:1px solid var(--border);
  border-radius:8px;cursor:pointer;color:var(--text3);font-size:12.5px;transition:border-color var(--dur) var(--ease),color var(--dur) var(--ease)}
.sb-search:hover{border-color:var(--border2);color:var(--text2)}
.sb-search .kbd{font-family:'Geist Mono',ui-monospace,monospace;font-size:10px;background:none;border:0;padding:0;color:var(--text3)}
/* En el riel, un ítem-grupo se abre como menú flotante a la derecha. */
.rail-fly{position:fixed;z-index:950;min-width:220px;background:var(--bg2);border:1px solid var(--border2);border-radius:12px;
  box-shadow:0 14px 34px rgba(0,0,0,.4);padding:6px;display:none}
.rail-fly.open{display:block}
html.light .rail-fly,body.light .rail-fly{box-shadow:0 14px 34px rgba(0,0,0,.14)}
.rail-fly-t{font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.08em;color:var(--text3);padding:6px 10px 4px}
.rail-fly-i{display:flex;align-items:center;gap:9px;width:100%;background:none;border:0;border-radius:8px;padding:8px 10px;font:inherit;font-size:13px;
  color:var(--text2);cursor:pointer;text-align:left}
.rail-fly-i:hover,.rail-fly-i:focus-visible{background:var(--bg3);color:var(--text);outline:none}
.rail-fly-i.on{background:var(--accent-dim);color:var(--accent);font-weight:600}
.rail-fly-i .nav-sub-ic{opacity:1}
/* La cuenta: arriba a la derecha en las dos apps (con el tema adentro y «Cerrar sesión» abajo). */
.top-menu-wrap{position:relative;display:inline-flex}
.top-avatar{width:30px;height:30px;border-radius:50%;border:1px solid var(--border2);background:var(--bg4);color:var(--text);font:inherit;
  font-size:12px;font-weight:700;letter-spacing:.02em;cursor:pointer;display:flex;align-items:center;justify-content:center;
  box-shadow:none;--mk1:#14CA80;--mk2:#BFF3DA;--mkn:#0A3D2B}
.top-avatar:hover{filter:brightness(1.06)}
.top-avatar:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.top-avatar svg{width:20px;height:20px;display:block}
.top-avatar.con-foto{background:var(--bg3);overflow:hidden;padding:0}
.top-avatar img{width:100%;height:100%;border-radius:50%;object-fit:cover;display:block}
.top-menu{display:none;position:absolute;top:calc(100% + 8px);right:0;z-index:960;width:278px;background:var(--bg2);border:1px solid var(--border2);
  border-radius:14px;box-shadow:0 18px 44px rgba(0,0,0,.45);padding:6px}
.top-menu.open{display:block}
html.light .top-menu,body.light .top-menu{box-shadow:0 18px 44px rgba(0,0,0,.14)}
.tm-hd{padding:8px 10px 10px;border-bottom:1px solid var(--border);margin-bottom:4px}
.tm-hd b{display:block;font-size:13px;color:var(--text)}
.tm-hd span{font-size:11px;color:var(--text3)}
.tm-item{display:flex;align-items:center;gap:10px;width:100%;background:none;border:0;border-radius:9px;padding:8px 10px;font:inherit;
  font-size:12.5px;font-weight:500;color:var(--text2);cursor:pointer;text-align:left}
.tm-item:hover,.tm-item:focus-visible{background:var(--bg3);color:var(--text);outline:none}
.tm-item svg{width:15px;height:15px;flex-shrink:0;stroke:currentColor;stroke-width:1.8;fill:none;stroke-linecap:round;stroke-linejoin:round}
.tm-item kbd{margin-left:auto;font-family:'Geist Mono',ui-monospace,monospace;font-size:10px;color:var(--text3);border:1px solid var(--border2);border-radius:5px;padding:0 5px}
.tm-item.tm-tema{cursor:default}
.tm-item.tm-tema:hover{background:none}
.tm-sw{margin-left:auto;width:30px;height:17px;border-radius:99px;background:var(--border2);position:relative;flex:none;transition:background .15s}
.tm-sw::after{content:'';position:absolute;top:2px;left:2px;width:13px;height:13px;border-radius:50%;background:var(--text2);transition:transform .15s,background .15s}
html.light .tm-sw,body.light .tm-sw{background:var(--accent)}
html.light .tm-sw::after,body.light .tm-sw::after{transform:translateX(13px);background:#fff}
.tm-sep{height:1px;background:var(--border);margin:4px 6px}
.tm-rojo,.tm-rojo:hover{color:var(--red-txt)}
/* La barra de arriba NO es una barra: una ISLA flotante arriba a la derecha, sin fondo ni borde.
   Lleva las conexiones, un dato vivo y la cuenta; el título de la vista vive en el contenido (apartado 9). */
.topbar-actions{position:fixed;top:14px;right:calc(20px + env(safe-area-inset-right,0px));z-index:300;display:flex;align-items:center;gap:8px}
/* Lo que se mueve no pasa por debajo de la isla: cada app le pone detrás su FRANJA de arriba, a todo el ancho del contenido y del
   color de la página (colocación, en cada HTML: una franja fija en el dashboard, el contenido que se desplaza empieza debajo de
   ella en Brújula). La isla sigue sin fondo ni borde propios (golden «la isla… sin fondo ni borde»). */
/* Una pastilla de 30 px (la frescura del dashboard, el consumo de Brújula): ícono de línea 14 y el texto en 12. */
.topbar-btn{display:flex;align-items:center;gap:7px;height:30px;background:var(--bg2);border:1px solid var(--border);border-radius:var(--radius-pill);padding:0 12px;
  font-size:12px;font-weight:500;color:var(--text2);cursor:pointer;box-shadow:none;white-space:nowrap;
  transition:transform .2s ease,background .2s ease,color .2s ease,border-color .2s ease}
.topbar-btn:hover{background:var(--bg3);color:var(--text);border-color:var(--border2)}
html.light .topbar-btn,body.light .topbar-btn{box-shadow:0 2px 8px rgba(0,0,0,0.08)}   /* en claro la sombra es suave, no un borde negro */
.topbar-btn svg{flex-shrink:0;width:14px;height:14px;color:var(--text3);stroke:currentColor}
.topbar-btn.viejo,.topbar-btn.viejo svg{color:var(--warn-txt)}
.topbar-btn .kbd{font-size:9px;font-weight:700;padding:1px 5px;border-radius:4px;background:rgba(var(--ink-rgb),0.06);
  border:1px solid rgba(var(--ink-rgb),0.1);color:var(--text3);letter-spacing:.06em}
/* 🔌 Conexiones: un punto de 8 px; con texto y en rojo si algo no responde. El globo dice cuál y qué hacer. */
.salud-wrap{position:relative;display:inline-flex}
.salud-chip{display:inline-flex;align-items:center;justify-content:center;gap:7px;height:30px;min-width:30px;padding:0 9px;border-radius:20px;
  border:1px solid var(--border);background:var(--bg2);color:var(--text2);font:inherit;font-size:10.5px;font-weight:700;cursor:pointer;white-space:nowrap}
.salud-chip i{width:8px;height:8px;border-radius:50%;background:var(--accent);box-shadow:none;flex:none}   /* el halo, solo cuando avisa (.mal · .medio) */
.salud-chip.nd i{background:var(--text3);box-shadow:none}
.salud-chip.mal{color:var(--red-txt);border-color:var(--red);background:var(--red-dim)}
.salud-chip.mal i{background:var(--red);box-shadow:0 0 0 3px var(--red-dim)}
.salud-chip.medio{color:var(--warn-txt);border-color:var(--warn);background:var(--yellow-dim)}   /* a medias: ni bien ni roto */
.salud-chip.medio i{background:var(--warn);box-shadow:0 0 0 3px var(--yellow-dim)}
.salud-chip:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.salud-pop{display:none;position:absolute;top:calc(100% + 8px);right:0;z-index:950;width:min(310px,calc(100vw - 32px));background:var(--bg2);
  border:1px solid var(--border2);border-radius:12px;box-shadow:0 18px 40px rgba(0,0,0,.45);padding:12px 14px;text-align:left}
.salud-pop.open{display:block}
html.light .salud-pop,body.light .salud-pop{box-shadow:0 18px 40px rgba(0,0,0,.14)}
.salud-row{display:flex;gap:10px;align-items:flex-start;padding:8px 0;border-top:1px solid var(--border)}
.salud-row i{width:8px;height:8px;border-radius:50%;margin-top:5px;flex:none}
.salud-row b{display:block;font-size:12px;color:var(--text);font-weight:600}
.salud-row span{display:block;font-size:11.5px;color:var(--text2);line-height:1.45;white-space:normal}

/* ── (9) La cabecera de la página y la escala de letra ──
   La regla de familias que ordena las dos apps: **Geist Mono SOLO para números** (cifras, contadores, códigos)
   y **Geist 800 MAYÚSCULA para rótulos**, en tres tamaños — 9/.1em (sección del menú, apartado 7) ·
   10/.1em (.kpi-label y el th de .tabla) · 11/.06em (.card-title). Lo que cambia de tamaño entre las dos apps
   se dice en su sitio: el KPI (las tarjetas miden 661 px en el dashboard y 232 en Brújula). */
.page-header{margin-bottom:var(--s-4)}   /* sin raya debajo; el aire separa (16, el mismo que entre bloques: lienzo v2) */
.page-title{margin:0 0 5px;font-size:30px;font-weight:800;letter-spacing:-.03em;line-height:1.15;color:var(--text);
  background-image:var(--titulo-grad);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
/* En claro --titulo-grad es «none»: sin esta línea el título quedaría INVISIBLE (no feo). Un golden lo mide en los dos temas. */
html.light .page-title,body.light .page-title{-webkit-text-fill-color:var(--text)}
.page-sub{font-size:13px;color:var(--text3);font-weight:500;max-width:720px;line-height:19px}
.page-sub b{color:var(--text2)}
@media (max-width:640px){ .page-title{font-size:22px} }
/* Título de tarjeta + su subtítulo (el dashboard, sin cambios: golden). */
.card-title{margin:0;display:flex;align-items:center;gap:9px;font-size:11px;font-weight:700;
  text-transform:uppercase;letter-spacing:.06em;color:var(--text2)}
.card-title{margin-bottom:22px}
.card-sub{margin:2px 0 0;font-size:12.5px;font-weight:500;line-height:1.45;color:var(--text3);text-transform:none;letter-spacing:0}
/* La cabecera de tarjeta de Brújula (.card-h h3 + p) = la sección del lienzo: título 16/700 en caja normal y su línea en su
   renglón. Las 74 tarjetas de Brújula cambian sin tocar su markup (lienzo v2kit.section). */
.card-h h3{margin:0;display:flex;align-items:center;gap:9px;font-size:var(--fs-title);font-weight:700;letter-spacing:-.01em;
  line-height:22px;color:var(--text);text-transform:none}
.card-h h3 .sec-ic{margin:0}
.card-h p{margin:3px 0 0;font-size:12.5px;font-weight:500;line-height:18px;color:var(--text3);text-transform:none;letter-spacing:0}
.card-h p b{color:var(--text);font-weight:600}
.kpi-label{font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.1em;color:var(--text3);margin-bottom:12px}
/* El KPI: familia, peso y tabular iguales; el TAMAÑO es de cada app y se queda en su sitio. */
.kpi-value,.kpi .v{font-family:'Geist Mono',ui-monospace,monospace;font-weight:600;letter-spacing:-.02em;line-height:1.04;font-variant-numeric:tabular-nums}
.kpi-value{font-size:var(--fs-kpi)}   /* 26 px; el héroe (.kpi.hero) va en 40 y la compacta (.kpi.sm) en 18 */
/* Tabla con el th canónico. Es OPT-IN (clase .tabla): ⛔ la regla global table/th/td del dashboard NO se toca
   (el thead pegajoso del Catálogo y la impresión cuelgan de ella). */
.tabla{width:100%;border-collapse:collapse;font-size:13px}
.tabla th{font-family:'Geist',ui-sans-serif,system-ui,-apple-system,sans-serif;font-size:10px;font-weight:800;text-transform:uppercase;
  letter-spacing:.08em;color:var(--text3);text-align:left;padding:11px 12px;border-bottom:1px solid var(--border);white-space:nowrap;background:var(--bg3)}
.tabla td{padding:10px 12px;font-size:13px;color:var(--text);border-bottom:1px solid var(--border);vertical-align:middle}

/* ── (10) El celular: la barra de arriba, el cajón de la barra lateral y el riel ── */
/* La barra del celular, de 52 px: hamburguesa · bandera + TÍTULO DE LA VISTA · la cuenta.
   Acá va la PIEZA; cómo se coloca se queda en cada HTML (fija en el dashboard, pegajosa bajo la franja de
   diseño en Brújula), igual que la barra lateral de la 4a. El hueco de la derecha le deja sitio a la isla. */
.mob-topbar{display:none;align-items:center;gap:8px;height:52px;box-sizing:border-box;
  background:var(--bg2);border-bottom:1px solid var(--border);padding:0 96px 0 10px}
.mob-menu-btn{width:44px;height:44px;border-radius:10px;border:0;background:transparent;
  display:flex;align-items:center;justify-content:center;cursor:pointer;flex-shrink:0;color:var(--text)}
.mob-menu-btn svg{width:22px;height:22px}
.mob-title{flex:1;min-width:0;font-weight:700;font-size:15px;letter-spacing:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* Cajón de 272 px que entra desde la izquierda. Cada app pone SU clase de abierto (.mob-open en el dashboard,
   .app.drawer-on en Brújula): eso es colocación y se queda en su HTML. */
@media (max-width:768px){
  .sidebar{position:fixed;top:0;left:0;bottom:0;z-index:500;width:272px;min-width:272px;transform:translateX(-100%);
    transition:transform .28s var(--ease-drawer);overflow-y:auto;touch-action:pan-y;   /* lo horizontal es del gesto de cerrar (avsal.js) */
    padding-top:env(safe-area-inset-top,0px);padding-bottom:env(safe-area-inset-bottom,0px)}   /* la app instalada pinta bajo la barra de estado y la rayita (4-oct) */
  .sb-rail-btn{display:none}
  .sb-show-btn{display:none!important}
  .mob-overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:490;backdrop-filter:blur(2px);-webkit-backdrop-filter:blur(2px)}
  .mob-overlay.open{display:block}
  .mob-topbar{display:flex}
  /* La isla sube por encima de la barra del celular y se sienta dentro de ella: una sola cuenta, un solo menú. */
  .topbar-actions{top:calc(10px + env(safe-area-inset-top,0px));right:10px;gap:8px;z-index:460}
  /* En el celular: tres botones redondos de 34 (la frescura solo con su ícono; conexiones crece si avisa con texto). */
  .topbar-btn{width:34px;height:34px;padding:0;justify-content:center;border-radius:50%}
  .topbar-btn span{display:none}
  .salud-chip{height:34px;min-width:34px}
  .top-avatar{width:34px;height:34px;min-width:34px}
}
/* ⭐ La barra de abajo del celular (Paquete 3 del dashboard, 16-jul; desde el 29-oct también la de AVSAL Chat en modo lectura): los destinos
   diarios donde vive el pulgar. Sólida de 56, ícono 21, texto 10,5 (700 el activo). En el computador no existe. El numerito (.bn-num) va sobre el
   ícono, como el del ícono de la app. Cada ítem es un lugar, nunca una acción (Apple, «Tab bars»). */
.bottom-nav{display:none}
@media (max-width:768px){
  .bottom-nav{position:fixed;left:0;right:0;bottom:0;z-index:440;display:flex;background:var(--bg2);border-top:1px solid var(--border);
    padding:0 8px env(safe-area-inset-bottom)}
  .bn-item{flex:1;position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;padding:6px 2px;min-height:56px;
    color:var(--text3);font-size:10.5px;font-weight:500;cursor:pointer;border-radius:0;text-decoration:none;transition:color var(--dur) var(--ease)}
  .bn-item svg{width:21px;height:21px;stroke:currentColor;stroke-width:1.8;fill:none;stroke-linecap:round;stroke-linejoin:round}
  .bn-item.active{color:var(--accent);font-weight:700}
  .bn-num{position:absolute;top:5px;left:calc(50% + 6px);min-width:18px;height:18px;padding:0 5px;box-sizing:border-box;border-radius:9px;
    background:var(--red);color:#fff;font:700 11px/18px var(--mono);text-align:center;font-variant-numeric:tabular-nums}   /* el rojo de .nav-badge.num.rojo */
  /* 📖 Modo lectura (html.lectura, 29-oct): solo el dueño, con el dedo y en ancho de celular; «Versión completa en este celular» lo apaga.
     Lo de trabajar se ESCONDE (nada se borra) con .solo-trabajo; lo que existe solo para leer va con .solo-lectura. */
  html:not(.lectura) .solo-lectura{display:none!important}
  html.lectura .solo-trabajo{display:none!important}
}
@media (min-width:769px){.solo-lectura{display:none!important}}

/* Riel de solo íconos: el dashboard lo enciende a mano con .sb-collapsed y Brújula con .rail. El CONTENIDO se
   comporta igual en las dos; cuánto mide la barra lo pone cada app (ella sabe si es fija o columna de un grid). */
@media (min-width:769px){
  :is(.app.sb-collapsed,.app.rail) .sidebar-logo{justify-content:center;padding-left:0;padding-right:0}
  :is(.app.sb-collapsed,.app.rail) .logo-word,
  :is(.app.sb-collapsed,.app.rail) .store-pill-info,
  :is(.app.sb-collapsed,.app.rail) .store-pill-arr,
  :is(.app.sb-collapsed,.app.rail) .sb-search span,
  :is(.app.sb-collapsed,.app.rail) .nav-group-arr,
  :is(.app.sb-collapsed,.app.rail) .nav-group-items,
  :is(.app.sb-collapsed,.app.rail) .nav-app>span:not(.nav-icon),
  /* En el riel de AVSAL Chat (.app.rail) el numerito de un ítem NO se esconde: brujula.html lo pone sobre su ícono (tanda 6, M-27). El dashboard (.sb-collapsed) no cambia. */
  /* …y solo el texto del MENÚ (.sidebar) se esconde: las pestañas del agente también son .nav-item y conservan su nombre (tanda 8, M-26). */
  .app.sb-collapsed .nav-badge,.app.rail .nav-badge:not(.num),.app.rail :not(.nav-item)>.nav-badge.num,
  .app.sb-collapsed .nav-item>span:not(.nav-icon),.app.rail .sidebar .nav-item>span:not(.nav-icon):not(.nav-badge),
  :is(.app.sb-collapsed,.app.rail) .nav-sub>span:not(.nav-sub-ic){display:none!important}
  :is(.app.sb-collapsed,.app.rail) .nav-section-label{font-size:0;height:1px;padding:0;margin:10px 8px;background:var(--border)}
  :is(.app.sb-collapsed,.app.rail) .store-pill{justify-content:center;margin:0 10px 10px;padding:8px 0;width:auto}
  :is(.app.sb-collapsed,.app.rail) .sb-search{justify-content:center;margin:0 10px 12px;padding:9px 0}
  :is(.app.sb-collapsed,.app.rail) .nav-item,
  :is(.app.sb-collapsed,.app.rail) .nav-group-hdr,
  :is(.app.sb-collapsed,.app.rail) .nav-app{font-size:0;justify-content:center;padding:10px 0;gap:0}
  :is(.app.sb-collapsed,.app.rail) .nav-sub{justify-content:center;padding:7px 0}
  :is(.app.sb-collapsed,.app.rail) .sidebar-footer{padding:12px 10px}
  :is(.app.sb-collapsed,.app.rail) .sb-rail-btn svg{transform:scaleX(-1)}
  /* En el riel no cabe en la fila: vuelve a colgar del borde derecho, centrado con el bloque del logo. */
  :is(.app.sb-collapsed,.app.rail) .sb-rail-btn{position:absolute;top:16px;right:-14px;margin-left:0;border-radius:9px;background:var(--bg2);
    border-color:var(--border2);box-shadow:0 2px 8px rgba(0,0,0,.25)}
}

/* ══════════════════════════════════════════════════════════════════════════════════════════════════════════
   (11) LA CARA PROFESIONAL — piezas comunes (tanda 1, 2026-09-23)
   Lo que la auditoría visual encontró repetido de 4 a 28 maneras distintas, ahora una vez: la superficie de toda tarjeta,
   el número grande en tres tallas, la cabecera de sección, las pestañas, el segmento de período, el aviso y el mensaje
   flotante. Regla de color: los números van en el color del texto; el verde, el ámbar y el rojo salen solo cuando
   AVISAN algo (gana, vigila, pierde). Cada pieza vive UNA vez, acá (scripts/cara-check.js la vigila).
   ══════════════════════════════════════════════════════════════════════════════════════════════════════════ */

/* Cabecera de la vista: rótulo arriba, título, una línea y, si la vista los tiene, sus controles a la derecha. */
.page-eyebrow{font-size:var(--fs-label);font-weight:800;text-transform:uppercase;letter-spacing:.1em;color:var(--text3);margin-bottom:6px;line-height:14px}
.page-actions{display:flex;align-items:center;gap:10px;flex-wrap:wrap;flex:none}

/* El número grande: rótulo en mayúscula, cifra en Geist Mono y, debajo, su contexto. Tres tallas. */
.kpi.hero .kpi-value,.kpi.hero .v{font-size:var(--fs-kpi-hero)}
.kpi.sm .kpi-value{font-size:var(--fs-kpi-sm)}
.kpi.hero{padding:20px 22px}
.kpi.sm{padding:14px 16px}
.kpi.sm .kpi-foot{margin-top:6px}
/* Arriba: el rótulo y, a la derecha, una esquina opcional (pastilla o «?»). Abajo: el pie (delta · pastilla · contexto) y un
   segundo contexto (.kpi-ctx2, puede ser una mini-tabla .par). La sparkline va a la derecha de la cifra (.kpi-cuerpo) o debajo. */
.kpi-top{display:flex;align-items:flex-start;justify-content:space-between;gap:8px}
.kpi-top .kpi-label{margin-bottom:0}
.kpi-cuerpo{display:flex;align-items:flex-end;justify-content:space-between;gap:18px;min-width:0;flex-wrap:wrap}
.kpi-foot{display:flex;align-items:center;flex-wrap:wrap;gap:6px 8px;margin-top:10px}
.kpi-foot .kpi-sub{margin-top:0}
.kpi-ctx2{font-size:12px;line-height:17px;color:var(--text3);margin-top:6px}
.kpi-ctx2 .par{display:flex;justify-content:space-between;gap:8px}
.kpi-spark-abajo{margin-top:14px}
/* 🖱️ El mouse sobre una tarjeta de cifras (5-oct, Brahian: «unificar… sea aquí y sea en la brújula»): UNA regla para las dos apps. El
   borde sube a --border2 y nada más: sin saltito, sin sombra y sin tinte de color (una tarjeta de datos no es un botón). Solo con mouse:
   en el celular un toque no lo deja prendido. Las secciones y las tarjetas grandes no reaccionan. El `html` delante le gana a las reglas
   de cada HTML que ponen su borde con la misma fuerza (las .kpi.acc-* del dashboard). Una tarjeta de cifras nueva se suma a esta lista. */
html :is(.kpi, .cod-card, .rs-primary, .rs-secondary, .dk-card, .agc){transition:border-color var(--dur) var(--ease-out)}
@media (hover:hover) and (pointer:fine){html :is(.kpi, .cod-card, .rs-primary, .rs-secondary, .dk-card, .agc):hover{border-color:var(--border2)}}
.num-bad{color:var(--red-txt)!important}   /* el número que avisa pérdida (el único que se pinta) */
.num-warn{color:var(--warn-txt)!important} /* el que pide vigilar */
.num-ok{color:var(--accent)!important}   /* el total que gana (solo ese) */

/* Cabecera de sección (la tarjeta que se pliega): rótulo · ícono + título · una línea · controles · el chevron. */
.sec{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius-card);box-shadow:var(--surface-shadow);margin-bottom:var(--s-4);overflow:hidden}
.sec-hd{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--s-4);padding:var(--s-5) var(--s-5) 0;cursor:pointer;user-select:none}
/* La izquierda es una columna (lienzo v2): la ceja arriba, luego ícono + título (.sec-tl) y la línea en su propio renglón. */
.sec-hd-l{display:flex;flex-direction:column;align-items:flex-start;gap:0;min-width:0;flex:1}
.sec-ic{display:flex;flex:none;color:var(--text2);font-size:16px;line-height:22px}
.sec-ic svg{width:17px;height:17px;margin-top:0;stroke:currentColor;stroke-width:1.7;fill:none;stroke-linecap:round;stroke-linejoin:round}
/* El ícono de un rótulo de tarjeta (el que antes era un emoji): trazo de línea en el gris del rótulo, alineado al texto. */
.t-ic{display:inline-flex;align-items:center;flex:none;margin-right:6px;color:var(--text3);vertical-align:-2px}
.t-ic svg{width:14px;height:14px;stroke:currentColor;stroke-width:1.8;fill:none;stroke-linecap:round;stroke-linejoin:round}
.t-ic.ok{color:var(--accent)} .t-ic.warn{color:var(--warn)} .t-ic.bad{color:var(--red)} .t-ic.info{color:var(--info)}
/* El chevron de un grupo que se pliega (antes una flechita de texto ▾/▸): el mismo trazo del de las secciones, girado por su transform. */
.t-chev{display:inline-flex;align-items:center;justify-content:center;flex:none;width:14px;height:14px;color:var(--text3);transition:transform var(--dur) var(--ease)}
.t-chev svg{width:14px;height:14px;stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round}
/* La caja de ícono de un estado vacío o de error (antes un emoji de 30 px): gris, con el trazo de línea. .chica = la de una fila. */
.ic-caja{width:44px;height:44px;border-radius:12px;display:grid;place-items:center;flex:none;margin:0 auto 10px;background:var(--bg3);border:1px solid var(--border);color:var(--text2)}
.ic-caja svg{width:20px;height:20px;stroke:currentColor;stroke-width:1.8;fill:none;stroke-linecap:round;stroke-linejoin:round}
.ic-caja.chica{width:30px;height:30px;border-radius:9px;margin:0}
.ic-caja.chica svg{width:15px;height:15px}
.sec-eye{font-size:var(--fs-label);font-weight:800;text-transform:uppercase;letter-spacing:.1em;color:var(--text3);line-height:14px;margin-bottom:0}
.sec-title{font-size:var(--fs-title);font-weight:700;letter-spacing:-.01em;line-height:22px;color:var(--text)}
.sec-sub{display:block;margin-top:3px;font-size:12.5px;font-weight:500;color:var(--text3);line-height:18px}
.sec-sub b{color:var(--text);font-weight:600}
.sec-title .sec-sub{display:inline;margin-top:0;margin-left:4px}   /* compatibilidad: una vista que todavía la mete dentro del título */
.sec-tl{display:flex;align-items:center;gap:9px;min-width:0}
.sec-eye+.sec-tl{margin-top:4px}
.sec-nota{font-size:12px;color:var(--text3);white-space:nowrap}
.sec.fija .sec-hd{cursor:default}
.sec.plegada .sec-hd{padding-bottom:var(--s-5)}   /* plegada: el aire de abajo igual al de arriba (uiSection pone o quita .plegada) */
@media print{.sec.plegada .sec-hd{padding-bottom:0}}   /* en el papel todo sale abierto: el aire lo pone el cuerpo */
.sec-r{display:flex;align-items:center;gap:8px;flex-wrap:wrap;justify-content:flex-end}
.sec-chev{flex:none;width:28px;height:28px;border-radius:7px;display:flex;align-items:center;justify-content:center;color:var(--text3);transition:transform var(--dur) var(--ease),background var(--dur) var(--ease)}
.sec-chev svg{width:16px;height:16px;stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round}
.sec-hd:hover .sec-chev{background:rgba(var(--ink-rgb),.05);color:var(--text)}
.sec-body{padding:var(--s-4) var(--s-5) var(--s-5)}
.sec-body.flush{padding:var(--s-4) 0 0}   /* sin lados ni pie, pero con los 16 bajo la cabecera */

/* Pestañas de una vista (Día · Histórico · Semanal · Resumen del mes… · los filtros de Pedidos en Brújula): subrayadas, la
   elegida con la raya verde. La pieza es la que ya usaba Brújula; el dashboard la adopta (sus pestañas viejas la copian en su capa). */
.tabs{display:flex;gap:22px;border-bottom:1px solid var(--border);margin-bottom:var(--s-4);overflow-x:auto;scrollbar-width:none}
.tabs::-webkit-scrollbar{display:none}
.tabs button,.tabs>a{height:38px;padding:0;border:0;border-bottom:2px solid transparent;margin-bottom:-1px;background:none;font:inherit;font-size:13px;font-weight:500;
  color:var(--text3);white-space:nowrap;cursor:pointer;display:inline-flex;align-items:center;gap:6px;text-decoration:none;transition:color var(--dur) var(--ease)}
.tabs button:hover,.tabs>a:hover{color:var(--text2)}
.tabs button.on,.tabs>a.on{color:var(--text);font-weight:600;border-bottom-color:var(--accent)}
.tabs .c{font:500 11px/1 'Geist Mono',ui-monospace,monospace;color:var(--text3);margin-left:1px}
/* ↔️ (5-oct) Una fila de pestañas que no cabe: el borde donde hay más se desvanece (las marcas las pone AVSAL_UI.tabs.bordes; del
   negro de la máscara solo cuenta su opacidad). */
.tabs.mas-der{-webkit-mask-image:linear-gradient(to right,#000 calc(100% - 48px),transparent);mask-image:linear-gradient(to right,#000 calc(100% - 48px),transparent)}
.tabs.mas-izq{-webkit-mask-image:linear-gradient(to left,#000 calc(100% - 48px),transparent);mask-image:linear-gradient(to left,#000 calc(100% - 48px),transparent)}
.tabs.mas-izq.mas-der{-webkit-mask-image:linear-gradient(to right,transparent,#000 48px,#000 calc(100% - 48px),transparent);mask-image:linear-gradient(to right,transparent,#000 48px,#000 calc(100% - 48px),transparent)}

/* Segmento (Hoy · Ayer · 7 días · 30 días… · Mensaje / Nota): el elegido, relleno en verde. La pieza de Brújula, para las dos. */
.seg{display:inline-flex;align-items:center;flex-wrap:wrap;gap:2px;padding:3px;border-radius:10px;background:var(--surface);border:1px solid var(--border);min-width:0}
.seg button,.seg>a{height:28px;padding:0 12px;border:0;border-radius:7px;background:transparent;font:inherit;font-size:12.5px;font-weight:500;color:var(--text2);
  cursor:pointer;white-space:nowrap;display:inline-flex;align-items:center;text-decoration:none}
.seg button:hover,.seg>a:hover{color:var(--text)}
.seg button.on,.seg>a.on{background:var(--accent);color:var(--accent-ink);font-weight:700}
.seg button:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
.seg .c{font:500 11px/1 'Geist Mono',ui-monospace,monospace;opacity:.7;margin-left:4px}

/* El aviso: una franja propia con su ícono, separado del texto de lectura. Tonos ok · warn · bad · info. */
.banner{display:flex;align-items:flex-start;gap:14px;padding:16px 18px;border-radius:var(--radius-card);border:1px solid var(--border);
  background:rgba(var(--ink-rgb),.03);color:var(--text2);font-size:13px;line-height:1.5}
.banner.ok{background:var(--accent-dim)} .banner.warn{background:var(--yellow-dim)} .banner.bad{background:var(--red-dim)} .banner.info{background:var(--info-dim)}
.banner-ic{width:30px;height:30px;border-radius:8px;background:var(--surface);display:flex;align-items:center;justify-content:center;flex:none;color:var(--text2)}
.banner.ok .banner-ic{color:var(--accent)} .banner.warn .banner-ic{color:var(--warn)} .banner.bad .banner-ic{color:var(--red)} .banner.info .banner-ic{color:var(--info)}
.banner-ic svg{width:17px;height:17px;stroke:currentColor;stroke-width:1.8;fill:none;stroke-linecap:round;stroke-linejoin:round}
.banner-t{font-size:15px;font-weight:700;color:var(--text);line-height:21px}
.banner-x{font-size:13px;color:var(--text2);line-height:19px}
.banner b{color:var(--text)}
/* El cuerpo (título + texto) y, a la derecha, sus botones (AVSAL_UI.aviso lo arma igual en las dos apps). */
.banner-cuerpo{flex:1;min-width:0}
.banner-acciones{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end;flex:none;align-self:center}
.banner>.btn{flex:none;align-self:center}
.banner-t+.banner-x{margin-top:2px}

/* El mensaje flotante (AVSAL_UI.toast): uno para las dos apps, arriba al centro, con el color del aviso. */
.av-toast{position:fixed;top:calc(16px + env(safe-area-inset-top,0px));left:50%;z-index:99990;max-width:min(460px,calc(100vw - 32px));display:flex;align-items:flex-start;gap:10px;
  padding:11px 14px 11px 12px;border-radius:12px;background:var(--bg2);border:1px solid var(--border2);box-shadow:0 12px 36px rgba(0,0,0,.45);
  font-size:13px;font-weight:600;line-height:1.45;color:var(--text);transform:translate(-50%,-8px);opacity:0;pointer-events:none;
  transition:opacity var(--dur) var(--ease),transform var(--dur) var(--ease)}
.av-toast.on{opacity:1;transform:translate(-50%,0);pointer-events:auto}
.av-toast i{width:8px;height:8px;border-radius:50%;flex:none;margin-top:6px;background:var(--info)}
.av-toast.g i{background:var(--accent)} .av-toast.r i{background:var(--red)} .av-toast.y i{background:var(--warn)}
html.light .av-toast,body.light .av-toast{box-shadow:0 12px 36px rgba(0,0,0,.14)}
@media (prefers-reduced-motion:reduce){.av-toast{transition:opacity var(--dur) var(--ease)}}   /* menos movimiento, no cero: se funde sin bajar */
/* 🔄 El aviso de versión nueva (AVSAL_UI.vigilaVersion, 28-sep): el mismo mensaje flotante, abajo y fijo hasta «Recargar» o «×». */
.av-toast.abajo{top:auto;bottom:calc(16px + env(safe-area-inset-bottom,0px));align-items:center;transform:translate(-50%,8px)}
.av-toast.abajo.on{transform:translate(-50%,0)}
.av-toast.abajo i{margin-top:0}
.av-toast.abajo>span{flex:1;min-width:0}
.av-toast.abajo>.btn{flex:none}

/* El modal: el velo (.av-modal-bg) y la caja (.av-modal). Todo modal nuevo de las dos apps usa estas dos piezas. */
.av-modal-bg{position:fixed;inset:0;background:var(--modal-bg);backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px);display:flex;align-items:center;justify-content:center;padding:max(20px, env(safe-area-inset-top,0px)) 20px max(20px, env(safe-area-inset-bottom,0px));z-index:1000}
.av-modal{background:var(--surface);border:1px solid var(--border2);border-radius:var(--radius-lg);box-shadow:var(--modal-shadow);width:100%;max-width:560px;max-height:90vh;overflow:auto;padding:24px}
/* La ventana llega (4-oct): el velo se funde y la caja sale del 97 % de su tamaño, en 200 ms, solo cuando NACE (@starting-style,
   sin JavaScript). La caja de DropKiller se repinta con cada pestaña: se queda con el fundido del velo, o parpadearía.
   ⛔ La paleta de comandos (⌘K, .cmd-box) no es un .av-modal y abre sin animación, a propósito (se abre con el teclado). */
.av-modal-bg{transition:opacity .2s var(--ease-out)}
.av-modal-bg>.av-modal:not(.dk-modal){transition:opacity .2s var(--ease-out),transform .2s var(--ease-out)}
@starting-style{.av-modal-bg{opacity:0} .av-modal-bg>.av-modal:not(.dk-modal){opacity:0;transform:scale(.97)}}
@media (prefers-reduced-motion:reduce){.av-modal-bg>.av-modal:not(.dk-modal){transition:opacity .2s var(--ease-out)}}
/* 🔔 «Avisos en este celular» (AVSAL_UI.avisos, 3-oct): el estado en su .banner, qué te llega y el botón que toca. */
.av-avisos{max-width:480px}
.av-avisos-hd{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:14px}
.av-avisos-hd h3{display:flex;align-items:center;gap:10px;margin:0;font-size:18px;font-weight:700;color:var(--text)}
.av-avisos-hd h3 svg{width:20px;height:20px;stroke:var(--accent);stroke-width:1.8;fill:none;stroke-linecap:round;stroke-linejoin:round}
.av-avisos-cargando{color:var(--text2);font-size:14px;padding:12px 0}
.av-avisos-error{margin-top:10px;color:var(--red-txt);font-size:13px;line-height:19px}
.av-avisos-lista{margin:16px 0 0;padding:0;list-style:none;display:grid;gap:10px}
.av-avisos-lista li{display:flex;gap:10px;align-items:flex-start;font-size:14px;line-height:20px;color:var(--text2)}
.av-avisos-lista li b{color:var(--text);font-weight:600}
.av-avisos-lista li svg{width:16px;height:16px;flex:none;margin-top:2px;stroke:var(--text3);stroke-width:1.8;fill:none;stroke-linecap:round;stroke-linejoin:round}
.av-avisos-pie{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end;margin-top:20px}
.av-avisos-pie:empty{display:none}
/* ☁️ «Hay dos copias de la misma tienda» (dashboard → _nubeDupModal, 3-oct): cuál es la buena, una vez. */
.nube-copias-t{display:flex;align-items:center;gap:10px;margin:0 0 8px;font-size:18px;font-weight:700;color:var(--text)}
.nube-copias-x{margin:0 0 12px;font-size:14px;line-height:20px;color:var(--text2)}
.nube-copias-x+.lista{margin-bottom:12px}
.nube-copias-pie{display:flex;justify-content:flex-end;margin-top:8px}

/* ══════════════════════════════════════════════════════════════════════════════════════════════════════════
   (12) LOS GRÁFICOS — el kit de avsal-graficos.js (la cara profesional, tanda 2, 2026-09-23)
   Cada gráfico se dibuja al ancho real de su caja: la letra de los ejes mide lo mismo en cualquier pantalla. Colores con
   significado: gana en verde, pierde en rojo, lo demás en los grises del tema (--bar-main, --bar-soft, --bar-faint).
   ══════════════════════════════════════════════════════════════════════════════════════════════════════════ */
.g-auto{position:relative;width:100%;min-width:0}
.g-svg{display:block;overflow:visible}
.g-t{font-family:'Geist Mono',ui-monospace,monospace;font-size:10.5px;font-weight:500;fill:var(--text3);font-variant-numeric:tabular-nums}
.g-l{font-family:'Geist',ui-sans-serif,system-ui,sans-serif;font-size:11px;font-weight:500;fill:var(--text2)}
.g-v{font-family:'Geist Mono',ui-monospace,monospace;font-size:10.5px;font-weight:600;fill:var(--text);font-variant-numeric:tabular-nums}
.g-in{font-family:'Geist',ui-sans-serif,system-ui,sans-serif;font-size:10.5px;font-weight:700;fill:var(--bg)}
.g-halo{stroke:var(--surface);stroke-width:4px;paint-order:stroke;stroke-linejoin:round}
.g-v.g-gana{fill:var(--accent)} .g-v.g-pierde{fill:var(--red)}
.g-grid{stroke:var(--grid);stroke-width:1}
.g-cero{stroke:var(--axis);stroke-width:1}
.g-meta{stroke:var(--text2);stroke-width:1.2;stroke-dasharray:5 4}
.g-hito{stroke:var(--info);stroke-width:1.5;stroke-dasharray:3 3}   /* 📍 un hito en el tiempo (el día en que se encendió Brújula), kit linea · hitos (5-oct) */
.g-hito-t{fill:var(--info);font-weight:600}
.g-guia{stroke:var(--axis);stroke-width:1;stroke-dasharray:3 3}
.g-bar-gana{fill:var(--accent)} .g-bar-pierde{fill:var(--red)} .g-bar-main{fill:var(--bar-main)} .g-bar-soft,.g-bar-tenue{fill:var(--bar-soft)}
.g-bar-info{fill:var(--info)} .g-bar-warn{fill:var(--warn)}
.g-bar-cat1{fill:var(--cat-1)} .g-bar-cat2{fill:var(--cat-2)} .g-bar-cat3{fill:var(--cat-3)}   /* una barra (o un tramo de una apilada) por categoría: el mismo color de su leyenda .ley>i.catN (Consumo, 21-oct) */
.g-hit{fill:transparent;cursor:pointer}
.g-hit:hover{fill:rgba(var(--ink-rgb),.035)}
.g-z-esc{fill:var(--accent-dim)} .g-z-sos{fill:var(--bar-faint)} .g-z-pier{fill:var(--red-dim)}
.g-bala-gana{fill:var(--accent)} .g-bala-sos{fill:var(--text2)} .g-bala-pierde{fill:var(--red)}
.g-flecha-gana,.g-flecha-sos,.g-flecha-pierde{fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.g-flecha-gana{stroke:var(--accent)} .g-flecha-sos{stroke:var(--text2)} .g-flecha-pierde{stroke:var(--red)}
.g-marca{fill:var(--text)}
.g-linea{fill:none;stroke:var(--text2);stroke-width:2;stroke-linejoin:round;stroke-linecap:round}
.g-linea.gana{stroke:var(--accent)} .g-linea.pierde{stroke:var(--red)} .g-linea.info{stroke:var(--info)} .g-linea.warn{stroke:var(--warn)}
.g-linea.guia{stroke:var(--text3);stroke-width:1.2}
.g-linea-barras{pointer-events:none}   /* la línea que sigue las puntas de las barras (barras → cfg.linea) no le quita el globo a la barra de abajo */
.g-punto{fill:var(--text2);stroke:var(--surface);stroke-width:2}
.g-punto.gana{fill:var(--accent)} .g-punto.pierde{fill:var(--red)} .g-punto.warn{fill:var(--warn)} .g-punto.info{fill:var(--info)}
.g-punteada{stroke-dasharray:4 4}
.g-spark{display:block;overflow:visible}
.g-spark-l{fill:none;stroke:var(--text2);stroke-width:1.6;stroke-linejoin:round;stroke-linecap:round}
.g-spark-p{fill:var(--accent);stroke:var(--surface);stroke-width:2}
.g-spark-p.warn{fill:var(--warn)} .g-spark-p.bad{fill:var(--red)} .g-spark-p.neutral{fill:var(--text3)}   /* o.tono: el estado de la fila */
.g-spark-techo{stroke:var(--text3);stroke-width:1;stroke-dasharray:3 3}   /* o.techo: la guía del techo (5-oct) */
.g-spark-falla{fill:var(--red)}   /* o.fallos: un turno fallido, al pie de la línea (16-oct, la oficina) */
/* o.area (24-oct, el Inicio de AVSAL Chat): el relleno bajo la línea, del gris del tema arriba a nada abajo; .gana lo tiñe del acento */
.g-spark-g .s0{stop-color:var(--text2);stop-opacity:.16} .g-spark-g .s1{stop-color:var(--text2);stop-opacity:0}
.g-spark.gana .g-spark-g .s0{stop-color:var(--accent);stop-opacity:.22} .g-spark.gana .g-spark-g .s1{stop-color:var(--accent)}
.g-spark.gana .g-spark-l{stroke:var(--accent)}
/* El globo por punto de la sparkline (AVSAL_G.spark con o.globos, 1-oct): el punto se enciende solo mientras el mouse está en su franja. */
.g-spark-c{fill:var(--text);stroke:var(--surface);stroke-width:1.5;opacity:0;pointer-events:none;transition:opacity var(--dur) var(--ease)}
.g-spark-hit:hover .g-spark-c{opacity:1}
/* La barra de avance: una sola (8 px, radio 4, la pista del tema) para las ocho que había. */
.g-prog{height:8px;border-radius:4px;background:var(--bar-faint);overflow:hidden}
.g-prog>i{display:block;height:100%;border-radius:4px;background:var(--bar-main);transition:width var(--dur) var(--ease)}
.g-prog.ok>i{background:var(--accent)} .g-prog.warn>i{background:var(--warn)} .g-prog.bad>i{background:var(--red)} .g-prog.info>i{background:var(--info)}
@media print{.g-hit{display:none}}
/* Lienzo v2 (fase P, 2026-09-24): lo que el kit suma. La barra de la meta del mes (AVSAL_G.caja('meta')), el área y la cruz de la
   línea, su animación de entrada (una sola vez), la barra de «hoy» y el mapa de calor (AVSAL_G.caja('calor')). */
.g-pista{fill:var(--bar-faint)}
.g-meta-proy{fill:none;stroke:var(--warn);stroke-width:1.5;stroke-dasharray:3 3}
.g-meta-proy.gana{stroke:var(--accent)}
.g-meta-hoy{fill:var(--text2)}
.g-meta-t{font-family:'Geist',ui-sans-serif,system-ui,sans-serif;font-size:11.5px;font-weight:500;fill:var(--text2)}
.g-meta-t.fuerte{font-weight:600;fill:var(--text)}
.g-meta-t.warn{fill:var(--warn)} .g-meta-t.gana{fill:var(--accent)} .g-meta-t.pierde{fill:var(--red)}
.g-bar-hoy{fill:var(--text)}
.g-area{fill:rgba(var(--ink-rgb),.06)} .g-area.gana{fill:rgba(var(--accent-rgb),.14)}
.g-cruz{stroke:var(--border2);stroke-width:1;opacity:0;pointer-events:none}
.g-cruz-p{fill:var(--accent);stroke:var(--surface);stroke-width:2;opacity:0;pointer-events:none}
.g-hitg:hover .g-cruz,.g-hitg:hover .g-cruz-p{opacity:1}
@keyframes gDibuja{to{stroke-dashoffset:0}}
@keyframes gAparece{from{opacity:0}to{opacity:1}}
.g-anima{stroke-dasharray:1;stroke-dashoffset:1;animation:gDibuja .9s var(--ease-out) forwards}
.g-anima-f{opacity:0;animation:gAparece .5s ease-out .45s forwards}
.g-anima-p{opacity:0;animation:gAparece .35s ease-out .75s forwards}
@media (prefers-reduced-motion:reduce),print{.g-anima,.g-anima-f,.g-anima-p{animation:none;opacity:1;stroke-dasharray:none}}
/* 🎞️ El primer vistazo del día (5-oct, «la segunda tanda»): la barra de la meta crece de 0 a su valor en 500 ms y lo punteado
   («a este ritmo cierras en…») se funde 300 ms después; las cifras no se mueven. Lo pide Hoy una vez al día (AVSAL_G meta, cfg.anima).
   Con «Reducir movimiento», solo los fundidos. */
@keyframes gCrece{from{transform:scaleX(0)}to{transform:scaleX(1)}}
.g-anima-m{transform-box:fill-box;transform-origin:0 50%;animation:gCrece .5s var(--ease-out) both}
.g-anima-mp{animation:gAparece .2s var(--ease-out) .3s both}
@media (prefers-reduced-motion:reduce){.g-anima-m{animation-name:gAparece;animation-duration:.2s}}
@media print{.g-anima-m,.g-anima-mp{animation:none}}
/* 🎞️ Lo que acaba de cambiar («Ver la tendencia», 5-oct; las skills de Emil): la cifra que cambió SOLA (llegó un dato con la vista
   abierta) se ilumina con el acento y se apaga en 1,2 s (solo color: vale igual con «Reducir movimiento»); un contador que sube da un
   salto chico de 320 ms (con «Reducir movimiento», nada). Las pone AVSAL_UI.resaltar; un repintado nunca las dispara. */
@keyframes av-cambio{from{background-color:color-mix(in srgb,var(--accent) 22%,transparent)}to{background-color:transparent}}
.av-cambio{animation:av-cambio 1.2s var(--ease-out);border-radius:var(--radius-sm)}
@keyframes av-salto{0%{transform:scale(1)}40%{transform:scale(1.22)}100%{transform:scale(1)}}
.av-salto{animation:av-salto .32s var(--ease-out)}
@media (prefers-reduced-motion:reduce){.av-salto{animation:none}}
/* 🏆 Un logro de verdad (5-oct, «la segunda tanda»): la pastilla de un logro DEFINITIVO —el cierre que pasó la meta, el producto que
   el tablero pasó a Escalando— lleva un ✓ dibujado en lugar del punto. La primera vez que se ve en este equipo la cruza un brillo (700 ms)
   y su ✓ se traza (300 ms): lo pone AVSAL_UI.logros, que recuerda qué logro ya celebró. Con «Reducir movimiento», sin brillo. */
.pill.av-logro{position:relative;overflow:hidden}
.pill.av-logro::before{display:none}
.av-logro-chk{width:11px;height:11px;flex:none;fill:none;stroke:currentColor;stroke-width:3;stroke-linecap:round;stroke-linejoin:round}
.av-logro::after{content:'';position:absolute;inset:0;background:linear-gradient(100deg,transparent 30%,var(--brillo) 50%,transparent 70%);transform:translateX(-110%);pointer-events:none}
.av-logro.brilla::after{animation:av-brillo .7s var(--ease-out) forwards}
.av-logro.brilla .av-logro-chk path{stroke-dasharray:1;animation:av-traza .3s var(--ease-out) .15s backwards}
@keyframes av-brillo{to{transform:translateX(110%)}}
@keyframes av-traza{from{stroke-dashoffset:1}to{stroke-dashoffset:0}}
@media (prefers-reduced-motion:reduce){.av-logro.brilla::after{animation:none}}
@media print{.av-logro::after{display:none}}
/* El mapa de calor: ganancia en 4 pasos de verde, pérdida en 3 de rojo, sin registro en la pista. */
.g-calor-c0{fill:var(--bar-faint)}
.g-calor-g1{fill:rgba(var(--accent-rgb),.22)} .g-calor-g2{fill:rgba(var(--accent-rgb),.42)} .g-calor-g3{fill:rgba(var(--accent-rgb),.66)} .g-calor-g4{fill:var(--accent)}
.g-calor-p1{fill:rgba(var(--red-rgb),.3)} .g-calor-p2{fill:rgba(var(--red-rgb),.6)} .g-calor-p3{fill:var(--red)}
.g-calor-c{cursor:pointer}
.g-calor-mes{font-size:11px;font-weight:600;fill:var(--text2)} .g-calor-dia{font-size:11px;fill:var(--text3)}
.calor-ley{display:flex;align-items:center;flex-wrap:wrap;gap:8px 10px;margin-top:16px;font-size:12px;color:var(--text3)}
.calor-sws{display:flex;gap:3px} .calor-sin{display:flex;align-items:center;gap:5px;margin:0 6px}
.calor-ley i{width:14px;height:14px;border-radius:3px;display:inline-block}
.calor-ley i.c0{background:var(--bar-faint)}
.calor-ley i.g1{background:rgba(var(--accent-rgb),.22)} .calor-ley i.g2{background:rgba(var(--accent-rgb),.42)} .calor-ley i.g3{background:rgba(var(--accent-rgb),.66)} .calor-ley i.g4{background:var(--accent)}
.calor-ley i.p1{background:rgba(var(--red-rgb),.3)} .calor-ley i.p2{background:rgba(var(--red-rgb),.6)} .calor-ley i.p3{background:var(--red)}
.calor-cortes{margin-left:10px;font-family:'Geist Mono',ui-monospace,monospace;font-variant-numeric:tabular-nums}
/* El radar (AVSAL_G.caja('radar'), 2026-09-28): UNA figura por gráfico; anillos y ejes en la grilla del tema, la referencia punteada.
   El aro de cada punta es del fondo de su caja: quien lo pone dentro de otra superficie la declara en --g-fondo. */
.g-radar-anillo{fill:none}
.g-radar-ref{fill:none;stroke:var(--text3);stroke-width:1.2;stroke-dasharray:3 3}
.g-radar-fig{fill-opacity:.16;stroke-width:2;stroke-linejoin:round}
.g-radar-p{stroke:var(--g-fondo,var(--surface));stroke-width:2}
.g-radar-etq{font-weight:600}
/* En papel el dibujo no se sale de la hoja (AVSAL_G.imprimir lo redibuja a 660; esto es el respaldo). */
@media print{.g-svg{max-width:100%;height:auto}}

/* ══════════════════════════════════════════════════════════════════════════════════════════════════════════
   (13) LAS PIEZAS DEL LIENZO v2 («AVSAL, así quedaría», fase P, 2026-09-24)
   Lo que cada pantalla del lienzo repite, una vez: la cabecera con controles, el selector con cara de botón, los números sin
   tarjeta (stats), la lista de filas con su total, la tabla con su sub-fila «Qué hacer», el rótulo interno, la fila de barra, la
   bala del CPA en una celda, la leyenda, la caja interior, la etiqueta de devolución, los campos de formulario y el acordeón de
   pasos. Ninguna vista las vuelve a definir en su <style> (scripts/cara-check.js). Medidas: specs/00-lenguaje.md.
   ══════════════════════════════════════════════════════════════════════════════════════════════════════════ */

/* Cabecera de vista con controles a la derecha y, si las hay, las pestañas debajo (dentro de la cabecera). */
.page-header.con-acciones{display:flex;align-items:flex-end;justify-content:space-between;flex-wrap:wrap;gap:var(--s-4) var(--s-6)}
.page-hd-l{flex:1 1 420px;min-width:0}
.page-header>.page-actions{padding-bottom:2px;justify-content:flex-end;flex:0 1 auto;min-width:0;margin-left:auto}
/* Sin línea, el título es corto: no reserva 420 px y los controles caben en su renglón. Si igual bajan, se quedan a la derecha. */
.page-header.con-acciones>.page-hd-l:not(:has(.page-sub)){flex-basis:auto}
.page-tabs{flex-basis:100%;min-width:0;margin-top:var(--s-4)}
.page-tabs>.inner-tabs,.page-tabs>.prod-tabs,.page-tabs>.tabs{margin-bottom:0}
.page-title .pill{-webkit-text-fill-color:currentColor;vertical-align:middle}
.page-title .t-bandera{-webkit-text-fill-color:currentColor;background:none}   /* la bandera con sus colores, no con el degradado */
h1.page-title{font-family:inherit}
@media (max-width:768px){.page-header.con-acciones{align-items:flex-start}.page-header>.page-actions{justify-content:flex-start;margin-left:0}}

/* Selector con cara de botón (mes, producto, período): el único de las dos apps. Ícono a la izquierda, chevron a la derecha. */
.sel-hd{position:relative;display:inline-flex;align-items:center;gap:7px;height:34px;padding:0 10px 0 12px;border-radius:var(--radius-btn);
  background:var(--bg2);border:1px solid var(--border2);color:var(--text)}
.sel-hd>svg{width:15px;height:15px;flex:none;stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;color:var(--text3)}
.sel-hd select{appearance:none;-webkit-appearance:none;background:transparent;border:0;outline:0;padding:0 18px 0 0;margin:0;
  font:600 13px/1 'Geist',ui-sans-serif,system-ui,sans-serif;color:inherit;cursor:pointer;min-width:0;max-width:260px;height:100%}
.sel-hd select option{color:var(--text);background:var(--bg2)}
.sel-hd .sel-chev{position:absolute;right:10px;pointer-events:none;width:14px;height:14px}
.sel-hd.on{border-color:var(--accent);background:var(--accent-dim);color:var(--accent)}
.sel-hd:focus-within{outline:2px solid var(--accent);outline-offset:1px}

/* Stats: números SIN tarjeta dentro de una sección. .sep = contrapuestos (Plan · Real · Caja), con raya entre ellos. */
.stats{display:grid;grid-template-columns:repeat(var(--n,3),minmax(0,1fr));gap:var(--s-6)}
.stats:where(.n2){--n:2} .stats:where(.n3){--n:3} .stats:where(.n4){--n:4} .stats:where(.n5){--n:5} .stats:where(.n6){--n:6}   /* (0,1,0): el celular y la clase de cada vista les ganan */
.stats.sep>.stat+.stat{border-left:1px solid var(--border);padding-left:var(--s-6)}
.stat{min-width:0}
.stat-v{font-family:'Geist Mono',ui-monospace,monospace;font-size:22px;font-weight:600;letter-spacing:-.02em;line-height:28px;
  margin-top:8px;color:var(--text);white-space:nowrap;font-variant-numeric:tabular-nums}
.stat-v.lg{font-size:26px;line-height:32px}
.stat-v.txt{font-family:'Geist',ui-sans-serif,system-ui,sans-serif;letter-spacing:-.01em}   /* una palabra en la caja de cifra: «nada» */
.stat-v.mut{color:var(--text3)}
.stat-u{font-size:12px;font-weight:500;color:var(--text3);margin-left:4px;font-family:'Geist',ui-sans-serif,system-ui,sans-serif}
.stat-de{font-size:14px;font-weight:500;color:var(--text3)}
.stat .pill{margin-top:6px}
.stat-x{font-size:12px;line-height:17px;color:var(--text3);margin-top:6px}
.stat-x.en-linea{display:inline;margin:0 0 0 6px}
/* En el celular, a 2 columnas (también las .n4/.n5/.n6: va después y pesa lo mismo; una vista puede pedir otra con su clase). */
@media (max-width:768px){.stats{--n:2;gap:16px 14px}.stats.sep>.stat+.stat{border-left:0;padding-left:0}.stat-v{font-size:17px;line-height:22px}}

/* Lista de filas: rótulo + ayuda a la izquierda, monto a la derecha, separadas por una raya fina. El total es la última fila. */
.lista{display:flex;flex-direction:column}
.fila{display:flex;align-items:center;gap:14px;padding:9px 0;border-top:1px solid var(--border);min-width:0}
.lista>.fila:first-child{border-top:0}
.lista.con-tope>.fila:first-child{border-top:1px solid var(--border)}
.fila-l{flex:1;min-width:0}
.fila-t{font-size:13px;font-weight:600;color:var(--text);line-height:18px}
.fila-x{font-size:11.5px;color:var(--text3);line-height:1.45;margin-top:2px}
.fila-x.mono{font-family:'Geist Mono',ui-monospace,monospace}
.fila-v{font-family:'Geist Mono',ui-monospace,monospace;font-size:13px;font-weight:500;color:var(--text);white-space:nowrap;
  font-variant-numeric:tabular-nums;text-align:right}
.fila.fuerte .fila-t,.fila.fuerte .fila-v{font-weight:700}
.fila.total{border-top-color:var(--border2)} .fila.total .fila-t,.fila.total .fila-v{font-weight:700}
.fila.total.gana .fila-v{color:var(--accent)} .fila.total.pierde .fila-v{color:var(--red-txt)}
.fila.apretada{padding:5px 0} .fila.alta{padding:12px 0;align-items:flex-start}
.lista-grupo{margin-top:12px;padding-bottom:4px}

/* La tabla v2: sin cebra, cifras a la derecha en Mono, un segundo renglón (.t-sub) en Geist, fila de total y la sub-fila
   «Qué hacer» a todo el ancho (tr.con-det + tr.fila-det > td[colspan] > .que-hacer). */
.tabla th.r,.tabla td.r{text-align:right}
.tabla td.num,.tabla td.r{font-family:'Geist Mono',ui-monospace,monospace;font-variant-numeric:tabular-nums}
.tabla td.r :is(button,.btn,.lnk,.pill,.tag){font-family:'Geist',ui-sans-serif,system-ui,sans-serif}   /* Mono es la cifra, no el botón de la celda */
.t-sub{display:block;font-family:'Geist',ui-sans-serif,system-ui,sans-serif;font-size:11.5px;line-height:15px;color:var(--text3);
  letter-spacing:0;white-space:nowrap;margin-top:2px;font-weight:400}
.t-sub.mono{font-family:'Geist Mono',ui-monospace,monospace}
.tabla tr.total td{font-weight:700} .tabla tr.total td:first-child{font-weight:800}
.tabla tr.con-det td{border-bottom:0}
.tabla tr.fila-det td{padding:0 12px 12px;white-space:normal}
.tabla.compacta th{padding:8px 10px} .tabla.compacta td{padding:6px 10px;font-size:12px}
.que-hacer{display:flex;align-items:flex-start;gap:10px;padding:10px 12px;border-radius:8px;background:var(--bg3)}
.que-hacer-l{font-size:10px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--text3);white-space:nowrap;margin-top:2px}
.que-hacer-x{font-size:12.5px;line-height:1.55;color:var(--text2);font-family:'Geist',ui-sans-serif,system-ui,sans-serif}
.que-hacer.warn{background:var(--yellow-dim)} .que-hacer.warn .que-hacer-l{color:var(--warn-txt)}
@media (max-width:768px){.tabla tr.fila-det .que-hacer{position:sticky;left:12px;max-width:calc(100vw - 72px)}}
/* Sin cebra: le gana a la del dashboard en oscuro (0,2,3) y en claro (0,3,4). */

/* Rótulo interno de un sub-bloque (10/800 MAYÚSCULA), con ícono o contador opcional. */
.rotulo{font-size:var(--fs-label);font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--text3);line-height:14px;
  display:flex;align-items:center;gap:8px}
.rotulo.sep{margin-top:var(--s-5);margin-bottom:var(--s-2)}

/* Fila de barra: nombre | barra | monto | %/pastilla (distribución, ranking, días, embudo). La barra es AVSAL_G.progreso. */
.barra-fila{display:grid;grid-template-columns:var(--bf-n,120px) minmax(0,1fr) auto;align-items:center;gap:12px;min-height:30px}
.barra-fila.con-extra{grid-template-columns:var(--bf-n,120px) minmax(0,1fr) auto auto}
.barra-fila>.g-prog{min-width:0}
.barra-fila>.bf-n{font-size:13px;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.barra-fila>.bf-v{font-family:'Geist Mono',ui-monospace,monospace;font-size:12.5px;font-weight:600;color:var(--text);
  text-align:right;min-width:var(--bf-v,84px);font-variant-numeric:tabular-nums}
.barra-fila>.bf-p{font-size:12px;color:var(--text3);text-align:right;min-width:56px}
.barra-fila.destacada>.bf-n{color:var(--accent);font-weight:600}
.barra-fila.baja{min-height:24px} .barra-fila.alta{min-height:34px}
.g-prog.mini{display:inline-block;width:64px;height:6px;border-radius:3px;vertical-align:middle}
.g-prog.grueso{height:12px;border-radius:4px} .g-prog.embudo{height:14px;border-radius:3px}
.g-prog.sin-pista{background:transparent}
.g-prog.derecha{display:flex;justify-content:flex-end;background:transparent}
.caida{font-size:12px;font-weight:600;margin:2px 0 6px calc(var(--bf-n,120px) + 12px)} .caida.warn{color:var(--warn-txt)} .caida.bad{color:var(--red-txt)}

/* La bala del CPA dentro de una celda: arriba la cifra (color de su zona) y «rec · techo», en medio la bala, abajo el ROAS. */
.cpa-celda{width:210px}
.cpa-top{display:flex;align-items:baseline;justify-content:space-between;gap:8px}
.cpa-v{font-family:'Geist Mono',ui-monospace,monospace;font-size:13px;font-weight:600;color:var(--text)}
.cpa-v.ok{color:var(--accent)} .cpa-v.warn{color:var(--warn-txt)} .cpa-v.bad{color:var(--red-txt)}
.cpa-ref{font-family:'Geist',ui-sans-serif,system-ui,sans-serif;font-size:11px;color:var(--text3);white-space:nowrap;letter-spacing:0}
.cpa-celda .g-auto{margin-top:3px}
.cpa-roas{font:500 11px/15px 'Geist Mono',ui-monospace,monospace;margin-top:1px}
.cpa-roas.ok{color:var(--accent)} .cpa-roas.bad{color:var(--red-txt)}

/* Leyenda: en la derecha de la cabecera de su sección o encima del gráfico. */
.leyenda{display:flex;flex-wrap:wrap;align-items:center;gap:8px 16px}
.leyenda.centro{justify-content:center}
.ley{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--text2);white-space:nowrap}
.ley>i{width:10px;height:10px;border-radius:3px;flex:none;background:var(--bar-main)}
.ley>i.z-esc{background:var(--accent-dim)} .ley>i.z-sos{background:var(--bg4)} .ley>i.z-pier{background:var(--red-dim)}
.ley>i.gana{background:var(--accent)} .ley>i.pierde{background:var(--red)} .ley>i.warn{background:var(--warn)}
.ley>i.info{background:var(--info)} .ley>i.tenue{background:var(--bar-soft)}
.ley>i.cat1{background:var(--cat-1)} .ley>i.cat2{background:var(--cat-2)} .ley>i.cat3{background:var(--cat-3)} .ley>i.cat4{background:var(--cat-4)} .ley>i.cat5{background:var(--cat-5)}
.ley>i.tick{width:2px;height:12px;border-radius:0;background:var(--text)}
/* Las líneas (5-oct, «Ver la tendencia»): la serie real en trazo lleno; lo proyectado o lo que todavía madura, punteado. */
.ley>i.linea{width:14px;height:2px;border-radius:1px;background:var(--text2)}
.ley>i.linea.gana{background:var(--accent)}
.ley>i.punteada{width:14px;height:0;border-radius:0;background:none;border-top:2px dashed var(--text2)}
.ley>i.raya{width:16px;height:0;border-radius:0;background:none;border-top:1.5px dashed currentColor}

/* Caja interior: el tono de fondo dentro de una sección (nunca borde ni sombra adentro de otra tarjeta). */
.caja{background:var(--bg3);border-radius:var(--radius);padding:14px 16px;min-width:0}
.caja.fila-accion{display:flex;align-items:center;gap:14px;min-height:64px;padding:10px 14px}
.caja.fila-accion>.pill-col{width:92px;flex:none}
.cajas{display:grid;grid-template-columns:repeat(var(--n,2),minmax(0,1fr));gap:12px}
.cajas.n3{--n:3} .cajas.n4{--n:4}
@media (max-width:768px){.cajas{grid-template-columns:1fr}}

/* La etiqueta de devolución (medida · esperada · mientras madura · heredada): ícono 12 + texto, segundo renglón de la celda. */
.dev-tag{display:inline-flex;align-items:center;gap:4px;font-size:11.5px;color:var(--text3);white-space:nowrap;
  font-family:'Geist',ui-sans-serif,system-ui,sans-serif;letter-spacing:0}
.dev-tag .t-ic{margin-right:0;color:inherit} .dev-tag .t-ic svg{width:12px;height:12px}

/* Formularios. El campo con su rótulo arriba (.campo, en grilla .campos) y el control suelto (.inp, se mudó de brujula.html con
   .fld y .search). `html :is(…).inp` le gana a input[type=text] del dashboard (0,1,1) y pierde, como antes, contra lo que
   Brújula ajusta por contexto (.search .inp, .cc-comp .box .inp…). Alto 36 en las dos apps (.inp.sm 30 · .inp.xs 28). */
.campo{display:flex;flex-direction:column;gap:6px;min-width:0}
.campo>label,.campo-l{font-size:var(--fs-label);font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--text3);line-height:14px;display:flex;align-items:center;justify-content:space-between;gap:8px}
.campo-x{text-transform:none;letter-spacing:0;font-weight:500}
.campo input:not([type=range]):not([type=checkbox]),.campo select,.campo textarea{width:100%;box-sizing:border-box;height:34px;padding:0 10px;border-radius:var(--radius-btn);background:var(--bg3);border:1px solid var(--border2);color:var(--text);font:inherit;font-size:13px;outline:none}
.campo textarea{height:auto;min-height:66px;padding:9px 11px;line-height:1.55;resize:vertical}
.campo input[inputmode=numeric],.campo input[type=number],.campo input.num{font-family:'Geist Mono',ui-monospace,monospace;font-variant-numeric:tabular-nums}
.campo :is(input,select,textarea):focus{border-color:var(--accent);box-shadow:0 0 0 2px rgba(var(--accent-rgb),.12)}
.campo.chico select,.campo.chico input{height:28px;font-size:12px}
.campos{display:grid;grid-template-columns:repeat(var(--n,3),minmax(0,1fr));gap:12px;align-items:end}
.campos.n2{--n:2} .campos.n4{--n:4}
@media (max-width:768px){.campos{grid-template-columns:1fr}}
.fld{display:grid;gap:6px}
.fld label{font-size:12px;font-weight:500;color:var(--text2)}
.fld .h{font-size:11.5px;color:var(--text3)}
html :is(input,select,textarea).inp{height:36px;width:100%;padding:0 12px;border-radius:9px;background:var(--bg3);border:1px solid var(--line2);outline:0;font-size:13px;color:var(--text);font-family:inherit}
html textarea.inp{height:auto;min-height:96px;padding:10px 12px;line-height:1.5;resize:vertical}
.inp:focus{border-color:var(--accent-line);box-shadow:0 0 0 3px var(--accent-soft)}
.inp.sm{height:30px;font-size:12.5px} .inp.xs{height:28px;padding:0 8px;font-size:12px}
.inp.cifra{font-family:'Geist Mono',ui-monospace,monospace;text-align:right;font-variant-numeric:tabular-nums}
/* 📱 El iPhone agranda la página al tocar un campo con letra de menos de 16 px, y no vuelve sola (4-oct): en pantallas táctiles
   todo campo va en 16. ⛔ Nunca bloquear el zoom (maximum-scale / user-scalable): es la causa, no el remedio. */
@media (pointer:coarse){input:not([type=checkbox]):not([type=radio]):not([type=range]):not([type=color]),select,textarea{font-size:16px!important}}
/* 👆 M-03 (tanda 6 de AVSAL Chat, 22-oct): en una pantalla táctil todo lo que se toca mide al menos 44 × 44 px (antes 30-32 y los enlaces 19:
   «Volver a la bandeja», «⋯», «Tomar», «Ir al chat», «Copiar el teléfono»). Solo en AVSAL Chat (#app, su cajón y su menú flotante): el
   dashboard ya sube sus botones a 42 en el celular a su manera. Con mouse nada cambia. */
@media (pointer:coarse){
  :is(#app,#drawer,#pop) :is(.ibtn,.btn-ico,.lado-cp){min-width:44px;min-height:44px}
  :is(#app,#drawer,#pop) :is(.btn.sm,.btn-sm,.btn-xs){min-width:44px;min-height:44px}
  :is(#app,#drawer,#pop) :is(.seg>button,.seg>a,.tabs>button,.tabs>a,.lnk,button.tag-t){min-height:44px}
  :is(#app,#drawer,#pop) :is(input,select,textarea).inp{min-height:44px}
  :is(#app,#drawer) :is(.nav-item,.nav-sub,.nav-group-hdr,.nav-app,.cc-mm button),#pop button{min-height:44px}
  /* Un enlace DENTRO de una frase no se vuelve un bloque de 44 (partía el renglón): sigue en la línea y su relleno agranda el toque sin mover el texto. */
  :is(#app,#drawer,#pop) :is(p,span,li)>.lnk{display:inline;min-height:0;padding-block:14px}
}
/* 🧭 El recorrido de globos anclados (M-39, tanda 8 de AVSAL Chat; AVSAL_UI.recorrido en avsal.js): un globo con su flecha junto a lo que hay que tocar,
   y eso mismo con un anillo verde. Sin ancla a la vista, el globo espera abajo al centro. */
.av-rec{position:fixed;z-index:1300;width:min(300px,calc(100vw - 24px));background:var(--bg2);border:1px solid var(--accent-line);border-radius:12px;
  box-shadow:var(--modal-shadow);padding:14px 16px 12px;color:var(--text);font-size:13px}
.av-rec::before{content:'';position:absolute;width:12px;height:12px;background:var(--bg2);border:1px solid var(--accent-line);transform:rotate(45deg)}
.av-rec[data-lado="abajo"]::before{top:-7px;left:calc(var(--rec-x,24px) - 6px);border-right:0;border-bottom:0}
.av-rec[data-lado="arriba"]::before{bottom:-7px;left:calc(var(--rec-x,24px) - 6px);border-left:0;border-top:0}
.av-rec[data-lado="der"]::before{left:-7px;top:calc(50% - 6px);border-top:0;border-right:0}
.av-rec.sin-ancla{left:50%;bottom:24px;transform:translateX(-50%)}
.av-rec.sin-ancla::before{display:none}
.av-rec-n{font:500 12px 'Geist Mono',ui-monospace,monospace;color:var(--text3);margin-bottom:4px}
.av-rec-t{display:block;font-size:14px;font-weight:700;line-height:1.35;margin-bottom:4px}
.av-rec-x{margin:0 0 12px;font-size:13px;line-height:1.5;color:var(--text2)}
.av-rec-acc{display:flex;justify-content:flex-end;gap:8px}
html .av-rec-foco{outline:2px solid var(--accent);outline-offset:3px;border-radius:8px}
@media (prefers-reduced-motion:no-preference){.av-rec:not(.sin-ancla){animation:av-rec-in var(--dur) var(--ease-out)}}
@keyframes av-rec-in{from{opacity:0;translate:0 4px}to{opacity:1;translate:0 0}}
/* ♿ Solo para el lector de pantalla (M-31, tanda 8): el título de una vista sin cabecera visible (Chats) sigue siendo su H1. */
.solo-lector{position:absolute!important;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}
/* ♿ M-28 (tanda 8 de AVSAL Chat, 22-oct): el foco SE VE para quien usa el teclado (Tab), en los botones, el menú, las pestañas, las filas
   de chat, los enlaces y los interruptores. `.btn` trae `outline:none` y el campo `.inp`, `outline:0`: esta regla va DESPUÉS y gana por
   orden. Con el mouse no aparece (:focus-visible). El dashboard ya lo pinta con su `*:focus-visible{…!important}`: para él no cambia nada. */
:where(.btn,.nav-item,.nav-sub,.nav-group-hdr,.nav-app,.tabs>button,.tabs>a,.seg>button,.seg>a,.ci,.lnk,.ibtn,.tgl,[role=tab],[role=switch],[role=button],summary):focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* El campo de AVSAL Chat enfocado: su borde en el verde entero y el halo más firme (antes 35 % y 12 %: con el teclado casi no se veía dónde estabas). */
:is(#app,#drawer,#pop) :is(input,select,textarea).inp:focus-visible{border-color:var(--accent);box-shadow:0 0 0 3px rgba(var(--accent-rgb),.22)}
/* 🔠 M-30 (tanda 8): en AVSAL Chat lo que se LEE va a 12 px como mínimo (pastillas, «hace X min», el globo); 11 px y menos queda solo para los
   rótulos en MAYÚSCULA y 800. Solo en AVSAL Chat (#app, su cajón y su menú flotante): el dashboard no cambia. */
:is(#app,#drawer,#pop) .pill{font-size:12px;height:22px}
:is(#app,#drawer,#pop) .pill.lg{font-size:12.5px;height:26px}
:is(#app,#drawer,#pop) :is(.fresco,.store-pill-sub,.dev-tag,.fld .h,.tm-hd span,.salud-chip,.tabs .c,.btn .c,.acord-m,.ci-q-pop){font-size:12px}
:is(#app,#drawer,#pop) .nav-badge.soon{font-size:10px}
.search{position:relative}
.search>svg,.search svg.i{position:absolute;left:11px;top:50%;transform:translateY(-50%);color:var(--text3);pointer-events:none}
.search>svg:not(.i){width:15px;height:15px;stroke:currentColor;fill:none;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.search .inp{padding-left:34px}

/* Acordeón de pasos (Ruta de lanzamiento, Integraciones): círculo de estado + título + tiempo + chevron; abierto, el cuerpo con
   sangría 30. Brújula conserva su .paso propio (por eso este se llama .acord). */
.acord{display:flex;flex-direction:column}
.acord-paso{border-top:1px solid var(--border)}
.acord-paso:first-child{border-top:0}
.acord-hd{display:flex;align-items:center;gap:12px;width:100%;min-height:44px;padding:10px 0;background:none;border:0;font:inherit;text-align:left;color:var(--text);cursor:pointer;flex-wrap:wrap}
.acord-ck{width:18px;height:18px;border-radius:50%;border:1.5px solid var(--border2);display:grid;place-items:center;flex:none;color:var(--accent-ink)}
.acord-ck svg{width:11px;height:11px;stroke:currentColor;stroke-width:2.6;fill:none;stroke-linecap:round;stroke-linejoin:round}
.acord-paso.ok .acord-ck{background:var(--accent);border-color:var(--accent)}
.acord-paso.sig:not(.ok) .acord-ck{border-color:var(--warn)}
.acord-t{flex:1;min-width:0;display:flex;align-items:center;gap:8px;font-size:14px;font-weight:600;line-height:20px}
.acord-t .t-ic{color:var(--text3)}
.acord-paso.ok .acord-t{color:var(--text2)}
.acord-m{font:500 11.5px/1 'Geist Mono',ui-monospace,monospace;color:var(--text3);white-space:nowrap}
.acord-chev{width:28px;height:28px;border-radius:7px;display:flex;align-items:center;justify-content:center;color:var(--text3);flex:none;transition:transform var(--dur) var(--ease)}
.acord-chev svg{width:16px;height:16px;stroke:currentColor;stroke-width:2;fill:none;stroke-linecap:round;stroke-linejoin:round}
.acord-hd:hover .acord-chev{background:rgba(var(--ink-rgb),.05);color:var(--text)}
.acord-paso.on .acord-chev{transform:rotate(180deg)}
.acord-hd:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:6px}
.acord-body{display:none;padding:0 0 14px 30px}
.acord-paso.on .acord-body{display:block}
.acord-x{margin:0;font-size:12.5px;line-height:1.55;color:var(--text2)}
.acord-acciones{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:10px}
/* 💳 Selector de modelo de pago: gana a los destinos del menú (.nav-item/.nav-sub/.nav-app). */
body.modo-tarjeta .solo-cod{display:none}
body:not(.modo-tarjeta) .solo-tarjeta{display:none}
@media print{.acord-paso .acord-body{display:block}}
@media (max-width:768px){.acord-body{padding-left:0}}
