:root {
  color-scheme: dark;
  --page-plane: #0a0e17;
  --surface-1: #111827;
  --surface-2: #171f30;
  --text-primary: #ffffff;
  --text-secondary: #c3c2b7;
  --muted: #7c8598;
  --gridline: #242e42;
  /* Neutro fijo, nunca lo pisa la personalización de "Color e intensidad" de Estilo del
     panel (ver static/app.js::applyBorderStyle/applyTextStyle) -- --border y --text-primary
     sí se sobrescriben con la elección del usuario, pero la opción "Gris (predeterminado)"
     de ambas paletas necesita un punto de referencia que no cambie con ellas mismas. */
  --neutral-strong: #ffffff;
  /* Mismo criterio que --neutral-strong, pero como referencia de --text-secondary (no de
     --text-primary) -- la opción "Gris (predeterminado)" del tuner de textos secundarios
     usa este valor en vez de --neutral-strong, porque el gris real de los textos
     secundarios nunca fue blanco/negro puro. */
  --neutral-secondary: #c3c2b7;
  --border: rgba(255, 255, 255, 0.20); /* PRUEBA 2026-08-07 — era 0.10, revertir si no convence */
  --good: #0ca30c;
  --critical: #d03b3b;
  --warning: #c98500;
  --series-1: #3987e5; /* EMA9 / acento primario */
  --series-2: #199e70; /* EMA21 */
  --series-3: #c98500; /* EMA200 */
  /* series-4 a series-8: resto de la paleta categórica (naranja/magenta/verde/violeta/rojo),
     usadas por el Gráfico De Torta de Portafolio (ver renderPortfolioPie en app.js) para
     tener hasta 7 monedas con color propio + "Otros" en gris antes de repetir un tono. */
  --series-4: #d95926;
  --series-5: #d55181;
  --series-6: #008300;
  --series-7: #9085e9;
  --series-8: #e66767;
  /* Paleta tecnológica exclusiva del portafolio: no altera las series de otros gráficos.
     Tonos vivos + degradé "3D" por porción (ver donutSlicePath/shadeHex en app.js). */
  --portfolio-1: #2f88ff;
  --portfolio-2: #00d6ae;
  --portfolio-3: #ffb200;
  --portfolio-4: #ff4d5e;
  --portfolio-5: #a855f7;
  --portfolio-6: #ff2e93;
  --portfolio-7: #ff7a1a;
  --portfolio-8: #22e07a;
  --candle-up: #0ca30c;
  --candle-down: #d03b3b;
  --radius: 10px;
}

:root[data-theme="light"] {
  color-scheme: light;
  --page-plane: #eef1f7;
  --surface-1: #ffffff;
  --surface-2: #eef1f6;
  --text-primary: #0b0f1a;
  --text-secondary: #3c4658;
  --muted: #6b7688;
  --gridline: #d7dce6;
  --neutral-strong: #0b0f1a;
  --neutral-secondary: #3c4658;
  --border: rgba(11, 15, 26, 0.3); /* PRUEBA 2026-08-07 — era 0.12, revertir si no convence */
  --good: #0ca30c;
  --critical: #d03b3b;
  --warning: #eda100;
  --series-1: #2a78d6;
  --series-2: #1baf7a;
  --series-3: #eda100;
  --series-4: #eb6834;
  --series-5: #e87ba4;
  --series-6: #008300;
  --series-7: #4a3aa7;
  --series-8: #e34948;
  --portfolio-1: #1c6fe6;
  --portfolio-2: #00a68a;
  --portfolio-3: #dc8c00;
  --portfolio-4: #e6394a;
  --portfolio-5: #9333ea;
  --portfolio-6: #e01a80;
  --portfolio-7: #e6650f;
  --portfolio-8: #0fa860;
  --candle-up: #0ca30c;
  --candle-down: #d03b3b;
}

/* Campo sensible con control para mostrar/ocultar su contenido. */
.password-field {
  position: relative;
}
.password-field > input {
  padding-right: 42px !important;
}
.password-toggle {
  position: absolute;
  top: 50%;
  right: 7px;
  width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  border-radius: 5px;
  background: transparent;
  color: var(--muted);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transform: translateY(-50%);
  cursor: pointer;
}
.password-toggle:hover { color: var(--text-primary); background: rgba(127, 127, 127, 0.12); }
.password-toggle:focus-visible { outline: 2px solid var(--series-1); outline-offset: 1px; }
.password-toggle svg { width: 18px; height: 18px; pointer-events: none; }
.password-toggle .eye-closed { display: none; }
.password-toggle[aria-pressed="true"] .eye-open { display: none; }
.password-toggle[aria-pressed="true"] .eye-closed { display: block; }

/* Tour guiado del producto */
.header-actions { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.tour-launch-btn {
  display: inline-flex; align-items: center; gap: 7px;
  border: 1px solid color-mix(in srgb, var(--series-1) 55%, var(--border));
  background: color-mix(in srgb, var(--series-1) 12%, var(--surface-1));
  color: var(--text-primary); white-space: nowrap;
}
.tour-launch-btn svg { width: 16px; height: 16px; color: var(--series-1); }
.tour-launch-btn:hover { border-color: var(--series-1); box-shadow: 0 0 0 3px color-mix(in srgb, var(--series-1) 12%, transparent); }
.dashboard-refresh-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  border: 1px solid color-mix(in srgb, var(--series-2) 55%, var(--border));
  background: color-mix(in srgb, var(--series-2) 12%, var(--surface-1));
  color: var(--text-primary); white-space: nowrap;
}
.dashboard-refresh-btn svg { width: 16px; height: 16px; color: var(--series-2); }
.dashboard-refresh-btn:hover { border-color: var(--series-2); box-shadow: 0 0 0 3px color-mix(in srgb, var(--series-2) 12%, transparent); }
.dashboard-refresh-btn.is-refreshing { pointer-events: none; opacity: .72; }
.dashboard-refresh-btn.is-refreshing svg { animation: dashboard-refresh-spin .75s linear infinite; }
@keyframes dashboard-refresh-spin { to { transform: rotate(360deg); } }

.pull-refresh-indicator { display: none; }
.product-tour { display: none; position: fixed; inset: 0; z-index: 1000; }
.product-tour.active { display: block; }
.tour-mask { position: fixed; background: rgba(3, 7, 18, .78); backdrop-filter: blur(2px); }
.tour-highlight { position: fixed; border: 2px solid #63a8ff; border-radius: 14px; box-shadow: 0 0 0 5px rgba(57,135,229,.18), 0 18px 55px rgba(0,0,0,.38); pointer-events: none; transition: all .22s ease; }
.tour-card {
  position: fixed; width: min(410px, calc(100vw - 28px)); max-height: calc(100vh - 28px); overflow: auto;
  padding: 22px; border: 1px solid rgba(115,174,255,.35); border-radius: 16px;
  background: linear-gradient(145deg, color-mix(in srgb, var(--surface-1) 96%, #183f72), var(--surface-1));
  color: var(--text-primary); box-shadow: 0 24px 80px rgba(0,0,0,.52); z-index: 1002;
}
.tour-card-topline { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.tour-eyebrow { color: var(--series-1); font-size: 10px; font-weight: 750; letter-spacing: .14em; }
.tour-close { width: 30px; height: 30px; padding: 0; border-radius: 50%; background: transparent; color: var(--muted); font-size: 22px; line-height: 1; }
.tour-progress { height: 3px; margin: 15px 0 12px; overflow: hidden; border-radius: 9px; background: var(--gridline); }
.tour-progress span { display: block; width: 0; height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--series-1), #73d7ff); transition: width .25s ease; }
.tour-pipeline {
  display: flex; align-items: flex-start; gap: 0; width: 100%; margin: 2px 0 12px;
  overflow-x: auto; padding: 3px 2px 7px; scrollbar-width: thin; scroll-behavior: smooth;
}
.tour-pipeline-step {
  position: relative; flex: 1 0 25px; min-width: 25px; height: 24px; padding: 0;
  border: 0; border-radius: 0; background: transparent; color: var(--muted); filter: none;
}
.tour-pipeline-step::before {
  content: ""; position: absolute; left: 0; right: 0; top: 10px; height: 2px;
  background: var(--gridline); transition: background .2s ease;
}
.tour-pipeline-step:first-child::before { left: 50%; }
.tour-pipeline-step:last-child::before { right: 50%; }
.tour-pipeline-dot {
  position: relative; z-index: 1; display: grid; place-items: center; width: 11px; height: 11px;
  margin: 5px auto 0; border: 2px solid var(--muted); border-radius: 50%;
  background: var(--surface-1); transition: width .2s ease, height .2s ease, margin .2s ease, border-color .2s ease, background .2s ease, box-shadow .2s ease;
}
/* Color que evoluciona a lo largo de la línea de tiempo (pedido explícito 2026-09-07) -- app.js
   calcula el HSL final (hue 220°→140°, más saturación/luminosidad en punta) y lo deja ya
   resuelto en --tour-dot-color por punto, según su posición FIJA en la secuencia (no según el
   paso actual), así que el tramo ya recorrido se ve como un degradé continuo de azul a verde a
   medida que se acerca al final, en vez del mismo azul parejo de siempre. Se calcula en JS y
   no con calc()/var() anidados acá (como en un intento anterior) porque Chrome no resolvía un
   calc() dentro de un hsl() cuando dependía de un var() sustituido 2 niveles más abajo
   (custom property -> descendiente) -- quedaba "inválido en tiempo de cómputo" en silencio y
   el punto se veía sin color. Con el string ya armado en JS, es un var() de un solo nivel,
   sin ese problema. */
.tour-pipeline-step.completed, .tour-pipeline-step.active {
  /* fallback por si --tour-dot-color no llegó a fijarse por algún motivo */
  --tour-dot-color: var(--series-1);
}
.tour-pipeline-step.completed::before, .tour-pipeline-step.active::before { background: var(--tour-dot-color); }
.tour-pipeline-step.completed .tour-pipeline-dot { border-color: var(--tour-dot-color); background: var(--tour-dot-color); }
.tour-pipeline-step.active .tour-pipeline-dot {
  width: 15px; height: 15px; margin-top: 3px; border-color: var(--tour-dot-color); background: var(--tour-dot-color);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--tour-dot-color) 18%, transparent);
}
.tour-pipeline-step:hover { background: transparent; filter: none; }
.tour-pipeline-step:hover .tour-pipeline-dot { border-color: #8bc4ff; transform: scale(1.12); }
.tour-pipeline-step:focus-visible { outline: none; }
.tour-pipeline-step:focus-visible .tour-pipeline-dot { outline: 2px solid #8bc4ff; outline-offset: 3px; }
.tour-step-count { color: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums; }
.tour-icon { width: 38px; height: 38px; margin-top: 14px; display: grid; place-items: center; border-radius: 11px; color: #8bc4ff; background: rgba(57,135,229,.15); font-size: 18px; }
.tour-card h2 { margin: 13px 0 8px; font-size: 21px; line-height: 1.2; letter-spacing: -.02em; }
.tour-card p { margin: 0; color: var(--text-secondary); font-size: 13px; line-height: 1.65; }
.tour-note { margin-top: 13px; padding: 10px 12px; border-left: 2px solid var(--series-1); border-radius: 0 7px 7px 0; background: rgba(57,135,229,.08); color: var(--muted); font-size: 11px; line-height: 1.5; }
.tour-note:empty { display: none; }
.tour-actions { display: flex; justify-content: space-between; gap: 12px; margin-top: 20px; }
.tour-actions button { min-width: 92px; }
body.tour-open { overflow: hidden; }
@media (max-width: 720px) {
  .tabs-bar-row { align-items: flex-start; }
  .header-actions { flex-direction: column; align-items: stretch; }
  .tour-launch-btn span { display: none; }
  .tour-launch-btn { justify-content: center; }
  .tour-card { padding: 18px; }
}

* { box-sizing: border-box; }

/* Reserva siempre el espacio de la barra de scroll vertical (esté o no realmente presente).
   Sin esto, una pestaña más alta que la pantalla mete la barra y le resta ~15px de ancho a
   la página, mientras que una pestaña más baja no la muestra — el contenido se corre esos
   mismos píxeles al cambiar de pestaña y los recuadros parecen "moverse" entre grupos. */
html {
  scrollbar-gutter: stable;
  overflow-y: scroll;
}

html, body {
  margin: 0;
  padding: 0;
  background: var(--page-plane);
  color: var(--text-primary);
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: 14px;
}

.app {
  max-width: 1352px; /* +1cm (~38px) de ancho útil a cada lado, sumado al +1cm anterior (1200px -> 1276px -> 1352px) */
  margin: 0 auto;
  padding: 24px 20px 60px;
}

header.topbar {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 16px;
  margin-bottom: 24px;
}

.topbar-side.right {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 14px;
}

header.topbar h1 {
  font-size: 18px;
  font-weight: 600;
  margin: 0;
}

header.topbar .subtitle {
  color: var(--muted);
  font-size: 12px;
  margin-top: 2px;
}

.app-version {
  color: var(--muted);
  font-size: 10px;
  line-height: 1.2;
  margin-top: 3px;
  letter-spacing: 0.02em;
}

.login-version {
  margin: -14px 0 18px;
  text-align: center;
}

/* padding/border-radius fijos en AMBOS temas (no solo en claro) a propósito: si el tema
   claro le agrega tamaño a esta caja que el oscuro no tiene, el header queda más alto en
   un tema que en el otro y TODO lo de abajo se corre unos milímetros al cambiar de tema
   (bug real encontrado 2026-08-07). Con el mismo padding en los dos, la geometría es
   idéntica siempre — lo único que cambia entre temas es el color de fondo. */
header.topbar .brand {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  padding: 8px 20px;
  border-radius: 10px;
  background: transparent;
}
header.topbar .brand img {
  height: 44px;
  width: auto;
}
/* El logo es plateado/metálico: en tema claro necesita un fondo oscuro para no perderse
   contra el fondo blanco. */
:root[data-theme="light"] header.topbar .brand {
  background: #0a0e17;
}

/* Cierre automático pausado en la tarjeta DCA (corrección 12 de la auditoría, 2026-09-27). */
.dca-autoclose-paused {
  display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap;
  margin-top: 8px; padding: 8px 10px; border-radius: 8px; font-size: 12px; line-height: 1.4;
  color: var(--critical);
  background: color-mix(in srgb, var(--critical) 10%, var(--surface-1));
  border: 1px solid color-mix(in srgb, var(--critical) 35%, var(--border));
}
.dca-autoclose-paused .dca-btn { flex: none; }

/* Reiniciar Datos oculto a clientes con [hidden] (corrección 1 de la auditoría, 2026-09-27):
   .icon-btn fija su propio display y le ganaba al [hidden] del navegador. */
#btn-reset-data[hidden] { display: none !important; }

.icon-btn {
  width: 28px;
  height: 28px;
  padding: 0;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
}
/* Los 3 íconos del header (Ajustes/Reiniciar/Cerrar Sesión -- Tema se mudó adentro de
   Ajustes) -- un tono sobrio y distinto para cada uno (misma paleta categórica que el
   resto de la app), con el mismo glow de borde al hover que ya usan los demás chips con
   ícono (.tour-launch-btn, etc.). */
#btn-settings { color: color-mix(in srgb, var(--series-2) 80%, var(--text-primary)); }
#btn-reset-data { color: color-mix(in srgb, var(--series-3) 80%, var(--text-primary)); }
#btn-logout { color: color-mix(in srgb, var(--critical) 80%, var(--text-primary)); }
#btn-settings:hover { border-color: var(--series-2); box-shadow: 0 0 0 3px color-mix(in srgb, var(--series-2) 14%, transparent); }
#btn-reset-data:hover { border-color: var(--series-3); box-shadow: 0 0 0 3px color-mix(in srgb, var(--series-3) 14%, transparent); }
#btn-logout:hover { border-color: var(--critical); box-shadow: 0 0 0 3px color-mix(in srgb, var(--critical) 14%, transparent); }

.conn-status {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--text-secondary);
}

.conn-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--critical);
}
.conn-dot.online { background: var(--good); }

/* ---------- Navegación por pestañas, estilo recuadros elegantes ----------
   Cada botón es su propio recuadro chico (ancho propio, borde completo), todos a la misma
   altura. La inactiva queda en tono apagado con su ícono en gris; la activa se distingue por
   una franja de acento azul arriba, fondo más claro, texto e ícono resaltados, y una sombra
   suave que la despega apenas del resto. */
.tabs-bar-row {
  position: sticky;
  top: 12px;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 16px;
}
.section-tabs {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
/* Mismo formato de recuadro que las pestañas (tamaño, padding, radio, tipografía) para que
   quede alineado con ellas en la misma fila, pero con el color que ya tenía antes (fondo
   azul, letras blancas — el mismo de los botones primarios de la app, ej. "Guardar"). */
.admin-mode-btn {
  flex: 0 0 auto;
  padding: 7px 13px;
  background: var(--series-1);
  border: 1px solid transparent;
  border-radius: 9px;
  color: #ffffff;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.01em;
  white-space: nowrap;
}
.admin-mode-btn:hover { filter: brightness(1.1); }
/* Mismo lenguaje visual que .tour-launch-btn (borde + fondo teñidos con color-mix, en vez
   de un recuadro plano) -- pedido explícito, para que las pestañas se vean "sobrias y
   elegantes" en lugar del bloque sólido de antes. Un solo tono (el acento azul de siempre)
   para las 7, no uno distinto por pestaña -- con 7 en fila, un color por botón se vería
   recargado en vez de sobrio. */
.tab-btn {
  position: relative;
  z-index: 1;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 7px 13px;
  background: color-mix(in srgb, var(--series-1) 7%, var(--surface-1));
  border: 1px solid color-mix(in srgb, var(--series-1) 28%, var(--border));
  border-radius: 9px;
  color: var(--text-primary);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.01em;
  overflow: hidden;
  transition: color 0.2s ease, background 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}
/* Franja de acento arriba del recuadro: oculta (escala 0) en las inactivas, se despliega
   de centro hacia los costados cuando la pestaña pasa a estar activa. */
.tab-btn::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--series-1), #7fb8f5);
  transform: scaleX(0);
  transition: transform 0.25s ease;
}
.tab-btn.active::before { transform: scaleX(1); }

.tab-btn .tab-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tab-btn .tab-icon {
  width: 17px;
  height: 17px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: color-mix(in srgb, var(--series-1) 10%, var(--surface-1));
  color: var(--muted);
  font-size: 9.5px;
  line-height: 1;
  flex-shrink: 0;
  transition: background 0.2s ease, color 0.2s ease, box-shadow 0.2s ease;
}

.tab-btn:hover {
  color: var(--text-primary);
  border-color: var(--series-1);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--series-1) 12%, transparent);
}
.tab-btn:hover .tab-icon { color: var(--text-primary); }
.tab-btn.active {
  z-index: 2;
  background: var(--surface-1);
  border-color: color-mix(in srgb, var(--series-1) 40%, var(--border));
  color: var(--text-primary);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.14);
}
.tab-btn.active .tab-icon {
  background: var(--series-1);
  color: #ffffff;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--series-1) 18%, transparent);
}

.tab-panel {
  display: none;
}
.tab-panel.active {
  display: block;
  animation: tabPanelIn 0.22s ease;
}
@keyframes tabPanelIn {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: translateY(0); }
}

@media (max-width: 900px) {
  .tabs-bar-row { flex-wrap: wrap; }
  .section-tabs { overflow-x: auto; -webkit-overflow-scrolling: touch; }
}

.kpi-row {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 12px;
  margin-bottom: 18px;
}

/* Indicadores Globales (Admin Mode) tiene una tarjeta más por fila que el resto de los
   .kpi-row del sitio (8 en vez de 7) — override solo por id para no afectar el Dashboard
   ni la pestaña Stake, que usan clases de spanning atadas a esas 7 columnas. */
#admin-kpi-row {
  grid-template-columns: repeat(8, 1fr);
}

.kpi-tile {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 14px;
  min-width: 0;
  position: relative; /* ancla para el ícono "i" en la esquina, ver más abajo */
}
.kpi-row > .kpi-tile { text-align: center; }

/* Columna vacía a propósito: reserva el espacio de una tarjeta sacada de la fila (ej.
   Saldo Disponible se movió a su propia fila) sin dibujar nada, para que el resto de las
   tarjetas no se corran de columna. */
.kpi-tile-gap { visibility: hidden; }

/* "Stake (Interés Ganado)" es el título más largo de Indicadores Globales — con el padding
   y font-size normales de .kpi-tile no entra entero y queda con "…" (ver .kpi-tile .label
   más abajo). Achica el padding lateral de la tarjeta y el font-size/letter-spacing SOLO
   del label para que entre completo en una línea, sin tocar el resto de las tarjetas. */
.kpi-tile-tight-label {
  padding-left: 4px;
  padding-right: 4px;
}
.kpi-tile-tight-label .label {
  font-size: 9.5px;
  letter-spacing: 0;
}

.kpi-tile .label {
  color: var(--muted);
  font-size: 11px;
  letter-spacing: 0.03em;
  margin-bottom: 6px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Empuja el texto centrado un poco a la izquierda para que no quede pegado/tapado por la
   insignia del ícono en la esquina derecha (ver .kpi-tile .info-icon más abajo). */
.kpi-tile .label:has(.info-icon) {
  padding-right: 16px;
}
/* El ícono "i" va como una insignia en la esquina de la tarjeta (ancla: .kpi-tile de
   arriba), fuera del flujo del texto del label. Así el label queda siempre en una sola
   línea sin importar cuán largo sea el título — todos los valores quedan alineados
   horizontalmente entre tarjetas — y el ícono nunca se sale del recuadro. Al quedar
   afuera de .label, tampoco lo afecta el overflow:hidden de acá arriba (su tooltip
   ::after se sigue viendo bien, con .kpi-tile como referencia en vez de .label). */
.kpi-tile .info-icon {
  position: absolute;
  top: 8px;
  right: 8px;
}

.kpi-tile .value {
  font-size: 18px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.kpi-tile .value.good { color: var(--good); }
.kpi-tile .value.critical { color: var(--critical); }
/* Mejora N°4: saldo mostrado es el último conocido porque Binance no respondió */
.value-stale, .kpi-tile .value.value-stale { color: var(--warning) !important; cursor: help; text-decoration: underline dotted; text-underline-offset: 3px; }
/* Dato guardado a propósito (no un error): Monitoreo Admin acepta intereses de hasta 6 h
   (pedido explícito 2026-09-30). Sin color de alerta, solo el subrayado que invita a ver cuándo. */
.value-aged { cursor: help; text-decoration: underline dotted; text-decoration-color: var(--muted); text-underline-offset: 3px; }

/* Tile dividido en 2 (ej. PNL Realizado: Acum. / Mes Act.): título arriba, debajo una
   fila con los dos valores separados por una línea vertical y su etiqueta bajo cada uno,
   todo centrado, mismo alto que las demás tarjetas. */
.kpi-tile-split {
  display: flex;
  flex-direction: column;
  align-items: center;
  /* Poco margen a los costados a propósito: los números (ej. "$10.000") necesitan casi
     todo el ancho del recuadro para no cortarse — ver .kpi-split-col más abajo. */
  padding: 12px 4px 10px;
}
.kpi-split-title {
  margin-bottom: 6px;
}
/* Total (Stake+Libre) chico junto al título — ej. "Saldo Disponible ($754)" — el resto del
   tile ya muestra Stake y Libre por separado, esto es solo la suma de referencia. */
.kpi-split-total {
  font-weight: 400;
  opacity: 0.75;
  font-variant-numeric: tabular-nums;
}
.kpi-split-row {
  display: flex;
  align-items: stretch;
  justify-content: center;
  width: 100%;
}
.kpi-split-col {
  flex: 1 1 0;
  min-width: 0;
  padding: 0 3px;
}
.kpi-split-col .label {
  margin-bottom: 0;
  margin-top: 4px;
}
.kpi-split-divider {
  width: 1px;
  background: var(--border);
  flex-shrink: 0;
  margin: 0 4px;
}

.kpi-tile.editable {
  display: flex;
  flex-direction: column;
  /* Sin gap acá: el label ya trae su propio margin-bottom (regla de arriba) — sumarle
     gap además duplicaba el espacio y hacía que el valor de Monto Total quedara más
     abajo que el de las demás tarjetas, que no son flex y solo usan ese margin. */
}

/* Saldo Total: ocupa las 2 filas de .kpi-row-double (columna 1), centrado en el medio
   de ambas — queda a la altura del punto medio entre Saldo Invertido (fila 1) y Saldo
   Disponible (fila 2), que comparten esa misma columna. */
.kpi-row-double { grid-auto-rows: auto; margin-bottom: 12px; }
.kpi-tile-total-spanning {
  grid-column: 1;
  grid-row: 1 / span 2;
  justify-content: center;
}
/* PNL Realizado + Stake: mismo truco que Saldo Total, pero en la columna 3 — a la derecha
   de Saldo Invertido/Saldo Disponible, que comparten la columna 2. */
.kpi-tile-pnl-stake-spanning {
  grid-column: 3;
  grid-row: 1 / span 2;
  justify-content: center;
}
/* PNL Total + Stake: mismo truco, columna 7 (la última) — igual que PNL Realizado + Stake,
   es .kpi-tile-split (Acum./Mes Act.), que ya trae su propio flex column. */
.kpi-tile-pnltotal-stake-spanning {
  grid-column: 7;
  grid-row: 1 / span 2;
  justify-content: center;
}

.kpi-tile.editable .edit-row {
  display: flex;
  gap: 6px;
}

.kpi-tile input[type="number"] {
  width: 100%;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-primary);
  padding: 6px 8px;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}
.kpi-tile input[type="number"]:disabled {
  opacity: 0.7;
  cursor: not-allowed;
}
button {
  cursor: pointer;
  font-family: inherit;
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 6px 12px;
  font-size: 13px;
  background: var(--series-1);
  color: #fff;
}
button:hover { filter: brightness(1.1); }
button.ghost {
  background: transparent;
  border: 1px solid var(--border);
  color: var(--text-secondary);
}
/* Ghost destructivo -- ej. "Borrar" un descuento ya cancelado en Tramo Tarifario (pedido
   explícito 2026-09-11): mismo tamaño/forma que un ghost normal, pero en rojo para que se
   note que es irreversible, sin llegar al peso visual de button.danger (sólido). */
button.ghost.critical {
  border-color: color-mix(in srgb, var(--critical) 45%, var(--border));
  color: var(--critical);
}
button.ghost.critical:hover {
  background: color-mix(in srgb, var(--critical) 12%, transparent);
}
button:disabled {
  cursor: not-allowed;
  opacity: 0.45;
  filter: none;
}
button:disabled:hover { filter: none; }

section.panel {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px 20px;
  margin-bottom: 20px;
}

section.panel h2 {
  font-size: 14px;
  font-weight: 600;
  margin: 0 0 14px;
  color: var(--text-primary);
  letter-spacing: 0.04em;
}

.info-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--surface-2);
  color: var(--text-primary);
  font-size: 10px;
  font-style: italic;
  font-weight: 600;
  border: 1px solid var(--border);
  cursor: help;
  position: relative;
  vertical-align: middle;
}
.info-icon:hover::after,
.info-icon:focus::after {
  content: attr(data-tooltip);
  position: absolute;
  bottom: 130%;
  left: 50%;
  transform: translateX(-50%);
  background: var(--surface-2);
  color: var(--text-primary);
  border: 1px solid var(--border);
  padding: 8px 10px;
  border-radius: 8px;
  font-size: 12px;
  font-style: normal;
  font-weight: 400;
  white-space: normal;
  width: 220px;
  line-height: 1.4;
  z-index: 60;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.3);
}

/* Separa la fila de recuadros (Saldo Total, Saldo Invertido, etc.) de la fila de métricas
   (Operaciones Cerradas, Win Rate, etc.) — mismo color y grosor que el contorno de esas
   tarjetas (.metric-tile { border: 1px solid var(--border) }), sobria, sin protagonismo. */
.row-divider {
  height: 1px;
  background: var(--border);
  margin: 0 0 12px;
}

.metrics-row {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 12px;
  margin-bottom: 18px;
}

.metric-tile {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 14px;
}

.metric-label {
  color: var(--muted);
  font-size: 10px;
  letter-spacing: 0.02em;
  margin-bottom: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  gap: 4px;
  white-space: nowrap;
  /* Ojo: nada de overflow:hidden acá — el tooltip del ícono "i" es un ::after posicionado
     por fuera de esta caja (aparece arriba del ícono) y quedaría recortado/invisible. */
}

.metric-value {
  font-size: 18px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-align: center;
}
.metric-value.good { color: var(--good); }
.metric-value.critical { color: var(--critical); }

.chart-subtitle {
  color: var(--muted);
  font-size: 12px;
  margin-bottom: 8px;
}

.chart-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  min-height: 32px;
  margin-bottom: 8px;
}
.chart-header-row .chart-subtitle { margin-bottom: 0; }

.chart-header-title-group {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  gap: 8px;
  min-width: 0;
  /* flex: 1 para ocupar todo el ancho del header -- sin esto, el grupo (título + select)
     se achicaba al contenido y el select quedaba pegado al texto del título en vez de ir
     hacia la derecha (pedido explícito: alinear el select con los valores de la fila de
     abajo). padding-right compensa el padding propio de 4px que tiene .pnl-by-pair (ver
     styles.css) -- sin esto el select quedaba 4px más a la derecha que la columna de
     valores de abajo. */
  flex: 1 1 auto;
  padding-right: 4px;
}
/* Título + ícono de info van juntos en su propio flex (pegados entre sí, como en
   cualquier otro panel) -- el que crece para empujar el <select> a la derecha es ESTE
   envoltorio, no el título solo, porque si el título fuera el único con flex:1 el ícono
   quedaba como tercer hijo del grupo grande y el espacio libre lo separaba del texto en
   vez de quedar pegado (bug real reportado 2026-09-23). */
.chart-header-title-group .chart-title-with-info {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  flex: 1 1 auto;
}
.chart-header-title-group .chart-subtitle {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.chart-header-title-group .range-select,
.chart-header-title-group .info-icon,
.chart-header-title-group .bu-reset-btn {
  flex-shrink: 0;
}
/* Botón "Restablecer" del gráfico "Última Hora" (pedido explícito 2026-10-03): mismo alto y
   tamaño de letra que la lista de temporalidad que tiene al lado. */
.bu-reset-btn { padding: 4px 10px; font-size: 12px; line-height: 1.3; }

.range-select {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-secondary);
  padding: 4px 6px;
  font-size: 12px;
}

#equity-chart-container {
  width: 100%;
  height: 220px;
}

.panel-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0 0 14px;
}
.panel-header-row h2 { margin: 0; }

.admin-client-tools {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  min-width: 0;
}
.admin-user-search-wrap {
  position: relative;
  display: flex;
  align-items: center;
  margin-right: 8px; /* ~2mm -- deja más aire hacia el contador de usuarios y Crear Cliente */
}
.admin-user-search-icon {
  position: absolute;
  left: 10px;
  color: var(--muted);
  font-size: 15px;
  pointer-events: none;
}
#admin-user-search {
  width: 230px;
  min-width: 150px;
  padding: 8px 10px 8px 30px;
  border: 1px solid var(--border);
  border-radius: 7px;
  background: var(--surface-2);
  color: var(--text-primary);
  font-size: 12px;
  outline: none;
}
#admin-user-search:focus { border-color: var(--series-1); }
#admin-user-search::placeholder { color: var(--muted); }
.admin-filter-count {
  min-width: 54px;
  color: var(--muted);
  font-size: 11px;
  text-align: right;
}
/* Paginación de Monitoreo De Clientes (pedido explícito 2026-10-06): 10 / 20 / 50 / Todos. */
.admin-pagination {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 10px;
  color: var(--text-secondary);
  font-size: 12px;
}
.admin-pagination-size { display: flex; align-items: center; gap: 6px; }
.admin-pagination-info { color: var(--muted); }
.admin-pagination-nav { display: flex; align-items: center; gap: 8px; }
.admin-pagination-nav[hidden] { display: none; }
.admin-pagination-nav button { padding: 4px 10px; font-size: 12px; }
.admin-pagination-nav button:disabled { opacity: 0.4; cursor: default; }
.admin-pagination-page { min-width: 90px; text-align: center; }

@media (max-width: 700px) {
  .panel-header-row:has(.admin-client-tools) {
    align-items: flex-start;
    flex-direction: column;
  }
  .admin-client-tools {
    width: 100%;
    flex-wrap: wrap;
    justify-content: flex-start;
  }
  .admin-user-search-wrap { flex: 1 1 190px; }
  #admin-user-search { width: 100%; }
}

.hidden { display: none !important; }

.charts-row {
  display: flex;
  gap: 10px;
}
/* Segunda fila de gráficos (PNL Acum. + Portafolio) -- separada de la fila de detalle
   (Escalones / PNL Por Par / Más Cerca De Ejecutarse) que va arriba. */
.charts-row + .charts-row { margin-top: 10px; }
.chart-panel {
  flex: 2.25;
  min-width: 0;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 12px 14px;
}
.chart-placeholder {
  height: 220px;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0 16px;
  border: 1px dashed var(--border);
  border-radius: var(--radius);
  color: var(--muted);
  font-size: 13px;
}

@media (max-width: 860px) {
  .charts-row { flex-direction: column; }
}

/* Segundo gráfico: PNL por par, barras horizontales */
.pnl-by-pair {
  height: 220px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 2px 4px;
}
.pnl-by-pair-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.pnl-by-pair-symbol {
  width: 70px;
  flex-shrink: 0;
  font-size: 10.5px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.pnl-by-pair-track {
  flex: 1;
  height: 8px;
  background: var(--surface-2);
  border-radius: 4px;
  overflow: hidden;
}
.pnl-by-pair-bar {
  height: 100%;
  border-radius: 4px;
}
.pnl-by-pair-bar.badge-good { background: var(--good); }
.pnl-by-pair-bar.badge-critical { background: var(--critical); }
.pnl-by-pair-value {
  width: 64px;
  flex-shrink: 0;
  text-align: right;
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
}

/* Tercer gráfico: distribución de escalones DCA, mismo patrón de barras horizontales */
.steps-distribution {
  height: 220px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 2px 4px;
}
.steps-distribution-row {
  display: flex;
  align-items: center;
  gap: 6px;
}
.steps-distribution-label {
  width: 38px;
  flex-shrink: 0;
  font-size: 10.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.steps-distribution-track {
  flex: 1;
  height: 8px;
  background: var(--surface-2);
  border-radius: 4px;
  overflow: hidden;
}
.steps-distribution-bar {
  height: 100%;
  border-radius: 4px;
  background: var(--series-1);
}
.steps-distribution-value {
  width: 44px;
  flex-shrink: 0;
  text-align: right;
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
}
.steps-distribution-invested {
  width: 68px;
  flex-shrink: 0;
  text-align: right;
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
}
.steps-distribution-track-spacer {
  flex: 1;
}
.steps-distribution-header {
  color: var(--muted);
  font-size: 10px;
}
.steps-distribution-header .steps-distribution-value,
.steps-distribution-header .steps-distribution-invested {
  font-weight: 600;
}
.steps-distribution-row-clickable {
  cursor: pointer;
  border-radius: 4px;
}
.steps-distribution-row-clickable:hover {
  background: var(--surface-2);
}
.steps-distribution-symbols {
  display: none;
  font-size: 10px;
  color: var(--text-secondary);
  background: var(--surface-2);
  border-radius: 4px;
  /* Sin padding horizontal a propósito: el texto tiene que arrancar exactamente donde
     arranca el label del escalón (0, mismo borde izquierdo que la fila de arriba) y la
     caja tiene que llegar hasta el borde derecho de la columna Inversión -- ambos bordes
     ya coinciden solos porque esta fila es un div de ancho completo, hermano de
     .steps-distribution-row dentro del mismo contenedor (mismo padding heredado). Con
     padding propio quedaba corrida hacia adentro de los dos lados (pedido explícito). */
  padding: 4px 0;
  margin: -2px 0 2px;
}
.steps-distribution-symbol-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  padding: 2px 0;
}
.steps-distribution-symbol-name {
  font-weight: 600;
}
.steps-distribution-symbol-invested {
  font-variant-numeric: tabular-nums;
  flex-shrink: 0;
}
.steps-distribution-symbols.open {
  display: block;
}

/* Cuarto gráfico (a modo de prueba): posiciones más cerca de disparar compra o TP */
.closest-execute {
  height: 220px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 2px 4px;
}
.closest-execute-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.closest-execute-symbol {
  width: 66px;
  flex-shrink: 0;
  font-size: 10.5px;
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.closest-execute-track {
  flex: 1;
  height: 8px;
  background: var(--surface-2);
  border-radius: 4px;
  overflow: hidden;
}
.closest-execute-bar {
  height: 100%;
  border-radius: 4px;
}
.closest-execute-bar.buy { background: var(--critical); }
.closest-execute-bar.tp { background: var(--good); }
/* Trailing Stop: mismo ámbar que ya usa el pill de escalón maxeado (--series-3) para
   "estado intermedio" -- ni la venta clásica (verde) ni la próxima compra (rojo). */
.closest-execute-bar.trailing { background: var(--series-3); }
.closest-execute-value {
  width: 34px;
  flex-shrink: 0;
  text-align: right;
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
}
.closest-execute-type {
  width: 60px;
  flex-shrink: 0;
  text-align: right;
  font-size: 10.5px;
}
.closest-execute-type.buy { color: var(--critical); }
.closest-execute-type.tp { color: var(--good); }
.closest-execute-type.trailing { color: var(--series-3); }

/* Nivel De Exposición: 2 tacómetros (Invertido Hoy / Comprometido Si Todo Cae) -- ver
   renderExposureGauges en app.js. Cada zona del arco es un <path> propio (mismo gradiente
   userSpaceOnUse detrás de los 2) para poder mostrar una explicación distinta al pasar el
   mouse por cada tramo de color, pedido explícito. */
/* "Invertido Hoy" y "Comprometido Si Todo Cae" viven cada uno en su propio chart-panel
   (separados a pedido explícito, antes compartían un panel "Nivel De Exposición") -- el
   título y el ícono de info ya los pone el chart-header-row del panel, esta tarjeta es
   solo el gauge + su lectura. */
.exposure-gauge {
  /* 355px (no 296px): arco 20% más grande, pedido explícito 2026-09-28 -- el ancho real lo
     define este max-width porque el SVG interno escala a "width: 100%" del contenedor. */
  max-width: 355px;
  margin: 0 auto;
  text-align: center;
}
.exposure-gauge-svg { width: 100%; display: block; }
.exposure-gauge-zone { cursor: pointer; }
.exposure-gauge-value {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 7px;
  margin-top: -6px;
}
.exposure-gauge-value .num { font-size: 18px; font-weight: 600; color: var(--text-primary); }
.exposure-gauge-legend {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-top: 8px;
  font-size: 10.5px;
  color: var(--text-secondary);
  flex-wrap: wrap;
}
.exposure-gauge-legend span { display: inline-flex; align-items: center; gap: 4px; }
.exposure-gauge-legend i {
  width: 7px; height: 7px; border-radius: 50%; display: inline-block;
}
.exposure-gauge-caption {
  font-size: 11px;
  color: var(--muted);
  line-height: 1.45;
  margin-top: 8px;
  min-height: 30px;
}
/* Usado solo por los medidores de Invertido Hoy / Comprometido Si Todo Cae (y la barra de
   Uso en Admin) -- colores de la paleta de Portafolio (--portfolio-N), no de --good/
   --warning/--critical, para que compartan familia de colores (pedido explícito 2026-09-28). */
.pill.state-good { background: color-mix(in srgb, var(--portfolio-8) 18%, transparent); color: var(--portfolio-8); }
.pill.state-warning { background: color-mix(in srgb, var(--portfolio-3) 18%, transparent); color: var(--portfolio-3); }
.pill.state-critical { background: color-mix(in srgb, var(--portfolio-4) 18%, transparent); color: var(--portfolio-4); }

/* Portafolio abierto: inventario a la izquierda (1/3) y dona protagonista a la derecha
   (2/3). La distribución horizontal evita que muchas posiciones achiquen el gráfico. */
.portfolio-pie {
  height: 250px;
  display: grid;
  grid-template-columns: minmax(150px, 1fr) minmax(220px, 2fr);
  gap: 14px;
}
.portfolio-pie-donut {
  min-width: 0;
  display: grid;
  place-items: center;
  border-radius: 10px;
  background: radial-gradient(circle, color-mix(in srgb, var(--series-1) 11%, var(--surface-2)) 0 29%, transparent 30%);
}
.portfolio-pie-donut svg { width: min(200px, 90%); height: min(200px, 90%); overflow: visible; filter: drop-shadow(0 12px 18px rgba(0,0,0,.28)); }
.portfolio-pie-slice {
  /* Borde negro a modo de "plomo" entre porciones -- separa y tapa el diente de sierra
     del antialiasing en el límite entre dos degradés saturados. Antes vivía en `opacity`
     (grupo) y `stroke` con alpha propio, así que se multiplicaban entre sí (.55 x .8 ≈ .44)
     y el negro terminaba gris y lavado. fill-opacity/stroke-opacity los separa: el relleno
     sigue atenuado, el borde queda 100% negro sólido. */
  fill-opacity: .8;
  stroke: #000; stroke-opacity: .85; stroke-width: 0.75; stroke-linejoin: round;
  /* stroke-width fino en un viewBox chico (108) se re-escala a menos de 1px real si baja de
     ~0.6 -- ahí "auto" cae en un muestreo de baja calidad; geometricPrecision fuerza el
     antialiasing bueno en vez de verse pixelado/con dientes en el trazo entre porciones. */
  shape-rendering: geometricPrecision;
  opacity: 1; transform-origin: 54px 54px; transition: transform .2s ease, filter .2s ease, opacity .2s ease;
}
.portfolio-pie-slice:hover { transform: scale(1.035); filter: brightness(1.18); }
.portfolio-pie-total-label {
  fill: var(--text-primary);
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.portfolio-pie-total-sublabel {
  fill: var(--muted);
  font-size: 6.5px;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.portfolio-pie-legend {
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 2px 5px 2px 2px;
  scrollbar-width: thin;
}
.portfolio-pie-legend-head {
  position: sticky; top: 0; z-index: 2;
  /* Mismas columnas Y mismo gap que .portfolio-pie-legend-row -- son grids separados (cada
     fila es su propio contenedor), así que si alguno de los dos difiere, la 3ra columna
     ("auto", Valor) se mide por el contenido de CADA fila por separado y "Peso" termina en
     una posición distinta entre el título y los valores (bug real reportado, se veía
     desalineado aunque los dos tuvieran text-align:center). minmax(0, 42px) en vez de "auto"
     (un ancho por contenido en cada fila es justo lo que rompía la alineación) NI de un
     ancho fijo a secas (con la columna angosta de este panel, un ancho fijo no podía
     encogerse y el "Peso" quedaba cortado -- bug real reportado 2026-09-23 al probarlo). El
     mínimo en 0 dejar que la 3ra columna ceda espacio antes que desbordar el panel; el
     overflow:ellipsis de .portfolio-pie-amount cubre el caso de un monto que no entre. */
  display: grid; grid-template-columns: 10px minmax(45px, 1fr) minmax(0, 42px) 38px; gap: 7px;
  padding: 3px 5px; color: var(--text-primary); background: var(--surface-2);
  font-size: 7px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
}
.portfolio-pie-legend-head span:first-child { grid-column: 1 / 3; }
.portfolio-pie-legend-head span:nth-child(n+2) { text-align: right; }
.portfolio-pie-legend-head span:last-child { text-align: center; }
.portfolio-pie-legend-row {
  display: grid;
  grid-template-columns: 10px minmax(45px, 1fr) minmax(0, 42px) 38px;
  align-items: center;
  gap: 7px;
  min-height: 23px;
  padding: 3px 5px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: color-mix(in srgb, var(--surface-1) 64%, transparent);
  transition: border-color .18s ease, transform .18s ease, background .18s ease;
}
/* Sin transform: correr la fila con translateX en :hover corre el borde derecho por
   debajo del cursor -- al quedar el mouse "afuera" del elemento se dispara un loop de
   hover on/off (titileo). El resaltado (borde + fondo) alcanza para marcar la fila. */
.portfolio-pie-legend-row:hover { border-color: color-mix(in srgb, var(--series-1) 35%, var(--border)); background: color-mix(in srgb, var(--series-1) 8%, var(--surface-1)); }
.portfolio-pie-swatch {
  width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; opacity: .8;
  box-shadow: 0 0 0 2px color-mix(in srgb, currentColor 12%, transparent), 0 0 7px currentColor;
}
.portfolio-pie-swatch.is-other { background: var(--muted); opacity: .55; }
.portfolio-pie-symbol {
  min-width: 0;
  font-size: 9px;
  font-weight: 700;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.portfolio-pie-amount {
  font-size: 8.5px;
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.portfolio-pie-pct {
  text-align: center;
  font-size: 8.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
@media (max-width: 620px) {
  .portfolio-pie { height: auto !important; grid-template-columns: 1fr; }
  .portfolio-pie-legend { max-height: 190px; order: 2; }
  .portfolio-pie-donut { min-height: 235px; order: 1; }
  .portfolio-pie-donut svg { width: 210px; height: 210px; }
}

.table-toolbar {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 10px;
  font-size: 12px;
  color: var(--text-primary);
}
.table-toolbar select {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-primary);
  padding: 5px 8px;
  font-size: 12px;
  margin-left: 6px;
}

.table-scroll {
  overflow-x: auto;
}

/* Movimientos (Stake): la lista puede tener decenas de filas (cada rescate/inversión
   automática suma una) — altura fija con scroll vertical propio, en vez de estirar la
   página entera, mismo patrón que .billing-charges-wrap. */
.stake-movements-wrap {
  max-height: 360px;
  overflow-y: auto;
  border: 1px solid var(--border);
  border-radius: 8px;
}
.stake-movements-wrap thead th {
  position: sticky;
  top: 0;
  background: var(--surface-1);
  z-index: 1;
}

.admin-row-warning td:first-child {
  box-shadow: inset 3px 0 0 var(--critical);
}

.admin-row-clickable { cursor: pointer; }
.admin-row-clickable:hover { background: var(--surface-2); }
.admin-badge {
  display: inline-block;
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--series-1);
  border: 1px solid var(--series-1);
  border-radius: 3px;
  padding: 1px 4px;
  margin-left: 4px;
  vertical-align: middle;
}
#admin-users-table td.admin-col-center,
#admin-users-table th.admin-col-center {
  text-align: center;
}
/* %Trans./%Ut. Trade/%Stake -- texto de solo lectura, no editable (pedido explícito: esas
   3 tarifas ya no se cambian a mano, las decide el Tramo Tarifario de cada cliente solo).
   Sin borde ni fondo de input, sin flechitas de <input type=number> -- ya no aplica ningún
   color rojo/verde tampoco, no hay "cambio pendiente" que marcar. */
.admin-rate-value {
  font-size: 11px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
}
#admin-users-table td.admin-col-narrow,
#admin-users-table th.admin-col-narrow {
  text-align: center;
  padding-left: 1px;
  padding-right: 1px;
}
/* "%Trans." corrido ~6mm a la derecha respecto al resto de los encabezados angostos. */
#admin-users-table th.admin-col-trans-header { padding-left: 23.8px; }

/* Botones de acción por cliente (Hacer/Quitar Admin, Avisar Pago Pendiente, Borrar Cliente)
   -- pedido explícito de un look "más elegante y sobrio": ícono lineal (SVG, currentColor)
   en gris apagado por defecto, sin borde ni fondo de color permanente -- el color de
   intención (rojo/ámbar/azul) recién aparece al pasar el mouse, mismo criterio que los
   íconos ghost de la topbar (sutiles todo el tiempo, no gritan). stopPropagation en JS
   evita que el click dispare "Ver Dashboard De Este Cliente" (la fila entera es
   clickeable, ver renderAdminUsers). */
.admin-actions-cell {
  display: flex;
  gap: 4px;
  justify-content: center;
}
/* button.admin-action-btn (no solo .admin-action-btn) a propósito -- "button.ghost" (el
   estilo base) tiene la misma cantidad de clases pero SUMA el elemento "button" a la
   especificidad, así que le ganaba a una regla de una sola clase sin importar el orden en
   el archivo (mismo motivo que el bug ya encontrado con .admin-rate-input.rate-changed). */
button.admin-action-btn {
  width: 24px;
  height: 24px;
  padding: 0;
  border-radius: 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  background: transparent;
  border: 1px solid transparent;
  color: var(--muted);
}
.admin-action-btn svg { width: 14px; height: 14px; }
button.admin-action-btn:hover { filter: none; background: var(--surface-2); border-color: var(--border); }
.admin-action-btn.delete:hover { color: var(--critical); border-color: var(--critical); }
.admin-action-btn.warning:hover { color: var(--warning); border-color: var(--warning); }
.admin-action-btn.promote:hover { color: var(--series-1); border-color: var(--series-1); }
.admin-action-btn.invitation:hover { color: var(--good); border-color: var(--good); }
.admin-action-btn.audit:hover, .admin-action-btn.billing:hover, .admin-action-btn.rate-menu:hover { color: var(--series-1); border-color: var(--series-1); }
/* Ícono (mismo que "Ver Bitácora Del Usuario") justo antes de cada input de %Trans./
   %Ut. Trade/%Stake -- ver TODO en renderAdminUsers, todavía no tiene acción definida. */
.admin-rate-cell { display: flex; align-items: center; justify-content: center; gap: 4px; }

/* Modal "Tramo tarifario" -- desglose personalizado de un cliente (ver openRateTierModal
   en app.js y app/admin.py::compute_tariff_breakdown). Reutiliza la misma rampa de color
   secuencial de Tramos Tarifarios (Facturación) para las insignias de tramo, así los dos
   cuadros se leen como una sola familia visual en toda la app. */
.rate-tier-modal-box { width: min(640px, 94vw); }

/* Modal "Facturación Del Cliente" (pedido explícito 2026-10-06, ver openClientBilling en
   app.js y app/admin_billing.py). Reutiliza las tarjetas y las insignias de Tramo Tarifario. */
/* .modal.client-billing-box (2 clases): con una sola, la regla base .modal (más abajo en el
   archivo, misma especificidad) le ganaba y el modal quedaba en 880px. */
.modal.client-billing-box { width: min(1180px, 96vw); max-height: 92vh; }
.client-billing-header-actions { display: flex; gap: 8px; }
.client-billing-loading { padding: 28px 0; text-align: center; color: var(--muted); font-size: 13px; }
.client-billing-kpis { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 10px; }
@media (max-width: 900px) { .client-billing-kpis { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 560px) { .client-billing-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.client-billing-kpi {
  padding: 11px 12px; text-align: center;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 10px;
}
.client-billing-kpi .label { color: var(--muted); font-size: 10.5px; font-weight: 600; }
.client-billing-kpi .value { margin-top: 4px; font-size: 17px; font-weight: 700; font-variant-numeric: tabular-nums; color: var(--text-primary); }
.client-billing-kpi .value.good { color: var(--good); }
.client-billing-kpi .value.critical { color: var(--critical); }
.client-billing-kpi .sub { margin-top: 3px; color: var(--muted); font-size: 10px; }
.client-billing-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 14px; }
@media (max-width: 760px) { .client-billing-cards { grid-template-columns: 1fr; } }
.client-billing-line { display: flex; justify-content: space-between; gap: 10px; font-size: 11.5px; color: var(--text-secondary); }
.client-billing-line strong { color: var(--text-primary); font-weight: 600; font-variant-numeric: tabular-nums; text-align: right; }
.client-billing-line strong.critical { color: var(--critical); }
.client-billing-line strong.good { color: var(--good); }
.client-billing-note { font-size: 11px; color: var(--muted); }
.client-billing-note.warning { color: var(--warning); }
.client-billing-card-actions { display: flex; justify-content: flex-end; }
.client-billing-card-actions button { padding: 4px 10px; font-size: 11.5px; }
.client-billing-section-title { margin: 18px 0 8px; font-size: 13px; font-weight: 700; color: var(--text-primary); }
.client-billing-section-title span { margin-left: 8px; font-size: 11px; font-weight: 400; color: var(--muted); }
.client-billing-table td, .client-billing-table th { white-space: nowrap; }
.client-billing-table tbody tr.client-billing-month { cursor: pointer; }
.client-billing-table tbody tr.client-billing-month:hover { background: var(--surface-2); }
.client-billing-table tbody tr.client-billing-month.open { background: var(--surface-2); }
.client-billing-table .month-caret { display: inline-block; width: 12px; color: var(--muted); transition: transform .15s; }
.client-billing-table tr.open .month-caret { transform: rotate(90deg); }
.client-billing-table tr.client-billing-detail > td { padding: 10px 14px 14px; background: var(--surface-2); white-space: normal; }
.client-billing-detail-grid { display: flex; flex-wrap: wrap; gap: 6px 22px; margin-bottom: 10px; font-size: 11.5px; color: var(--text-secondary); }
.client-billing-detail-grid strong { color: var(--text-primary); font-weight: 600; }
.client-billing-mini { width: 100%; border-collapse: collapse; font-size: 11.5px; }
.client-billing-mini th { text-align: left; color: var(--muted); font-weight: 600; padding: 4px 6px; border-bottom: 1px solid var(--border); }
.client-billing-mini td { padding: 4px 6px; border-bottom: 1px solid color-mix(in srgb, var(--border) 50%, transparent); font-variant-numeric: tabular-nums; }
.client-billing-mini-scroll { max-height: 260px; overflow-y: auto; }
.rate-tier-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; margin-top: 16px; }
@media (max-width: 560px) { .rate-tier-grid { grid-template-columns: 1fr; } }

.rate-tier-card {
  display: flex; flex-direction: column; gap: 10px;
  padding: 13px 14px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
}
.rate-tier-card-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.rate-tier-card-title { font-size: 12px; font-weight: 700; color: var(--text-primary); }
.rate-tier-card-period { margin-top: -3px; color: var(--muted); font-size: 10px; }

/* Editar quién refirió a ESTE cliente (distinto de la lista de a quiénes referenció él,
   que va en la tarjeta de la derecha) -- único lugar para corregirlo después del alta. */
.rate-tier-referrer-row {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  margin-top: 14px; padding: 10px 12px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.rate-tier-referrer-row label { font-size: 11.5px; color: var(--text-secondary); flex-shrink: 0; }
/* Buscador (no <select>) -- pedido explícito: la lista de usuarios va a crecer mucho y un
   desplegable plano se vuelve inmanejable. Reutiliza el mismo componente .search-row /
   .search-results que ya usa el buscador de pares de DCA, solo que filtra en el cliente
   (adminUsersData ya está cargado) en vez de pegarle a una API. */
/* .rate-tier-referrer-search-row.search-row (2 clases, no 1) a propósito -- le gana en
   especificidad a ".search-row" de más abajo (que trae margin-bottom:16px, pensado para el
   buscador de DCA) sin importar el orden en el archivo. Con una sola clase, "margin-bottom:
   0" perdía contra esa regla y los 16px de margen de más corrían el recuadro 8px hacia
   arriba dentro de la fila -- bug real, confirmado con getBoundingClientRect(). */
.rate-tier-referrer-search-row.search-row { flex: 1; min-width: 160px; margin-bottom: 0; align-self: center; }
.rate-tier-referrer-search-row input[type="text"] { max-width: none; font-size: 12px; padding: 7px 9px; line-height: normal; }

/* Insignia de tramo -- paleta de metales (pedido explícito 2026-10-11): fondo oscuro tintado,
   filo y texto del color del metal. Los 4 tramos salen de las variables --tier-N-* de abajo,
   las mismas que usa el encabezado de la tabla de Tramos Tarifarios. */
:root {
  --tier-1-bg: #45270E; --tier-1-edge: #E08A3C; --tier-1-text: #FFC285;
  --tier-2-bg: #2C3441; --tier-2-edge: #BCC9DC; --tier-2-text: #EEF3FB;
  --tier-3-bg: #47340A; --tier-3-edge: #F0BE35; --tier-3-text: #FFE08A;
  --tier-4-bg: #22306A; --tier-4-edge: #7C9BFF; --tier-4-text: #E4ECFF;
}
.rate-tier-tramo-badge {
  display: inline-flex; align-items: center; padding: 3px 11px;
  border-radius: 999px; border: 1px solid transparent; font-size: 10px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; white-space: nowrap;
}
.rate-tier-tramo-badge.tramo-1 { background: var(--tier-1-bg); border-color: var(--tier-1-edge); color: var(--tier-1-text); }
.rate-tier-tramo-badge.tramo-2 { background: var(--tier-2-bg); border-color: var(--tier-2-edge); color: var(--tier-2-text); }
.rate-tier-tramo-badge.tramo-3 { background: var(--tier-3-bg); border-color: var(--tier-3-edge); color: var(--tier-3-text); }
.rate-tier-tramo-badge.tramo-4 { background: var(--tier-4-bg); border-color: var(--tier-4-edge); color: var(--tier-4-text); }
.rate-tier-tramo-badge-big { padding: 5px 14px; font-size: 12px; }

.rate-tier-months { display: flex; flex-direction: column; gap: 5px; }
.rate-tier-month-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 11px; color: var(--text-secondary); }
.rate-tier-month-row strong { color: var(--text-primary); font-weight: 600; font-variant-numeric: tabular-nums; }
.rate-tier-empty-hint { color: var(--muted); font-size: 11px; font-style: italic; }
.rate-tier-manual-tag {
  margin-left: 4px; padding: 1px 6px; border-radius: 999px;
  background: color-mix(in srgb, var(--series-3) 18%, transparent);
  color: var(--series-3); font-size: 9px; font-weight: 700;
}

/* Carga manual, única vez, de M-1/M-2 para un cliente sin ningún cierre todavía (ver
   saveRateTierManualSaldo) -- de ahí en más el ciclo normal de cierres los reemplaza solo. */
.rate-tier-month-pending input {
  width: 110px; text-align: right;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 5px;
  color: var(--text-primary);
  padding: 4px 7px;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}
/* Mismo tamaño que cualquier otro botón "Guardar" de la app (sin ancho forzado al 100%) --
   pedido explícito de no dejarlo más ancho que el resto -- centrado en el recuadro. */
.rate-tier-manual-save { align-self: center; margin-top: 4px; }

.rate-tier-avg-row {
  display: flex; align-items: center; justify-content: space-between;
  margin-top: auto; padding-top: 9px; border-top: 1px dashed var(--border);
  font-size: 11.5px; color: var(--text-secondary);
}
.rate-tier-avg-row strong { font-size: 16px; color: var(--text-primary); font-variant-numeric: tabular-nums; }

/* Alto para ~10 referidos visibles sin scroll (pedido explícito) -- de ahí en más scrollea. */
.rate-tier-referral-list { display: flex; flex-direction: column; gap: 5px; max-height: 230px; overflow-y: auto; }
.rate-tier-referral-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 11px; }
.rate-tier-referral-email {
  flex: 1; min-width: 0; color: var(--text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rate-tier-referral-status { flex-shrink: 0; padding: 2px 7px; border-radius: 999px; font-size: 9.5px; font-weight: 700; }
.rate-tier-referral-status.active { color: var(--good); background: color-mix(in srgb, var(--good) 15%, transparent); }
.rate-tier-referral-status.inactive { color: var(--muted); background: color-mix(in srgb, var(--muted) 15%, transparent); }

.rate-tier-applied {
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
  margin-top: 14px; padding: 12px 14px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
}
.rate-tier-applied-label { font-size: 11.5px; font-weight: 600; color: var(--text-primary); }
.rate-tier-applied-reason { color: var(--muted); font-size: 11px; }

.rate-tier-fees { display: flex; gap: 10px; margin-top: 12px; }
.rate-tier-fee {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 11px 8px; text-align: center;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
}
.rate-tier-fee svg { width: 16px; height: 16px; color: var(--series-1); }
.rate-tier-fee span { font-size: 10px; color: var(--muted); }
.rate-tier-fee strong { font-size: 15px; color: var(--text-primary); font-variant-numeric: tabular-nums; }

/* Descuento manual de tarifa (pedido explícito 2026-09-06) -- un admin puede fijar a mano
   las 3 tarifas de un cliente para un rango de meses, excluyéndolo del cálculo automático
   por Saldo Total/Referidos Activos mientras dure. */
/* [hidden] explícito por el mismo bug de especificidad que .altfins-cards[hidden] de más
   arriba: display:flex/grid de una clase empata en especificidad con el display:none que el
   navegador le da a [hidden], y como el CSS del sitio carga después, sin esto quedaban
   visibles igual estando hidden. */
.rate-tier-override-banner[hidden],
.rate-tier-grid[hidden],
.rate-tier-applied[hidden],
.rate-tier-override-form[hidden] { display: none; }

.rate-tier-override-banner {
  display: flex; align-items: flex-start; gap: 10px;
  margin-top: 16px; padding: 12px 14px;
  background: color-mix(in srgb, var(--series-3) 12%, var(--surface-2));
  border: 1px solid color-mix(in srgb, var(--series-3) 45%, var(--border));
  border-radius: 10px;
}
.rate-tier-override-banner-icon { flex: none; color: var(--series-3); font-size: 15px; line-height: 1.4; }
.rate-tier-override-banner strong { display: block; font-size: 12.5px; color: var(--text-primary); }
.rate-tier-override-banner p { margin: 2px 0 0; font-size: 11px; color: var(--text-secondary); line-height: 1.4; }

.rate-tier-override-section { margin-top: 16px; }
.rate-tier-override-header {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  margin-bottom: 8px;
}
/* Alto fijo + scroll propio (pedido explícito 2026-09-11): con el tiempo se acumulan
   descuentos vencidos/cancelados -- sin esto, la lista crecía sin límite y empujaba el resto
   del modal cada vez más abajo. El historial completo sigue estando ahí, solo con scroll
   adentro en vez de estirar el modal -- mismo patrón que .portfolio-pie-legend/
   .steps-distribution-container. */
.rate-tier-override-list {
  display: flex; flex-direction: column; gap: 6px; margin-bottom: 8px;
  max-height: 260px; overflow-y: auto; scrollbar-width: thin;
}
.rate-tier-override-empty { color: var(--muted); font-size: 11px; margin: 0 0 8px; }
.rate-tier-override-item {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 11px;
}
.rate-tier-override-item-info { flex: 1; min-width: 0; }
.rate-tier-override-item-range { color: var(--text-primary); font-weight: 600; }
.rate-tier-override-item-fees { color: var(--muted); }
.rate-tier-override-item-note { color: var(--muted); font-style: italic; margin-top: 2px; }
.rate-tier-override-item-trace { color: var(--muted); font-size: 9.5px; margin-top: 2px; }
.rate-tier-override-status {
  flex: none; padding: 2px 8px; border-radius: 999px; font-size: 9.5px; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.03em;
}
.rate-tier-override-status--active { background: color-mix(in srgb, var(--good) 20%, transparent); color: var(--good); }
.rate-tier-override-status--expired { background: color-mix(in srgb, var(--muted) 20%, transparent); color: var(--muted); }
.rate-tier-override-status--cancelled { background: color-mix(in srgb, var(--critical) 18%, transparent); color: var(--critical); }
.rate-tier-override-cancel-btn { flex: none; padding: 4px 10px; font-size: 10.5px; }

.rate-tier-override-form {
  display: flex; flex-direction: column; gap: 8px;
  padding: 12px 14px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 10px;
}
.rate-tier-override-form-row { display: flex; gap: 8px; }
.rate-tier-override-form-row label {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; gap: 4px;
  font-size: 10.5px; color: var(--text-secondary);
}
.rate-tier-override-note-label { flex: 1; }
.rate-tier-override-form-row input {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-primary);
  padding: 6px 8px;
  font-size: 12px;
}
.rate-tier-override-form-actions { display: flex; justify-content: flex-end; gap: 8px; }
.rate-tier-override-error { color: var(--critical); font-size: 11px; min-height: 14px; }

/* Ya es admin: el ícono de escudo queda tenuemente celeste en reposo (no gris parejo con
   los demás) para poder distinguir de un vistazo quién ya tiene el rol, sin necesitar hover. */
.admin-action-btn.promote.is-admin { color: var(--series-1); }

/* Administración: accesos y ventanas independientes de bitácoras. */
.admin-module-subtitle { margin-top: 4px; color: var(--muted); font-size: 11px; }
.audit-launch-panel { display: flex; align-items: center; justify-content: space-between; gap: 18px; }
/* Botones de esta fila (Bitácora De Usuarios / Bitácora Admin. / API Keys AltFins):
   sin ícono ni subtítulo -- mismo botón "de serie" que Crear Cliente (#btn-create-client),
   solo el contenedor decide cómo se acomodan entre sí. */
.audit-launch-actions { display: flex; flex-wrap: wrap; gap: 10px; }
.audit-filters { display: flex; align-items: flex-end; flex-wrap: wrap; gap: 10px; margin: 16px 0 14px; }
/* Sin text-transform: uppercase -- pedido explícito de sentencia (solo inicio de frase),
   no Title Case ni mayúscula sostenida en ningún texto de la Bitácora. */
.audit-filters label { display: flex; flex-direction: column; gap: 5px; color: var(--text-primary); font-size: 10px; font-weight: 650; letter-spacing: .04em; }
.audit-filters input, .audit-filters select { height: 34px; padding: 7px 9px; border: 1px solid var(--border); border-radius: 6px; background: var(--surface-2); color: var(--text-primary); }
.audit-keyword-field { flex: 1 1 250px; }
.audit-keyword-field input { width: 100%; }
.audit-result-count { margin-left: auto; padding-bottom: 9px; color: var(--muted); font-size: 11px; }
.audit-export-btn { color: var(--good); border-color: color-mix(in srgb, var(--good) 45%, var(--border)); }
.audit-export-btn:hover { color: var(--good); border-color: var(--good); background: color-mix(in srgb, var(--good) 8%, transparent); }
.audit-table-wrap { max-height: 460px; border: 1px solid var(--border); border-radius: 8px; }
.audit-table { min-width: 980px; }
.audit-table thead { position: sticky; top: 0; z-index: 1; background: var(--surface-1); }
.audit-table td { vertical-align: top; }
.audit-action-cell { min-width: 220px; white-space: normal; }
.audit-details { max-width: 340px; margin-top: 4px; color: var(--muted); font: 10px/1.4 ui-monospace, SFMono-Regular, Consolas, monospace; overflow-wrap: anywhere; }
.audit-status { display: inline-flex; padding: 3px 7px; border-radius: 999px; font-size: 10px; font-weight: 700; }
.audit-status.ok { color: var(--good); background: color-mix(in srgb, var(--good) 12%, transparent); }
.audit-status.error { color: var(--critical); background: color-mix(in srgb, var(--critical) 12%, transparent); }
.audit-user-modal, .audit-browser-modal { z-index: 140; }
.audit-user-modal .modal, .audit-browser-modal .modal { width: min(1120px, 95vw); max-height: 90vh; }
.altfins-keys-modal { z-index: 140; }
.altfins-keys-modal .modal { width: min(1180px, 96vw); max-height: 92vh; }
.altfins-schedule-form { display: flex; align-items: flex-end; flex-wrap: wrap; gap: 10px; margin-top: 18px; padding: 12px 14px; border: 1px solid color-mix(in srgb, var(--series-1) 35%, var(--border)); border-radius: 9px; background: color-mix(in srgb, var(--series-1) 7%, var(--surface-2)); }
/* Sin text-transform: uppercase -- pedido explícito de dejar la etiqueta con la
   capitalización tal cual está escrita en el HTML, no toda en mayúscula. */
.altfins-schedule-form label { display: flex; flex-direction: column; gap: 5px; color: var(--text-primary); font-size: 10px; font-weight: 650; }
.altfins-schedule-form input { width: 105px; height: 34px; padding: 7px 9px; border: 1px solid var(--border); border-radius: 6px; background: var(--surface-1); color: var(--text-primary); }
/* Envuelve el botón Guardar y el resumen juntos, centrados entre sí en su propia fila --
   así el texto queda a la altura exacta del texto del botón sin importar cuánto más alto
   sea el campo de al lado (pedido explícito: alineados en altura entre ellos dos). */
.altfins-schedule-actions { display: flex; align-items: center; gap: 10px; flex: 1 1 280px; }
.altfins-schedule-summary { color: var(--text-secondary); font-size: 11px; }
/* Recuadro informativo (pedido explícito 2026-09-30): reemplaza el campo "N° de
   Actualizaciones Diarias" -- ya no hay nada que configurar, solo cómo se consume altFINS. */
.altfins-usage-info { flex-direction: column; align-items: flex-start; gap: 4px; }
.altfins-usage-info .altfins-schedule-summary:first-child { color: var(--text-primary); font-size: 12px; font-weight: 600; }
.altfins-key-form { display: grid; grid-template-columns: minmax(180px, 1fr) minmax(240px, 2fr) 100px auto; align-items: end; gap: 10px; margin: 18px 0 10px; }
/* Ídem .altfins-schedule-form label: sin uppercase, capitalización tal cual el HTML. */
.altfins-key-form label { display: flex; flex-direction: column; gap: 5px; color: var(--text-primary); font-size: 10px; font-weight: 650; }
.altfins-key-form input { height: 34px; padding: 7px 9px; border: 1px solid var(--border); border-radius: 6px; background: var(--surface-2); color: var(--text-primary); }
.altfins-key-help { margin-bottom: 14px; color: var(--muted); font-size: 11px; }
.altfins-keys-table-wrap { max-height: 480px; border: 1px solid var(--border); border-radius: 8px; }
.altfins-keys-table { min-width: 1050px; }
.altfins-keys-table input { width: 100%; min-width: 70px; padding: 6px 7px; border: 1px solid var(--border); border-radius: 5px; background: var(--surface-2); color: var(--text-primary); }
.altfins-key-label-input { min-width: 150px !important; }
.altfins-key-masked { font-family: ui-monospace, SFMono-Regular, Consolas, monospace; }
.altfins-credit-value { font-variant-numeric: tabular-nums; white-space: nowrap; }
.altfins-key-error { max-width: 210px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); }
.altfins-key-status { display: inline-flex; padding: 3px 7px; border-radius: 999px; font-size: 10px; font-weight: 700; white-space: nowrap; }
.altfins-key-status.ok { color: var(--good); background: color-mix(in srgb, var(--good) 12%, transparent); }
.altfins-key-status.active { color: #8bc4ff; background: rgba(57,135,229,.16); box-shadow: inset 0 0 0 1px rgba(99,168,255,.28); }
.altfins-key-status.warning { color: var(--warning); background: color-mix(in srgb, var(--warning) 12%, transparent); }
.altfins-key-status.error { color: var(--critical); background: color-mix(in srgb, var(--critical) 12%, transparent); }
.altfins-key-status.disabled { color: var(--muted); background: var(--surface-2); }
.altfins-key-actions { display: flex; gap: 5px; }
.altfins-key-actions button { padding: 5px 7px; font-size: 10px; white-space: nowrap; }
.altfins-key-actions .altfins-delete:hover { color: var(--critical); border-color: var(--critical); }
.altfins-key-detail-modal { z-index: 160; }
.altfins-key-detail-modal .modal { width: min(760px, 94vw); }
.gemini-settings-modal { z-index: 145; }
.gemini-settings-modal .modal { width: min(700px, 94vw); }
.gemini-settings-status { display: flex; align-items: center; gap: 12px; margin: 18px 0; padding: 13px 15px; border: 1px solid var(--border); border-radius: 9px; background: var(--surface-2); }
.gemini-settings-status-dot { width: 10px; height: 10px; flex: 0 0 auto; border-radius: 50%; background: var(--muted); box-shadow: 0 0 0 4px color-mix(in srgb, var(--muted) 14%, transparent); }
.gemini-settings-status.configured .gemini-settings-status-dot { background: var(--good); box-shadow: 0 0 0 4px color-mix(in srgb, var(--good) 14%, transparent); }
.gemini-settings-status > div { display: flex; flex-direction: column; gap: 3px; }
.gemini-settings-status strong { font-size: 12px; }
.gemini-settings-status small { color: var(--muted); font-size: 10px; }
.gemini-settings-form { display: grid; gap: 14px; }
.gemini-settings-form > label { display: flex; flex-direction: column; gap: 6px; color: var(--text-primary); font-size: 10px; font-weight: 650; }
.gemini-settings-form input { width: 100%; height: 38px; padding: 8px 10px; border: 1px solid var(--border); border-radius: 7px; background: var(--surface-2); color: var(--text-primary); }
.gemini-settings-form label > small { color: var(--muted); font-weight: 400; }
.gemini-settings-help { display: flex; flex-direction: column; gap: 4px; padding: 12px 14px; border-left: 3px solid var(--series-1); border-radius: 0 8px 8px 0; background: color-mix(in srgb, var(--series-1) 9%, transparent); font-size: 11px; }
.gemini-settings-help span { color: var(--muted); line-height: 1.5; }
.gemini-settings-actions { display: flex; justify-content: flex-end; gap: 9px; margin-top: 4px; }
.altfins-detail-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-top: 18px; }
.altfins-detail-grid > div { min-width: 0; padding: 12px 14px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface-2); }
.altfins-detail-grid span { display: block; margin-bottom: 6px; color: var(--text-primary); font-size: 9px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase; }
.altfins-detail-grid strong { display: block; color: var(--text-primary); font-size: 13px; overflow-wrap: anywhere; }
.altfins-detail-wide { grid-column: 1 / -1; }
@media (max-width: 600px) { .altfins-detail-grid { grid-template-columns: 1fr; } .altfins-detail-wide { grid-column: auto; } }
@media (max-width: 900px) { .altfins-key-form { grid-template-columns: 1fr 1fr; } }
@media (max-width: 700px) {
  .audit-filters > label { flex: 1 1 140px; }
  .audit-filters button { flex: 1 1 auto; }
  .audit-result-count { width: 100%; margin-left: 0; padding: 0; }
  .audit-launch-panel { align-items: stretch; flex-direction: column; }
  .audit-launch-actions button { flex: 1 1 100%; }
}
/* Recordatorio De Pago activo: la campanita queda "encendida" (ámbar, con fondo tenue) en
   reposo -- pedido explícito, "mientras esté encendido debe quedar de color encendido",
   para que se note de un vistazo qué clientes tienen el aviso repitiéndose en cada login,
   sin necesitar pasar el mouse. */
.admin-action-btn.warning.active {
  color: var(--warning);
  background: color-mix(in srgb, var(--warning) 14%, transparent);
  border-color: color-mix(in srgb, var(--warning) 45%, transparent);
}

.client-view-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  background: var(--surface-2);
  border: 1px solid var(--series-1);
  border-radius: var(--radius);
  padding: 10px 16px;
  margin-bottom: 20px;
  font-size: 13px;
}

#user-view.read-only-view {
  position: relative;
  pointer-events: none;
  opacity: 0.75;
  user-select: none;
}
/* Excepciones de la vista de cliente (pedido explícito 2026-10-06): el admin puede mover el
   gráfico "PNL Acum.", abrir la lista de Dust (sin convertir, ver static/app.js) y navegar
   Facturación (mes, año, filtro, tramos). Lo que modifica algo del cliente se oculta en JS. */
#user-view.read-only-view #equity-chart-container,
#user-view.read-only-view #btn-dust,
#user-view.read-only-view .billing-panel {
  pointer-events: auto;
}
#user-view.read-only-view .billing-panel { user-select: text; }

table.pairs th[data-sort] {
  cursor: pointer;
  user-select: none;
}
table.pairs th[data-sort]:hover { color: var(--text-secondary); }
table.pairs th[data-sort].sorted-asc::after { content: " ▲"; font-size: 9px; }
table.pairs th[data-sort].sorted-desc::after { content: " ▼"; font-size: 9px; }

.activity-list {
  /* Pedido explícito: 450px fijos. */
  max-height: 450px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.activity-item {
  display: flex;
  gap: 10px;
  padding: 8px 4px;
  border-bottom: 1px solid var(--gridline);
  font-size: 12px;
}
.activity-item:last-child { border-bottom: none; }
.activity-time {
  color: var(--muted);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.activity-symbol {
  color: var(--series-1);
  font-weight: 600;
  white-space: nowrap;
}
.activity-message {
  color: var(--text-secondary);
}

.search-row {
  position: relative;
  margin-bottom: 16px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
}
/* "Dust a Usdt": misma línea que el buscador de pares, empujado hasta el borde derecho del
   recuadro de Operaciones Abiertas (pedido explícito) -- margin-left:auto lo corre sin
   afectar el ancho del input de al lado. Sin clase "ghost": el <button> sin modificadores ya
   tiene el mismo relleno de color que "Comprar Ahora" (ver regla base `button` más arriba) --
   y sin agregarle ninguna otra clase de tamaño, queda con el padding/font-size compacto por
   default en vez de estirarse (antes tomaba el ancho de una celda entera de grid del
   formulario DCA, pedido explícito de que no quede "enorme"). */
.dust-inline-btn {
  flex-shrink: 0;
}

.dca-card-tour-launch {
  margin-left: auto; flex-shrink: 0; display: inline-flex; align-items: center; gap: 7px;
  border: 1px solid color-mix(in srgb, var(--series-1) 55%, var(--border));
  background: color-mix(in srgb, var(--series-1) 12%, var(--surface-1)); color: var(--text-primary);
}
.dca-card-tour-launch svg { width: 16px; height: 16px; color: var(--series-1); }
.dca-card-tour-launch:hover { border-color: var(--series-1); box-shadow: 0 0 0 3px color-mix(in srgb, var(--series-1) 12%, transparent); }

/* Tour premium y autónomo de una tarjeta DCA. La tarjeta central es deliberadamente una
   maqueta: permite enseñar toda la interfaz sin enlazar eventos ni tocar datos reales. */
.dca-card-tour-overlay {
  display: none; position: fixed; inset: 0; z-index: 1100; padding: 24px;
  place-items: center; background: rgba(3, 7, 18, .82); backdrop-filter: blur(8px);
}
.dca-card-tour-overlay.active { display: grid; }
.dca-card-tour-window {
  width: min(1240px, 100%); max-height: calc(100vh - 48px); overflow: auto; padding: 24px;
  border: 1px solid rgba(115,174,255,.35); border-radius: 20px;
  background: linear-gradient(145deg, color-mix(in srgb, var(--surface-1) 96%, #183f72), var(--surface-1));
  color: var(--text-primary); box-shadow: 0 28px 90px rgba(0,0,0,.58);
}
.dca-card-tour-header { display: flex; justify-content: space-between; gap: 20px; align-items: flex-start; }
.dca-card-tour-header h2 { margin: 8px 0 4px; font-size: clamp(22px, 3vw, 32px); letter-spacing: -.035em; }
.dca-card-tour-header p { margin: 0; color: var(--muted); font-size: 12px; }
.dca-card-tour-layout { display: grid; grid-template-columns: minmax(0, 1.65fr) minmax(290px, .7fr); gap: 24px; align-items: stretch; }
.dca-tour-demo-wrap { min-width: 0; display: flex; align-items: center; }
.dca-tour-demo-card {
  position: relative; width: 100%; padding: 18px; overflow: hidden; border: 1px solid var(--border); border-radius: 14px;
  background: color-mix(in srgb, var(--surface-2) 94%, #102c50); box-shadow: 0 14px 35px rgba(0,0,0,.2);
}
.dca-tour-demo-top { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 16px; }
.dca-tour-demo-top > strong { margin-right: auto; font-size: 18px; letter-spacing: .02em; }
.dca-tour-demo-step, .dca-tour-demo-decimals, .dca-tour-demo-paused { padding: 6px 9px; border: 1px solid var(--border); border-radius: 7px; font-size: 11px; }
.dca-tour-demo-step { color: #63a8ff; background: rgba(57,135,229,.12); font-weight: 700; }
.dca-tour-demo-paused { display: flex; align-items: center; gap: 5px; }
.dca-tour-demo-paused i { width: 7px; height: 7px; border-radius: 50%; background: var(--positive); box-shadow: 0 0 0 3px color-mix(in srgb, var(--positive) 18%, transparent); }
.dca-tour-demo-stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.dca-tour-demo-stats > div, .dca-tour-demo-pnl, .dca-tour-demo-trailing { padding: 10px; border: 1px solid var(--gridline); border-radius: 9px; background: color-mix(in srgb, var(--surface-1) 72%, transparent); }
.dca-tour-demo-stats span, .dca-tour-demo-pnl > span { display: block; margin-bottom: 5px; color: var(--muted); font-size: 9px; text-transform: uppercase; letter-spacing: .04em; }
.dca-tour-demo-stats b { font-size: 11px; font-variant-numeric: tabular-nums; }
.dca-tour-demo-pnl { display: flex; align-items: center; gap: 12px; margin-top: 8px; }
.dca-tour-demo-pnl > span { margin: 0 auto 0 0; }
.dca-tour-demo-pnl strong, .dca-tour-demo-pnl em { color: var(--positive); font-size: 12px; font-style: normal; }
.dca-tour-demo-progress { margin: 14px 0; height: 7px; position: relative; border-radius: 8px; background: var(--gridline); }
.dca-tour-demo-progress > span { display: block; height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--series-1), var(--positive)); }
.dca-tour-demo-progress small { display: block; margin-top: 6px; color: var(--muted); font-size: 9px; }
.dca-tour-demo-fields { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; margin-top: 28px; }
.dca-tour-demo-fields label { color: var(--muted); font-size: 9px; }
.dca-tour-demo-fields input, .dca-tour-demo-fields select { width: 100%; margin-top: 5px; padding: 7px; font-size: 10px; pointer-events: none; }
.dca-tour-demo-trailing { display: flex; justify-content: space-between; gap: 10px; margin-top: 8px; color: var(--muted); font-size: 10px; }
.dca-tour-demo-trailing b { color: var(--text-primary); }
.dca-tour-demo-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 14px; }
.dca-tour-demo-actions button { padding: 8px 10px; font-size: 10px; pointer-events: none; }
.dca-tour-demo-actions .danger { border-color: color-mix(in srgb, var(--negative) 55%, var(--border)); background: color-mix(in srgb, var(--negative) 17%, var(--surface-1)); }
.dca-tour-demo-actions > span { margin-left: auto; color: var(--muted); font-size: 10px; }
.dca-tour-demo-actions > span b { color: var(--text-primary); }
.dca-tour-demo-safe { margin: 15px -18px -18px; padding: 8px; text-align: center; color: #9bcaff; background: rgba(57,135,229,.1); font-size: 9px; font-weight: 750; letter-spacing: .12em; }
.dca-card-tour-copy { align-self: stretch; padding: 20px; border: 1px solid var(--gridline); border-radius: 14px; background: rgba(0,0,0,.08); }
.dca-card-tour-copy h3 { margin: 13px 0 8px; font-size: 21px; line-height: 1.2; }
.dca-card-tour-copy > p { min-height: 86px; margin: 0; color: var(--text-secondary); font-size: 13px; line-height: 1.65; }
.dca-card-tour-copy .tour-actions { margin-top: 24px; }
.dca-tour-demo-card [data-dca-tour-target] { transition: box-shadow .2s ease, border-color .2s ease, background .2s ease, transform .2s ease; }
.dca-tour-demo-card .tour-demo-active {
  position: relative; z-index: 2; border-color: #63a8ff !important;
  background: color-mix(in srgb, #3987e5 16%, var(--surface-1)) !important;
  box-shadow: 0 0 0 4px rgba(57,135,229,.18), 0 10px 28px rgba(0,0,0,.22); transform: translateY(-1px);
}

@media (max-width: 900px) {
  .dca-card-tour-overlay { padding: 12px; }
  .dca-card-tour-window { max-height: calc(100vh - 24px); padding: 18px; }
  .dca-card-tour-layout { grid-template-columns: 1fr; }
  .dca-tour-demo-wrap { overflow-x: auto; padding: 4px 4px 12px; }
  .dca-tour-demo-card { min-width: 790px; }
  .dca-card-tour-copy > p { min-height: 0; }
}
@media (max-width: 560px) {
  .dca-card-tour-launch span { display: none; }
  .dca-card-tour-launch { padding-inline: 10px; }
  .dca-card-tour-overlay { padding: 0; }
  .dca-card-tour-window { width: 100%; height: 100%; max-height: none; border-radius: 0; padding: 16px; }
  .dca-card-tour-header { position: sticky; top: -16px; z-index: 5; padding: 12px 0; background: var(--surface-1); }
  .dca-card-tour-header p { display: none; }
  .dca-card-tour-layout { gap: 14px; }
}

/* Tour contextual de Operaciones Abiertas: la demo vive en el panel real y usa exactamente
   las clases de una tarjeta productiva; la capa guiada reutiliza el formato del tour general. */
.dca-tour-demo-host { position: relative; width: 100%; margin: 0 0 16px; }
.dca-tour-demo-host[hidden] { display: none; }
.dca-tour-demo-host.is-tour-active { padding-bottom: 340px; }
.dca-tour-demo-host .dca-card { position: relative; border-color: color-mix(in srgb, var(--series-1) 55%, var(--border)); box-shadow: 0 12px 35px rgba(0,0,0,.22), 0 0 0 3px color-mix(in srgb, var(--series-1) 9%, transparent); }
.dca-tour-demo-host .dca-card::after {
  content: "DEMO · SIN OPERACIONES REALES"; position: absolute; right: 10px; top: -10px;
  padding: 4px 8px; border: 1px solid color-mix(in srgb, var(--series-1) 48%, var(--border)); border-radius: 999px;
  background: var(--surface-1); color: #8bc4ff; font-size: 8px; font-weight: 750; letter-spacing: .09em;
}
.dca-tour-demo-host .dca-card input,
.dca-tour-demo-host .dca-card select,
.dca-tour-demo-host .dca-card button,
.dca-tour-demo-host .dca-card-symbol,
.dca-tour-demo-host .dca-step-pill { pointer-events: none; }
/* Antes forzaba visible + verde (var(--good)), un estado que no existe en la tarjeta real:
   este punto nunca es verde -- solo aparece en rojo (var(--critical)) cuando la última
   compra automática falló por falta de saldo, y está oculto el resto del tiempo (ver
   dca-paused-dot en app.js). La demo ahora usa auto_buy_skipped: true así el punto se ve
   con su color y visibilidad reales, sin necesitar overrides -- pedido explícito 2026-09-11,
   "el punto verde nunca aparecería". */
.dca-tour-demo-host .dca-paused-dot.dca-tour-status-dot { box-shadow: 0 0 0 3px color-mix(in srgb, var(--critical) 18%, transparent); }
.dca-card-product-tour { z-index: 1100; }
.dca-card-product-tour .tour-card {
  z-index: 1102; width: min(410px, calc(100vw - 28px)); max-height: none; overflow: visible; padding: 16px;
}
.dca-card-product-tour .tour-progress { margin: 10px 0 8px; }
.dca-card-product-tour .tour-pipeline { margin-bottom: 7px; padding-bottom: 4px; }
.dca-card-product-tour .tour-icon { width: 30px; height: 30px; margin-top: 8px; border-radius: 8px; font-size: 14px; }
.dca-card-product-tour .tour-card h2 { margin: 8px 0 5px; font-size: 17px; }
.dca-card-product-tour .tour-card p { font-size: 11px; line-height: 1.45; }
.dca-card-product-tour .tour-note { margin-top: 8px; padding: 7px 9px; font-size: 9.5px; line-height: 1.4; }
.dca-card-product-tour .tour-actions { margin-top: 12px; }
.dca-card-product-tour .tour-actions button { min-width: 82px; padding: 7px 10px; }
.dca-card-product-tour .tour-highlight { z-index: 1101; }
@media (max-width: 720px) {
  .dca-tour-demo-host { padding-top: 12px; }
  .dca-tour-demo-host.is-tour-active { padding-bottom: 370px; }
  .dca-card-product-tour .tour-card { width: min(390px, calc(100vw - 20px)); padding: 13px; }
}
@media (max-height: 560px) {
  .dca-card-product-tour .tour-card { padding: 11px 14px; }
  .dca-card-product-tour .tour-icon { display: none; }
  .dca-card-product-tour .tour-pipeline { margin-bottom: 4px; }
  .dca-card-product-tour .tour-card h2 { margin-top: 5px; font-size: 15px; }
  .dca-card-product-tour .tour-card p { font-size: 10px; line-height: 1.35; }
  .dca-card-product-tour .tour-note { margin-top: 5px; padding-block: 5px; }
  .dca-card-product-tour .tour-actions { margin-top: 7px; }
}

.search-row input[type="text"] {
  width: 100%;
  max-width: 320px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-primary);
  padding: 8px 10px;
  font-size: 13px;
}

.search-results {
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 4px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  max-width: 320px;
  max-height: 220px;
  overflow-y: auto;
  z-index: 20;
  display: none;
}
.search-results.open { display: block; }

.search-results .item {
  padding: 8px 12px;
  font-size: 13px;
  cursor: pointer;
}
.search-results .item:hover { background: var(--surface-1); }

table.pairs {
  width: 100%;
  border-collapse: collapse;
}

table.pairs th {
  text-align: left;
  color: var(--muted);
  font-size: 11px;
  letter-spacing: 0.03em;
  font-weight: 500;
  padding: 8px 10px;
  border-bottom: 1px solid var(--gridline);
}

table.pairs td {
  padding: 10px;
  border-bottom: 1px solid var(--gridline);
  font-variant-numeric: tabular-nums;
  vertical-align: middle;
}

table.pairs tr:last-child td { border-bottom: none; }

table.pairs .symbol-cell {
  font-weight: 600;
  cursor: pointer;
}
table.pairs .symbol-cell:hover { color: var(--series-1); }

/* Tabla compacta: letra más chica y filas más bajas para que entren muchas transacciones */
table.pairs.table-compact th {
  font-size: 10px;
  padding: 6px 8px;
}

#admin-users-table thead th[colspan] {
  text-align: center;
}
#admin-users-table thead tr:nth-child(2) th:first-child {
  text-align: left;
}
#admin-users-table thead th[rowspan] {
  vertical-align: bottom;
}
/* Ver comentario en index.html junto a "Acciones" -- ocupa el alto de una 2da línea pero
   sin mostrar nada, solo para que el bottom-align natural deje "Acciones" a la altura de
   "PNL Realizado" (la 1ra línea del vecino) en vez de "+ Stake" (la 2da). */
.admin-actions-header-spacer { visibility: hidden; }
#admin-users-table thead th[data-sort="pnl_realizado"] {
  text-align: center;
  vertical-align: middle;
}
#admin-users-table thead th[data-sort="email"] {
  text-align: center;
  vertical-align: middle;
}
#admin-users-table thead th:first-child {
  text-align: center;
  vertical-align: middle;
}
#admin-users-table .group-header-row th {
  background: var(--surface-2);
  color: var(--text-primary);
  font-weight: 600;
  border-bottom: 1px solid var(--border);
}
#admin-users-table thead .group-end,
#admin-users-table tbody .group-end {
  border-right: 1px solid var(--border);
}
#admin-users-table {
  border: 1px solid var(--border);
}
#admin-users-table tbody td {
  border-bottom: 1px solid var(--border);
}
#admin-users-table tbody td:nth-child(8) {
  text-align: center;
}
table.pairs.table-compact td {
  font-size: 12.5px;
  padding: 6px 8px;
}

table.pairs input[type="number"] {
  width: 90px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-primary);
  padding: 5px 7px;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

.switch {
  position: relative;
  display: inline-block;
  width: 36px;
  height: 20px;
}
.switch input { opacity: 0; width: 0; height: 0; }
.switch .slider {
  position: absolute;
  cursor: pointer;
  inset: 0;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 20px;
  transition: 0.15s;
}
.switch .slider::before {
  content: "";
  position: absolute;
  width: 14px;
  height: 14px;
  left: 2px;
  top: 2px;
  background: var(--muted);
  border-radius: 50%;
  transition: 0.15s;
}
.switch input:checked + .slider { background: rgba(12, 163, 12, 0.25); border-color: var(--good); }
.switch input:checked + .slider::before { transform: translateX(16px); background: var(--good); }

.pill {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 20px;
  font-size: 11px;
  font-weight: 600;
}
.pill.open { background: rgba(12, 163, 12, 0.18); color: var(--good); }
.pill.none { background: rgba(137, 135, 129, 0.15); color: var(--muted); }

.badge-good { color: var(--good); }
.badge-critical { color: var(--critical); }

/* Señales AltFins — 2 vistas alternativas (Tarjetas / Tabla), elegidas por el usuario con
   .altfins-view-toggle y recordadas en localStorage (ver setAltfinsView en app.js). Antes
   había una sola tabla densa con "Strong Up (8/10)" en 3 columnas de texto en inglés —
   pedido explícito de que sea más sobria y fácil de interpretar para alguien nuevo. */
.altfins-name { color: var(--muted); font-size: 11px; margin-left: 4px; }
.altfins-updated { color: var(--muted); font-size: 12px; }

.altfins-toolbar { justify-content: space-between; align-items: center; }
.altfins-view-toggle { display: flex; gap: 4px; background: var(--surface-2); border: 1px solid var(--border); border-radius: 8px; padding: 3px; }
.altfins-view-btn {
  background: transparent;
  border: 1px solid transparent;
  color: var(--text-primary);
  padding: 5px 12px;
  font-size: 11.5px;
  font-weight: 600;
  border-radius: 6px;
}
.altfins-view-btn:hover { filter: none; color: var(--text-primary); }
.altfins-view-btn.active { background: var(--surface-1); color: var(--text-primary); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); }

/* Flecha de tendencia -- misma pieza reutilizada en las 2 vistas (tarjetas y tabla) y en
   la referencia de colores. Pastilla circular chica con fondo teñido (mismo lenguaje que
   el resto de la app -- insignias de Tramo Tarifario, chips de referidos, etc.) en vez de
   un carácter de flecha suelto, para que se vea más sobria. "Fuerte" (doble flecha) va con
   el fondo/color más saturado; la versión normal, más suave -- mismo criterio que ya usaban
   .trend-strong-up (más opaco) vs .trend-up (más suave) antes de este rediseño, para no
   perder la distinción entre las 5 categorías reales de altFINS. */
.altfins-arrow {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 21px;
  height: 21px;
  border-radius: 50%;
  font-size: 11px;
  font-weight: 800;
  line-height: 1;
}
.altfins-arrow.up-strong { background: rgba(12, 163, 12, 0.20); color: var(--good); }
.altfins-arrow.up { background: rgba(12, 163, 12, 0.10); color: color-mix(in srgb, var(--good) 65%, var(--muted)); }
.altfins-arrow.down-strong { background: rgba(208, 59, 59, 0.20); color: var(--critical); }
.altfins-arrow.down { background: rgba(208, 59, 59, 0.10); color: color-mix(in srgb, var(--critical) 65%, var(--muted)); }
.altfins-arrow.flat { background: rgba(201, 133, 0, 0.14); color: var(--warning); }

.altfins-legend { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 10px; padding: 0 2px; font-size: 11px; color: var(--muted); }
.altfins-legend-item { display: flex; align-items: center; gap: 5px; }
/* "Tendencia" centrado sobre las 3 sub-columnas (Corto/Mediano/Largo), y esas 3 en una
   grilla de 3 columnas iguales -- .altfins-arrows del cuerpo usa la MISMA grilla, así cada
   flecha cae exactamente debajo de su palabra (pedido explícito). */
/* table.pairs th (no solo .altfins-th-trend) a propósito -- ese selector suma el elemento
   "th" a la especificidad y le ganaba a una clase sola sin importar el orden en el archivo
   (mismo motivo que el bug ya encontrado con .admin-rate-input.rate-changed y
   .altfins-cards[hidden]), así que "Tendencia" seguía a la izquierda pese al text-align acá. */
table.pairs th.altfins-th-trend { text-align: center; }
.altfins-th-cols {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px;
  margin-top: 3px; font-weight: 400; text-transform: none; font-size: 9px; color: var(--muted);
}

/* ---- Vista Tarjetas ---- */
/* [hidden] explícito -- "display: grid" de la regla de abajo tiene la MISMA especificidad
   que el "display: none" que el navegador le da a [hidden], y como el CSS del sitio carga
   después que el del navegador, "grid" ganaba y la vista quedaba visible igual (bug real,
   confirmado con getComputedStyle: mostraba las 2 vistas superpuestas en vez de una sola). */
.altfins-cards[hidden] { display: none; }
/* minmax más ancho (230px -> 270px) para que entren ~4 columnas en vez de 5 en el ancho
   típico del panel, más gap más grande (10px -> 18px) para que se respire entre tarjetas
   tanto horizontal como verticalmente (pedido explícito). */
.altfins-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); gap: 18px; }
.altfins-card { background: var(--surface-2); border: 1px solid var(--border); border-radius: 10px; padding: 12px 13px; }
.altfins-card-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 8px; }
.altfins-card-id { display: flex; align-items: center; gap: 8px; min-width: 0; }
.altfins-card-dot {
  width: 28px; height: 28px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  background: color-mix(in srgb, var(--series-1) 16%, var(--surface-1));
  color: var(--series-1);
  font-size: 8.5px;
  font-weight: 800;
}
.altfins-card-id-text { min-width: 0; display: flex; flex-direction: column; }
.altfins-card-name { font-size: 12.5px; font-weight: 700; color: var(--text-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.altfins-card-rank { font-size: 9.5px; color: var(--muted); }
.altfins-card-price { text-align: right; flex-shrink: 0; }
.altfins-card-price strong { display: block; font-size: 12.5px; font-variant-numeric: tabular-nums; color: var(--text-primary); }
.altfins-card-price span { font-size: 10.5px; font-variant-numeric: tabular-nums; }
.altfins-card-trends { display: flex; gap: 6px; margin-top: 10px; }
.altfins-trend-chip { flex: 1; min-width: 0; text-align: center; padding: 6px 4px; border-radius: 7px; background: var(--surface-1); }
.altfins-trend-chip-label { display: block; font-size: 8.5px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.03em; margin-bottom: 2px; }
.altfins-trend-chip-value { font-size: 10.5px; font-weight: 700; white-space: nowrap; }
.altfins-trend-chip-value.up-strong { color: var(--good); }
.altfins-trend-chip-value.up { color: color-mix(in srgb, var(--good) 65%, var(--muted)); }
.altfins-trend-chip-value.down-strong { color: var(--critical); }
.altfins-trend-chip-value.down { color: color-mix(in srgb, var(--critical) 65%, var(--muted)); }
.altfins-trend-chip-value.flat { color: var(--warning); }
.altfins-trend-chip-value.stable { color: var(--muted); font-weight: 600; }
/* Centrada horizontalmente, al menos a la mitad del ancho de la tarjeta (pedido explícito)
   -- min-width en vez de width fijo + white-space:nowrap para que "Tendencia Positiva
   Fuerte"/"Tendencia Negativa Fuerte" (los textos más largos, ahora que se distingue
   fuerte de normal) nunca corten a 2 líneas, creciendo por encima del 50% si hace falta. */
.altfins-overall-pill {
  display: flex; align-items: center; justify-content: center;
  width: fit-content; min-width: 50%; max-width: 100%;
  margin: 9px auto 0; padding: 3px 10px; border-radius: 999px;
  font-size: 10px; font-weight: 700; white-space: nowrap; text-align: center;
}
.altfins-overall-pill.good { background: rgba(12, 163, 12, 0.15); color: var(--good); }
.altfins-overall-pill.critical { background: rgba(208, 59, 59, 0.15); color: var(--critical); }
.altfins-overall-pill.flat { background: rgba(201, 133, 0, 0.15); color: var(--warning); }
/* Stablecoins: gris a propósito, ni rojo ni amarillo ni verde -- no tiene sentido calificar
   "tendencia" en algo que por diseño busca valer siempre $1 (pedido explícito). */
.altfins-overall-pill.stable { background: color-mix(in srgb, var(--muted) 15%, transparent); color: var(--muted); }

/* ---- Vista Tabla ---- */
.altfins-arrows { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; justify-items: center; }
.altfins-stable-cell { text-align: center; color: var(--text-primary); font-size: 10.5px; font-weight: 600; }

/* ---- Opinión IA (pedido explícito 2026-09-07) -- complementa la Valoración Técnica de
   altFINS con qué opina una IA del proyecto/moneda. Un solo botón por moneda, tanto en la
   vista Tarjetas como en la Tabla, que abre el mismo modal. ---- */
.altfins-card-bottom { display: flex; flex-direction: column; gap: 8px; margin-top: 2px; }
.ai-opinion-btn {
  display: flex; align-items: center; justify-content: center; gap: 5px;
  width: 100%; padding: 6px 8px; border-radius: 8px;
  border: 1px solid color-mix(in srgb, var(--series-7) 45%, var(--border));
  background: color-mix(in srgb, var(--series-7) 10%, transparent);
  color: color-mix(in srgb, var(--series-7) 80%, var(--text-primary));
  font-size: 10.5px; font-weight: 700;
  transition: background .15s ease, border-color .15s ease;
}
.ai-opinion-btn:hover { background: color-mix(in srgb, var(--series-7) 20%, transparent); border-color: var(--series-7); }
.ai-opinion-btn span { font-size: 11px; }
/* Versión ícono-solo de la tabla -- misma identidad visual (borde+fondo violeta), tamaño de
   celda en vez de ancho completo. */
.ai-opinion-btn-icon { width: 26px; height: 26px; padding: 0; border-radius: 50%; margin: 0 auto; }

.ai-opinion-box { width: min(560px, 94vw); }
.ai-opinion-title-row { display: flex; align-items: center; gap: 10px; }
.ai-opinion-badge {
  flex: none; width: 34px; height: 34px; display: grid; place-items: center;
  border-radius: 10px; font-size: 16px;
  background: color-mix(in srgb, var(--series-7) 18%, transparent); color: var(--series-7);
}
.ai-opinion-body { margin-top: 4px; min-height: 120px; }
/* [hidden] explícito -- mismo bug de especificidad que .altfins-cards[hidden] (ver esa nota
   más arriba): display:flex de la clase empata en especificidad con el display:none que el
   navegador le da a [hidden], y como el CSS del sitio carga después, sin esto el loading
   quedaba visible aunque estuviera hidden. */
.ai-opinion-loading[hidden] { display: none; }
.ai-opinion-loading {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  padding: 34px 0; color: var(--muted); font-size: 12px;
}
.ai-opinion-spinner {
  width: 26px; height: 26px; border-radius: 50%;
  border: 3px solid color-mix(in srgb, var(--series-7) 25%, transparent);
  border-top-color: var(--series-7);
  animation: ai-opinion-spin .8s linear infinite;
}
@keyframes ai-opinion-spin { to { transform: rotate(360deg); } }
.ai-opinion-error {
  padding: 14px 16px; border-radius: 8px; margin: 6px 0;
  background: color-mix(in srgb, var(--critical) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--critical) 35%, var(--border));
  color: var(--critical); font-size: 12.5px; line-height: 1.5;
}
.ai-opinion-verdict {
  display: inline-block; padding: 4px 12px; border-radius: 999px;
  font-size: 11px; font-weight: 800; letter-spacing: .02em;
}
.ai-opinion-verdict-good { background: rgba(12, 163, 12, 0.15); color: var(--good); }
.ai-opinion-verdict-promising { background: color-mix(in srgb, var(--series-1) 18%, transparent); color: var(--series-1); }
.ai-opinion-verdict-speculative { background: rgba(201, 133, 0, 0.15); color: var(--warning); }
.ai-opinion-verdict-critical { background: rgba(208, 59, 59, 0.15); color: var(--critical); }
.ai-opinion-resumen { margin: 12px 0 0; color: var(--text-secondary); font-size: 13px; line-height: 1.6; }
.ai-opinion-columns { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; margin-top: 16px; }
.ai-opinion-col-title { font-size: 10px; font-weight: 750; text-transform: uppercase; letter-spacing: .05em; margin-bottom: 8px; }
.ai-opinion-col-good .ai-opinion-col-title { color: var(--good); }
.ai-opinion-col-risk .ai-opinion-col-title { color: var(--critical); }
.ai-opinion-col ul { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 6px; }
.ai-opinion-col li { font-size: 12px; line-height: 1.45; color: var(--text-secondary); }
.ai-opinion-col-good li::marker { color: var(--good); }
.ai-opinion-col-risk li::marker { color: var(--critical); }
.ai-opinion-meta { margin-top: 16px; color: var(--muted); font-size: 10.5px; text-align: right; }
.ai-opinion-disclaimer {
  margin: 16px 0 0; padding-top: 12px; border-top: 1px solid var(--border);
  color: var(--muted); font-size: 10.5px; line-height: 1.5;
}
@media (max-width: 560px) {
  .ai-opinion-columns { grid-template-columns: 1fr; }
}

.empty-row td {
  color: var(--muted);
  text-align: center;
  padding: 24px 0;
}

/* Modal */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.6);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 100;
}
.modal-overlay.open { display: flex; }

.modal {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  width: min(880px, 92vw);
  max-height: 88vh;
  overflow-y: auto;
  padding: 20px 22px;
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}
.modal-header h3 { margin: 0; font-size: 16px; }

.dca-modal-exit-summary {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 10px 14px;
  margin-bottom: 14px;
}
.dca-modal-exit-summary .item {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.dca-modal-exit-summary .item .label {
  color: var(--muted);
  font-size: 10.5px;
}
.dca-modal-exit-summary .item .value {
  font-weight: 600;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

.legend {
  display: flex;
  gap: 16px;
  font-size: 12px;
  color: var(--text-secondary);
  margin-bottom: 10px;
}
.legend .swatch {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 2px;
  margin-right: 5px;
}

#chart-container {
  width: 100%;
  height: 420px;
}

.toast-stack {
  position: fixed;
  bottom: 20px;
  right: 20px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  z-index: 200;
}
.toast {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-left: 3px solid var(--series-1);
  border-radius: 8px;
  padding: 10px 14px;
  font-size: 13px;
  min-width: 220px;
  box-shadow: 0 6px 18px rgba(0,0,0,0.4);
}
.toast.good { border-left-color: var(--good); }
.toast.critical { border-left-color: var(--critical); }

/* Barra de progreso: entrada (una sola barra) o SL/TP-DCA (dos lados) */
.progress-bar {
  position: relative;
  width: 90px;
  height: 8px;
  border-radius: 4px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  overflow: hidden;
}
.progress-bar .fill-single {
  position: absolute;
  inset: 0;
  width: 0%;
  background: var(--series-1);
  border-radius: 4px;
}
.progress-bar .fill-left {
  position: absolute;
  top: 0;
  bottom: 0;
  right: 66.6667%;
  width: 0%;
  background: var(--critical);
}
.progress-bar .fill-yellow {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 33.3333%;
  width: 0%;
  background: var(--warning);
}
.progress-bar .fill-right {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 66.6667%;
  width: 0%;
  background: var(--good);
}
.progress-bar .midline {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--border);
}
.progress-bar .midline-1 { left: 33.3333%; }
.progress-bar .midline-2 { left: 66.6667%; }
.progress-cell {
  display: flex;
  flex-direction: column;
  gap: 3px;
  align-items: flex-start;
}
.progress-label {
  font-size: 10px;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
/* "Colchón" (Stop Dinámico ya activado, ver progressLabelHtml en app.js) -- subrayado
   punteado + cursor de ayuda para dar a entender que tiene un tooltip propio (CUSHION_TOOLTIP)
   antes de pasar el mouse, sin agregar texto fijo a la línea (pedido explícito). */
.cushion-label {
  cursor: help;
  text-decoration: underline dotted;
  text-underline-offset: 2px;
}
.progress-cell.compact .progress-bar {
  width: 56px;
  height: 6px;
}

/* DCA — formulario de alta */
.dca-form {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 18px 20px;
  margin-bottom: 20px;
  /* Angosta (ancho justo del contenido, ver .dca-form-grid) pero centrada respecto de la
     tarjeta que engloba las posiciones abiertas (pedido explícito) -- ese contenedor
     (.dca-cards / cada .dca-card) ocupa el 100% del panel, así que sin esto la tarjeta de
     alta quedaba pegada a la izquierda en vez de centrada. */
  width: fit-content;
  margin-left: auto;
  margin-right: auto;
}
.dca-form-header {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 16px;
  padding-bottom: 14px;
  border-bottom: 1px solid var(--gridline);
}
.dca-form-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--text-primary);
}
.dca-form-price {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.dca-form-price-label {
  font-size: 11px;
  color: var(--muted);
  letter-spacing: 0.04em;
}
.dca-form-price-value {
  font-size: 18px;
  font-weight: 700;
  color: var(--series-1);
  font-variant-numeric: tabular-nums;
}
/* Capital Máximo: mismo estilo que Precio Actual (pedido explícito, "en línea... que sale
   en azul") -- un poco de separación extra (margin-left) para que se lea como un segundo
   par etiqueta/valor y no un texto corrido con el precio. */
.dca-form-max-capital-label { margin-left: 10px; }
.dca-form-available-label { margin-left: 10px; }
.dca-form-price-value.dca-form-available-value { color: var(--good); }
/* Antes repeat(4, 1fr) -- estiraba las columnas a lo ancho de toda la tarjeta, mucho más de
   lo que necesita cualquier campo (pedido explícito, "desproporcionadamente grandes"). 160px
   es el ancho medido del título más largo ("Monto Próxima Compra (USD)", 156px) más un
   margen chico -- todas las columnas miden lo mismo. 5 columnas (no 4): Comprar Ahora y
   Cancelar necesitaban 2 columnas propias en la fila 2, a la derecha de Modo De Salida, sin
   agregar una 3ra fila (pedido explícito). */
.dca-form-grid {
  display: grid;
  grid-template-columns: repeat(5, 160px);
  /* Comprar Ahora/Cancelar (27px, sin título arriba) quedaban pegados arriba de su celda --
     por default (align-items normal/stretch) un item con alto fijo no se estira, y se alinea
     al INICIO de la fila en vez de abajo, donde caen los recuadros de los demás campos (cuyo
     input siempre es lo último dentro de su <label> en columna). align-items: end los baja
     a la misma línea de base que esos recuadros. */
  align-items: end;
  gap: 12px;
  margin-bottom: 18px;
}
.dca-form-grid label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 11px;
  color: var(--muted);
  letter-spacing: 0.03em;
}
/* Recuadros más sobrios (pedido explícito, "desproporcionadamente grandes") -- mismo
   --dca-field-height/font-size que ya usan los campos de configuración de cada tarjeta de
   posición abierta (ver .dca-config-inline en esta misma hoja), en vez del padding/font-size
   más grandes que tenía este form de alta. */
.dca-form-grid input[type="number"] {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-primary);
  padding: 0 8px;
  height: var(--dca-field-height);
  font-size: 12px;
  width: 100%;
  font-variant-numeric: tabular-nums;
}
.dca-form-grid select {
  box-sizing: border-box;
  margin: 0;
  background-color: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-primary);
  padding: 0 20px 0 8px;
  height: var(--dca-field-height);
  line-height: calc(var(--dca-field-height) - 2px);
  font-size: 12px;
  font-family: inherit;
  width: 100%;
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%237c8598' stroke-width='1.5' fill='none' fill-rule='evenodd'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 8px center;
}
.dca-form-grid select:focus {
  outline: none;
  border-color: var(--accent, var(--good));
}
/* Comprar Ahora / Cancelar ahora viven adentro del grid, cada uno en su propia celda:
   Comprar Ahora alineado debajo de Modo De Salida, Cancelar a su derecha (pedido explícito)
   -- mismo alto que los recuadros de al lado para que la fila quede pareja. */
.dca-form-action-btn {
  height: var(--dca-field-height);
  line-height: calc(var(--dca-field-height) - 2px);
  padding: 0 10px;
  font-size: 12px;
  width: 100%;
}

/* DCA — tarjetas de posiciones abiertas */
.dca-cards {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-bottom: 8px;
}

.dca-card {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 18px;
}
.dca-card.paused { border-color: rgba(208, 59, 59, 0.4); }

/* Fila 1 y fila 2 comparten el mismo grid de columnas (símbolo, escalón, decimales, punto de
   pausa, 7 columnas de estadística/configuración, columna final flexible) para que ambas
   filas queden alineadas verticalmente, no solo entre tarjetas distintas sino entre sí.
   Las 7 columnas de estadística (Precio Actual .. Valor Actual) miden todas lo mismo
   (pedido explícito, "misma separación" entre todas) -- "Precio Últ. Compra", la etiqueta
   más larga, se sale del recuadro angosto en una sola línea (white-space: nowrap en
   .dca-quickstat .label) en vez de ensanchar su columna. */
.dca-row-top,
.dca-row-bottom {
  display: grid;
  grid-template-columns: 90px 56px 96px 14px repeat(7, 90px) 1fr;
  gap: 10px;
}
.dca-row-top {
  align-items: center;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--gridline);
}
.dca-row-bottom {
  align-items: end;
  padding-top: 12px;
}

/* Los wrappers no generan su propia grilla: sus hijos pasan a ser celdas directas del
   grid de la fila (símbolo, escalón, decimales y punto de pausa quedan en las columnas 1-4;
   cada estadística/config recibe su columna vía JS con style.gridColumn). */
.dca-identity {
  display: contents;
}
.dca-closed-symbol {
  cursor: pointer;
  font-weight: 700;
  text-decoration: underline dotted;
}

.dca-card-symbol {
  grid-column: 1;
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dca-card-symbol:hover { color: var(--series-1); }

.dca-decimals-select {
  grid-column: 3;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-secondary);
  padding: 4px 6px;
  font-size: 11px;
  /* "Sin Decimales" no entraba entero (pedido explícito) -- crece hacia la izquierda
     (margin-left negativo, invade el espacio libre a la derecha del step-pill). El borde
     derecho queda 15px más adentro que la celda original, a propósito, para alinearlo con
     la barra de progreso ya achicada (ver .dca-progress-inline .progress-bar). 104px es el
     ancho final pedido. */
  margin-left: -23px;
  width: 104px;
}

.dca-step-pill {
  grid-column: 2;
  display: inline-block;
  /* Ancho fijo (pedido explícito) -- antes el pill medía lo justo para su texto ("3/8" vs
     "10/10" vs "15 (Manual)" varían bastante de ancho) y como el recuadro de decimales
     empieza en un punto fijo de la columna siguiente, el espacio entre los dos cambiaba de
     tarjeta en tarjeta. Padding angosto (3px 6px, antes 3px 10px) + 38px de ancho: mismo
     espacio hasta el recuadro de decimales que tenía "3/8" (la referencia pedida, ARBUSDT)
     con cualquier texto de "0/10" a "10/10" (medido, todos entran sin recortarse). El caso
     raro "N (Manual)" se sale del recuadro en vez de recortarse -- no vale la pena agrandar
     el fijo para un caso que casi no se da. */
  width: 38px;
  text-align: center;
  padding: 3px 6px;
  border-radius: 20px;
  font-size: 11px;
  font-weight: 600;
  background: rgba(57, 135, 229, 0.15);
  color: var(--series-1);
  white-space: nowrap;
  justify-self: start;
  box-sizing: border-box;
}
.dca-step-pill.maxed {
  background: rgba(200, 133, 0, 0.15);
  color: var(--series-3);
}
/* Clic para cambiar el tope de escalones automáticos de una posición ya abierta (pedido
   explícito 2026-09-07) -- ver startEditDcaMaxSteps en app.js. */
.dca-step-pill-editable { cursor: pointer; }
.dca-step-pill-editable:hover { filter: brightness(1.25); }
.dca-step-pill-input {
  width: 100%;
  background: var(--surface-1);
  border: 1px solid var(--series-1);
  border-radius: 10px;
  color: var(--text-primary);
  font-size: 11px;
  font-weight: 600;
  text-align: center;
  padding: 0 2px;
  box-sizing: border-box;
}
.dca-step-pill.is-editing {
  position: relative;
  z-index: 20;
  width: 112px;
  min-height: 36px;
  padding: 4px;
  border: 1px solid color-mix(in srgb, var(--series-1) 72%, var(--border));
  border-radius: 10px;
  background: var(--surface-1);
  box-shadow: 0 10px 28px rgba(0, 0, 0, .34), 0 0 0 3px color-mix(in srgb, var(--series-1) 14%, transparent);
}
.dca-step-pill.is-editing .dca-step-pill-input {
  width: 100%;
  height: 28px;
  padding: 2px 8px;
  border: 0;
  outline: 0;
  background: transparent;
  font-size: 16px;
  font-variant-numeric: tabular-nums;
}
.dca-step-edit-hint,
.dca-step-save-reminder {
  position: absolute;
  left: 0;
  top: calc(100% + 8px);
  z-index: 30;
  width: max-content;
  max-width: 190px;
  padding: 7px 9px;
  border: 1px solid color-mix(in srgb, var(--series-1) 55%, var(--border));
  border-radius: 8px;
  background: color-mix(in srgb, var(--surface-1) 96%, var(--series-1));
  color: var(--text-primary);
  box-shadow: 0 8px 24px rgba(0, 0, 0, .32);
  font-size: 10px;
  font-weight: 650;
  line-height: 1.25;
  white-space: normal;
  pointer-events: none;
}
.dca-step-edit-hint::before,
.dca-step-save-reminder::before {
  content: "";
  position: absolute;
  left: 14px;
  bottom: 100%;
  border: 5px solid transparent;
  border-bottom-color: color-mix(in srgb, var(--series-1) 55%, var(--border));
}
.dca-step-edit-hint { opacity: 0; transform: translateY(-3px); transition: opacity .16s ease, transform .16s ease; }
.dca-step-pill.has-pending-change .dca-step-edit-hint { opacity: 1; transform: translateY(0); }
.dca-step-save-reminder {
  left: -2px;
  color: var(--series-3);
  border-color: color-mix(in srgb, var(--series-3) 58%, var(--border));
  animation: dca-step-reminder-in .18s ease-out;
}
@keyframes dca-step-reminder-in {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}
.dca-paused-dot {
  grid-column: 4;
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--critical);
  cursor: help;
  justify-self: start;
}

/* Pass-through: cada estadística recibe su columna (5-10) vía JS (style.gridColumn) para
   que Precio Actual/Precio Promedio/Unidades queden exactamente arriba de Próx. Compra/
   Caída %/Take Profit % de la fila 2. */
.dca-quickstats {
  display: contents;
}
.dca-quickstat {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  text-align: left;
  gap: 2px;
}
/* Sin overflow:hidden acá (a diferencia de .value, que sí lo necesita para el elipsis
   numérico): con las 7 columnas ahora del mismo ancho (pedido explícito), "Precio Últ.
   Compra" -- la etiqueta más larga -- se sale del recuadro angosto en una sola línea en
   vez de cortarse a la mitad. */
.dca-quickstat .label {
  font-size: 9px;
  color: var(--muted);
  letter-spacing: 0.04em;
  white-space: nowrap;
}
.dca-quickstat .value {
  font-size: 12.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.dca-pnl-block {
  grid-column: 12;
  text-align: right;
}
.dca-pnl-block .pnl-value {
  font-size: 16px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
.dca-pnl-block .pnl-roi {
  font-size: 11px;
  font-variant-numeric: tabular-nums;
}

/* Fila 2: la barra de progreso ocupa el mismo ancho que la identidad (columnas 1-4);
   cada input de configuración recibe su columna (5-7) vía JS para alinear con la
   estadística de arriba, y Guardar cae en la columna 8. */
.dca-progress-inline {
  grid-column: 1 / 4;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
/* Antes 100% -- la barra terminaba más a la derecha que el texto "Próxima Compra X% ·
   Recuperación Y% · Take Profit Z%" que cae inmediatamente abajo (.progress-label), sobre
   todo con porcentajes cortos (pedido explícito, ~4mm/15px de diferencia medida). El
   recuadro de decimales (.dca-decimals-select) se corrió el mismo -15px en su borde derecho
   para quedar alineado con este nuevo borde de la barra. */
.dca-progress-inline .progress-bar { width: calc(100% - 15px); }
.dca-progress-labels-inline {
  display: flex;
  gap: 10px;
  font-size: 10px;
  white-space: nowrap;
}
.dca-progress-labels-inline .left { color: var(--critical); }
.dca-progress-labels-inline .right { color: var(--good); }
.dca-progress-labels-inline .target { color: var(--muted); font-variant-numeric: tabular-nums; }

/* Pass-through de grid (igual que .dca-quickstats): cada campo recibe su columna vía JS
   (style.gridColumn) para quedar alineado exactamente debajo de la estadística
   correspondiente de la fila de arriba (pedido explícito) -- Próx. Compra bajo Precio
   Actual, Caída % bajo Precio Promedio, Take Profit %/% Utilidad Activación bajo Precio
   Últ. Compra, % Caída Desde Máximo bajo Unidades. Take Profit % y % Utilidad Activación
   comparten columna porque nunca están visibles los dos a la vez según el Modo De Salida. */
.dca-config-inline {
  display: contents;
}
/* .dca-mode-col comparte esta base aunque ya no vive dentro de .dca-config-inline (se movió
   a su propia celda del grid, columna 10, bajo "Abierta" -- pedido explícito).
   white-space: nowrap para que el título no se parta en 2 líneas aunque sea largo (pedido
   explícito) -- se permite que se salga del recuadro angosto en vez de cortarse. */
.dca-config-inline label,
.dca-mode-col {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 9px;
  color: var(--muted);
  letter-spacing: 0.03em;
  width: 100%;
  white-space: nowrap;
}

/* Ganancia Sobre Promedio + P. Máx., una al lado de la otra (pedido explícito). */
.dca-trailing-line {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 10px;
  font-size: 10px;
  font-weight: 600;
}
.dca-trailing-gain .target { color: var(--muted); font-variant-numeric: tabular-nums; }
/* P. Máx.: label en --good (mismo verde que "Stop" del lado derecho de la barra, con el
   que se corresponde 1 a 1 -- Stop = P. Máx. × (1 − trailing_stop_pct)); el precio en sí
   queda en .target (color neutro), igual que cualquier otro precio de la tarjeta. */
.dca-trailing-max { color: var(--good); }
.dca-trailing-max .target { color: var(--muted); font-variant-numeric: tabular-nums; }
/* Alto único para Take Profit %, el <select> de Modo De Salida, y los 3 botones (Guardar,
   Comprar Ahora, Cerrar Posición) -- pedido explícito de que midan EXACTAMENTE lo mismo.
   Padding solo no alcanzaba: cada tipo de elemento (input/select/button) tiene su propio
   line-height nativo por default, así que con el mismo padding+font-size terminaban con
   alturas distintas igual. Acá se fija el alto en píxeles + line-height explícito (mismo
   truco clásico de centrado vertical de una sola línea) para que los 3 midan lo mismo pase
   lo que pase con las diferencias nativas de cada elemento. */
:root {
  --dca-field-height: 27px;
}
.dca-config-inline input[type="number"] {
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-primary);
  padding: 0 8px;
  height: var(--dca-field-height);
  font-size: 12px;
  width: 100%;
  font-variant-numeric: tabular-nums;
}

.dca-config-inline select,
.dca-mode-col select {
  box-sizing: border-box;
  margin: 0;
  background-color: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-primary);
  /* Padding angosto (antes 8px/20px) -- a 90px de ancho de recuadro, "Trailing Stop"
     (66px de texto) no entraba con el padding anterior (dejaba solo 62px libres). Con
     6px/16px quedan 68px libres, entra completo. */
  padding: 0 16px 0 6px;
  height: var(--dca-field-height);
  line-height: calc(var(--dca-field-height) - 2px);
  font-size: 12px;
  font-family: inherit;
  width: 100%;
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' stroke='%237c8598' stroke-width='1.5' fill='none' fill-rule='evenodd'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 5px center;
}
/* Tinte tenue según el modo (pedido explícito) -- color_mix mezcla un % del acento sobre el
   fondo/borde normal, así se adapta solo a tema claro/oscuro sin duplicar valores. Mismos
   colores que ya usa el resto de la app para cada mecanismo (--good para Take Profit,
   --series-3 para Trailing Stop, ver .closest-execute-type.trailing). */
.dca-mode-col select.mode-take-profit {
  /* Antes 14%/45% -- pedido explícito de un poco más claro. */
  background-color: color-mix(in srgb, var(--good) 20%, var(--surface-1));
  border-color: color-mix(in srgb, var(--good) 55%, var(--border));
}
.dca-mode-col select.mode-trailing-stop {
  /* Antes 14%/45% de --series-3 solo -- pedido explícito de un poco más claro, y un poco
     más anaranjado (--series-3 tira a café/oliva mezclado con el fondo oscuro). Se le suma
     un toque de naranja puro (#ff8c00) encima del tinte de --series-3, sin sacarle el color
     ya usado en el resto de la app para "Trailing" -- solo lo corre un poco hacia naranja. */
  background-color: color-mix(in srgb, #ff8c00 5%, color-mix(in srgb, var(--series-3) 20%, var(--surface-1)));
  border-color: color-mix(in srgb, #ff8c00 12%, color-mix(in srgb, var(--series-3) 55%, var(--border)));
}
.dca-config-inline select:focus,
.dca-mode-col select:focus {
  outline: none;
  /* Antes verde (var(--good)) -- pedido explícito de que el resalte al abrir el desplegable
     use el mismo color que ya tiene el borde de Guardar (.ghost), no un verde de acento.
     Si el resultado convence, el mismo criterio se extiende a todos los recuadros editables
     (ver .dca-config-inline input[type="number"]:focus más abajo). */
  border-color: var(--border);
}

/* Modo De Salida sale del flex de configuración y pasa a ser celda propia del grid, columna
   10 -- la misma columna donde "Abierta" cae en la fila de arriba (pedido explícito). */
.dca-mode-col {
  grid-column: 10;
  grid-row: 1;
  width: 100%;
}

/* Guardar sale del flex de configuración y pasa a ser celda propia del grid, columna 11 --
   la misma columna donde "Valor Actual" cae en la fila de arriba (pedido explícito). El
   ancho 100% lo hace ocupar todo el recuadro de esa columna, como cualquier otro campo. */
.dca-save-btn {
  grid-column: 11;
  grid-row: 1;
  width: 100%;
}

/* Guardar, Comprar Ahora y Cerrar Posición: mismo alto exacto que Take Profit % (pedido
   explícito), sin tocar color ni tipografía (eso lo sigue dando .ghost / el botón base). */
.dca-btn {
  height: var(--dca-field-height);
  line-height: calc(var(--dca-field-height) - 2px);
  padding: 0 8px;
  font-size: 13px;
}

/* Comprar Ahora + Cerrar Posición + capital máx.: columna final (12), bajo el bloque de PNL.
   La columna 11 (bajo "Valor Actual") ahora es exclusiva de Guardar (.dca-save-btn) -- antes
   compartían 11-13, pero eso la corría hacia dentro del bloque de acciones.
   grid-row fijo en 1: sin esto, agregar dca-exit-mode-row (ancho completo, ver más abajo)
   ANTES en el DOM corría el cursor de auto-flow a la fila 2, y este bloque (sin fila
   explícita) quedaba empujado a la fila 3 en vez de compartir la fila 1 con Guardar. */
.dca-row2-trailing {
  grid-row: 1;
  grid-column: 12 / 13;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 6px;
}
.dca-actions-inline {
  display: flex;
  gap: 8px;
}

.dca-meta-inline {
  font-size: 11px;
  color: var(--muted);
  white-space: nowrap;
}

@media (max-width: 860px) {
  .kpi-row, #admin-kpi-row { grid-template-columns: repeat(2, 1fr); }
  .metrics-row { grid-template-columns: repeat(3, 1fr); }
  .dca-form-grid { grid-template-columns: repeat(2, 1fr); }
  .dca-form-grid label, .dca-form-grid .dca-form-action-btn { grid-column: auto !important; grid-row: auto !important; }
}

@media (max-width: 560px) {
  .app { padding: 16px 12px 40px; }
  header.topbar {
    grid-template-columns: 1fr;
    justify-items: center;
    text-align: center;
    gap: 10px;
  }
  .topbar-side.right { justify-content: center; flex-wrap: wrap; }
  header.topbar .brand img { height: 31px; }
  .kpi-row, #admin-kpi-row { grid-template-columns: 1fr 1fr; }
  .metrics-row { grid-template-columns: repeat(2, 1fr); }
  .modal { padding: 14px 14px; }
  .search-row input[type="text"] { max-width: 100%; }
  /* En 1 sola columna, las posiciones explícitas (grid-column/grid-row) del form de alta
     dejarían de tener sentido y generarían columnas extra vacías -- se resetean a auto para
     que todo se apile en el mismo orden del DOM. */
  .dca-form-grid { grid-template-columns: 1fr; }
  .dca-form-grid label, .dca-form-grid .dca-form-action-btn { grid-column: auto !important; grid-row: auto !important; }
  .dca-form-header { flex-direction: column; align-items: flex-start; }
  /* En mobile no hace falta que las 2 filas del cuadro DCA compartan grid de columnas:
     todo se apila para que se pueda leer sin scroll horizontal. */
  .dca-row-top, .dca-row-bottom { display: flex; flex-direction: column; align-items: stretch; }
  .dca-identity { display: flex; flex-wrap: wrap; gap: 8px; }
  .dca-card-symbol, .dca-step-pill, .dca-decimals-select, .dca-paused-dot { grid-column: auto; }
  /* El margin-left negativo de escritorio (ver .dca-decimals-select) asume que está pegado
     al grid de columnas -- acá .dca-identity ya es flex-wrap, así que se resetea para que
     no se monte sobre el step-pill anterior. */
  .dca-decimals-select { margin-left: 0; width: auto; }
  .dca-step-pill.is-editing { width: 132px; }
  .dca-pnl-block { text-align: left; }
  .dca-quickstats { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px 16px; }
  .dca-quickstat { grid-column: auto !important; }
  .dca-progress-inline { width: 100%; }
  /* En mobile .dca-row-bottom ya es flex-column (ver arriba); .dca-config-inline sigue
     siendo display:contents así que sus labels pasan directo a ser items de ese flex,
     apilados en el orden del DOM junto con Modo De Salida y Guardar. */
  .dca-config-inline label, .dca-mode-col { grid-column: auto; white-space: normal; }
  .dca-save-btn { grid-column: auto; width: 100%; }
  .dca-config-inline input[type="number"] { width: 100%; }
  .dca-row2-trailing { align-items: stretch; }
  .dca-actions-inline { flex-direction: column; }
}

/* Dashboard principal en celular: restablece las coordenadas de la grilla de escritorio
   y crea una jerarquía compacta, táctil y sin desbordes. Se mantiene acotado a
   data-tab-panel="performance" para no alterar formularios ni módulos operativos. */
@media (max-width: 560px) {
  html { scrollbar-gutter: auto; }
  .app { padding: 12px 10px 32px; }

  header.topbar { margin-bottom: 14px; gap: 8px; }
  header.topbar .brand { grid-row: 1; padding: 5px 14px; }
  header.topbar .brand img { height: 34px; }
  header.topbar > .topbar-side:first-child { grid-row: 2; }
  header.topbar h1 { font-size: 16px; line-height: 1.2; }
  header.topbar .subtitle { font-size: 11px; }
  .app-version { font-size: 9px; }
  .topbar-side.right { grid-row: 3; width: 100%; gap: 8px; }
  .topbar-side.right .icon-btn { width: 38px; height: 38px; }
  .topbar-side.right .conn-status {
    min-height: 30px; padding: 5px 8px; border: 1px solid var(--border);
    border-radius: 999px; background: var(--surface-1); font-size: 10px;
  }

  .tabs-bar-row {
    top: 0; z-index: 45; display: flex; flex-wrap: wrap; gap: 7px;
    margin: 0 -10px 12px; padding: 8px 10px;
    background: color-mix(in srgb, var(--page-plane) 94%, transparent);
    border-bottom: 1px solid var(--border); backdrop-filter: blur(12px);
  }
  .section-tabs {
    order: 1; flex: 1 1 100%; width: 100%; gap: 7px; padding: 2px 1px 6px;
    overflow-x: auto; overscroll-behavior-x: contain; scrollbar-width: none;
    scroll-snap-type: x proximity;
  }
  .section-tabs::-webkit-scrollbar { display: none; }
  .tab-btn { min-width: 42px; min-height: 42px; padding: 7px 9px; scroll-snap-align: start; justify-content: center; }
  .tab-btn .tab-icon { width: 24px; height: 24px; }
  .tab-btn.active { padding-inline: 11px; }
  .tab-btn.active .tab-label { display: block; max-width: 110px; font-size: 10.5px; }
  .header-actions { order: 2; width: 100%; flex-direction: row; justify-content: flex-end; align-items: center; }
  .tour-launch-btn, .dashboard-refresh-btn, .admin-mode-btn { min-height: 38px; }
  .tour-launch-btn span { display: inline; }

.pull-refresh-indicator {
    position: fixed; top: 8px; left: 50%; z-index: 90;
    display: flex; align-items: center; justify-content: center; gap: 8px;
    min-height: 36px; padding: 7px 13px; border: 1px solid var(--border); border-radius: 999px;
    background: color-mix(in srgb, var(--surface-1) 96%, transparent);
    color: var(--text-primary); box-shadow: 0 8px 24px rgba(0, 0, 0, .24);
    font-size: 10px; font-weight: 650; pointer-events: none;
    opacity: 0; transform: translate(-50%, -54px); transition: opacity .14s ease, transform .14s ease;
  }
  .pull-refresh-indicator.visible { opacity: 1; }
  .pull-refresh-indicator.ready { color: var(--series-2); border-color: color-mix(in srgb, var(--series-2) 60%, var(--border)); }
  .pull-refresh-indicator.refreshing { opacity: 1; transform: translate(-50%, 0) !important; }
  .pull-refresh-spinner {
    width: 15px; height: 15px; flex: 0 0 auto; border: 2px solid color-mix(in srgb, currentColor 25%, transparent);
    border-top-color: currentColor; border-radius: 50%;
  }
  .pull-refresh-indicator.refreshing .pull-refresh-spinner { animation: dashboard-refresh-spin .75s linear infinite; }

  section.panel[data-tab-panel="performance"] {
    padding: 12px; margin-bottom: 14px; border-radius: 12px;
  }
  [data-tab-panel="performance"] .kpi-row-double {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    grid-auto-rows: auto; gap: 7px; margin-bottom: 12px;
  }
  [data-tab-panel="performance"] .kpi-row-double > .kpi-tile {
    grid-column: auto; grid-row: auto; min-width: 0; min-height: 82px; padding: 10px 5px;
    justify-content: center;
  }
  [data-tab-panel="performance"] #tile-monto-total {
    grid-column: 1 / -1; min-height: 88px; order: 1;
    background: linear-gradient(135deg, color-mix(in srgb, var(--series-1) 11%, var(--surface-1)), var(--surface-1));
  }
  [data-tab-panel="performance"] #tile-saldo-invertido { order: 2; }
  [data-tab-panel="performance"] #tile-pnl-plus-stake { order: 3; }
  [data-tab-panel="performance"] #tile-roi { order: 4; }
  [data-tab-panel="performance"] #tile-pnl-no-realizado { order: 5; }
  [data-tab-panel="performance"] #tile-pnl-realizado { order: 6; }
  [data-tab-panel="performance"] #tile-pnltotal-plus-stake { order: 7; }
  [data-tab-panel="performance"] #tile-saldo-disponible { order: 8; }
  [data-tab-panel="performance"] #tile-apy-dashboard { order: 9; }
  [data-tab-panel="performance"] #tile-rendimiento-efectivo { order: 10; }
  [data-tab-panel="performance"] #tile-interes-ganado { order: 11; }
  [data-tab-panel="performance"] .kpi-tile .label {
    min-height: 30px; margin-bottom: 4px; display: flex; align-items: center;
    justify-content: center; overflow: visible; text-overflow: clip; white-space: normal;
    font-size: 9px; line-height: 1.18;
  }
  [data-tab-panel="performance"] .kpi-tile .value {
    max-width: 100%; overflow: hidden; text-overflow: ellipsis;
    font-size: clamp(13px, 3.8vw, 16px); line-height: 1.1;
  }
  [data-tab-panel="performance"] #tile-monto-total .value { font-size: 21px; }
  [data-tab-panel="performance"] .kpi-split-title { width: 100%; }
  [data-tab-panel="performance"] .kpi-split-cols { gap: 3px; }
  [data-tab-panel="performance"] .kpi-split-col { min-width: 0; }
  [data-tab-panel="performance"] .kpi-split-col .label { min-height: auto; margin-top: 3px; font-size: 7.5px; }
  [data-tab-panel="performance"] .kpi-tile-split .value { font-size: clamp(11px, 3.25vw, 14px); }
  [data-tab-panel="performance"] .edit-row { width: 100%; }
  [data-tab-panel="performance"] .edit-row button { min-height: 38px; }

  [data-tab-panel="performance"] .row-divider { margin: 4px 0 10px; }
  [data-tab-panel="performance"] .metrics-row { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 7px; margin-bottom: 12px; }
  [data-tab-panel="performance"] .metric-tile { min-width: 0; min-height: 76px; padding: 9px 5px; display: flex; flex-direction: column; justify-content: center; }
  [data-tab-panel="performance"] .metric-label { min-height: 28px; white-space: normal; font-size: 8.5px; line-height: 1.18; }
  [data-tab-panel="performance"] .metric-value {
    max-width: 100%; overflow: hidden; text-overflow: ellipsis;
    font-size: clamp(13px, 3.8vw, 16px); line-height: 1.1;
  }
  [data-tab-panel="performance"] .metrics-row .metric-tile:last-child:nth-child(odd) { grid-column: auto; }

  [data-tab-panel="performance"] .charts-row { gap: 9px; }
  [data-tab-panel="performance"] .chart-panel { padding: 10px; border-radius: 10px; }
  [data-tab-panel="performance"] .chart-header-row { min-height: 28px; margin-bottom: 5px; }
  [data-tab-panel="performance"] .chart-subtitle { font-size: 11px; line-height: 1.3; }
  [data-tab-panel="performance"] #equity-chart-container,
  [data-tab-panel="performance"] .chart-placeholder,
  [data-tab-panel="performance"] .pnl-by-pair,
  [data-tab-panel="performance"] .steps-distribution,
  [data-tab-panel="performance"] .closest-execute,
  [data-tab-panel="performance"] .portfolio-pie { height: 200px; }

  .info-icon:hover::after, .info-icon:focus::after {
    position: fixed; left: 12px; right: 12px; bottom: 14px; width: auto;
    transform: none; padding: 11px 12px; font-size: 12px; z-index: 200;
  }
}

@media (max-width: 420px) {
  /* Conserva las tres columnas incluso en teléfonos angostos, con densidad de dashboard SaaS. */
  [data-tab-panel="performance"] .kpi-row-double,
  [data-tab-panel="performance"] .metrics-row { gap: 5px; }
  [data-tab-panel="performance"] .kpi-row-double > .kpi-tile { padding-inline: 4px; }
  [data-tab-panel="performance"] .kpi-tile-split .value { font-size: 10.5px; }
  [data-tab-panel="performance"] .kpi-split-col .label { font-size: 7px; }
  [data-tab-panel="performance"] .closest-execute-symbol { width: 54px; }
  [data-tab-panel="performance"] .closest-execute-type { width: 52px; font-size: 9.5px; }
  [data-tab-panel="performance"] .steps-distribution-invested { width: 60px; }
}

/* Dashboard principal · celular · modo oscuro.
   Refuerza separación y lectura sin alterar el tema claro ni los demás módulos. */
@media (max-width: 560px) {
  :root:not([data-theme="light"]) section.panel[data-tab-panel="performance"] {
    border: 1px solid rgba(148, 163, 184, .24);
    background: linear-gradient(155deg, #111a2a, #0d1421);
    box-shadow: 0 12px 30px rgba(0, 0, 0, .24);
  }

  :root:not([data-theme="light"]) [data-tab-panel="performance"] .kpi-tile,
  :root:not([data-theme="light"]) [data-tab-panel="performance"] .metric-tile,
  :root:not([data-theme="light"]) [data-tab-panel="performance"] .chart-panel {
    border-color: rgba(148, 163, 184, .34);
    background: linear-gradient(145deg, #172235, #121b2b);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .035), 0 5px 14px rgba(0, 0, 0, .18);
  }

  :root:not([data-theme="light"]) [data-tab-panel="performance"] #tile-monto-total {
    border-color: rgba(96, 165, 250, .58);
    background: linear-gradient(135deg, rgba(37, 99, 235, .24), #142139 62%, #121b2b);
    box-shadow: inset 0 1px 0 rgba(147, 197, 253, .13), 0 7px 18px rgba(0, 0, 0, .22);
  }

  :root:not([data-theme="light"]) [data-tab-panel="performance"] .kpi-tile .label,
  :root:not([data-theme="light"]) [data-tab-panel="performance"] .metric-label,
  :root:not([data-theme="light"]) [data-tab-panel="performance"] .chart-subtitle,
  :root:not([data-theme="light"]) [data-tab-panel="performance"] .kpi-split-col .label {
    color: #cbd5e1;
    font-weight: 650;
  }

  :root:not([data-theme="light"]) [data-tab-panel="performance"] .kpi-tile .value,
  :root:not([data-theme="light"]) [data-tab-panel="performance"] .metric-value,
  :root:not([data-theme="light"]) [data-tab-panel="performance"] .chart-title {
    color: #f8fafc;
    font-weight: 750;
    text-shadow: 0 1px 1px rgba(0, 0, 0, .32);
  }

  :root:not([data-theme="light"]) [data-tab-panel="performance"] .row-divider {
    border-color: rgba(148, 163, 184, .28);
  }

  :root:not([data-theme="light"]) [data-tab-panel="performance"] button,
  :root:not([data-theme="light"]) [data-tab-panel="performance"] .period-btn {
    border: 1px solid rgba(147, 197, 253, .54);
    background: #1d4f91;
    color: #f8fafc;
    font-weight: 700;
    box-shadow: 0 3px 9px rgba(0, 0, 0, .24);
  }

  :root:not([data-theme="light"]) [data-tab-panel="performance"] button:hover,
  :root:not([data-theme="light"]) [data-tab-panel="performance"] button:focus-visible,
  :root:not([data-theme="light"]) [data-tab-panel="performance"] .period-btn.active {
    border-color: #93c5fd;
    background: #2563a9;
  }

  :root:not([data-theme="light"]) [data-tab-panel="performance"] input,
  :root:not([data-theme="light"]) [data-tab-panel="performance"] select {
    border-color: rgba(148, 163, 184, .5);
    background: #0b1320;
    color: #f8fafc;
  }

  :root:not([data-theme="light"]) [data-tab-panel="performance"] .info-icon {
    color: #93c5fd;
    border-color: rgba(147, 197, 253, .56);
    background: rgba(37, 99, 235, .15);
  }
}

/* Celebración al alcanzar Take Profit */
.celebration-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 300;
}
.celebration-overlay.open { display: flex; }
.celebration-card {
  background: linear-gradient(160deg, var(--surface-1), var(--surface-2));
  border: 1px solid var(--good);
  box-shadow: 0 0 0 1px rgba(12, 163, 12, 0.25), 0 20px 60px rgba(0, 0, 0, 0.45);
  border-radius: 16px;
  padding: 32px 36px;
  text-align: center;
  max-width: 380px;
  animation: celebration-pop 0.35s ease-out;
}
@keyframes celebration-pop {
  from { transform: scale(0.85); opacity: 0; }
  to { transform: scale(1); opacity: 1; }
}
.celebration-emoji { font-size: 42px; margin-bottom: 8px; }
.celebration-title {
  font-size: 20px;
  font-weight: 800;
  color: var(--good);
  margin-bottom: 6px;
}
.celebration-body {
  font-size: 14px;
  color: var(--text-primary);
  margin-bottom: 4px;
}
.celebration-pnl {
  font-size: 24px;
  font-weight: 800;
  color: var(--good);
  margin: 10px 0 18px;
  font-variant-numeric: tabular-nums;
}
.celebration-close {
  background: var(--good);
}

/* Recordatorio De Pago: mismo mecanismo que la celebración de Take Profit, pero en ámbar
   (--warning) en vez de rojo/verde -- pedido explícito de un tono amable y sobrio, no de
   alarma. Reutiliza .celebration-card/.celebration-close como base y solo pisa el color. */
.warning-card {
  border-color: var(--warning);
  box-shadow: 0 0 0 1px rgba(201, 133, 0, 0.2), 0 20px 60px rgba(0, 0, 0, 0.45);
}
.warning-card .celebration-title { color: var(--warning); }
.warning-close { background: var(--warning); }
/* Ícono lineal chico (mismo SVG que .admin-action-btn.warning) en vez del emoji grande de
   .celebration-emoji -- más elegante/sobrio, pedido explícito. */
.celebration-icon { display: flex; justify-content: center; margin-bottom: 10px; color: var(--warning); }
.celebration-icon svg { width: 32px; height: 32px; }

/* El modal de confirmación puede abrirse encima de otro modal ya abierto (ej. Guardar
   Configuración De Binance) — necesita quedar siempre arriba, sin importar el orden en el
   HTML (por defecto, a igual z-index, gana el que está más abajo en el DOM). */
.confirm-modal { z-index: 150; }

/* Modal de reinicio de datos (pide clave) */
.confirm-modal .modal { width: min(360px, 92vw); }
.reset-modal .modal { width: min(360px, 92vw); }
.reset-modal-body {
  font-size: 13px;
  color: var(--text-primary);
  margin-bottom: 14px;
  line-height: 1.5;
}
.reset-modal #reset-password {
  width: 100%;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-primary);
  padding: 8px 10px;
  font-size: 14px;
  margin-bottom: 10px;
}
.reset-modal-error {
  color: var(--critical);
  font-size: 12px;
  margin-bottom: 10px;
  min-height: 16px;
}
.reset-modal-actions {
  display: flex;
  gap: 10px;
  justify-content: flex-end;
}
button.danger { background: var(--critical); }

/* Modal de configuración de Binance (modo paper/real + API keys) */
.settings-modal .modal { width: min(400px, 92vw); }
.settings-field { margin-bottom: 14px; }
.settings-field label {
  display: block;
  font-size: 12px;
  color: var(--text-secondary);
  margin-bottom: 6px;
}
.settings-field .current-key {
  color: var(--muted);
  font-weight: 400;
}
.settings-field input[type="text"],
.settings-field input[type="password"],
.settings-field input[type="number"],
.settings-field select {
  width: 100%;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-primary);
  padding: 8px 10px;
  font-size: 14px;
}
.settings-hint {
  font-size: 12px;
  color: var(--muted);
  line-height: 1.5;
  margin-bottom: 14px;
}

/* Configuración Del Bot -- antes eran 3 pestañas separadas (API/Visual/Notificaciones);
   ahora es una sola página con scroll, dividida en secciones (pedido explícito
   2026-09-04: "no lo separes en 3 pestañas, deja todo junto, pero dividido en secciones"). */
/* .modal.bot-settings-modal, no ".bot-settings-modal .modal" -- bot-settings-modal va en
   el MISMO elemento que .modal (ver static/index.html), no en un ancestro; con el
   combinador descendiente esta regla nunca matcheaba nada y el modal quedaba con el ancho
   por defecto de .settings-modal .modal (400px) -- bug preexistente, encontrado al mirar
   por qué el modal salía angosto pese a este ancho. */
/* Modal más ancho y más alto que el resto (680x88vh -> 960px x 94vh) a propósito -- con 3
   columnas de tarjetas de notificaciones compactas entra casi todo sin scroll interno
   (pedido explícito: "trata de evitar los scroll, si quieres agrandar un poco la ventana,
   evalúalo"). */
/* overflow-y: hidden pisa el "auto" de .modal a propósito -- sin esto, el modal entero
   también scrollea (max-height + overflow-y:auto en la regla base .modal) AL MISMO TIEMPO
   que .bot-settings-body más abajo, apareciendo 2 barras de scroll anidadas (pedido
   explícito: "deja solo 1 scroll"). El header y los botones Cancelar/Guardar quedan fijos;
   solo .bot-settings-body scrollea. */
.modal.bot-settings-modal { width: min(960px, 94vw); max-height: 94vh; overflow-y: hidden; }
.bot-settings-body {
  max-height: calc(94vh - 130px);
  overflow-y: auto;
  padding-right: 4px;
  margin-right: -4px;
}
/* Cada sección es su propia "tarjeta" (fondo + borde + acento de color a la izquierda,
   a juego con el ícono de la cabecera) -- pedido explícito 2026-09-04: "separa bien las 3
   secciones... haz que se note mucho más" (antes solo una línea fina las separaba y no se
   notaban como bloques distintos). */
.bot-settings-section {
  padding: 14px 16px;
  margin-bottom: 12px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 12px;
}
.bot-settings-section:last-child { margin-bottom: 0; }
.bot-settings-section--visual { border-left: 3px solid color-mix(in srgb, var(--series-1) 55%, var(--border)); }
.bot-settings-section--notif { border-left: 3px solid color-mix(in srgb, var(--series-2) 55%, var(--border)); }
.bot-settings-section--api { border-left: 3px solid color-mix(in srgb, var(--series-3) 55%, var(--border)); }
.bot-settings-section .settings-hint { margin-bottom: 10px; }
.bot-settings-section .settings-field { margin-bottom: 10px; }
.bot-settings-section .settings-field:last-child { margin-bottom: 0; }
.admin-server-ip {
  display: flex; align-items: center; gap: 12px;
  margin: 0 0 12px; padding: 10px 12px;
  border: 1px solid color-mix(in srgb, var(--series-1) 40%, var(--border));
  border-radius: 9px;
  background: color-mix(in srgb, var(--series-1) 8%, var(--surface-2));
}
.admin-server-ip[hidden] { display: none; }
/* Resultado de la revisión semanal de permisos de la API Key (corrección 5, 2026-09-27). */
.settings-key-status {
  margin: 6px 0 2px; padding: 8px 10px; border-radius: 8px; font-size: 11px; line-height: 1.45;
  color: var(--critical);
  background: color-mix(in srgb, var(--critical) 10%, var(--surface-1));
  border: 1px solid color-mix(in srgb, var(--critical) 35%, var(--border));
}
.settings-key-status[hidden] { display: none; }
.admin-server-ip > div { flex: 1; min-width: 0; }
.admin-server-ip strong { display: block; font-size: 11.5px; color: var(--text-primary); }
.admin-server-ip span { display: block; margin-top: 2px; font-size: 9.5px; color: var(--muted); }
.admin-server-ip code {
  padding: 5px 8px; border-radius: 6px; color: var(--text-primary);
  background: var(--surface-1); font-size: 11px; font-variant-numeric: tabular-nums;
}
.admin-server-ip button { flex: none; padding: 6px 9px; font-size: 10px; }
@media (max-width: 560px) {
  .admin-server-ip { align-items: stretch; flex-direction: column; }
  .admin-server-ip button { width: 100%; }
}
/* La sección ahora tiene su propio fondo (--surface-2, ver arriba) -- todo lo que iba
   sobre el fondo del modal (--surface-2 también) necesita un tono más para no fundirse
   con la tarjeta que lo contiene. */
.bot-settings-section .settings-field input[type="text"],
.bot-settings-section .settings-field input[type="password"],
.bot-settings-section .theme-choice-btn { background: var(--surface-1); }
.bot-settings-section-head {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 10px;
}
/* El bloque de título+bajada crece para empujar las acciones (Guardar/Default) al extremo
   derecho de la cabecera -- .bot-settings-section-actions NO crece (así ambos quedan
   pegados uno junto al otro a la derecha, no repartidos por todo el ancho). */
.bot-settings-section-title { flex: 1; min-width: 0; }
.bot-settings-section-actions {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 8px;
  align-self: center;
}
.bot-settings-reset-btn,
.bot-settings-test-btn,
.bot-settings-save-btn {
  flex: none;
  padding: 5px 12px;
  font-size: 11.5px;
  font-weight: 600;
}
.bot-settings-test-btn { color: var(--series-1); border-color: color-mix(in srgb, var(--series-1) 42%, var(--border)); }
.bot-settings-section-head h4 {
  margin: 0 0 2px;
  font-size: 14px;
  font-weight: 700;
  color: var(--text-primary);
}
.bot-settings-section-head p {
  margin: 0;
  font-size: 12px;
  color: var(--muted);
  line-height: 1.4;
}
/* Un ícono redondo con acento de color propio por sección -- misma idea que los íconos
   categóricos del header (color-mix sobre el fondo del círculo + el trazo del ícono). */
.bot-settings-section-icon {
  flex: none;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.bot-settings-section-icon svg { width: 17px; height: 17px; }
.bot-settings-section-icon--api {
  background: color-mix(in srgb, var(--series-3) 16%, var(--surface-1));
  color: var(--series-3);
}
.bot-settings-section-icon--visual {
  background: color-mix(in srgb, var(--series-1) 16%, var(--surface-1));
  color: var(--series-1);
}
.bot-settings-section-icon--notif {
  background: color-mix(in srgb, var(--series-2) 16%, var(--surface-1));
  color: var(--series-2);
}
/* Visual -- elegir tema como botones explícitos (Oscuro/Claro/Personalizado 1/2) en vez
   del único ícono de toggle que había en el header (pedido explícito: se elimina de ahí,
   se muda acá). flex-wrap porque con los 2 "Personalizado" son 4 botones -- en una ventana
   angosta pasan a 2 filas de 2 en vez de achicarse hasta ilegibles. */
.theme-choice { display: flex; flex-wrap: wrap; gap: 8px; }
/* Oscuro y Claro son fijos -- no se puede tocar el color/intensidad de contornos ni
   textos estando en ninguno de los dos (pedido explícito 2026-09-05); esta bajada solo se
   ve mientras eso aplica (ver static/app.js::updateStyleActionButtons). */
.bot-settings-lock-hint {
  margin: 8px 0 0;
  font-size: 11px;
  color: var(--muted);
  line-height: 1.4;
}
.theme-choice-btn {
  flex: 1;
  min-width: 120px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  color: var(--text-primary);
  padding: 9px;
  font-size: 13px;
  font-weight: 600;
}
.theme-choice-btn:hover { filter: none; border-color: color-mix(in srgb, var(--series-1) 40%, var(--border)); }
.theme-choice-btn.active {
  background: color-mix(in srgb, var(--series-1) 12%, var(--surface-1));
  border-color: var(--series-1);
  color: var(--text-primary);
}

/* Color e intensidad de contornos y textos (primarios y secundarios) -- personalizan
   --border, --text-primary y --text-secondary en toda la app (pedido explícito
   2026-09-04). Aplicado y persistido en vivo desde static/app.js::applyStyleTuner --
   preferencia de este navegador, no pasa por el backend, mismo criterio que el tema. Los 3
   controles comparten el mismo diseño (.style-tuner) uno al lado del otro para no ocupar
   más alto que uno solo. */
.style-tuner-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
}
.style-tuner { display: flex; flex-direction: column; gap: 8px; }
.style-tuner label {
  font-size: 12px;
  color: var(--text-secondary);
}
/* Barra fina y sobria -- pedido explícito: "hazla elegante y sobria, reduce su tamaño"
   (el control nativo del navegador era grueso y llamativo). Reglas -webkit/-moz por
   separado a propósito: un selector inválido en un motor invalida TODA la regla que lo
   agrupa, así que no se pueden combinar en una sola lista como el resto del archivo.
   Ancho calculado, no medido -- pedido explícito 2026-09-05: "que las barras de intensidad
   tengan el mismo largo que las pelotitas, para que queden alineadas". Las 3 paletas
   siempre pintan las mismas 9 pelotitas (8 fijas + la personalizada, ver
   STYLE_ACCENT_COLORS/initStyleTuner en app.js): 9 × 15px de .style-color-swatch + 8 huecos
   × 6px de gap = 183px. Medirlo con JS (getBoundingClientRect) resultó frágil -- en este
   navegador embebido el layout del modal recién visible no siempre estaba listo a tiempo,
   ni con doble requestAnimationFrame. Si el conteo o tamaño de pelotitas cambia, este número
   hay que actualizarlo a mano junto con .style-color-swatch/.style-color-custom-input. */
.style-intensity-slider {
  width: 183px;
  height: 14px;
  margin: 2px 0;
  accent-color: var(--series-1);
  cursor: pointer;
}
.style-intensity-slider,
.style-intensity-slider::-webkit-slider-runnable-track { -webkit-appearance: none; appearance: none; background: transparent; }
.style-intensity-slider::-webkit-slider-runnable-track {
  height: 3px;
  border-radius: 999px;
  background: var(--border);
}
.style-intensity-slider::-moz-range-track {
  height: 3px;
  border-radius: 999px;
  background: var(--border);
}
.style-intensity-slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 12px;
  height: 12px;
  margin-top: -4.5px;
  border-radius: 50%;
  background: var(--series-1);
  border: 2px solid var(--surface-2);
  box-shadow: 0 0 0 1px var(--border);
}
.style-intensity-slider::-moz-range-thumb {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--series-1);
  border: 2px solid var(--surface-2);
  box-shadow: 0 0 0 1px var(--border);
}
.style-color-palette {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  /* fit-content, no 100% -- si no, esta fila ocupa todo el ancho de la columna (el div es
     hijo de un flex en columna, que por defecto estira a sus hijos) en vez del ancho justo
     de las pelotitas, que es con el que .style-intensity-slider se calculó para alinear. */
  width: fit-content;
}
.style-color-swatch {
  width: 15px;
  height: 15px;
  border-radius: 50%;
  border: 2px solid transparent;
  background: var(--swatch-color);
  cursor: pointer;
  padding: 0;
}
.style-color-swatch:hover { filter: none; transform: scale(1.15); }
.style-color-swatch.active {
  border-color: var(--neutral-strong);
  box-shadow: 0 0 0 2px var(--surface-2);
}
/* Oscuro/Claro: contornos y textos quedan bloqueados (pedido explícito 2026-09-05) --
   deshabilitados de verdad (no solo "no clickeables" a mano), así ni un clic accidental ni
   Tab+Enter los cambia. */
.style-color-swatch:disabled,
.style-color-custom-input:disabled {
  cursor: not-allowed;
  opacity: 0.4;
}
.style-color-swatch:disabled:hover,
.style-color-custom-input:disabled:hover { transform: none; }
.style-intensity-slider:disabled { cursor: not-allowed; opacity: 0.4; }

/* Última "pelotita": no es un color fijo, es un <input type="color"> real -- abre el
   selector nativo del sistema operativo con toda la rueda de colores (pedido explícito
   2026-09-05: "que puedas elegir muchos más colores"). Borde punteado en reposo para
   distinguirla de un vistazo de las 8 de color fijo; sólido + el mismo aro que las demás
   cuando es la elegida. */
.style-color-custom-input {
  -webkit-appearance: none;
  appearance: none;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  border: 2px dashed var(--muted);
  padding: 0;
  cursor: pointer;
  background: none;
  overflow: hidden;
}
.style-color-custom-input::-webkit-color-swatch-wrapper { padding: 0; border-radius: 50%; overflow: hidden; }
.style-color-custom-input::-webkit-color-swatch { border: none; border-radius: 50%; }
.style-color-custom-input::-moz-color-swatch { border: none; border-radius: 50%; }
.style-color-custom-input:hover { filter: none; transform: scale(1.15); }
.style-color-custom-input.active {
  border-style: solid;
  border-color: var(--neutral-strong);
  box-shadow: 0 0 0 2px var(--surface-2);
}

@media (max-width: 760px) {
  .style-tuner-grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 560px) {
  .style-tuner-grid { grid-template-columns: 1fr; }
}

/* Notificaciones -- catálogo fijo de 12 tipos (ver app/notifications.py), cada uno con
   Email y App activables por separado, cada canal con su propio modo (Tiempo real /
   Resumen diario / semanal / mensual). La leyenda de colores Email/App se retiró (pedido
   explícito 2026-09-05): el encabezado de la tabla ya dice "Email"/"App" sin ambigüedad. */

/* Tabla agrupada (Tu cuenta / Tus operaciones / Facturación y referidos / Seguridad, ver
   app/notifications.py::NOTIFICATION_CATALOG) -- de vuelta a columnas Email/App con
   encabezado único (pedido explícito 2026-09-04: "son muchas tarjetas... volvamos a las
   columnas de email y app"), pero conservando el título+bajada de cada aviso (eso sí
   gustó) y el agrupado por categoría, ahora como filas separadoras dentro de una sola
   tabla en vez de un header de tabla repetido por grupo. */
.notification-list { overflow-x: auto; }
.notif-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.notif-table th {
  text-align: left;
  padding: 0 8px 6px;
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-primary);
  border-bottom: 1px solid var(--border);
}
.notif-table-channel-head { width: 168px; text-align: center !important; }
.notif-table td {
  padding: 8px;
  border-bottom: 1px solid var(--border);
  vertical-align: middle;
}
.notif-table tbody tr:last-child td { border-bottom: none; }
.notif-group-row td {
  padding: 12px 8px 4px;
  font-size: 10.5px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-primary);
  border-bottom: none;
}
.notif-group-row:first-child td { padding-top: 2px; }
.notif-table-info { width: auto; }
.notif-row-title { font-size: 12px; font-weight: 700; color: var(--text-primary); }
.notif-row-desc { font-size: 10.5px; color: var(--muted); line-height: 1.3; margin-top: 2px; }
.notif-table-channel { width: 168px; }

.notif-channel {
  /* min-width: 0 -- si no, un <select> con opciones largas ("Resumen semanal") le impone
     su ancho de contenido a esta celda (default min-width: auto en items de flex),
     empujando toda la fila a desbordar con scroll horizontal. */
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 5px 6px;
  border-radius: 7px;
  background: var(--surface-1);
}
/* Antes solo el borde izquierdo distinguía Email de App, muy sutil (pedido explícito
   2026-09-05: "una distinción demasiado leve") -- ahora también un lavado de fondo del
   mismo color, bien tenue para no perder legibilidad del texto encima. */
.notif-channel--email {
  border-left: 2px solid color-mix(in srgb, var(--series-1) 55%, transparent);
  background: color-mix(in srgb, var(--series-1) 15%, var(--surface-1));
}
.notif-channel--app {
  border-left: 2px solid color-mix(in srgb, var(--series-2) 55%, transparent);
  background: color-mix(in srgb, var(--series-2) 15%, var(--surface-1));
}
.notif-channel-toggle {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--text-primary);
  cursor: pointer;
}
.notif-channel-toggle input[type="checkbox"] { width: 13px; height: 13px; cursor: pointer; flex: none; }
.notif-channel select {
  width: 100%;
  min-width: 0;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-primary);
  padding: 3px 4px;
  font-size: 10px;
}
.notif-channel select:disabled { color: var(--muted); cursor: not-allowed; opacity: 0.6; }

@media (max-width: 760px) {
  .notif-group-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 500px) {
  .notif-group-grid { grid-template-columns: 1fr; }
}

/* Antes era un <label>+<input> sueltos al pie de la sección; ahora es lo primero que se ve
   (pedido explícito 2026-09-05: se muda a donde estaba la leyenda Email/App, ya retirada, y
   se le pide un diseño "más elegante y sobrio") -- una barra con ícono, texto y el campo de
   hora alineados en fila, en su propia tarjeta para distinguirla de la tabla de abajo. */
.notification-digest-field {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 14px;
  padding: 10px 14px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--surface-1);
}
.notification-digest-icon {
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, var(--series-2) 16%, var(--surface-1));
  color: var(--series-2);
}
.notification-digest-icon svg { width: 15px; height: 15px; }
.notification-digest-text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.notification-digest-text label {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-primary);
  cursor: default;
}
.notification-digest-hint { font-size: 10.5px; color: var(--muted); }
/* Borde con el mismo acento verde que el ícono de la izquierda + sombra chica -- antes se
   perdía un poco contra el fondo de la barra (pedido explícito 2026-09-05: "dale nitidez"). */
.notification-digest-field input[type="time"] {
  flex: none;
  background: var(--surface-2);
  border: 1.5px solid color-mix(in srgb, var(--series-2) 45%, var(--border));
  border-radius: 8px;
  color: var(--text-primary);
  padding: 7px 12px;
  /* font-weight 400, no 700 -- pedido explícito 2026-09-05: el número muy grueso se veía
     poco definido (los dígitos casi se fusionan entre sí a este tamaño). */
  font-size: 14px;
  font-weight: 400;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);
}
.notification-digest-field input[type="time"]:hover { filter: none; border-color: var(--series-2); }
.notification-digest-field input[type="time"]:focus-visible { outline: 2px solid var(--series-2); outline-offset: 1px; }

/* Modal de Dust (saldos residuales -> USDT vía Convert, ver app/dust.py) */
.dust-modal .modal { width: min(520px, 92vw); }
.dust-list-header {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 8px;
}
.dust-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  max-height: 60vh;
  overflow-y: auto;
}
.dust-row {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
}
.dust-row-info { flex: 1; min-width: 0; }
.dust-row-asset { font-weight: 600; }
.dust-row-amount {
  font-size: 12px;
  color: var(--text-secondary);
  font-variant-numeric: tabular-nums;
}
.dust-row-usdt {
  font-size: 13px;
  font-weight: 600;
  color: var(--good);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* Dust cotizable pero por debajo del mínimo que Binance acepta ni siquiera en Convert (ver
   app/dust.py::_quote_dust) -- se muestra igual (pedido explícito: "que muestre el detalle
   del dust"), pero sin acción posible, atenuado para que no compita visualmente con las
   filas que sí se pueden convertir. */
.dust-row.not-convertible { opacity: 0.55; }
.dust-row-reason {
  font-size: 11px;
  color: var(--muted);
}
.dust-row button {
  flex-shrink: 0;
  padding: 6px 14px;
  font-size: 13px;
}

/* Panel de Facturación (tarifas globales + detalle mensual de cobros) */
.billing-header-row {
  display: flex;
  align-items: flex-end;
  justify-content: flex-start;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}

/* Configuración de cobros MIT: reutiliza el lenguaje visual de Integraciones, con la
   explicación separada de los secretos para que el flujo sea legible también en móvil. */
.mercadopago-settings-box { max-width: 820px; }

.checkout-mode-settings { display: grid; gap: 11px; padding: 14px; border: 1px solid var(--border);
  border-radius: 12px; background: color-mix(in srgb, var(--series-1) 5%, var(--surface-1)); }
.checkout-mode-heading { display: flex; align-items: center; gap: 8px; color: var(--text-primary); font-size: 12px; }
.checkout-mode-options { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 9px; }
.checkout-mode-option { display: flex; align-items: flex-start; gap: 8px; padding: 12px;
  border: 1px solid var(--border); border-radius: 10px; background: var(--surface-2); cursor: pointer; }
.checkout-mode-option:has(input:checked) { border-color: var(--series-1);
  background: color-mix(in srgb, var(--series-1) 12%, var(--surface-2));
  box-shadow: 0 0 15px color-mix(in srgb, var(--series-1) 16%, transparent); }
.gemini-settings-form .checkout-mode-option input[type="radio"] { width: 17px; height: 17px; flex: 0 0 17px;
  margin: 0; padding: 0; accent-color: var(--series-1); }
.checkout-mode-option > span:not(.info-icon) { display: grid; gap: 5px; min-width: 0; flex: 1; }
.checkout-mode-option strong { color: var(--text-primary); font-size: 11px; }
.checkout-mode-option small, .checkout-mode-note { color: var(--text-secondary); font-size: 10px; line-height: 1.45; }
.checkout-mode-option .checkout-info-icon { flex: 0 0 14px; }
.checkout-info-icon:hover::after, .checkout-info-icon:focus::after { content: none; }
.checkout-help-popover { position: fixed; z-index: 250; width: min(275px, calc(100vw - 24px));
  padding: 10px 12px; border: 1px solid color-mix(in srgb, var(--series-1) 50%, var(--border));
  border-radius: 10px; color: var(--text-primary); background: var(--surface-1);
  box-shadow: 0 12px 34px rgba(0,0,0,.38), 0 0 15px color-mix(in srgb, var(--series-1) 14%, transparent);
  font-size: 12px; font-weight: 400; line-height: 1.45; pointer-events: none; }
.checkout-help-popover[hidden] { display: none; }
@media (max-width: 680px) { .checkout-mode-options { grid-template-columns: 1fr; } }

#billing-payments-list { display: grid; gap: 8px; margin-top: 16px; }
.checkout-payment-row { display: grid; grid-template-columns: 1.35fr 1fr 1fr 1fr auto;
  align-items: center; gap: 10px; padding: 10px 12px; border: 1px solid var(--border, #425a7a);
  border-radius: 10px; background: rgba(64, 134, 210, .07); font-size: .82rem; }
.checkout-payment-row button { white-space: nowrap; }
#checkout-result-body { line-height: 1.6; overflow-wrap: anywhere; }
@media (max-width: 720px) {
  .checkout-payment-row { grid-template-columns: 1fr 1fr; }
  .checkout-payment-row button { grid-column: 1 / -1; }
}
.gemini-model-picker { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; }
.gemini-model-picker select { min-width: 0; }
.gemini-model-picker button { white-space: nowrap; }
.billing-payment-method {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 14px 0;
  padding: 12px 14px;
  border: 1px solid color-mix(in srgb, var(--good) 34%, var(--border));
  border-radius: 12px;
  background: color-mix(in srgb, var(--good) 6%, var(--panel));
}
.billing-payment-copy { display: grid; gap: 3px; margin-right: auto; }
.billing-payment-copy strong { color: var(--text-primary); }
.billing-payment-copy span { color: var(--text-secondary); font-size: 12px; }
.payment-method-box { max-width: 640px; }
.mp-secure-field {
  min-height: 42px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--input-bg, var(--panel));
}
.mercadopago-explanation {
  margin: 0 0 16px;
  padding: 14px 16px;
  border: 1px solid color-mix(in srgb, var(--series-1) 36%, var(--border));
  border-radius: 12px;
  background: color-mix(in srgb, var(--series-1) 7%, var(--panel));
}
.mercadopago-explanation strong { color: var(--text-primary); }
.mercadopago-explanation p { margin: 6px 0 0; color: var(--text-secondary); line-height: 1.5; }
.mercadopago-settings-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.mercadopago-enable {
  display: flex !important;
  align-items: flex-start;
  gap: 10px;
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 10px;
}
.mercadopago-enable input { width: auto !important; margin-top: 3px; }
.mercadopago-enable > span { display: grid; gap: 4px; }
.mercadopago-enable small { color: var(--text-secondary); font-weight: 400; }
@media (max-width: 640px) {
  .mercadopago-settings-grid { grid-template-columns: 1fr; }
  .mercadopago-settings-form .gemini-settings-actions { flex-wrap: wrap; }
  .billing-payment-method { align-items: stretch; flex-wrap: wrap; }
  .gemini-model-picker { grid-template-columns: 1fr; }
}
.billing-month-selector {
  display: flex;
  gap: 10px;
  margin-left: auto;
}

/* "Tramos Tarifarios" -- a qué tramo entra un cliente (por Saldo Total o Referidos
   Activos, lo que llegue primero) y qué se le cobra en cada uno. Referencia fija del
   negocio, no un dato en vivo -- por eso vive en un popover propio, no en el detalle
   mensual de al lado. El toggle sigue la misma receta de chip con ícono que ya usan
   .tour-launch-btn / .dashboard-refresh-btn (borde+fondo teñidos con color-mix, glow al
   hover) para que se sienta parte del mismo sistema, no un link suelto. */
.tariff-tiers { position: relative; }
.tariff-tiers-toggle {
  display: inline-flex; align-items: center; gap: 7px;
  border: 1px solid color-mix(in srgb, var(--series-1) 55%, var(--border));
  background: color-mix(in srgb, var(--series-1) 12%, var(--surface-1));
  color: var(--text-primary); white-space: nowrap;
}
.tariff-tiers-toggle svg:first-child { width: 15px; height: 15px; color: var(--series-1); flex-shrink: 0; }
/* Barra 1 (corta) roja, barra 2 (media) ámbar, barra 3 (alta) queda como estaba (currentColor,
   el azul de acento) -- tonos suaves via color-mix, no el rojo/ámbar puro, para que se vea
   sobrio y no "grite" al lado del resto de íconos apagados de la topbar/paneles. */
.tariff-tiers-bar-1 { fill: color-mix(in srgb, var(--critical) 80%, var(--text-primary)); }
.tariff-tiers-bar-2 { fill: color-mix(in srgb, var(--warning) 80%, var(--text-primary)); }
.tariff-tiers-bar-3 { fill: currentColor; }
.tariff-tiers-toggle:hover { border-color: var(--series-1); box-shadow: 0 0 0 3px color-mix(in srgb, var(--series-1) 12%, transparent); }
.tariff-tiers-caret { width: 12px; height: 12px; color: var(--muted); flex-shrink: 0; transition: transform .18s ease; }
.tariff-tiers-toggle[aria-expanded="true"] .tariff-tiers-caret { transform: rotate(90deg); }

.tariff-tiers-panel {
  position: absolute;
  top: calc(100% + 10px);
  left: 0;
  z-index: 20;
  width: 620px;
  max-width: min(94vw, 620px);
  padding: 16px 18px 14px;
  background: var(--surface-1);
  border: 1px solid var(--border);
  border-radius: 12px;
  box-shadow: 0 16px 40px rgba(0, 0, 0, .3);
}
.tariff-tiers-panel-header { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 12px; }
.tariff-tiers-panel-header h4 { margin: 0 0 3px; font-size: 14px; font-weight: 700; }
/* Mismo tamaño/tipo de letra que .tariff-tiers-note -- pedido explícito de que la bajada
   del título y las dos notas de abajo se lean como un mismo estilo de texto secundario. */
.tariff-tiers-panel-header p { margin: 0; color: var(--muted); font-size: 10.5px; font-weight: 400; line-height: 1.5; }
.tariff-tiers-close { width: 24px; height: 24px; padding: 0; flex-shrink: 0; border-radius: 6px; font-size: 12px; line-height: 1; }

/* table-layout: fixed + colgroup -- pedido explícito de que las 4 columnas de tramos
   tengan siempre el mismo ancho entre sí, sin importar si el contenido de una celda
   ("Sobre $30.000") es más largo que el de las otras. */
.tariff-tiers-table { width: 100%; min-width: 520px; table-layout: fixed; border-collapse: separate; border-spacing: 0; font-size: 12px; }
.tariff-tiers-col-label { width: 27%; }
.tariff-tiers-table th, .tariff-tiers-table td {
  padding: 8px 10px;
  text-align: center;
  border-bottom: 1px solid var(--border);
  overflow-wrap: break-word;
}
.tariff-tiers-table thead th { border-bottom: none; padding-bottom: 9px; }
.tariff-tiers-corner { background: transparent; }

/* Encabezado de tramos: cada columna con su propio degradé (misma familia de color, cada
   vez más intensa de izquierda a derecha) -- refuerza que son pasos ordenados de un mismo
   camino y a la vez le da profundidad propia a cada una, en vez de un bloque plano. La
   franja de color de cada columna sigue después hacia abajo (ver tinte por nth-child más
   abajo) para que quede "una columna", no solo "un encabezado de color". */
.tariff-tiers-tramo-row th {
  font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase;
  border-radius: 6px 6px 0 0;
  border-top: 3px solid transparent;
}
.tariff-tiers-tramo-1 { background: var(--tier-1-bg); color: var(--tier-1-text); border-top-color: var(--tier-1-edge); }
.tariff-tiers-tramo-2 { background: var(--tier-2-bg); color: var(--tier-2-text); border-top-color: var(--tier-2-edge); }
.tariff-tiers-tramo-3 { background: var(--tier-3-bg); color: var(--tier-3-text); border-top-color: var(--tier-3-edge); }
.tariff-tiers-tramo-4 { background: var(--tier-4-bg); color: var(--tier-4-text); border-top-color: var(--tier-4-edge); }

/* La franja de cada columna baja por el cuerpo de la tabla (tinte creciente, muy sutil)
   para que la separación entre columnas se note en toda la fila, no solo en el título. */
.tariff-tiers-table tbody td:nth-child(2) { background: color-mix(in srgb, var(--tier-1-edge) 9%, transparent); }
.tariff-tiers-table tbody td:nth-child(3) { background: color-mix(in srgb, var(--tier-2-edge) 9%, transparent); }
.tariff-tiers-table tbody td:nth-child(4) { background: color-mix(in srgb, var(--tier-3-edge) 9%, transparent); }
.tariff-tiers-table tbody td:nth-child(5) { background: color-mix(in srgb, var(--tier-4-edge) 11%, transparent); }

/* Criterios (a qué saldo/referidos corresponde cada tramo) -- más chicos y apagados,
   claramente subordinados a los Fee de abajo, que son lo que realmente se cobra. */
.tariff-tiers-criteria-row th {
  position: relative;
  text-align: left; font-weight: 600; font-size: 11px; color: var(--text-primary);
}
/* El * cuelga a la izquierda con position:absolute (no ancho-0+margen -- eso también corre
   "Saldo Total") para que quede antes de la palabra, con un espacio, sin mover ni un
   píxel "Saldo Total" de donde ya está alineado. left en positivo, DENTRO del padding
   izquierdo de la celda (10px) -- en negativo queda por fuera del área visible de
   .table-scroll (overflow-x: auto) y no se ve nada, que es lo que pasó la primera vez. */
.tariff-tiers-star { position: absolute; left: 1px; top: 8px; color: var(--muted); font-weight: 400; }
/* Sin text-transform: uppercase -- "Menor a" / "Al Menos" van tal cual están escritos en
   el HTML, no en mayúscula sostenida. */
.tariff-tiers-criteria-row th small { display: block; font-weight: 400; color: var(--muted); font-size: 9.5px; letter-spacing: .03em; }
.tariff-tiers-criteria-row td { color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.tariff-tiers-criteria-row:last-of-type th, .tariff-tiers-criteria-row:last-of-type td { border-bottom: 1px solid var(--border); }

/* Fees: la fila que de verdad importa -- ícono + nombre a la izquierda, porcentaje
   grande y en negrita por tramo. */
.tariff-tiers-fee-row th {
  text-align: left; font-weight: 600; font-size: 12px; color: var(--text-primary);
  border-bottom: 1px solid var(--gridline);
}
/* Ícono + texto van en un span inline-flex adentro del th -- un display:flex directo en
   la celda la sacaría del algoritmo de layout de tabla y desalinearía las columnas del
   resto de las filas. */
.tariff-tiers-fee-label { display: inline-flex; align-items: center; gap: 7px; }
.tariff-tiers-fee-label svg { width: 15px; height: 15px; color: var(--series-1); flex-shrink: 0; }
.tariff-tiers-fee-row td {
  font-weight: 700; font-size: 13px; font-variant-numeric: tabular-nums;
  border-bottom: 1px solid var(--gridline);
}
.tariff-tiers-fee-row:last-child th, .tariff-tiers-fee-row:last-child td { border-bottom: none; }

.tariff-tiers-note { margin: 12px 0 0; padding-top: 10px; border-top: 1px solid var(--border); color: var(--muted); font-size: 10.5px; line-height: 1.5; }
.tariff-tiers-note + .tariff-tiers-note { margin-top: 6px; padding-top: 0; border-top: none; }
/* El * cuelga afuera del texto con position:absolute -- un inline-block de ancho 0 con
   margin negativo (como estaba antes) también corre el TEXTO que sigue, no solo el
   asterisco, y por eso "El Saldo Total..." quedaba desalineado de la nota de arriba.
   Sacándolo del flujo por completo, el párrafo arranca en la misma sangría que el de
   arriba y el * queda "corrido" a la izquierda como pieza aparte. */
.tariff-tiers-note-star { position: absolute; left: -8px; top: 0; }
.tariff-tiers-note:has(.tariff-tiers-note-star) { position: relative; }
/* El de la pestaña Stake no comparte fila con otro elemento (a diferencia del de
   Facturación, donde margin-left:auto lo empuja contra un título al lado) — al ocupar el
   ancho completo por su cuenta, hace falta justify-content para mandar los selects a la
   derecha en vez de que queden pegados a la izquierda. */
.stake-movements-filter {
  justify-content: flex-end;
  margin-bottom: 10px;
}
.billing-month-selector select,
#admin-period-select {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--text-primary);
  padding: 6px 10px;
  font-size: 13px;
}
.billing-columns {
  display: flex;
  gap: 20px;
  align-items: flex-start;
}
.billing-detail {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 4px 16px;
  width: 380px;
  flex: 0 0 380px;
  box-sizing: border-box;
}
.billing-group-title {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--text-primary);
  padding-top: 10px;
  margin-bottom: 4px;
}
.billing-group:first-child .billing-group-title { padding-top: 6px; }
.billing-group-charges {
  border-top: 1px solid var(--border);
  margin-top: 10px;
}
.billing-group-charges .billing-group-title { padding-top: 14px; }
.billing-row {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 0;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
}
.billing-group .billing-row:last-child { border-bottom: none; }
.billing-row-sub {
  padding: 4px 0;
  font-size: 11px;
}
.billing-detail > .billing-total { border-bottom: none; }
.billing-row-sub-first {
  border-bottom: none;
}
.billing-row span:first-child { color: var(--text-secondary); }
.billing-row span:last-child { color: var(--text-primary); font-variant-numeric: tabular-nums; font-weight: 600; }

/* Regla semántica global del Estilo del panel: títulos y cualquier texto marcado como
   negrita pertenecen al nivel primario y, por tanto, siguen su selector de color. Los
   controles con fondo propio y los estados verde/rojo/ámbar conservan su color funcional
   para no comprometer contraste ni significado. */
:is(h1, h2, h3, h4, h5, h6, strong, b) { color: var(--text-primary); }
.billing-row span.good { color: var(--good); }
.billing-row span.critical { color: var(--critical); }
.billing-row-white span:first-child,
.billing-row-white span:last-child { color: var(--text-primary); }
.billing-total { padding-top: 16px; }
.billing-total span:first-child,
.billing-total span:last-child { color: var(--series-1); font-weight: 600; }
.billing-charges-wrap {
  flex: 1 1 0;
  min-width: 0;
  /* Antes 480px -- acortado, pedido explícito. 430px (no 423, los -1,5cm exactos) para que
     coincida con .billing-detail de al lado, que necesita esos 430px para no mostrar
     scroll (ver comentario ahí). */
  height: 360px;
  overflow-y: auto;
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: 8px;
  box-sizing: border-box;
}
.billing-charges-table {
  width: 100%;
}
.billing-charges-table thead th {
  position: sticky;
  top: 0;
  background: var(--surface-1);
  z-index: 1;
}

@media (max-width: 900px) {
  .billing-header-row {
    flex-direction: column;
    align-items: stretch;
  }
  .billing-month-selector {
    margin-left: 0;
  }
  .billing-columns {
    flex-direction: column;
  }
  .billing-detail {
    width: 100%;
    flex: 1 1 auto;
  }
}

/* Pestaña Facturación reordenada (pedido explícito 2026-10-11): 3 tarjetas resumen arriba,
   detalle del mes plegable a la izquierda y una sola zona con pestañas (Cargos / Mis pagos)
   a la derecha. Los ids de todos los elementos se conservan: la lógica no cambió. */
.billing-summary { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 14px 0; }
.billing-card {
  display: flex; flex-direction: column; gap: 6px; padding: 14px 16px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 12px; min-width: 0;
}
.billing-card-label { font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--text-secondary); }
.billing-card-value { font-size: 24px; font-weight: 600; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.billing-card-note { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px; font-size: 12px; color: var(--text-secondary); }
.billing-card-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: auto; }
.billing-card-actions button[hidden] { display: none; }
.billing-card-actions:not(:has(button:not([hidden]))) { display: none; }

.billing-detail-title { font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--text-secondary); padding: 10px 0 4px; }
.billing-fold { border-bottom: 1px solid var(--border); }
.billing-fold summary {
  display: flex; justify-content: space-between; gap: 12px; align-items: center; padding: 10px 0;
  font-size: 13px; cursor: pointer; list-style: none; color: var(--text-primary);
}
.billing-fold summary::-webkit-details-marker { display: none; }
.billing-fold summary > span:first-child::before { content: "▸"; display: inline-block; width: 14px; color: var(--text-secondary); transition: transform .15s; }
.billing-fold[open] summary > span:first-child::before { transform: rotate(90deg); }
.billing-fold summary > span:last-child { font-variant-numeric: tabular-nums; font-weight: 600; }
.billing-fold .billing-row { padding-left: 14px; }
.billing-fold .billing-row:last-child { border-bottom: none; }

.billing-right { flex: 1 1 0; min-width: 0; }
.billing-tabs { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-bottom: 10px; flex-wrap: wrap; }
.billing-tab-buttons { display: flex; gap: 10px; flex-wrap: wrap; }
/* Las pestañas reutilizan el chip de "Tramos Tarifarios" (.tariff-tiers-toggle); la activa
   queda marcada con el borde de acento pleno y el halo que ese chip muestra en hover. */
.billing-tab.active { border-color: var(--series-1); box-shadow: 0 0 0 3px color-mix(in srgb, var(--series-1) 12%, transparent); }
.billing-tabs select {
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 6px;
  color: var(--text-primary); padding: 6px 10px; font-size: 13px;
}
.billing-pane[hidden], .billing-month-selector[hidden] { display: none; }
.billing-tabs { margin: 14px 0 12px; }
.billing-box-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; min-height: 42px; }
.billing-box-head .billing-detail-title { padding: 0; }
/* "Este Mes": las dos cajas (Detalle del mes / Cargos del mes) son gemelas -- mismo borde,
   mismo encabezado y el mismo alto, la de la derecha se estira a la de la izquierda. */
.billing-pane[data-billing-pane="month"] .billing-columns { align-items: stretch; }
.billing-pane[data-billing-pane="month"] .billing-right {
  display: flex; flex-direction: column; background: var(--surface-2);
  border: 1px solid var(--border); border-radius: 8px; padding: 4px 16px 16px; box-sizing: border-box;
}
.billing-pane[data-billing-pane="month"] .billing-charges-wrap {
  flex: 1 1 0; height: auto; min-height: 200px; border-radius: 6px;
}
.billing-card-wide { margin-bottom: 14px; }
.billing-summary-two { grid-template-columns: repeat(2, minmax(0, 1fr)); margin-top: 0; }
#billing-payments-panel { padding-top: 4px; }
@media (max-width: 900px) {
  .billing-summary, .billing-summary-two { grid-template-columns: 1fr; }
  .billing-right { width: 100%; }
}

/* Pestaña "Saldo Pendiente": total + botón arriba, meses adeudados con las mismas columnas del
   Historial Mensual del admin, y el pago automático como franja al final. */
.billing-pending-head { flex-direction: row; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.billing-pending-total { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.billing-pending-head .billing-card-actions { margin-top: 0; }
.billing-card-strip { flex-direction: row; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap; margin-top: 14px; }
.billing-card-strip .billing-card-actions { margin-top: 0; }
.billing-box { background: var(--surface-2); border: 1px solid var(--border); border-radius: 8px; padding: 4px 16px 12px; margin-top: 14px; }
.billing-box[hidden] { display: none; }
#pending-months-box .client-billing-note { margin-left: 4px; }
#pending-months-box .billing-card-note { text-align: right; }

/* Meses pendientes como tarjetas: cada mes es un bloque con sus cifras agrupadas por tema
   (Actividad / Transacciones / Utilidad / Stake) y el resumen de pago destacado a la derecha. */
.pm-list { display: grid; gap: 10px; margin-top: 6px; }
.pm-card { border: 1px solid var(--border); border-radius: 10px; background: var(--surface-1); overflow: hidden; }
.pm-card.open { border-color: color-mix(in srgb, var(--series-1) 45%, var(--border)); }
.pm-head {
  display: flex; align-items: center; gap: 10px; width: 100%; padding: 12px 16px; text-align: left;
  background: transparent; border: none; border-radius: 0; color: var(--text-primary); cursor: pointer;
}
.pm-head .month-caret { color: var(--text-secondary); transition: transform .15s; }
.pm-card.open .pm-head .month-caret { transform: rotate(90deg); }
.pm-title { font-size: 15px; font-weight: 600; }
.pm-sub { font-size: 12px; color: var(--text-secondary); }
.pm-head-end { margin-left: auto; display: flex; align-items: center; gap: 12px; }
.pm-due { font-size: 16px; font-weight: 600; color: var(--critical); font-variant-numeric: tabular-nums; }
.pm-card:not(.open) .pm-body { display: none; }
.pm-card:not(.open) .pm-more { display: none; }
.pm-more { padding: 9px 16px; border-top: 1px solid var(--border); }
.pm-more .pay-link { font-size: 12.5px; }
.pm-body { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)) minmax(0, 1.15fr); gap: 0; border-top: 1px solid var(--border); }
.pm-group { padding: 12px 16px; border-right: 1px solid var(--border); display: grid; gap: 6px; align-content: start; }
.pm-group:last-child { border-right: none; background: color-mix(in srgb, var(--series-1) 6%, transparent); }
.pm-group-title { font-size: 10.5px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--text-secondary); margin-bottom: 2px; }
.pm-line { display: flex; justify-content: space-between; gap: 8px; font-size: 12.5px; }
.pm-line span:first-child { color: var(--text-secondary); }
.pm-line span:last-child, .pm-line strong { font-variant-numeric: tabular-nums; color: var(--text-primary); }
.pm-line-total { padding-top: 6px; border-top: 1px solid var(--border); font-size: 13.5px; }
.pm-line-total strong.critical { color: var(--critical); }
.pm-detail { border-top: 1px solid var(--border); padding: 10px 16px 14px; }
@media (max-width: 900px) {
  .pm-body { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pm-group { border-bottom: 1px solid var(--border); }
  .pm-group:last-child { grid-column: 1 / -1; border-bottom: none; }
}
@media (max-width: 520px) { .pm-body { grid-template-columns: 1fr; } .pm-group { border-right: none; } }

/* Mis Pagos: cada pago es una tarjeta (misma familia visual que "Meses pendientes"); los
   documentos (comprobante, boleta, factura) son botones dentro de la tarjeta. */
.pay-filters { display: flex; gap: 8px; flex-wrap: wrap; }
.pay-filters select, .cb-docs-form select, .cb-docs-form input[type="text"] {
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 6px;
  color: var(--text-primary); padding: 6px 10px; font-size: 13px;
}
.pay-card { border: 1px solid var(--border); border-radius: 10px; background: var(--surface-1); overflow: hidden; }
.pay-card.open { border-color: color-mix(in srgb, var(--series-1) 45%, var(--border)); }
.pay-card.muted { opacity: .8; }
.pay-card.open .pm-head .month-caret { transform: rotate(90deg); }
.pay-card .pm-head { padding: 9px 14px; }
.pay-body { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 22px; padding: 7px 14px 9px; border-top: 1px solid var(--border); font-size: 12px; }
.pay-meta span { color: var(--text-secondary); }
.pay-meta strong { color: var(--text-primary); font-weight: 600; margin-left: 4px; }
.pay-body .pay-docs { margin-left: auto; }
#payment-history-list { gap: 8px; }
.pay-body .pm-group:last-child { background: transparent; border-right: none; }
.pay-docs { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.pay-doc-btn { font-size: 12px; padding: 5px 12px; border-radius: 6px; white-space: nowrap; }
.pay-doc-empty { font-size: 12.5px; color: var(--text-secondary); }
.pay-detail-grid { display: flex; flex-wrap: wrap; gap: 6px 22px; margin-bottom: 10px; font-size: 11.5px; color: var(--text-secondary); }
.pay-detail-grid strong { color: var(--text-primary); font-weight: 600; }
.cb-docs-form { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin: 8px 0 10px; }
.cb-docs-form input[type="file"] { font-size: 12px; max-width: 260px; }
.cb-doc-chip { display: inline-flex; align-items: center; gap: 6px; margin: 2px 8px 2px 0; }
.cb-doc-chip button { padding: 0 6px; font-size: 12px; line-height: 1.4; }
@media (max-width: 600px) { .pay-body .pay-docs { margin-left: 0; width: 100%; } }

/* Mis Pagos simplificado (pedido explícito 2026-10-11): sin recuadros anidados. Una lista plana,
   una fila por pago separada por una línea fina; los documentos son enlaces de texto. */
.pay-wrap { margin-top: 4px; }
.pay-toolbar { display: flex; justify-content: space-between; align-items: center; gap: 10px; flex-wrap: wrap; padding: 4px 2px 10px; }
.pay-toolbar .billing-detail-title { padding: 0; }
.pay-list { border-top: 1px solid var(--border); }
.pay-row { border-bottom: 1px solid var(--border); }
.pay-row.muted .pay-what strong, .pay-row.muted .pay-amount { color: var(--text-secondary); }
.pay-main {
  display: grid; grid-template-columns: 96px minmax(0, 1fr) 104px 132px 330px; align-items: center; gap: 14px;
  padding: 11px 6px; cursor: pointer;
}
.pay-main:hover { background: color-mix(in srgb, var(--series-1) 5%, transparent); }
.pay-date { font-size: 12.5px; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.pay-what { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.pay-what strong { font-size: 15px; font-weight: 600; color: var(--text-primary); }
.pay-what small { font-size: 12px; color: var(--text-secondary); }
.pay-amount { text-align: right; font-size: 16px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--text-primary); }
.pay-main .pay-docs { display: flex; flex-wrap: wrap; justify-content: flex-start; gap: 4px 14px; }
.pay-main .pill { justify-self: center; }
.pay-link { background: none; border: none; padding: 0; font-size: 12.5px; color: var(--series-1); text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
.pay-link:hover { filter: brightness(1.2); }
.pay-row .pm-detail { border-top: 1px dashed var(--border); background: color-mix(in srgb, var(--series-1) 4%, transparent); }
@media (max-width: 760px) {
  .pay-main { grid-template-columns: minmax(0, 1fr) auto; gap: 4px 12px; }
  .pay-date { grid-column: 1; }
  .pay-what { grid-column: 1; grid-row: 2; }
  .pay-main .pill { grid-column: 2; grid-row: 1; justify-self: end; }
  .pay-amount { grid-column: 2; grid-row: 2; }
  .pay-main .pay-docs { grid-column: 1 / -1; justify-content: flex-start; }
}

/* Estados de cobranza: Vigente / Atrasado / Suspendido / Desconectado. */
.account-notice-actions { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin-top: 4px; }
.account-notice-actions .celebration-close { margin-top: 0; }
.account-suspended-overlay {
  position: fixed; inset: 0; z-index: 30; display: flex; align-items: center; justify-content: center;
  padding: 24px; background: rgba(5, 10, 20, .6); pointer-events: none;
}
.account-suspended-overlay[hidden] { display: none; }
.account-suspended-card {
  pointer-events: auto; width: min(460px, 100%); padding: 24px 26px; text-align: center;
  background: var(--surface-1); border: 1px solid var(--critical); border-radius: 14px;
  box-shadow: 0 24px 70px rgba(0, 0, 0, .5);
}
.account-suspended-icon { width: 34px; height: 34px; margin: 0 auto 10px; color: var(--critical); }
.account-suspended-icon svg { width: 100%; height: 100%; }
.account-suspended-title { font-size: 17px; font-weight: 600; color: var(--text-primary); margin-bottom: 10px; }
.account-suspended-body { font-size: 13px; line-height: 1.6; color: var(--text-secondary); margin-bottom: 16px; white-space: pre-line; }
/* Suspendido: solo se puede mirar. La barra de pestañas sigue activa (para entrar a Facturación);
   el contenido de las demás pestañas no recibe clics. El servidor además rechaza cada cambio. */
body.account-suspended .tab-panel:not([data-tab-panel="billing"]) { pointer-events: none; user-select: text; }

.account-pill { display: inline-block; margin-left: 6px; padding: 1px 8px; border-radius: 999px; font-size: 10.5px; font-weight: 600; cursor: pointer; white-space: nowrap; }
.account-pill.atrasado { background: color-mix(in srgb, var(--warning, #f0be35) 18%, transparent); color: var(--warning, #f0be35); }
.account-pill.suspendido { background: color-mix(in srgb, var(--critical) 18%, transparent); color: var(--critical); }
.account-pill.desconectado { background: var(--surface-2); color: var(--text-secondary); border: 1px solid var(--border); }
.account-pill.approval { box-shadow: 0 0 0 1px var(--critical); }
.cb-account-status {
  display: flex; align-items: center; justify-content: space-between; gap: 14px; flex-wrap: wrap;
  margin: 0 0 14px; padding: 12px 16px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-1);
}
.cb-account-status[hidden] { display: none; }
.cb-account-status .cb-status-main { display: grid; gap: 4px; }
.cb-account-status .cb-status-title { font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--text-secondary); }
.cb-account-status .cb-status-line { font-size: 13px; color: var(--text-secondary); }
.cb-account-status .cb-status-actions { display: flex; gap: 8px; flex-wrap: wrap; }

.cb-month-btn { margin-left: 6px; padding: 1px 8px; font-size: 11px; border-radius: 6px; white-space: nowrap; }

/* Admin Mode: la pestaña entera se ensancha 1 cm a cada lado (pedido explícito 2026-10-12). Solo
   el contenido de la pestaña: el recuadro "Bot De Trading Automatizado" y el de las pestañas
   (dentro de .app, fuera de #admin-view) conservan su ancho. En pantallas angostas se ensancha
   lo que quepa, siempre dejando 20 px de margen contra el borde de la ventana. */
#admin-view {
  margin-inline: calc(-1 * min(1cm, max(0px, (100vw - 100% - 40px) / 2)));
}

.cb-docs-label { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 600; color: var(--text-secondary); }
.cb-docs-target { margin: 0 0 8px; font-size: 12.5px; color: var(--text-secondary); }
.cb-docs-target strong { color: var(--text-primary); }
#cb-docs-body tr.cb-row-selected td { background: color-mix(in srgb, var(--series-1) 14%, transparent); }
#cb-docs-body tr.cb-row-selected td:first-child { box-shadow: inset 3px 0 0 var(--series-1); }

/* === VISTA PREVIA DE ESCALERA + MEDIDOR DE COBERTURA (ideas 1 y 2) -- ver app.js === */
.dca-preview {
  display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: 14px; margin-top: 14px;
  padding-top: 14px; border-top: 1px solid var(--border);
}
.dca-preview[hidden] { display: none; }
.dca-preview-title { font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--text-secondary); margin-bottom: 8px; }
.dca-preview-chart, .dca-preview-meter { min-width: 0; padding: 12px 14px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-1); }
/* Colores del gráfico: los MISMOS del dashboard, para que todo el bot siga una secuencia común.
   Azul = compras/escalones (como "Distribución De Escalones"), verde = venta con ganancia
   (como el Take Profit de "Más Cerca De Ejecutarse"), ámbar = punto intermedio (como el
   portafolio y los medidores) y rojo = insuficiente (como "Cobertura De Escalones").
   Al ser variables del tema, cambian solas entre tema oscuro y claro. */
.dca-preview-chart {
  --c-buy: var(--series-1);
  --c-buy-dark: color-mix(in srgb, var(--series-1) 74%, #06152b);   /* extremos del degradé de las barras: */
  --c-buy-2: #69b3ff;                                              /* el mismo de .steps-distribution-bar */
  --c-avg: var(--portfolio-3);
  --c-sell: var(--good);
  --c-warn: var(--critical);
  --c-warn-dark: color-mix(in srgb, var(--critical) 72%, #21070b);   /* degradé rojo de .closest-execute-bar.buy */
  --c-warn-2: #ff7180;
  --c-glow: var(--premium-glow);
}
.dca-preview-story { font-size: 13px; line-height: 1.55; color: var(--text-secondary); margin: -2px 0 10px; }
.dca-preview-story b { color: var(--text-primary); font-weight: 600; }
.dca-chart-wrap { position: relative; }
.dca-preview-chart svg { display: block; width: 100%; height: auto; overflow: visible; }
.dca-preview-chart .grid { stroke: var(--border); stroke-width: 1; stroke-dasharray: 2 4; }
.dca-preview-chart .axis { stroke: var(--border); stroke-width: 1; }
.dca-preview-chart .buy-line { fill: none; stroke: var(--c-buy); stroke-width: 2.6; stroke-linejoin: round; stroke-linecap: round; filter: drop-shadow(0 0 5px var(--c-glow)); }
.dca-preview-chart .avg-line { fill: none; stroke: var(--c-avg); stroke-width: 1.6; stroke-linejoin: round; opacity: .9; }
.dca-preview-chart .target-line { fill: none; stroke: var(--c-sell); stroke-width: 2.2; stroke-dasharray: 6 5; filter: drop-shadow(0 0 4px color-mix(in srgb, var(--c-sell) 55%, transparent)); }
.dca-preview-chart .draw { stroke-dasharray: 1; stroke-dashoffset: 0; }
.dca-preview-chart g.step { cursor: pointer; }
.dca-preview-chart .dot { fill: var(--c-buy); stroke: var(--surface-1); stroke-width: 2; transition: r .15s; filter: drop-shadow(0 0 4px var(--c-glow)); }
.dca-preview-chart g.step:hover .dot { stroke: var(--text-primary); }
.dca-preview-chart g.no-funds .dot { fill: url(#dcaBarGradWarn); stroke: url(#dcaBarGradWarn); stroke-width: 2; filter: drop-shadow(0 0 4px color-mix(in srgb, var(--c-warn) 60%, transparent)); }
.dca-preview-chart text.dot-num { fill: #fff; font-size: 10px; font-weight: 700; pointer-events: none; }
.dca-preview-chart g.no-funds text.dot-num { fill: #fff; }
.dca-preview-chart .pulse { fill: none; stroke: var(--c-buy); stroke-width: 1.5; opacity: 0; animation: dcaPulse 2.2s ease-out infinite; }
.dca-preview-chart .bar { fill: url(#dcaBarGrad); opacity: .9; transform-box: fill-box; transform-origin: bottom; }
.dca-preview-chart .bar.no-funds { fill: url(#dcaBarGradWarn); opacity: .95; }
.dca-preview-chart text { fill: var(--text-secondary); font-size: 10.5px; }
.dca-preview-chart text.xl { font-size: 10.5px; }
.dca-preview-chart text.flag { font-weight: 600; }
.dca-preview-chart text.good { fill: var(--c-sell); }
.dca-preview-chart text.bar-label { font-size: 10px; fill: var(--text-primary); }
.dca-preview-chart text.bars-title { font-size: 10px; letter-spacing: .05em; text-transform: uppercase; }
.dca-chart-tip {
  position: absolute; top: -6px; z-index: 5; width: min(300px, 90%); padding: 10px 12px; font-size: 12px; line-height: 1.5;
  color: var(--text-secondary); background: var(--surface-popover, var(--surface-2)); border: 1px solid var(--border);
  border-radius: 10px; box-shadow: 0 10px 28px rgba(0, 0, 0, .35); pointer-events: none; transform: translateY(-100%);
}
.dca-chart-tip[hidden] { display: none; }
.dca-chart-tip strong { display: block; margin-bottom: 3px; color: var(--text-primary); font-size: 12.5px; }
.dca-chart-tip b { color: var(--text-primary); }
.dca-chart-tip em { display: block; margin-top: 4px; color: var(--c-warn); font-style: normal; }
/* Animación de entrada: la línea se dibuja, las compras aparecen una a una y las barras crecen. */
.animate .draw { animation: dcaDraw 1.1s ease-out both; }
.animate .pop { animation: dcaPop .38s cubic-bezier(.2, 1.4, .4, 1) both; transform-box: fill-box; transform-origin: center; }
.animate .bar { animation: dcaGrow .5s ease-out both; }
.animate .fade { animation: dcaFade .7s ease-out .8s both; }
@keyframes dcaDraw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes dcaPop { from { opacity: 0; transform: scale(.2); } to { opacity: 1; transform: scale(1); } }
@keyframes dcaGrow { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes dcaFade { from { opacity: 0; } to { opacity: 1; } }
@keyframes dcaPulse { 0% { r: 11; opacity: .8; } 100% { r: 22; opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .dca-preview-chart .pulse { animation: none; } }
.dca-preview-legend { display: flex; flex-wrap: wrap; gap: 4px 16px; margin-top: 8px; font-size: 11.5px; color: var(--text-secondary); }
.dca-preview-legend i { display: inline-block; width: 18px; height: 0; border-top: 3px solid var(--c-buy); vertical-align: middle; margin-right: 5px; border-radius: 2px; }
.dca-preview-legend i.l-avg { border-top: 2px solid var(--c-avg); }
.dca-preview-legend i.target { border-top: 2px dashed var(--c-sell); }
.dca-preview-legend i.nofunds { width: 10px; height: 10px; border: 0; border-radius: 50%; background: linear-gradient(180deg, var(--c-warn-2), var(--c-warn-dark)); }
.dca-preview-row { display: flex; justify-content: space-between; gap: 10px; padding: 5px 0; font-size: 12.5px; border-bottom: 1px solid var(--border); }
.dca-preview-row:last-child { border-bottom: none; }
.dca-preview-row span:first-child { color: var(--text-secondary); }
.dca-preview-row strong { color: var(--text-primary); font-variant-numeric: tabular-nums; text-align: right; }
.dca-preview-row strong.warn { color: var(--warning, #f0be35); }
.dca-preview-row strong.ok { color: var(--good); }
.dca-preview-hint { margin-top: 8px; font-size: 12px; line-height: 1.5; color: var(--text-secondary); }
.dca-preview-note { grid-column: 1 / -1; font-size: 11.5px; color: var(--text-muted, var(--text-secondary)); }
@media (max-width: 900px) { .dca-preview { grid-template-columns: 1fr; } }
/* === SIMULADOR HISTÓRICO (idea 3) -- ver app.js === */
.dca-sim { grid-column: 1 / -1; padding: 12px 14px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-1); }
.dca-sim-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 4px; }
.dca-sim-head select { background: var(--surface-2); border: 1px solid var(--border); border-radius: 6px; color: var(--text-primary); padding: 5px 10px; font-size: 12.5px; }
.dca-sim-cards { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; margin: 12px 0 8px; }
.dca-sim-card { padding: 10px 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface-2); min-width: 0; }
.dca-sim-card .label { font-size: 10.5px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--text-secondary); }
.dca-sim-card .value { margin: 4px 0 2px; font-size: 18px; font-weight: 600; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.dca-sim-card .sub { font-size: 11.5px; color: var(--text-secondary); line-height: 1.4; }
.dca-sim-line { font-size: 12.5px; color: var(--text-secondary); margin: 4px 0; }
.dca-sim-line strong { color: var(--text-primary); }
.dca-sim-stale { color: var(--warning, #f0be35); }
.dca-sim details { margin-top: 8px; }
.dca-sim summary { cursor: pointer; font-size: 12.5px; color: var(--series-1); }
.dca-sim-table { width: 100%; margin-top: 6px; border-collapse: collapse; font-size: 12px; }
.dca-sim-table th { text-align: left; font-weight: 600; color: var(--text-secondary); padding: 4px 6px; border-bottom: 1px solid var(--border); }
.dca-sim-table td { padding: 4px 6px; border-bottom: 1px solid var(--border); font-variant-numeric: tabular-nums; }
.dca-sim-table .good { color: var(--good); }
.dca-sim-table .critical { color: var(--critical); }
.dca-sim-fine { margin-top: 10px; font-size: 12px; line-height: 1.55; color: var(--text-secondary); }
.dca-sim-fine strong { color: var(--text-primary); }
.dca-sim-how { margin-top: 6px; }
.dca-sim-how ul { margin: 6px 0 0; padding-left: 18px; }
.dca-sim-how li { margin: 3px 0; }
@media (max-width: 900px) { .dca-sim-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* === fin SIMULADOR HISTÓRICO === */
/* === fin VISTA PREVIA DE ESCALERA === */

/* Aviso de comisiones pagadas con BNB: ámbar, el mismo tono de advertencia del resto del bot. */
.bnb-banner {
  display: flex; align-items: center; justify-content: space-between; gap: 14px; margin: 0 0 14px; padding: 12px 16px;
  border: 1px solid var(--portfolio-3); border-radius: 12px; background: color-mix(in srgb, var(--portfolio-3) 12%, var(--surface-1));
  font-size: 13px; line-height: 1.55; color: var(--text-secondary);
}
.bnb-banner[hidden] { display: none; }
.bnb-banner strong { color: var(--text-primary); }
.bnb-banner-msg { margin-top: 4px; font-size: 12.5px; color: var(--portfolio-3); }
.bnb-banner-actions { display: flex; flex-direction: column; gap: 8px; flex: 0 0 auto; }
.bnb-banner button { flex: 0 0 auto; white-space: nowrap; }
@media (max-width: 700px) { .bnb-banner { flex-direction: column; align-items: stretch; } }
.account-pill.bnb { background: color-mix(in srgb, var(--portfolio-3) 18%, transparent); color: var(--portfolio-3); }

/* Evolutivo mensual de Indicadores Globales (Admin Mode) */
.admin-title-with-icon { display: flex; align-items: center; gap: 8px; }
.admin-title-with-icon h2 { margin: 0 !important; }
/* Mismo chip e icono de barras que "Tramos Tarifarios" (Facturación), en versión compacta. */
.evo-open-btn {
  display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; padding: 0; cursor: pointer; border-radius: 8px;
  border: 1px solid color-mix(in srgb, var(--series-1) 55%, var(--border));
  background: color-mix(in srgb, var(--series-1) 12%, var(--surface-1)); color: var(--series-1);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.evo-open-btn svg { width: 15px; height: 15px; }
.evo-open-btn:hover { border-color: var(--series-1); box-shadow: 0 0 0 3px color-mix(in srgb, var(--series-1) 12%, transparent); }
.evolution-box { width: 98vw; max-width: 1800px; max-height: 94vh; overflow-x: hidden; padding: 16px 20px; }
.evo-controls { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 10px; margin-bottom: 10px; }
.evo-presets, .evo-options { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.evo-toggle { display: inline-flex; border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.evo-toggle button { border: 0; border-radius: 0; }
.evo-toggle button.active { background: var(--series-1); color: #fff; }
.evo-status { margin-bottom: 10px; padding: 8px 12px; border-radius: 8px; font-size: 12.5px; border: 1px solid var(--portfolio-3); color: var(--portfolio-3); }
.evo-status[hidden] { display: none; }
.evo-chart-frame { margin-bottom: 12px; padding: 10px 14px 6px; border: 1px solid var(--border); border-radius: 14px; background: linear-gradient(180deg, var(--surface-2), var(--surface-1)); }
.evo-frame-head { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 16px; margin-bottom: 6px; }
.evo-frame-head strong { font-size: 14px; }
.evo-table-btn { margin-left: auto; padding: 4px 12px; font-size: 12px; }
.evo-table-wrap { margin: 6px 0 8px; padding-top: 6px; border-top: 1px solid var(--border); }
.evo-legend-box { display: flex; flex-wrap: wrap; gap: 6px; }
.evo-leg-group { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 5px; }
.evo-leg-title { font-size: 11px; letter-spacing: .06em; text-transform: uppercase; color: var(--text-secondary); margin-right: 2px; }
.evo-leg { display: inline-flex; align-items: center; gap: 6px; padding: 3px 10px; border-radius: 999px; border: 1px solid var(--border); background: transparent; color: var(--text-secondary); font-size: 12px; cursor: pointer; opacity: .7; }
.evo-leg .dot { width: 9px; height: 9px; border-radius: 50%; border: 2px solid var(--chip); }
.evo-leg:hover { opacity: 1; }
.evo-leg.on { opacity: 1; color: var(--text-primary); border-color: var(--chip); background: color-mix(in srgb, var(--chip) 16%, transparent); }
.evo-leg.on .dot { background: var(--chip); }
.evo-empty { padding: 40px 10px; text-align: center; color: var(--text-secondary); }
.evo-stage { position: relative; }
.evo-svg { width: 100%; height: auto; display: block; }
.evo-grid { stroke: var(--gridline); stroke-width: 1; stroke-dasharray: 2 4; }
.evo-zero { stroke: var(--text-secondary); stroke-width: 1.6; }
.evo-axis.zero { fill: var(--text-primary); font-weight: 700; }
.evo-axis { fill: var(--text-secondary); font-size: 12px; }
.evo-axis.current { fill: var(--text-primary); font-weight: 700; }
.evo-current-band { fill: color-mix(in srgb, var(--series-1) 9%, transparent); }
.evo-bar.current { opacity: .6; stroke: var(--text-primary); stroke-width: 1; stroke-dasharray: 3 2; }
.evo-guide { stroke: var(--text-secondary); stroke-width: 1; stroke-dasharray: 3 3; opacity: .6; pointer-events: none; }
.evo-axes-note { display: flex; justify-content: space-between; margin-top: 2px; font-size: 11px; color: var(--text-secondary); }
.evo-tip { position: absolute; z-index: 5; min-width: 190px; padding: 9px 11px; border-radius: 10px; font-size: 12px; pointer-events: none; background: var(--surface-1); border: 1px solid var(--border); box-shadow: 0 8px 24px rgba(0,0,0,.35); }
.evo-tip[hidden] { display: none; }
.evo-tip strong { display: block; margin-bottom: 4px; }
.evo-tip div { display: flex; align-items: center; gap: 6px; padding: 1px 0; }
.evo-tip i, .evo-table th i { display: inline-block; width: 8px; height: 8px; border-radius: 50%; }
.evo-table th i { margin-right: 6px; }
.evo-tip b { margin-left: auto; padding-left: 12px; }
.evo-table-wrap { overflow-x: auto; }
.evo-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }
.evo-table th, .evo-table td { padding: 7px 10px; text-align: right; border-bottom: 1px solid var(--border); white-space: nowrap; }
.evo-table thead th { color: var(--text-secondary); font-weight: 500; }
.evo-table thead th:first-child { text-align: left; padding-left: 24px; } /* 10px + viñeta (8px) + margen (6px): alinea con la primera palabra */
.evo-table tbody th { text-align: left; font-weight: 500; position: sticky; left: 0; background: var(--surface-1); }
.evo-table .current { background: color-mix(in srgb, var(--series-1) 9%, transparent); }
.evo-table small { display: block; font-size: 10.5px; color: var(--series-1); }
.evo-delta { display: block; font-size: 11px; margin-top: 2px; }
.evo-delta.up { color: var(--good); }
.evo-delta.down { color: var(--critical); }
.evo-delta.flat { color: var(--text-secondary); }
.evo-note { margin-top: 10px; font-size: 12px; color: var(--text-secondary); }

/* ========================================================================== */
/* COVEX PREMIUM SAAS — capa visual transversal (solo presentación)          */
/* ========================================================================== */

:root {
  --premium-glow: color-mix(in srgb, var(--series-1) 28%, transparent);
  --premium-glow-soft: color-mix(in srgb, var(--series-1) 11%, transparent);
  --premium-surface: linear-gradient(145deg,
    color-mix(in srgb, var(--surface-1) 96%, var(--series-1)),
    color-mix(in srgb, var(--surface-1) 98%, #000));
  --premium-surface-2: linear-gradient(145deg,
    color-mix(in srgb, var(--surface-2) 96%, var(--series-1)),
    color-mix(in srgb, var(--surface-2) 98%, #000));
  --premium-shadow: 0 14px 38px rgba(0, 0, 0, .22),
    0 1px 0 rgba(255, 255, 255, .035) inset;
  --premium-shadow-hover: 0 19px 48px rgba(0, 0, 0, .30),
    0 0 24px var(--premium-glow-soft), 0 1px 0 rgba(255, 255, 255, .07) inset;
}
:root[data-theme="light"] {
  --premium-shadow: 0 12px 34px rgba(24, 44, 78, .10),
    0 1px 0 rgba(255, 255, 255, .88) inset;
  --premium-shadow-hover: 0 18px 44px rgba(24, 44, 78, .15),
    0 0 20px var(--premium-glow-soft), 0 1px 0 #fff inset;
}

body {
  background:
    radial-gradient(circle at 12% -8%, color-mix(in srgb, var(--series-1) 13%, transparent), transparent 34rem),
    radial-gradient(circle at 92% 16%, color-mix(in srgb, var(--series-7) 8%, transparent), transparent 30rem),
    var(--page-plane);
  background-attachment: fixed;
}
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  opacity: .23;
  background-image: linear-gradient(color-mix(in srgb, var(--series-1) 12%, transparent) 1px, transparent 1px),
    linear-gradient(90deg, color-mix(in srgb, var(--series-1) 10%, transparent) 1px, transparent 1px);
  background-size: 48px 48px;
  mask-image: linear-gradient(to bottom, rgba(0,0,0,.7), transparent 72%);
}

header.topbar {
  position: relative;
  padding: 10px 14px;
  border: 1px solid color-mix(in srgb, var(--series-1) 16%, var(--border));
  border-radius: 16px;
  background: color-mix(in srgb, var(--surface-1) 84%, transparent);
  box-shadow: var(--premium-shadow);
  backdrop-filter: blur(18px) saturate(125%);
}
header.topbar::after {
  content: "";
  position: absolute;
  inset: 0 auto auto 12%;
  width: 34%;
  height: 1px;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--series-1) 72%, white), transparent);
  box-shadow: 0 0 14px var(--premium-glow);
}
header.topbar .brand img { filter: drop-shadow(0 4px 11px rgba(0,0,0,.42)); }
.conn-dot.online { box-shadow: 0 0 0 3px color-mix(in srgb, var(--good) 14%, transparent), 0 0 12px var(--good); }

.tabs-bar-row {
  padding: 7px;
  border: 1px solid color-mix(in srgb, var(--series-1) 34%, var(--border));
  border-radius: 14px;
  background: color-mix(in srgb, var(--surface-1) 84%, transparent);
  box-shadow: 0 10px 30px rgba(0,0,0,.20), 0 0 22px var(--premium-glow-soft),
    0 1px 0 color-mix(in srgb, var(--series-1) 24%, transparent) inset;
  backdrop-filter: blur(18px) saturate(125%);
}
.tab-btn, .tour-launch-btn, .dashboard-refresh-btn, .admin-mode-btn {
  border-color: color-mix(in srgb, var(--series-1) 36%, var(--border));
  box-shadow: 0 6px 17px rgba(0,0,0,.16), 0 0 11px var(--premium-glow-soft),
    0 1px 0 color-mix(in srgb, var(--series-1) 26%, transparent) inset;
  transition: transform .2s ease, color .2s ease, background .2s ease,
    border-color .2s ease, box-shadow .2s ease, filter .2s ease;
}
.tab-btn::before { transform: scaleX(.34); opacity: .82; }
.tab-btn.active::before { transform: scaleX(1); opacity: 1; box-shadow: 0 0 12px var(--premium-glow); }
.tab-btn:hover, .tour-launch-btn:hover, .dashboard-refresh-btn:hover, .admin-mode-btn:hover {
  transform: translateY(-1px);
}
.tab-btn.active {
  background: linear-gradient(145deg,
    color-mix(in srgb, var(--series-1) 20%, var(--surface-1)),
    color-mix(in srgb, var(--series-1) 8%, var(--surface-1)));
  box-shadow: 0 8px 22px color-mix(in srgb, var(--series-1) 17%, transparent),
    0 1px 0 rgba(255,255,255,.07) inset;
}

section.panel, .modal, .tour-card, .dca-card-tour-window {
  position: relative;
  background: var(--premium-surface);
  border-color: color-mix(in srgb, var(--series-1) 34%, var(--border));
  box-shadow: var(--premium-shadow), 0 0 23px var(--premium-glow-soft),
    0 0 0 1px color-mix(in srgb, var(--series-1) 7%, transparent) inset;
}
section.panel::before, .modal::before, .dca-card-tour-window::before {
  content: "";
  position: absolute;
  top: -1px;
  left: 18px;
  right: 42%;
  height: 1px;
  pointer-events: none;
  background: linear-gradient(90deg, transparent, color-mix(in srgb, var(--series-1) 58%, white), transparent);
  opacity: 1;
  box-shadow: 0 0 13px var(--premium-glow);
}
.modal-overlay { backdrop-filter: blur(8px) saturate(120%); }
.modal { border-radius: 16px; box-shadow: 0 28px 90px rgba(0,0,0,.5), 0 0 36px var(--premium-glow-soft); }

.kpi-tile, .metric-tile, .chart-panel, .dca-card, .altfins-card,
.billing-detail, .billing-charges-wrap, .audit-launch-panel,
.dca-modal-exit-summary, .gemini-settings-status, .settings-group,
.notification-card, .rate-tier-card, .admin-kpi-card {
  position: relative;
  background: var(--premium-surface-2);
  border-color: color-mix(in srgb, var(--series-1) 32%, var(--border));
  box-shadow: 0 8px 24px rgba(0,0,0,.18), 0 0 18px var(--premium-glow-soft),
    0 1px 0 color-mix(in srgb, var(--series-1) 28%, transparent) inset,
    0 0 0 1px color-mix(in srgb, var(--series-1) 6%, transparent) inset;
  transition: transform .22s ease, border-color .22s ease, box-shadow .22s ease, filter .22s ease;
}
.kpi-tile::before, .metric-tile::before, .chart-panel::before,
.dca-card::before, .altfins-card::before {
  content: "";
  position: absolute;
  inset: 0 auto auto 0;
  width: 58%;
  height: 1px;
  pointer-events: none;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--series-1) 78%, white), transparent);
  opacity: .92;
  box-shadow: 0 0 12px var(--premium-glow);
}
.kpi-tile:hover, .metric-tile:hover, .chart-panel:hover,
.dca-card:hover, .altfins-card:hover {
  transform: translateY(-2px);
  border-color: color-mix(in srgb, var(--series-1) 42%, var(--border));
  box-shadow: var(--premium-shadow-hover);
}
/* El tooltip del ícono "i" vive dentro de la tarjeta, y estas tarjetas crean su propio plano de
   apilamiento (transform en hover, isolation en .chart-panel): el tooltip quedaba por debajo
   de la barra de pestañas sticky (z-index 45) y no se podía leer. Mientras el "i" está activo
   se sube la tarjeta entera por encima de la barra. */
:is(.kpi-tile, .metric-tile, .chart-panel, .dca-card, .altfins-card):has(.info-icon:hover, .info-icon:focus) {
  position: relative;
  z-index: 50;
}
.kpi-tile .value, .metric-value, .portfolio-pie-total-label {
  text-shadow: 0 0 18px color-mix(in srgb, currentColor 18%, transparent);
}

.chart-panel { isolation: isolate; }
.chart-panel::after {
  content: "";
  position: absolute;
  inset: 42px 10px 10px;
  z-index: -1;
  border-radius: 10px;
  pointer-events: none;
  background: radial-gradient(circle at 50% 0%, var(--premium-glow-soft), transparent 58%);
}
.chart-placeholder {
  background: linear-gradient(180deg, color-mix(in srgb, var(--series-1) 4%, transparent), transparent);
  box-shadow: 0 1px 0 rgba(255,255,255,.025) inset;
}
#chart-container, .pnl-by-pair, .steps-distribution, .closest-execute,
.portfolio-pie, .portfolio-pie-donut {
  filter: drop-shadow(0 9px 18px rgba(0,0,0,.14));
}
.portfolio-pie-donut svg {
  filter: drop-shadow(0 16px 25px rgba(0,0,0,.34)) drop-shadow(0 0 12px var(--premium-glow-soft));
}
.portfolio-pie-slice { stroke: color-mix(in srgb, var(--surface-1) 80%, transparent); stroke-width: .7; }
.portfolio-pie-legend-row {
  background: color-mix(in srgb, var(--surface-1) 76%, transparent);
  box-shadow: 0 4px 12px rgba(0,0,0,.10);
}

.pnl-by-pair-track, .steps-distribution-track, .closest-execute-track, .progress-bar, .tour-progress {
  background: color-mix(in srgb, var(--page-plane) 68%, var(--surface-2));
  box-shadow: 0 1px 3px rgba(0,0,0,.42) inset, 0 1px 0 rgba(255,255,255,.04);
}
.pnl-by-pair-bar, .steps-distribution-bar, .closest-execute-bar,
.progress-bar .fill-single, .progress-bar .fill-left,
.progress-bar .fill-yellow, .progress-bar .fill-right {
  position: relative;
  box-shadow: 0 0 12px color-mix(in srgb, currentColor 42%, transparent),
    0 1px 0 rgba(255,255,255,.28) inset;
}
.steps-distribution-bar, .progress-bar .fill-single {
  background: linear-gradient(90deg, color-mix(in srgb, var(--series-1) 74%, #06152b), var(--series-1), #69b3ff);
}
.pnl-by-pair-bar.badge-good, .progress-bar .fill-right, .closest-execute-bar.tp {
  background: linear-gradient(90deg, color-mix(in srgb, var(--good) 72%, #071b12), var(--good), #4fe39a);
}
.pnl-by-pair-bar.badge-critical, .closest-execute-bar.buy {
  background: linear-gradient(90deg, color-mix(in srgb, var(--critical) 72%, #21070b), var(--critical), #ff7180);
}
/* fill-left crece al revés que el resto de las barras rojas: su borde DERECHO queda fijo
   en el límite del primer tercio (ver "right: 66.6667%" en la regla base de layout) y la
   punta que avanza a medida que sube Próx. Compra es la IZQUIERDA, acercándose a 0% (una
   compra nueva). Compartir el degradé oscuro-a-claro de izquierda a derecha de las demás
   barras críticas (pensado para barras que crecen de izquierda a derecha) dejaba la punta
   que avanza siempre oscura y el borde fijo siempre claro -- exactamente al revés de "se
   pone más vivo a medida que se acerca al 100%" (pedido explícito 2026-09-24). Stops
   invertidos para esta sola barra. */
.progress-bar .fill-left {
  background: linear-gradient(90deg, #ff7180, var(--critical), color-mix(in srgb, var(--critical) 72%, #21070b));
}
/* Recuperación: mismo sentido que Take Profit (el borde izquierdo queda fijo en el límite
   del segundo tercio y la punta que avanza es la derecha, acercándose al 100% de
   recuperación), mismo nivel de contraste que Próx. Compra/Take Profit (72%) -- pedido
   explícito 2026-09-24 de igualar intensidad, después de probar 88% y 78% como "muy leve"
   y quedar cortos. */
.progress-bar .fill-yellow {
  background: linear-gradient(90deg, color-mix(in srgb, var(--warning) 72%, black), var(--warning), color-mix(in srgb, var(--warning) 72%, white));
}
/* Mismo factor de degradé que arriba, aplicado al tono ámbar del Trailing Stop
   (--series-3) -- pedido explícito para que "Más Cerca De Ejecutarse" luzca igual que
   Distribución De Escalones / PNL Por Par. `color` propio en las 3 variantes porque el
   glow de arriba usa currentColor y esta barra no comparte clase con ningún badge que
   ya lo defina (a diferencia de .badge-good/.badge-critical). */
.closest-execute-bar.buy { color: var(--critical); }
.closest-execute-bar.tp { color: var(--good); }
.closest-execute-bar.trailing {
  color: var(--series-3);
  background: linear-gradient(90deg, color-mix(in srgb, var(--series-3) 72%, #2b1a00), var(--series-3), #ffcf5c);
}

table.pairs {
  border-collapse: separate;
  border-spacing: 0;
  background: color-mix(in srgb, var(--surface-1) 78%, transparent);
}
table.pairs th {
  background: color-mix(in srgb, var(--surface-2) 92%, var(--series-1));
  box-shadow: 0 -1px 0 rgba(255,255,255,.025) inset, 0 1px 0 var(--border);
}
table.pairs tbody tr { transition: background .16s ease, box-shadow .16s ease; }
table.pairs tbody tr:hover {
  background: color-mix(in srgb, var(--series-1) 7%, transparent);
  box-shadow: 3px 0 0 color-mix(in srgb, var(--series-1) 70%, transparent) inset;
}

button:not(.tour-pipeline-step):not(.password-toggle) {
  box-shadow: 0 6px 16px color-mix(in srgb, var(--series-1) 19%, transparent),
    0 1px 0 rgba(255,255,255,.16) inset;
  transition: transform .18s ease, box-shadow .18s ease, filter .18s ease, border-color .18s ease;
}
button:not(:disabled):not(.tour-pipeline-step):not(.password-toggle):hover {
  transform: translateY(-1px);
  box-shadow: 0 9px 24px color-mix(in srgb, var(--series-1) 25%, transparent),
    0 1px 0 rgba(255,255,255,.2) inset;
}
button:not(:disabled):active { transform: translateY(0); }
button.ghost { background: color-mix(in srgb, var(--surface-2) 62%, transparent); }

input:not([type="checkbox"]):not([type="radio"]), select, textarea {
  background: color-mix(in srgb, var(--surface-2) 92%, var(--page-plane));
  border-color: color-mix(in srgb, var(--series-1) 12%, var(--border));
  box-shadow: 0 2px 7px rgba(0,0,0,.14) inset, 0 1px 0 rgba(255,255,255,.025);
  transition: border-color .18s ease, box-shadow .18s ease, background .18s ease;
}
input:not([type="checkbox"]):not([type="radio"]):focus, select:focus, textarea:focus {
  outline: none;
  border-color: color-mix(in srgb, var(--series-1) 78%, white);
  box-shadow: 0 0 0 3px var(--premium-glow-soft), 0 0 18px var(--premium-glow-soft),
    0 2px 7px rgba(0,0,0,.16) inset;
}
.switch input:checked + .slider {
  box-shadow: 0 0 14px color-mix(in srgb, var(--good) 30%, transparent), 0 1px 4px rgba(0,0,0,.3) inset;
}

.toast {
  background: color-mix(in srgb, var(--surface-2) 90%, transparent);
  box-shadow: 0 16px 42px rgba(0,0,0,.38), 0 0 22px var(--premium-glow-soft);
  backdrop-filter: blur(16px);
}
.info-icon { box-shadow: 0 0 10px var(--premium-glow-soft); }
.pill, .badge-good, .badge-critical, .altfins-overall-pill, .ai-opinion-verdict {
  text-shadow: 0 0 12px color-mix(in srgb, currentColor 20%, transparent);
}

/* Login y recuperación: misma identidad visual premium que el dashboard. */
.auth-page .login-wrap {
  position: relative;
  padding: 24px;
  overflow: hidden;
}
.auth-page .login-wrap::before, .auth-page .login-wrap::after {
  content: "";
  position: absolute;
  width: 420px;
  height: 420px;
  border-radius: 50%;
  filter: blur(18px);
  pointer-events: none;
}
.auth-page .login-wrap::before {
  top: -230px;
  left: -160px;
  background: radial-gradient(circle, color-mix(in srgb, var(--series-1) 24%, transparent), transparent 68%);
}
.auth-page .login-wrap::after {
  right: -180px;
  bottom: -250px;
  background: radial-gradient(circle, color-mix(in srgb, var(--series-7) 17%, transparent), transparent 68%);
}
.auth-page .login-card {
  position: relative;
  z-index: 1;
  max-width: 410px !important;
  padding: 34px 32px 30px !important;
  border: 1px solid color-mix(in srgb, var(--series-1) 30%, var(--border)) !important;
  border-radius: 20px !important;
  background: color-mix(in srgb, var(--surface-1) 88%, transparent) !important;
  box-shadow: 0 30px 90px rgba(0,0,0,.46), 0 0 52px var(--premium-glow-soft),
    0 1px 0 rgba(255,255,255,.08) inset !important;
  backdrop-filter: blur(22px) saturate(135%);
}
.auth-page .login-card::before {
  content: "COVEX";
  display: block;
  width: fit-content;
  margin: 0 auto 18px;
  color: var(--text-primary);
  font-size: 24px;
  font-weight: 800;
  letter-spacing: .28em;
  text-indent: .28em;
  text-shadow: 0 0 22px var(--premium-glow), 0 3px 12px rgba(0,0,0,.45);
}
.auth-page .login-card h1 { font-size: 20px !important; letter-spacing: -.02em; }
.auth-page .login-card .subtitle { margin-bottom: 24px !important; }
.auth-page .login-field { margin-bottom: 17px !important; }
.auth-page .login-field input {
  min-height: 44px;
  border-radius: 10px !important;
  padding: 10px 12px !important;
}
.auth-page #btn-submit, .auth-page #btn-forgot-submit {
  min-height: 44px;
  border-radius: 10px;
  font-weight: 700;
  background: linear-gradient(135deg, color-mix(in srgb, var(--series-1) 82%, #183765), var(--series-1), #5aa8ff);
  box-shadow: 0 12px 28px color-mix(in srgb, var(--series-1) 32%, transparent), 0 1px 0 rgba(255,255,255,.22) inset;
}
.auth-page .link-row a { text-shadow: 0 0 14px var(--premium-glow); }
.auth-page .form-error:not(:empty), .auth-page .form-ok:not(:empty) {
  padding: 10px 12px;
  border-radius: 9px;
  border: 1px solid color-mix(in srgb, currentColor 35%, transparent);
  background: color-mix(in srgb, currentColor 8%, transparent);
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { scroll-behavior: auto !important; transition-duration: .01ms !important; animation-duration: .01ms !important; animation-iteration-count: 1 !important; }
}

@media (max-width: 720px) {
  header.topbar { border-radius: 13px; padding: 9px 10px; }
  .tabs-bar-row { border-radius: 12px; }
  .kpi-tile:hover, .metric-tile:hover, .chart-panel:hover, .dca-card:hover, .altfins-card:hover { transform: none; }
  .auth-page .login-card { padding: 28px 22px 24px !important; }
}
@media (max-width: 560px) {
  .tabs-bar-row { top: 0; }
  .tab-btn { padding: 9px 12px; }
  .tab-btn .tab-label { display: none; }
  .tab-btn .tab-icon { width: 24px; height: 24px; font-size: 13px; }
}

/* ========================================================================== */
/* COVEX MOBILE SAAS — optimización transversal para todas las pestañas       */
/* ========================================================================== */
@media (max-width: 600px) {
  html, body { width: 100%; max-width: 100%; overflow-x: clip; }
  body { -webkit-text-size-adjust: 100%; }
  .app { width: 100%; padding: 10px 8px 28px; }

  header.topbar {
    margin-bottom: 10px;
    padding: 10px 9px;
    gap: 7px;
    border-radius: 14px;
    box-shadow: 0 10px 28px rgba(0,0,0,.24), 0 0 18px var(--premium-glow-soft);
  }
  header.topbar .brand { padding-block: 2px; }
  header.topbar .brand img { max-width: min(210px, 65vw); height: 31px; }
  header.topbar h1 { font-size: 15px; }
  header.topbar .subtitle { font-size: 10px; }
  .topbar-side.right { gap: 6px; }
  .topbar-side.right .conn-status { max-width: 100%; }

  .tabs-bar-row {
    margin: 0 -8px 10px;
    padding: 7px 8px 8px;
    gap: 6px;
    border-radius: 0 0 14px 14px;
    box-shadow: 0 9px 24px rgba(0,0,0,.20), 0 0 16px var(--premium-glow-soft);
  }
  .section-tabs { gap: 6px; padding-bottom: 4px; }
  .tab-btn {
    min-width: 40px;
    min-height: 40px;
    padding: 6px 8px;
    border-radius: 10px;
  }
  .tab-btn.active { min-width: max-content; }
  .tab-btn.active .tab-label { max-width: 104px; }
  .header-actions {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(42px, max-content));
    justify-content: end;
    gap: 6px;
  }
  .header-actions > button { min-height: 38px; padding-inline: 10px; }

  section.panel {
    width: 100%;
    min-width: 0;
    margin-bottom: 10px;
    padding: 11px 9px;
    border-radius: 13px;
    box-shadow: 0 9px 25px rgba(0,0,0,.20), 0 0 16px var(--premium-glow-soft);
  }
  .panel-header-row, .billing-header-row, .audit-launch-panel {
    align-items: stretch;
    flex-direction: column;
    gap: 9px;
  }
  .panel-header-row > *, .billing-header-row > *, .audit-launch-panel > * { min-width: 0; }
  .panel-header-row h2, .panel-header-row h3 { line-height: 1.25; }

  .search-row, .audit-filters, .altfins-schedule-form,
  .admin-client-tools, .billing-month-selector {
    width: 100%;
    margin-left: 0;
    align-items: stretch;
    gap: 8px;
  }
  .search-row, .billing-month-selector { flex-wrap: wrap; }
  .search-row input[type="text"], .audit-filters label,
  .audit-filters input, .audit-filters select,
  .altfins-schedule-form label, .altfins-schedule-form input,
  .billing-month-selector select { width: 100%; min-width: 0; }
  .audit-filters > button, .altfins-schedule-actions > button { flex: 1 1 120px; }
  .altfins-schedule-actions, .gemini-settings-actions { width: 100%; flex-wrap: wrap; }
  .altfins-schedule-actions > *, .gemini-settings-actions > * { flex: 1 1 130px; }
  .altfins-key-form { grid-template-columns: 1fr; }
  .altfins-key-actions { display: grid; grid-template-columns: 1fr 1fr; }
  .altfins-key-actions button { width: 100%; }
  .altfins-cards { grid-template-columns: 1fr; gap: 10px; }
  .altfins-card { padding: 12px; }

  .kpi-row, #admin-kpi-row { gap: 7px; }
  .kpi-tile, .metric-tile { min-width: 0; padding: 10px 7px; border-radius: 11px; }
  .kpi-tile .label, .metric-label { white-space: normal; line-height: 1.2; }
  .kpi-tile .value, .metric-value { overflow-wrap: anywhere; }

  .charts-row { gap: 8px; }
  .chart-panel { padding: 10px 8px; border-radius: 11px; }
  .chart-header-row { align-items: flex-start; gap: 7px; }
  .chart-title { line-height: 1.25; }
  .chart-placeholder, .pnl-by-pair, .steps-distribution, .closest-execute { height: 205px; }
  .portfolio-pie { gap: 10px; }
  .portfolio-pie-donut { min-height: 220px; }
  .portfolio-pie-donut svg { width: min(210px, 68vw); height: min(210px, 68vw); }

  .table-scroll, .notification-list, .billing-charges-wrap {
    width: 100%;
    max-width: 100%;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    border-radius: 9px;
  }
  .table-scroll table, .notification-list table { min-width: 680px; }
  table.pairs th, table.pairs td { padding-inline: 8px; }

  .dca-card { padding: 12px 10px; border-radius: 12px; }
  .dca-quickstats { gap: 8px 10px; }
  .dca-actions-inline button { width: 100%; min-height: 40px; }
  .dca-tour-demo-host.is-tour-active { padding-bottom: 0; }
  .dca-tour-popover {
    position: fixed !important;
    inset: auto 8px 8px !important;
    width: auto !important;
    max-height: min(48dvh, 380px);
    overflow-y: auto;
  }

  .modal-overlay { align-items: flex-end; padding: 0; }
  .modal, .modal.bot-settings-modal {
    width: 100%;
    max-width: none;
    max-height: 94dvh;
    margin: 0;
    padding: 16px 13px max(16px, env(safe-area-inset-bottom));
    border-radius: 18px 18px 0 0;
  }
  .modal-header { position: sticky; top: -16px; z-index: 6; padding: 10px 0; background: var(--surface-1); }
  .modal-header h3 { font-size: 16px; line-height: 1.25; }
  .modal-header button { min-width: 40px; min-height: 38px; }
  .bot-settings-body { max-height: calc(94dvh - 112px); padding-right: 1px; margin-right: 0; }
  .bot-settings-section { padding: 12px 10px; }
  .bot-settings-section-head { flex-wrap: wrap; gap: 9px; }
  .bot-settings-section-actions { width: 100%; display: grid; grid-template-columns: repeat(2, 1fr); }
  .bot-settings-section-actions button { width: 100%; min-height: 38px; }
  .theme-choice-btn { min-width: calc(50% - 4px); }
  .notification-digest-field { align-items: flex-start; flex-wrap: wrap; padding: 10px; }

  .tour-card {
    width: calc(100vw - 16px);
    max-height: calc(100dvh - 16px);
    padding: 16px 14px;
    overflow-y: auto;
  }
  .tour-pipeline { min-width: 330px; }
  .tour-actions { position: sticky; bottom: -16px; padding: 10px 0 2px; background: var(--surface-1); }

  .auth-page .login-wrap {
    min-height: 100svh;
    align-items: center;
    padding: max(18px, env(safe-area-inset-top)) 14px max(18px, env(safe-area-inset-bottom));
  }
  .auth-page .login-card {
    width: 100%;
    max-width: 390px !important;
    padding: 25px 20px 22px !important;
    border-radius: 18px !important;
  }
  .auth-page .login-card::before { margin-bottom: 14px; font-size: 22px; }
  .auth-page .login-card .subtitle { margin-bottom: 18px !important; }
  .auth-page .login-field input, .auth-page #btn-submit, .auth-page #btn-forgot-submit { min-height: 46px; }
}

@media (max-width: 380px) {
  .app { padding-inline: 6px; }
  .tabs-bar-row { margin-inline: -6px; padding-inline: 6px; }
  [data-tab-panel="performance"] .kpi-row-double,
  [data-tab-panel="performance"] .metrics-row { gap: 4px; }
  [data-tab-panel="performance"] .kpi-row-double > .kpi-tile,
  [data-tab-panel="performance"] .metric-tile { padding-inline: 3px; }
  .header-actions > button { padding-inline: 8px; }
  .auth-page .login-card { padding-inline: 17px !important; }
}

/* ========================================================================== */
/* COVEX VISUAL PERFORMANCE — premium liviano, sin alterar funcionalidad      */
/* ========================================================================== */
body { background-attachment: scroll; }

/* El aspecto translúcido se conserva con color-mix; se elimina el blur de toda la
   pantalla, que obligaba al navegador a recomponer cada píxel durante scroll y carga. */
header.topbar, .tabs-bar-row, .toast, .auth-page .login-card {
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
header.topbar, .tabs-bar-row { background-color: var(--surface-1); }

/* Los SVG/canvas ya tienen contraste propio. Un drop-shadow aplicado al contenedor
   completo es especialmente caro porque se recalcula en cada actualización del gráfico. */
#chart-container, .pnl-by-pair, .steps-distribution, .closest-execute,
.portfolio-pie, .portfolio-pie-donut, .portfolio-pie-donut svg {
  filter: none;
}

/* Mantiene profundidad y luz permanente con solo dos capas de sombra. */
section.panel, .modal, .tour-card, .dca-card-tour-window {
  box-shadow: 0 12px 30px rgba(0,0,0,.22), 0 0 14px var(--premium-glow-soft);
}
.kpi-tile, .metric-tile, .chart-panel, .dca-card, .altfins-card,
.billing-detail, .billing-charges-wrap, .audit-launch-panel,
.dca-modal-exit-summary, .gemini-settings-status, .settings-group,
.notification-card, .rate-tier-card, .admin-kpi-card {
  box-shadow: 0 7px 18px rgba(0,0,0,.16), 0 0 10px var(--premium-glow-soft);
}

/* Dispositivos táctiles no usan hover: se evita preparar animaciones y repintados que
   nunca aportan una interacción visible. */
@media (hover: none), (pointer: coarse) {
  .tab-btn, .tour-launch-btn, .dashboard-refresh-btn, .admin-mode-btn,
  .kpi-tile, .metric-tile, .chart-panel, .dca-card, .altfins-card,
  button:not(.tour-pipeline-step):not(.password-toggle) {
    transition: color .14s ease, background-color .14s ease, border-color .14s ease;
  }
  .kpi-tile:hover, .metric-tile:hover, .chart-panel:hover,
  .dca-card:hover, .altfins-card:hover,
  button:not(:disabled):not(.tour-pipeline-step):not(.password-toggle):hover {
    transform: none;
  }
}

/* Los segmentos de la ruta DCA deben permanecer superpuestos dentro de la pista.
   La capa premium compartía estos selectores con barras normales y les asignaba
   position:relative, desplazándolos fuera de la barra aunque el ancho calculado siguiera
   siendo correcto. Se restaura solo el posicionamiento visual original. */
.progress-bar .fill-single,
.progress-bar .fill-left,
.progress-bar .fill-yellow,
.progress-bar .fill-right {
  position: absolute;
}

@media (max-width: 600px) {
  body::before { display: none; }
  header.topbar, .tabs-bar-row, section.panel,
  .kpi-tile, .metric-tile, .chart-panel, .dca-card, .altfins-card {
    box-shadow: 0 6px 16px rgba(0,0,0,.17), 0 0 8px var(--premium-glow-soft);
  }
  .modal-overlay { -webkit-backdrop-filter: none; backdrop-filter: none; }
  .modal { box-shadow: 0 -10px 32px rgba(0,0,0,.34), 0 0 10px var(--premium-glow-soft); }
  .auth-page .login-wrap::before, .auth-page .login-wrap::after {
    filter: none;
    opacity: .72;
  }
  .auth-page .login-card {
    box-shadow: 0 18px 46px rgba(0,0,0,.34), 0 0 12px var(--premium-glow-soft) !important;
  }
}


/* ---------- Admin: Uso De Binance (semáforo de consultas, mejora N°5, 2026-09-24) ---------- */
/* "Limita: <cupo>" bajo el número del recuadro "Límite Máximo de Usuarios" (pedido explícito
   2026-10-01, reemplaza los 3 recuadros de capacidad que había arriba del panel). */
.bu-tile-sub { color: var(--muted); font-size: 11px; margin-top: 2px; line-height: 1.3; }
.bu-gauges {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 14px;
}
.bu-gauge { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.bu-gauge-title { display: flex; align-items: center; justify-content: center; text-align: center; gap: 6px; font-size: 13px; font-weight: 600; color: var(--text-primary); }
.bu-gauge-title i, .bu-legend i { width: 9px; height: 9px; border-radius: 50%; display: inline-block; flex: none; }
.bu-gauge-sub { text-align: center; color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }
.bu-gauge-sub.critical { color: var(--critical); }
.bu-chart { width: 100%; }
.bu-svg { width: 100%; height: auto; display: block; }
.bu-axis { font-size: 10.5px; fill: var(--muted); font-variant-numeric: tabular-nums; }
.bu-axis-critical { fill: var(--critical); }
.bu-legend { display: flex; flex-wrap: wrap; gap: 6px 14px; margin-top: 6px; font-size: 12px; color: var(--text-secondary); }
.bu-legend span { display: inline-flex; align-items: center; gap: 5px; }
.bu-counters { margin-top: 10px; }
.bu-counters .kpi-tile .label { white-space: normal; overflow: visible; text-overflow: clip; }
/* Los 4 recuadros de consultas viven DENTRO del panel "Última Hora" (pedido explícito
   2026-09-28: antes eran una fila aparte, fija a 24 H) -- mismo look que .kpi-tile, pero en
   su propia grilla de 4 columnas en vez de las 7 de .kpi-row, porque el panel es más angosto
   que el ancho completo de la página. */
.bu-hour-counters {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 10px;
  margin-top: 14px;
}
.bu-hour-counters .kpi-tile { text-align: center; }
.bu-hour-counters .kpi-tile .label { white-space: normal; overflow: visible; text-overflow: clip; }
.bu-thresholds { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 10px; font-size: 12px; color: var(--muted); }
.bu-threshold-chip { border: 1px solid var(--border); border-radius: 999px; padding: 2px 9px; color: var(--text-secondary); }
.bu-threshold-chip b { color: var(--text-primary); font-weight: 600; }
@media (max-width: 760px) {
  #binance-usage-panel .charts-row { flex-direction: column; }
}

/* Monitoreo De Clientes: columna que todavía espera el detalle de Binance (carga progresiva, mejora N°6) */
.admin-loading { color: var(--muted); letter-spacing: 1px; animation: admin-loading-pulse 1.2s ease-in-out infinite; }
@keyframes admin-loading-pulse { 50% { opacity: 0.35; } }
@media (prefers-reduced-motion: reduce) { .admin-loading { animation: none; } }
