/* ═══════════════════════════════════════════════════════════════════════
   FLUXA — DESIGN SYSTEM
   Un único sitio donde vive la apariencia. Ninguna pantalla define colores,
   espaciados ni tipografías por su cuenta: todas consumen estos tokens.
   ═══════════════════════════════════════════════════════════════════════ */

:root {
  /* ── Superficies ─────────────────────────────────────────────────── */
  --bg:            #07090d;
  --surface:       #0e1117;
  --surface-2:     #141821;
  --surface-3:     #1a1f2a;
  --border:        #1e2430;
  --border-strong: #2a3242;

  /* ── Texto ───────────────────────────────────────────────────────── */
  --text:          #e8ebf0;
  --text-2:        #9aa4b5;
  --text-3:        #5f6a7d;

  /* ── Semánticos ──────────────────────────────────────────────────── */
  --accent:        #5b8cff;
  /* Segundo acento, para degradados. Un solo sitio, como todo lo demás. */
  --accent-2:      #8b6cff;
  --accent-soft:   #5b8cff1f;
  --success:       #2ecc8f;
  --success-soft:  #2ecc8f1c;
  --warning:       #e8a33d;
  --warning-soft:  #e8a33d1c;
  --danger:        #f2545b;
  --danger-soft:   #f2545b1c;

  /* BUY y SELL no se distinguen solo por color: llevan además forma,
     posición y etiqueta. Ver §32 de accesibilidad. */
  --buy:           var(--success);
  --sell:          var(--danger);

  /* ── Espaciado ───────────────────────────────────────────────────── */
  --s1: 4px;  --s2: 8px;  --s3: 12px; --s4: 16px;
  --s5: 24px; --s6: 32px; --s7: 48px; --s8: 64px;

  /* ── Radios ──────────────────────────────────────────────────────── */
  --r1: 4px; --r2: 8px; --r3: 12px; --r4: 16px; --r-full: 999px;

  /* ── Tipografía ──────────────────────────────────────────────────── */
  --font: -apple-system, BlinkMacSystemFont, "Inter", "Segoe UI", system-ui, sans-serif;
  /* Los números van SIEMPRE en tabular: sin esto, una columna de precios
     baila al cambiar de dígito y deja de poder leerse en vertical. */
  --mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace;
  /* Las CIFRAS no van en la monoespaciada. Una fuente de código trae cero
     barrado, uno con serifas y anchos de máquina de escribir: en una pantalla
     de precios eso parece un volcado de terminal, no un producto. Se usa la
     misma tipografía que el resto con sus NUMERALES TABULARES, que alinean
     las columnas igual de bien y se leen mucho mejor. La monoespaciada se
     reserva para lo que de verdad es código: hashes, direcciones e ids. */
  --num: -apple-system, BlinkMacSystemFont, "Inter", "SF Pro Display", "Segoe UI", system-ui, sans-serif;
  --t-xs: 12px; --t-sm: 13px; --t-md: 15px; --t-lg: 17px;
  --t-xl: 21px; --t-2xl: 29px; --t-3xl: 40px;

  /* ── Elevación ───────────────────────────────────────────────────── */
  --shadow-1: 0 1px 2px #0006;
  --shadow-2: 0 4px 16px #0008;
  --shadow-3: 0 12px 40px #000a;
  --glow: 0 0 0 1px var(--accent-soft), 0 0 24px -6px var(--accent);

  /* ── Movimiento ──────────────────────────────────────────────────── */
  --t-fast: 120ms cubic-bezier(.2,.8,.2,1);
  --t-base: 200ms cubic-bezier(.2,.8,.2,1);

  /* ── Alturas de control ──────────────────────────────────────────── */
  --h-sm: 32px; --h-md: 40px; --h-lg: 46px; --h-xl: 54px;
}

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

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0; background: var(--bg); color: var(--text);
  font: var(--t-md)/1.55 var(--font);
  -webkit-font-smoothing: antialiased;
  font-variant-numeric: tabular-nums;
}
a { color: inherit; text-decoration: none; }
h1 { font-size: var(--t-2xl); font-weight: 600; letter-spacing: -.02em; margin: 0; }
h2 { font-size: var(--t-lg); font-weight: 600; letter-spacing: -.01em; margin: 0; }
h3 { font-size: var(--t-xs); font-weight: 600; text-transform: uppercase;
     letter-spacing: .09em; color: var(--text-3); margin: 0 0 var(--s3); }
.num { font-family: var(--num); font-variant-numeric: tabular-nums; }

/* Accesibilidad: el foco tiene que verse siempre. */
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--r1); }
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ═══ APP SHELL ═══════════════════════════════════════════════════════ */
/* 232 px y no 216: «FLUXABOTS» son nueve letras donde antes había cinco, y al
   tamaño que se pidió (--t-xl) no cabían. Se ensancha la columna en lugar de
   encoger la marca, porque el tamaño grande fue una petición explícita. */
.shell { display: grid; grid-template-columns: 232px 1fr; min-height: 100vh; }

.sidebar {
  background: var(--surface); border-right: 1px solid var(--border);
  display: flex; flex-direction: column; padding: var(--s4) 0;
  position: sticky; top: 0; height: 100vh; overflow-y: auto;
}
.brand { display: flex; align-items: center; gap: var(--s3); padding: 0 var(--s4) var(--s5); min-width: 0; }
.brand-mark { width: 36px; height: 36px; flex: 0 0 36px; }
/* El nombre tiene que CABER, y «FLUXABOTS» son nueve letras en una columna de
   216 px que antes solo llevaba cinco. Con el espaciado de antes (.16em) la
   última se salía y quedaba «FLUXABOT», que es peor que una marca pequeña:
   es una marca mal escrita. El espaciado se ajusta al nombre real y se deja
   que el hueco encoja antes de recortar nada. */
.brand-name {
  font-size: var(--t-xl); font-weight: 700; letter-spacing: .02em;
  min-width: 0; white-space: nowrap;
}

.nav-group { padding: 0 var(--s2); margin-bottom: var(--s4); }
.nav-group-title {
  font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: .12em;
  color: var(--text-3); padding: 0 var(--s3) var(--s2);
}
.nav-item {
  display: flex; align-items: center; gap: var(--s3);
  height: var(--h-md); padding: 0 var(--s3); border-radius: var(--r2);
  color: var(--text-2); font-size: var(--t-md); font-weight: 500;
  transition: background var(--t-fast), color var(--t-fast);
  position: relative;
}
.nav-item:hover { background: var(--surface-2); color: var(--text); }
.nav-item[aria-current="page"] { background: var(--surface-3); color: var(--text); }
.nav-item[aria-current="page"]::before {
  content: ''; position: absolute; left: calc(var(--s2) * -1 + 2px); top: 50%;
  transform: translateY(-50%); width: 3px; height: 16px;
  background: var(--accent); border-radius: 0 2px 2px 0;
}
.nav-item .ico { width: 16px; height: 16px; flex: 0 0 16px; opacity: .8; }
.nav-cta { margin-top: auto; padding: var(--s4); }

.nav-badge {
  margin-left: auto; min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: var(--r-full); background: var(--accent-soft); color: var(--accent);
  font-size: 10px; font-weight: 700; display: grid; place-items: center;
}

.main { display: flex; flex-direction: column; min-width: 0; }

/* La barra NO hace scroll. Antes tenía alto fijo y `overflow-x: auto`: al
   estrechar la ventana aparecían las dos barras de desplazamiento dentro de
   una tira de 56 px, que es exactamente lo que no debe pasar. Ahora crece de
   alto si hace falta, y lo accesorio se va retirando por tamaño. */
.topbar {
  min-height: 56px; flex: none; display: flex; align-items: center;
  gap: var(--s3) var(--s4); padding: var(--s2) var(--s5); flex-wrap: wrap;
  border-bottom: 1px solid var(--border); background: var(--surface);
  position: sticky; top: 0; z-index: 20;
}
.topbar-spacer { flex: 1 1 0; min-width: 0; }
.topbar-stat { display: flex; flex-direction: column; gap: 1px; line-height: 1.2; min-width: 0; }

.topbar-stat .k { font-size: 10px; text-transform: uppercase; letter-spacing: .08em; color: var(--text-3); }
.topbar-stat .v { font-size: var(--t-sm); font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.content { padding: var(--s5); max-width: 1680px; width: 100%; }
.page-head { display: flex; align-items: flex-start; gap: var(--s4); margin-bottom: var(--s5); flex-wrap: wrap; }
.page-head .sub { color: var(--text-2); font-size: var(--t-sm); margin-top: var(--s1); }

/* ═══ BADGES ══════════════════════════════════════════════════════════ */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  height: 21px; padding: 0 8px; border-radius: var(--r-full);
  font-size: var(--t-xs); font-weight: 600; letter-spacing: .03em;
  border: 1px solid transparent; white-space: nowrap;
}
.badge .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: 0 0 6px; }
/* Un distintivo no puede empujar la página: con el rótulo largo («A tu
   precio · Sin liquidez») sobresalía de la tarjeta de mercado. Se recorta,
   pero el texto entero sigue disponible en el `title`. */
.badge { max-width: 100%; overflow: hidden; text-overflow: ellipsis; }
.badge-neutral { background: var(--surface-3); color: var(--text-2); border-color: var(--border); }
.badge-accent  { background: var(--accent-soft);  color: var(--accent);  border-color: #5b8cff33; }
.badge-success { background: var(--success-soft); color: var(--success); border-color: #2ecc8f33; }
.badge-warning { background: var(--warning-soft); color: var(--warning); border-color: #e8a33d33; }
.badge-danger  { background: var(--danger-soft);  color: var(--danger);  border-color: #f2545b33; }
/* El distintivo de entorno es el más visible de la interfaz: no debe haber
   ninguna duda sobre si lo que se ve es real, de testnet o simulado. */
.badge-env { height: 24px; padding: 0 10px; font-weight: 700; letter-spacing: .09em; }

.pulse .dot { animation: pulse 2.4s ease-in-out infinite; }
@keyframes pulse { 0%,100% { opacity: 1 } 50% { opacity: .35 } }

/* ═══ TARJETAS ════════════════════════════════════════════════════════ */
.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r3); padding: var(--s4);
  transition: border-color var(--t-base), transform var(--t-base);
}
.card-hover:hover { border-color: var(--border-strong); }
.card-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--s3); }

.metric { display: flex; flex-direction: column; gap: var(--s1); }
.metric .label { font-size: var(--t-xs); text-transform: uppercase; letter-spacing: .08em; color: var(--text-3); }
.metric .value { font-family: var(--num); font-size: var(--t-xl); font-weight: 600; letter-spacing: -.01em; }
.metric .value.lg { font-size: var(--t-2xl); }
.metric .foot { font-size: var(--t-xs); color: var(--text-3); }

.grid-cards { display: grid; gap: var(--s3); grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.cols-2 { display: grid; gap: var(--s4); grid-template-columns: repeat(2, minmax(0, 1fr)); }
.cols-3 { display: grid; gap: var(--s4); grid-template-columns: repeat(3, minmax(0, 1fr)); }
.split-main { display: grid; gap: var(--s4); grid-template-columns: minmax(0, 1fr) 340px; }
.stack { display: flex; flex-direction: column; gap: var(--s4); min-width: 0; }
.stack > * { min-width: 0; }
.row { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }

.pos { color: var(--success); } .neg { color: var(--danger); } .muted { color: var(--text-3); }
.na { color: var(--text-3); font-family: var(--num); }

/* ═══ TABLAS ══════════════════════════════════════════════════════════ */
.table-wrap { overflow-x: auto; border-radius: var(--r3); border: 1px solid var(--border); background: var(--surface); }
table { width: 100%; border-collapse: collapse; font-size: var(--t-sm); }
thead th {
  text-align: left; font-size: 10px; font-weight: 600; text-transform: uppercase;
  letter-spacing: .09em; color: var(--text-3); padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--border); background: var(--surface-2);
  position: sticky; top: 0;
}
tbody td { padding: var(--s3) var(--s4); border-bottom: 1px solid var(--border); }
tbody tr:last-child td { border-bottom: none; }
tbody tr { transition: background var(--t-fast); }
tbody tr:hover { background: var(--surface-2); }
td.n, th.n { text-align: right; font-family: var(--num); }
th[aria-sort] { cursor: pointer; user-select: none; }
th[aria-sort]:hover { color: var(--text-2); }
th[aria-sort="ascending"]::after { content: ' ↑'; color: var(--accent); }
th[aria-sort="descending"]::after { content: ' ↓'; color: var(--accent); }

/* ═══ CONTROLES ═══════════════════════════════════════════════════════ */
label { display: block; font-size: var(--t-xs); text-transform: uppercase;
        letter-spacing: .07em; color: var(--text-3); margin-bottom: var(--s2); font-weight: 600; }
input, select, textarea {
  width: 100%; height: var(--h-lg); background: var(--surface-2);
  border: 1px solid var(--border); border-radius: var(--r2); color: var(--text);
  padding: 0 var(--s3); font-family: var(--num); font-size: var(--t-md);
  transition: border-color var(--t-fast), background var(--t-fast);
}
textarea { height: auto; padding: var(--s3); font-family: var(--font); resize: vertical; }
input:hover, select:hover, textarea:hover { border-color: var(--border-strong); }
input:focus, select:focus, textarea:focus { outline: none; border-color: var(--accent); background: var(--surface-3); }
.field { margin-bottom: var(--s4); }

/* Un enlace que hace de botón. `a.btn` se pinta igual que un `button`, pero
   sigue siendo un enlace: lleva a otro sitio y el navegador debe poder
   abrirlo en otra pestaña. Un `button` con un `onclick` que navega no lo
   permite y no se anuncia como enlace. */
button, a.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2);
  height: var(--h-lg); padding: 0 var(--s4);
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: var(--r2); color: var(--text);
  font-size: var(--t-md); font-weight: 600; font-family: var(--font); cursor: pointer;
  transition: background var(--t-fast), border-color var(--t-fast), transform var(--t-fast);
}
button:hover:not(:disabled), a.btn:hover { background: var(--surface-3); border-color: var(--border-strong); }
button:active:not(:disabled), a.btn:active { transform: translateY(1px); }
button:disabled { opacity: .4; cursor: not-allowed; }
button.primary, a.btn.primary { background: var(--accent); border-color: var(--accent); color: #04101f; }
button.primary:hover:not(:disabled) { background: #7aa3ff; border-color: #7aa3ff; }
button.ai { background: linear-gradient(135deg, var(--accent-2), var(--accent)); border-color: transparent; color: #fff; }
button.ai:hover:not(:disabled) { filter: brightness(1.12); }
button.ghost { background: transparent; }
button.sm { height: var(--h-sm); padding: 0 var(--s3); font-size: var(--t-sm); }
.actions { display: flex; gap: var(--s3); flex-wrap: wrap; }

.seg { display: inline-flex; background: var(--surface-2); border: 1px solid var(--border);
       border-radius: var(--r2); padding: 2px; gap: 2px; }
.seg button { height: var(--h-sm); border: none; background: transparent; font-weight: 500; }
.seg button[aria-pressed="true"] { background: var(--surface-3); color: var(--text); }

/* ═══ AVISOS ══════════════════════════════════════════════════════════ */
.note { display: flex; gap: var(--s3); padding: var(--s3) var(--s4);
        border-radius: var(--r2); font-size: var(--t-sm); border: 1px solid; }
.note-info    { background: var(--accent-soft);  border-color: #5b8cff2e; color: #c3d5ff; }
.note-warning { background: var(--warning-soft); border-color: #e8a33d2e; color: #f0d09a; }
.note-danger  { background: var(--danger-soft);  border-color: #f2545b2e; color: #f7b3b6; }
.note-success { background: var(--success-soft); border-color: #2ecc8f2e; color: #a9e8cd; }
.note .ico { width: 17px; height: 17px; flex: none; margin-top: 2px; }

/* ═══ ESTADOS ═════════════════════════════════════════════════════════ */
.empty { display: flex; flex-direction: column; align-items: center; gap: var(--s3);
         padding: var(--s7) var(--s5); text-align: center; color: var(--text-2); }
.empty > .ico { width: 56px; height: 56px; opacity: .3; }
.empty > .ico .ico { width: 100%; height: 100%; }
.empty h2 { color: var(--text); }
.empty p { margin: 0; font-size: var(--t-sm); max-width: 380px; }

.skel { background: linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 50%, var(--surface-2) 75%);
        background-size: 200% 100%; animation: shimmer 1.4s infinite; border-radius: var(--r1); }
@keyframes shimmer { to { background-position: -200% 0 } }
.skel-line { height: 12px; margin-bottom: var(--s2); }
.skel-card { height: 84px; border-radius: var(--r3); }
.skel-chart { height: 260px; border-radius: var(--r3); }

/* ═══ TOOLTIP ═════════════════════════════════════════════════════════ */
.tip {
  position: fixed; z-index: 100; pointer-events: none;
  background: var(--surface-3); border: 1px solid var(--border-strong);
  border-radius: var(--r2); padding: var(--s3); box-shadow: var(--shadow-3);
  font-size: var(--t-sm); min-width: 170px; opacity: 0;
  transition: opacity var(--t-fast); line-height: 1.5;
}
.tip[data-show] { opacity: 1; }
.tip .k { color: var(--text-3); font-size: var(--t-xs); }
.tip .r { display: flex; justify-content: space-between; gap: var(--s4); }
.tip .r .v { font-family: var(--num); }

/* ═══ GRID VISUALIZATION ══════════════════════════════════════════════ */
.gridviz { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r3); overflow: hidden; }
.gridviz svg { display: block; width: 100%; }
.gv-level { cursor: pointer; }
.gv-level rect.hit { fill: transparent; }
.gv-level:hover rect.hit { fill: #ffffff08; }
.gv-legend { display: flex; gap: var(--s4); padding: var(--s3) var(--s4);
             border-top: 1px solid var(--border); font-size: var(--t-xs); color: var(--text-2); flex-wrap: wrap; }
.gv-legend .item { display: flex; align-items: center; gap: 6px; }
.gv-legend .sw { width: 14px; height: 3px; border-radius: 2px; }
.gv-legend .sw.dash { background: none; border-top: 2px dashed currentColor; height: 0; }

/* ═══ ORDERBOOK ═══════════════════════════════════════════════════════ */
.ob { font-family: var(--num); font-size: var(--t-sm); }
.ob-row { display: grid; grid-template-columns: 1fr 1fr 72px; position: relative;
          padding: 3px var(--s3); align-items: center; }
.ob-row .depth { position: absolute; inset: 0 auto 0 0; opacity: .13; border-radius: 2px; }
.ob-row.ask .depth { background: var(--danger); right: 0; left: auto; }
.ob-row.bid .depth { background: var(--success); }
.ob-row .p { position: relative; }
.ob-row.ask .p { color: var(--danger); }
.ob-row.bid .p { color: var(--success); }
.ob-row.mine { box-shadow: inset 2px 0 0 var(--accent); }
.ob-spread { display: flex; justify-content: space-between; padding: var(--s3);
             border-block: 1px solid var(--border); background: var(--surface-2); }

/* ═══ ASISTENTE ═══════════════════════════════════════════════════════ */
.steps { display: flex; gap: var(--s2); margin-bottom: var(--s5); flex-wrap: wrap; }
.step { display: flex; align-items: center; gap: var(--s2); height: var(--h-sm);
        padding: 0 var(--s3); border-radius: var(--r-full);
        background: var(--surface-2); border: 1px solid var(--border);
        font-size: var(--t-xs); color: var(--text-3); transition: all var(--t-base); }
.step .n { width: 16px; height: 16px; border-radius: 50%; background: var(--surface-3);
           display: grid; place-items: center; font-size: 9px; font-weight: 700; }
.step.on { background: var(--accent-soft); border-color: #5b8cff44; color: var(--accent); }
.step.on .n { background: var(--accent); color: #04101f; }
.step.done { color: var(--success); border-color: #2ecc8f2e; }
.step.done .n { background: var(--success-soft); color: var(--success); }

/* ═══ TARJETA DE BOT ══════════════════════════════════════════════════ */
.bot-card { display: flex; flex-direction: column; gap: var(--s3); }
.bot-card .pair { font-size: var(--t-lg); font-weight: 600; }
.bot-card .kv { display: flex; justify-content: space-between; font-size: var(--t-sm); }
.bot-card .kv .k { color: var(--text-3); }
.bot-card .kv .v { font-family: var(--num); }
.bot-grid { display: grid; gap: var(--s4); grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); }

/* ═══ RESPONSIVE ══════════════════════════════════════════════════════ */
/* 1100 y no 1280: con el menú de 232 px, a 1280 quedan 1048 para el
   contenido, de sobra para 1fr + 340. Cortando a 1280 la columna de
   resultados caía DEBAJO del formulario en casi cualquier portátil, y pulsar
   «configurar con IA» parecía no hacer nada porque la respuesta salía fuera
   de la pantalla. Medido: a 1100 el formulario aún conserva ~500 px. */
@media (max-width: 1100px) {
  .split-main { grid-template-columns: minmax(0, 1fr); }
  .explica { grid-template-columns: minmax(0, 1fr); }
  .cols-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 900px) {
  .shell { grid-template-columns: 1fr; }
  /* El menú NO se desplaza en horizontal: un menú con opciones escondidas
     detrás de una barra de scroll no es un menú, es un escondite. Se reparte
     en las filas que hagan falta y se ven todas las opciones a la vez. */
  .sidebar { position: static; height: auto; overflow: visible;
             flex-direction: row; flex-wrap: wrap; row-gap: var(--s2);
             padding: var(--s2) var(--s3); align-items: center; gap: var(--s2); }
  .brand { padding: 0 var(--s3) 0 var(--s2); flex: none; }
  .nav-group { display: flex; flex-wrap: wrap; gap: var(--s1); margin: 0; padding: 0; min-width: 0; }
  .nav-group-title { display: none; }
  .nav-item { white-space: nowrap; height: var(--h-sm); padding: 0 var(--s3); font-size: var(--t-sm); }
  .nav-item .ico { width: 15px; height: 15px; flex: 0 0 15px; }
  .nav-item[aria-current="page"]::before { display: none; }
  /* El botón de «nuevo bot» del pie del menú ya está en el panel: en
     horizontal solo repetiría una acción y robaría sitio a las opciones. */
  .nav-cta { display: none; }
  .cols-2, .cols-3 { grid-template-columns: minmax(0, 1fr); }
  .content { padding: var(--s4); }
  .topbar { padding: var(--s2) var(--s4); }
}
@media (max-width: 560px) {
  .grid-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  h1 { font-size: var(--t-xl); }
}

/* ═══════════════════════════════════════════════════════════════════════
   FASE 12 — PIEZAS PREMIUM
   ═══════════════════════════════════════════════════════════════════════ */

/* ── Fichas de token ────────────────────────────────────────────────── */
.tchip { display: inline-grid; place-items: center; flex: none; }
.tchip svg { width: 100%; height: 100%; display: block; }
.tpair { display: inline-flex; align-items: center; }
.tpair .tchip + .tchip { margin-left: -8px; }

/* ── Visualización del grid ─────────────────────────────────────────── */
.gviz {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r3); overflow: hidden;
}
.gviz-head {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s4);
  padding: var(--s4); border-bottom: 1px solid var(--border);
  background: linear-gradient(180deg, var(--surface-2), transparent);
  flex-wrap: wrap;
}
.gviz-title { display: flex; align-items: center; gap: var(--s3); }
.gviz-pair { font-size: var(--t-lg); font-weight: 650; letter-spacing: -.01em; }
.gviz-sub { font-size: var(--t-xs); color: var(--text-3); margin-top: 1px; }
.gviz-stats { display: flex; gap: var(--s5); }
.gviz-stat { display: flex; flex-direction: column; gap: 1px; text-align: right; }
.gviz-stat .k { font-size: 10px; text-transform: uppercase; letter-spacing: .09em; color: var(--text-3); }
.gviz-stat .v { font-family: var(--num); font-size: var(--t-lg); font-weight: 600; }
.gviz-svg { display: block; width: 100%; }

.gviz-lvl { cursor: pointer; transition: opacity var(--t-fast); }
.gviz-lvl rect.hit { fill: transparent; }
.gviz-lvl:hover rect.hit, .gviz-lvl:focus-visible rect.hit { fill: #ffffff09; }
.gviz-lvl:hover { opacity: 1 !important; }
.gviz-price { font-family: var(--num); font-size: 10.5px; fill: var(--text-2); }
.gviz-lvl.on .gviz-price { fill: var(--text); }
.gviz-side { font-family: var(--font); font-size: 10px; font-weight: 700; letter-spacing: .05em; }
.gviz-st { font-family: var(--font); font-size: 9.5px; fill: var(--text-3); }
/* La anotación que explica QUÉ hace la forma de ejecutar elegida. Solo sale
   en el asistente, y es la única diferencia visible entre las dos formas. */
.gviz-mectxt { font-family: var(--font); font-size: 10px; font-weight: 600; fill: var(--accent); }
.gviz-mectxt.dim { fill: var(--text-2); font-weight: 600; }

/* La explicación de cómo va a operar el bot. Dos columnas: qué es un grid y
   qué cambia con la forma de ejecutar elegida. Se apilan en pantalla
   estrecha, que es cuando leer en dos columnas cuesta más que ayuda. */
.explica { display: grid; gap: var(--s4); grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
           margin-bottom: var(--s4); }
.explica-b { padding: var(--s4); border-radius: var(--r2); background: var(--surface-2);
             border: 1px solid var(--border); }
.explica-b.acc { border-color: var(--accent); background: var(--accent-soft); }
.explica-b h4 { margin: 0 0 var(--s2); font-size: var(--t-sm); }
.explica-b p { margin: 0 0 var(--s2); font-size: var(--t-sm); color: var(--text-2); line-height: 1.55; }
.explica-b p:last-child { margin-bottom: 0; }

/* El reparto del capital deja de ser una tarjeta suelta sin contexto: vive
   dentro del bloque que explica cómo va a operar el bot, separado por una
   línea, porque es parte de la misma respuesta («qué hace y con qué dinero»). */
.capsplit-block { margin-top: var(--s4); padding-top: var(--s4); border-top: 1px solid var(--border); }

/* Botones en columna: en la barra lateral de 340 px, tres botones en fila se
   parten en tres anchos distintos y quedan desiguales. */
.actions.actions-col { flex-direction: column; align-items: stretch; }
.actions.actions-col > button { width: 100%; }

/* El estado inicial de la IA: la ilustración ocupa el hueco de la respuesta
   MIENTRAS no hay respuesta, y se va en cuanto la hay. */
.ia-inicial { text-align: center; }
.ia-inicial .art { margin-bottom: var(--s3); }
.ia-inicial h2 { margin: 0 0 var(--s2); font-size: var(--t-lg); }
.ia-inicial p { max-width: 62ch; margin: 0 auto var(--s4); font-size: var(--t-sm); }
.ia-inicial ul { text-align: left; max-width: 62ch; margin: 0 auto; padding-left: var(--s5);
                 font-size: var(--t-sm); line-height: 1.7; }
.gviz-edge { font-family: var(--font); font-size: 9px; font-weight: 600;
             letter-spacing: .12em; fill: var(--text-3); }
.gviz-nowtxt { font-family: var(--num); font-size: 11px; font-weight: 700; fill: #04101f; }
.gviz-fill { cursor: pointer; }
.gviz-fill:hover circle:first-child { fill-opacity: .3; }

.gviz-legend {
  display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap;
  padding: var(--s3) var(--s4); border-top: 1px solid var(--border);
  font-size: var(--t-xs); color: var(--text-2);
}
.gviz-legend .li { display: flex; align-items: center; gap: 6px; }
.gviz-legend .li.dim { color: var(--text-3); }
.gviz-legend .sy { width: 10px; height: 10px; flex: none; }
.gviz-legend .sy.buy { clip-path: polygon(50% 0, 100% 100%, 0 100%); background: var(--buy); }
.gviz-legend .sy.sell { clip-path: polygon(50% 100%, 100% 0, 0 0); background: var(--sell); }
.gviz-legend .sy.fill { border-radius: 50%; background: var(--accent); }
.gviz-legend .sy.idle { border-radius: 50%; border: 1.5px dashed var(--text-3); }

.gviz-empty { display: flex; flex-direction: column; align-items: center; justify-content: center;
              gap: var(--s3); padding: var(--s7) var(--s4); text-align: center; }
.gviz-blank { width: 140px; opacity: .5; }
.gviz-blank-txt { color: var(--text-2); font-size: var(--t-sm); }
.gviz-blank-txt span { color: var(--text-3); }

/* ── Reparto del capital ────────────────────────────────────────────── */
.capsplit { display: flex; flex-direction: column; gap: var(--s3); }
.capsplit-bar { display: flex; height: 8px; border-radius: var(--r-full); overflow: hidden; background: var(--surface-3); }
.capsplit-bar .seg.used { background: linear-gradient(90deg, var(--accent-2), var(--accent)); }
.capsplit-bar .seg.free { background: var(--surface-3); }
.capsplit-rows { display: flex; gap: var(--s4); flex-wrap: wrap; font-size: var(--t-sm); }
.capsplit-rows > div { display: flex; align-items: center; gap: 6px; }
.capsplit-rows b { font-family: var(--num); font-weight: 600; margin-left: 4px; }
.capsplit-rows .dot { width: 8px; height: 8px; border-radius: 50%; }
.capsplit-rows .dot.used { background: var(--accent); }
.capsplit-rows .dot.free { background: var(--surface-3); border: 1px solid var(--border-strong); }

/* ── Hero del dashboard ─────────────────────────────────────────────── */
.hero {
  position: relative; overflow: hidden;
  background: linear-gradient(135deg, #10131c 0%, var(--surface) 60%);
  border: 1px solid var(--border); border-radius: var(--r4);
  padding: var(--s6) var(--s5); margin-bottom: var(--s5);
}
.hero::before {
  content: ''; position: absolute; inset: -40% -10% auto auto; width: 520px; height: 380px;
  background: radial-gradient(circle at 70% 30%, #6d5cff22, transparent 62%);
  pointer-events: none;
}
.hero-greet { font-size: var(--t-sm); color: var(--text-3); }
.hero-title { font-size: var(--t-2xl); font-weight: 650; letter-spacing: -.025em; margin: var(--s1) 0 var(--s4); }
.hero-figures { display: flex; align-items: baseline; gap: var(--s4); flex-wrap: wrap; }
.hero-main { font-family: var(--num); font-size: 40px; font-weight: 650; letter-spacing: -.03em; }
.hero-delta { font-family: var(--num); font-size: var(--t-lg); font-weight: 600; }
.hero-actions { display: flex; gap: var(--s3); margin-top: var(--s5); flex-wrap: wrap; }

/* ── Tarjeta de bot premium ─────────────────────────────────────────── */
.botcard {
  display: flex; flex-direction: column; gap: var(--s3);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r3); padding: var(--s4); position: relative; overflow: hidden;
  transition: border-color var(--t-base), transform var(--t-base);
}
.botcard::after {
  content: ''; position: absolute; inset: 0 0 auto 0; height: 2px;
  background: linear-gradient(90deg, transparent, var(--accent), transparent); opacity: 0;
  transition: opacity var(--t-base);
}
.botcard:hover { border-color: var(--border-strong); transform: translateY(-1px); }
.botcard:hover::after { opacity: .6; }
.botcard-top { display: flex; align-items: center; gap: var(--s3); }
.botcard-pair { font-size: var(--t-lg); font-weight: 650; letter-spacing: -.01em; }
.botcard-meta { display: flex; gap: var(--s2); flex-wrap: wrap; }
.botcard-pnl { display: flex; align-items: baseline; gap: var(--s3); }
.botcard-pnl .big { font-family: var(--num); font-size: var(--t-2xl); font-weight: 650; letter-spacing: -.02em; }
.botcard-range { display: flex; flex-direction: column; gap: 5px; }
.botcard-range .track { height: 4px; border-radius: 2px; background: var(--surface-3); position: relative; }
.botcard-range .fillbar { position: absolute; inset: 0; border-radius: 2px;
                          background: linear-gradient(90deg, var(--buy), var(--sell)); opacity: .5; }
.botcard-range .now { position: absolute; top: -3px; width: 2px; height: 10px;
                      background: var(--accent); border-radius: 1px; }
.botcard-range .ends { display: flex; justify-content: space-between;
                       font-family: var(--num); font-size: var(--t-xs); color: var(--text-3); }

/* ── Tarjeta de mercado ─────────────────────────────────────────────── */
.mktcard {
  display: flex; flex-direction: column; gap: var(--s3);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r3); padding: var(--s4);
  transition: border-color var(--t-base), transform var(--t-base);
}
.mktcard:hover { border-color: var(--border-strong); transform: translateY(-1px); }
.mktcard-top { display: flex; align-items: center; gap: var(--s3); }
.mktcard-name { font-weight: 650; font-size: var(--t-md); }
.mktcard-price { font-family: var(--num); font-size: var(--t-xl); font-weight: 600; }
.mktcard-venues { display: flex; gap: 6px; flex-wrap: wrap; }
.mkt-section { margin-bottom: var(--s6); }
.mkt-section-head { display: flex; align-items: baseline; gap: var(--s3); margin-bottom: var(--s3); }
.mkt-section-head .why { font-size: var(--t-xs); color: var(--text-3); }
.mkt-grid { display: grid; gap: var(--s3); grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); }

/* ── Planes ─────────────────────────────────────────────────────────── */
.plan-card { position: relative; }
.plan-card.on { border-color: var(--accent); box-shadow: var(--glow); }
.plan-price { font-family: var(--num); font-size: var(--t-3xl); font-weight: 650; letter-spacing: -.03em; }
.plan-list { display: flex; flex-direction: column; gap: var(--s2); margin-top: var(--s3); }
.plan-list li { display: flex; gap: var(--s2); align-items: flex-start; font-size: var(--t-sm); list-style: none; }
.plan-list .ico { width: 16px; height: 16px; color: var(--success); flex: none; margin-top: 2px; }
.usebar { height: 6px; border-radius: 3px; background: var(--surface-3); overflow: hidden; }
.usebar > span { display: block; height: 100%; border-radius: 3px;
                 background: linear-gradient(90deg, var(--accent), var(--accent-2)); transition: width var(--t-base); }
.usebar.full > span { background: linear-gradient(90deg, var(--warning), var(--danger)); }
.use-row { display: flex; flex-direction: column; gap: 5px; margin-bottom: var(--s3); }
.use-row .lbl { display: flex; justify-content: space-between; font-size: var(--t-sm); }
.use-row .lbl .n { font-family: var(--num); color: var(--text-2); }

/* ── Desglose de comisiones ─────────────────────────────────────────── */
.feerow { display: flex; justify-content: space-between; padding: var(--s2) 0;
          border-bottom: 1px solid var(--border); font-size: var(--t-sm); }
.feerow:last-child { border-bottom: none; font-weight: 600; }
.feerow .v { font-family: var(--num); }
.feerow.fluxa { color: var(--accent); }

/* ── Onboarding ─────────────────────────────────────────────────────── */
.onboard { display: grid; grid-template-columns: 1fr 380px; gap: var(--s6); align-items: center;
           padding: var(--s6); background: linear-gradient(135deg, #10131c, var(--surface));
           border: 1px solid var(--border); border-radius: var(--r4); }
.onboard h2 { font-size: var(--t-2xl); letter-spacing: -.02em; margin-bottom: var(--s3); }
.onboard p { color: var(--text-2); margin: 0 0 var(--s5); max-width: 46ch; }
.onboard-art { opacity: .9; }
@media (max-width: 900px) { .onboard { grid-template-columns: 1fr; } .onboard-art { display: none; } }

/* ── Pasos del asistente, versión premium ───────────────────────────── */
/* Fija mientras se recorre el asistente: es la referencia de por dónde vas,
   y de nada sirve si se queda arriba en cuanto empiezas a leer.
   `--topbar-h` la mide la propia barra superior al pintarse: es sticky y
   ENVUELVE, así que su altura cambia con el ancho y no se puede fijar aquí. */
.wsteps {
  display: flex; gap: var(--s2); margin-bottom: var(--s5); flex-wrap: wrap;
  position: sticky; top: calc(var(--topbar-h, 56px) - 1px); z-index: 15;
  background: var(--bg); padding: var(--s3) 0;
  border-bottom: 1px solid var(--border);
}
.wstep { display: flex; align-items: center; gap: var(--s2); padding: var(--s2) var(--s3);
         border-radius: var(--r2); background: var(--surface); border: 1px solid var(--border);
         font-size: var(--t-xs); color: var(--text-3); transition: all var(--t-base); }
.wstep .ic { width: 22px; height: 22px; border-radius: var(--r1); background: var(--surface-3);
             display: grid; place-items: center; color: var(--text-3); flex: none; }
.wstep.on { border-color: var(--accent); color: var(--text); background: var(--accent-soft); }
.wstep.on .ic { background: var(--accent); color: #04101f; }
.wstep.done { color: var(--success); border-color: #2ecc8f33; }
.wstep.done .ic { background: var(--success-soft); color: var(--success); }

.trust { display: flex; gap: var(--s4); flex-wrap: wrap; }
.trust-item { display: flex; align-items: center; gap: var(--s2); font-size: var(--t-sm); color: var(--text-2); }
.trust-item .ico { width: 17px; height: 17px; flex: none; color: var(--success); }


/* ═══ PASADA PREMIUM ══════════════════════════════════════════════════
   Botones con icono, métricas enlazables, plan en la barra superior,
   selector de idioma e ilustraciones. Todo con los tokens ya definidos:
   ni una imagen remota, ni una fuente externa. */

/* ── Botones ─────────────────────────────────────────────────────────
   El icono va dentro del botón, así que necesita alineación propia y un
   tamaño ligado a la altura del control (si no, un icono de 16 px dentro
   de un botón de 54 px parece un error de maquetación). */
/* Un SVG con `viewBox` y sin medidas se estira hasta llenar su hueco. Sin
   esta regla, el icono de una fila de dos líneas salía a 85 px, y el de la
   lista del plan a 819. El tamaño por defecto va aquí; quien necesite otro
   lo pisa después. */
.ico { width: 17px; height: 17px; flex: none; }

button { gap: var(--s2); letter-spacing: -.01em; }
button .ico { width: 17px; height: 17px; flex: none; }
button.lg { height: var(--h-xl); padding: 0 var(--s5); font-size: var(--t-lg); border-radius: var(--r3); }
button.lg .ico { width: 19px; height: 19px; }
button.sm .ico { width: 15px; height: 15px; }
button.icon-only { width: var(--h-lg); padding: 0; }
button.primary { box-shadow: 0 1px 0 #fff2 inset, 0 6px 18px -10px var(--accent); }
button.primary:hover:not(:disabled) { box-shadow: 0 1px 0 #fff3 inset, 0 10px 26px -10px var(--accent); }
button.ai .ico { width: 18px; height: 18px; }

/* ── Métrica con icono y enlace ──────────────────────────────────── */
.metric .label { display: flex; align-items: center; gap: var(--s2); }
.metric-ico { display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: var(--r2);
  background: var(--surface-2); color: var(--accent); flex: none; }
.metric-ico .ico { width: 15px; height: 15px; }
.metric-link { position: relative; display: flex; flex-direction: column;
  transition: border-color var(--t-fast), transform var(--t-fast); }
.metric-link:hover { border-color: var(--accent); transform: translateY(-1px); }
.metric-link > .ico { position: absolute; top: var(--s4); right: var(--s4);
  width: 15px; height: 15px; color: var(--text-3); }

/* ── Plan contratado en la barra superior ────────────────────────── */
.topbar-plan { display: flex; align-items: center; gap: var(--s2);
  height: var(--h-md); padding: 0 var(--s3);
  border: 1px solid var(--border); border-radius: var(--r-full);
  background: var(--surface-2);
  transition: border-color var(--t-fast), background var(--t-fast); }
.topbar-plan:hover { border-color: var(--accent); background: var(--surface-3); }
.topbar-plan .ico { width: 16px; height: 16px; color: var(--accent); }

/* ── Selector de idioma ──────────────────────────────────────────── */
.lang-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: var(--s3); }
.lang-opt { display: flex; align-items: center; gap: var(--s3);
  padding: var(--s4); border: 1px solid var(--border); border-radius: var(--r3);
  background: var(--surface-2); cursor: pointer; text-align: left;
  height: auto; font-size: var(--t-md);
  transition: border-color var(--t-fast), background var(--t-fast); }
.lang-opt:hover { border-color: var(--border-strong); }
.lang-opt[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-soft); }
.lang-flag { display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; flex: none; border-radius: var(--r2);
  background: var(--surface-3); font-family: var(--mono); font-weight: 700;
  font-size: var(--t-sm); letter-spacing: .06em; color: var(--text-2); }
.lang-opt[aria-pressed="true"] .lang-flag { background: var(--accent); color: #04101f; }
.lang-txt { display: flex; flex-direction: column; gap: 1px; line-height: 1.25; }
.lang-txt .n { font-weight: 650; font-size: var(--t-md); }
.lang-txt .s { font-size: var(--t-xs); color: var(--text-3); }
.lang-opt .ico { margin-left: auto; width: 17px; height: 17px; color: var(--accent); }

/* ── Ilustraciones ───────────────────────────────────────────────────
   SVG en línea sobre un lienzo con degradado. Sin peticiones de red: una
   ilustración que no carga es peor que no tener ilustración. */
.art { position: relative; overflow: hidden; border-radius: var(--r4);
  background: radial-gradient(120% 140% at 15% 0%, var(--accent-soft) 0%, transparent 55%),
              linear-gradient(160deg, var(--surface-2), var(--surface));
  border: 1px solid var(--border); }
/* Una ilustración estirada a 1.100 px dentro de una tarjeta ancha deja de
   parecer una ilustración y parece un error. Se acota y se centra: el
   degradado del lienzo se encarga del resto del ancho. */
.art svg { display: block; width: 100%; max-width: 480px; height: auto; margin-inline: auto; }
.art-band .art svg { max-width: 100%; }
.art-band { display: grid; grid-template-columns: 1.15fr .85fr; gap: var(--s6);
  align-items: center; padding: var(--s6); }
@media (max-width: 900px) {
  /* Apilada ya no hay dos columnas que llenar: la ilustración vuelve a su
     tope, o se estira a todo el ancho de la tarjeta. */
  .art-band { grid-template-columns: minmax(0, 1fr); }
  .art-band .art svg { max-width: 480px; }
}
.feature-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--s4); }
.feature { display: flex; flex-direction: column; gap: var(--s2); padding: var(--s5);
  border: 1px solid var(--border); border-radius: var(--r3); background: var(--surface); }
.feature-ico { display: inline-flex; align-items: center; justify-content: center;
  width: 42px; height: 42px; border-radius: var(--r3);
  background: linear-gradient(140deg, var(--accent-soft), transparent);
  border: 1px solid var(--border); color: var(--accent); margin-bottom: var(--s2); }
.feature-ico .ico { width: 21px; height: 21px; }
.feature h3 { margin: 0; font-size: var(--t-md); }
.feature p { margin: 0; font-size: var(--t-sm); color: var(--text-3); line-height: 1.55; }

/* Un icono dentro de un encabezado: alineado con el texto y a su tamaño. */
h2 > .ico, h3 > .ico { width: 19px; height: 19px; vertical-align: -3px; }

/* ── Barra superior: qué se retira y en qué orden ─────────────────────
   Lo que NO se va nunca: el entorno, el plan y la parada de emergencia.
   Se retira primero lo informativo (gasto de IA, proveedor) y después el
   detalle de red y modo de ejecución, que ya están en Ajustes. */
@media (max-width: 1180px) { .topbar-opt-2 { display: none; } }
@media (max-width: 860px)  { .topbar-opt-1 { display: none; } }
@media (max-width: 480px) {
  .topbar { gap: var(--s2) var(--s3); padding: var(--s2) var(--s4); }
  .topbar-plan { padding: 0 var(--s2); }
}

/* ── Estado del bot y avisos ──────────────────────────────────────────
   Pausar o detener tiene que verse. Antes solo cambiaba un distintivo
   pequeño entre otros cuatro y, con el bot ya parado, no se notaba nada. */
.botstate { display: flex; flex-direction: column; align-items: flex-end; gap: var(--s3); }
.botstate-now { display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3) var(--s4); border-radius: var(--r3);
  border: 1px solid var(--border); background: var(--surface-2); }
.botstate-now .dot { width: 10px; height: 10px; border-radius: 50%; background: var(--text-3); flex: none; }
.botstate-now .txt { display: flex; flex-direction: column; gap: 1px; line-height: 1.2; }
.botstate-now .k { font-size: 10px; text-transform: uppercase; letter-spacing: .09em; color: var(--text-3); }
.botstate-now .v { font-size: var(--t-lg); font-weight: 650; }
.botstate-success { border-color: #2ecc8f55; background: var(--success-soft); }
.botstate-success .dot { background: var(--success); box-shadow: 0 0 0 4px #2ecc8f22; }
.botstate-accent  { border-color: #5b8cff55; background: var(--accent-soft); }
.botstate-accent .dot { background: var(--accent); box-shadow: 0 0 0 4px #5b8cff22; }
.botstate-warning { border-color: #e8a33d55; background: var(--warning-soft); }
.botstate-warning .dot { background: var(--warning); box-shadow: 0 0 0 4px #e8a33d22; }
.botstate-danger  { border-color: #f2545b55; background: var(--danger-soft); }
.botstate-danger .dot { background: var(--danger); box-shadow: 0 0 0 4px #f2545b22; }
.botstate-neutral .dot { background: var(--text-3); }

.toast { position: fixed; right: var(--s5); bottom: var(--s5); z-index: 60;
  display: flex; gap: var(--s3); align-items: flex-start; max-width: 380px;
  padding: var(--s4); border-radius: var(--r3); border: 1px solid var(--border-strong);
  background: var(--surface-2); box-shadow: var(--shadow-3);
  animation: toast-entra var(--t-base) both; }
.toast .ico { color: var(--success); margin-top: 1px; }
.toast .d { font-size: var(--t-sm); color: var(--text-3); margin-top: 2px; }
.toast-danger { border-color: #f2545b66; }
.toast-danger .ico { color: var(--danger); }
.toast-warning { border-color: #e8a33d66; }
.toast-warning .ico { color: var(--warning); }
.toast.irse { opacity: 0; transform: translateY(8px); transition: all var(--t-base); }
@keyframes toast-entra { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }
@media (max-width: 560px) { .toast { left: var(--s4); right: var(--s4); max-width: none; } }

/* ═══ ILUSTRACIONES ANIMADAS ═══════════════════════════════════════════
   El movimiento va en CSS, NO en SMIL (`<animate>`), a propósito: la regla
   de `prefers-reduced-motion` de arriba alcanza a las animaciones CSS y las
   apaga solas. Con SMIL habría que apagarlas a mano y se olvidaría.

   Todo es lento y de poco recorrido. Una ilustración que se agita distrae de
   lo que hay al lado; ésta solo tiene que estar viva. */

@keyframes art-orbita   { to   { transform: rotate(360deg); } }
@keyframes art-latido   { 0%, 100% { opacity: .55; transform: scale(1); }
                          50%      { opacity: 1;   transform: scale(1.06); } }
@keyframes art-respira  { 0%, 100% { opacity: .35; } 50% { opacity: .85; } }
@keyframes art-flotar   { 0%, 100% { transform: translateY(0); }
                          50%      { transform: translateY(-4px); } }
@keyframes art-recorre  { from { stroke-dashoffset: var(--largo); } to { stroke-dashoffset: 0; } }
@keyframes art-fluye    { to   { stroke-dashoffset: -16; } }
@keyframes art-barrido  { 0%   { transform: translateX(-14px); opacity: 0; }
                          20%, 80% { opacity: 1; }
                          100% { transform: translateX(14px); opacity: 0; } }
@keyframes art-crecer   { 0%, 100% { transform: scaleX(.82); } 50% { transform: scaleX(1); } }
@keyframes art-brillo   { 0%, 100% { opacity: .25; } 50% { opacity: .7; } }
@keyframes art-marcar   { 0%   { stroke-dashoffset: var(--largo); }
                          55%, 100% { stroke-dashoffset: 0; } }

/* El trazo del precio se dibuja solo y se queda; el resto respira. */
.art .a-linea   { animation: art-recorre 3.4s cubic-bezier(.4,0,.2,1) both; }
.art .a-orbita  { animation: art-orbita 26s linear infinite; transform-origin: center; }
.art .a-orbita-lenta { animation: art-orbita 44s linear infinite reverse; transform-origin: center; }
.art .a-latido  { animation: art-latido 3.6s ease-in-out infinite; transform-origin: center; }
.art .a-respira { animation: art-respira 4.4s ease-in-out infinite; }
.art .a-flota   { animation: art-flotar 5.2s ease-in-out infinite; }
.art .a-fluye   { stroke-dasharray: 5 5; animation: art-fluye 1.4s linear infinite; }
.art .a-barrido { animation: art-barrido 3.8s ease-in-out infinite; }
.art .a-crece   { animation: art-crecer 3.2s ease-in-out infinite; transform-box: fill-box; transform-origin: left center; }
.art .a-brillo  { animation: art-brillo 3s ease-in-out infinite; }
.art .a-marca   { animation: art-marcar 2.6s ease-out both; }

/* Los retardos escalonan la entrada: nada aparece a la vez. */
.art .d1 { animation-delay: .25s; } .art .d2 { animation-delay: .6s; }
.art .d3 { animation-delay: .95s; } .art .d4 { animation-delay: 1.3s; }
.art .d5 { animation-delay: 1.65s; } .art .d6 { animation-delay: 2s; }

/* Al pasar por encima, el conjunto se despierta un poco. */
.art:hover .a-latido { animation-duration: 2.4s; }

/* Meridianos del globo: se estrechan y se ensanchan desfasados, que es como
   se ve girar una esfera dibujada con elipses. */
@keyframes art-meridiano { 0%, 100% { transform: scaleX(1); } 50% { transform: scaleX(.12); } }
.art .a-meridiano { transform-box: fill-box; transform-origin: center;
  animation: art-meridiano 9s ease-in-out infinite; }
.art .a-meridiano.m1 { animation-delay: -3s; }
.art .a-meridiano.m2 { animation-delay: -6s; }

/* ── Cifras ────────────────────────────────────────────────────────────
   Un solo sitio para las prestaciones tipográficas de los números:
   · `tabular-nums`  → todas las cifras ocupan lo mismo, así una columna de
     precios no baila al cambiar de dígito. Es lo único que aportaba la
     monoespaciada, y aquí se consigue sin su aspecto de terminal.
   · `lining-nums`   → cifras a la altura de las mayúsculas, sin descendentes.
   · `"zero" 0`      → **fuera el cero barrado**. Es una convención de código
     para no confundir 0 con O; en un precio sobra y ensucia.
   · `"ss01" 0`      → fuera los estilísticos alternativos de algunas fuentes. */
.num, .na, td.n, th.n, input, .metric .value, .hero-main, .hero-delta,
.botcard-pnl .big, .mktcard-price, .plan-price, .feerow .v, .use-row .lbl .n,
.capsplit-rows b, .gviz-stat .v, .topbar-stat .v, .botstate-now .v, .ob,
.tip .r .v, text.n-svg {
  font-variant-numeric: tabular-nums lining-nums;
  font-feature-settings: "tnum" 1, "lnum" 1, "zero" 0, "ss01" 0;
}

/* Las cifras grandes piden un pelo menos de aire entre signos. */
.hero-main, .plan-price, .botcard-pnl .big, .metric .value.lg { letter-spacing: -.035em; }

/* Cifras dentro de un SVG (etiquetas de precio del grid y del gráfico). */
text.n-svg { font-family: var(--num); }

/* Lo que SÍ es código: hashes, direcciones e identificadores de orden. */
.cod { font-family: var(--mono); font-size: .94em; letter-spacing: -.01em; }

/* ── Menú de más acciones ─────────────────────────────────────────────
   Las acciones peligrosas no comparten sitio con las de todos los días: van
   detrás de un menú y marcadas, para que nadie elimine un bot buscando
   pausarlo. */
.menu { position: relative; }
.menu-pop { position: absolute; right: 0; top: calc(100% + 6px); z-index: 40;
  min-width: 220px; padding: var(--s2); border-radius: var(--r3);
  border: 1px solid var(--border-strong); background: var(--surface-2);
  box-shadow: var(--shadow-3); display: flex; flex-direction: column; gap: 2px; }
.menu-pop button { width: 100%; justify-content: flex-start; height: var(--h-md);
  background: transparent; border: 0; border-radius: var(--r2); font-weight: 500; }
.menu-pop button:hover:not(:disabled) { background: var(--surface-3); }
.menu-pop button.peligro { color: var(--danger); }
.menu-pop button.peligro:hover:not(:disabled) { background: var(--danger-soft); }
/* `display: flex` PISA al `display: none` que el navegador aplica por el
   atributo `hidden`. Sin esta línea el menú se ve siempre abierto, que es
   justo lo que pasaba: los dos menús de la lista aparecían a la vez. */
.menu-pop[hidden] { display: none; }

button.peligro { background: var(--danger-soft); border-color: #f2545b66; color: var(--danger); }
button.peligro:hover:not(:disabled) { background: #f2545b2e; border-color: var(--danger); }
h2.peligro, h3.peligro { color: var(--danger); }

/* ── Diálogo de confirmación ──────────────────────────────────────────
   Modal de verdad: tapa la pantalla y obliga a decidir. Una acción que puede
   costar dinero no se confirma con un `confirm()` del navegador. */
.dlg-fondo { position: fixed; inset: 0; z-index: 80; display: grid; place-items: center;
  padding: var(--s4); background: #000a; backdrop-filter: blur(3px);
  animation: dlg-entra var(--t-base) both; overflow: auto; }
@keyframes dlg-entra { from { opacity: 0; } to { opacity: 1; } }
.dlg { width: min(560px, 100%); max-height: 90vh; overflow: auto;
  padding: var(--s6); border-radius: var(--r4);
  border: 1px solid var(--border-strong); background: var(--surface);
  box-shadow: var(--shadow-3); display: flex; flex-direction: column; gap: var(--s4); }
.dlg h2 { display: flex; align-items: center; gap: var(--s2); margin: 0; }
.dlg h3 { margin: 0; }
.dlg p { margin: 0; color: var(--text-2); }
.dlg-lista { margin: 0; padding-left: var(--s5); color: var(--text-2);
  font-size: var(--t-sm); line-height: 1.7; }
.dlg-ops { display: flex; flex-direction: column; gap: var(--s2); }
.dlg-op { display: grid; grid-template-columns: auto 1fr; gap: 2px var(--s3);
  align-items: center; padding: var(--s3) var(--s4); cursor: pointer;
  border: 1px solid var(--border); border-radius: var(--r3); background: var(--surface-2); }
.dlg-op.on { border-color: var(--accent); background: var(--accent-soft); }
.dlg-op input { grid-row: span 2; width: 16px; height: 16px; accent-color: var(--accent); }
.dlg-op .n { font-weight: 650; text-transform: none; letter-spacing: normal;
  font-size: var(--t-md); color: var(--text); }
.dlg-op .s { font-size: var(--t-xs); color: var(--text-3); grid-column: 2;
  text-transform: none; letter-spacing: normal; }
.dlg-cifras { display: flex; flex-direction: column;
  padding: var(--s3) var(--s4); border-radius: var(--r3); background: var(--surface-2); }
.dlg input[aria-invalid="true"] { border-color: var(--danger); }

/* El menú de la tarjeta se superpone en la esquina: la tarjeta entera sigue
   siendo un enlace y el menú no vive dentro de él. */
.botcard-wrap { position: relative; }
.botcard-menu { position: absolute; top: var(--s3); right: var(--s3); z-index: 5; }
.botcard-menu > button { background: var(--surface-2); border-color: var(--border); opacity: .75; }
.botcard-wrap:hover .botcard-menu > button { opacity: 1; }

/* La procedencia del activo, cuando el símbolo se repite y SE SABE de dónde
   viene. Va pequeña y al lado del par: es una aclaración, no un título. */
.origen { display: inline-block; margin-left: var(--s2); padding: 1px 6px;
  border-radius: var(--r-full); background: var(--surface-3); border: 1px solid var(--border);
  font-size: 10px; font-weight: 600; letter-spacing: .04em; color: var(--text-3);
  text-transform: uppercase; vertical-align: 2px; }

/* En la cabecera de una tarjeta, el distintivo de estado no se encoge: lo que
   cede es el nombre del par. Un «Disponible» cortado por la mitad se lee como
   otra cosa. */
.mktcard-top .badge, .botcard-top .badge { flex: none; }
.mktcard-top > div, .botcard-top > div { min-width: 0; }
/* El nombre del par NO se parte ni se recorta: es el dato que distingue un
   mercado de otro, que es de lo que va toda esta fase. Si no cabe todo en una
   línea, lo que baja es el distintivo de estado. */
.mktcard-name, .botcard-pair { white-space: nowrap; }
.mktcard-top, .botcard-top { flex-wrap: wrap; row-gap: var(--s2); }

/* ── Cartera ──────────────────────────────────────────────────────────
   La píldora conectada reutiliza el estilo del plan: misma familia visual,
   ningún rediseño. */
/* ── Conectar cartera ─────────────────────────────────────────────────
   Es la acción que abre la puerta al dinero del usuario: tiene que destacar
   sin gritar. Un borde de acento a plena saturación parecía un anillo de
   foco y le ganaba la partida a la píldora del plan que tiene al lado; la
   elegancia aquí sale de la MATERIA —una veladura de acento, un filo de luz
   arriba y un halo bajo— y no del color plano.

   El icono va en una cápsula translúcida con el mismo lenguaje que
   `.metric-ico` y `.feature-ico`: la cabecera no estrena vocabulario. */
.topbar-wallet {
  position: relative; overflow: hidden; flex: none;
  height: var(--h-md); padding: 0 var(--s4) 0 6px; gap: var(--s3);
  border-radius: var(--r-full);
  border: 1px solid #5b8cff4d;
  background:
    linear-gradient(180deg, #5b8cff1a, #5b8cff08) padding-box,
    var(--surface-2) padding-box;
  color: var(--text);
  font-size: var(--t-sm); font-weight: 600; letter-spacing: -.005em;
  box-shadow: 0 1px 0 #ffffff14 inset, 0 8px 22px -18px var(--accent);
  transition: border-color var(--t-base), box-shadow var(--t-base),
              transform var(--t-fast), background var(--t-base);
}
.topbar-wallet:hover:not(:disabled) {
  transform: translateY(-1px);
  border-color: #5b8cff73;
  background:
    linear-gradient(180deg, #5b8cff2e, #5b8cff0f) padding-box,
    var(--surface-2) padding-box;
  box-shadow: 0 1px 0 #ffffff1f inset, 0 12px 26px -18px var(--accent);
}
.topbar-wallet:active:not(:disabled) { transform: translateY(0); }
.topbar-wallet:disabled { opacity: .55; }
.topbar-wallet .txt { position: relative; z-index: 1; }

.topbar-wallet .ico-caja {
  position: relative; z-index: 1;
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; flex: none; border-radius: var(--r2);
  background: linear-gradient(140deg, #8b6cff33, #5b8cff1f);
  border: 1px solid #5b8cff33;
  color: var(--accent);
  transition: background var(--t-base), border-color var(--t-base);
}
.topbar-wallet:hover:not(:disabled) .ico-caja {
  background: linear-gradient(140deg, #8b6cff4d, #5b8cff33);
  border-color: #5b8cff59;
}
.topbar-wallet .ico-caja .ico { width: 15px; height: 15px; }

/* Pasada de luz al pasar por encima. Lenta y de poca opacidad: tiene que
   notarse que el botón está vivo, no llamar la atención. */
.topbar-wallet .brillo {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(105deg, transparent 38%, #ffffff14 50%, transparent 62%);
  transform: translateX(-120%);
}
.topbar-wallet:hover:not(:disabled) .brillo { animation: wallet-brillo 1.2s ease-out; }
@keyframes wallet-brillo { to { transform: translateX(120%); } }

/* ── Cartera conectada ─────────────────────────────────────────────────
   Conectada ya no hace falta que llame: baja a la familia de la píldora del
   plan y solo conserva el punto vivo, que es la información nueva. */
.topbar-wallet-pill { padding-right: var(--s2); gap: var(--s3); }
.topbar-wallet-pill .vivo {
  width: 7px; height: 7px; flex: none; border-radius: 50%;
  background: var(--success); box-shadow: 0 0 0 3px #2ecc8f26;
  animation: wallet-latido 2.8s ease-in-out infinite;
}
@keyframes wallet-latido {
  0%, 100% { box-shadow: 0 0 0 3px #2ecc8f26; }
  50%      { box-shadow: 0 0 0 6px #2ecc8f14; }
}
.topbar-wallet-pill > .ico { width: 13px; height: 13px; color: var(--text-3); opacity: .7; }
.topbar-wallet-pill:hover > .ico { opacity: 1; }

.menu-pop-ancho { min-width: 320px; padding: var(--s3); gap: var(--s3); }
.wdet { display: flex; flex-direction: column; gap: var(--s2); }
.wdet .r { display: flex; justify-content: space-between; gap: var(--s3); font-size: var(--t-sm); }
.wdet .k { color: var(--text-3); flex: none; }
.wdet .v { overflow-wrap: anywhere; text-align: right; }

.saldos { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--s3); }
.saldo { padding: var(--s4); border: 1px solid var(--border); border-radius: var(--r3);
  background: var(--surface-2); display: flex; flex-direction: column; gap: var(--s2); }
.saldo .n { display: flex; align-items: center; gap: var(--s2); font-weight: 650; font-size: var(--t-md); }
.saldo .c { font-size: var(--t-xl); font-weight: 600; }
.tecn summary { cursor: pointer; font-size: var(--t-xs); list-style: none; }
.tecn summary::-webkit-details-marker { display: none; }
.tecn summary::after { content: ''; display: inline-block; margin-left: 6px;
  width: 0; height: 0; border: 4px solid transparent; border-top-color: currentColor;
  transform: translateY(2px); transition: transform var(--t-fast); }
.tecn[open] summary::after { transform: rotate(180deg) translateY(2px); }
.tecn .r { display: flex; justify-content: space-between; gap: var(--s3); font-size: var(--t-xs);
  padding: 2px 0; border-bottom: 1px solid var(--border); }
.tecn .k { color: var(--text-3); }
.tecn .v { overflow-wrap: anywhere; text-align: right; }

/* ── Elegir cómo conectar ─────────────────────────────────────────────
   Tres caminos en orden de preferencia. El que no se puede usar se enseña
   igual, apagado y con su motivo: esconder la cartera de escritorio porque
   no se puede detectar sería esconder justo la primera opción oficial. */
.wopts { display: flex; flex-direction: column; gap: var(--s2); }
.wopt { display: flex; align-items: center; gap: var(--s3); width: 100%;
  height: auto; padding: var(--s4); text-align: left; justify-content: flex-start;
  border-radius: var(--r3); background: var(--surface-2); border: 1px solid var(--border); }
.wopt:hover:not(:disabled) { border-color: var(--accent); background: var(--surface-3); }
.wopt:disabled { opacity: .55; }
.wopt-ico { display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; flex: none; border-radius: var(--r2);
  background: linear-gradient(140deg, #8b6cff26, #5b8cff14);
  border: 1px solid #5b8cff26; color: var(--accent); }
.wopt-ico .ico { width: 19px; height: 19px; }
.wopt-txt { display: flex; flex-direction: column; gap: 1px; line-height: 1.3; flex: 1; min-width: 0; }
.wopt-txt .n { font-weight: 650; font-size: var(--t-md); text-transform: none; letter-spacing: normal; }
.wopt-txt .s { font-size: var(--t-xs); color: var(--text-3); text-transform: none; letter-spacing: normal; }
.wopt .badge { flex: none; }

/* El código QR: fondo claro siempre, o los lectores no lo ven. */
.wqr { display: grid; place-items: center; padding: var(--s4);
  background: #fff; border-radius: var(--r3); }
.wqr img { display: block; width: 100%; max-width: 280px; height: auto; image-rendering: pixelated; }
