:root {
  color-scheme: dark;
  --page-plane: #0a0e17;
  --surface-1: #111827;
  --surface-2: #171f30;
  --text-primary: #ffffff;
  --text-secondary: #c3c2b7;
  --muted: #7c8598;
  --gridline: #242e42;
  --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 */
  --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;
  --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;
  --candle-up: #0ca30c;
  --candle-down: #d03b3b;
}

* { 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;
}

/* 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;
}

.icon-btn {
  width: 28px;
  height: 28px;
  padding: 0;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
}

.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); }
.tab-btn {
  position: relative;
  z-index: 1;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 7px 13px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 9px;
  color: var(--muted);
  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: 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: color-mix(in srgb, var(--series-1) 35%, var(--border)); }
.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; }
}
@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; }
}

.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); }

/* 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);
}

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-secondary);
  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(--muted);
  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;
}
.chart-header-title-group .chart-subtitle {
  min-width: 0;
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.chart-header-title-group .range-select {
  flex-shrink: 0;
}

.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; }

.hidden { display: none !important; }

.charts-row {
  display: flex;
  gap: 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-panel-wide { flex: 2.75; }
.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); }

.table-toolbar {
  display: flex;
  justify-content: flex-end;
  margin-bottom: 10px;
  font-size: 12px;
  color: var(--text-secondary);
}
.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;
}
/* #admin-users-table + .admin-rate-input (en vez de solo la clase) para ganarle en
   especificidad a "table.pairs input[type=number]" (más específica que una clase sola) —
   si no, ese ancho de 90px de las demás tablas se comía este más angosto. */
#admin-users-table .admin-rate-input {
  width: 60px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text-primary);
  padding: 3px 2px;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  text-align: center;
}
.admin-rate-input:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
#admin-users-table td.admin-col-narrow,
#admin-users-table th.admin-col-narrow {
  text-align: center;
  padding-left: 1px;
  padding-right: 1px;
}
/* Antes un punto verde/rojo al lado del primer recuadro (%Trans.) nada más, reflejando un
   estado agregado de los 3 campos juntos. Ahora cada recuadro tiene su propio borde: rojo
   si su valor difiere de la tarifa activa (ver data-active / syncAdminRateBorder en
   app.js), verde apenas lo devolvés al valor activo (momentáneo, se resetea si se
   reordena/refresca la tabla -- pedido explícito). */
/* #admin-users-table de nuevo acá (mismo motivo que arriba, ver comentario) -- sin el ID,
   estas 2 reglas perdían contra la de arriba (1 ID + 1 clase le gana a 2 clases sin ID, sin
   importar el orden en el archivo) y el borde nunca cambiaba de color -- bug real reportado. */
#admin-users-table .admin-rate-input.rate-changed { border-color: var(--critical); }
#admin-users-table .admin-rate-input.rate-reverted { border-color: var(--good); }

/* 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); }
/* 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); }
/* 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;
}

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;
}

.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-secondary);
  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 — pastillas de Corto/Mediano/Largo Plazo (mismo look que .pill) */
.trend-pill {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
}
.trend-pill.trend-strong-up { background: rgba(12, 163, 12, 0.22); color: var(--good); }
.trend-pill.trend-up { background: rgba(12, 163, 12, 0.12); color: var(--good); }
.trend-pill.trend-neutral { background: rgba(137, 135, 129, 0.15); color: var(--muted); }
.trend-pill.trend-down { background: rgba(208, 59, 59, 0.12); color: var(--critical); }
.trend-pill.trend-strong-down { background: rgba(208, 59, 59, 0.22); color: var(--critical); }

.altfins-name { color: var(--muted); font-size: 11px; margin-left: 4px; }
.altfins-updated { color: var(--muted); font-size: 12px; }

.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;
}
.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; }
/* 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);
}
.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;
}

.dca-trailing-gain {
  font-size: 10px;
  font-weight: 600;
}
/* 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-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; }
}

/* 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-secondary);
  margin-bottom: 14px;
  line-height: 1.5;
}
.reset-modal input[type="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;
}

/* Panel de Facturación (tarifas globales + detalle mensual de cobros) */
.billing-header-row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 16px;
}
.billing-month-selector {
  display: flex;
  gap: 10px;
  margin-left: auto;
}
/* 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;
  /* Alineado con .billing-charges-wrap de al lado (mismo alto, pedido explícito) pero SIN
     scroll (pedido explícito) -- medido: el contenido real (Estado Del Mes + 3 grupos de
     comisiones) necesita 427px, así que 423px (los -1,5cm originales) le quedaban 4px
     cortos y forzaban la barrita. 430px es el punto justo: entra todo sin scroll y las dos
     cajas quedan a la misma altura. */
  height: 430px;
  overflow-y: hidden;
  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-row-sub-first {
  border-bottom: none;
}
.billing-row span:first-child { color: var(--text-secondary); }
.billing-row span:last-child { font-variant-numeric: tabular-nums; font-weight: 600; }
.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: 430px;
  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;
  }
}
