/* ============================================================
   IEB Internacional — Tema "MERIDIAN" (onyx editorial)
   ------------------------------------------------------------
   Capa de tema. NO toca app.js: usa las mismas clases.
   Reemplaza el look "Aurora/Luxe" (vidrio, gradientes, blobs,
   destellos, redondeos) por un negro cálido editorial: reglas
   finas en oro, titulares serif, esquinas rectas, cero efectos.

   INSTALACIÓN: en index.html, cargar ESTE archivo DESPUÉS de
   styles.css —
       <link rel="stylesheet" href="styles.css?v=20260624" />
       <link rel="stylesheet" href="grm-meridian.css?v=1" />
   Para volver al tema anterior: quitar esa línea.
   ============================================================ */

/* ============================================================
   TOKENS POR TEMA — el usuario elige con el selector del header
   (data-theme en <html>; lo fija theme-init.js antes de pintar).
   3 paletas, todas con el ORO de marca:
     onyx  = actual (negro cálido editorial)
     black = obsidiana (negro puro)
     ivory = marfil (claro, papel)
   Las esquinas rectas / sin sombras son comunes a las 3 (Meridian).
   ============================================================ */
:root{
  /* Opción C — esquinas suaves + sombras sutiles en TODA la app (pedido del dueño). */
  --r:16px; --r-lg:18px; --r-pill:999px;
  --blur:none;
  --shadow:0 18px 44px -22px rgba(0,0,0,.72); --shadow-lg:0 30px 60px -26px rgba(0,0,0,.80);
  /* --- ESCALA TIPOGRÁFICA (T1): 9 pasos. Migrados los roles más visibles; el resto de los
     tamaños ad-hoc queda por migrar en un pase mecánico posterior. --- */
  --fs-2xs:10px; --fs-xs:11px; --fs-sm:12px; --fs-base:13.5px; --fs-md:15px;
  --fs-lg:18px; --fs-xl:22px; --fs-2xl:28px; --fs-display:34px;
  /* --- TRACKING (T3): 3 niveles fijos --- */
  --track-tight:.04em; --track:.08em; --track-wide:.14em;
  /* --- ESPACIADO 4pt (E1) --- */
  --sp-1:4px; --sp-2:8px; --sp-3:12px; --sp-4:16px; --sp-6:24px; --sp-8:32px;
  /* --- radio de controles chicos (K3, opcional) --- */
  --r-sm:10px;
}
/* --- 1 · ONYX (actual) --- */
:root, html[data-theme="onyx"]{
  --gold:#E0C078; --gold-deep:#C8A86A;
  --ink:#ECE5D5; --grey-warm:#A0977F; --ivory:#15140F; /* muted subido de #8C846F → ~6.3:1 sobre el fondo (AA con margen) */
  --card:rgba(255,255,255,.030); --panel:rgba(255,255,255,.022);
  --line:rgba(224,192,120,.16); --stroke:rgba(224,192,120,.20);
  --app-bg:#15140F; --chrome-bg:#1B1A14; --float-bg:#1B1A14;
  --field-bg:rgba(255,255,255,.02); --option-bg:#1B1A14; --menu-bg:#1B1A14;
  --on-gold:#1a1206;
  --pos:#6FC28C; --neg:#E58E80;   /* verde/rojo SOLO para G/P de tenencias */
  --gold-text:var(--gold);        /* oro TIPOGRÁFICO (texto <18px) — sobre oscuro = el oro de marca */
  --ok:#6FC28C; --warn:#E0A07A; --info:#8FB0D8;  /* semántica de estado (tags/perfiles/urgencias) */
}
/* --- 2 · OBSIDIANA (negro puro) --- */
html[data-theme="black"]{
  --gold:#E6C77E; --gold-deep:#CDA95F;
  --ink:#F2F0EC; --grey-warm:#8C8A85; --ivory:#070708;
  --card:rgba(255,255,255,.026); --panel:rgba(255,255,255,.018);
  --line:rgba(230,199,126,.15); --stroke:rgba(230,199,126,.20);
  --app-bg:#070708; --chrome-bg:#101012; --float-bg:#121214;
  --field-bg:rgba(255,255,255,.026); --option-bg:#121214; --menu-bg:#141416;
  --on-gold:#0A0A0B;
  --pos:#6FC28C; --neg:#E58E80;
  --gold-text:var(--gold);
  --ok:#6FC28C; --warn:#E0A07A; --info:#8FB0D8;
}
/* --- 3 · MARFIL (claro / papel) — oro más profundo para legibilidad sobre blanco --- */
html[data-theme="ivory"]{
  --gold:#B0883A; --gold-deep:#8A6A2A;
  /* oro TIPOGRÁFICO más profundo: #7E6230 ≈4.9:1 sobre el fondo/paneles claros (AA). El --gold (#B0883A)
     queda SOLO para filetes/bordes/swatches/reglas, donde brilla sin tener que leerse. */
  --gold-text:#7E6230;
  --ok:#1a7a3a; --warn:#9A5A3A; --info:#3A5E8C;  /* legibles sobre blanco (≥4.5:1) */
  --ink:#262219; --grey-warm:#6C6353; --ivory:#F4F0E6;  /* muted subido de #7C7363 (~4.0:1) → #6C6353 (~4.9:1, AA) */
  --card:rgba(40,30,10,.045); --panel:#FFFFFF;
  --line:rgba(140,106,46,.26); --stroke:rgba(140,106,46,.34);
  --app-bg:#F1EDE2; --chrome-bg:#FBF9F2; --float-bg:#FFFFFF;
  --field-bg:#FFFFFF; --option-bg:#FFFFFF; --menu-bg:#FFFFFF;
  --on-gold:#2A2012;
  --pos:#2E7D46; --neg:#B23A2E;   /* más oscuros: legibles sobre blanco */
  /* sombra más suave/cálida sobre fondo claro (la oscura quedaría muy marcada en Marfil) */
  --shadow:0 16px 40px -24px rgba(70,55,30,.20); --shadow-lg:0 26px 56px -28px rgba(70,55,30,.26);
}

/* ---- fondo plano: anula gradientes / cream de Aurora+Luxe ---- */
html{ background:var(--app-bg) !important; }
body{
  background:var(--app-bg) !important;
  color:var(--ink);
}

/* ---- ambiente del fondo: el resplandor del cursor queda SIEMPRE apagado (pedido); aurora/grano los
   gobierna el nivel de movimiento (Ajustes → Apariencia): visibles en "Completo", atenuados en "Sobrio",
   ocultos en "Mínimo". Ver la "CAPA DE MOVIMIENTO" al final de este archivo. ---- */
.lux-cursor{ display:none !important; }
/* La capa ambiente (aurora/grano) está pintada para fondo OSCURO: sobre Marfil/Daylight se filtraba como una
   mancha gris difusa entrando por el borde izquierdo. Se apaga en los temas claros. */
html[data-theme="ivory"] .lux-bg, html[data-theme="ivory"] .lux-grain,
html[data-theme="daylight"] .lux-bg, html[data-theme="daylight"] .lux-grain{ display:none !important; }
html[data-motion="minimo"] .lux-bg, html[data-motion="minimo"] .lux-grain{ display:none !important; }
html[data-motion="sobrio"] .lux-grain{ display:none !important; }
html[data-motion="sobrio"] .lux-bg{ opacity:.45 !important; }
html[data-motion="sobrio"] .lux-bg i{ animation-duration:120s !important; }

/* ---- barras: vidrio claro -> negro con filete dorado ---- */
/* OPACAS: el header es sticky; sin opacidad, el contenido se ve por detrás al hacer scroll. */
.nx-header, .nx-footer, .acct-bar{
  background:var(--chrome-bg) !important;
  -webkit-backdrop-filter:none !important;
  backdrop-filter:none !important;
  box-shadow:none !important;
}
.summary-strip{ background:transparent !important; -webkit-backdrop-filter:none !important; backdrop-filter:none !important; box-shadow:none !important; }

/* ---- tarjetas / paneles: esquinas suaves + sombra sutil (Opción C) ---- */
.kpi, .table-card, .info-section, .bal-card, .group-card, .empty-state,
.side-nav, .acct-chip, .perf-card, .refresh-card, .modal, .login-card,
.gsearch-panel, .toast{
  background:var(--panel) !important;
  -webkit-backdrop-filter:none !important;
  backdrop-filter:none !important;
  box-shadow:var(--shadow) !important;
  border:1px solid var(--line) !important;
  border-radius:var(--r) !important;
}
.acct-chip{ border-radius:var(--r) !important; }
/* Superficies FLOTANTES (se apoyan sobre el contenido): fondo opaco + radio mayor + sombra más marcada. */
.modal, .login-card, .asst-win, .tasks-panel, .gsearch-box{ background:var(--float-bg) !important; border-radius:var(--r-lg) !important; box-shadow:var(--shadow-lg) !important; }

/* ---- sin micro-rebotes ni reveals (tema calmo) ---- */
.kpi, .bal-card, .group-card, .perf-card{ transition:border-color .15s ease !important; }
.kpi:hover, .bal-card:hover, .group-card:hover, .perf-card:hover{
  transform:none !important;
  box-shadow:var(--shadow) !important;
  border-color:var(--gold-deep) !important;
}
/* Estas supresiones del look "plano editorial" ahora SOLO aplican en "Mínimo" (o reduced-motion):
   en Completo/Sobrio vuelven el hover de botones, el reveal al scrollear y el dibujado del donut. */
html[data-motion="minimo"] .btn-primary:hover, html[data-motion="minimo"] .btn-secondary:hover, html[data-motion="minimo"] .btn-danger:hover,
html[data-motion="minimo"] .link-groups-btn:hover, html[data-motion="minimo"] .back-btn:hover, html[data-motion="minimo"] .link-btn:hover{ transform:none !important; }
html[data-motion="minimo"] .aurora-reveal, html[data-motion="minimo"] .aurora-reveal.in{ opacity:1 !important; animation:none !important; transform:none !important; }
html[data-motion="minimo"] .donut .dseg{ transition:none !important; }

/* ---- monograma tipográfico: oro plano, sin gradiente de texto ni glow ---- */
.grm-word{
  background:none !important;
  -webkit-text-fill-color:var(--ink) !important;
  color:var(--ink) !important;
  -webkit-background-clip:border-box !important;
  background-clip:border-box !important;
  filter:none !important;
  animation:none !important;
}
.grm-dot{ color:var(--gold) !important; }
.login-brand .grm-word{ animation:none !important; filter:none !important; }

/* ---- cifras grandes: serif editorial, sin "sheen" dorado animado ---- */
.kpi .k-value, .bal-card .bv, .perf-card .perf-value{
  background:none !important;
  -webkit-text-fill-color:var(--ink) !important;
  color:var(--ink) !important;
  -webkit-background-clip:border-box !important;
  background-clip:border-box !important;
  animation:none !important;
  font-family:var(--serif) !important;
  font-weight:400 !important;
}

/* ---- botón primario: oro pleno y plano (sin barrido de luz) ---- */
.btn-primary{
  background:var(--gold) !important;
  border:1px solid var(--gold) !important;
  color:var(--on-gold) !important;
  box-shadow:none !important;
  border-radius:var(--r) !important;
}
.btn-primary::after{ display:none !important; }
.btn-secondary, .btn-danger, .link-groups-btn, .back-btn, .link-btn, .more-btn,
.lm-new button{ border-radius:var(--r) !important; }

/* ---- inputs / selects: rectos, sin vidrio ---- */
.search-box input, .toolbar select, .period-sel, .ge-search, .ge-name,
.lm-new input, .modal input, .login-input{
  border-radius:var(--r) !important;
  -webkit-backdrop-filter:none !important;
  backdrop-filter:none !important;
  background:var(--field-bg) !important;
  color:var(--ink) !important;
}

/* ---- badges / tags / pills -> rectángulos sobrios ---- */
.cust-badge, .tag, .badge, .brand-pill, .member-chip, .role-badge,
.user-role, .tag-cash, .tag-conc, .tag-margin, .tag-in, .tag-out, .tag-mat{
  border-radius:var(--r-pill) !important;
}

/* ---- regla dorada de secciones: barra sólida (no degradé) ---- */
.gold-line::before, .panel h2::before, .list-title h1::before,
.sec-title::before, .modal-h::before{
  background:var(--gold) !important;
  width:48px !important;
  height:2px !important;
}

/* ---- nav: subrayado dorado simple (sin animación de crecer) ---- */
.nx-nav-item::after{ display:none !important; }
.nx-nav-item.active{ border-bottom-color:var(--gold) !important; }

/* ---- fila de tabla: hover quieto con filete dorado a la izquierda ---- */
.nx-table tbody tr:hover{ box-shadow:inset 2px 0 0 var(--gold) !important; }

/* ---- impresión: papel blanco, tinta negra ---- */
@media print{
  html, body{ background:#fff !important; }
  .kpi .k-value, .bal-card .bv, .perf-card .perf-value, .grm-word{
    -webkit-text-fill-color:#15140F !important; color:#15140F !important;
  }
}

/* ============================================================
   TENENCIAS — G/P No Realizada en VERDE (positivo) / ROJO (negativo).
   Excepción puntual a la convención "sin rojo/verde": solo esta
   columna (clase .gl-sign), pedido del dueño. El resto sigue neutro.
   Vence a la regla .nx-table td.num.pos/.neg{color:var(--ink)}.
   ============================================================ */
.nx-table td.gl-sign.pos, .nx-table td.gl-sign.pos *{ color:var(--pos) !important; }
.nx-table td.gl-sign.neg, .nx-table td.gl-sign.neg *{ color:var(--neg) !important; }
@media print{
  .nx-table td.gl-sign.pos, .nx-table td.gl-sign.pos *{ color:#1f7a3a !important; }
  .nx-table td.gl-sign.neg, .nx-table td.gl-sign.neg *{ color:#a83228 !important; }
}

/* ============================================================
   SELECTOR DE TEMA — 3 swatches en el header (a simple vista).
   Cada uno muestra el fondo del tema + una esquina dorada.
   ============================================================ */
.theme-switch{display:inline-flex;align-items:center;gap:5px;margin:0;flex:0 0 auto}
.thsw{width:18px;height:18px;border-radius:50%;border:1px solid var(--line);cursor:pointer;padding:0;
  position:relative;overflow:hidden;transition:transform .12s ease,border-color .15s ease;flex:0 0 auto}
.thsw::after{content:"";position:absolute;right:-2px;bottom:-2px;width:10px;height:10px;border-radius:50%;background:var(--sw-gold)}
@media (hover:hover) and (pointer:fine){ .thsw:hover{transform:translateY(-1px);border-color:var(--gold-deep)} }
.thsw:active{transform:scale(.97)}
.thsw.on{border-color:var(--gold);box-shadow:0 0 0 2px var(--gold) inset}
.thsw-onyx{background:#15140F;--sw-gold:#E0C078}
.thsw-black{background:#070708;--sw-gold:#E6C77E}
.thsw-ivory{background:#F1EDE2;--sw-gold:#B0883A}
/* La regla `@media (max-width:760px){ .theme-switch{display:none} }` se ELIMINÓ (2026-07-17): existía para
   descomprimir el HEADER en mobile, donde vivían los swatches. Ahora el selector vive SOLO en Ajustes →
   Apariencia, así que esa regla lo volvía imposible de cambiar desde el celular. No re-agregarla sin scopearla
   (`.nx-header-right .theme-switch`). */

/* ============================================================
   MARFIL — afinados de legibilidad sobre claro (tonos que la capa
   ONYX de styles.css había aclarado para fondo oscuro). El resto
   de los colores usa var(--ink)/var(--grey-warm) → ya se adaptan.
   ============================================================ */
html[data-theme="ivory"] .tag-mat{color:var(--warn);border-color:#C2A45E}
/* Los tags/perfiles/urgencias YA consumen --warn/--ok/--neg por tema (ver bloque "TOKENS SEMÁNTICOS"
   abajo) → los overrides manuales de Marfil que había acá desaparecieron. */
html[data-theme="ivory"] .login-error{color:#8A4A2A !important;background:rgba(168,106,72,.10) !important;border-color:rgba(154,90,58,.35) !important}
html[data-theme="ivory"] *::-webkit-scrollbar-thumb{background:rgba(140,106,46,.30)}
/* el QR de TOTP ya va sobre fondo blanco; en Marfil el panel es blanco → borde visible */
html[data-theme="ivory"] .totp-qr svg{border-color:var(--line)}

/* ============================================================
   MIGRACIÓN SISTÉMICA (auditoría 2026-07-01)
   Todo lo que sigue vence a styles.css (meridian carga última).
   ============================================================ */
/* --- ÍCONOS SVG inline: alineación con el texto del botón/link --- */
.icn{ display:inline-block; vertical-align:-.18em; flex:0 0 auto; }
.nx-icon-btn .icn, .nx-home .icn, .thsw .icn{ vertical-align:middle; }

/* --- C1 · ORO TIPOGRÁFICO (--gold-text): texto dorado <18px legible en todos los temas.
   El --gold (#B0883A en Marfil) fallaba AA como texto; --gold-text lo resuelve por tema. --- */
.ov-seeall, .prod-edit, .asst-link, .mkt-chev, .tp-meta.soon, .set-ok, .vr-filled,
.na-all, .na-cta, .filter-chip, .chip-link, .msg-att, .cost-add, .cost-manual,
a.filter-chip, .lm-new button, .tag.tag-cash{ color:var(--gold-text) !important; }
.cli-statline .si b:hover, .acct-menu-item:hover, .ov-seeall:hover, .prod-edit:hover,
.na-all:hover, .na-row:hover .na-cta, .asst-chip:hover, .asst-link:hover,
.dp-cap b, .dp-cap:hover b{ color:var(--gold-text) !important; }
/* el hover "sube" al oro brillante en oscuro; en Marfil --gold-deep sigue legible */
html:not([data-theme="ivory"]) .ov-seeall:hover, html:not([data-theme="ivory"]) .prod-edit:hover{ color:var(--gold) !important; }

/* --- C2 · MERCADOS con tokens (--pos/--neg), calibrados por tema. Borra los hex de fondo-oscuro. --- */
.mkt-up .mkt-chg, .mkt-ti.mkt-up .tv{ color:var(--pos) !important; }
.mkt-down .mkt-chg, .mkt-ti.mkt-down .tv{ color:var(--neg) !important; }
.mkt-up{ border-color:color-mix(in srgb, var(--pos) 34%, var(--line)) !important; }
.mkt-down{ border-color:color-mix(in srgb, var(--neg) 34%, var(--line)) !important; }

/* --- C3 · SEMÁNTICA DE ESTADO por token (tags/perfiles/urgencias) --- */
.tag-in, .rp-conservador{ color:var(--ok) !important; }
.tag-margin, .rp-agresivo, .tp-meta.over{ color:var(--warn) !important; }
.rp-moderado{ color:var(--gold-text) !important; }

/* --- T1 · escala tipográfica en los roles más visibles --- */
.kpi .k-label{ font-size:var(--fs-2xs); letter-spacing:var(--track-wide); }
.kpi .k-value{ font-size:var(--fs-2xl); }
.nx-table thead th{ font-size:var(--fs-2xs); letter-spacing:var(--track-wide); }
.list-title h1{ font-size:var(--fs-2xl); }
.panel h2{ font-size:var(--fs-xl); }
.sec-title, .info-section .sec-title{ font-size:var(--fs-lg); }
.bal-card .bl, .metric .ml{ font-size:var(--fs-2xs); }
.bal-card .bv{ font-size:var(--fs-xl); }
.btn-primary, .btn-secondary, .btn-danger, .link-groups-btn, .back-btn, .link-btn,
.nx-hdr-btn{ letter-spacing:var(--track); }
.cust-badge, .tag, .badge{ letter-spacing:var(--track-tight); }

/* --- C4 · grises del statement (AA en pantalla y en print) --- */
.st-kv .k, .st-sub, .st-note, .st-disc{ color:#6E6657; }
.st-disc{ font-size:10.5px; }

/* --- T2 · cifras hero en Plex (Libre Caslon no trae tabular-nums → los millones "respiraban").
   La cifra va en Plex 400 con tnum; el label/moneda quedan en su tipografía. --- */
.kpi .k-value, .bal-card .bv, .perf-card .perf-value{
  font-family:var(--sans) !important; font-weight:400 !important; font-variant-numeric:tabular-nums !important;
}

/* --- E1 · espaciado 4pt en las tarjetas/gaps principales --- */
.kpis{ gap:var(--sp-4); }
.kpi{ padding:var(--sp-6); }
.bal-cards{ gap:var(--sp-4); }
.bal-card{ padding:var(--sp-4) var(--sp-4); }

/* --- K3 · radio de controles chicos (inputs/selects/icon-btns/menu-items ≤36px) --- */
.search-box input, .toolbar select, .period-sel, .lm-new input, .lm-new button,
.acct-menu-item, .txdd-item, .nr-add, .tp-filter, .tp-iconbtn{ border-radius:var(--r-sm) !important; }

/* --- L1 · pulso del badge de mensajes tokenizado con --neg (antes rgba rojo hardcodeado) --- */
/* 2026-09-20: el pulso infinito se saca (el punto ya indica que hay algo sin leer y latía toda la jornada).
   Ahora un destello corto SOLO cuando el contador sube — app.js pone .bump al detectar el cambio. */
html:not([data-motion="minimo"]) .msg-badge.bump{ animation:fxBadgeBump .4s var(--ease-out); }
@keyframes fxBadgeBump{ 0%{ transform:scale(1) } 35%{ transform:scale(1.26) } 100%{ transform:scale(1) } }
@keyframes fxPulseTok{
  0%{ box-shadow:0 0 0 0 color-mix(in srgb, var(--neg) 55%, transparent); }
  70%{ box-shadow:0 0 0 7px color-mix(in srgb, var(--neg) 0%, transparent); }
  100%{ box-shadow:0 0 0 0 color-mix(in srgb, var(--neg) 0%, transparent); }
}

/* --- M1 · burbuja del asistente: círculo sobrio (--panel + borde oro), sin gradiente fintech --- */
.asst-bubble{ background:var(--float-bg) !important; color:var(--gold-text) !important;
  border:1px solid var(--gold-deep) !important; box-shadow:var(--shadow) !important; }
.asst-bubble .icn, .asst-bubble svg{ color:var(--gold-text); }

/* Contenido disponible para lectores de pantalla sin alterar la composición visual. */
.a11y-only{ position:absolute !important; width:1px !important; height:1px !important; padding:0 !important; margin:-1px !important; overflow:hidden !important; clip:rect(0,0,0,0) !important; white-space:nowrap !important; border:0 !important; }

/* --- UX-23 · header responsive: colapsar el cluster derecho en pantallas chicas --- */
@media (max-width:900px){
  /* el wordmark cede espacio; el ícono de casita y el ☰ mandan */
  .grm-word{ font-size:var(--fs-lg); letter-spacing:.10em; }
  .nx-header{ gap:10px; }
  .nx-header-right{ gap:8px; }
  /* búsqueda · mensajes · ajustes · salir quedan como íconos; el chip de usuario se reduce al nombre (sin rol) */
  .user-chip .user-role{ display:none; }
  .user-chip{ max-width:96px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
}
@media (max-width:620px){
  /* muy angosto: el wordmark se reduce al monograma "G" y se sueltan los botones de acción del header
     (Aviso/Transferencia ya viven en el sidebar) para que nada se solape */
  .nx-header-actions{ display:none; }
  .user-chip{ display:none; }
  .nx-header-left{ gap:12px; }
}

/* ============================================================
   StoneX — 2 TEMAS NUEVOS (Spectrum oscuro · Daylight claro)
   Mismos nombres de variables que onyx/black/ivory → re-skin total.
   + firma "spectrum": la regla dorada de sección pasa a degradé
   multicolor, y un filete multicolor arriba del header.
   ============================================================ */
html[data-theme="spectrum"]{
  --gold:#5E84C4; --gold-deep:#45689F;
  --ink:#E6EAF0; --grey-warm:#8794A6; --ivory:#1A2230;
  --card:rgba(255,255,255,.04); --panel:#222C3C;
  --line:rgba(255,255,255,.08); --stroke:rgba(255,255,255,.12);
  --app-bg:#1A2230; --chrome-bg:#141A26; --float-bg:#222C3C;
  --field-bg:rgba(255,255,255,.05); --option-bg:#222C3C; --menu-bg:#222C3C;
  --on-gold:#141A26;
  --pos:#5BB06A; --neg:#E07868;
  --gold-text:#7FA6D8; --ok:#5BB06A; --warn:#D89A5A; --info:#7FA6D8;
}
html[data-theme="daylight"]{
  --gold:#345B9B; --gold-deep:#284B85;
  --ink:#1B2330; --grey-warm:#6B7686; --ivory:#F4F6F9;
  --card:rgba(20,35,60,.03); --panel:#FFFFFF;
  --line:rgba(27,35,48,.10); --stroke:rgba(27,35,48,.16);
  --app-bg:#F4F6F9; --chrome-bg:#FFFFFF; --float-bg:#FFFFFF;
  --field-bg:#FFFFFF; --option-bg:#FFFFFF; --menu-bg:#FFFFFF;
  --on-gold:#FFFFFF;
  --pos:#2E8B57; --neg:#C24536;
  --gold-text:var(--gold-deep); --ok:#1a7a3a; --warn:#9A5A3A; --info:#284B85;
  --shadow:0 16px 40px -24px rgba(30,45,75,.20); --shadow-lg:0 26px 56px -28px rgba(30,45,75,.26);
}
/* firma StoneX: regla de sección en degradé multicolor */
html[data-theme="spectrum"] .gold-line::before, html[data-theme="spectrum"] .panel h2::before,
html[data-theme="spectrum"] .list-title h1::before, html[data-theme="spectrum"] .sec-title::before,
html[data-theme="spectrum"] .modal-h::before,
html[data-theme="daylight"] .gold-line::before, html[data-theme="daylight"] .panel h2::before,
html[data-theme="daylight"] .list-title h1::before, html[data-theme="daylight"] .sec-title::before,
html[data-theme="daylight"] .modal-h::before{
  background:linear-gradient(90deg,#3E6DB5,#2C9C8E,#5BA85C,#D9B23F,#DD8A3C,#C8503E)!important;
  width:46px!important; height:3px!important;
}
/* filete multicolor arriba del header */
html[data-theme="spectrum"] .nx-header, html[data-theme="daylight"] .nx-header{ position:relative; }
html[data-theme="spectrum"] .nx-header::after, html[data-theme="daylight"] .nx-header::after{
  content:""; position:absolute; left:0; right:0; top:0; height:3px; pointer-events:none;
  background:linear-gradient(90deg,#3E6DB5,#2C9C8E,#5BA85C,#D9B23F,#DD8A3C,#C8503E);
}
/* swatches del selector (header) */
.thsw-spectrum{background:#1A2230;--sw-gold:#5E84C4}
.thsw-daylight{background:#F4F6F9;--sw-gold:#345B9B}

/* ============================================================================
   CAPA DE MOVIMIENTO — efectos gobernados por html[data-motion] (Ajustes → Apariencia)
   Completo (full) = todo · Sobrio = sutil · Mínimo = nada. Respeta prefers-reduced-motion.
   ============================================================================ */

/* prefers-reduced-motion del sistema: apaga todo lo de esta capa, pase lo que pase. */
@media (prefers-reduced-motion: reduce){
  #view.view-enter, .fx-skel-ln, .msg-badge, .fx-progress::before, .toast{ animation:none !important; }
  #view.view-enter{ opacity:1 !important; transform:none !important; }
}

/* ---- 1 · Entrada de vista (fundido + leve ascenso en Completo; solo fundido en Sobrio) ---- */
/* 2026-09-20: de 500ms a 180ms, y app.js ya no la dispara al cambiar de pestaña dentro de la misma cuenta. */
html[data-motion="full"] #view.view-enter{ animation:fxViewEnter var(--dur-ui) var(--ease-out) both; }
html[data-motion="sobrio"] #view.view-enter{ animation:fxViewFade var(--dur-ui) var(--ease-out) both; }
@keyframes fxViewEnter{ from{ opacity:0; transform:translateY(10px); } to{ opacity:1; transform:none; } }
@keyframes fxViewFade{ from{ opacity:0; } to{ opacity:1; } }

/* ---- 2 · Stagger más calmo en Sobrio (sin escalonar) ---- */
html[data-motion="sobrio"] .aurora-reveal{ animation-delay:0s !important; }

/* ---- 3 · Hover lift en tarjetas/KPIs y tarjetas clickeables (Completo + Sobrio) ---- */
html:not([data-motion="minimo"]) .kpi,
html:not([data-motion="minimo"]) .clickable-card,
html:not([data-motion="minimo"]) .group-card,
html:not([data-motion="minimo"]) .lift{ transition:transform .26s var(--ease-out), box-shadow .26s, border-color .26s !important; }
html:not([data-motion="minimo"]) .kpi:hover,
html:not([data-motion="minimo"]) .clickable-card:hover,
html:not([data-motion="minimo"]) .group-card:hover,
@media (hover:hover) and (pointer:fine){
html:not([data-motion="minimo"]) .lift:hover{ transform:translateY(-4px) !important; box-shadow:var(--shadow-lg) !important; }
}

/* ---- 4 · Botón primario: barrido de oro al hover + reseteo suave del magnético ---- */
html:not([data-motion="minimo"]) .btn-primary{ position:relative; overflow:hidden; transition:transform var(--dur-press) var(--ease-out), box-shadow var(--dur-ui) ease, filter var(--dur-ui) ease; }
html:not([data-motion="minimo"]) .btn-primary::after{
  content:"" !important; display:block !important; position:absolute; top:0; left:-130%; width:55%; height:100%; transform:skewX(-20deg);
  background:linear-gradient(90deg, transparent, rgba(255,255,255,.45), transparent); pointer-events:none; }
html:not([data-motion="minimo"]) .btn-primary:hover::after{ animation:fxSheen .75s ease; }
@keyframes fxSheen{ to{ left:170%; } }

/* ---- 5 · Punto / badge que late (mensajes sin leer) — el pulso se define abajo con --neg
   tokenizado (fxPulseTok, bloque "MIGRACIÓN SISTÉMICA"). El fxPulse con rojo hardcodeado se retiró (L1). ---- */

/* ---- 5b · Aparición del VALOR (reemplaza al count-up, que mostraba cifras intermedias falsas — ver
   revealValue() en app.js). Fade + micro-ascenso: da vida sin inventar números. ---- */
.fx-num-in{ animation:fxNumIn .3s ease both; }
@keyframes fxNumIn{ from{ opacity:0; transform:translateY(3px); } to{ opacity:1; transform:none; } }
@media (prefers-reduced-motion: reduce){ .fx-num-in{ animation:none !important; } }

/* ---- 6 · Shimmer / esqueleto de carga (clase utilitaria .fx-skel) ---- */
.fx-skel{ display:flex; flex-direction:column; gap:10px; }
.fx-skel-ln{ height:13px; border-radius:7px; background:var(--field-bg,rgba(255,255,255,.04)); }
html:not([data-motion="minimo"]) .fx-skel-ln{
  background:linear-gradient(90deg, var(--field-bg,rgba(255,255,255,.04)) 25%,
    color-mix(in srgb, var(--gold) 18%, var(--field-bg,rgba(255,255,255,.04))) 37%,
    var(--field-bg,rgba(255,255,255,.04)) 63%);
  background-size:400% 100%; animation:fxShimmer 1.4s linear infinite; }
.fx-skel-ln.w80{ width:80%; } .fx-skel-ln.w60{ width:60%; } .fx-skel-ln.w40{ width:40%; }
@keyframes fxShimmer{ 0%{ background-position:100% 0; } 100%{ background-position:-100% 0; } }

/* ---- 7 · Borde de oro animado para estados "en progreso" (clase utilitaria .fx-progress) ---- */
.fx-progress{ position:relative; }
html[data-motion="full"] .fx-progress::before{
  content:""; position:absolute; inset:-1px; border-radius:inherit; padding:1px; pointer-events:none;
  background:conic-gradient(from var(--fx-ang,0deg), transparent 18%, var(--gold) 50%, transparent 82%);
  -webkit-mask:linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite:xor; mask-composite:exclude;
  animation:fxSpin 3.2s linear infinite; }
@property --fx-ang{ syntax:'<angle>'; inherits:false; initial-value:0deg; }
@keyframes fxSpin{ to{ --fx-ang:360deg; } }

/* ---- 8 · Entrada del toast (aviso) ---- */
/* `both` es el arreglo del bug: sin fill-mode, al terminar la animación el toast volvía al opacity:0 de su regla
   base (styles.css) y se apagaba a los 340ms, aunque seguía 2s en el DOM. */
html:not([data-motion="minimo"]) .toast{ animation:fxToastIn .28s var(--ease-out) both; }
@keyframes fxToastIn{ from{ opacity:0; transform:translateY(14px) translateX(-50%); } to{ opacity:1; transform:translateY(0) translateX(-50%); } }
/* Salida: la clase .out existía en styles.css pero nadie la ponía; ahora la pone toast() en app.js. Más rápida que
   la entrada, porque descartar no necesita ceremonia. */
html:not([data-motion="minimo"]) .toast.out{ animation:fxToastOut .16s var(--ease-out) both; }
@keyframes fxToastOut{ from{ opacity:1; transform:translateY(0) translateX(-50%); } to{ opacity:0; transform:translateY(8px) translateX(-50%); } }

/* ============================================================================
   PORTADA DE ACCESO — primera impresión editorial antes del login
   ============================================================================ */
/* Login full-bleed: sin header (el logo grande vive en el centro de la bóveda). Vale para toda
   pantalla pre-login (portada, 2FA, bloqueo, enrolamiento TOTP, códigos de respaldo). */
body:not(.authed) .nx-header{ display:none !important; }
html[data-theme] body:not(.authed) .nx-header::after{ display:none !important; }
body:not(.authed) .nx-content{ min-height:100vh; }
body:not(.authed) .nx-footer{ display:none; }

/* Portada de acceso "Meridianos" (antes "Bóveda"): animación generativa a pantalla completa (oro sobre negro),
   logo IEB al centro + slogan, botón Ingresar abajo. Al tocar Ingresar la bóveda se atenúa
   y sube la tarjeta usuario+contraseña centrada (openLoginForm → .login-form-open + .is-open).
   El login SIEMPRE es oscuro (login-theme-black) sin importar el tema del usuario. */
.login-wrap-entry{
  min-height:100vh !important;
  position:relative;
  display:block !important;
  padding:0 !important;
  background:#070708;
  overflow:hidden;
}
.login-wrap-entry.login-theme-black{
  --login-accent:#D9B66B;
  --login-accent-2:#8F6C2B;
  --login-ink:#F4EDDD;
  --login-muted:rgba(236,229,213,.62);
}
/* el logo de marca dentro del login nunca lleva el filtro de oscurecido de los temas claros
   (el fondo del login es siempre oscuro) */
.login-wrap-entry .brand-logo{ filter:none !important; -webkit-filter:none !important; }

/* ---- pantalla de carga post-login ---- */
.login-loading{ position:absolute; inset:0; z-index:40; display:flex; flex-direction:column;
  align-items:center; justify-content:center; gap:20px; }
.login-loading .brand-logo{ height:56px; width:auto; opacity:0;
  animation:llFadeIn .5s ease forwards; }
.login-loading-text{ font:500 20px/1.3 var(--ff-sans,system-ui,sans-serif);
  color:var(--login-ink,#F4EDDD); opacity:0;
  animation:llFadeIn .5s .15s ease forwards; }
.login-loading-bar{ width:min(240px,60vw); height:3px; border-radius:3px;
  background:rgba(217,182,107,.15); overflow:hidden; opacity:0;
  animation:llFadeIn .4s .3s ease forwards; }
.login-loading-fill{ width:0; height:100%; border-radius:3px;
  background:linear-gradient(90deg,var(--login-accent,#D9B66B),var(--login-accent-2,#8F6C2B));
  animation:llProgress 2.4s .4s cubic-bezier(.4,0,.2,1) forwards; }
@keyframes llFadeIn{ to{ opacity:1; } }
@keyframes llProgress{ 0%{width:0} 40%{width:55%} 70%{width:78%} 100%{width:96%} }

/* ---- escena Meridianos (antes "Bóveda") ---- */
/* fondo FIJO a pantalla completa (NO se mueve en el split — si estuviera dentro del grupo, al
   desplazarse se vería el borde del rectángulo detrás del aro) */
.lv-bg{ position:absolute; inset:0; z-index:0; background:
  radial-gradient(60% 60% at 50% 50%, rgba(217,182,107,.10), transparent 60%),
  linear-gradient(180deg,#0a0a0b,#060606); }
/* grupo del globo (globo + logo/slogan): en el split se desliza a la izquierda y achica como bloque */
.lv-group{ position:absolute; inset:0; z-index:2; pointer-events:none; transform-origin:center center;
  transition:transform .5s var(--ease-drawer), opacity var(--dur-panel) ease; }
.login-wrap-entry.login-form-open .lv-group{ transform:translateX(-24vw) scale(.86); }
/* globo "Meridianos" (canvas a pantalla completa dentro del grupo; lo dibuja initLoginVault en app.js) */
.lv-globe{ position:absolute; inset:0; width:100%; height:100%; display:block; }
.lv-logoback{ position:absolute; left:50%; top:50%; width:44vmin; height:44vmin; transform:translate(-50%,-50%);
  border-radius:50%; background:radial-gradient(circle,rgba(6,5,4,.92),rgba(6,5,4,.7) 42%,transparent 68%); }
.lv-dust{ position:absolute; inset:0; z-index:5; width:100%; height:100%; }
.lv-vignette{ position:absolute; inset:0; z-index:6; background:radial-gradient(120% 90% at 50% 45%,transparent 42%,rgba(0,0,0,.55) 100%); }

/* ---- bloque central: logo + slogan ----
   El LOGO va dead-center sobre el aro. Truco de centrado independiente de la pantalla: el <section>
   mide SOLO lo que mide el logo (la regla y el slogan van FUERA DE FLUJO, absolutos, debajo) → con
   translate(-50%,-50%) el logo queda en el centro EXACTO en desktop y mobile, sin calibrar un % a mano.
   La regla/slogan se centran por left/margin (NO por transform, que lvReveal pisaría con transform:none). */
.login-hero{ position:absolute; left:50%; top:50%; transform:translate(-50%,-50%); z-index:20;
  width:min(90vw,560px); text-align:center; }
.login-wrap-entry .login-hero-logo{ display:block; margin:0 auto; width:clamp(176px,23vmin,288px); height:auto;
  filter:drop-shadow(0 4px 22px rgba(0,0,0,.5)) !important; -webkit-filter:drop-shadow(0 4px 22px rgba(0,0,0,.5)) !important;
  opacity:0; transform:translateY(10px) scale(.98); animation:lvReveal 1.4s .3s var(--ease-out) forwards; }
.login-hero-rule{ position:absolute; left:50%; margin-left:-32px; top:calc(100% + 14px); width:64px; height:1px;
  background:linear-gradient(90deg,transparent,rgba(217,182,107,.7),transparent);
  opacity:0; animation:lvReveal 1s 1.1s forwards; }
.login-hero-slogan{ position:absolute; left:0; right:0; top:calc(100% + 26px); color:var(--login-muted);
  font-size:clamp(12px,1.4vw,15px); font-weight:600; letter-spacing:.34em; text-transform:uppercase;
  opacity:0; animation:lvReveal 1.2s .9s forwards; }
@keyframes lvReveal{ to{ opacity:1; transform:none; } }

/* ---- botón Ingresar (portada, abajo) ---- */
.login-cta{ position:absolute; left:50%; bottom:clamp(46px,9vh,96px); z-index:25;
  /* 2026-09-20: de 1,3s de espera + 1,2s de animación a 0,4s + 0,5s. Los asesores entran todos los días: la
     portada no es un momento de "primera vez" y el botón de entrar no puede tardar 2,5s en existir. */
  transform:translate(-50%,14px); opacity:0; animation:lvRiseX .5s .4s forwards; transition:opacity var(--dur-ui) ease; }
@keyframes lvRiseX{ to{ opacity:1; transform:translate(-50%,0); } }
.login-wrap-entry .login-start{
  min-width:180px; padding:15px 52px !important; justify-content:center;
  color:#0a0906 !important; letter-spacing:.16em; text-transform:uppercase; font-weight:700;
  background:linear-gradient(135deg, var(--login-accent), #efd9a3) !important; border-color:transparent !important;
  box-shadow:0 18px 44px rgba(143,108,43,.42),0 0 0 1px rgba(255,240,200,.25) inset !important; }

/* ---- tarjeta de acceso (entra desde la DERECHA en el split) ---- */
.login-card-access{ position:absolute; right:max(6vw,34px); top:50%; left:auto; z-index:30; width:min(92vw,384px);
  transform:translate(48px,-50%); opacity:0; visibility:hidden; pointer-events:none;
  animation:none !important; /* anular auroraIn de la capa Aurora (fija transform:none) */
  transition:opacity .55s ease, transform .5s var(--ease-drawer), visibility 0s linear .8s;
  background:linear-gradient(180deg,rgba(20,17,12,.9),rgba(12,10,7,.94)) !important;
  border:1px solid rgba(217,182,107,.24) !important; border-radius:20px !important;
  box-shadow:0 40px 90px rgba(0,0,0,.6),inset 0 1px 0 rgba(255,240,200,.06) !important;
  -webkit-backdrop-filter:blur(10px); backdrop-filter:blur(10px); padding:32px 30px 28px !important; text-align:center; }
.login-card-access .login-brand{ justify-content:center; margin-bottom:16px; }
.login-card-access .login-brand .brand-logo{ height:44px; margin:0 auto; }
.login-card-access .login-title{ font-size:24px; text-align:center; margin-bottom:4px; }
.login-card-access .login-sub{ color:var(--login-muted); text-align:center; }
.login-card-access .login-foot{ text-align:center; }
/* el login es oscuro forzado → los campos van oscuros aunque el usuario tenga un tema claro
   (si no, en Marfil/Daylight salían con fondo blanco sobre la tarjeta oscura) */
.login-card-access .login-title{ color:var(--login-ink) !important; }
.login-card-access .login-label{ color:var(--login-muted) !important; }
.login-card-access .login-input{
  background:rgba(6,5,4,.72) !important; border:1px solid rgba(217,182,107,.22) !important;
  color:var(--login-ink) !important; }
.login-card-access .login-input:focus{
  border-color:rgba(217,182,107,.7) !important; box-shadow:0 0 0 3px rgba(217,182,107,.14) !important; }
.login-card-access .login-input::placeholder{ color:rgba(236,229,213,.34) !important; }
/* la capa de tema claro pinta .login-card claro con la misma especificidad (0,1,0) y gana por orden;
   subimos a (0,2,0) con el ancestro .login-wrap-entry para forzar la tarjeta oscura en TODO tema */
.login-wrap-entry .login-card-access{
  background:linear-gradient(180deg,rgba(20,17,12,.92),rgba(12,10,7,.95)) !important;
  border:1px solid rgba(217,182,107,.24) !important;
  box-shadow:0 40px 90px rgba(0,0,0,.6),inset 0 1px 0 rgba(255,240,200,.06) !important; }
.login-wrap-entry .login-card-access .login-sub{ color:var(--login-muted) !important; }
.login-card-access .login-btn{
  color:#0a0906 !important; letter-spacing:.16em; text-transform:uppercase; font-weight:700;
  background:linear-gradient(135deg, var(--login-accent), #efd9a3) !important; border-color:transparent !important; }
.login-card-access.is-open{ opacity:1; visibility:visible; pointer-events:auto; transform:translate(0,-50%); transition-delay:.08s,.3s,0s; }

/* ---- estado "form abierto" (SPLIT): el aro (con el logo) se corre a la izquierda y sigue vivo;
   NO se atenúa la portada, solo se oculta el botón Ingresar de la portada (la tarjeta trae el suyo) ---- */
.login-wrap-entry.login-form-open .login-cta{ opacity:0; pointer-events:none; animation:none; }

/* pantallas angostas: no hay lugar para el split → el aro se atenúa detrás y la tarjeta va centrada */
@media (max-width:860px){
  .login-wrap-entry.login-form-open .lv-group{ transform:scale(.94); opacity:.4; }
  .login-card-access{ right:50%; transform:translate(calc(50% + 48px),-50%); }
  .login-card-access.is-open{ transform:translate(50%,-50%); }
}
@media (max-width:600px){
  .login-wrap-entry .login-hero-logo{ width:clamp(150px,44vw,224px); }
  .login-hero-slogan{ letter-spacing:.18em; font-size:12px; }
  .login-card-access{ width:min(94vw,380px); }
}
@media (prefers-reduced-motion:reduce){
  .login-hero-logo,.login-hero-rule,.login-hero-slogan{ opacity:1 !important; transform:none !important; animation:none !important; }
  .login-cta{ opacity:1 !important; transform:translateX(-50%) !important; animation:none !important; }
  .lv-group{ transition:none !important; } /* el split se aplica al instante, sin deslizamiento */
  .login-card-access{ transition:opacity .2s ease; }
}

/* ============================================================================
   PASE GLOBAL — interior de producto estilo banca privada
   ============================================================================ */
:root, html[data-theme="onyx"]{
  --surface-deep:#11110D;
  --surface-raised:#191913;
  --surface-soft:#202018;
  --line-soft:rgba(236,229,213,.075);
  --cool-accent:#8FA8B8;
}

html[data-theme="black"]{
  --surface-deep:#060607;
  --surface-raised:#111113;
  --surface-soft:#18181B;
  --line-soft:rgba(242,240,236,.075);
  --cool-accent:#8EA1B8;
}

html[data-theme="ivory"]{
  --surface-deep:#EEE9DC;
  --surface-raised:#FFFFFF;
  --surface-soft:#F7F3EA;
  --line-soft:rgba(38,34,25,.09);
  --cool-accent:#4F6D7A;
}

/* white-label StoneX — superficies propias (sin estos tokens heredaban las
   oscuras de onyx y Daylight quedaba con tarjetas negras: audit 2026-07-08 S1/A1) */
html[data-theme="spectrum"]{
  --surface-deep:#141A26;
  --surface-raised:#222C3C;
  --surface-soft:#2A3547;
  --line-soft:rgba(255,255,255,.08);
  --cool-accent:#8FA8C4;
}

html[data-theme="daylight"]{
  --surface-deep:#EDF1F6;
  --surface-raised:#FFFFFF;
  --surface-soft:#F4F6F9;
  --line-soft:rgba(27,35,48,.10);
  --cool-accent:#4F6D7A;
}

body.authed{
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--app-bg) 94%, var(--gold) 6%) 0%, var(--app-bg) 360px),
    var(--app-bg) !important;
}

body.authed .nx-content{
  min-height:calc(100vh - 66px);
  background:
    linear-gradient(90deg, transparent 0, transparent calc(100% - 1px), color-mix(in srgb, var(--gold) 4.5%, transparent) 100%),
    linear-gradient(180deg, rgba(255,255,255,.018), transparent 220px);
}

body.authed .nx-header{
  height:64px;
  background:color-mix(in srgb, var(--chrome-bg) 94%, #000 6%) !important;
  border-bottom-color:var(--line-soft) !important;
}

body.authed .nx-logo{
  min-width:106px;
}

body.authed .grm-word{
  font-size:23px;
  letter-spacing:.2em;
}

body.authed .nx-icon-btn,
body.authed .nx-hdr-btn,
body.authed .user-chip{
  background:transparent !important;
  border-color:transparent !important;
}

body.authed .nx-icon-btn:hover,
body.authed .nx-icon-btn.active{
  background:color-mix(in srgb, var(--gold) 8%, transparent) !important;
  border-color:color-mix(in srgb, var(--gold) 22%, transparent) !important;
  color:var(--gold) !important;
}

/* Cluster del header (opción 1, 2026-08-04): íconos MÁS GRANDES + usuario ADELANTE con avatar y separador. */
body.authed .nx-header-right .nx-icon-btn{ width:40px; height:40px; }
.user-av{ width:28px; height:28px; flex:0 0 auto; border-radius:50%; display:inline-flex; align-items:center; justify-content:center;
  background:color-mix(in srgb, var(--gold) 16%, transparent); border:1px solid color-mix(in srgb, var(--gold) 42%, transparent);
  color:var(--gold); font-size:12.5px; font-weight:700; line-height:1; }
.user-chip-lead{ position:relative; padding-left:4px; margin-right:10px; padding-right:14px; }
.user-chip-lead::after{ content:""; position:absolute; right:0; top:7px; bottom:7px; width:1px; background:var(--line); }

body.authed .nx-hdr-btn:hover{
  background:color-mix(in srgb, var(--gold) 7%, transparent) !important;
  border-color:color-mix(in srgb, var(--gold) 20%, transparent) !important;
}

.nx-side{
  background:color-mix(in srgb, var(--chrome-bg) 96%, #000 4%) !important;
  border-right:1px solid var(--line-soft) !important;
}

.nx-snav{
  padding:16px 12px 22px !important;
  flex:1 1 auto;
}

.nx-snav a,
.nx-snav .nx-snav-item{
  border-radius:12px !important;
  min-height:38px;
  padding:9px 12px !important;
  color:color-mix(in srgb, var(--grey-warm) 88%, var(--ink) 12%) !important;
}

.nx-snav a:hover,
.nx-snav .nx-snav-item:hover{
  background:rgba(255,255,255,.035) !important;
  color:var(--ink) !important;
}

.nx-snav a.active,
.nx-snav .nx-snav-item.active{
  background:linear-gradient(90deg, color-mix(in srgb, var(--gold) 14%, transparent), color-mix(in srgb, var(--gold) 3.5%, transparent)) !important;
  box-shadow:inset 2px 0 0 var(--gold);
  color:var(--ink) !important;
}

.list-wrap,
.panel{
  max-width:1320px;
}

.list-head{
  align-items:flex-start !important;
  margin-bottom:24px !important;
}

.list-title h1,
.panel h2{
  font-size:clamp(30px,3.2vw,42px) !important;
  letter-spacing:0;
}

/* .page-note = la nota "qué se ve / qué se puede hacer" de las pantallas que abren con .acct-bar. Comparte
   tono y ancho con el <p> de .list-title para que sea UNA sola voz visual en toda la app (ver pageNote()). */
.list-title p,
.panel .panel-sub,
.page-note{
  max-width:760px;
  color:color-mix(in srgb, var(--grey-warm) 90%, var(--cool-accent) 10%) !important;
}
body.authed .page-note{ font-size:13px !important; }

.gold-line::before,
.panel h2::before,
.list-title h1::before,
.sec-title::before,
.modal-h::before{
  width:54px !important;
  height:2px !important;
  border-radius:2px;
  /* oro pleno = firma de marca; el degradé multicolor es exclusivo de Spectrum/Daylight
     (definido arriba). Un solo dueño por regla (audit 2026-07-08 S3). */
  background:var(--gold) !important;
}

.kpi,
.table-card,
.info-section,
.bal-card,
.group-card,
.empty-state,
.perf-card,
.refresh-card,
.dash-w,
.modal,
.login-card,
.acct-chip,
.side-nav{
  background:
    linear-gradient(180deg, rgba(255,255,255,.035), rgba(255,255,255,.012)),
    var(--surface-raised) !important;
  border-color:var(--line-soft) !important;
  box-shadow:0 18px 46px -34px rgba(0,0,0,.88), inset 0 1px 0 rgba(255,255,255,.045) !important;
}

.kpi,
.bal-card,
.perf-card,
.refresh-card,
.dash-w{
  position:relative;
  overflow:hidden;
}

.kpi::before,
.bal-card::before,
.perf-card::before,
.refresh-card::before,
.dash-w::before{
  content:"";
  position:absolute;
  inset:0 0 auto;
  height:1px;
  background:linear-gradient(90deg, transparent, color-mix(in srgb, var(--gold) 38%, transparent), transparent);
  pointer-events:none;
}

.kpi .k-label,
.bal-card .bl,
.perf-card .perf-label,
.metric .ml,
.nx-table thead th,
.login-label{
  color:color-mix(in srgb, var(--grey-warm) 72%, var(--cool-accent) 28%) !important;
  letter-spacing:var(--track-wide) !important;
}

.kpi .k-value,
.bal-card .bv,
.perf-card .perf-value{
  font-size:clamp(24px,2.4vw,34px) !important;
}

.toolbar{
  gap:12px !important;
  margin-bottom:20px !important;
}

.search-box input,
.toolbar select,
.period-sel,
.modal input,
.login-input,
input[type=text],
input[type=number],
input[type=password],
input[type=date],
input[type=email],
input[type=search],
select,
textarea{
  border-color:var(--line-soft) !important;
  background:rgba(255,255,255,.035) !important;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.035) !important;
}

.search-box input:focus,
.toolbar select:focus,
.period-sel:focus,
.modal input:focus,
.login-input:focus,
input:focus,
select:focus,
textarea:focus{
  outline:2px solid color-mix(in srgb, var(--gold) 18%, transparent) !important;
  outline-offset:2px;
  border-color:color-mix(in srgb, var(--gold) 42%, transparent) !important;
}

.btn-primary{
  background:linear-gradient(180deg, #E8CF8D, var(--gold)) !important;
  border-color:color-mix(in srgb, var(--gold) 84%, #fff 16%) !important;
}

.btn-secondary,
.link-groups-btn,
.back-btn,
.link-btn,
.more-btn,
.acct-actions .circ{
  background:rgba(255,255,255,.025) !important;
  border-color:var(--line-soft) !important;
}

.btn-secondary:hover,
.link-groups-btn:hover,
.back-btn:hover,
.link-btn:hover,
.more-btn:hover,
.acct-actions .circ:hover{
  background:color-mix(in srgb, var(--gold) 8%, transparent) !important;
  border-color:color-mix(in srgb, var(--gold) 32%, transparent) !important;
}

.table-card{
  overflow:hidden;
}
/* En mobile, una tabla más ancha que la pantalla (p.ej. Top-10 del Inicio, 640px) quedaba CLIPEADA: este
   `overflow:hidden` de meridian carga después de la regla de scroll de styles.css y la pisaba. Restauramos el
   scroll horizontal (la última capa gana) → la tabla se puede deslizar en vez de cortarse el badge del custodio. */
@media (max-width:760px){
  .table-card{ overflow-x:auto; overflow-y:hidden; -webkit-overflow-scrolling:touch; }
}

.nx-table thead th{
  background:rgba(255,255,255,.018) !important;
  border-bottom-color:var(--line-soft) !important;
}

.nx-table tbody td{
  border-bottom-color:var(--line-soft) !important;
}

.nx-table tbody tr{
  transition:background .16s ease, box-shadow .16s ease;
}

.nx-table tbody tr:hover{
  background:color-mix(in srgb, var(--gold) 4.5%, transparent) !important;
  box-shadow:inset 3px 0 0 var(--gold) !important;
}

.cust-badge,
.tag,
.badge,
.brand-pill,
.member-chip,
.role-badge,
.user-role{
  background:rgba(255,255,255,.025);
  border-color:var(--line-soft) !important;
}

/* El .cust-badge.Pershing SALIÓ de acá (2026-07-16): con borde dorado y el de StoneX gris, el oro —que en toda
   la app significa marca/acción— se leía como "destacado/activo" y sugería una preferencia de custodio que no
   existe. Ahora los dos badges son neutros y se distinguen por un PUNTO de color (ver .cust-badge en styles.css).
   El oro queda para .role-badge.admin, donde sí marca jerarquía. */
.role-badge.admin{
  border-color:color-mix(in srgb, var(--gold) 42%, transparent) !important;
}

.acct-bar{
  padding-top:18px !important;
  padding-bottom:18px !important;
  background:
    linear-gradient(180deg, rgba(255,255,255,.022), transparent),
    var(--surface-deep) !important;
}

.acct-label{
  color:color-mix(in srgb, var(--grey-warm) 72%, var(--cool-accent) 28%) !important;
}

.acct-chip{
  padding:9px 18px !important;
}

.acct-chip .nm{
  font-size:var(--fs-lg) !important;
}

.summary-strip{
  background:rgba(255,255,255,.012) !important;
  border-bottom-color:var(--line-soft) !important;
}

.detail-body{
  background:linear-gradient(180deg, rgba(255,255,255,.012), transparent 260px);
}

.side-nav{
  margin:0 !important;
  border-radius:0 0 var(--r-lg) 0 !important;
}

.side-nav .sn-head{
  color:var(--gold) !important;
  opacity:.82;
}

.side-nav .sn-item{
  border-radius:0 12px 12px 0;
  margin:2px 10px 2px 0;
}

.side-nav .sn-item.active{
  background:color-mix(in srgb, var(--gold) 11%, transparent) !important;
}

.info-section .sec-title{
  background:rgba(255,255,255,.014);
  border-bottom-color:var(--line-soft) !important;
}

.nx-footer{
  background:var(--surface-deep) !important;
  border-top-color:var(--line-soft) !important;
}

@media (max-width:760px){
  body.authed .nx-header{ height:62px; }
  .list-wrap{ padding-left:20px !important; padding-right:20px !important; }
  .list-title h1,.panel h2{ font-size:30px !important; }
  .side-nav{
    border-radius:0 !important;
    margin:0 !important;
  }
  .side-nav .sn-item{
    border-radius:12px;
    margin:2px;
  }
}

/* ============================================================================
   REFINAMIENTO FINO — tarjetas compactas, números sobrios
   ============================================================================ */
body.authed .kpis{
  gap:12px !important;
  margin-bottom:22px !important;
}

body.authed .kpi,
body.authed .bal-card,
body.authed .perf-card,
body.authed .refresh-card{
  padding:15px 16px !important;
  min-height:auto;
  border-radius:14px !important;
  background:
    linear-gradient(180deg, rgba(255,255,255,.026), rgba(255,255,255,.008)),
    color-mix(in srgb, var(--surface-raised) 92%, var(--surface-deep) 8%) !important;
  box-shadow:0 14px 34px -30px rgba(0,0,0,.92), inset 0 1px 0 rgba(255,255,255,.032) !important;
}

body.authed .kpi::before,
body.authed .bal-card::before,
body.authed .perf-card::before,
body.authed .refresh-card::before{
  background:linear-gradient(90deg, color-mix(in srgb, var(--gold) 28%, transparent), transparent 62%);
  opacity:.62;
}

body.authed .kpi .k-label,
body.authed .bal-card .bl,
body.authed .perf-card .perf-label{
  font-size:9.5px !important;
  line-height:1.25;
  letter-spacing:.17em !important;
}

body.authed .kpi .k-value,
body.authed .bal-card .bv,
body.authed .perf-card .perf-value{
  margin-top:7px !important;
  font-family:var(--sans) !important;   /* Plex: dígitos técnicos con tabular-nums (el tamaño se define abajo) */
  line-height:1.18 !important;
  font-weight:500 !important;
  letter-spacing:0 !important;
  color:color-mix(in srgb, var(--ink) 92%, var(--gold) 8%) !important;
  font-variant-numeric:tabular-nums;
}

body.authed .kpi .k-sub,
body.authed .bal-card .bv + *,
body.authed .perf-card .perf-sub{
  margin-top:5px !important;
  font-size:var(--fs-xs) !important;
  line-height:1.35;
}

body.authed .dash-hero{
  padding:16px !important;
  border-radius:16px !important;
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--gold) 3.5%, transparent), rgba(255,255,255,.012)),
    var(--surface-raised) !important;
  border-color:var(--line-soft) !important;
  box-shadow:0 18px 42px -36px rgba(0,0,0,.88) !important;
}

body.authed .dash-hero .kpis{
  grid-template-columns:repeat(4,minmax(0,1fr));
}

body.authed .dash-mod,
body.authed .dash-coll,
body.authed .pad-card{
  border-radius:16px !important;
  background:
    linear-gradient(180deg, rgba(255,255,255,.024), rgba(255,255,255,.008)),
    var(--surface-raised) !important;
  box-shadow:0 14px 36px -32px rgba(0,0,0,.9), inset 0 1px 0 rgba(255,255,255,.035) !important;
}

body.authed .dash-mod .sec-title,
body.authed .dash-coll .sec-title,
body.authed .info-section .sec-title{
  font-size:var(--fs-lg) !important;
  letter-spacing:0 !important;
}

body.authed .dash-whead{
  margin-bottom:8px;
}

body.authed .dash-chart{
  height:142px !important;
}

body.authed .bal-cards{
  gap:14px !important;
  margin-bottom:18px !important;
}

body.authed .bal-card .bv{
  font-size:clamp(18px,1.7vw,24px) !important;
}

body.authed .acct-bar{
  padding-top:14px !important;
  padding-bottom:14px !important;
}

body.authed .acct-chip{
  padding:8px 15px !important;
  box-shadow:none !important;
}

body.authed .acct-chip .nm{
  font-size:17px !important;
}

body.authed .acct-chip .an{
  font-size:var(--fs-sm) !important;
}

body.authed .table-card,
body.authed .info-section{
  border-radius:16px !important;
  box-shadow:0 14px 36px -34px rgba(0,0,0,.9), inset 0 1px 0 rgba(255,255,255,.03) !important;
}

body.authed .nx-table{
  font-size:13px !important;
}

body.authed .nx-table thead th{
  padding-top:12px !important;
  padding-bottom:12px !important;
  font-size:9.5px !important;
}

body.authed .nx-table tbody td{
  padding-top:12px !important;
  padding-bottom:12px !important;
}

body.authed .btn-primary,
body.authed .btn-secondary,
body.authed .link-groups-btn,
body.authed .back-btn,
body.authed .link-btn,
body.authed .more-btn{
  min-height:36px;
  padding:9px 14px !important;
  font-size:10.5px !important;
  letter-spacing:.13em !important;
}

body.authed .head-actions{
  gap:10px !important;
}

body.authed .search-box input,
body.authed .toolbar select,
body.authed .period-sel{
  min-height:38px;
  padding-top:9px !important;
  padding-bottom:9px !important;
  font-size:13px !important;
}

body.authed .list-wrap{
  padding-top:clamp(24px,3.8vw,44px) !important;
}

body.authed .list-title h1,
body.authed .panel h2{
  font-size:clamp(28px,2.8vw,36px) !important;
}

body.authed .list-title p,
body.authed .panel .panel-sub{
  font-size:13px !important;
}

html:not([data-motion="minimo"]) body.authed .kpi:hover,
html:not([data-motion="minimo"]) body.authed .bal-card:hover,
html:not([data-motion="minimo"]) body.authed .perf-card:hover,
html:not([data-motion="minimo"]) body.authed .refresh-card:hover{
  transform:translateY(-2px) !important;
  box-shadow:0 18px 42px -34px rgba(0,0,0,.95), inset 0 1px 0 rgba(255,255,255,.045) !important;
}

@media (max-width:760px){
  body.authed .kpis,
  body.authed .dash-hero .kpis{
    grid-template-columns:repeat(2,minmax(0,1fr)) !important;
  }
  body.authed .kpi,
  body.authed .bal-card,
  body.authed .perf-card{
    padding:13px 14px !important;
  }
  body.authed .kpi .k-value,
  body.authed .bal-card .bv,
  body.authed .perf-card .perf-value{
    font-size:19px !important;
  }
}

/* Escala de cifras — ÚNICA fuente de verdad para .k-value/.bv/.perf-value (audit 2026-07-08
   M4/T1: antes había 3 reescrituras encadenadas; el resto de props [Plex, tabular-nums, color]
   vive en el bloque de arriba). Cifra hero grande pero sobria: es el ancla del dashboard. */
body.authed .kpi,
body.authed .bal-card,
body.authed .perf-card{
  padding:12px 14px !important;
}

body.authed .kpi .k-value,
body.authed .bal-card .bv,
body.authed .perf-card .perf-value{
  font-size:clamp(22px,1.9vw,28px) !important;
  line-height:1.18 !important;
  font-weight:500 !important;
}

body.authed .kpi .k-label,
body.authed .bal-card .bl,
body.authed .perf-card .perf-label{
  font-size:var(--fs-2xs) !important;      /* 10px — nunca versalita <10px */
  letter-spacing:var(--track-wide) !important;  /* .14em */
}

body.authed .kpi .k-sub,
body.authed .perf-card .perf-sub{
  font-size:10.5px !important;
  opacity:.82;
}

body.authed .kpis-4,
body.authed .kpis-5,
body.authed .kpis-6{
  gap:10px !important;
}

body.authed .panel .kpis{
  margin-bottom:18px !important;
}

body.authed .dash-pending{
  gap:8px !important;
  margin-bottom:14px !important;
}

body.authed .pchip,
body.authed .dash-pending .pchip{
  min-height:32px;
  padding:5px 12px !important;
  border-color:var(--line-soft) !important;
  background:rgba(255,255,255,.022) !important;
}

body.authed .pchip b{
  font-size:var(--fs-md);
  font-weight:600;
  color:color-mix(in srgb, var(--gold) 82%, var(--ink) 18%);
}

@media (max-width:760px){
  body.authed .kpi .k-value,
  body.authed .bal-card .bv,
  body.authed .perf-card .perf-value{
    font-size:17px !important;
  }
}

/* Guard de impresión: el bloque "PASE GLOBAL" (posterior + !important) le ganaba al reset
   de print de Meridian → sombras/degradés se filtraban al imprimir listas/dashboards/modales.
   Este reset es lo último que habla. El estado de cuenta (.stmt-doc) no se toca. (audit 2026-07-08 A2) */
@media print{
  body.authed .kpi, body.authed .table-card, body.authed .info-section,
  body.authed .bal-card, body.authed .dash-mod, body.authed .dash-coll,
  body.authed .pad-card, body.authed .dash-hero, body.authed .modal, body.authed .nx-table{
    box-shadow:none !important;
    background:#fff !important;
    border-color:#ddd !important;
  }
}

/* ===== Tour de bienvenida (onboarding) — velo + recorte iluminado (spotlight) + globo =====
   Técnica de un solo elemento: el .tour-hole pinta el oscuro ALREDEDOR con box-shadow gigante y deja el
   target visible por el recorte. Para pasos centrados (bienvenida/cierre) el velo se pone sólido y el hole
   se oculta. Todo con tokens → anda en los 5 temas. No se imprime. */
.tour-ov{position:fixed; inset:0; z-index:4000; background:transparent}
.tour-ov.solid{background:rgba(0,0,0,.62)}
.tour-hole{position:fixed; border-radius:12px; box-shadow:0 0 0 9999px rgba(0,0,0,.62);
  outline:2px solid var(--gold); outline-offset:2px; pointer-events:none; transition:left .18s ease,top .18s ease,width .18s ease,height .18s ease}
.tour-pop{position:fixed; z-index:4001; width:min(360px,calc(100vw - 24px)); background:var(--float-bg);
  color:var(--ink); border:1px solid var(--line); border-radius:var(--r); box-shadow:var(--shadow-lg); font-size:14px}
.tour-pop.center{left:50% !important; top:50% !important; transform:translate(-50%,-50%); width:min(420px,calc(100vw - 24px))}
.tour-card{padding:16px 18px}
.tour-title{margin:0 0 8px; font-size:16px; font-weight:600; color:var(--ink); line-height:1.3}
.tour-text{margin:0; color:var(--muted); line-height:1.55}
.tour-text b{color:var(--ink); font-weight:600}
.tour-lead{margin:0 0 8px; color:var(--muted)}
.tour-items{margin:0; padding:0; list-style:none; display:flex; flex-direction:column; gap:7px}
.tour-items li{color:var(--muted); line-height:1.45; font-size:13.5px; padding-left:13px; position:relative}
.tour-items li::before{content:""; position:absolute; left:0; top:.55em; width:4px; height:4px; border-radius:50%; background:var(--gold)}
.tour-items b{color:var(--ink); font-weight:600}
.tour-foot{display:flex; align-items:center; gap:10px; flex-wrap:wrap; padding:11px 18px; border-top:1px solid var(--line)}
.tour-dots{display:flex; gap:5px}
.tour-dots i{width:6px; height:6px; border-radius:50%; background:var(--line); display:block; transition:background .15s,transform .15s}
.tour-dots i.on{background:var(--gold); transform:scale(1.18)}
.tour-prog{font-size:11px; color:var(--muted); margin-right:auto}
.tour-btns{display:flex; gap:6px; margin-left:auto}
.tour-btns button{font:inherit; font-size:13px; font-weight:600; border-radius:9px; padding:7px 13px; cursor:pointer;
  border:1px solid var(--line); background:transparent; color:var(--ink)}
.tour-btns button:hover{border-color:var(--gold)}
.tour-btns .tour-skip{color:var(--muted)}
.tour-btns .tour-next{background:var(--gold); border-color:var(--gold); color:var(--on-gold)}
@media (prefers-reduced-motion:reduce){ .tour-hole{transition:none} }
@media print{ .tour-ov, .tour-pop{display:none !important} }

/* ============================================================================
   CAPA DE MOVIMIENTO v2 — "más tecnológico" (2026-09-09)
   ----------------------------------------------------------------------------
   Los 20 efectos elegidos en design/animaciones.html. TODO cuelga de
   html[data-motion] (Ajustes → Apariencia): "Completo" = todo, "Sobrio" = solo
   lo sutil, "Mínimo" = nada. prefers-reduced-motion apaga la capa entera.
   Lo que ya existía arriba (entrada de vista, cascada, lift, donut, grano,
   dibujo de la línea del gráfico) NO se duplica acá.
   ============================================================================ */

/* ---- 0 · interruptor general: reduced-motion mata toda esta capa ---- */
@media (prefers-reduced-motion: reduce){
  /* 2026-09-20: faltaban .bal-card::before y .perf-card::before (el barrido seguía corriendo con reduced-motion). */
  .nx-table tbody tr, .alloc-fill, .kpi::before, .table-card::before, .bal-card::before, .perf-card::before,
  .kpi::after, .fx-dg, .nx-tape .nxt-track, .snav-ind, .lux-grid, .msg-badge.bump{ animation:none !important; transition:none !important; }
  .alloc-fill{ transform:none !important; }
  .fx-dg{ opacity:1 !important; }
}

/* ---- 1 · ENTRADA · filas de tabla en cascada -------------------------------
   Solo las primeras 18 filas: en una tabla de 800 el resto aparece de una (ni
   se ve, y 800 animaciones simultáneas cuestan caro). ---------------------- */
html:not([data-motion="minimo"]) .nx-table.fx-rows-in tbody tr:nth-child(-n+18){
  animation:fxRowIn .38s var(--ease-out) both;
}
@keyframes fxRowIn{ from{ opacity:0; transform:translateX(-9px); } to{ opacity:1; transform:none; } }
html:not([data-motion="minimo"]) .nx-table.fx-rows-in tbody tr:nth-child(1){ animation-delay:0ms }
html:not([data-motion="minimo"]) .nx-table.fx-rows-in tbody tr:nth-child(2){ animation-delay:32ms }
html:not([data-motion="minimo"]) .nx-table.fx-rows-in tbody tr:nth-child(3){ animation-delay:64ms }
html:not([data-motion="minimo"]) .nx-table.fx-rows-in tbody tr:nth-child(4){ animation-delay:96ms }
html:not([data-motion="minimo"]) .nx-table.fx-rows-in tbody tr:nth-child(5){ animation-delay:128ms }
html:not([data-motion="minimo"]) .nx-table.fx-rows-in tbody tr:nth-child(6){ animation-delay:160ms }
html:not([data-motion="minimo"]) .nx-table.fx-rows-in tbody tr:nth-child(7){ animation-delay:192ms }
html:not([data-motion="minimo"]) .nx-table.fx-rows-in tbody tr:nth-child(8){ animation-delay:224ms }
html:not([data-motion="minimo"]) .nx-table.fx-rows-in tbody tr:nth-child(9){ animation-delay:256ms }
html:not([data-motion="minimo"]) .nx-table.fx-rows-in tbody tr:nth-child(10){ animation-delay:288ms }
html:not([data-motion="minimo"]) .nx-table.fx-rows-in tbody tr:nth-child(n+11){ animation-delay:180ms }

/* ---- 2 · ENTRADA · enfoque (blur → nítido) ---------------------------------
   Variante de la cascada que ya existe: en "Completo" la tarjeta entra
   desenfocada. En "Sobrio" sigue el auroraIn de siempre. -------------------- */
/* 2026-09-20: se saca el desenfoque de entrada. La tabla de clientes y los KPIs entraban borrosos 660ms, o sea
   que el movimiento tapaba justo el dato que el asesor fue a buscar. Queda un ascenso corto y nítido. */
html[data-motion="full"] .aurora-reveal.in{
  animation-name:fxRise !important; animation-duration:var(--dur-ui) !important;
}
@keyframes fxRise{
  from{ opacity:0; transform:translateY(8px); }
  to{ opacity:1; transform:none; }
}

/* ---- 3 · DATOS · barras de asignación / concentración que crecen ---------- */
html:not([data-motion="minimo"]) .alloc-fill{
  transform-origin:left center;
  animation:fxBarGrow .8s var(--ease-out) both;
}
@keyframes fxBarGrow{ from{ transform:scaleX(0); } to{ transform:scaleX(1); } }
html:not([data-motion="minimo"]) .alloc-row:nth-child(1) .alloc-fill{ animation-delay:0ms }
html:not([data-motion="minimo"]) .alloc-click:nth-child(2) .alloc-fill{ animation-delay:45ms }
html:not([data-motion="minimo"]) .alloc-click:nth-child(3) .alloc-fill{ animation-delay:90ms }
html:not([data-motion="minimo"]) .alloc-click:nth-child(4) .alloc-fill{ animation-delay:135ms }
html:not([data-motion="minimo"]) .alloc-click:nth-child(5) .alloc-fill{ animation-delay:180ms }
html:not([data-motion="minimo"]) .alloc-click:nth-child(6) .alloc-fill{ animation-delay:225ms }
html:not([data-motion="minimo"]) .alloc-click:nth-child(n+7) .alloc-fill{ animation-delay:270ms }

/* ---- 4 · DATOS · dígitos que ruedan — SIN USO desde 2026-09-20 -------------
   app.js ya no llama a applyDigitRoll: partía cada importe en <span> por caracter y un valor de 12 caracteres
   tardaba ~680ms en poder leerse, rehecho en cada filtro/orden. Las reglas quedan por si se vuelve atrás. ---- */
html[data-motion="full"] .fx-dg{
  display:inline-block; opacity:0;
  animation:fxDigit .42s var(--ease-out) both;
  animation-delay:calc(var(--d,0) * 22ms);
}
@keyframes fxDigit{ from{ opacity:0; transform:translateY(.45em) rotateX(-65deg); } to{ opacity:1; transform:none; } }

/* ---- 5 · DATOS · destello cuando un valor CAMBIÓ de verdad ----------------
   Lo pone app.js solo si el número nuevo difiere del anterior (no en la
   primera pintada): así el oro significa "esto se movió". ------------------- */
html:not([data-motion="minimo"]) .fx-flash{ animation:fxFlash .4s var(--ease-out); }
@keyframes fxFlash{
  0%{ color:var(--gold); text-shadow:0 0 18px color-mix(in srgb, var(--gold) 65%, transparent); }
  100%{ color:inherit; text-shadow:none; }
}

/* ---- 6 · SUPERFICIES · inclinación 3D del KPI (transform lo pone app.js) --
   El hover de la capa 1 fuerza translateY(-4px) con !important: acá se le da
   prioridad a --fx-tilt, que YA incluye ese ascenso. ------------------------ */
html[data-motion="full"] .kpi.fx-tilting,
html[data-motion="full"] .kpi.fx-tilting:hover{
  transform:var(--fx-tilt, none) !important;
  transition:transform .12s ease-out !important;
}

/* ---- 7 · SUPERFICIES · barrido de luz sobre el filete dorado -------------- */
html[data-motion="full"] .kpi::before,
html[data-motion="full"] .table-card::before,
html[data-motion="full"] .bal-card::before,
html[data-motion="full"] .perf-card::before{
  background:linear-gradient(90deg, transparent 0%,
    color-mix(in srgb, var(--gold) 12%, transparent) 34%,
    color-mix(in srgb, var(--gold) 92%, #fff 8%) 50%,
    color-mix(in srgb, var(--gold) 12%, transparent) 66%, transparent 100%) !important;
  background-size:220% 100% !important;
  /* 2026-09-20: era `infinite`. `background-position` es pintura pura (no se compone) sobre cuatro familias de
     tarjetas, sin parar nunca, en un panel que queda abierto todo el día. Queda UNA pasada al entrar. */
  animation:fxSweep 1.4s linear 1 both;
}
@keyframes fxSweep{ 0%{ background-position:120% 0; } 100%{ background-position:-120% 0; } }
html[data-motion="full"] .kpi:nth-child(2)::before{ animation-delay:.25s }
html[data-motion="full"] .kpi:nth-child(3)::before{ animation-delay:.5s }
html[data-motion="full"] .kpi:nth-child(4)::before{ animation-delay:.75s }
html[data-motion="full"] .kpi:nth-child(5)::before{ animation-delay:1s }
html[data-motion="full"] .kpi:nth-child(6)::before{ animation-delay:1.25s }

/* ---- 8 · SUPERFICIES · borde de luz giratorio en los KPIs — SACADO 2026-09-20 --
   Era un conic-gradient girando 6s en bucle infinito por cada KPI (4-6 en pantalla). Un degradado cónico no se
   compone: se repinta entero en cada frame, para siempre. Era el efecto más caro de la app y no aportaba dato.
   Se conserva el mismo recurso en .fx-progress, donde sí informa (algo está procesando). -------------------- */

/* ---- 9 · SUPERFICIES · fila resaltada con degradé ------------------------- */
html:not([data-motion="minimo"]) .nx-table.fx-rows-in tbody tr{ position:relative; }
html:not([data-motion="minimo"]) .nx-table.fx-rows-in tbody tr td:first-child{ position:relative; z-index:1 }
html:not([data-motion="minimo"]) .nx-table.fx-rows-in tbody tr:hover td{
  background-image:linear-gradient(90deg, color-mix(in srgb, var(--gold) 11%, transparent), transparent 55%);
}

/* ---- 10 · FONDO · rejilla técnica con parallax (la crea luxInit) ---------- */
.lux-grid{
  position:fixed; inset:0; z-index:0; pointer-events:none; opacity:0;
  background-image:
    linear-gradient(color-mix(in srgb, var(--gold) 5%, transparent) 1px, transparent 1px),
    linear-gradient(90deg, color-mix(in srgb, var(--gold) 5%, transparent) 1px, transparent 1px);
  background-size:48px 48px;
  -webkit-mask-image:radial-gradient(130% 95% at 50% 0%, #000 18%, transparent 76%);
  mask-image:radial-gradient(130% 95% at 50% 0%, #000 18%, transparent 76%);
  transform:translate3d(var(--gx,0px), var(--gy,0px), 0);
  transition:transform .55s var(--ease-out), opacity .4s ease;
}
html[data-motion="full"] .lux-grid{ opacity:1 }
/* sobre los temas claros la rejilla se ensucia: se apaga, igual que la aurora. */
html[data-theme="ivory"] .lux-grid, html[data-theme="daylight"] .lux-grid{ display:none !important }

/* ---- 11 · NAV · indicador que se desliza en el menú lateral --------------- */
/* El indicador es position:absolute → SU bloque contenedor tiene que ser la barra. Sin esto se posiciona
   contra .nx-side (que es sticky, o sea "positioned") y el filete cae ~2 ítems más abajo del que tocás. */
.nx-snav{ position:relative }
.snav-ind{
  position:absolute; left:6px; width:2px; border-radius:2px; background:var(--gold);
  opacity:0; pointer-events:none; top:0; height:0;
}
html:not([data-motion="minimo"]) .snav-ind{
  transition:top var(--dur-ui) var(--ease-in-out), height var(--dur-ui) var(--ease-in-out), opacity var(--dur-ui) ease;
}
html:not([data-motion="minimo"]) .snav-ind.on{ opacity:1 }
/* si el usuario baja a "Mínimo" con el indicador ya pintado, se va sin esperar al próximo render */
html[data-motion="minimo"] .snav-ind{ display:none !important }
/* con el indicador vivo, el filete fijo del activo sobra (quedarían dos) */
html:not([data-motion="minimo"]) .nx-snav .nx-snav-item.active{ box-shadow:none !important }

/* ---- 12 · NAV · cinta de mercados (franja bajo el header, dentro de .nx-content) ---------- */
.nx-tape{
  flex:0 0 auto; overflow:hidden; position:relative;
  padding:6px 0; border-bottom:1px solid var(--line-soft);
  background:color-mix(in srgb, var(--chrome-bg) 72%, transparent);
  -webkit-mask-image:linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent);
  mask-image:linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent);
}
.nx-tape .nxt-track{ display:inline-flex; white-space:nowrap; }
html[data-motion="full"] .nx-tape .nxt-track{ animation:fxTicker 60s linear infinite }
html[data-motion="full"] .nx-tape:hover .nxt-track{ animation-play-state:paused }
@keyframes fxTicker{ from{ transform:translateX(0) } to{ transform:translateX(-50%) } }
.nx-tape .nxt-set{ display:inline-flex; gap:26px; padding-right:26px }
.nx-tape i{
  font-style:normal; font-size:11.5px; color:var(--grey-warm);
  font-variant-numeric:tabular-nums; display:inline-flex; gap:5px; align-items:baseline;
}
.nx-tape i b{ font-weight:500; color:color-mix(in srgb, var(--ink) 82%, transparent) }
.nx-tape .up{ color:var(--pos) } .nx-tape .dn{ color:var(--neg) }
/* La cinta es la ÚNICA vista de mercados desde que se sacó el panel del sidebar (2026-09-09):
   por eso se muestra en todos los anchos, también en mobile. */
@media print{ .nx-tape{ display:none !important } }

/* ---- 13 · MICRO · apertura elástica de la sección plegable ---------------- */
.dash-coll-body.fx-coll{ overflow:hidden; max-height:0; opacity:0; display:block !important }
html:not([data-motion="minimo"]) .dash-coll-body.fx-coll{
  transition:max-height var(--dur-panel) var(--ease-out), opacity var(--dur-panel) ease;
}
/* la altura de apertura la fija app.js (scrollHeight → "none"): nada queda cortado */
.dash-coll-body.fx-coll.open{ opacity:1 }
html:not([data-motion="minimo"]) .dash-coll-h .mkt-chev{ transition:transform var(--dur-ui) var(--ease-out); display:inline-block }

/* ---- 14 · ENTRADA · esqueleto de carga: el .fx-skel ya existía arriba,
   ahora lo usan de verdad los módulos del Inicio (ver dashSectionHtml). ----- */
.fx-skel{ padding:4px 0 2px }

/* ============================================================================
   VARIACIÓN DEL DÍA (2026-09-09) — tarjeta del Inicio.
   Verde/rojo acá SÍ: es la misma excepción que G/P en Tenencias (`.gl-sign`),
   son variaciones de plata y el signo es el dato.
   ============================================================================ */
.var-card .na-head{ flex-wrap:wrap; row-gap:8px }
.var-ctl{ display:inline-flex; gap:8px; flex-wrap:wrap; margin-left:auto }
.var-seg{ display:inline-flex; border:1px solid var(--line); border-radius:var(--r-pill); overflow:hidden }
.vseg{ appearance:none; border:0; background:transparent; color:var(--grey-warm); font-family:var(--sans);
  font-size:11.5px; font-weight:500; padding:6px 12px; cursor:pointer; transition:background .15s, color .15s }
.vseg:hover{ color:var(--ink) }
.vseg.on{ background:color-mix(in srgb, var(--gold) 16%, transparent); color:var(--ink) }
.vseg.vdir{ border:1px solid var(--line); border-radius:var(--r-pill) }

.var-sum{ display:flex; flex-wrap:wrap; gap:10px 22px; padding:2px 0 16px; border-bottom:1px solid var(--line-soft); margin-bottom:12px }
.var-sum span{ display:flex; flex-direction:column; gap:2px; font-size:13.5px; font-variant-numeric:tabular-nums }
.var-sum i{ font-style:normal; font-size:9.5px; font-weight:500; letter-spacing:.14em; text-transform:uppercase; color:var(--grey-warm) }

.var-up{ color:var(--pos) } .var-dn{ color:var(--neg) } .var-flat{ color:var(--grey-warm) }
.var-pct{ font-size:11.5px; color:var(--grey-warm) }
.var-tbl td.num, .var-tbl th.num{ text-align:right; font-variant-numeric:tabular-nums; white-space:nowrap }
.var-gap{ font-size:10.5px; color:var(--warn); border:1px solid color-mix(in srgb, var(--warn) 40%, transparent);
  border-radius:var(--r-pill); padding:1px 7px; margin-left:7px; white-space:nowrap }
.var-nodata{ margin-top:12px; padding-top:10px; border-top:1px solid var(--line-soft); font-size:12px }
@media (max-width:760px){ .var-ctl{ margin-left:0; width:100% } }
