/* ===========================================================================
   ATLADIX — SISTEMA DE DISEÑO

   La piel compartida por el panel de firma (/panel) y la app de trading (/app),
   y la que heredará la plataforma comercial cuando exista. Un solo fichero, sin
   build, sin framework: se sirve tal cual desde el binario en /assets/design.css.

   POR QUÉ ESTÁ TODO EN VARIABLES. El color de "en positivo" aparece en la
   cabecera, en la tabla de fills, en el badge de una cuenta activa y en la barra
   de riesgo. Si vive en cinco sitios, la primera vez que haya que ajustarlo por
   contraste quedarán tres verdes distintos en la misma pantalla. Aquí se cambia
   en :root y se mueve todo a la vez.

   LAS DOS TIPOGRAFÍAS NO SON UN CAPRICHO. La del sistema para la interfaz —se
   lee más rápido y no parece un terminal de los noventa— y monoespaciada con
   cifras tabulares para TODO número: precio, equity, ticks, cantidades. Una
   columna de dinero en proporcional baila de fila en fila y obliga a leerla
   cifra a cifra; en tabular, un cero de más se ve sin leer.

   EL COLOR SIGNIFICA SIEMPRE LO MISMO, en las dos interfaces:
     verde  = a favor  → comprar, activo, en positivo, lejos del suelo
     rojo   = en contra → vender, liquidada, en negativo, peligro
     ámbar  = ojo      → suspendida, override puesto a mano, se acerca el límite
     azul   = referencia, sin juicio de valor (live, acciones neutras)
   Nada decorativo usa esos cuatro. Si algo es verde en esta pantalla, es porque
   está a favor de quien mira.
   =========================================================================== */

/* ---------------------------------------------------------------------------
   1. FICHAS DE DISEÑO
   --------------------------------------------------------------------------- */
:root {
  /* --- superficies. Casi negro y tres escalones, no más: con cinco grises
         nadie sabe ya qué está por encima de qué. --- */
  --bg:        #07090c;   /* el fondo de todo */
  --surface:   #0e1218;   /* paneles y tarjetas */
  --surface-2: #151b23;   /* lo que se levanta sobre un panel: hover, cabeceras */
  --surface-3: #1c242e;   /* lo que se levanta sobre eso: botón, fila marcada */
  --surface-4: #232d39;   /* el hover de un botón: el último escalón */
  --inset:     #05070a;   /* lo hundido: inputs, canaletas, barras */

  --line:      #1a212a;   /* separador fino: entre filas de una tabla */
  --line-2:    #28313d;   /* borde visible: panel, input, botón */
  --line-3:    #3a4757;   /* borde con foco o énfasis */

  /* --- texto --- */
  --text:      #e7edf5;
  --text-2:    #9aa6b6;   /* etiquetas, unidades, lo secundario */
  --text-3:    #626e7e;   /* lo que casi no importa: placeholders, pistas */

  /* --- semántica. Ver la cabecera de este fichero: no hay más colores. --- */
  --green:      #34d399;
  --green-soft: rgba(52, 211, 153, .12);
  --green-line: rgba(52, 211, 153, .38);
  --red:        #ff4d5e;
  --red-soft:   rgba(255, 77, 94, .12);
  --red-line:   rgba(255, 77, 94, .40);
  --amber:      #f5b544;
  --amber-soft: rgba(245, 181, 68, .12);
  --amber-line: rgba(245, 181, 68, .38);
  --blue:       #4d8ee0;
  --blue-soft:  rgba(77, 142, 224, .12);
  --blue-line:  rgba(77, 142, 224, .40);
  --violet:     #a78bfa;
  --violet-soft: rgba(167, 139, 250, .12);
  --violet-line: rgba(167, 139, 250, .38);

  --accent:      var(--blue);
  --accent-soft: var(--blue-soft);
  --accent-line: var(--blue-line);
  /* El relleno de un botón de acento con el ratón encima: el mismo azul, más
     presente. Va como ficha y no escrito en la regla para que el día que el
     acento deje de ser azul no queden tres botones azules sueltos. */
  --accent-hover: rgba(77, 142, 224, .22);
  --red-hover:    rgba(255, 77, 94, .22);

  /* --- tipografía --- */
  --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto,
             "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
               "Liberation Mono", monospace;

  --fs-xs: 10.5px;
  --fs-sm: 11.5px;
  --fs:    13px;
  --fs-md: 14px;
  --fs-lg: 18px;
  --fs-xl: 26px;
  --fs-2xl: 34px;

  /* --- espacio, radio, sombra --- */
  --sp-1: 4px;  --sp-2: 8px;  --sp-3: 12px;
  --sp-4: 16px; --sp-5: 24px; --sp-6: 32px;

  --r-1: 4px; --r-2: 6px; --r-3: 10px; --r-full: 999px;

  --shadow-1: 0 1px 2px rgba(0,0,0,.4);
  --shadow-2: 0 8px 24px rgba(0,0,0,.45);
  --shadow-3: -24px 0 60px rgba(0,0,0,.55);

  /* Altura de la barra superior; la usan el sticky del contenido y el shell. */
  --topbar-h: 52px;
  --sidebar-w: 216px;

  /* --- el menú lateral ---
     La fila es alta porque es un blanco que se pulsa mil veces al día, y la
     pastilla activa lleva aire a los lados para leerse como un bloque y no como
     una fila de borde a borde. El padding de la etiqueta se mide desde el borde
     del sidebar: --nav-inset + el del propio item. */
  --nav-h: 44px;
  --nav-inset: var(--sp-3);
  --nav-ico: 20px;
  /* LA COLUMNA DE ALINEACIÓN del menú, medida desde el borde del sidebar: donde
     empiezan TODOS los iconos y TODOS los rótulos de grupo. Es una sola ficha
     porque es una sola columna — si el rótulo y el icono se calcularan por
     separado, un día dejarían de coincidir. */
  --nav-col: calc(var(--nav-inset) + var(--sp-3));

  /* Anchos de control. Un formulario con medidas sueltas escritas en el sitio
     donde se usan acaba con seis anchos distintos para el mismo tipo de dato:
     aquí hay tres, tienen nombre, y lo que mide "una hora" o "una cantidad" se
     cambia en un sitio. */
  --w-time: 84px;
  --w-qty: 96px;
  --w-narrow: 150px;

  /* --- texto SOBRE un fondo de color, y otros sueltos que antes estaban
         escritos a mano dentro de las reglas. Van aquí porque son justo lo que
         un tema claro tiene que poder cambiar: un texto pensado para leerse
         sobre azul oscuro es ilegible sobre azul pálido. --- */
  --on-accent: #cfe2fb;
  --on-red:    #ffd2d6;
  --on-amber:  #ffe4a8;
  --scrim:     rgba(2, 4, 6, .74);
  --meter-mark: rgba(255, 255, 255, .18);

  /* --- el color de una FILA por su gravedad, y el relleno de una barra de
         consumo. Son fichas y no `color-mix` escrito en la regla porque es
         justo lo que un tema tiene que poder recalibrar: un 7% de ámbar sobre
         casi negro se ve, y sobre blanco no existe. --- */
  --row-warn:   color-mix(in srgb, var(--amber) 7%, transparent);
  --row-danger: color-mix(in srgb, var(--red) 9%, transparent);
  --bar-ok:     color-mix(in srgb, var(--green) 55%, transparent);
  --bar-warn:   color-mix(in srgb, var(--amber) 60%, transparent);
  --bar-danger: color-mix(in srgb, var(--red) 60%, transparent);
  --latido:     color-mix(in srgb, var(--accent) 22%, transparent);
}

/* ---------------------------------------------------------------------------
   1b. EL TEMA CLARO
   ---------------------------------------------------------------------------

   Las MISMAS fichas con otros valores. Ni una regla de componente cambia: todo
   lo de abajo lee --surface, --text o --green sin saber en qué tema está, y por
   eso el tema entero cabe en este bloque.

   Se activa con un atributo en <html> y NO con prefers-color-scheme. Es
   deliberado: manda el interruptor de la cabecera y su elección se guarda. Una
   mesa que trabaja de noche con el sistema en claro no quiere que el panel le
   imponga el blanco, y al revés.

   POR QUÉ ESTÁ AQUÍ Y NO EN EL PANEL DE FIRMA: la hoja es la misma para los tres
   paneles, y una copia del tema en cada uno serían tres verdes distintos dentro
   de un mes. Quien no ponga el atributo se queda en oscuro, que es lo que hacen
   hoy /operator y /app. */
:root[data-theme="light"] {
  /* Las superficies se invierten de orden, no de escala: --bg sigue siendo «el
     fondo de todo» y --surface «lo que se levanta encima». En claro eso
     significa que la tarjeta es MÁS clara que el fondo, al revés que en oscuro,
     y por eso el blanco puro se reserva para las tarjetas. */
  --bg:        #f7f8fa;
  --surface:   #ffffff;
  --surface-2: #f2f4f7;
  --surface-3: #e9edf2;
  --surface-4: #dfe5ec;
  --inset:     #f4f6f9;

  --line:      #eceff3;
  --line-2:    #dfe4ea;
  --line-3:    #c3ccd6;

  --text:      #12161c;
  --text-2:    #5c6673;
  --text-3:    #8b95a3;

  /* Los colores de estado bajan de luminosidad: el verde que brilla sobre casi
     negro desaparece sobre blanco. Los _soft suben de opacidad por lo mismo —
     un 12% sobre blanco no se ve— y son los fondos pastel de los badges. */
  --green:      #067a52;
  --green-soft: #e3f7ee;
  --green-line: #a8e2ca;
  --red:        #c8283c;
  --red-soft:   #fdeaec;
  --red-line:   #f3bcc3;
  --amber:      #9a6408;
  --amber-soft: #fdf3e0;
  --amber-line: #eed6a6;
  --blue:       #1f66d0;
  --blue-soft:  #e8f0fd;
  --blue-line:  #bcd4f6;
  --violet:      #6d46d9;
  --violet-soft: #efe9fd;
  --violet-line: #cfc0f7;

  --accent-hover: #dbe8fb;
  --red-hover:    #fbdde1;

  /* Texto sobre color: en claro el color ES el texto, sobre su propio pastel. */
  --on-accent: #14498f;
  --on-red:    #97182a;
  --on-amber:  #6d4606;

  /* Sombras difusas y suaves en vez de negros duros: sobre blanco, una sombra
     opaca ensucia; lo que separa una tarjeta del fondo es el desenfoque. Y el
     radio crece — es la mitad del aire de un panel claro moderno. */
  --shadow-1: 0 1px 2px rgba(16, 24, 40, .05), 0 1px 3px rgba(16, 24, 40, .06);
  --shadow-2: 0 4px 12px rgba(16, 24, 40, .06), 0 12px 32px rgba(16, 24, 40, .08);
  --shadow-3: -24px 0 60px rgba(16, 24, 40, .12);
  --r-3: 14px;

  --scrim:      rgba(16, 24, 40, .32);
  --meter-mark: rgba(16, 24, 40, .22);

  /* Las filas usan el pastel de los badges, que ya está calibrado para leerse
     sobre blanco. Las barras van a color pleno: en claro no hay negro debajo
     que apagar, y una barra al 55% sobre blanco es una barra que no se ve. */
  --row-warn:   var(--amber-soft);
  --row-danger: var(--red-soft);
  --bar-ok:     var(--green);
  --bar-warn:   var(--amber);
  --bar-danger: var(--red);
  --latido:     var(--accent-soft);
}

/* ---------------------------------------------------------------------------
   1c. LO POCO QUE EL TEMA CLARO CAMBIA ADEMÁS DE LAS FICHAS
   ---------------------------------------------------------------------------

   Todo lo anterior son valores. Aquí hay tres reglas de verdad, y cada una está
   porque en claro la MISMA idea se expresa de otra manera, no porque el color no
   cuadre. */

/* La pastilla del menú activo. En oscuro se levanta con un gris (--surface-3):
   lo que marca «estás aquí» es el relieve. En claro no hay relieve que ganar —
   el fondo ya es blanco— así que lo marca el color, que es como lo hacen los
   paneles claros. */
:root[data-theme="light"] .nav-item.on,
:root[data-theme="light"] .nav-item.on:hover:not(:disabled) {
  background: var(--accent-soft); color: var(--accent);
}

/* La cabecera de una tabla. En oscuro es del color del panel y la separa una
   línea; en claro necesita su propio gris o la fila de títulos flota sobre el
   blanco sin pertenecer a nada. */
:root[data-theme="light"] th { background: var(--surface-2); }

/* Los paneles y tarjetas se separan del fondo con SOMBRA en vez de con borde:
   sobre gris muy claro, un borde de un gris parecido es una raya sucia, y lo
   que da la sensación de tarjeta es la elevación. El borde se queda en el
   escalón más tenue para que el recorte siga siendo nítido en pantallas malas. */
:root[data-theme="light"] .panel {
  border-color: var(--line); box-shadow: var(--shadow-1);
}

/* Las cifras de la cabecera pasan a ser TARJETAS. En oscuro son cuatro cifras
   sueltas sobre el fondo del panel y funcionan: el vacío entre ellas las separa.
   Sobre blanco ese mismo vacío no separa nada —todo es blanco— así que cada una
   necesita su caja.

   El acento es un gradiente pastel muy tenue en diagonal, no un bloque de
   color: la tarjeta sigue siendo blanca y lo que se lee primero es la cifra. */
:root[data-theme="light"] .kpi {
  padding: 6px var(--sp-3);
  border: 1px solid var(--line-2); border-radius: var(--r-3);
  background: linear-gradient(135deg, var(--accent-soft) 0%, var(--surface) 62%);
  box-shadow: var(--shadow-1);
}
:root[data-theme="light"] .kpi .v { color: var(--text); font-weight: 600; }
/* Cada tarjeta con su matiz, y con el mismo que ya usa su información en el
   resto del panel: el que cuenta liquidaciones va en rojo aquí y en rojo en la
   tabla, así que la cabecera y el contenido dicen lo mismo. */
:root[data-theme="light"] .kpi.verde { background: linear-gradient(135deg, var(--green-soft) 0%, var(--surface) 62%); }
:root[data-theme="light"] .kpi.rojo  { background: linear-gradient(135deg, var(--red-soft) 0%, var(--surface) 62%); }
:root[data-theme="light"] .kpi.ambar { background: linear-gradient(135deg, var(--amber-soft) 0%, var(--surface) 62%); }

/* El interruptor de tema: un botón de icono más en la cabecera. No lleva estado
   propio de color — el sol o la luna ya dicen a qué se va. */
.tema-btn .luna { display: none; }
:root[data-theme="light"] .tema-btn .sol { display: none; }
:root[data-theme="light"] .tema-btn .luna { display: block; }

/* ---------------------------------------------------------------------------
   2. BASE
   --------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

/* [hidden] es una regla del navegador con menos peso que cualquier clase, así
   que un .row{display:flex} la anulaba y el campo de precio se veía con Market
   seleccionado. Se le devuelve la última palabra. */
[hidden] { display: none !important; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: var(--fs)/1.5 var(--font-ui);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

code, pre, .mono { font-family: var(--font-mono); }
code {
  font-size: .92em; background: var(--inset); color: var(--text-2);
  border: 1px solid var(--line); border-radius: var(--r-1); padding: 0 4px;
}
pre {
  margin: 0; font-size: var(--fs-sm); white-space: pre-wrap;
  word-break: break-word; color: var(--text-2);
}

/* La canaleta de scroll, discreta: en una pantalla oscura y densa, una barra
   gris claro de sistema es lo más brillante que hay y se lleva la mirada. */
* { scrollbar-width: thin; scrollbar-color: var(--line-3) transparent; }
*::-webkit-scrollbar { width: 9px; height: 9px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--line-2); border-radius: var(--r-full); }
*::-webkit-scrollbar-thumb:hover { background: var(--line-3); }

:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* ---------------------------------------------------------------------------
   3. TIPOGRAFÍA Y UTILIDADES
   --------------------------------------------------------------------------- */
h1, h2, h3, h4 { margin: 0; font-weight: 600; }

/* h2 es el rótulo de una sección dentro de un panel: pequeño, en versalitas y
   apagado. El contenido tiene que pesar más que su etiqueta. */
h2 {
  font-size: var(--fs-sm); text-transform: uppercase; letter-spacing: .09em;
  color: var(--text-2); margin-bottom: var(--sp-2);
}
h3 {
  font-size: var(--fs-md); color: var(--text);
  margin: var(--sp-4) 0 var(--sp-2);
}

.mono, .num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.num  { text-align: right; }
.dim  { color: var(--text-2); }
.dim3 { color: var(--text-3); }
.green  { color: var(--green); }
.red    { color: var(--red); }
.amber  { color: var(--amber); }
.blue   { color: var(--blue); }
.violet { color: var(--violet); }
.strong { font-weight: 600; }
.upper  { text-transform: uppercase; letter-spacing: .06em; }
.nowrap { white-space: nowrap; }
.grow   { flex: 1; min-width: 140px; }
.spacer { flex: 1; }

.hint {
  font-size: var(--fs-sm); color: var(--text-3); line-height: 1.5;
  margin: var(--sp-1) 0 0;
}

/* ---------------------------------------------------------------------------
   4. MARCA

   Un wordmark y nada más: ni logotipo, ni degradado, ni icono. Una herramienta
   con la que se mueven límites de pérdida se firma con su nombre bien puesto.
   --------------------------------------------------------------------------- */
.brand {
  display: flex; flex-direction: column; gap: 1px; user-select: none;
}
.brand-mark {
  font-family: var(--font-ui); font-weight: 700; font-size: var(--fs-md);
  letter-spacing: .26em; color: var(--text); text-transform: uppercase;
}
.brand-sub {
  font-size: var(--fs-xs); letter-spacing: .14em; text-transform: uppercase;
  color: var(--text-3);
}
.brand-lg .brand-mark { font-size: var(--fs-xl); letter-spacing: .3em; }
.brand-lg .brand-sub  { font-size: var(--fs-sm); letter-spacing: .18em; }

/* Título de una ficha de detalle: un número de cuenta o un correo. NO usa el
   wordmark —el espaciado ancho de la marca convierte "AYM-EDGE" en ocho letras
   sueltas— sino monoespaciada, que es como se escribe un identificador. */
.detail-title {
  font-family: var(--font-mono); font-size: var(--fs-lg); font-weight: 600;
  color: var(--text); line-height: 1.25; word-break: break-word;
}

/* ---------------------------------------------------------------------------
   5. ESTRUCTURA DE APLICACIÓN

   Sidebar fija + área de trabajo. Las pestañas sueltas dejan de escalar a la
   quinta pantalla y no dicen dónde estás; una navegación lateral se lee de un
   vistazo y deja el ancho entero para las tablas, que es donde está el dato.
   --------------------------------------------------------------------------- */
.shell {
  display: grid;
  grid-template-columns: var(--sidebar-w) minmax(0, 1fr);
  height: 100dvh;
}

.sidebar {
  display: flex; flex-direction: column;
  background: var(--surface); border-right: 1px solid var(--line-2);
  overflow-y: auto;
}

/* El wordmark respira: es lo primero que se ve y lo único que no se pulsa. Y
   arranca en la MISMA columna que el menú. */
.sidebar > .brand { padding: var(--sp-6) var(--nav-col) var(--sp-5); }

/* El carril del menú. Su padding lateral es el margen de la pastilla: el fondo
   del item activo llega justo hasta aquí, ni al borde del sidebar ni más
   adentro. */
.sidebar-nav {
  display: flex; flex-direction: column; gap: var(--sp-1);
  padding: 0 var(--nav-inset) var(--sp-4);
}

/* El rótulo de un grupo. Pequeño, apagado y con el tracking abierto: tiene que
   poder ignorarse cuando ya sabes dónde vas y estar ahí cuando no. El aire de
   arriba es lo que de verdad agrupa — más que el propio texto. */
/* El rótulo del grupo arranca en la columna: --nav-inset lo pone el carril y
   este padding pone el resto. Pequeño, apagado y con el tracking abierto: tiene
   que poder ignorarse cuando ya sabes dónde vas y estar ahí cuando no. El aire
   de arriba es lo que de verdad agrupa — más que el propio texto. */
.nav-group {
  font-size: var(--fs-sm); font-weight: 600; letter-spacing: .13em;
  text-transform: uppercase; color: var(--text-3);
  padding: 0 var(--sp-3); margin: var(--sp-5) 0 var(--sp-2);
}
.nav-group:first-child { margin-top: 0; }

/* EL ITEM. Todo lo de aquí existe para que haya UNA columna:
   - justify-content: flex-start ANULA el `center` que traen todos los botones
     (ver la sección 8). Sin esto, el contenido se centra dentro de la fila y
     cada item empieza en una x distinta según lo largo que sea su texto — que
     es exactamente el aspecto de un menú sin columna.
   - el padding lateral es --sp-3, y sumado al carril da --nav-col: la misma
     vertical que los rótulos de grupo.
   - sin padding vertical: la altura la fija min-height y así es idéntica en
     todos, tengan contador o no. */
.nav-item {
  display: flex; align-items: center; justify-content: flex-start;
  gap: var(--sp-3);
  min-height: var(--nav-h); padding: 0 var(--sp-3);
  border: 0; border-radius: var(--r-3); background: none; color: var(--text-2);
  font: inherit; font-size: var(--fs); text-align: left; cursor: pointer;
  width: 100%;
  transition: background-color .15s ease, color .15s ease;
}

/* EL ICONO SE UNIFORMA AQUÍ Y NO EN CADA SVG. Poner el grosor de trazo en cada
   icono es garantizar que el noveno entre con otro: en el marcado solo va la
   forma, y que todos se vean del mismo peso lo sostiene una regla.
   flex: none es lo que impide que un icono se encoja y descuadre la columna
   cuando la etiqueta es larga. */
.nav-item .ico {
  width: var(--nav-ico); height: var(--nav-ico); flex: none;
  fill: none; stroke: currentColor; stroke-width: 1.5;
  stroke-linecap: round; stroke-linejoin: round;
  color: var(--text-3); transition: color .15s ease;
}

/* Los estados llevan :not(:disabled) para GANARLE en especificidad a
   `button:hover:not(:disabled)`, que es global y pinta un gris escrito a mano.
   Sin esto, el hover del menú era el de un botón cualquiera — y peor: el item
   ACTIVO perdía su pastilla azul con solo pasar el ratón por encima. */
.nav-item:hover:not(:disabled) { background: var(--surface-2); color: var(--text); }
.nav-item:hover:not(:disabled) .ico { color: var(--text-2); }

/* ACTIVO: la pastilla ES el indicador, y por eso no lleva barra lateral. Dos
   señales para lo mismo compiten entre ellas, y la barra obliga además a
   descuadrar el padding de esa fila respecto a las demás. El fondo llega hasta
   el borde del carril; el CONTENIDO no se mueve ni un píxel — la pastilla pinta
   detrás, no empuja. */
.nav-item.on,
.nav-item.on:hover:not(:disabled) {
  background: var(--surface-3); color: var(--accent); font-weight: 600;
}
.nav-item.on .ico, .nav-item.on:hover:not(:disabled) .ico { color: var(--accent); }

/* Y sin el saltito de 0.5px que llevan los botones al pulsarlos: una pastilla de
   navegación que brinca se lee como un fallo de pintado, no como una pulsación. */
.nav-item:active:not(:disabled) { transform: none; }

/* El contador vivo, a la derecha. Gris y pequeño a propósito: es un dato de
   apoyo —cuántas cuentas hay— y si gritara competiría con el semáforo del
   monitor, que es el que sí tiene que llamar la atención. */
.nav-count {
  margin-left: auto; font-size: var(--fs-sm); color: var(--text-3);
  font-variant-numeric: tabular-nums;
}

.sidebar-foot {
  margin-top: auto; display: flex; flex-direction: column; gap: var(--sp-2);
  padding: var(--sp-3) calc(var(--nav-inset) + var(--sp-3));
  border-top: 1px solid var(--line);
}

.workspace { display: flex; flex-direction: column; min-width: 0; overflow: hidden; }

.topbar {
  display: flex; align-items: center; gap: var(--sp-4);
  height: var(--topbar-h); flex: none;
  padding: 0 var(--sp-4);
  background: var(--surface); border-bottom: 1px solid var(--line-2);
}

.workspace > main {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: var(--sp-4);
  display: flex; flex-direction: column; gap: var(--sp-3);
}

/* Rejillas de contenido. .split es tabla + detalle, que es la forma de casi
   todas las pantallas de administración. */
.split {
  display: grid; grid-template-columns: minmax(0, 1fr) 480px;
  gap: var(--sp-3); align-items: start;
}
.stack { display: flex; flex-direction: column; gap: var(--sp-3); min-width: 0; }
.row {
  display: flex; gap: var(--sp-3); flex-wrap: wrap; align-items: flex-end;
}
.row.tight { gap: var(--sp-2); }
.row.center { align-items: center; }

@media (max-width: 1180px) { .split { grid-template-columns: minmax(0, 1fr); } }
/* En estrecho el menú se tumba y pasa a ser una tira de pastillas. Los rótulos
   de grupo se van: en una fila horizontal no agrupan nada —no hay nada encima ni
   debajo que agrupar— y se leerían como una pestaña más. */
@media (max-width: 860px) {
  .shell { grid-template-columns: 1fr; height: auto; }
  .sidebar { flex-direction: row; align-items: center; flex-wrap: wrap; height: auto;
             padding: var(--sp-3); gap: var(--sp-3); }
  .sidebar > .brand { padding: 0; }
  .sidebar-nav { flex-direction: row; flex-wrap: wrap; padding: 0; }
  .nav-group { display: none; }
  .nav-item { width: auto; min-height: 36px; }
  .nav-count { margin-left: var(--sp-1); }
  .sidebar-foot { margin: 0; flex-direction: row; padding: 0; border-top: 0; }
}

/* ---------------------------------------------------------------------------
   6. PANELES, TARJETAS Y MÉTRICAS
   --------------------------------------------------------------------------- */
.panel {
  background: var(--surface); border: 1px solid var(--line-2);
  border-radius: var(--r-3); padding: var(--sp-3) var(--sp-4);
  min-width: 0;
}
.panel.flush { padding: 0; overflow: hidden; }
.panel-head {
  display: flex; align-items: center; gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border-bottom: 1px solid var(--line);
}
.panel-head h2 { margin: 0; }
.panel-body { padding: var(--sp-3) var(--sp-4); }

.scroll { max-height: 280px; overflow-y: auto; }
.scroll.tall { max-height: 420px; }

/* Rejilla de métricas del dashboard: auto-fit para que no haya que decidir
   cuántas caben, y mínimo generoso porque la cifra tiene que ser GRANDE. */
.metrics {
  display: grid; gap: var(--sp-3);
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
.metric {
  background: var(--surface); border: 1px solid var(--line-2);
  border-radius: var(--r-3); padding: var(--sp-3) var(--sp-4);
  display: flex; flex-direction: column; gap: 2px; min-width: 0;
}
.metric .k {
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .1em;
  color: var(--text-3);
}
.metric .v {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--fs-2xl); line-height: 1.15; letter-spacing: -.02em;
}
.metric .sub { font-size: var(--fs-sm); color: var(--text-3); }
.metric.sm .v { font-size: var(--fs-xl); }

/* Cifra de cabecera: la misma idea en pequeño, para la barra superior. */
.kpi { display: flex; flex-direction: column; min-width: 84px; }
.kpi .k {
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .1em;
  color: var(--text-3);
}
.kpi .v {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-size: var(--fs-lg); line-height: 1.2;
}
.kpis { display: flex; gap: var(--sp-5); align-items: center; }

/* Par etiqueta/valor, para fichas de estado. */
.kv {
  display: flex; justify-content: space-between; gap: var(--sp-3);
  font-size: var(--fs-sm); padding: 3px 0;
}
.kv > :first-child { color: var(--text-3); flex: none; }
/* El valor se recorta antes que partirse en dos líneas: en una barra lateral
   estrecha, "synthetic NQU6 (1 tick cada 250ms)" en tres renglones desalinea
   todo lo que tiene debajo. El texto entero queda en el title. */
.kv > :last-child {
  font-family: var(--font-mono); min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* ---------------------------------------------------------------------------
   7. BOTONES

   Un solo botón base y tres modificadores. `primary` para la acción que se
   espera, `danger` para la que no se puede deshacer, `ghost` para lo demás.
   Se estiliza el elemento <button> y no una clase .btn a propósito: en estas
   páginas los botones se crean desde JavaScript y uno al que se le olvide la
   clase tiene que salir bien igual.
   --------------------------------------------------------------------------- */
button, .btn {
  font: inherit; font-size: var(--fs); line-height: 1.2;
  display: inline-flex; align-items: center; justify-content: center;
  gap: 6px; cursor: pointer; white-space: nowrap;
  padding: 7px 12px; border-radius: var(--r-2);
  border: 1px solid var(--line-2); background: var(--surface-3);
  color: var(--text); transition: background .12s, border-color .12s, color .12s;
}
button:hover:not(:disabled), .btn:hover { background: var(--surface-4); border-color: var(--line-3); }
button:active:not(:disabled) { transform: translateY(.5px); }
button:disabled, .btn:disabled { opacity: .4; cursor: not-allowed; }

button.primary {
  background: var(--accent-soft); border-color: var(--accent-line); color: var(--on-accent);
  font-weight: 600;
}
button.primary:hover:not(:disabled) { background: var(--accent-hover); border-color: var(--accent); }

button.danger {
  background: var(--red-soft); border-color: var(--red-line); color: var(--on-red);
  font-weight: 600;
}
button.danger:hover:not(:disabled) { background: var(--red-hover); border-color: var(--red); }

button.ghost { background: transparent; border-color: transparent; color: var(--text-2); }
button.ghost:hover:not(:disabled) { background: var(--surface-2); color: var(--text); }

button.subtle { background: var(--surface-2); }

button.sm { padding: 3px 8px; font-size: var(--fs-sm); border-radius: var(--r-1); }
button.block { width: 100%; }

/* Botón de solo icono: cerrar un slide-over, descartar un aviso. */
.icon-btn {
  padding: 4px; width: 26px; height: 26px; border-radius: var(--r-1);
  background: transparent; border-color: transparent; color: var(--text-3);
}
.icon-btn:hover:not(:disabled) { background: var(--surface-3); color: var(--text); }

/* ---------------------------------------------------------------------------
   8. FORMULARIOS
   --------------------------------------------------------------------------- */
label {
  display: block; font-size: var(--fs-xs); color: var(--text-3);
  text-transform: uppercase; letter-spacing: .08em; margin-bottom: 3px;
}
input, select, textarea {
  font: inherit; font-size: var(--fs);
  background: var(--inset); color: var(--text);
  border: 1px solid var(--line-2); border-radius: var(--r-2);
  padding: 7px 9px; width: 100%; min-width: 0;
}
input:hover, select:hover, textarea:hover { border-color: var(--line-3); }
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft);
}
input::placeholder { color: var(--text-3); }
input:disabled, select:disabled, textarea:disabled { opacity: .5; cursor: not-allowed; }
/* Todo lo que sea un número se escribe y se lee en monoespaciada. */
input.num, input[type="number"] {
  font-family: var(--font-mono); font-variant-numeric: tabular-nums; text-align: right;
}
textarea { resize: vertical; font-family: var(--font-mono); font-size: var(--fs-sm); line-height: 1.55; }
select {
  appearance: none;
  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='%239aa6b6' stroke-width='1.4' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 9px center;
  padding-right: 26px;
}
input[type="checkbox"] {
  width: 14px; height: 14px; accent-color: var(--accent); padding: 0;
}

/* .field agrupa etiqueta + control + pista, que es la unidad con la que se
   construyen los formularios desde JavaScript. */
.field { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.field.narrow { flex: 0 0 auto; width: var(--w-narrow); }
.field .hint { margin-top: 3px; }

/* Rejilla de DOS COLUMNAS para los formularios largos.
   .row es flex y sirve para juntar dos o tres controles sueltos, pero en un alta
   de veinte campos deja cada fila con anchos distintos según lo que le quepa:
   las etiquetas no caen a la misma altura y el ojo no encuentra la columna. Esto
   es una rejilla de verdad —dos columnas iguales, un solo gap— así que todo lo
   que se meta dentro queda alineado sin que nadie ajuste nada.

   .full ocupa la fila entera: es para lo que se lee de un tirón (una dirección,
   un correo) o para lo que aparece y desaparece, que partido en media columna
   descolocaría al de al lado. */
.form-grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-3) var(--sp-4); align-items: start;
}
.form-grid > .full { grid-column: 1 / -1; }
@media (max-width: 620px) { .form-grid { grid-template-columns: minmax(0, 1fr); } }

/* Sección con título dentro de un formulario. La línea bajo el título es la
   separación: sin ella, en una columna estrecha, un formulario de cuatro
   secciones se lee como una lista de veinte campos. */
.form-section { display: flex; flex-direction: column; gap: var(--sp-3); }
.form-section > h3 {
  margin: 0; padding-bottom: var(--sp-2); border-bottom: 1px solid var(--line);
}

/* El formulario entero: un hueco IGUAL entre todo lo que va al primer nivel
   —secciones, avisos, la línea del endpoint—. Separaciones distintas según lo
   que haya encima es exactamente lo que hace que un formulario largo parezca
   desordenado aunque cada pieza esté bien. */
.form-stack { display: flex; flex-direction: column; gap: var(--sp-5); }

/* Tres columnas para lo que se lee en grupos cortos (importe, modo, unidades).
   Cae a dos y a una con el ancho, con los mismos cortes que el resto. */
.form-grid.cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 900px) { .form-grid.cols-3 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px) { .form-grid.cols-3 { grid-template-columns: minmax(0, 1fr); } }

/* Anchos con nombre para los controles que no deben ocupar toda la columna. */
.input-time { width: var(--w-time); flex: 0 0 auto; }
.input-qty  { width: var(--w-qty);  flex: 0 0 auto; }

/* LA REGLA QUE NO SE APLICA. Una regla opcional apagada no es una regla en cero:
   "este producto no tiene límite diario" y "su límite es cero, así que liquida
   al primer tick en rojo" son cosas opuestas. El campo apagado lo dice con
   todas las letras en vez de quedarse en blanco, que se lee como "falta por
   rellenar". */
.field.apagado > label { color: var(--text-3); }
.field .no-aplica { color: var(--text-3); font-style: italic; }

/* El error de UN campo, debajo de él. Va al lado de lo que está mal y no en un
   toast: un mensaje que aparece en una esquina obliga a adivinar cuál de los
   veinte campos lo provocó. */
.field .error { color: var(--red); font-size: var(--fs-xs); margin-top: 3px; }
input.invalid, select.invalid, textarea.invalid { border-color: var(--red-line); }
input.invalid:focus, select.invalid:focus { outline-color: var(--red); }

/* Una fila repetible dentro de una sección (un tope por producto, una ventana
   horaria): controles alineados y el botón de quitar al final. */
.rule-row {
  display: flex; align-items: center; gap: var(--sp-2); flex-wrap: wrap;
  padding: var(--sp-2); border: 1px solid var(--line);
  border-radius: var(--r-2); background: var(--inset);
}
.rule-row .grow { min-width: 120px; }

/* Casilla con su etiqueta al lado, en línea. */
.check { display: flex; align-items: center; gap: 6px; }
.check label { margin: 0; text-transform: none; letter-spacing: 0; font-size: var(--fs-sm); }
.check input { width: auto; }

/* ---------------------------------------------------------------------------
   9. TABLAS

   Densas: es una herramienta de trabajo y lo que se pide de ella es ver muchas
   filas a la vez. Cabecera pegajosa dentro de su panel, hover en toda la fila y
   orden por columna donde tiene sentido.
   --------------------------------------------------------------------------- */
table { width: 100%; border-collapse: collapse; }

th {
  text-align: left; font-weight: 600; font-size: var(--fs-xs);
  text-transform: uppercase; letter-spacing: .07em; color: var(--text-3);
  padding: 7px var(--sp-2); white-space: nowrap;
  background: var(--surface); border-bottom: 1px solid var(--line-2);
  position: sticky; top: 0; z-index: 2;
}
td {
  padding: 6px var(--sp-2); border-bottom: 1px solid var(--line);
  vertical-align: top;
}
tbody tr:last-child td { border-bottom: none; }
th.num, td.num {
  text-align: right; font-family: var(--font-mono); font-variant-numeric: tabular-nums;
}
/* Los identificadores —números de cuenta, contratos, códigos— también son
   datos que se comparan de un vistazo: monoespaciada y sin partir. Un
   "REPLAY-0001" roto en dos líneas por el guion deja de parecer un número. */
td.id { font-family: var(--font-mono); white-space: nowrap; }

tbody tr.clickable { cursor: pointer; }
tbody tr:hover td { background: var(--surface-2); }
tbody tr.selected td {
  background: var(--accent-soft);
  box-shadow: inset 3px 0 0 var(--accent);
}
tbody tr.selected:hover td { background: var(--accent-hover); }

/* Orden por columna. El indicador va SIEMPRE reservado (la flecha inactiva es
   transparente) para que ordenar no descoloque los encabezados. */
th.sortable { cursor: pointer; user-select: none; }
th.sortable:hover { color: var(--text-2); }
th.sortable::after {
  content: "▾"; margin-left: 5px; font-size: 9px; opacity: 0;
  display: inline-block; transition: opacity .1s, transform .1s;
}
th.sortable:hover::after { opacity: .35; }
th.sortable[aria-sort="ascending"]::after  { opacity: 1; transform: rotate(180deg); color: var(--accent); }
th.sortable[aria-sort="descending"]::after { opacity: 1; color: var(--accent); }
th.num.sortable::after { margin-left: 4px; }

.empty { color: var(--text-3); padding: var(--sp-4) var(--sp-2); text-align: center; }

/* ---------------------------------------------------------------------------
   10. BADGES DE ESTADO

   El color dice lo mismo que el texto. En una tabla de cincuenta cuentas,
   "liquidated" en rojo se encuentra sin leer; en gris hay que leerlas todas.
   --------------------------------------------------------------------------- */
.badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 1px 7px; border-radius: var(--r-full);
  border: 1px solid var(--line-2); background: var(--surface-2);
  font-size: var(--fs-xs); font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; white-space: nowrap; color: var(--text-2);
  vertical-align: 1px;
}
.badge::before {
  content: ""; width: 5px; height: 5px; border-radius: var(--r-full);
  background: currentColor; flex: none;
}
.badge.plain::before { display: none; }

.badge.active,    .badge.ok      { color: var(--green);  background: var(--green-soft);  border-color: var(--green-line); }
.badge.suspended, .badge.warn    { color: var(--amber);  background: var(--amber-soft);  border-color: var(--amber-line); }
.badge.liquidated,.badge.danger,
.badge.disabled                  { color: var(--red);    background: var(--red-soft);    border-color: var(--red-line); }
.badge.live,      .badge.info    { color: var(--blue);   background: var(--blue-soft);   border-color: var(--blue-line); }
.badge.old                       { color: var(--violet); background: var(--violet-soft); border-color: var(--violet-line); }
.badge.off                       { color: var(--text-3); background: var(--surface-2);   border-color: var(--line-2); }

/* ---------------------------------------------------------------------------
   11. AVISOS: TOASTS

   Confirman y explican; no bloquean. El CÓDIGO del error va bien grande porque
   es lo que la interfaz tiene que saber tratar y lo que se busca en docs/api.md;
   debajo, el mensaje literal del servidor.
   --------------------------------------------------------------------------- */
.toasts {
  position: fixed; z-index: 400; display: flex; flex-direction: column;
  gap: var(--sp-2); width: min(420px, calc(100vw - 32px));
  pointer-events: none;
}
.toasts.top-right    { top: var(--sp-3); right: var(--sp-3); }
.toasts.bottom-right { bottom: var(--sp-3); right: var(--sp-3); flex-direction: column-reverse; }

.toast {
  pointer-events: auto; cursor: pointer;
  background: var(--surface-2); border: 1px solid var(--line-2);
  border-left: 3px solid var(--text-3);
  border-radius: var(--r-2); padding: var(--sp-2) var(--sp-3);
  box-shadow: var(--shadow-2);
  animation: toast-in .16s ease-out;
}
@keyframes toast-in {
  from { opacity: 0; transform: translateX(12px); }
  to   { opacity: 1; transform: none; }
}
.toast .code {
  font-weight: 700; font-size: var(--fs-sm); letter-spacing: .06em;
  text-transform: uppercase;
}
.toast .msg {
  color: var(--text-2); font-size: var(--fs-sm); margin-top: 3px;
  overflow-wrap: anywhere; white-space: pre-wrap;
}
.toast.ok   { border-left-color: var(--green); } .toast.ok   .code { color: var(--green); }
.toast.err  { border-left-color: var(--red); }   .toast.err  .code { color: var(--red); }
.toast.warn { border-left-color: var(--amber); } .toast.warn .code { color: var(--amber); }
.toast.info { border-left-color: var(--blue); }  .toast.info .code { color: var(--blue); }

/* ---------------------------------------------------------------------------
   12. SLIDE-OVER

   Los formularios entran por la derecha en vez de empujar la pantalla hacia
   abajo. Un alta que desplaza la tabla hace perder el sitio a quien la estaba
   leyendo, y al cerrarla nadie sabe dónde estaba.
   --------------------------------------------------------------------------- */
.slideover { position: fixed; inset: 0; z-index: 300; display: flex; justify-content: flex-end; }
.slideover-scrim { position: absolute; inset: 0; background: var(--scrim); animation: fade-in .14s; }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }

.slideover-panel {
  position: relative; display: flex; flex-direction: column;
  width: min(680px, 100vw); background: var(--surface);
  border-left: 1px solid var(--line-2); box-shadow: var(--shadow-3);
  animation: slide-in .18s cubic-bezier(.22,.61,.36,1);
}
@keyframes slide-in { from { transform: translateX(24px); opacity: .6; } to { transform: none; opacity: 1; } }

.slideover-head {
  display: flex; align-items: center; gap: var(--sp-3); flex: none;
  padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--line-2);
}
.slideover-head h2 { flex: 1; margin: 0; }
.slideover-body {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: var(--sp-4); display: flex; flex-direction: column; gap: var(--sp-3);
}
.slideover-foot {
  flex: none; display: flex; gap: var(--sp-2); justify-content: flex-end;
  padding: var(--sp-3) var(--sp-4); border-top: 1px solid var(--line-2);
  background: var(--surface);
}

/* ---------------------------------------------------------------------------
   13. BUSCADOR GLOBAL
   --------------------------------------------------------------------------- */
.search { position: relative; flex: 1; max-width: 520px; }
.search input {
  padding-left: 30px; background: var(--inset); border-radius: var(--r-2);
}
.search .ico {
  position: absolute; left: 9px; top: 50%; transform: translateY(-50%);
  width: 14px; height: 14px; color: var(--text-3); pointer-events: none;
}
.search-results {
  position: absolute; top: calc(100% + 5px); left: 0; right: 0; z-index: 200;
  background: var(--surface-2); border: 1px solid var(--line-2);
  border-radius: var(--r-2); box-shadow: var(--shadow-2);
  max-height: 60vh; overflow-y: auto; padding: var(--sp-1);
}
.search-group {
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .1em;
  color: var(--text-3); padding: var(--sp-2) var(--sp-2) var(--sp-1);
}
.search-hit {
  display: flex; align-items: center; gap: var(--sp-2);
  padding: 6px var(--sp-2); border-radius: var(--r-1); cursor: pointer;
}
.search-hit:hover, .search-hit.on { background: var(--accent-soft); }
.search-hit .main { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.search-hit .side { font-size: var(--fs-sm); color: var(--text-3); font-family: var(--font-mono); }

/* ---------------------------------------------------------------------------
   14. MEDIDORES DE RIESGO

   El elemento protagonista de la app de trading. Lo que quiere ver un trader no
   es cuánto lleva perdido, sino CUÁNTO LE QUEDA antes de que le cierren la
   cuenta — así que se pinta la distancia al suelo y el porcentaje consumido, y
   el relleno recorre verde → ámbar → rojo con el consumo.

   El degradado vive en el relleno y se escala con background-size, de modo que
   el color del borde derecho es siempre el que le toca a ESE porcentaje: al 30%
   la punta es verde, al 85% ya es roja. Un relleno de color plano tendría que
   saltar de un color a otro, y el salto se lee como un error.
   --------------------------------------------------------------------------- */
.meter {
  position: relative; height: 10px; border-radius: var(--r-full);
  background: var(--inset); border: 1px solid var(--line-2); overflow: hidden;
}
.meter-fill {
  height: 100%; width: 0;
  background-image: linear-gradient(90deg, var(--green) 0%, var(--green) 35%,
                                            var(--amber) 68%, var(--red) 100%);
  background-repeat: no-repeat;
  transition: width .18s ease-out, background-size .18s ease-out;
}
/* La marca del 80%: el punto en el que quien mira debería dejar de mirar y
   hacer algo. */
.meter::after {
  content: ""; position: absolute; top: 0; bottom: 0; left: 80%;
  width: 1px; background: var(--meter-mark);
}
.meter.lg { height: 14px; }

.meter-row {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: var(--sp-3); margin-bottom: 4px;
}
.meter-row .name {
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .09em;
  color: var(--text-3);
}
.meter-row .val { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------------------
   15. AVISOS EN LÍNEA
   --------------------------------------------------------------------------- */
.callout {
  border: 1px solid var(--amber-line); background: var(--amber-soft);
  border-left-width: 3px; border-radius: var(--r-2);
  padding: var(--sp-2) var(--sp-3); font-size: var(--fs-sm);
  color: var(--text-2); line-height: 1.55;
}
.callout.danger { border-color: var(--red-line); background: var(--red-soft); border-left-width: 3px; }
.callout.info   { border-color: var(--blue-line); background: var(--blue-soft); border-left-width: 3px; }
.callout b { color: var(--text); }

/* El secreto de un token recién emitido: se enseña UNA vez, así que tiene que
   ser imposible de no ver y fácil de copiar entero. */
.secret {
  border: 1px solid var(--amber); background: var(--amber-soft);
  border-radius: var(--r-2); padding: var(--sp-3);
}
.secret code {
  display: block; margin: var(--sp-2) 0; padding: var(--sp-2);
  font-size: var(--fs-md); word-break: break-all; user-select: all;
  color: var(--on-amber); background: var(--inset); border-color: var(--amber-line);
}

/* Pastilla de conexión. */
.pill {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: var(--fs-xs); font-family: var(--font-mono);
  padding: 2px 8px; border-radius: var(--r-full);
  border: 1px solid var(--line-2); color: var(--text-3);
}
.pill::before {
  content: ""; width: 6px; height: 6px; border-radius: var(--r-full);
  background: currentColor;
}
.pill.up   { color: var(--green); border-color: var(--green-line); background: var(--green-soft); }
.pill.down { color: var(--red);   border-color: var(--red-line);   background: var(--red-soft); }
.pill.wait { color: var(--amber); border-color: var(--amber-line); background: var(--amber-soft); }

/* ---------------------------------------------------------------------------
   16. PANTALLA DE ENTRADA

   Las dos interfaces piden un token pegado a mano y ninguna lo guarda. Es la
   primera pantalla que se ve, así que se firma con la marca.
   --------------------------------------------------------------------------- */
.login { min-height: 100dvh; display: flex; align-items: center; justify-content: center; padding: var(--sp-4); }
.login-card {
  width: min(520px, 100%); padding: var(--sp-6);
  display: flex; flex-direction: column; gap: var(--sp-3);
  box-shadow: var(--shadow-2);
}
.login-card .brand { align-items: center; text-align: center; margin-bottom: var(--sp-2); }
.login-card p { margin: 0; color: var(--text-2); font-size: var(--fs); line-height: 1.6; }

/* ---------------------------------------------------------------------------
   12. LOS TRES SEMÁFOROS DE LA CABECERA
   ---------------------------------------------------------------------------

   Market data, RMS y System. Píldora oscura y sobria: un paso más clara que la
   cabecera, borde apenas visible, punto de color y el estado escrito al lado.

   LA PÍLDORA ES EL MENSAJE. Dice «Market data ok» o «Market data caído», no un
   color que haya que interpretar. El detalle técnico —edad del último tick,
   latencia de la base— aparece al pulsarla, que es cuando alguien quiere saber
   cuánto exactamente.

   EL ESTADO NORMAL ES SILENCIOSO. En verde no hay halo ni movimiento: una
   cabecera con tres cosas brillando enseña a no mirarlas. Solo el rojo se mueve,
   con un pulso corto del punto, y por eso se ve — porque es lo único que lo
   hace. */

.semaforos { display: flex; align-items: center; gap: 10px; }

.semaforo {
  position: relative;
  display: inline-flex; align-items: center; gap: var(--sp-2);
  padding: 8px 14px;
  border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface-2);
  font-size: var(--fs-sm); font-weight: 400; color: var(--text-2);
  line-height: 1;
  cursor: pointer;
  transition: background .15s, border-color .15s, color .15s;
}
.semaforo:hover { background: var(--surface-3); border-color: var(--line-2); color: var(--text); }
.semaforo:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* El punto. Liso: el color ya distingue los tres estados, y un halo alrededor
   de algo de ocho píxeles solo lo emborrona. */
.semaforo .punto {
  width: 8px; height: 8px; border-radius: 50%; flex: none;
  background: var(--sem, var(--text-3));
}
.semaforo .etiqueta { white-space: nowrap; }

/* Los colores salen de las fichas del sistema: el verde de aquí es el mismo
   verde de una fila que va bien. El fondo de la píldora NO cambia con el
   estado — lo que cambia es el punto y lo que dice el texto. */
.semaforo.green { --sem: var(--green); }
.semaforo.amber { --sem: var(--amber); color: var(--text); }
.semaforo.red   { --sem: var(--red);   color: var(--text); border-color: var(--red-line); }
/* Sin dato todavía: gris y quieto. Un semáforo que no ha medido nada no puede
   ponerse verde, pero tampoco debe llamar la atención. */
.semaforo.unknown { --sem: var(--text-3); }

/* Lo único que se mueve en toda la cabecera. */
.semaforo.red .punto { animation: sem-pulso 1.4s ease-in-out infinite; }
@keyframes sem-pulso { 0%, 100% { opacity: 1; } 50% { opacity: .25; } }

/* Quien pidió que las cosas no se muevan tiene motivos, y aquí se le hace caso
   sin perder el aviso: el rojo se queda quieto, pero el borde encendido y el
   texto («System caído») siguen diciendo lo mismo. */
@media (prefers-reduced-motion: reduce) {
  .semaforo .punto { animation: none !important; }
  .semaforo.red { border-color: var(--red); }
}

/* El detalle, al pulsar. Cuelga de la píldora y se cierra al pulsar fuera. */
.semaforo-detalle {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 40;
  min-width: 260px; max-width: 340px;
  padding: var(--sp-3);
  background: var(--surface-2); border: 1px solid var(--line-2);
  border-radius: var(--r-3); box-shadow: var(--shadow-2);
  font-size: var(--fs-sm); color: var(--text-2);
  text-align: left; cursor: default; white-space: normal;
}
.semaforo-detalle h4 {
  margin: 0 0 var(--sp-2); font-size: var(--fs-sm); color: var(--text);
  text-transform: uppercase; letter-spacing: .08em;
}
.semaforo-detalle .motivo { color: var(--text); line-height: 1.5; margin-bottom: var(--sp-2); }
.semaforo-detalle .medidas { display: grid; grid-template-columns: 1fr auto; gap: 2px var(--sp-3); }
.semaforo-detalle .medidas b {
  font-family: var(--font-mono); font-weight: 500; color: var(--text);
  font-variant-numeric: tabular-nums;
}

/* En pantalla estrecha se van las etiquetas y quedan los tres puntos: el color
   es lo que hay que ver, y el nombre se recupera al pulsar. */
/* En pantalla estrecha se van las etiquetas y quedan los tres puntos: el color
   es lo que hay que ver, y el texto se recupera al pulsar. */
@media (max-width: 1100px) {
  .semaforo .etiqueta { display: none; }
  .semaforo { padding: 8px; }
}

/* ---------------------------------------------------------------------------
   13. EL SWITCHER DE IB
   ---------------------------------------------------------------------------

   «IB: [Todos ▼]» en la cabecera, a la izquierda de las cifras. Solo lo ve quien
   puede ver más de una marca: a un gestor de un IB su pantalla está fijada a la
   suya, y un selector con una sola opción prometería una elección que no tiene. */
.switcher { display: inline-flex; align-items: center; gap: var(--sp-2); }
.switcher .k {
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .1em;
  color: var(--text-3);
}
.switcher select { min-width: 150px; }

/* El aviso de que se está mirando UNA marca y no la casa entera. Sin esto, un
   switcher olvidado en un IB hace leer «tres cuentas» donde hay treinta. */
.switcher.filtrando select { border-color: var(--accent-line); color: var(--accent); }
