/*
 * Sistema visual de BlockBoard — v2.
 *
 * La v1 era legible y no era nada más: un esqueleto correcto que no convencía
 * a nadie de pagar. Esta versión sale de una segunda ronda de investigación
 * (research/2026-09-24/07-diseno.md §7-9) con una pregunta distinta: no "¿se
 * lee?" sino "¿parece un producto por el que alguien pasaría por caja?".
 *
 * Las decisiones que la separan de la anterior:
 *  - una identidad, no una paleta neutra: un azul-cian como acento único y un
 *    ámbar reservado para lo que quema;
 *  - superficies con luz propia (borde de 1 px + reflejo interior superior),
 *    que es el detalle que separa una tarjeta cara de un div gris;
 *  - verde y rojo solo para mercado, nunca para estado de interfaz, y siempre
 *    acompañados de un signo, no solo de color;
 *  - números en tabular siempre, porque una columna que baila es ilegible;
 *  - densidad como atributo, no como constante.
 */

:root {
  /* --- primitivos --------------------------------------------------------- */
  --ink-950: #080a0f;
  --ink-900: #0c0f16;
  --ink-850: #11151e;
  --ink-800: #161b26;
  --ink-750: #1c2230;
  --ink-700: #232a3a;
  --ink-600: #2f3849;
  --ink-500: #6a7488;
  --ink-400: #8b94a8;
  --ink-300: #a8b0c2;
  --ink-100: #e7eaf2;
  --ink-000: #f6f8fd;

  --cyan-400: #38bdf8;
  --cyan-300: #6fd0fb;
  --blue-500: #3b82f6;
  --amber-400: #fbbf24;
  --green-400: #22c55e;
  --green-300: #4ade80;
  --red-400: #ef4444;
  --red-300: #f87171;
  --violet-400: #a78bfa;

  /* --- semánticos --------------------------------------------------------- */
  --bg: var(--ink-950);
  --bg-elevated: var(--ink-900);
  --surface: var(--ink-850);
  --surface-hover: var(--ink-800);
  --surface-sunken: var(--ink-900);
  --line: rgba(255, 255, 255, 0.07);
  --line-strong: rgba(255, 255, 255, 0.13);

  --text: var(--ink-100);
  --text-muted: var(--ink-300);
  --text-faint: var(--ink-500);

  --accent: var(--cyan-400);
  --accent-soft: rgba(56, 189, 248, 0.14);
  --accent-ink: #04121c;
  --hot: var(--amber-400);
  --up: var(--green-400);
  --down: var(--red-400);
  --info: var(--violet-400);
  --warn: var(--amber-400);
  --danger: var(--red-300);
  --ok: var(--green-300);
  --focus: var(--cyan-300);

  /* El reflejo superior: 1 px de luz que hace que una superficie parezca
     material y no un rectángulo pintado. */
  --sheen: inset 0 1px 0 rgba(255, 255, 255, 0.05);
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px -12px rgba(0, 0, 0, 0.6);

  /* --- tipografía: base 15, razón 1,25 ------------------------------------ */
  --font: "Inter var", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  --size-2xs: 11px;
  --size-xs: 12px;
  --size-sm: 13px;
  --size-base: 15px;
  --size-md: 17px;
  --size-lg: 21px;
  --size-xl: 27px;
  --size-2xl: 34px;
  --size-3xl: 46px;

  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px;
  --s5: 24px; --s6: 32px; --s7: 48px; --s8: 72px;

  --radius: 12px;
  --radius-sm: 7px;
  --radius-pill: 999px;

  --row-y: 9px;
  --row-x: 12px;
}

[data-density="compact"] { --row-y: 5px; --row-x: 10px; --size-base: 14px; }

/* ============================================================
   EL TEMA CLARO (2026-10-12)
   ============================================================
   Pedido así: «ya que se optimiza podria añadirse el modo claro/oscuro».

   **Se pudo hacer en veinte líneas porque la v1 ya separaba primitivos de
   semánticos**, y esa separación estaba escrita arriba sin saber todavía para
   qué iba a servir. Aquí solo se redefinen los semánticos: ninguna regla de
   las dos mil que vienen debajo sabe que existe un tema claro.

   **Los colores de mercado no son los mismos en los dos temas, y eso no es
   capricho.** El verde #22c55e sobre fondo negro tiene contraste de sobra;
   sobre blanco se queda en 2,2:1, que no llega al mínimo legible. Los de aquí
   son los tonos oscuros de la misma familia, elegidos por contraste contra el
   fondo claro y no por parecerse a los de arriba.

   **Qué no cambia, a propósito:** la imagen de cada historia. Es un SVG con
   sus colores dentro porque viaja fuera del sitio —se comparte en X, en
   Telegram, en un chat— y allí no hay tema que valga. Una tarjeta que cambia
   de color según cómo tenga el navegador quien la generó sería impredecible
   justo donde más se ve.

   El estado lo decide el servidor y vive en una galleta, como la barra de la
   izquierda y por la misma razón: leerlo del navegador al arrancar haría que
   la página saliera oscura y pegara un fogonazo al aclararse en cada carga. */
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="light"],
:root[data-theme="auto"] {
  --claro-bg: #f4f6fb;
  --claro-elevated: #ffffff;
  --claro-surface: #ffffff;
  --claro-surface-hover: #eef1f8;
  --claro-surface-sunken: #eceff7;
  --claro-line: rgba(15, 23, 42, 0.10);
  --claro-line-strong: rgba(15, 23, 42, 0.20);
  --claro-text: #0d1117;
  --claro-text-muted: #4b5568;
  --claro-text-faint: #717c92;
  --claro-accent: #0b7fc0;
  --claro-accent-soft: rgba(11, 127, 192, 0.12);
  --claro-accent-ink: #ffffff;
  --claro-hot: #b45309;
  --claro-up: #15803d;
  --claro-down: #d02424;
  --claro-info: #6d35d6;
  --claro-warn: #b45309;
  --claro-danger: #b91c1c;
  --claro-ok: #15803d;
  --claro-focus: #0b7fc0;
  --claro-sheen: inset 0 1px 0 rgba(255, 255, 255, 0.9);
  --claro-shadow: 0 1px 2px rgba(15, 23, 42, 0.06), 0 8px 24px -12px rgba(15, 23, 42, 0.22);
}

/* El cambio de verdad. Va en una regla aparte y repetida porque `auto` solo lo
   aplica cuando el sistema lo pide, y una única regla con `:is()` no permite
   meter la consulta de medios por dentro. */
:root[data-theme="light"] {
  --bg: var(--claro-bg);
  --bg-elevated: var(--claro-elevated);
  --surface: var(--claro-surface);
  --surface-hover: var(--claro-surface-hover);
  --surface-sunken: var(--claro-surface-sunken);
  --line: var(--claro-line);
  --line-strong: var(--claro-line-strong);
  --text: var(--claro-text);
  --text-muted: var(--claro-text-muted);
  --text-faint: var(--claro-text-faint);
  --accent: var(--claro-accent);
  --accent-soft: var(--claro-accent-soft);
  --accent-ink: var(--claro-accent-ink);
  --hot: var(--claro-hot);
  --up: var(--claro-up);
  --down: var(--claro-down);
  --info: var(--claro-info);
  --warn: var(--claro-warn);
  --danger: var(--claro-danger);
  --ok: var(--claro-ok);
  --focus: var(--claro-focus);
  --sheen: var(--claro-sheen);
  --shadow: var(--claro-shadow);
}

/* «Auto»: manda el sistema operativo. Es lo que trae por defecto quien no ha
   elegido nunca, porque es la respuesta correcta antes de saber nada de esa
   persona. */
@media (prefers-color-scheme: light) {
  :root[data-theme="auto"] {
    color-scheme: light;
    --bg: var(--claro-bg);
    --bg-elevated: var(--claro-elevated);
    --surface: var(--claro-surface);
    --surface-hover: var(--claro-surface-hover);
    --surface-sunken: var(--claro-surface-sunken);
    --line: var(--claro-line);
    --line-strong: var(--claro-line-strong);
    --text: var(--claro-text);
    --text-muted: var(--claro-text-muted);
    --text-faint: var(--claro-text-faint);
    --accent: var(--claro-accent);
    --accent-soft: var(--claro-accent-soft);
    --accent-ink: var(--claro-accent-ink);
    --hot: var(--claro-hot);
    --up: var(--claro-up);
    --down: var(--claro-down);
    --info: var(--claro-info);
    --warn: var(--claro-warn);
    --danger: var(--claro-danger);
    --ok: var(--claro-ok);
    --focus: var(--claro-focus);
    --sheen: var(--claro-sheen);
    --shadow: var(--claro-shadow);
  }
}

/* El selector de tema, abajo del todo en la barra. Tres posturas y no un
   interruptor de dos: «auto» no es lo mismo que «oscuro», y quien tiene el
   portátil en claro de día y oscuro de noche quiere que esto le siga. */
.tema { display: flex; gap: 2px; padding: 3px; margin: var(--s2) var(--s3) var(--s4);
  background: var(--surface-sunken); border: 1px solid var(--line);
  border-radius: var(--radius-pill); }
.tema button { flex: 1 1 0; border: 0; background: none; cursor: pointer;
  border-radius: var(--radius-pill); padding: 4px 0; line-height: 1;
  color: var(--text-faint); font: inherit; font-size: var(--size-2xs); }
.tema button:hover { color: var(--text); }
.tema button[aria-pressed="true"] { background: var(--surface); color: var(--text);
  box-shadow: var(--shadow); }
.tema svg { width: 13px; height: 13px; display: block; margin: 0 auto; }
.shell.side-closed .tema { flex-direction: column; margin: var(--s2) 6px var(--s4); }



* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
:root { --sticky-top: 52px; }   /* .topbar */
.shell { --sticky-top: 46px; }  /* .topstrip */

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: var(--size-base)/1.55 var(--font);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  font-feature-settings: "ss01", "cv01";
}

a { color: inherit; text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }
a.link { color: var(--accent); }
:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; border-radius: var(--radius-sm); }

h1, h2, h3, h4 { margin: 0; line-height: 1.2; font-weight: 680; letter-spacing: -0.021em; }
h1 { font-size: var(--size-xl); }
h2 { font-size: var(--size-lg); }
h3 { font-size: var(--size-md); }
p { margin: 0 0 var(--s3); }
.num, td.num, th.num { font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------- cabecera */

.topbar {
  position: sticky; top: 0; z-index: 30;
  /* Lo que tiene que esquivar una cabecera de tabla fija en este diseño. */
  display: flex; align-items: center; gap: var(--s5);
  padding: 0 var(--s5); height: 52px;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: saturate(140%) blur(12px);
  border-bottom: 1px solid var(--line);
}
.wordmark { display: inline-flex; align-items: center; gap: 8px; font-size: var(--size-md);
  font-weight: 750; letter-spacing: -0.03em; }
.wordmark:hover { text-decoration: none; }
.wordmark svg { display: block; }
.topbar nav { display: flex; gap: var(--s1); font-size: var(--size-sm); }
.topbar nav a { color: var(--text-muted); padding: 5px 10px; border-radius: var(--radius-sm); }
.topbar nav a:hover { background: var(--surface); color: var(--text); text-decoration: none; }
.topbar nav a.on { background: var(--surface); color: var(--text); box-shadow: var(--sheen); }
.topbar .right { margin-left: auto; display: flex; align-items: center; gap: var(--s3);
  font-size: var(--size-xs); color: var(--text-faint); }

.wrap { max-width: 1140px; margin: 0 auto; padding: var(--s6) var(--s5) var(--s8); }
.wrap.narrow { max-width: 820px; }
.wrap.wide { max-width: 1320px; }

.page-head { margin-bottom: var(--s5); }
.page-head h1 { font-size: var(--size-2xl); }
.page-head p { color: var(--text-muted); font-size: var(--size-base); max-width: 68ch; margin: var(--s2) 0 0; }
/* **El resumen de una historia no lleva esa medida** (2026-10-12). Pedido así:
   «Mejora de margenes del texto resumen, deja un espacio libre a la derecha,
   deberia tener el mismo ancho que la seccion del titulo».

   El `max-width: 70ch` del propio párrafo se quitó primero y no cambió nada,
   porque el que mandaba era **éste**, puesto aquí para los párrafos de
   entradilla de las demás páginas. Medido en el navegador: 639 px de texto
   bajo una imagen de 754, los 115 px de hueco que se veían. Donde el párrafo
   va debajo de algo que ocupa la columna entera, una medida de lectura más
   estrecha no se lee como cuidado tipográfico, se lee como un bloque mal
   alineado. En las demás páginas la entradilla va suelta y la medida sigue
   siendo la correcta, así que se levanta aquí y no allí. */
.page-head p.story-lede { max-width: none; }
.eyebrow { font-size: var(--size-2xs); text-transform: uppercase; letter-spacing: .12em;
  color: var(--accent); font-weight: 650; margin-bottom: var(--s2); }

/* ------------------------------------------------------------------ piezas */

.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius); padding: var(--s4); box-shadow: var(--sheen);
}
/* **`overflow-x: auto` y no `hidden`** (2026-10-12). El `hidden` estaba para
   que el contenido no se saliera de las esquinas redondeadas, y en una
   pantalla ancha hacía justo eso. En un teléfono hacía otra cosa: medido a
   390 px, la tabla de alertas mide 510, la de mercados 1.247 y la de estado
   2.560 — y `hidden` las **recortaba sin dejar forma de llegar al resto**. La
   página no se desplazaba a lo ancho (comprobado: `scrollX` se quedaba en 0),
   así que las columnas de la derecha sencillamente no existían para quien
   entra desde el móvil.

   Con `auto` se desplazan dentro de su tarjeta, que es lo que hace cualquier
   tabla ancha en un móvil, y las esquinas siguen limpias porque un elemento
   con desplazamiento también recorta. */
/* **Vuelve a `hidden` el 2026-10-12**, y el ida y vuelta merece quedar
   escrito. Se puso en `auto` el mismo día para que las tablas anchas no se
   quedaran recortadas en un móvil — lo estaban, y era un fallo. Pero la
   respuesta correcta no era una barra: era que sobren columnas, que es lo que
   el usuario pidió a continuación —«si la informacion no cabe en el tamaño del
   usuario siempre se reduce»— y lo que hacen ahora las clases `d1`…`d4` y el
   reparto fijo de más abajo. Con eso ninguna tabla se sale, y `hidden` vuelve
   a hacer solo lo que hacía: que el contenido no pise las esquinas. */
.card.flush { padding: 0; overflow: hidden; }
.card.tight { padding: var(--s3) var(--s4); }
.card.hoverable:hover { background: var(--surface-hover); border-color: var(--line-strong); }

.grid { display: grid; gap: var(--s3); }
.grid.two { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.grid.three { grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); }
.grid.four { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }
.cols { display: grid; grid-template-columns: minmax(0, 1fr) 320px; gap: var(--s4); align-items: start; }

.stat { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  padding: var(--s3) var(--s4); box-shadow: var(--sheen); }
.stat b { display: block; font-size: var(--size-xl); line-height: 1.1; letter-spacing: -0.025em;
  font-variant-numeric: tabular-nums; }
.stat span { color: var(--text-faint); font-size: var(--size-2xs); text-transform: uppercase;
  letter-spacing: .09em; }
.stat .trend { font-size: var(--size-xs); font-variant-numeric: tabular-nums; }

.meta { display: flex; flex-wrap: wrap; gap: var(--s3); align-items: center;
  color: var(--text-muted); font-size: var(--size-sm); }
.meta b { color: var(--text); font-weight: 620; }
.meta .right { margin-left: auto; }

.pill { display: inline-flex; align-items: center; gap: 5px; border: 1px solid var(--line-strong);
  border-radius: var(--radius-pill); padding: 2px 9px; font-size: var(--size-2xs);
  color: var(--text-muted); white-space: nowrap; letter-spacing: .01em; }
.pill.ok { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 38%, transparent);
  background: color-mix(in srgb, var(--ok) 10%, transparent); }
.pill.warn { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 38%, transparent);
  background: color-mix(in srgb, var(--warn) 10%, transparent); }
.pill.danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 38%, transparent); }
.pill.accent { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 40%, transparent);
  background: var(--accent-soft); }

.score { display: inline-flex; align-items: center; justify-content: center; min-width: 38px;
  height: 27px; padding: 0 var(--s2); border-radius: var(--radius-sm); font-weight: 700;
  font-size: var(--size-sm); font-variant-numeric: tabular-nums;
  background: var(--accent-soft); color: var(--accent); box-shadow: var(--sheen); }
.score.hot { background: color-mix(in srgb, var(--hot) 16%, transparent); color: var(--hot); }

.up { color: var(--up); } .down { color: var(--down); }
.mono { font-family: var(--font-mono); font-size: var(--size-xs); }
.muted { color: var(--text-muted); } .faint { color: var(--text-faint); }
.right { margin-left: auto; }

/* Monograma: nuestra marca para un medio o un activo. No usamos sus logos —ni
   nos pertenecen ni los queremos servir— y una letra con su color es
   suficiente para reconocerlo en una lista. */
.mark { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px;
  border-radius: 6px; font-size: var(--size-2xs); font-weight: 700; color: #0a0d12;
  flex: 0 0 auto; letter-spacing: -0.02em; }
.mark.lg { width: 32px; height: 32px; border-radius: 8px; font-size: var(--size-sm); }
.withmark { display: inline-flex; align-items: center; gap: var(--s2); }

/* El logo de una moneda. Va sobre un fondo propio y con esquinas redondeadas
   porque los logos vienen de mil sitios: unos son cuadrados opacos, otros PNG
   con transparencia y unos pocos traen el fondo blanco pegado. Sin el marco,
   una tabla de trescientas filas parece trescientos recortes distintos. */
/* El logo de un medio. Mismo tamaño y mismas esquinas que el monograma al que
   sustituye, para que una lista con los dos casos no baile. El fondo claro es
   deliberado y no decorativo: la mitad de los iconos de prensa son logotipos
   oscuros pensados para papel blanco, y sobre nuestro fondo desaparecen.
   `object-fit: contain` deja respirar al que no es cuadrado en vez de
   recortarlo. */
.olg { width: var(--olg, 22px); height: var(--olg, 22px); border-radius: 6px;
  background: #fff; object-fit: contain; padding: 1px; flex: 0 0 auto; }
.olg.lg { width: 32px; height: 32px; border-radius: 8px; }

/* Los medios de una historia, apilados como naipes. El solape iba antes en un
   `style` en línea dentro del bucle, con un número distinto en cada plantilla
   —−5 px en el terminal, −6 px en la lista—; aquí es uno y el mismo. El borde
   del color del fondo es lo que hace que se vean como piezas separadas y no
   como una mancha, y el último no se solapa con nada. */
.stack { display: inline-flex; margin-right: -6px; }
.stack:last-of-type { margin-right: 0; }
.stack > .olg, .stack > .mark { box-shadow: 0 0 0 2px var(--bg); }

.coin { display: inline-flex; flex: 0 0 auto; }
.coin-logo { border-radius: 50%; background: var(--surface); object-fit: contain;
  width: var(--coin, 22px); height: var(--coin, 22px); }

.reasons { display: flex; gap: 3px; }
.reasons i { height: 4px; border-radius: 2px; display: block; background: var(--accent); opacity: .8; }
.reasons i.b2 { background: var(--info); }
.reasons i.b3 { background: var(--up); }
.reasons i.b4 { background: var(--text-faint); }
/* Señales añadidas en F6-04: fuente primaria, magnitud y conversación. */
.reasons i.b5 { background: var(--warn); }
.reasons i.b6 { background: var(--down); }
.reasons i.b7 { background: var(--accent); opacity: .5; }

.spark { display: block; }
.chart { display: block; overflow: visible; }

/* ------------------------------------------------------------------ tablas */

/* `border-collapse: separate` con separación cero: colapsadas, los navegadores
   pierden el borde de una cabecera fija, que es parte de lo que se veía mal. */
table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: var(--size-sm); }
th { text-align: left; font-weight: 600; color: var(--text-faint); font-size: var(--size-2xs);
  text-transform: uppercase; letter-spacing: .09em; padding: var(--row-y) var(--row-x);
  border-bottom: 1px solid var(--line-strong); white-space: nowrap; }

/* La cabecera fija se pide, no se hereda. Estaba puesta en TODAS las tablas
   con `top: 52px`, la altura de la barra superior de la web; en las páginas que
   llevan la tira de 46px —terminal, panel, ficha de historia— se quedaba seis
   píxeles más abajo y tapaba la primera fila de cada tabla. Con listas de tres
   filas dentro de una tarjeta, además, no aporta nada. */
.sticky-head th { position: sticky; top: var(--sticky-top, 0px); background: var(--surface);
  z-index: 1; }
td { padding: var(--row-y) var(--row-x); border-bottom: 1px solid var(--line); vertical-align: middle; }
tbody tr:hover td { background: var(--surface-hover); }
tbody tr:last-child td { border-bottom: 0; }
td.when { color: var(--text-muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
td.who { white-space: nowrap; color: var(--text-muted); }

/* --------------------------------------------------------------- controles */

button, .btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  font: inherit; font-size: var(--size-sm); font-weight: 560;
  border: 1px solid var(--line-strong); background: var(--surface);
  color: var(--text); border-radius: var(--radius-sm); padding: 7px var(--s3);
  cursor: pointer; min-height: 32px; box-shadow: var(--sheen);
}
button:hover, .btn:hover { background: var(--surface-hover); border-color: var(--text-faint); text-decoration: none; }
button.primary, .btn.primary {
  background: linear-gradient(180deg, var(--cyan-300), var(--cyan-400));
  border-color: transparent; color: var(--accent-ink); font-weight: 650;
  box-shadow: 0 1px 0 rgba(255,255,255,.25) inset, 0 6px 20px -8px rgba(56,189,248,.6);
}
button.primary:hover, .btn.primary:hover { filter: brightness(1.07); }
button.ghost { background: transparent; box-shadow: none; }
.btn.lg { min-height: 42px; padding: 0 var(--s5); font-size: var(--size-base); border-radius: 9px; }

input, select, textarea { font: inherit; font-size: var(--size-sm); color: var(--text);
  background: var(--surface-sunken); border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm); padding: 7px var(--s2); min-height: 32px; }
input::placeholder { color: var(--text-faint); }

/* ------------------------------------------------------------------ landing */

.hero { position: relative; overflow: hidden; border-bottom: 1px solid var(--line);
  background: radial-gradient(1100px 420px at 50% -120px, rgba(56,189,248,.14), transparent 70%),
              radial-gradient(700px 300px at 85% 0, rgba(167,139,250,.10), transparent 70%); }
.hero .wrap { padding-top: var(--s8); padding-bottom: var(--s7); }
.hero h1 { font-size: clamp(32px, 5.2vw, var(--size-3xl)); letter-spacing: -0.035em; max-width: 17ch; }
.hero h1 em { font-style: normal; color: var(--accent); }
.hero .sub { font-size: var(--size-md); color: var(--text-muted); max-width: 58ch; margin: var(--s4) 0 var(--s5); }
.hero .actions { display: flex; gap: var(--s3); flex-wrap: wrap; align-items: center; }
.hero .proof { margin-top: var(--s5); display: flex; gap: var(--s5); flex-wrap: wrap;
  color: var(--text-faint); font-size: var(--size-xs); }
.hero .proof b { color: var(--text); font-size: var(--size-base); display: block;
  font-variant-numeric: tabular-nums; }

.section { padding: var(--s8) 0; border-bottom: 1px solid var(--line); }
.section:last-of-type { border-bottom: 0; }
.section h2 { font-size: var(--size-xl); letter-spacing: -0.028em; }
.section .lead { color: var(--text-muted); max-width: 64ch; margin-top: var(--s2); }

.feature { padding: var(--s5); }
.feature .icon { width: 34px; height: 34px; border-radius: 9px; display: grid; place-items: center;
  background: var(--accent-soft); color: var(--accent); margin-bottom: var(--s3); }
.feature h3 { margin-bottom: var(--s2); }
.feature p { color: var(--text-muted); font-size: var(--size-sm); margin: 0; }

.steps { counter-reset: step; }
.steps .card { display: flex; gap: var(--s4); align-items: flex-start; }
.steps .card::before { counter-increment: step; content: counter(step);
  width: 26px; height: 26px; border-radius: 50%; background: var(--accent-soft); color: var(--accent);
  display: grid; place-items: center; font-size: var(--size-xs); font-weight: 700; flex: 0 0 auto; }

.plan { display: flex; flex-direction: column; gap: var(--s3); }
.plan.featured { border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  box-shadow: var(--sheen), 0 0 0 1px color-mix(in srgb, var(--accent) 25%, transparent),
              0 20px 50px -30px rgba(56,189,248,.7); }
.plan .price { font-size: var(--size-2xl); font-weight: 720; letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums; }
.plan .price small { font-size: var(--size-sm); color: var(--text-faint); font-weight: 500; letter-spacing: 0; }
.plan ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s2);
  font-size: var(--size-sm); color: var(--text-muted); }
.plan li { display: flex; gap: var(--s2); align-items: flex-start; }
.plan li::before { content: "✓"; color: var(--accent); font-weight: 700; }
.plan li.no { color: var(--text-faint); }
.plan li.no::before { content: "—"; color: var(--text-faint); }

.compare td:first-child { color: var(--text-muted); }
.compare .yes { color: var(--up); } .compare .no { color: var(--text-faint); }

/* Lo que aún no existe se dice. */
.sample { position: relative; border-style: dashed; }
.sample::after { content: "sample"; position: absolute; top: 10px; right: 12px;
  font-size: 10px; letter-spacing: .1em; text-transform: uppercase; color: var(--hot);
  border: 1px solid color-mix(in srgb, var(--hot) 45%, transparent);
  background: color-mix(in srgb, var(--hot) 10%, transparent);
  border-radius: var(--radius-pill); padding: 1px 8px; z-index: 2; }

footer.site { border-top: 1px solid var(--line); color: var(--text-faint); font-size: var(--size-xs); }
footer.site .wrap { padding: var(--s5); display: flex; gap: var(--s5); flex-wrap: wrap; align-items: center; }

@media (max-width: 900px) { .cols { grid-template-columns: minmax(0, 1fr); } }
@media (max-width: 640px) {
  .wrap { padding: var(--s5) var(--s3) var(--s7); }
  .topbar { padding: 0 var(--s3); gap: var(--s3); overflow-x: auto; }
  .topbar .right span { display: none; }
  td.who { white-space: normal; }
}

/* --------------------------------------------------------- menú lateral */

.shell { display: grid; grid-template-columns: 216px minmax(0, 1fr); min-height: 100vh; }
.side {
  position: sticky; top: 0; align-self: start; height: 100vh;
  border-right: 1px solid var(--line); background: var(--bg-elevated);
  display: flex; flex-direction: column; gap: var(--s2); padding: var(--s3);
  overflow-y: auto;
}
.side .wordmark { padding: var(--s2) var(--s2) var(--s4); font-size: var(--size-md); }
.side nav { display: flex; flex-direction: column; gap: 1px; }
.side nav a {
  display: flex; align-items: center; gap: var(--s3); padding: 7px var(--s3);
  border-radius: var(--radius-sm); color: var(--text-muted); font-size: var(--size-sm);
}
.side nav a:hover { background: var(--surface); color: var(--text); text-decoration: none; }
.side nav a.on { background: var(--surface); color: var(--text); box-shadow: var(--sheen); }
.side nav a.on .ico { color: var(--accent); }
.side .ico { width: 16px; display: inline-grid; place-items: center; color: var(--text-faint); flex: 0 0 auto; }
.side .group { font-size: var(--size-2xs); text-transform: uppercase; letter-spacing: .1em;
  color: var(--text-faint); padding: var(--s3) var(--s3) var(--s1); }
.side .bottom { margin-top: auto; border-top: 1px solid var(--line); padding-top: var(--s3);
  font-size: var(--size-2xs); color: var(--text-faint); display: grid; gap: 4px; }

.topstrip { display: flex; align-items: center; gap: var(--s3); height: 46px;
  padding: 0 var(--s5); border-bottom: 1px solid var(--line);
  background: color-mix(in srgb, var(--bg) 85%, transparent); backdrop-filter: blur(10px);
  position: sticky; top: 0; z-index: 20; font-size: var(--size-xs); color: var(--text-faint); }

/* ------------------------------------------------------ panel por piezas */

.board { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s3); }
.board > .widget.w1 { grid-column: span 1; }
.board > .widget.w2 { grid-column: span 2; }
.board > .widget.w3 { grid-column: span 3; }
/* **`overflow: visible` y no `hidden` (2026-10-03).** El `hidden` estaba para
   que el contenido no se saliera de las esquinas redondeadas, y recortaba el
   globo de la «i» de la cabecera: las letras se cortaban al llegar al borde del
   widget. Lo que recorta ahora es `.body`, que ya tenía `overflow: auto` por su
   propio scroll, así que las esquinas siguen limpias y el globo sale. */
.widget { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--sheen); display: flex; flex-direction: column; overflow: visible; }
/* Las esquinas de abajo las redondea el cuerpo, que es el último hijo. */
.widget > .body:last-child { border-radius: 0 0 var(--radius) var(--radius); }
/* **La cabecera es una banda y el título es un título** (2026-10-12).
   Pedido así: «Titulos de bloque: Stories / Alerts / What is coming, no
   destacan sobre el resto deberian resaltar más, tienen casi el mismo formato
   que cualquier texto, mismo tamaño, fuente y color que el resto de info».

   Y era exacto, no una impresión: el `h3` medía `--size-sm` —13 px— que es
   **el mismo tamaño que `table`**, y con peso 620 contra el 600 de un `<b>`
   de una celda. Es decir, el título de un panel y una cifra de su tabla
   estaban a dos puntos de peso de distancia. Un panel sin título visible es
   una tabla suelta, y diez tablas sueltas no son un terminal.

   Tres cosas, y ninguna grita: el título sube a 15 px y a peso 700; la banda
   tiene fondo propio, así que se lee como cabecera y no como la primera fila
   del contenido; y una barra de acento de 2 px a la izquierda la ancla. El
   fondo de la banda es el que hace casi todo el trabajo. */
.widget > header { display: flex; align-items: center; gap: var(--s2);
  padding: var(--s2) var(--s3) var(--s2) calc(var(--s3) - 2px);
  border-bottom: 1px solid var(--line); border-left: 2px solid var(--accent);
  border-radius: var(--radius) var(--radius) 0 0;
  background: var(--surface-sunken); }
.widget > header h3 { font-size: var(--size-base); font-weight: 700; letter-spacing: -0.015em;
  color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.widget > header .tools { margin-left: auto; display: flex; gap: 2px; opacity: 0; transition: opacity .12s; }
.widget:hover > header .tools, .widget:focus-within > header .tools { opacity: 1; }
.widget > header .tools a { width: 24px; height: 24px; display: grid; place-items: center;
  border-radius: 5px; color: var(--text-faint); font-size: var(--size-xs); }
.widget > header .tools a:hover { background: var(--surface-hover); color: var(--text); text-decoration: none; }
.widget .body { padding: var(--s3); overflow: auto; }
.widget .body.flush { padding: 0; }
.widget.sample::after { top: 7px; right: 96px; }

.addbar { display: flex; gap: var(--s2); flex-wrap: wrap; align-items: center;
  margin-top: var(--s4); padding-top: var(--s4); border-top: 1px solid var(--line); }
.addbar .chip { border: 1px dashed var(--line-strong); border-radius: var(--radius-sm);
  padding: 5px 10px; font-size: var(--size-xs); color: var(--text-muted); }
.addbar .chip:hover { border-style: solid; color: var(--text); background: var(--surface); text-decoration: none; }

.funnel { display: grid; gap: 6px; }
.funnel .step { display: flex; align-items: center; gap: var(--s2); font-size: var(--size-xs); }
.funnel .bar { height: 20px; border-radius: 4px; background: linear-gradient(90deg,
  color-mix(in srgb, var(--accent) 65%, transparent), color-mix(in srgb, var(--accent) 25%, transparent)); }
.funnel .n { font-variant-numeric: tabular-nums; color: var(--text); min-width: 52px; text-align: right; }

@media (max-width: 1100px) { .board { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .board > .widget.w3 { grid-column: span 2; } }
@media (max-width: 860px) {
  .shell { grid-template-columns: minmax(0, 1fr); }
  .side { position: static; height: auto; flex-direction: row; align-items: center;
    overflow-x: auto; border-right: 0; border-bottom: 1px solid var(--line); }
  .side nav { flex-direction: row; }
  .side .group, .side .bottom { display: none; }
  .board { grid-template-columns: minmax(0, 1fr); }
  .board > .widget.w2, .board > .widget.w3 { grid-column: span 1; }
}

/* ------------------------------------------------------ barras horizontales */

.hbars { display: grid; gap: 6px; }
.hbar { display: grid; grid-template-columns: 96px 1fr 48px; gap: var(--s2);
  align-items: center; font-size: var(--size-xs); }
.hbar .lbl { color: var(--text-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hbar .track { height: 7px; background: var(--surface-sunken); border-radius: 4px; overflow: hidden; }
.hbar .track i { display: block; height: 100%; border-radius: 4px;
  background: linear-gradient(90deg, var(--accent), color-mix(in srgb, var(--accent) 40%, transparent)); }
.hbar .val { text-align: right; font-variant-numeric: tabular-nums; color: var(--text); }

.legend { display: grid; gap: 5px; font-size: var(--size-xs); }
.legend div { display: flex; align-items: center; gap: var(--s2); }
.legend i { width: 9px; height: 9px; border-radius: 3px; flex: 0 0 auto; }
.legend .v { margin-left: auto; font-variant-numeric: tabular-nums; color: var(--text-muted); }

.timeline { position: relative; padding-left: var(--s5); }
.timeline::before { content: ""; position: absolute; left: 7px; top: 6px; bottom: 6px;
  width: 1px; background: var(--line-strong); }
.timeline .node { position: relative; padding: var(--s2) 0; }
.timeline .node::before { content: ""; position: absolute; left: calc(var(--s5) * -1 + 3px);
  top: 15px; width: 9px; height: 9px; border-radius: 50%; background: var(--surface);
  border: 2px solid var(--line-strong); }
.timeline .node.on::before { background: var(--accent); border-color: var(--accent); }
.timeline .node.done::before { background: var(--up); border-color: var(--up); }

.claim { display: grid; grid-template-columns: 22px 1fr; gap: var(--s2);
  padding: var(--s2) 0; border-bottom: 1px solid var(--line); font-size: var(--size-sm); }
.claim:last-child { border-bottom: 0; }
.claim .flag { font-size: var(--size-sm); }
.claim .src { color: var(--text-faint); font-size: var(--size-2xs); margin-top: 2px; }

.codeblock { background: var(--surface-sunken); border: 1px solid var(--line);
  border-radius: var(--radius-sm); padding: var(--s3); font-family: var(--font-mono);
  font-size: var(--size-xs); color: var(--text-muted); overflow-x: auto; white-space: pre; }
.codeblock .k { color: var(--accent); } .codeblock .s { color: var(--up); }
.codeblock .c { color: var(--text-faint); }

/* ----------------------------------------------- cronología de aportación */

.contrib { display: grid; gap: 0; }
.contrib .row { display: grid; grid-template-columns: 74px 22px 1fr; gap: var(--s3);
  align-items: start; padding: var(--s3) 0; position: relative; }
.contrib .row + .row { border-top: 1px solid var(--line); }
.contrib .t { text-align: right; font-variant-numeric: tabular-nums;
  color: var(--text-muted); font-size: var(--size-xs); padding-top: 3px; }
.contrib .dot { position: relative; }
.contrib .dot::before { content: ""; position: absolute; left: 6px; top: 6px;
  width: 10px; height: 10px; border-radius: 50%; background: var(--line-strong); }
.contrib .dot::after { content: ""; position: absolute; left: 10.5px; top: 18px;
  bottom: -18px; width: 1px; background: var(--line); }
.contrib .row:last-child .dot::after { display: none; }
.contrib .row.first .dot::before { background: var(--up); box-shadow: 0 0 0 3px color-mix(in srgb, var(--up) 22%, transparent); }
.contrib .row.adds .dot::before { background: var(--accent); }
.contrib .row.echo .dot::before { background: var(--ink-600); }
.contrib .what { font-size: var(--size-sm); }
.contrib .who { display: flex; align-items: center; gap: var(--s2); margin-bottom: 3px; }
.contrib .who b { font-size: var(--size-sm); font-weight: 620; }

.prob { display: flex; align-items: center; gap: var(--s2); }
.prob .track { flex: 1; height: 6px; background: var(--surface-sunken); border-radius: 4px; overflow: hidden; }
.prob .track i { display: block; height: 100%; background: var(--accent); border-radius: 4px; }
.prob .pct { font-variant-numeric: tabular-nums; font-weight: 650; min-width: 42px; text-align: right; }

.ahead { color: var(--up); font-weight: 620; }

/* --------------------------------------------------------------- intereses */

.chips { display: flex; flex-wrap: wrap; gap: 6px; }

/* **La pastilla, que no existía** (2026-10-09). `.chip` se usa en media docena
   de sitios y no tenía ninguna regla: en la bandeja del terminal parecían
   pastillas porque allí son `<button>` y el navegador les pone borde solo,
   pero en la lista de historias son `<a>` y salían como **texto corrido** —«All
   Bitcoin 68 Ethereum 33 Solana 16…» de seguido—, que es lo que el usuario vio:
   «categorias en texto sin ningun tipo de formato visual».

   Un filtro que no parece pulsable no se pulsa. Y el recuento va dentro, en su
   propio tono, porque pegado al nombre se lee como parte del nombre. */
.chip { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap;
  padding: 5px 11px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--surface); color: var(--text-muted);
  font-size: var(--size-xs); line-height: 1.2; text-decoration: none; cursor: pointer;
  transition: border-color .12s, color .12s, background .12s; }
.chip:hover { border-color: var(--line-strong); color: var(--text); text-decoration: none; }
.chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.chip .n { font-variant-numeric: tabular-nums; font-size: var(--size-2xs);
  color: var(--text); opacity: .55; }
.chip[disabled] { opacity: .5; cursor: default; }

/* El elegido, sin ambigüedad: con veinte filtros a la vista, «cuál está puesto»
   tiene que verse sin leer. */
.chip.on { background: var(--accent); border-color: var(--accent); color: var(--bg); font-weight: 600; }
.chip.on .n, .chip.on .faint { color: var(--bg); opacity: .75; }
.chip-i {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--line-strong); border-radius: var(--radius-pill);
  padding: 4px 11px 4px 8px; font-size: var(--size-xs); color: var(--text-muted);
  background: var(--surface); cursor: pointer; white-space: nowrap;
}
.chip-i:hover { border-color: var(--text-faint); color: var(--text); text-decoration: none; }
.chip-i .n { color: var(--text-faint); font-variant-numeric: tabular-nums; font-size: var(--size-2xs); }
.chip-i.on { border-color: color-mix(in srgb, var(--accent) 55%, transparent);
  background: var(--accent-soft); color: var(--accent); }
.chip-i.on .n { color: color-mix(in srgb, var(--accent) 75%, transparent); }
.chip-i .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--line-strong); }
.chip-i.on .dot { background: var(--accent); }

.watch { display: grid; gap: var(--s2); }
/* `minmax` y no 130 px fijos: «Ethereum Foundation» con su pastilla al lado
   pide 169 y se salía de su columna a cualquier ancho de pantalla. */
.watch .row { display: grid; grid-template-columns: minmax(130px, auto) 70px 1fr 90px 54px;
  gap: var(--s3); align-items: center; padding: var(--s2) var(--s3);
  border: 1px solid var(--line); border-radius: var(--radius-sm); background: var(--surface); }
.watch .row:hover { background: var(--surface-hover); }
.watch .who { display: flex; align-items: center; gap: var(--s2); font-weight: 600; font-size: var(--size-sm); }
.watch .last { font-size: var(--size-sm); color: var(--text-muted); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.watch .num { font-variant-numeric: tabular-nums; font-size: var(--size-xs); text-align: right; }

.emerging { display: grid; gap: var(--s2); }
.emerging .row { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) 0;
  border-bottom: 1px solid var(--line); font-size: var(--size-sm); }
.emerging .row:last-child { border-bottom: 0; }
/* En el móvil se parte: una fila de cuatro cosas en línea pide 443 px dentro
   de una tarjeta de 332, y se llevaba la página entera a 472 sobre 390. */
@media (max-width: 560px) { .emerging .row { flex-wrap: wrap; } }

/* ------------------------------------------------------------ rendimientos */

/* Lo que paga la actividad y lo que paga una emisión de token se enseñan
   separados siempre. Sumarlos es la mentira más extendida del sector: un 40 %
   que son 4 % de comisiones y 36 % de emisiones es un 4 % con un cupón que
   puede desaparecer mañana. */
.apy { display: flex; align-items: baseline; gap: 5px; justify-content: flex-end; }
.apy .base { font-variant-numeric: tabular-nums; font-weight: 650; font-size: var(--size-base); }
.apy .reward { font-variant-numeric: tabular-nums; color: var(--hot); font-size: var(--size-xs); }
.apy .reward::before { content: "+"; }
.split { display: flex; height: 5px; border-radius: 3px; overflow: hidden;
  background: var(--surface-sunken); margin-top: 4px; min-width: 70px; }
.split i { display: block; height: 100%; }
.split i.b { background: var(--accent); }
.split i.r { background: var(--hot); opacity: .8; }

.risk { font-size: var(--size-2xs); }
.risk.yes { color: var(--warn); }
.risk.no { color: var(--text-faint); }

/* ------------------------------------------------- datos y servicios */

.dset { border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface);
  box-shadow: var(--sheen); overflow: hidden; }
.dset > header { display: flex; align-items: flex-start; gap: var(--s3); padding: var(--s3) var(--s4); }
.dset .grow { flex: 1; min-width: 0; }
.dset h3 { font-size: var(--size-base); }
.dset .what { color: var(--text-muted); font-size: var(--size-sm); margin-top: 3px; }
.dset .big { font-size: var(--size-xl); font-weight: 700; letter-spacing: -0.025em;
  font-variant-numeric: tabular-nums; line-height: 1.1; }
.dset .foot { display: flex; gap: var(--s4); flex-wrap: wrap; align-items: center;
  padding: var(--s2) var(--s4); border-top: 1px solid var(--line);
  background: var(--surface-sunken); font-size: var(--size-xs); color: var(--text-muted); }
.dset table { font-size: var(--size-xs); }
.dset table td { padding: 5px var(--s4); }

.state { display: inline-flex; align-items: center; gap: 6px; font-size: var(--size-xs);
  white-space: nowrap; }
.state .led { width: 8px; height: 8px; border-radius: 50%; background: var(--text-faint);
  flex: 0 0 auto; }
.state.ok .led { background: var(--up); box-shadow: 0 0 0 3px color-mix(in srgb, var(--up) 20%, transparent); }
.state.warn .led { background: var(--warn); box-shadow: 0 0 0 3px color-mix(in srgb, var(--warn) 20%, transparent); }
.state.danger .led { background: var(--down); box-shadow: 0 0 0 3px color-mix(in srgb, var(--down) 22%, transparent); }
.state.ok { color: var(--up); } .state.warn { color: var(--warn); } .state.danger { color: var(--down); }

.svc { border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface);
  box-shadow: var(--sheen); padding: var(--s3) var(--s4); display: grid; gap: 6px; }
.svc .top { display: flex; align-items: center; gap: var(--s2); }
.svc .top b { font-size: var(--size-base); }
.svc .sum { font-size: var(--size-sm); color: var(--text); }
.svc .check { font-size: var(--size-2xs); color: var(--text-faint); border-top: 1px solid var(--line);
  padding-top: 6px; margin-top: 2px; }
.svc.down { border-color: color-mix(in srgb, var(--down) 45%, transparent); }
.svc.warn { border-color: color-mix(in srgb, var(--warn) 40%, transparent); }
/* Para qué sirve cada cosa, en palabras. Un nombre propio —«Snapshot»— no le
   dice nada a quien entra a comprobar si el sitio está bien. */
.svc-feeds { font-size: var(--size-xs); color: var(--text-muted); }
.svc-fix { font-size: var(--size-xs); }
.svc-grid { display: grid; gap: var(--s3);
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.svc-h { font-size: var(--size-md); margin: var(--s6) 0 2px; }
.svc-blurb { font-size: var(--size-xs); margin: 0 0 var(--s3); }

/* El veredicto: una frase y, si hay algo que mirar, la lista de qué.
   Se pinta como una tarjeta ancha y no como un contador porque la respuesta
   que se busca aquí es sí o no, no un número. */
.verdict { border: 1px solid var(--line); border-left-width: 4px;
  border-radius: var(--radius); background: var(--surface);
  padding: var(--s4) var(--s5); display: grid; gap: var(--s3); }
.verdict.ok { border-left-color: var(--up); }
.verdict.warn { border-left-color: var(--warn); }
.verdict.bad { border-left-color: var(--down); }
.verdict-main { display: flex; align-items: center; gap: var(--s4); }
.verdict h1 { margin: 0; font-size: var(--size-xl); }
.verdict p { margin: 2px 0 0; font-size: var(--size-sm); }
.verdict-dot { width: 14px; height: 14px; border-radius: 50%; flex: none;
  background: var(--text-faint); }
.verdict.ok .verdict-dot { background: var(--up);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--up) 20%, transparent); }
.verdict.warn .verdict-dot { background: var(--warn);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--warn) 20%, transparent); }
.verdict.bad .verdict-dot { background: var(--down);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--down) 20%, transparent); }
.verdict-list { margin: 0; padding-left: var(--s5); display: grid; gap: 6px;
  font-size: var(--size-sm); border-top: 1px solid var(--line); padding-top: var(--s3); }
.verdict-list li > span { display: block; font-size: var(--size-xs); }
.verdict-list li > span.state { display: inline-block; min-width: 108px;
  font-size: var(--size-2xs); text-transform: uppercase; letter-spacing: .04em;
  font-weight: 600; }
.verdict-list a { margin-left: var(--s2); }

/* Cajas de cifra: un número grande y su etiqueta debajo. El panel ya tenía
   esto y la web pública no, así que `<b>` y `<span>` caían en la misma línea y
   se amontonaban. Es rejilla y no flex para que todas midan igual y no bailen
   cuando una cifra crece. */
.statcards { display: grid; gap: var(--s3); margin-bottom: var(--s5);
  grid-template-columns: repeat(auto-fit, minmax(168px, 1fr)); }
.statcards .card { padding: var(--s3) var(--s4); display: flex; flex-direction: column;
  gap: 2px; justify-content: center; }
.statcards .card b { font-size: var(--size-xl); line-height: 1.1; font-weight: 700;
  font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.statcards .card span { color: var(--text-faint); font-size: var(--size-2xs);
  text-transform: uppercase; letter-spacing: .07em; line-height: 1.3; }

/* ---------------------------------------------------------------- mercados */
/* Los filtros son radios escondidos con su etiqueta: así cambian la vista sin
   JavaScript y sin recargar. El script solo hace lo que el navegador no puede
   saber —los favoritos de quien mira y la búsqueda sobre las filas ya
   servidas—, así que con el script caído la tabla sigue completa y legible. */
.mkt-controls { display: flex; gap: var(--s4) var(--s3); flex-wrap: wrap;
  align-items: center; justify-content: space-between; margin-bottom: var(--s4); }
.mkt-controls .chips { display: flex; gap: var(--s2); flex-wrap: wrap; }

/* El radio se esconde sin salir del flujo de foco: `width:1px` y `clip` en vez
   de `display:none`, que lo saca del tabulador. Lo que se pulsa es la etiqueta
   entera, de borde a borde, y lo que cambia también: el punto de la izquierda
   era la única señal de estado y era demasiado pequeño para verse. */
.chips input[type=radio] { position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.chips input[type=radio] + .chip-i { cursor: pointer; padding: 6px 14px; font-weight: 500; }
.chips input[type=radio]:checked + .chip-i {
  background: var(--accent-soft); color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 55%, transparent); font-weight: 600; }
.chips input[type=radio]:focus-visible + .chip-i { outline: 2px solid var(--accent);
  outline-offset: 2px; }
.chips input#v-gainers:checked + .chip-i { background: color-mix(in srgb, var(--up) 14%, transparent);
  color: var(--up); border-color: color-mix(in srgb, var(--up) 50%, transparent); }
.chips input#v-losers:checked + .chip-i { background: color-mix(in srgb, var(--down) 14%, transparent);
  color: var(--down); border-color: color-mix(in srgb, var(--down) 50%, transparent); }
.chips input#v-stars:checked + .chip-i { background: color-mix(in srgb, var(--up) 14%, transparent);
  color: var(--up); border-color: color-mix(in srgb, var(--up) 50%, transparent); }
.chips .chip-i .n { margin-left: 2px; }
.star-ico { color: var(--up); margin-right: 5px; }

.mkt-search { flex: 1 1 300px; max-width: 460px; }
.mkt-search input { width: 100%; padding: 7px 12px; }

/* La estrella: apagada es un contorno tenue, encendida es ámbar. Un botón y no
   una casilla porque no se envía con ningún formulario: lo guarda el navegador. */
.star { background: none; border: 0; cursor: pointer; padding: 2px 4px; line-height: 1;
  color: var(--line-strong, #39425a); font-size: 16px;
  transition: color .12s, transform .12s; }
/* **La forma dice el estado, no el color** (2026-10-03). El color encendido era
   `var(--up)` y `:hover` tambien: con el raton encima de una estrella apagada
   se veia exactamente igual que una encendida, asi que al desmarcar «no se
   deselecciona». Y no era cosa del guardado — medido en el navegador: la clase
   `starred` pasaba a false y el almacen a `[]`, pero el color seguia verde
   mientras el puntero no se iba. Lo que enganaba era la apariencia.

   Asi que la glifa la pone el CSS: hueca apagada, llena encendida. El hover
   puede seguir poniendose verde —es una buena pista de que se puede pulsar— sin
   mentir, porque la forma ya no coincide. Y de paso funciona para quien no
   distingue el verde. */
.star { font-size: 0; }
.star::before { content: '\2606'; font-size: 16px; }
.star:hover { color: var(--up); transform: scale(1.2); }
tr.starred .star, .star.on, .star[aria-pressed=true] { color: var(--up);
  text-shadow: 0 0 10px color-mix(in srgb, var(--up) 45%, transparent); }
tr.starred .star::before, .star.on::before, .star[aria-pressed=true]::before { content: '\2605'; }

/* Dónde cerró dentro del recorrido del día. Una barra y un punto dicen en un
   vistazo lo que dos números no: si el 3 % acabó arriba o se dio la vuelta. */
.range { position: relative; display: block; height: 4px; border-radius: 2px;
  background: var(--surface-sunken, var(--surface)); }
.range i { position: absolute; top: -2px; width: 3px; height: 8px; border-radius: 2px;
  background: var(--text-muted); transform: translateX(-1px); }

/* **Sin partir, salvo donde hay texto de verdad** (2026-10-12). El `nowrap`
   es correcto para una tabla de cifras —una columna de precios que parte a
   media celda es ilegible— y esta regla cae sobre **cualquier** tabla con la
   clase `mkt`, incluidas las de estado, que tienen una columna con lo que
   escribe el proveedor. Medido: esa tabla llegaba a **2.590 px** con cuatro
   columnas, de las cuales una sola ocupaba 2.200, porque una frase larga no
   tenía permiso para pasar a la línea siguiente.

   `.wrap` es la salida, y se pone en la celda y en su cabecera. No se invierte
   la regla —nowrap solo en `.num`— porque hay columnas cortas sin clase que
   también quieren quedarse en una línea; marcar las tres de texto es menos
   superficie de error que marcar las treinta de cifras. */
table.mkt th, table.mkt td { white-space: nowrap; }
table.mkt th.wrapcell, table.mkt td.wrapcell { white-space: normal; }
/* Y que parta también dentro de una palabra cuando no hay más remedio. El
   texto del proveedor trae nombres de red y rutas sin espacios —«Noble Testnet
   network outage», «Stablr USD (USDR)»— y una palabra larga fija un ancho
   mínimo que ninguna consulta de medios puede bajar: medida a 390 px, esa
   columna sola pedía 196 de 366. `anywhere` solo actúa cuando la línea ya no
   cabe, así que no parte nada que quepa. */
/* **Fuera del ámbito `.mkt`**, y eso costó una vuelta: de las siete tablas de
   la pantalla de estado, cuatro llevan esa clase y tres no, así que la regla
   alcanzaba a unas sí y a otras no. Lo que `.wrap` significa —«esta columna es
   texto de verdad»— no depende de qué clase lleve su tabla. */
/* **`wrapcell` y no `wrap`**, y el nombre corto costó una fila de 125 píxeles
   de alto. `.wrap` es el contenedor principal de **todas** las páginas de este
   sitio —`max-width: 1140px; padding: 32px 24px 72px`— y una celda con esa
   clase heredaba ese relleno: una línea de texto dentro de una caja de ciento
   veinticinco. Es el mismo choque que ya costó `.info` contra `.al-info` en
   2026-10-09: un nombre de clase corto y genérico en una hoja compartida acaba
   encontrándose con otro. */
th.wrapcell, td.wrapcell { white-space: normal; overflow-wrap: anywhere; }
/* El aire de las filas. Con el logo de 22 px dentro de una celda de 6 px de
   padding, la fila medía 34 px y las dos líneas del nombre se tocaban. */
table.mkt td { padding-top: 7px; padding-bottom: 7px; vertical-align: middle; }
table.mkt th { padding-top: 9px; padding-bottom: 9px; }
table.mkt tbody tr:hover { background: var(--surface); }
table.mkt .withmark { gap: var(--s2); }
table.mkt .withmark .faint { margin-top: 1px; line-height: 1.25; }

/* Pestañas y tabla del widget de mercado.
 *
 * **Reescrito el 2026-10-02.** La versión anterior cambiaba de pestaña con
 * `:checked ~ .panel`, servía tres tablas y enseñaba una: funcionaba sin
 * JavaScript, que era la razón de hacerlo así, pero tenía dos límites que al
 * añadir búsqueda y estrellas dejaron de ser aceptables. Uno: con los
 * favoritos marcables desde aquí, la pestaña de favoritos **ya depende** del
 * script, así que el apaño dejaba de comprar nada. Dos: ataba cada panel a un
 * identificador fijo (`#wm-top`), con lo que solo podía haber un widget así en
 * la página.
 *
 * Ahora hay **una** tabla y el script decide qué filas se ven, igual que en la
 * página de mercados y con el mismo fichero. Sin script, se ven las 150 filas
 * ordenadas por capitalización, que es un estado útil.
 */
.w-tabs { display: flex; align-items: center; gap: 2px; padding: 6px var(--s3);
  border-bottom: 1px solid var(--line); font-size: var(--size-2xs); }
/* **La misma tira, dentro de la franja de la cabecera** (2026-10-15): «subir a
   la primera franja negra las seciones de top, estrella, gainer, loser». Sin
   borde ni relleno propios —ya los pone la cabecera— y pegada a la derecha,
   antes de los botones de la pieza. */
.w-tabs.in-head { padding: 0; border: 0; margin-left: auto; min-width: 0; flex: 0 1 auto; }
.w-tabs.in-head label { padding: 2px 7px; }
.w-tabs.in-head .w-mkt-q { min-width: 70px; max-width: 150px; }
/* En una pieza estrecha sobra el buscador: las pestañas son la navegación y
   él es un atajo. (La cifra del mercado entero vivía aquí y se fue el mismo
   día que subió a la franja: ver la nota de `_w_market_strip.html`.) */
@container pieza (max-width: 560px) {
  .w-tabs.in-head .w-mkt-q { display: none; }
}
@container pieza (max-width: 430px) {
  .w-tabs.in-head label { padding: 2px 5px; }
}
.w-tabs label { cursor: pointer; padding: 3px 9px; border-radius: 999px;
  color: var(--text-faint); text-transform: uppercase; letter-spacing: .06em;
  font-size: var(--size-2xs); display: inline-flex; align-items: center; gap: 4px; }
.w-tabs label:hover { color: var(--text); }
/* El radio se esconde pero **se deja enfocable**: `display:none` lo saca del
   orden de tabulación y entonces las pestañas no se pueden recorrer con el
   teclado. */
/* **Solo los radios**, y el `[type=radio]` no es cosmetico (2026-10-03). Sin
   el, esta regla alcanzaba tambien a la caja de busqueda de la barra: le ponia
   `opacity: 0` —asi que no se veia— y `position: absolute`, y como `.w-mkt-q`
   le da `min-width: 90px`, que gana a `width: 1px`, quedaba un rectangulo
   invisible de 90x32 px flotando sobre las pestanas **y comiendose sus
   clics**. Una sola regla causaba los dos fallos que el usuario vio: «sigue sin
   salir la busqueda» y «el boton top no funciona». Medido con el navegador:
   Playwright se negaba a pulsar la pestana porque el buscador interceptaba. */
.w-tabs input[type=radio] { position: absolute; opacity: 0; width: 1px; height: 1px; }
.w-tabs label:has(input:checked) { background: var(--surface); color: var(--text); }
.w-tabs label:has(input[data-mkt-view=gainers]:checked) { color: var(--up); }
.w-tabs label:has(input[data-mkt-view=losers]:checked) { color: var(--down); }
.w-tabs label:has(input[data-mkt-view=stars]:checked) { color: var(--up); }
.w-tabs label:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 1px; }

/* La búsqueda, dentro de la barra de pestañas (2026-10-03). Ocupaba una línea
   entera para una caja de texto, y en un widget dentro de una rejilla de diez
   piezas una línea es mucho. `margin-left:auto` la empuja a la derecha y se
   queda con el hueco que sobre, sin fijarle un ancho que se rompería al
   cambiar de columnas. */
.w-mkt-q { margin-left: auto; min-width: 90px; max-width: 200px; flex: 0 1 auto;
  background: var(--bg); color: var(--text); border: 1px solid var(--line);
  border-radius: 999px; padding: 3px var(--s3); font-size: var(--size-2xs);
  font-family: inherit; }
.w-mkt-q:focus { outline: none; border-color: var(--accent); }
.w-mkt-q::-webkit-search-cancel-button { filter: grayscale(1) opacity(.6); }

/* Altura fija para que la rejilla no baile al filtrar. */
/* **La tabla llena la pieza, no 300 píxeles fijos** (2026-10-09). Ese alto era
   de cuando el widget medía siempre lo mismo; desde que la pieza se estira, lo
   que sobraba quedaba **en blanco debajo de la última fila** —que es lo que el
   usuario vio— y agrandar el widget no enseñaba ni una fila más, que es lo que
   uno espera al agrandarlo.

   `min-height: 0` no es decorativo: sin él, un hijo de un contenedor flexible
   se niega a encogerse por debajo de su contenido, y con ciento cincuenta filas
   eso significa que la tabla empuja la pieza en vez de desplazarse dentro. */
/* **Vertical sí, horizontal no** (2026-10-12). Pedido así: «los widgets no
   tienen que tener barra horizontal […] si la informacion no cabe en el tamaño
   del usuario siempre se reduce, no se pone una barra para mover dentro de la
   caja. la barra vertical si la mantenemos por ejemplo en markets para ir
   bajando la lista de monedas».

   Es una regla de producto y no un ajuste: en un tablero que el usuario
   dimensiona a mano, una barra horizontal dentro de una pieza es pedirle que
   arrastre dentro de algo que él mismo acaba de estrechar. Lo que tiene que
   pasar es que sobren columnas, y de eso se encargan las consultas de
   contenedor de más abajo.

   `overflow-x: hidden` y no `clip` porque con `overflow-y: auto` el navegador
   convierte `clip` en `hidden` de todas formas — comprobado — y escribir lo
   que de verdad se aplica ahorra la siguiente duda. */
.w-mkt-scroll { flex: 1 1 auto; min-height: 0; overflow-x: hidden; overflow-y: auto;
  overscroll-behavior: contain; }
.w-mkt-scroll::-webkit-scrollbar { width: 8px; }
.w-mkt-scroll::-webkit-scrollbar-thumb { background: var(--line-strong); border-radius: 4px; }

/* La tabla del widget, con anchos fijos. Dejarla en automático descolocaba la
   columna de precios a media tabla —lo que se veía torcido— porque cada fila
   la medía según su propio contenido. */
table.w-mkt { width: 100%; table-layout: fixed; }
table.w-mkt td { padding: 5px var(--s2); border-bottom: 1px solid var(--line);
  font-size: var(--size-xs); vertical-align: middle; }
table.w-mkt tr:last-child td { border-bottom: 0; }
/* Doce columnas, con los anchos repartidos a mano. La tabla se veía vacía al
   lado de la de Mercados —había hueco de sobra— así que entran 7 d, el rango
   del día, el volumen y los sucesos. `table-layout: fixed` obliga a declarar
   los anchos, y eso es bueno: con automático, cada fila los calculaba según su
   contenido y la columna de precios se descolocaba a media tabla. */
/* **La cabecera tiene que leerse.** Estaba servida —las columnas estaban en el
   HTML— y aun así el usuario dijo que el widget «no muestra que es cada
   columna»: con el tamaño más pequeño de la escala, en el color más tenue de la
   paleta y en mayúsculas, no se veía. Está servido y no se lee es lo mismo que
   no estar. Ahora: un punto más de tamaño, el color de texto atenuado en vez
   del desvaído, sin mayúsculas forzadas y con la línea de abajo marcada. */
table.w-mkt thead th { padding: 5px var(--s2); border-bottom: 1px solid var(--line-strong);
  font-size: var(--size-xs); font-weight: 600; color: var(--text-muted);
  letter-spacing: .01em; text-align: left; white-space: nowrap; }
table.w-mkt thead th.num { text-align: right; }
/* Y se queda pegada arriba al hacer scroll por las 150 filas: con la cabecera
   fuera de la vista, la columna de «+2,4» vuelve a no significar nada. */
table.w-mkt thead th { position: sticky; top: 0; background: var(--surface); z-index: 2; }
/* **Los anchos, repartidos por lo que cabe en cada columna** (2026-10-09). El
   reparto anterior era a ojo y se notaba: «Coin» se llevaba 180 píxeles, los
   porcentajes quedaban sueltos y a la derecha la capitalización salía pegada al
   borde. Ahora cada columna pide lo que su contenido necesita —un precio de
   seis cifras ocupa más que un «+0,9»— y la de la moneda se queda con lo que
   sobre, que es la única que crece bien.

   `table-layout: fixed` es lo que hace que esto se cumpla: en automático, cada
   fila mide según su propio contenido y la columna de precios se descoloca a
   media tabla. Con doce columnas y ciento cincuenta filas, eso se ve —y ya
   estaba puesto arriba, por eso aquí no se repite. */
table.w-mkt .coin-cell { width: auto; min-width: 118px; padding-left: 4px; }
table.w-mkt .price { width: 82px; }
table.w-mkt .c-1h, table.w-mkt .c-7d { width: 54px; }
table.w-mkt .own { width: 50px; }
table.w-mkt .range-cell { width: 58px; }  /* cabe «Range» sin cortarse */
table.w-mkt .cap, table.w-mkt .vol { width: 64px; }
table.w-mkt .ev { width: 38px; }
/* **`td.spark` y no `.spark`**, y esos ocho píxeles eran una barra. El `<svg>`
   del gráfico lleva también `class="spark"`, así que la regla de ancho le caía
   encima y lo estiraba a 58 px dentro de una celda que, descontado el relleno,
   tiene 48: medido, el dibujo acababa 8 px a la derecha del borde de su celda.
   El `max-width` es el cinturón: aunque alguien vuelva a darle un ancho, no se
   sale. */
table.w-mkt td.spark, table.w-mkt th.spark { width: 58px; }
table.w-mkt .spark svg, table.w-mkt svg.spark { max-width: 100%; height: auto; }

/* La estrella, el logo y el ticker, pegados y en ese orden. El `gap` de 6 es lo
   que fija la distancia ahora: no depende del reparto de la tabla.

   **El flex va en un envoltorio y no en el `<td>`**: `display: flex` sobre una
   celda la saca del reparto de la tabla, y entonces esa columna deja de
   alinearse con su cabecera. Es el tipo de arreglo que parece funcionar hasta
   que alguien mira la cabecera. */
table.w-mkt .coin-wrap { display: flex; align-items: center; gap: 6px; min-width: 0; }
table.w-mkt .coin-wrap .star { flex: 0 0 auto; padding: 2px; font-size: 0; }
table.w-mkt .coin-link { display: inline-flex; align-items: center; gap: 6px;
  color: var(--text); text-decoration: none; min-width: 0; }
table.w-mkt .coin-link:hover b { color: var(--accent); }
table.w-mkt .coin-link b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* La barrita del rango, también en el widget. */
table.w-mkt .range { display: block; }
table.w-mkt .num { font-variant-numeric: tabular-nums; text-align: right; }
/* La estrella marcada, también en el widget: si solo se viera en la página de
   mercados, la misma lista parecería dos listas. */
table.w-mkt tr.starred .star { color: var(--up); opacity: 1; }

/* El método, plegado. Un ranking sin sus reglas es una afirmación, así que las
   reglas tienen que estar; lo que no tienen es que ocupar media pantalla. */
details.method { padding: var(--s3) var(--s4); }
details.method > summary { cursor: pointer; font-weight: 600; font-size: var(--size-sm);
  color: var(--text-muted); list-style: none; }
details.method > summary::marker, details.method > summary::-webkit-details-marker { display: none; }
details.method > summary::before { content: '▸ '; color: var(--text-faint); }
details.method[open] > summary::before { content: '▾ '; }
details.method > summary:hover { color: var(--text); }
details.method[open] > summary { margin-bottom: var(--s2); }

/* --- Avisos en línea -----------------------------------------------------
   `.notice` se usaba en hilos y en estados desde el 2026-10-01 y **no estaba
   definida**: el texto salía sin recuadro, así que una frase que dice «esto no
   lo sabemos» se leía como un párrafo más. Las frases que dicen lo que no
   sabemos son el producto, y tienen que verse. */
.notice { border: 1px solid var(--line); border-left-width: 3px; border-radius: var(--radius-sm);
  background: var(--surface-sunken); padding: var(--s3) var(--s4);
  font-size: var(--size-sm); color: var(--text-muted); }
.notice b { color: var(--text); }
.notice.ok { border-left-color: var(--ok); }
.notice.danger { border-left-color: var(--danger); }

/* --- Formularios de cuenta ---------------------------------------------- */
.stack { display: flex; flex-direction: column; gap: var(--s3); }
.stack label { display: flex; flex-direction: column; gap: 4px;
  font-size: var(--size-xs); color: var(--text-muted); }
.stack input { width: 100%; }
.stack button { align-self: flex-start; }

/* Los botones de proveedor, a lo ancho y en columna: en una fila, con cuatro
   proveedores y nombres de largo distinto, quedan de tamaños distintos y
   parece que uno es el recomendado. */
.providers { display: flex; flex-direction: column; gap: var(--s2); }
.providers .btn { justify-content: center; text-align: center; padding: 10px 14px; }

/* El separador «or». Una línea a cada lado, hecha con el borde del pseudo
   elemento para no meter dos divs vacíos en la plantilla. */
.or { display: flex; align-items: center; gap: var(--s3); margin: var(--s4) 0;
  color: var(--text-faint); font-size: var(--size-2xs); text-transform: uppercase;
  letter-spacing: .12em; }
.or::before, .or::after { content: ''; flex: 1; height: 1px; background: var(--line); }

/* Dos columnas iguales, para las parejas de tarjetas del panel de cuenta.
   `.cols` a secas es 1fr + 320px, que es para contenido y barra lateral. */
.cols.even { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }

/* --- La «i» de información -------------------------------------------------
 *
 * Decisión del 2026-10-02: los widgets llevaban un subtítulo explicativo
 * permanente debajo del título, y diez de ellos a la vez convertían el terminal
 * en una página de texto con tablas dentro. El texto no sobra —lo que explica
 * de dónde sale un número es justo lo que distingue este producto de un panel
 * de cifras sin procedencia— pero no tiene que estar siempre visible.
 *
 * Así que: título corto y claro, y una «i» que lo cuenta al pasar por encima.
 *
 * **Sin JavaScript, como el resto del sitio.** Es un `span` con el texto en un
 * atributo y un `::after` que lo pinta. `:focus-visible` además de `:hover`
 * porque con el teclado no hay «encima», y `tabindex="0"` para que se pueda
 * enfocar; el mismo texto va en `aria-label` para quien usa un lector.
 */
.info {
  display: inline-flex; align-items: center; justify-content: center;
  width: 15px; height: 15px; border-radius: 50%;
  border: 1px solid var(--line-strong); color: var(--text-muted);
  font-size: 10px; font-style: italic; font-weight: 600; line-height: 1;
  cursor: help; user-select: none; position: relative; flex: none;
}
.info:hover, .info:focus-visible { color: var(--accent); border-color: var(--accent); outline: none; }

/* El rótulo que se explica solo: para cabeceras de tabla, donde una insignia
   por columna no cabe. Comparte el globo con la «i» —misma regla más abajo— y
   se distingue por el subrayado de puntos, que es la señal de «hay algo
   debajo» que todo el mundo reconoce. */
.hint { position: relative; cursor: help; text-decoration: underline dotted;
  text-decoration-color: var(--text-faint); text-underline-offset: 3px;
  text-decoration-thickness: 1px; }
.hint:hover, .hint:focus-visible { color: var(--accent); text-decoration-color: var(--accent);
  outline: none; }
/* **El fondo usa `--bg-elevated`, que existe.** La primera versión escribía
   `var(--bg-raised)`, una variable que no está definida en ninguna parte: sin
   valor, `background` se quedaba sin resolver y el globo salía **transparente**,
   con el texto de la página leyéndose por debajo. Es el fallo que el usuario
   describió como «el fondo se transparenta y no se lee bien».

   Y se ancla a la **izquierda** en vez de centrarse: centrado, un globo de 34
   caracteres junto a un título corto se sale por el lado y se corta. Anclado,
   crece hacia dentro. `.info.right` lo ancla al otro lado para los que están
   pegados al borde derecho. */
.info::after, .hint::after {
  content: attr(data-info);
  /* **Fijo al pie de la ventana desde el 2026-10-12**, y antes anclado al
     elemento. El motivo es medible y es un fallo que introduje yo el día
     anterior, al poner una explicación por columna.

     Un globo colocado en absoluto dentro de una caja con desplazamiento
     **suma a su anchura desplazable**. Medido en el widget de mercado: la
     tabla medía 578 y la caja 578 —cabía exacta— y la caja decía 913. Eso son
     335 píxeles de barra horizontal puestos por una decoración, y el usuario
     los vio: «los widgets no tienen que tener barra horizontal».

     Fijo, el globo sale del flujo y de la cuenta: la misma medición da 578
     contra 578. Y arregla de paso tres cosas que el anclado no podía: no lo
     recorta ningún contenedor —hubo un apaño de 2026-10-02 justo por eso—,
     cabe siempre porque se mide contra la ventana, y en un móvil se lee
     entero en vez de salirse por el borde.

     Lo que se pierde: ya no sale pegado a lo que preguntas. A cambio sale
     siempre en el mismo sitio, que con catorce columnas se sigue mejor con la
     vista que catorce posiciones distintas. */
  position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%);
  /* 52ch y no 34: desde el 2026-10-09 estos globos llevan las explicaciones
     que antes eran párrafos de la página, de cuarenta a noventa palabras. A
     34 caracteres eso es una columna de veinte líneas, que es tan ilegible
     como no tenerlo. 52 es una medida de lectura cómoda y sigue cabiendo. */
  width: max-content; max-width: min(62ch, 92vw);
  padding: var(--s2) var(--s3);
  background: var(--bg-elevated); border: 1px solid var(--line-strong); border-radius: 6px;
  box-shadow: 0 6px 20px rgb(0 0 0 / 45%);
  color: var(--text); font-size: var(--size-xs); font-style: normal; font-weight: 400;
  line-height: 1.45; text-align: left; white-space: normal;
  opacity: 0; visibility: hidden; transition: opacity .12s ease;
  /* Por encima de la barra lateral y de cualquier cabecera pegajosa. */
  z-index: 200; pointer-events: none;
}
.info:hover::after, .info:focus-visible::after,
.hint:hover::after, .hint:focus-visible::after { opacity: 1; visibility: visible; }

/* --- El mismo globo, junto al ratón ------------------------------------------
 *
 * Pedido el 2026-10-14: «el texto debe salir al lado del raton justo cuando
 * pasas por encima de la i». Lo de arriba sale fijo al pie de la ventana, y el
 * motivo está escrito ahí: anclado al elemento sumaba a la anchura desplazable
 * de cualquier caja con scroll y ponía barras horizontales en los paneles.
 *
 * La salida es un **solo globo colgado del `<body>`**, al que `hint.js` le da
 * las coordenadas del puntero. No está dentro de ninguna caja, así que no suma
 * a la anchura de ninguna, y sale donde se está mirando.
 *
 * `html.hint-js` lo pone el script **al final**, cuando ya tiene todo
 * enganchado: hasta entonces manda el `::after` de arriba, que es el respaldo
 * sin JavaScript y el que sigue valiendo si el fichero no carga. Nunca hay dos.
 */
.hint-js .info::after, .hint-js .hint::after { content: none; }

.hint-pop {
  position: fixed; left: 0; top: 0; z-index: 300;
  width: max-content; max-width: min(62ch, 92vw);
  padding: var(--s2) var(--s3);
  background: var(--bg-elevated); border: 1px solid var(--line-strong); border-radius: 6px;
  box-shadow: 0 6px 20px rgb(0 0 0 / 45%);
  color: var(--text); font-size: var(--size-xs); font-style: normal; font-weight: 400;
  line-height: 1.45; text-align: left; white-space: normal;
  /* Letra normal aunque el globo salga de una cabecera en versalitas: hereda
     del `<body>` y no del elemento, por estar colgado del `<body>`. */
  letter-spacing: normal; text-transform: none;
  /* Invisible **y sin medir a cero**: se mide con el texto puesto para saber
     dónde cabe, así que no puede ser `display: none`. */
  opacity: 0; visibility: hidden; transition: opacity .1s ease;
  pointer-events: none;
}
.hint-pop.on { opacity: 1; visibility: visible; }
/* Pegada al borde derecho de su contenedor, el globo se saldría: se ancla al
   otro lado. */
/* `.right` anclaba el globo al otro lado cuando el elemento estaba pegado al
   borde derecho. Fijo al pie no hay lado al que anclarse, así que ya no hace
   nada; las llamadas que lo pasan siguen siendo válidas y se ignora. */
/* El globo de una cabecera de tabla hereda el peso y el tamaño de la cabecera
   —versalitas de 11 px— y así no se lee. Se devuelve al cuerpo normal. */
.hint::after { font-weight: 400; font-size: var(--size-xs); letter-spacing: normal;
  text-transform: none; color: var(--text); }

/* --- El calendario -----------------------------------------------------------
 *
 * Tres diseños servidos a la vez mientras se elige uno (2026-10-02). Lo que
 * comparten, y es lo que hay que conservar en el que gane:
 *
 *   · el color dice la clase, y es el mismo en los tres;
 *   · una fecha **estimada** no se pinta como un hecho;
 *   · un día cargado se ve antes de leerlo.
 */
.k-macro   { --k: var(--accent); }
.k-expiry  { --k: var(--warn); }
.k-governance { --k: #8b7bd8; }
.k-protocol   { --k: var(--up); }
.k-unlock     { --k: var(--hot); }
.pill.k-macro, .pill.k-expiry, .pill.k-governance, .pill.k-protocol {
  color: var(--k); border-color: color-mix(in srgb, var(--k) 40%, transparent); }

/* Una fecha calculada y no anunciada. Va en cursiva y con borde punteado
   porque es exactamente la clase de dato que alguien copiaría como seguro. */
.cal-est { font-size: var(--size-2xs); font-style: italic; color: var(--text-faint);
  border-bottom: 1px dotted var(--text-faint); margin-left: 6px; cursor: help; }

/* A. Agenda */
.cal-agenda { display: flex; flex-direction: column; gap: 2px; }
.cal-day { display: grid; grid-template-columns: 92px 1fr; gap: var(--s3);
  padding: var(--s3) 0; border-top: 1px solid var(--line); }
.cal-day.today { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.cal-day.heavy .cal-date b { color: var(--warn); }
/* La muestra de la leyenda: el mismo color que pinta la fecha, para que lo que
   se explica y lo que se ve sean el mismo ámbar y no dos parecidos. */
.cal-amber-demo { color: var(--warn); font-variant-numeric: tabular-nums; }
.cal-date { display: flex; flex-direction: column; align-items: flex-start; gap: 1px;
  padding-left: var(--s2); }
.cal-date b { font-size: var(--size-xl); line-height: 1; font-variant-numeric: tabular-nums; }
.cal-date span { font-size: var(--size-2xs); text-transform: uppercase; letter-spacing: .07em; }
.cal-items { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.cal-item { display: grid; grid-template-columns: 62px 52px 1fr auto; gap: var(--s3);
  align-items: baseline; padding: 4px var(--s3) 4px 0;
  border-left: 2px solid var(--k, var(--line-strong)); padding-left: var(--s3); }
.cal-kind { font-size: var(--size-2xs); text-transform: uppercase; letter-spacing: .07em;
  color: var(--k, var(--text-faint)); }
.cal-time { font-size: var(--size-2xs); color: var(--text-faint); font-variant-numeric: tabular-nums; }
.cal-title { font-size: var(--size-sm); min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.cal-size { font-size: var(--size-2xs); color: var(--text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.cal-detail { grid-column: 3 / -1; font-size: var(--size-2xs); }

/* B. Mes */
.cal-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
.cal-head { padding: 6px var(--s2); font-size: var(--size-2xs); text-transform: uppercase;
  letter-spacing: .07em; color: var(--text-faint); border-bottom: 1px solid var(--line); }
.cal-cell { min-height: 92px; padding: 5px var(--s2); border-right: 1px solid var(--line);
  border-bottom: 1px solid var(--line); display: flex; flex-direction: column; gap: 2px; }
.cal-cell.empty { background: color-mix(in srgb, var(--line) 18%, transparent); }
.cal-cell.today { background: color-mix(in srgb, var(--accent) 8%, transparent); }
.cal-cell.heavy { box-shadow: inset 0 2px 0 var(--warn); }
.cal-cell-date { font-size: var(--size-2xs); color: var(--text-faint); font-variant-numeric: tabular-nums; }
.cal-chip { display: flex; align-items: center; gap: 4px; font-size: var(--size-2xs);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: help; }
.cal-chip i { width: 6px; height: 6px; border-radius: 50%; background: var(--k); flex: none; }

/* C. Carriles */
.cal-lanes { display: flex; flex-direction: column; gap: 2px; padding: var(--s3); min-width: 640px; }
.cal-lane { display: grid; grid-template-columns: 80px 1fr; align-items: center; gap: var(--s3); }
.cal-lane-name { font-size: var(--size-2xs); text-transform: uppercase; letter-spacing: .07em;
  color: var(--text-faint); }
.cal-lane-track { position: relative; height: 26px; border-bottom: 1px solid var(--line); }
.cal-dot { position: absolute; top: 9px; width: 8px; height: 8px; border-radius: 50%;
  background: var(--k); transform: translateX(-50%); cursor: help; }
.cal-dot.big { width: 13px; height: 13px; top: 6px;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--k) 22%, transparent); }
.cal-axis { position: relative; height: 16px; }
.cal-axis span { position: absolute; transform: translateX(-50%); font-size: var(--size-2xs);
  color: var(--text-faint); font-variant-numeric: tabular-nums; }

/* El chip activo de los selectores. */
.chip.on { background: var(--surface); color: var(--text); border-color: var(--line-strong); }

/* --- Las cajitas de datos del terminal (2026-10-03) -------------------------
 *
 * Una cajita es **un dato** elegido de una lista buscable, no un widget: puede
 * haber varias del mismo tipo —tres monedas son tres cajitas— y caben donde
 * quepan. De ahí la rejilla automática en vez de columnas fijas: con doce
 * cajitas en una pantalla ancha salen cuatro filas de tres, y en un móvil una
 * columna, sin reglas por tamaño.
 */
.tiles { display: grid; gap: var(--s3); margin-bottom: var(--s4);
  grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); }
.tile { position: relative; background: var(--surface); border: 1px solid var(--line);
  border-radius: 8px; padding: var(--s3); min-width: 0; }
.tile-label { font-size: var(--size-2xs); color: var(--text-faint);
  text-transform: uppercase; letter-spacing: .06em; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis; padding-right: 14px; }
.tile-value { font-size: var(--size-lg); font-variant-numeric: tabular-nums;
  line-height: 1.2; margin-top: 3px; white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; }
.tile-value a { color: inherit; text-decoration: none; }
.tile-value a:hover { color: var(--accent); }
/* La misma cifra en la otra unidad (2026-10-15): «un poco mas pequeña a su
   derecha del precio en dolares». Al lado y en gris, así que no compite con el
   total; con `nowrap` en el padre, si no cabe se corta antes el aparte que la
   cifra, que es el orden correcto de pérdidas. */
.tile-aside { font-size: .56em; font-weight: 500; color: var(--text-muted);
  margin-left: .45em; letter-spacing: 0; }
/* **Y la cifra de al lado se reacomoda en vez de cortarse** (2026-10-15):
   «cuando se hace mas pequeño corta lo de btc y pone ..., ese comportamiento
   no es correcto, tiene que reescalar». `.tile-value` lleva `nowrap` y puntos
   suspensivos —que es lo correcto para un título largo— y con el aparte al
   lado lo que se comía era la otra unidad. Con aparte, la caja puede partir en
   dos líneas; y en una pieza estrecha el aparte baja solo. */
.tile-value:has(.tile-aside) { white-space: normal; }
.tile-aside { display: inline-block; white-space: nowrap; }
@container pieza (max-width: 300px) {
  .tile-aside { display: block; margin-left: 0; font-size: .62em; }
}
.tile-note { display: flex; gap: 6px; align-items: baseline; margin-top: 2px;
  font-size: var(--size-2xs); }
.tile-note .right { margin-left: auto; }
/* La equis aparece al pasar por encima y **se queda visible con el teclado**:
   con `display:none` no se podría quitar una cajita sin ratón. */
.tile-x { position: absolute; top: 5px; right: 7px; font-size: 11px;
  color: var(--text-faint); text-decoration: none; opacity: 0;
  transition: opacity .12s ease; }
.tile:hover .tile-x, .tile-x:focus-visible { opacity: 1; }
.tile-x:hover { color: var(--danger); }
@media (hover: none) { .tile-x { opacity: .6; } }

.tile-search { display: flex; gap: var(--s2); align-items: center; flex: 1 1 320px; }
.tile-search input { flex: 1 1 auto; min-width: 140px; background: var(--bg);
  color: var(--text); border: 1px solid var(--line); border-radius: 999px;
  padding: 4px var(--s3); font-size: var(--size-xs); font-family: inherit; }
.tile-search input:focus { outline: none; border-color: var(--accent); }

/* --- El filtro lateral del calendario (2026-10-03) --------------------------
 *
 * Pedido con una referencia concreta: el de CoinMarketCal. Dos cosas lo hacen
 * distinto de una fila de botones, y las dos son del lado del contenido y no
 * del CSS: cada opción lleva su recuento, y las que valen cero no se ofrecen.
 *
 * Son enlaces y no casillas con script: el filtro acaba en la URL, así que se
 * puede enlazar y funciona sin JavaScript. En pantalla estrecha el panel pasa
 * arriba y las opciones se ponen en fila, porque una columna de veinte filtros
 * en un móvil es scroll antes de ver un solo dato.
 */
.cal-layout { display: grid; grid-template-columns: 190px minmax(0, 1fr); gap: var(--s5); }
.cal-main { min-width: 0; }
.cal-filters { display: flex; flex-direction: column; gap: var(--s4); }
.cal-filter-group { display: flex; flex-direction: column; gap: 2px; }
.cal-filter-group .eyebrow { margin-bottom: 4px; }
.cal-filter { display: flex; align-items: center; gap: 6px; padding: 3px var(--s2);
  border-radius: 5px; color: var(--text-muted); text-decoration: none;
  font-size: var(--size-xs); }
.cal-filter:hover { background: var(--surface); color: var(--text); }
.cal-filter.on { background: var(--surface); color: var(--text); font-weight: 500;
  box-shadow: inset 2px 0 0 var(--accent); }
.cal-filter .n { margin-left: auto; color: var(--text-faint);
  font-variant-numeric: tabular-nums; font-size: var(--size-2xs); }
.cal-filter i { width: 7px; height: 7px; border-radius: 50%; background: var(--k, var(--line-strong));
  flex: none; }

@media (max-width: 900px) {
  .cal-layout { grid-template-columns: minmax(0, 1fr); }
  .cal-filters { flex-direction: row; flex-wrap: wrap; gap: var(--s3); }
  .cal-filter-group { flex-direction: row; flex-wrap: wrap; align-items: center; }
  .cal-filter-group .eyebrow { margin: 0 var(--s2) 0 0; }
}

/* --- El botón de añadir, arriba del terminal (2026-10-03) -------------------
 *
 * Estaba al final de la página, debajo de diez widgets: para poner una pieza
 * había que bajar hasta el fondo. Ahora arriba, y como `<details>` en vez de un
 * menú con JavaScript — se abre y se cierra solo, y funciona con el script
 * caído.
 */
.board-top { display: flex; align-items: center; gap: var(--s3); margin-bottom: var(--s3); }
.add-menu { position: relative; }
.add-menu > summary { cursor: pointer; list-style: none; display: inline-flex;
  align-items: center; gap: 6px; }
.add-menu > summary::-webkit-details-marker { display: none; }
.add-menu[open] > summary { background: var(--surface-hover); }
.add-menu-panel { position: absolute; top: calc(100% + 6px); left: 0; z-index: 50;
  width: max-content; max-width: min(46ch, 88vw);
  background: var(--bg-elevated); border: 1px solid var(--line-strong);
  border-radius: 8px; padding: var(--s3); box-shadow: 0 10px 30px rgb(0 0 0 / 45%); }
.add-menu-panel .eyebrow { margin-bottom: var(--s2); }

/* ======================================================================
   EL TERMINAL: rejilla arrastrable, con modo lectura y modo edición
   ======================================================================
   Pedido así el 2026-10-03: «son mucho clicks, recargaas de pagina y es muy
   tedioso… que puedas completamente mover las cajas al buelo arrastrandolas,
   cambiar el sitio, el tamaño».

   **El reparto de trabajo con la librería.** gridstack pone el posicionado
   —`position: absolute` y `calc()` sobre las variables `--gs-x/y/w/h`— y esta
   hoja pone el aspecto. No se redefine nada de lo suyo: cuando se actualice la
   librería, lo que cambia es el posicionado y esto sigue valiendo.

   Y lo importante: **las variables las emite el servidor**, así que la rejilla
   sale colocada sin JavaScript y sin salto al cargar. */

/* El hueco entre piezas lo pone la librería con sus márgenes; aquí solo se
   evita que la rejilla se pegue al borde de la página. */
.grid-stack { margin: 0 calc(-1 * var(--s2)); min-height: 200px; }

/* Una pieza llena su hueco **y recorta por dentro**. Sin el `min-height: 0` del
   cuerpo, una tabla de 150 filas estira la pieza y rompe la rejilla: el scroll
   tiene que estar dentro de la pieza, no en la página. */
.grid-stack-item-content { overflow: visible; display: flex; }
/* **`min-width: 0`, y no es un detalle** (2026-10-12). Un hijo de un `flex`
   trae `min-width: auto`, que significa «nunca más estrecho que tu contenido»:
   medido en un móvil de 390 px, la pieza medía 366 y su cuerpo **385**, así que
   la tabla de historias se salía 19 px por la derecha de su propia tarjeta y la
   columna de la hora quedaba cortada — sin barra de desplazamiento, porque el
   cuerpo no había desbordado, había crecido. Con esto el cuerpo se queda en el
   ancho de la tarjeta y el `overflow: auto` que ya tenía hace su trabajo. */
.grid-stack-item-content > .widget { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column;
  min-height: 0; margin: 0; }
.grid-stack-item-content > .widget > .body { flex: 1 1 auto; min-height: 0; overflow: auto;
  display: flex; flex-direction: column; }

/* --- Modo lectura ---------------------------------------------------------
   Sin asas, sin bordes de arrastre, sin nada que distraiga de los datos: es
   para lo que se entra. Un panel siempre editable se desordena solo al intentar
   seleccionar un número. */
.grid-stack-static .grid-stack-item > .ui-resizable-handle { display: none; }

/* --- Modo edición ---------------------------------------------------------
   Tiene que **verse** que se ha entrado, o la persona no sabe que ya puede
   arrastrar y se queda pulsando. De ahí el contorno discontinuo en todas las
   piezas y el cursor de agarre en la cabecera. */
.board-editing .grid-stack-item-content > .widget {
  outline: 1px dashed color-mix(in srgb, var(--accent) 55%, transparent);
  outline-offset: 2px; }
.board-editing .grid-stack-item-content > .widget > header { cursor: grab; }
.board-editing .grid-stack-item-content > .widget > header:active { cursor: grabbing; }
/* En edición el contenido no se puede seleccionar: arrastrar por la cabecera
   seleccionaría media tabla por el camino. */
.board-editing .grid-stack-item-content { user-select: none; }

/* El sitio donde va a caer la pieza. La librería lo marca con esta clase; aquí
   se le da un color que se ve sobre el fondo oscuro. */
.grid-stack-placeholder > .placeholder-content {
  border: 1px dashed var(--accent); border-radius: var(--radius);
  background: color-mix(in srgb, var(--accent) 8%, transparent); }

/* Las asas de redimensionar. Las de la librería son transparentes de serie, así
   que no se encuentran: una esquina que no se ve es una esquina que no existe. */
/* **Las esquinas sin la rotación de la librería.** Ella les da 45 grados para
   que su flecha apunte en diagonal; al sustituir la flecha por un cuadrado, esa
   rotación lo convertía en un rombo cian que parecía un adorno roto. Visto en
   una captura, no leyendo el CSS. */
.board-editing .ui-resizable-se, .board-editing .ui-resizable-sw {
  width: 14px; height: 14px; background: var(--accent); opacity: .8;
  border-radius: 4px; z-index: 30; transform: none; background-image: none; }
.board-editing .ui-resizable-se { right: 2px; bottom: 2px; cursor: nwse-resize; }
.board-editing .ui-resizable-sw { left: 2px; bottom: 2px; cursor: nesw-resize; }
.board-editing .ui-resizable-e, .board-editing .ui-resizable-w {
  width: 8px; top: 20%; height: 60%; background: var(--accent); opacity: .35;
  border-radius: 4px; cursor: ew-resize; }
.board-editing .ui-resizable-e { right: 0; }
.board-editing .ui-resizable-w { left: 0; }
.board-editing .ui-resizable-s { height: 8px; left: 20%; width: 60%; bottom: 0;
  background: var(--accent); opacity: .35; border-radius: 4px; cursor: ns-resize; }
.board-editing .ui-resizable-handle:hover { opacity: 1; }

/* La ✕ de quitar, **solo en edición**: en lectura, un botón de borrar al lado
   de cada título es un accidente esperando a pasar.

   Y en edición las herramientas de la cabecera se ven **siempre**. De serie
   están a `opacity: 0` hasta que el ratón pasa por encima, que está bien para
   leer; pero quien acaba de pulsar «Customise» tiene que ver lo que puede
   hacer, no descubrirlo tanteando. Es el mismo criterio que las asas. */
.board-editing .widget > header .tools { opacity: 1; }
.widget-x { display: none; }
.board-editing .widget-x { display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border: 0; border-radius: 50%; cursor: pointer;
  background: color-mix(in srgb, var(--down) 18%, transparent); color: var(--down);
  font-size: 13px; line-height: 1; }
.board-editing .widget-x:hover { background: var(--down); color: #fff; }

/* --- Las herramientas del tablero, en la tira de arriba -------------------
 *
 * Pedido el 2026-10-14: «boton cutomise y arriba en el top de la pagina y
 * reset layout tambien pero sol otiene que aparecer cuadno se esta
 * customizando». Estaban dentro de la página, así que al bajar a mirar un
 * panel se perdían de vista — y es justo cuando se buscan.
 */
.board-tools { display: inline-flex; align-items: center; gap: var(--s2); }
.board-state { font-size: var(--size-2xs); color: var(--text-muted); }
.board-state[data-board-state=error] { color: var(--down); }
.board-reset { font-size: var(--size-2xs); }
.board-reset[hidden] { display: none; }

/* --- «Add a box» ----------------------------------------------------------
 *
 * Pedido el 2026-10-14: «ahi tenemos que cambir las forma de añair porque me
 * sigue pareciendo poco intuitiva y poco visual, poco interactica, debemos
 * encontrar otras opciones para que ese apartado de customizar tenga mucho mas
 * stilo, conservando la sencillez».
 *
 * **Lo que era.** Una fila de botones «+ Nombre», todos iguales, más otra fila
 * aparte para las cifras: dos sitios donde añadir y ocho palabras que leer.
 *
 * **Lo que es.** Una tira de puertas con dibujo y, debajo, tarjetas de lo que
 * esa puerta tiene. El dibujo se reconoce antes de leerse, que es lo que hace
 * falta cuando se elige; y la acción sigue siendo una sola, pulsar, que es la
 * sencillez que había que conservar.
 */
.board-tray { border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--bg-elevated); padding: var(--s3) var(--s4) var(--s4);
  margin-bottom: var(--s4); }
.board-tray[hidden] { display: none; }

.tray-head { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap;
  padding-bottom: var(--s3); border-bottom: 1px solid var(--line); }
.tray-t { font-size: var(--size-md); }
.tray-tip { font-size: var(--size-2xs); margin-left: auto; }
.tray-q { position: relative; display: inline-flex; align-items: center; flex: 1 1 240px;
  max-width: 420px; }
.tray-qi { position: absolute; left: 10px; display: inline-flex; color: var(--text-faint);
  pointer-events: none; }
.tray-q input[type=search] { width: 100%; padding: 7px 12px 7px 34px; }

/* Las puertas. Pulsada se marca con el acento y no sólo con el borde: en una
   tira de cinco, un borde de un píxel no dice cuál está abierta. */
.tray-doors { display: flex; flex-wrap: wrap; gap: var(--s2); margin: var(--s3) 0; }
.door { display: inline-flex; align-items: center; gap: 7px; padding: 7px 13px;
  border: 1px solid var(--line); border-radius: 999px; background: var(--surface);
  color: var(--text-muted); font: inherit; font-size: var(--size-xs); cursor: pointer;
  transition: border-color .12s ease, color .12s ease, background .12s ease; }
.door:hover { border-color: var(--line-strong); color: var(--text); }
.door-i { display: inline-flex; color: var(--text-faint); }
.door:hover .door-i { color: var(--text-muted); }
.door.on { border-color: var(--accent); color: var(--text);
  background: color-mix(in srgb, var(--accent) 12%, transparent); }
.door.on .door-i { color: var(--accent); }

/* Las tarjetas. Rejilla que se adapta sola: con ocho opciones y una ventana
   estrecha, tres columnas fijas dejarían tarjetas de 90 píxeles. */
.tray-grid { display: grid; gap: var(--s2);
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); }
.tray-empty { grid-column: 1 / -1; font-size: var(--size-2xs); margin: var(--s2) 0 0; }

.addcard { display: flex; align-items: flex-start; gap: var(--s3); width: 100%;
  padding: var(--s3); text-align: left; cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); color: var(--text); font: inherit;
  transition: border-color .12s ease, transform .12s ease, background .12s ease; }
.addcard:hover { border-color: var(--accent); transform: translateY(-1px);
  background: var(--bg-elevated); }
.addcard:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.addcard[disabled] { opacity: .6; cursor: progress; }
/* **Mientras carga, la tarjeta sigue siendo ella** (2026-10-15). El guion le
   ponía «…» como único contenido, así que perdía el dibujo y el nombre; y si la
   bandeja no se repintaba —lo que pasaba en toda vista que no fuera «Panels»—
   se quedaba así. Ahora el estado es una clase y lo pinta la hoja. */
.addcard.cargando .addcard-p { color: transparent; position: relative; }
.addcard.cargando .addcard-p::after {
  content: "…"; position: absolute; inset: 0; display: grid; place-items: center;
  color: var(--text-muted);
}
.addcard.fallo { border-color: var(--down); }
.addcard.fallo .addcard-p { color: var(--down); }
.addcard.fallo .addcard-h::after { content: " — could not add, try again"; color: var(--down); }
.addcard-i { display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; flex: none; border-radius: 8px;
  background: color-mix(in srgb, var(--accent) 12%, transparent); color: var(--accent); }
.addcard-b { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.addcard-b b { font-size: var(--size-sm); }
/* Dos líneas y corte: la pista sale del mismo `info` que cuenta la «i», que
   puede tener noventa palabras. La bandeja no es el sitio para leerlas. */
.addcard-h { font-size: var(--size-2xs); color: var(--text-muted); line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; }
.addcard-p { margin-left: auto; flex: none; color: var(--text-faint); font-size: 18px;
  line-height: 1; }
.addcard:hover .addcard-p { color: var(--accent); }

.board-where[hidden] { display: none; }

/* En el móvil la rejilla es de una columna y arrastrar sobra: lo que se quiere
   ahí es leer. El botón sigue estando para quitar y reordenar. */
@media (max-width: 700px) {
  .grid-stack { margin: 0; }
  .board-editing .ui-resizable-e, .board-editing .ui-resizable-w,
  .board-editing .ui-resizable-s { display: none; }
}

/* --- Cada pieza responde a SU tamaño, no al de la ventana -----------------
   Pedido así: «todos los widget han de ser responsitive segun su tamano y que
   el contenido no se superponga».

   **Consultas de contenedor y no de ventana, y la diferencia es el fondo del
   asunto.** En un tablero que se coloca a mano, el tamaño de la ventana no dice
   nada: la misma pantalla de 1600 píxeles puede tener el mercado a doce
   columnas o a tres. Lo que decide si una tabla de doce columnas cabe es
   **el ancho de su pieza**, y eso solo lo sabe un `@container`.

   El orden en que desaparecen las columnas no es casual: primero lo accesorio
   —la curva, los sucesos, el volumen—, después lo contextual —capitalización,
   rango, 7 d—, y al final quedan **moneda, precio y 24 h**, que es lo mínimo
   para que la tabla siga diciendo algo. Por debajo de eso no se encoge: el
   mínimo de la pieza lo impide (`gs-min-w`), que es la otra mitad de lo pedido
   —«no mas de que no se pueda ver nada por su superposicion»—. */
/* `size` y no `inline-size`: **`inline-size` solo mide el ancho**, así que las
   consultas por alto no disparaban nunca y una cajita de dos filas enseñaba lo
   mismo que una de seis. Lo vi midiendo las tres a la vez, no leyendo el CSS.
   `size` exige que el elemento no dependa de su contenido para medir, y eso se
   cumple: la rejilla le da alto y ancho explícitos a cada pieza. */
.grid-stack-item-content { container-type: size; container-name: pieza; }

/* **La tabla de historias suelta columnas al estrecharse**, igual que la de
   mercado y por lo mismo: en 366 px, cuatro columnas dejan el titular partido
   en una palabra por línea, que es ilegible. Primero se va la cobertura —los
   logos de los medios son contexto— y después la hora. Lo último que queda es
   la nota y el titular, que es lo que la pieza viene a decir. */
@container pieza (max-width: 420px) {
  .w-stories th.wst-cov, .w-stories td.wst-cov { display: none; }
}
/* **Entre 330 y 420 px la hora parte en dos líneas** (2026-10-13), y esto es
   lo que quitaba la última barra horizontal del terminal. Medido a 390 px: la
   celda tenía 74 px asignados y 100 px de contenido —«Oct 13, 05:48 AM» con
   `white-space: nowrap`—, así que la tabla no podía bajar de 381 px dentro de
   una caja de 348 y el panel sacaba barra.
   La regla de la casa es que lo que no cabe se reduce, nunca se desplaza: dos
   líneas de fecha caben en 74 px y una no. */
.w-stories td.wst-time { white-space: nowrap; }
@container pieza (max-width: 420px) {
  .w-stories td.wst-time { white-space: normal; }
}
@container pieza (max-width: 330px) {
  .w-stories th.wst-time, .w-stories td.wst-time { display: none; }
}

@container pieza (max-width: 760px) {
  table.w-mkt .spark, table.w-mkt .ev { display: none; }
}
@container pieza (max-width: 640px) {
  table.w-mkt .vol, table.w-mkt .c-1h { display: none; }
}
@container pieza (max-width: 520px) {
  table.w-mkt .cap, table.w-mkt .range-cell { display: none; }
}
@container pieza (max-width: 420px) {
  table.w-mkt .own, table.w-mkt .c-7d { display: none; }
  /* La barra de pestañas se parte en dos líneas en vez de apretar el buscador
     hasta que no quepa una palabra. */
  .w-tabs { flex-wrap: wrap; }
  .w-mkt-q { margin-left: 0; flex: 1 1 100%; max-width: none; }
}

/* Las demás piezas: lo que se esconde es lo que acompaña, nunca el dato.
   Una fecha o un recuento sin su etiqueta siguen leyéndose; el titular sin
   fecha, no. */
@container pieza (max-width: 440px) {
  .w-hide-narrow { display: none; }
  .widget .body table td, .widget .body table th { padding-left: 6px; padding-right: 6px; }
}

/* Y el freno de verdad contra la superposición: una tabla nunca empuja a su
   pieza. Si no cabe, se desplaza dentro; el que manda es el tablero. */
.grid-stack-item-content > .widget > .body { overflow: auto; }
.grid-stack-item-content > .widget > .body > table { min-width: 0; }

/* --- La cajita de datos, que enseña más cuanto más grande es -------------
   Pedido así: «cuando mas grande las haces mas informacion deberian mostrar, y
   cuando mas pequeñas pues menos, terminando por la mas basica».

   **Se sirve todo y se esconde por el tamaño de la pieza**, con `@container`.
   De pequeña a grande: la cifra sola → la cifra con su variación → con el
   gráfico → con el nombre largo → con capitalización, volumen y puesto. Lo
   último en irse es la cifra, que es lo que la cajita viene a decir.

   El orden en que desaparecen no es casual: primero lo que contextualiza
   (puesto, volumen), después lo que adorna (nombre), después la tendencia, y
   al final queda el dato. */
.tile-widget > .tile-body { display: flex; flex-direction: column; justify-content: center;
  gap: 2px; padding: var(--s3); overflow: hidden; }
/* **Y con la especificidad suficiente para ganar.** `overflow: hidden` estaba
   escrito arriba y no se aplicaba: `.grid-stack-item-content > .widget > .body`
   pesa tres clases y `.tile-widget > .tile-body` solo dos, así que la cajita
   heredaba el `overflow: auto` pensado para los paneles con tabla. Medido con
   la cajita de inflación a dos columnas de ancho: el cuerpo pedía 239 px en
   181, con barra horizontal — justo lo que el usuario volvió a ver.

   Una cajita nunca lleva barra horizontal: lo que no cabe se encoge o se va,
   y de eso se encargan las reglas de contenedor de más abajo. */
.grid-stack-item-content > .widget > .tile-body { overflow-x: hidden; overflow-y: auto; }
.tile-widget .tile-logo { border-radius: 50%; flex: 0 0 auto; }
.tile-widget .tile-main { display: flex; align-items: baseline; gap: var(--s2); flex-wrap: wrap; }
.tile-widget .tile-value { font-size: clamp(var(--size-md), 13cqi, 40px); font-weight: 650;
  line-height: 1.05; white-space: nowrap; }
/* Con la cifra en otra unidad al lado, la caja **puede** partir en dos líneas:
   esta regla gana a la de arriba por especificidad y es la que evita que «0.80
   BTC» acabe en puntos suspensivos. Medido el 2026-10-15 en el navegador. */
.tile-widget .tile-value:has(.tile-aside) { white-space: normal; }
.tile-widget .tile-value a { color: var(--text); text-decoration: none; }
.tile-widget .tile-value a:hover { color: var(--accent); }
/* La cifra y su signo no se parten; la unidad sí, y por eso va aparte. En la
   cajita de inflación la unidad es «Index 1982-1984=100» — diecinueve
   caracteres que, sin permiso para pasar de línea, fijaban un ancho mínimo
   mayor que la cajita entera. */
.tile-widget .tile-change { font-size: var(--size-sm); font-weight: 600;
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 0 5px; min-width: 0; }
.tile-widget .tile-change > b { white-space: nowrap; font-weight: inherit; }
.tile-widget .tile-unit { font-style: normal; font-weight: 500; color: var(--text-faint);
  font-size: var(--size-2xs); min-width: 0; overflow-wrap: anywhere; }
.tile-widget .tile-chart { margin-top: 4px; line-height: 0; }
.tile-widget .tile-chart svg { width: 100%; height: auto; }
.tile-widget .tile-name { font-size: var(--size-2xs); color: var(--text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tile-widget .tile-extra { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s3);
  margin-top: 4px; font-size: var(--size-2xs); color: var(--text-muted); }
.tile-widget .tile-extra i { font-style: normal; opacity: .65; margin-right: 3px; }

/* El plazo del porcentaje grande: pegado a él, más pequeño y apagado. Es una
   unidad, no un dato, y tiene que leerse como tal. */
.tile-widget .tile-change .tile-span-of { font-style: normal; font-weight: 500;
  font-size: var(--size-2xs); color: var(--text-faint); margin-left: 2px; }

/* Los demás plazos. Van **antes** que capitalización y volumen en el orden de
   lo que sobrevive al encoger: a quien sigue una moneda le dice más «7 d
   -12 %» que su puesto en la tabla. */
.tile-widget .tile-spans { display: flex; flex-wrap: wrap; gap: var(--s1) var(--s3);
  margin-top: 3px; font-size: var(--size-2xs); color: var(--text-muted); }
.tile-widget .tile-spans i { font-style: normal; opacity: .65; margin-right: 3px; }
.tile-widget .tile-spans b { font-weight: 600; font-variant-numeric: tabular-nums; }
.tile-widget .tile-age { font-size: var(--size-2xs); color: var(--text-muted); opacity: .7;
  margin-top: 2px; }
.tile-widget .tile-note { font-size: var(--size-2xs); color: var(--text-muted); }

/* Lo que se esconde al encoger, en este orden. Las medidas son del **alto** de
   la pieza porque es lo que escasea: una cajita de dos filas no tiene sitio
   para un gráfico por mucho que sea ancha. */
/* **Los escalones salen de los altos que la rejilla puede dar**, no de números
   redondos: una fila son 72 píxeles, así que una pieza mide 144, 216, 288, 360…
   Poner los cortes entre esos valores es lo que hace que cada fila que añades
   traiga algo. La primera versión los puse a ojo y la cajita de cuatro filas
   enseñaba lo mismo que la de seis, que es no haber hecho nada. */
@container pieza (max-height: 330px) {   /* menos de 5 filas */
  .tile-widget .tile-extra { display: none; }
}
/* Y cuando hay sitio de sobra, el contenido se reparte en vez de amontonarse en
   el centro: centrado, una cajita de seis filas deja dos huecos grandes arriba y
   abajo y parece a medio hacer. */
@container pieza (min-height: 331px) {
  .tile-widget > .tile-body { justify-content: space-between; }
  .tile-widget .tile-chart { margin: var(--s3) 0; }
}
@container pieza (max-height: 260px) {   /* menos de 4 filas */
  .tile-widget .tile-name, .tile-widget .tile-age { display: none; }
}
@container pieza (max-height: 190px) {   /* menos de 3 filas */
  .tile-widget .tile-chart { display: none; }
  /* Y los plazos se van con el gráfico, no antes: los dos dicen «qué ha hecho
     esto últimamente» y dejar uno sin el otro es media respuesta. */
  .tile-widget .tile-spans { display: none; }
}
@container pieza (max-height: 110px) {
  /* La más básica: la cifra y nada más. Por debajo de esto no se encoge —el
     mínimo de la pieza lo impide—, que es lo que evita la cajita ilegible. */
  .tile-widget .tile-change { display: none; }
  .tile-widget > .tile-body { padding: var(--s2) var(--s3); }
}
/* Y estrecha: la variación baja a su propia línea en vez de apretar la cifra. */
@container pieza (max-width: 150px) {
  .tile-widget .tile-main { flex-direction: column; gap: 0; align-items: flex-start; }
  .tile-widget .tile-extra span:nth-child(n+3) { display: none; }
  .tile-widget .tile-spans span:nth-child(n+3) { display: none; }
}

/* --- La barra de la izquierda, plegable ----------------------------------
   Pedido así: «quiero que la barra de la izquierda se pueda ocultar para que
   queda mas amplia la zona de la derecha como hace WP».

   **Recogida y no escondida**, que es lo que hace WordPress y es mejor: los
   iconos se quedan, así que sigues sabiendo dónde está cada cosa y puedes
   navegar sin desplegarla. Esconderla del todo obliga a desplegarla para cada
   salto, y entonces el espacio ganado se paga con un clic cada vez. */
.side-top { display: flex; align-items: center; gap: var(--s2); }
.side-top .wordmark { flex: 1 1 auto; min-width: 0; overflow: hidden; white-space: nowrap; }
.side-toggle-form { margin: 0; display: flex; }
.side-toggle { background: none; border: 0; cursor: pointer; color: var(--text-muted);
  font-size: 14px; line-height: 1; padding: 6px 7px; border-radius: var(--radius-sm, 6px); }
.side-toggle:hover { color: var(--text); background: var(--surface-hover, var(--surface)); }
.side-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* Recogida: solo iconos. El ancho es el justo para que el icono quede centrado
   y el objetivo del ratón siga siendo cómodo. */
.shell.side-closed { grid-template-columns: 56px minmax(0, 1fr); }
.shell.side-closed .side-name,
.shell.side-closed .side nav a span:not(.ico),
.shell.side-closed .side .eyebrow,
/* `.group` son los rótulos «Context» y «Yours». Se me escaparon en la primera
   versión —escondí `.eyebrow`, que es otra clase— y recogida quedaban cortados
   a media palabra, que se lee como una página rota. Lo vi en una captura, no
   leyendo el CSS. En su lugar va una línea de separación, que hace el mismo
   trabajo de agrupar sin necesitar sitio. */
.shell.side-closed .side .group,
.shell.side-closed .side .foot { display: none; }
.shell.side-closed .side nav + nav { border-top: 1px solid var(--line); padding-top: var(--s2); margin-top: var(--s2); }
.shell.side-closed .side nav a { justify-content: center; padding-left: 0; padding-right: 0; }
.shell.side-closed .side .wordmark { padding-left: 0; padding-right: 0; text-align: center; }
.shell.side-closed .side-top { flex-direction: column; gap: 4px; }

/* El nombre de cada sección, al pasar el ratón, porque un icono solo no siempre
   basta —y aquí hay trece—. Es CSS y no un `title`, que tarda un segundo largo
   en salir y no se puede estilar. */
.shell.side-closed .side nav a { position: relative; }
.shell.side-closed .side nav a::after {
  content: attr(data-label); position: absolute; left: calc(100% + 6px); top: 50%;
  transform: translateY(-50%); background: var(--bg-elevated); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--radius-sm, 6px);
  padding: 4px 8px; font-size: var(--size-2xs); white-space: nowrap;
  opacity: 0; pointer-events: none; transition: opacity .1s; z-index: 80; }
.shell.side-closed .side nav a:hover::after,
.shell.side-closed .side nav a:focus-visible::after { opacity: 1; }

/* **Y el contenido se queda de verdad con el sitio que gana**, que es para lo
   que se recoge la barra. Sin esto, recogerla liberaba 160 píxeles y el
   contenido solo crecía 36: el tope de `.wrap.wide` se comía el resto, y la
   función no hacía lo que promete. Medido antes de darla por buena.

   **Solo en las páginas anchas** —terminal, mercados—, no en las de texto: ahí
   el tope no es un descuido, es lo que hace que una línea se pueda leer, y
   ensanchar prosa a mil cuatrocientos píxeles la empeora. Quien recoge el menú
   en una página de texto gana margen, no líneas más largas. */
.shell.side-closed .wrap.wide { max-width: none; }

/* En el móvil la barra ya tiene su propio comportamiento: no se toca. */
@media (max-width: 860px) {
  .shell.side-closed { grid-template-columns: 1fr; }
  .shell.side-closed .side-name,
  .shell.side-closed .side nav a span:not(.ico) { display: inline; }
  .shell.side-closed .side nav a::after { content: none; }
}

/* ======================================================================
   LA PORTADA (2026-10-09)
   ======================================================================
   Pedida «bonita que agrade como primera visita». La regla que la gobierna es
   enseñar en vez de prometer: lo que sale son las historias de verdad de este
   momento y los recuentos reales, así que si el motor se parase, la página se
   quedaría visiblemente vacía. Eso es correcto — una portada que sigue
   presumiendo con el motor parado es una portada que miente. */
.hero .kicker { text-transform: uppercase; letter-spacing: .12em; font-size: var(--size-2xs);
  color: var(--accent); font-weight: 600; margin-bottom: var(--s3); }
.hero-cta { display: flex; gap: var(--s3); flex-wrap: wrap; margin-top: var(--s5); }
.hero-note { font-size: var(--size-xs); color: var(--text-muted); margin-top: var(--s4); }
.btn.lg { padding: 11px 22px; font-size: var(--size-sm); }

.section-head { display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s3); margin-bottom: var(--s4); }
.section-quiet { background: var(--bg-elevated); border-block: 1px solid var(--line); }
.section-cta { padding-block: var(--s8); }

/* Las historias de la portada: una fila por historia, con su nota a la
   izquierda. Es la misma lectura que la lista de verdad, para que pasar de la
   portada a la sección no sea aprender otra pantalla. */
.landing-stories { display: flex; flex-direction: column; gap: 1px;
  border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.landing-story { display: flex; align-items: flex-start; gap: var(--s3);
  padding: var(--s3) var(--s4); background: var(--surface); text-decoration: none;
  color: var(--text); transition: background .12s; }
.landing-story:hover { background: var(--surface-hover, var(--bg-elevated)); text-decoration: none; }
.landing-story-body { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.landing-story-body b { font-weight: 600; line-height: 1.35; }
.landing-story-meta { font-size: var(--size-2xs); color: var(--text-muted); }

.grid.three { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--s4); }
.grid.two { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s6); }
.card.tall { display: flex; flex-direction: column; gap: var(--s2); }
.card.tall p { color: var(--text-muted); font-size: var(--size-sm); flex: 1 1 auto; }

/* El manifiesto: cuatro reglas, y las cuatro comprobables en el sitio. No son
   valores de marca; son cosas que se pueden verificar en una página. */
.manifesto { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s4); margin-top: var(--s5); }
.manifesto > div { border-left: 2px solid var(--accent); padding-left: var(--s3);
  font-size: var(--size-sm); color: var(--text-muted); }
.manifesto b { color: var(--text); display: block; margin-bottom: 2px; }

.steps { margin: var(--s4) 0; padding-left: 0; list-style: none; counter-reset: paso; }
.steps li { position: relative; padding-left: 34px; margin-bottom: var(--s3);
  font-size: var(--size-sm); color: var(--text-muted); counter-increment: paso; }
.steps li::before { content: counter(paso); position: absolute; left: 0; top: 0;
  width: 22px; height: 22px; border-radius: 50%; background: var(--bg-elevated);
  border: 1px solid var(--line-strong); color: var(--accent);
  display: grid; place-items: center; font-size: var(--size-2xs); font-weight: 700; }
.steps b { color: var(--text); }

table.compare td:first-child { color: var(--text-muted); }
table.compare .yes { color: var(--up); font-size: 15px; }
table.compare .no { color: var(--line-strong); }

@media (max-width: 900px) {
  .grid.three, .grid.two, .manifesto { grid-template-columns: 1fr; }
}

/* El héroe en dos columnas: el texto a la izquierda y **dato real** a la
   derecha. Ese hueco con una ilustración diría «esto es una idea»; con la
   tabla de mercado dice «esto está funcionando», y además enseña la columna
   «own», que es justo lo que el titular promete. */
.hero-grid { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
  gap: var(--s7); align-items: center; }
.hero-card { border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); overflow: hidden; }
.hero-card-head { display: flex; align-items: baseline; justify-content: space-between;
  padding: var(--s3) var(--s4); border-bottom: 1px solid var(--line);
  font-size: var(--size-sm); }
.hero-card-foot { display: block; padding: var(--s3) var(--s4);
  border-top: 1px solid var(--line); font-size: var(--size-xs); }
table.hero-mkt { width: 100%; }
table.hero-mkt th { padding: 6px var(--s4); font-size: var(--size-2xs);
  color: var(--text-muted); font-weight: 600; text-align: left; }
table.hero-mkt th.num, table.hero-mkt td.num { text-align: right;
  font-variant-numeric: tabular-nums; }
table.hero-mkt td { padding: 7px var(--s4); font-size: var(--size-xs);
  border-top: 1px solid var(--line); }
table.hero-mkt .coin-wrap { display: inline-flex; align-items: center; gap: 6px; }
table.hero-mkt abbr { text-decoration: none; border-bottom: 1px dotted var(--line-strong); }

@media (max-width: 1000px) {
  .hero-grid { grid-template-columns: 1fr; gap: var(--s5); }
}


/* Un título con su frase de apoyo debajo. Existe porque la forma «obvia» de
   pegarlos —un margen superior negativo en el párrafo— los monta uno encima
   del otro en cuanto el margen del título es menor que el tirón, y eso no se
   ve hasta que alguien mira la página. */
.head-note { margin: var(--s6) 0 var(--s3); }
.head-note h2 { margin: 0 0 4px; }
.head-note > p { margin: 0; font-size: var(--size-xs); max-width: 86ch; }

/* ============================================================
   LA FICHA DE UNA MONEDA
   ============================================================
   El precio grande a la derecha y, debajo, **el exceso**: lo que se movió de
   más que el mercado. Es la única cifra de la página que contesta «¿le pasa
   algo a esta moneda?», y estaba enterrada en una columna de una tabla. */
.asset-head { display: flex; align-items: flex-start; justify-content: space-between;
  gap: var(--s5); flex-wrap: wrap; }
.asset-id { display: flex; align-items: center; gap: var(--s4); min-width: 0; }
.asset-id h1 { margin: 0; font-size: var(--size-2xl); }
.asset-id h1 .muted { font-weight: 500; font-size: var(--size-lg); }
.asset-tags { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap;
  margin-top: 6px; font-size: var(--size-xs); }
.asset-price { text-align: right; }
.asset-price .big { font-size: var(--size-2xl); font-weight: 700;
  font-variant-numeric: tabular-nums; line-height: 1.1; }
.asset-moves { display: flex; gap: var(--s4); justify-content: flex-end;
  margin-top: 4px; font-variant-numeric: tabular-nums; font-weight: 600; }
.asset-moves small { display: block; font-weight: 500; font-size: var(--size-2xs);
  color: var(--text-muted); text-transform: uppercase; letter-spacing: .04em; }
.asset-moves .own { padding-left: var(--s4); border-left: 1px solid var(--line); }

/* Las constantes vitales. Rejilla y no flex para que no bailen cuando una
   cifra crece, que es lo que pasa en cuanto un precio pasa de cuatro dígitos. */
.vitals { display: grid; gap: var(--s3); margin-bottom: var(--s5);
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.vital { border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); padding: var(--s3) var(--s4); display: grid; gap: 2px;
  align-content: start; }
.vital.wide { grid-column: span 2; }
.vital .k { font-size: var(--size-2xs); color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .04em; }
.vital b { font-size: var(--size-lg); font-variant-numeric: tabular-nums; }

/* Dónde ha cerrado dentro del recorrido del día. Un 3 % no dice lo mismo
   acabando en el máximo que acabando en el mínimo tras subir un 8 %. */
.range { display: flex; align-items: center; gap: var(--s2); margin-top: 4px;
  font-size: var(--size-2xs); color: var(--text-muted); }
.range .bar { flex: 1; height: 6px; border-radius: 3px; position: relative;
  background: linear-gradient(90deg, var(--down), var(--line-strong), var(--up)); }
.range .bar i { position: absolute; top: -3px; width: 3px; height: 12px; border-radius: 2px;
  background: var(--text); transform: translateX(-50%); }

.chart-card { margin-bottom: var(--s5); padding-bottom: var(--s3); }
.chart-card .meta { margin-bottom: var(--s3); }
.chart-card .eyebrow { margin: 0; }
.chart-legend { font-size: var(--size-2xs); margin: var(--s2) 0 0; max-width: 92ch; }
svg.chart.big .ax { fill: var(--text-faint); font-size: 11px; }
/* **Y en un móvil, mucho más grandes** (2026-10-13). El SVG se sirve al 100 %
   del ancho con un `viewBox` de 960: a 390 px el dibujo se encoge a un tercio
   **y el texto con él**, así que once píxeles se leían como tres y medio. Lo
   vi en una captura de la cartera y le pasa igual a la ficha de una moneda,
   que lleva meses así. Las unidades son del `viewBox`, no de la pantalla: 26
   aquí son unos nueve píxeles reales a 390. */
@media (max-width: 760px) {
  svg.chart.big .ax { font-size: 26px; }
  svg.chart.big .mvl { font-size: 24px; }
}
svg.chart.big .mvl { font-size: 11px; font-weight: 600; }
/* La marca es un enlace: tiene que parecerlo al pasar por encima. */
svg.chart.big a.mv { cursor: pointer; }
svg.chart.big a.mv:hover circle { r: 6; }
svg.chart.big a.mv:hover line { opacity: 1; }

.upcoming { border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); overflow: hidden; }
.up-row { display: flex; align-items: center; gap: var(--s4);
  padding: var(--s3) var(--s4); border-top: 1px solid var(--line); }
.up-row:first-child { border-top: 0; }
.up-row .when { min-width: 74px; font-variant-numeric: tabular-nums; }
.up-row .when small { display: block; font-size: var(--size-2xs); color: var(--text-muted); }
.up-row .what { flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--s2);
  flex-wrap: wrap; }
.up-row .size { font-variant-numeric: tabular-nums; color: var(--text-muted);
  font-size: var(--size-xs); white-space: nowrap; }

@media (max-width: 760px) {
  .asset-head { flex-direction: column; }
  .asset-price { text-align: left; }
  .asset-moves { justify-content: flex-start; }
  .vital.wide { grid-column: span 1; }
}

/* Un movimiento y lo que se sabía cuando pasó. Era una tabla de cuatro
   columnas con una fila: el formato costaba más de leer que el dato. */
.moves { display: grid; gap: var(--s3); margin-bottom: var(--s5); }
.move { border: 1px solid var(--line); border-left-width: 3px; border-radius: var(--radius);
  background: var(--surface); padding: var(--s3) var(--s4); }
.move.up { border-left-color: var(--up); }
.move.down { border-left-color: var(--down); }
.move-head { display: flex; align-items: baseline; gap: var(--s4); flex-wrap: wrap; }
.move-head .day { font-weight: 600; }
.move-head .pct { font-size: var(--size-lg); font-variant-numeric: tabular-nums; }
.move.up .pct { color: var(--up); } .move.down .pct { color: var(--down); }
.move-head .own { font-size: var(--size-xs); color: var(--text-muted);
  font-variant-numeric: tabular-nums; }
.move-before { margin: var(--s2) 0 0; display: grid; gap: 3px; font-size: var(--size-sm); }
.move-before .k, .move .k { font-size: var(--size-2xs); color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .04em; }
.card.how ul { margin: var(--s2) 0 0; padding-left: var(--s5); display: grid; gap: 6px;
  font-size: var(--size-sm); }

/* La tira de días de «Explain the move». Eran pastillas con una fecha y un
   número: para ver dónde hubo jaleo había que leerlas una a una. En barras,
   el día movido se ve sin leer nada, y la parte hueca —los movimientos sin
   motivo encontrado— es la cifra que de verdad describe el día. */
/* `align-items: stretch` y `height: 100%`, y no `flex-end`. Una altura en
   porcentaje necesita que el padre tenga **altura definida**; con `flex-end`
   cada columna se encogía a su contenido, el porcentaje no resolvía contra
   nada y las once barras salían iguales y de tres píxeles. Se vio en la
   captura, no leyendo el CSS. */
/* ============================================================
   LA TIRA DE DÍAS: TAMAÑO, NO CANTIDAD (2026-10-12)
   ============================================================
   De tres propuestas el usuario eligió ésta. La altura era **cuántos**
   movimientos tuvo el día, que es el peor número posible para una barra: tres
   movimientos pequeños hacían una columna más alta que el salto del 66 % de
   KAIA del día 9. Ahora la altura es cuánto se movió por su cuenta el mayor
   del día, el color dice la dirección, y un punto marca que algo se movió sin
   que nada lo explicara.

   `align-items: stretch` y el envoltorio `.rwrap` no son adorno: con
   `flex-end`, el botón mide lo que mide su contenido y el `height: %` de la
   barra no tiene contra qué resolverse — se queda en cero. Pasó en la maqueta
   y se vio en la captura, no leyendo el CSS. */
.ribbon { display: flex; align-items: stretch; gap: 3px; margin-top: var(--s3);
  height: 92px; }
.rday { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column;
  align-items: center; gap: 4px; border-radius: var(--radius-sm); padding: 3px 0 0;
  text-decoration: none; color: inherit; }
.rwrap { flex: 1 1 auto; width: 100%; display: flex; align-items: flex-end;
  justify-content: center; }
.rbar { width: 100%; max-width: 22px; min-height: 3px; border-radius: 3px 3px 0 0;
  background: var(--up); position: relative; }
.rday.down .rbar { background: var(--down); }
a.rday:hover { background: color-mix(in srgb, var(--accent) 8%, transparent);
  text-decoration: none; }
.rday.on { background: color-mix(in srgb, var(--accent) 18%, transparent); }
.rday.on .rlbl { color: var(--text); font-weight: 600; }
/* El punto de «nada lo explica» va **encima** de la barra y no dentro: dentro
   desaparecía en las barras de tres píxeles, que son justo los días tranquilos
   en los que un movimiento sin causa más llama la atención. */
.rbar .un { position: absolute; left: 50%; top: -8px; transform: translateX(-50%);
  width: 5px; height: 5px; border-radius: 50%; background: var(--hot); }
.rlbl { font-size: var(--size-2xs); color: var(--text-faint);
  font-variant-numeric: tabular-nums; }
/* Un día que falta del archivo no es un día tranquilo. Rayado y sin enlace. */
.rday.gap { cursor: default; }
.rday.gap .rbar { height: 14%; background: repeating-linear-gradient(45deg,
  var(--line-strong), var(--line-strong) 2px, transparent 2px, transparent 5px); }
.rday.gap .rlbl { opacity: .45; }

.daystrip-key { display: flex; gap: var(--s4); align-items: center;
  font-size: var(--size-2xs); margin-top: 6px; }
.daystrip-key .sw { display: inline-block; width: 9px; height: 9px; border-radius: 2px;
  margin-right: 4px; vertical-align: -1px; }
.daystrip-key .sw.up { background: var(--up); }
.daystrip-key .sw.down { background: var(--down); }
.daystrip-key .sw.dot { background: var(--hot); border-radius: 50%; width: 6px; height: 6px; }
.daystrip-key .sw.gap { background: repeating-linear-gradient(45deg,
  var(--line-strong), var(--line-strong) 2px, transparent 2px, transparent 5px); }

a.coin-link { text-decoration: none; color: inherit; display: inline-flex;
  align-items: center; gap: var(--s2); }
a.coin-link:hover b { color: var(--accent); }
.nothing { margin: 0; }

/* El separador de «lo que no estaba en la tabla». Sin él, las filas traídas
   del catálogo aparecen mezcladas con las de siempre y parece que la tabla
   tenía mil filas desde el principio. */
tr.mkt-more td { padding: 6px var(--s4); font-size: var(--size-2xs);
  color: var(--text-muted); text-transform: uppercase; letter-spacing: .04em;
  background: color-mix(in srgb, var(--accent) 8%, transparent);
  border-top: 1px solid var(--line); }

/* ============================================================
   HILOS: LA BRECHA, NO LA PUNTUACIÓN
   ============================================================
   Era una tabla de cinco columnas de números. Lo que ahora se ve es cuánto se
   habla de algo (la barra) frente a cuánto se ha movido su precio (el tope):
   las dos cifras ya existían y solo se publicaba su resta. */
.thr { display: grid; }
.thr-row { display: grid; gap: 4px; padding: var(--s3) var(--s4);
  border-top: 1px solid var(--line); text-decoration: none; color: inherit; }
.thr-row:first-child { border-top: 0; }
.thr-row:hover { background: color-mix(in srgb, var(--accent) 7%, transparent); }
.thr-top { display: flex; align-items: baseline; gap: var(--s2); }
.thr-name { font-size: var(--size-sm); }
.thr-row:hover .thr-name { color: var(--accent); }
.thr-facts { margin-left: auto; font-size: var(--size-2xs); color: var(--text-muted);
  font-variant-numeric: tabular-nums; white-space: nowrap; }
.thr-facts small { font-weight: 400; }
.thr-bar { position: relative; height: 7px; border-radius: 4px;
  background: var(--line); overflow: visible; }
.thr-bar .talk { display: block; height: 100%; border-radius: 4px;
  background: linear-gradient(90deg,
    color-mix(in srgb, var(--accent) 55%, transparent), var(--accent)); }
/* El precio es un tope y no una segunda barra: dos barras se comparan por
   longitud y hay que mirarlas las dos; un tope sobre la barra llena se lee
   solo —la distancia entre el tope y el final **es** la brecha. */
.thr-bar .price { position: absolute; top: -3px; width: 2px; height: 13px;
  border-radius: 1px; background: var(--text); transform: translateX(-50%); }
.thr-bar .price::after { content: ''; position: absolute; left: -3px; top: -4px;
  width: 8px; height: 4px; }
.thr-foot { font-size: var(--size-2xs); }
.thr-foot .warn { color: var(--warn); }

/* ============================================================
   CALENDARIO: UNA AGENDA, NO UNA TABLA
   ============================================================
   La columna de la fecha tenía 72 píxeles y «tomorrow 12:53» no cabe: se
   montaba sobre el título. Agrupando por día, la fecha se escribe una vez y
   la columna que causaba el choque desaparece. */
.agenda { display: grid; }
.ag-day { display: flex; align-items: center; gap: var(--s2);
  padding: var(--s3) var(--s4) 4px; }
.ag-day:first-child { padding-top: var(--s2); }
.ag-when { font-size: var(--size-2xs); font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--text); white-space: nowrap; }
.ag-in { font-size: var(--size-2xs); color: var(--text-faint); white-space: nowrap; }
.ag-rule { flex: 1; height: 1px; background: var(--line); }

/* Es un `<a>` desde el 2026-10-13: antes era un `div` con `:hover` pintado,
   o sea algo que se iluminaba y no llevaba a ningún sitio. `color: inherit` y
   sin subrayado porque el que manda aquí es el color de la clase, y tres
   títulos subrayados seguidos en un panel de 300 px son una reja. */
.ag-row { display: flex; align-items: baseline; gap: var(--s3);
  padding: 5px var(--s4); min-width: 0;
  color: inherit; text-decoration: none; }
.ag-row:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
.ag-out { color: var(--text-faint); }
.ag-row:hover { background: color-mix(in srgb, var(--accent) 6%, transparent); }
/* Cada clase con su color: entre seis «MACRO» en gris no se distingue un
   vencimiento de opciones de una votación sin leerlo entero. */
.ag-kind { font-size: var(--size-2xs); font-weight: 700; letter-spacing: .04em;
  text-transform: uppercase; white-space: nowrap; width: 58px; flex: none;
  color: var(--text-muted); }
.ag-row.k-expiry .ag-kind { color: var(--warn); }
.ag-row.k-unlock .ag-kind { color: var(--down); }
.ag-row.k-governance .ag-kind { color: var(--accent); }
.ag-row.k-macro .ag-kind { color: var(--up); }
.ag-row.k-listing .ag-kind, .ag-row.k-ico .ag-kind { color: var(--text); }
/* El título se lleva lo que sobre y se corta con puntos suspensivos, que es
   lo contrario de empujar a la columna de al lado. */
.ag-title { flex: 1; min-width: 0; font-size: var(--size-xs);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ag-est { margin-left: 4px; font-size: var(--size-2xs); color: var(--text-faint);
  text-decoration: none; border-bottom: 1px dotted var(--line-strong); }
.ag-meta { display: flex; gap: var(--s2); align-items: baseline; flex: none;
  font-size: var(--size-2xs); color: var(--text-muted);
  font-variant-numeric: tabular-nums; white-space: nowrap; }
.ag-size { color: var(--text-faint); }

/* Una sección anunciada y todavía no construida. */
.card.soon { max-width: 70ch; }
.card.soon .lead { margin-top: 0; }
.soon-links { display: flex; gap: var(--s3); flex-wrap: wrap; margin-top: var(--s4); }
.soon-tag { font-style: italic; font-size: var(--size-2xs); color: var(--text-faint);
  margin-left: 4px; }

/* La marca. «Board» en el acento y «beta» en cursiva al lado, pedido así.
   La etiqueta no compite con el nombre: más pequeña, apagada y levantada,
   que es como se escribe una versión y no una sección. */
.wordmark .side-name { letter-spacing: -.015em; font-weight: 700; }
.wordmark .bb { color: var(--accent); }
.wordmark .beta { font-style: italic; font-weight: 500; font-size: .62em;
  color: var(--text-faint); margin-left: 5px; vertical-align: .32em;
  letter-spacing: .02em; }
.hero .beta { font-style: italic; font-weight: 500; font-size: .34em;
  color: var(--text-faint); vertical-align: .9em; margin-left: 8px;
  letter-spacing: .02em; }

.brand-lockup { display: flex; align-items: center; gap: 9px; margin: 0 0 var(--s4);
  font-size: var(--size-lg); font-weight: 700; letter-spacing: -.015em; }
.brand-lockup svg { width: 26px; height: 26px; display: block; }
.brand-lockup .bb { color: var(--accent); }
.brand-lockup .beta { font-style: italic; font-weight: 500; font-size: .6em;
  color: var(--text-faint); margin-left: 6px; vertical-align: .35em; }

/* El aviso de qué miden estos números. Visible, no escondido en una «i»:
   es lo que impide leer un marcador de redacciones como un veredicto. */
p.limite { font-size: var(--size-xs); max-width: 86ch; margin: var(--s4) 0 0;
  padding-left: var(--s3); border-left: 2px solid var(--line-strong); }

/* ============================================================
   LA PORTADA
   ============================================================
   No hay titular de producto, ni tres ventajas, ni tabla comparativa, ni
   manifiesto. Lo primero que se ve es la noticia más cubierta de hoy
   dibujada como una carrera, porque es lo único que tenemos y nadie más
   enseña: buscado entre los agregadores del sector, todos son listas. */

svg.chart.race { display: block; }
svg.chart.race .ax { fill: var(--text-faint); font-size: 11px; }
svg.chart.race .rn { fill: var(--text-muted); font-size: 11.5px; }
svg.chart.race .rn.first { fill: var(--accent); font-size: 13px; font-weight: 700; }
svg.chart.race a { text-decoration: none; }
svg.chart.race a:hover circle { r: 7; }
svg.chart.race a:hover .rn { fill: var(--text); }

/* La tira de precios: una línea, con la columna propia en pequeño. */
.tira { margin: var(--s5) 0; border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line); }
.tira-link { display: flex; gap: var(--s5); align-items: center; padding: var(--s3) 0;
  text-decoration: none; overflow-x: auto; scrollbar-width: none; }
.tira-link::-webkit-scrollbar { display: none; }
.tira .tk { display: inline-flex; align-items: baseline; gap: 6px; white-space: nowrap;
  font-variant-numeric: tabular-nums; font-size: var(--size-sm); }
.tira .tk b { color: var(--text); }
.tira .tk small { color: var(--text-faint); font-size: var(--size-2xs); }
.tira .tk.mas { margin-left: auto; color: var(--accent); font-size: var(--size-xs); }

.home-grid { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
  gap: var(--s6); align-items: start; }
.sec-head { display: flex; align-items: baseline; gap: var(--s2); margin-bottom: var(--s3); }
.sec-head h2 { margin: 0; font-size: var(--size-lg); }
.sec-head .link, .sec-head .info { margin-left: auto; }
.sec-head .info { margin-left: 0; }

.entrar { display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap;
  margin: var(--s7) 0 var(--s5); padding-top: var(--s5); border-top: 1px solid var(--line); }
.entrar .faint { font-size: var(--size-sm); }

@media (max-width: 980px) {
  .home-grid { grid-template-columns: 1fr; gap: var(--s5); }
}

/* La cabecera de la portada: marca, una línea y la fecha. Sustituye al logo
   repetido —la barra de la izquierda ya lo lleva— y añade algo que en una
   página que cambia cada hora sí informa: de cuándo es lo que se está viendo. */
.mh-name { font-size: var(--size-lg); font-weight: 700; letter-spacing: -.015em; }
.mh-name .bb { color: var(--accent); }
.mh-name .beta { font-style: italic; font-weight: 500; font-size: .6em;
  color: var(--text-faint); margin-left: 5px; vertical-align: .35em; }

/* ============================================================
   ALERTAS: EL ICONO DE SU REGLA, NO UNA LETRA
   ============================================================
   Era una pastilla con «H», «W» o «I». Una clave que hay que aprenderse antes
   de que signifique algo no informa; un icono que dibuja lo que la regla mira
   —una señal cortada, algo saliendo de una caja, un salto con interrogación,
   varias líneas convergiendo— se entiende la primera vez. */
.alist { display: grid; }
.al { display: flex; align-items: flex-start; gap: var(--s3);
  padding: var(--s3) var(--s4); border-top: 1px solid var(--line);
  text-decoration: none; color: inherit; }
.al:first-child { border-top: 0; }
.al:hover { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.al-ico { flex: none; width: 30px; height: 30px; border-radius: 9px;
  display: grid; place-items: center; }
.al-ico svg { width: 18px; height: 18px; display: block; }
/* El nivel es el color del icono y nada más: sin pastillas y sin letras. */
.al.al-high .al-ico { color: var(--down);
  background: color-mix(in srgb, var(--down) 16%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--down) 32%, transparent); }
.al.al-warn .al-ico { color: var(--warn);
  background: color-mix(in srgb, var(--warn) 15%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--warn) 30%, transparent); }
.al.al-info .al-ico { color: var(--accent);
  background: color-mix(in srgb, var(--accent) 13%, transparent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 26%, transparent); }
/* --- El logo de quien protagoniza la alerta (2026-10-12) ------------------
   Pedido así: «en cuadrado de al lado podría ser el logo del proyecto, sería
   más llamativo y se identificaría mas rápido de que proyecto se habla».

   Cuando hay logo, el cuadrado lo ocupa él y pierde el fondo de color: un
   recuadro tintado detrás de un logotipo lo ensucia. El nivel no se pierde
   —era lo que ese fondo decía— porque pasa a la insignia de la esquina, que
   lleva **el icono de la regla** y su color. Así el cuadrado contesta las dos
   preguntas: arriba de quién, abajo de qué clase. */
.al-ico.has-face { background: none; box-shadow: none; position: relative;
  overflow: visible; }
.al-face { width: 26px; height: 26px; border-radius: 7px; background: #fff;
  object-fit: contain; padding: 1px; display: block; }
.al-rule { position: absolute; right: -3px; bottom: -3px; width: 15px; height: 15px;
  border-radius: 50%; display: grid; place-items: center;
  background: var(--bg-elevated); box-shadow: 0 0 0 1.5px var(--bg); }
.al-rule svg { width: 10px; height: 10px; }

/* **El color por clase de suceso**, que es la otra mitad de lo que se pidió:
   «un hackeo podria tener la etiqueta en rojo, una pausa de servicio por
   actualizacion de otro color».

   Va en la insignia de la regla y en las pastillas del filtro, no en el icono
   grande: ése ya dice la **gravedad**, y dos colores distintos en el mismo
   sitio no son un código, son un acertijo. Gravedad y clase son dos preguntas
   y aquí tienen dos sitios. El color nunca va solo: cada pastilla lleva su
   nombre escrito al lado, porque quien no distingue el ámbar del rojo tiene
   el mismo derecho a usar el filtro. */
.ar-big-theft          { --rule: var(--down); }
.ar-service-down       { --rule: var(--warn); }
.ar-unexplained-move   { --rule: var(--info); }
.ar-fast-consensus     { --rule: var(--accent); }
.al-rule { color: var(--rule, var(--text-muted)); }

/* Las pastillas del filtro: una por regla, con su icono, su color y su cuenta.
   Son el filtro **y** la leyenda, que es lo que evita tener las dos cosas y
   que se contradigan. */
.afil { display: flex; flex-wrap: wrap; gap: var(--s2); margin-bottom: var(--s4); }
.afil a { display: inline-flex; align-items: center; gap: 6px; padding: 5px 11px;
  border: 1px solid var(--line); border-radius: var(--radius-pill);
  background: var(--surface); font-size: var(--size-xs); color: var(--text-muted);
  text-decoration: none; }
.afil a:hover { border-color: var(--line-strong); color: var(--text); text-decoration: none; }
.afil a svg { width: 13px; height: 13px; color: var(--rule, var(--text-faint)); }
.afil a.on { color: var(--text); border-color: color-mix(in srgb, var(--rule, var(--accent)) 55%, var(--line));
  background: color-mix(in srgb, var(--rule, var(--accent)) 10%, var(--surface)); }
.afil a b { font-variant-numeric: tabular-nums; color: var(--text); }
.afil a .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--rule, var(--text-faint)); }

.al-body { min-width: 0; display: grid; gap: 2px; }
.al-body b { font-size: var(--size-xs); font-weight: 600; line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; }
.al:hover .al-body b { color: var(--accent); }
.al-meta { font-size: var(--size-2xs); color: var(--text-muted);
  text-transform: uppercase; letter-spacing: .03em; }

/* ============================================================
   EL PODIO DE LOS MEDIOS
   ============================================================
   Era una tabla de seis columnas. Un marcador se mira para saber quién va
   primero, y eso en una tabla hay que leerlo; en un podio se ve. El orden es
   el de un podio de verdad —segundo, primero, tercero— y las alturas lo
   acompañan, así que no hace falta el número para entenderlo. */
.podio { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s3);
  align-items: end; margin-bottom: var(--s6); }
.pod { display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 2px; }
.pod .awd { width: 44px; height: 44px; display: block; margin-bottom: 2px; }
.pod.p1 .awd { width: 58px; height: 58px; }
.pod .olg, .pod .mark { margin: 2px 0 5px; }
.pod-name { font-size: var(--size-base); letter-spacing: -.01em; }
.pod.p1 .pod-name { font-size: var(--size-lg); }
.pod-rate { font-size: var(--size-xl); font-weight: 700; line-height: 1;
  font-variant-numeric: tabular-nums; }
.pod.p1 .pod-rate { font-size: var(--size-2xl); color: var(--accent); }
.pod-sub, .pod-lead { font-size: var(--size-2xs); color: var(--text-muted); }
.pod-lead { color: var(--text-faint); }
/* El escalón. Alturas distintas y no una decoración: es lo que convierte tres
   tarjetas en un podio. */
.pod-step { width: 100%; margin-top: var(--s3); border-radius: 6px 6px 0 0;
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--line-strong) 70%, transparent), transparent);
  border-top: 2px solid var(--line-strong); }
.pod.p1 .pod-step { height: 74px; border-top-color: var(--accent);
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--accent) 22%, transparent), transparent); }
.pod.p2 .pod-step { height: 48px; }
.pod.p3 .pod-step { height: 32px; }

.medallas { display: grid; gap: 1px; background: var(--line);
  border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.med-row { display: flex; align-items: center; gap: var(--s3);
  padding: var(--s2) var(--s4); background: var(--surface); }
.med-row:hover { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.med-ico { flex: none; color: var(--text-faint); }
.med-ico .awd { width: 26px; height: 26px; display: block; }
.med-name { flex: none; width: 150px; font-size: var(--size-sm); }
.med-bar { flex: 1; min-width: 60px; height: 6px; border-radius: 3px;
  background: var(--line); overflow: hidden; }
.med-bar i { display: block; height: 100%; border-radius: 3px;
  background: color-mix(in srgb, var(--accent) 70%, transparent); }
.med-rate { width: 44px; text-align: right; font-variant-numeric: tabular-nums;
  font-weight: 600; font-size: var(--size-sm); }
.med-sub, .med-lead { font-size: var(--size-2xs); color: var(--text-muted);
  font-variant-numeric: tabular-nums; white-space: nowrap; }
.med-sub { width: 72px; text-align: right; }
.med-lead { width: 64px; text-align: right; }
.fuera { font-size: var(--size-xs); margin: var(--s3) 0 var(--s5); }

@media (max-width: 720px) {
  .podio { grid-template-columns: 1fr; align-items: stretch; }
  .pod-step { display: none; }
  .med-name { width: auto; flex: 1; }
  .med-bar, .med-sub { display: none; }
}

/* La clase «rewards», nueva con CoinMarketCal v2: programas de incentivos.
   Verde azulado para no confundirla con el verde de «sube» ni con el ámbar de
   un vencimiento. */
.ag-row.k-rewards .ag-kind { color: #2dd4bf; }
.ag-row.k-other .ag-kind { color: var(--text-faint); }

/* La frase que cruza el movimiento con los titulares de encima. Se marca como
   generada: es texto de un modelo y quien lo lee tiene derecho a saberlo sin
   preguntar. Sangrada y con filete, para que se vea que comenta lo de arriba
   y no es una noticia más. */
.movenote { margin: var(--s2) 0 0; padding-left: var(--s3);
  border-left: 2px solid color-mix(in srgb, var(--accent) 45%, transparent);
  font-size: var(--size-sm); color: var(--text-muted); max-width: 92ch; }
.mn-tag { display: inline-block; margin-right: 7px; font-size: var(--size-2xs);
  text-transform: uppercase; letter-spacing: .05em; color: var(--accent);
  border-bottom: 1px dotted color-mix(in srgb, var(--accent) 50%, transparent); }

/* Una sección anunciada y no construida. En grande y sin nada más: describir
   con detalle algo que todavía no existe es otra forma de maqueta. */
.comingsoon { display: grid; place-content: center; text-align: center;
  min-height: 56vh; gap: var(--s3); }
.cs-eyebrow { margin: 0; font-size: var(--size-xs); letter-spacing: .18em;
  text-transform: uppercase; color: var(--text-muted); }
.comingsoon h1 { margin: 0; font-size: clamp(2.6rem, 7vw, 5rem); line-height: 1;
  letter-spacing: -.03em; }
.cs-note { margin: var(--s4) auto 0; max-width: 52ch; font-size: var(--size-sm);
  color: var(--text-muted); }

/* ============================================================
   SEGUIR TEMAS Y MONEDAS
   ============================================================
   Dos pestañas y un desplegable compacto. El desplegable es `<details>`: se
   abre sin JavaScript y ocupa una línea cuando está cerrado, que es la mitad
   del encargo —«compacto»—. */
.st-bar { display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap;
  margin-bottom: var(--s4); }
.st-tabs { display: flex; gap: 2px; background: var(--surface); padding: 3px;
  border: 1px solid var(--line); border-radius: 999px; }
.st-tab { display: inline-flex; align-items: baseline; gap: 6px; padding: 5px 14px;
  border-radius: 999px; text-decoration: none; color: var(--text-muted);
  font-size: var(--size-sm); font-weight: 600; }
.st-tab small { font-weight: 400; font-size: var(--size-2xs); color: var(--text-faint); }
.st-tab:hover { color: var(--text); }
.st-tab.on { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--text); }
.st-tab .n { font-variant-numeric: tabular-nums; font-size: var(--size-2xs);
  color: var(--text-faint); }
/* «Mine» sin nada seleccionado lleva a una página vacía: se apaga en vez de
   prometer. */
.st-tab.vacia { opacity: .45; pointer-events: none; }

.st-pick { position: relative; }
.st-pick > summary { cursor: pointer; list-style: none; font-size: var(--size-sm);
  color: var(--text-muted); padding: 6px 12px; border: 1px solid var(--line);
  border-radius: 999px; background: var(--surface); }
.st-pick > summary::-webkit-details-marker { display: none; }
.st-pick > summary::after { content: ' ▾'; color: var(--text-faint); }
.st-pick[open] > summary { color: var(--text); border-color: var(--line-strong); }
.st-panel { position: absolute; z-index: 40; top: calc(100% + 6px); left: 0;
  width: min(560px, 90vw); max-height: 60vh; overflow-y: auto;
  background: var(--bg-elevated); border: 1px solid var(--line-strong);
  border-radius: var(--radius); box-shadow: 0 18px 40px rgba(0,0,0,.45);
  padding: var(--s4); display: grid; gap: var(--s3); }
.st-q { width: 100%; }
.st-gl { font-size: var(--size-2xs); text-transform: uppercase; letter-spacing: .06em;
  color: var(--text-muted); display: block; margin-bottom: 6px; }
.st-note { font-size: var(--size-2xs); margin: 0; }

/* Una pastilla que se marca. Botón y no enlace: cambia un estado, no navega. */
.chip-f { font: inherit; font-size: var(--size-xs); cursor: pointer;
  padding: 4px 10px; border-radius: 999px; background: transparent;
  border: 1px solid var(--line); color: var(--text-muted); }
.chip-f:hover { border-color: var(--line-strong); color: var(--text); }
.chip-f.on { background: color-mix(in srgb, var(--accent) 20%, transparent);
  border-color: color-mix(in srgb, var(--accent) 55%, transparent); color: var(--text); }
.chip-f .n { font-variant-numeric: tabular-nums; color: var(--text-faint); }

.w-empty { margin: 0; padding: var(--s4); font-size: var(--size-xs);
  color: var(--text-muted); }

/* El pie del widget de historias: la puerta a la sección. Va dentro del área
   que se desplaza, al final de la tabla, porque es donde se llega —un enlace
   fijo abajo taparía la última fila justo cuando se está leyendo.

   Era el botón de «cargar más» hasta el 2026-10-15: ver la nota de la
   plantilla sobre por qué un clic para enseñar lo que ya estaba descargado
   sobraba. */
.wst-all { display: block; padding: var(--s3) var(--s4) var(--s4);
  font-size: var(--size-2xs); }

/* ======================================================================
   Marcas y compartidos de una historia                       (2026-10-10)
   ======================================================================

   Pedido así: «añadir en cada history me gusta he iconos solciales y guardar
   solo para usuarios registrado si lo marcas y no estar logueado salta un
   popup de logue».

   El criterio de tamaño: **44 px de alto de zona pulsable** aunque el icono
   mida 17. Es la medida mínima que una guía de accesibilidad da para un dedo,
   y en una fila de siete botones pequeños pegados es la diferencia entre
   pulsar el que querías y pulsar el de al lado. El relleno hace el trabajo y
   el icono se queda pequeño, que es como tiene que verse.
   ---------------------------------------------------------------------- */

/* Para los textos que solo leen los lectores de pantalla. Cada icono lleva el
   suyo: un botón cuyo nombre accesible es «corazón» no dice qué hace. */
.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.mk {
  display: flex;
  align-items: center;
  gap: 2px;
  margin: var(--s3) 0 0;
  flex-wrap: wrap;
}

.mk-b {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-height: 34px;
  padding: 0 9px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: none;
  color: var(--text-muted);
  font: inherit;
  font-size: var(--size-xs);
  cursor: pointer;
  text-decoration: none;
  transition: background .12s, color .12s, border-color .12s;
}

.mk-b:hover { background: var(--surface-hover); color: var(--text); }
.mk-b:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

.mk-i { width: 17px; height: 17px; flex: none; }

/* Marcada. El relleno del corazón y del marcador llega del `currentColor` del
   trazo, así que basta cambiar el color y rellenar la figura. */
.mk-b.on { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 35%, transparent); }
.mk-b.on .mk-i path { fill: currentColor; }

/* El «copiado» dura un segundo y no pone texto: un botón que cambia de ancho
   al pulsarlo mueve los de al lado. */
.mk-b.ok { color: var(--ok); }

.mk-n { font-variant-numeric: tabular-nums; min-width: 0; }

.mk-sep {
  width: 1px;
  align-self: stretch;
  margin: 6px 7px;
  background: var(--line);
}

/* `.mk-shares` se retiró el 2026-10-13 con el número que pintaba: era la
   única cifra del sitio que cualquiera podía subir pulsando, sin cuenta y
   desde el propio botón. Lo que contaba se sigue guardando y se lee en el
   panel, en «Interactions». */

/* --- El aviso de entrar ---------------------------------------------- */

.mk-modal {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-items: center;
  padding: var(--s4);
  background: rgba(4, 6, 11, .66);
  /* Sin animación de entrada: el diálogo aparece porque acabas de pulsar, y
     una transición de 200 ms es justo el tiempo que tarda en sentirse lento. */
}

.mk-card {
  position: relative;
  width: min(420px, 100%);
  padding: var(--s5);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
  box-shadow: 0 18px 50px rgba(0, 0, 0, .45);
}

.mk-card h3 { margin: 0 0 var(--s3); font-size: var(--size-md); }
/* El popup de entrar (F7-33): el mismo diálogo, un poco más ancho para el
   formulario, y con su propio desplazamiento por si el teléfono es bajo. */
.auth-card { width: min(460px, 100%); max-height: calc(100vh - 2 * var(--s4)); overflow-y: auto; }
.auth-card h1 { font-size: var(--size-lg); margin-top: 0; padding-right: 36px; }
.mk-card p { margin: 0 0 var(--s3); color: var(--text-muted); font-size: var(--size-sm); line-height: 1.55; }
.mk-card .mk-why { font-size: var(--size-xs); }

.mk-close {
  position: absolute;
  top: 6px;
  right: 8px;
  width: 32px;
  height: 32px;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--text-muted);
  font-size: 20px;
  line-height: 1;
  cursor: pointer;
}

.mk-close:hover { background: var(--surface-hover); color: var(--text); }

.mk-actions { display: flex; gap: var(--s2); flex-wrap: wrap; margin-top: var(--s4); }

@media (max-width: 560px) {
  /* En el móvil los separadores sobran y el ancho se aprovecha mejor sin
     ellos: siete botones en una fila de 320 px ya van justos. */
  .mk-sep { display: none; }
  .mk-b { padding: 0 7px; }
}

/* ======================================================================
   La cartera                                                 (2026-10-10)
   ======================================================================

   Pedida así: «una lista de seguimiento, rentabilidad posicion total y una
   cartera completmante profesional».

   Dos decisiones de disposición que vienen de mirar los que ya existen:

   - **El valor, en grande y solo.** En CoinStats y en Delta lo primero y más
     grande de la pantalla es cuánto tienes; todo lo demás es secundario y se
     ve que lo es. Cuatro cifras del mismo tamaño no dicen cuál importa.
   - **La barra del peso.** El número de la columna ya está; la barra es para
     ver de un vistazo si la cartera está concentrada en una sola moneda, que
     es la pregunta que el número obliga a contestar sumando a mano.
   ---------------------------------------------------------------------- */

.pf-top {
  display: grid;
  grid-template-columns: minmax(220px, 300px) 1fr;
  gap: var(--s4);
  margin-bottom: var(--s5);
}

.pf-big {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: var(--s4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}

.pf-v {
  font-size: clamp(26px, 4.4vw, 38px);
  line-height: 1.05;
  font-variant-numeric: tabular-nums;
  letter-spacing: -.5px;
}

/* La misma cifra en BTC, a la derecha del total. `0.56em` del tamaño del
   valor y no un tamaño fijo: el total es `clamp()` y crece con la ventana, así
   que con una medida fija la proporción cambiaba con el ancho. */
.pf-vbtc { font-size: .42em; font-weight: 500; color: var(--text-muted);
  margin-left: .4em; letter-spacing: 0; white-space: nowrap; }

.pf-d { font-size: var(--size-sm); font-variant-numeric: tabular-nums; }
.pf-d small { opacity: .75; }

.pf-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: var(--s3);
}

.pf-c {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: var(--s4);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface);
}

.pf-c b { font-size: var(--size-md); font-variant-numeric: tabular-nums; }

/* --- Una sección de la cartera: su franja y su tabla ----------------------
 *
 * Pedido el 2026-10-14, tres puntos seguidos para las tres secciones: «la
 * tabla de position siempre se muestras aunque no haya ninguna añadida»,
 * «misma dinamica en la tabla de liquidity pool, siempre se muestras con los
 * botones en la franja mas oscura que por elgun motivo esta tabla no la tiene
 * como la de positions», «y wachlist misma dinamica […] asi eliminamos ruido de
 * la pagina de portfolio y la dejamos mas limpia».
 *
 * La franja es donde van el nombre, el recuento, la «i» y los botones de esa
 * sección. Antes los formularios eran bloques largos entre tablas y los
 * títulos eran `h2` sueltos: tres secciones con tres formas distintas de
 * empezar. Ahora las tres son iguales, y lo que cambia son sus botones.
 */
.pf-sec { border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); overflow: hidden; margin-bottom: var(--s4); }
/* **`--surface-sunken` y no `--bg-elevated`**, que es lo que puse primero y
   medí en el navegador: en el tema claro `--bg-elevated` es blanco y
   `--surface` también, así que la franja salía **del mismo color que la
   tabla** — «la franja mas oscura» no era más oscura de nada. `sunken` es el
   token que existe justo para esto y tiene valor en los dos temas. */
.pf-sec-h { display: flex; align-items: center; gap: var(--s2);
  padding: var(--s3) var(--s4); background: var(--surface-sunken);
  border-bottom: 1px solid var(--line); }
.pf-sec-h > b { font-size: var(--size-md); }
/* Los botones a la derecha y pegados entre sí: son de la misma sección. */
.pf-sec-a { display: inline-flex; align-items: center; gap: var(--s2);
  margin-left: auto; flex-wrap: wrap; justify-content: flex-end; }
/* La tabla ya vive dentro de la sección, así que el desplazamiento horizontal
   lo lleva su envoltorio y no una tarjeta aparte. */
.pf-sec .pf-scroll { overflow-x: auto; }

/* La fila de «no hay nada», dentro de la tabla y no en lugar de ella: así la
   primera vez que alguien entra ve dónde van a caer sus cifras. */
.pf-nada td { padding: var(--s5) var(--s4); color: var(--text-muted);
  text-align: center; }

.pf-t { width: 100%; }
.pf-t td, .pf-t th { vertical-align: top; }

/* La barra del peso. Fondo siempre visible para que una posición del 2 % se
   lea como «2 % de algo» y no como una celda vacía. */
.pf-w {
  display: inline-block;
  width: 56px;
  height: 5px;
  margin-right: 6px;
  border-radius: 3px;
  background: var(--line);
  overflow: hidden;
  vertical-align: middle;
}

.pf-w i { display: block; height: 100%; background: var(--accent); }

/* La fila de noticias de una posición: pegada a la suya, sin borde arriba, para
   que se lea como parte de ella y no como otra posición. */
.pf-news td {
  padding-top: 0;
  border-top: 0;
}

.pf-n {
  display: block;
  font-size: var(--size-xs);
  line-height: 1.45;
  margin-top: 2px;
}

/* El formulario: una rejilla que se parte sola. Siete campos en una fila fija
   obligan a hacer scroll lateral en un portátil. */
.pf-f {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: var(--s3);
}

.pf-f label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: var(--size-2xs);
  color: var(--text-muted);
}

.pf-f input, .pf-f select {
  min-height: 34px;
  padding: 0 9px;
  border: 1px solid var(--line);
  border-radius: 8px;
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: var(--size-xs);
}

.pf-f input[type="number"] { width: 110px; }
.pf-f input[list] { width: 140px; }
.pf-f input[type="text"] { width: 160px; }

.btn.sm {
  min-height: 26px;
  padding: 0 8px;
  font-size: var(--size-2xs);
}

@media (max-width: 860px) {
  .pf-top { grid-template-columns: 1fr; }
}

/* **Dos desbordes medidos con un navegador el 2026-10-13**, los dos en esta
   pantalla y ninguno visto antes porque exige cuenta: el barrido de pantallas
   entraba sin galleta y se quedaba en el formulario de entrada.

   A 390 px, la columna del peso pedía 69 px y tenía 46: la barra son 56 px
   fijos más seis de margen, y una barra fija no encoge. **Se va la barra y se
   queda el número**, que es el que lleva la información; la barra es la forma
   de leer «2 % de algo» de un vistazo y de un vistazo en un móvil no se lee
   una barra de 56 px al lado de nueve columnas. */
@media (max-width: 520px) {
  .pf-t .pf-w { display: none; }
}

/* Y a 1024 px, la tabla de pools pedía 828 y tenía 758: diez columnas no
   caben en un portátil. Se va **«If held»**, y se va ésa y no otra por una
   razón: es la base de la comparación, y la comparación ya está contada en
   «vs holding», que es una resta de ella. Quitar una columna cuyo contenido
   se deduce de la de al lado no pierde nada; quitar «In» —las cantidades que
   puso quien la abrió— sí perdería. */
@media (max-width: 1200px) {
  .pf-pools th:nth-child(6), .pf-pools td:nth-child(6) { display: none; }
}

/* **Y por debajo de 760 px deja de ser una tabla.**

   Medido con un navegador a 390 px: nueve columnas se repartían cuarenta
   píxeles cada una, las cabeceras se montaban unas sobre otras
   —«OPENED»+«IN», «VS HOLDING»+«FEES EARNED»—, «SOL/USDC» se leía hacia abajo
   una letra por línea y la pastilla de «modelled» era una columna de letras
   sueltas. No desbordaba: encogía, que es la otra forma de no verse.

   El remiendo de la casa —repartir el ancho y dejar partir el texto— funciona
   con seis u ocho columnas cortas. Con nueve, dinero y pastillas, no hay
   reparto que valga: cada posición pasa a ser una ficha y la cabecera de cada
   dato la pone el `data-label` de su celda. Es lo que hace cualquier cartera
   en un móvil, y es la única forma en que esto se lee. */
@media (max-width: 760px) {
  /* **Lo genérico, para las cuatro tablas de la cartera.** Posiciones,
     apuntes, cerradas y seguimiento tenían el mismo problema que las pools y
     se arreglaron tres días después: a 390 px, «Bitcoin» se leía hacia abajo
     a letra por línea. Cada fila pasa a ser una ficha y la cabecera de cada
     dato la pone el `data-label` de su celda. */
  .pf-ficha, .pf-ficha tbody, .pf-ficha tr, .pf-ficha td { display: block; width: auto; }
  .pf-ficha thead { display: none; }
  .pf-ficha tr { padding: var(--s3) var(--s4); border-top: 1px solid var(--line); }
  .pf-ficha tbody tr:first-child { border-top: 0; }
  .pf-ficha td { border: 0; padding: 2px 0; text-align: left; }
  .pf-ficha td[data-label]::before {
    content: attr(data-label);
    display: inline-block;
    min-width: 11ch;
    color: var(--text-muted);
    font-size: var(--size-2xs);
    text-transform: uppercase;
    letter-spacing: .04em;
  }
  /* La celda del titular —la moneda, el par— va primera y más grande, y su
     nombre largo en línea en vez de debajo: dentro de una ficha estrecha, dos
     líneas para «BTC / Bitcoin» parten la lectura en dos. */
  .pf-ficha td.pf-head { font-size: var(--size-md); padding-bottom: var(--s2); }
  .pf-ficha td.pf-head div { display: inline; margin-left: 6px; font-size: var(--size-2xs); }
  /* Lo que no es un dato no lleva etiqueta ni ocupa fila propia. */
  .pf-ficha td.pf-quita { padding-top: var(--s2); }
  .pf-ficha td.pf-quita::before { content: none; }
  /* Las filas que acompañan a la de arriba —la nota, las acciones, las
     noticias— no son fichas sueltas: sin esto, la raya las deja flotando
     entre dos posiciones y sin dueño. */
  .pf-ficha tr.pf-nota, .pf-ficha tr.pf-act, .pf-ficha tr.pf-news {
    border-top: 0; padding-top: 0; margin-top: calc(var(--s3) * -1);
  }
  .pf-ficha tr.pf-act > td { border-bottom: 0; }

  /* --- Y lo propio de las pools ---------------------------------------- */
  .pf-pools td.pf-pair { font-size: var(--size-md); padding-bottom: var(--s2); }
  .pf-pools td.pf-pair small { display: inline; margin-left: 6px; }
  /* Las dos cantidades de una pool van en línea aquí. */
  .pf-pools td.mono br { display: none; }
  .pf-pools td.mono span.faint::before { content: " / "; }
  .pf-pools td .num small, .pf-pools td small { display: inline; margin-left: 6px; }
  .pf-pools td .pill { margin-left: 6px; }
  /* «If held» vuelve: en una ficha hay sitio y es la base de la comparación. */
  .pf-pools td.pf-held { display: block; }
  .pf-pools td.pf-net { padding-top: var(--s2); }
}

/* El reparto por sector, en anillos (2026-10-15). Eran cuatro barras —`.pf-a`,
   `.pf-ab`, `.pf-aw`, `.pf-av`— al final de la pantalla, y salieron con su
   sección: «no una barra sin sentido y horrible». El porqué de los anillos, en
   la nota de `charts.arc`: los sectores no suman 100 %, así que unas barras a
   lo ancho de la tarjeta se leen como partes de un total que no existe.

   Rejilla que se parte sola: la tarjeta mide un tercio de la pantalla en
   escritorio y la pantalla entera en el móvil. */
.pf-sect { display: grid; gap: var(--s3) var(--s2); margin-top: var(--s3);
  grid-template-columns: repeat(auto-fit, minmax(78px, 1fr)); }
.pf-sc { display: flex; flex-direction: column; align-items: center; gap: 2px;
  text-align: center; font-size: var(--size-2xs); min-width: 0; }
.pf-sc > a, .pf-sc > span { max-width: 100%; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.pf-sc small { font-variant-numeric: tabular-nums; }
svg.arc { display: block; }
.pf-sect-rest { margin: var(--s3) 0 0; font-size: var(--size-2xs); }


/* ============================================================
   LA LISTA DE HISTORIAS, DENSA (2026-10-12)
   ============================================================
   Pedido así: «fijandonos en cryptopanic que todo es mucho mas minimalista y
   lo que prima es la cantidad de noricias que aparecen».

   Medido antes de tocar nada: cada historia era una `.card` con borde, relleno
   y margen, con cinco bloques apilados dentro, y ocupaba 185 px. Cuatro
   historias por pantalla de 900 px. Ahora son dos líneas separadas por una
   raya: el titular con su nota, y debajo todo lo demás en una fila que fluye.

   **Una lista y no tarjetas**, y esa es la decisión de fondo. Una tarjeta dice
   «esto es una unidad que se mira sola»; en una lista de cien titulares lo que
   se mira es la lista, y el borde de cada tarjeta es ruido repetido cien
   veces. El separador hace el mismo trabajo con un píxel. */
.slist { border-top: 1px solid var(--line); }
/* **Rejilla de tres columnas y dos filas**, y no una fila de cajas. Con
   `flex`, el titular competía por el ancho con la fecha y con los siete
   iconos de marcar y compartir —unos 400 px entre las dos— y acababa partido
   en dos líneas donde cabía en una: de nueve historias por pantalla se bajaba
   a siete, que es lo contrario de lo que este cambio busca.

   Así, el titular tiene toda la columna central de la primera fila, y la
   segunda —datos a la izquierda, marcas a la derecha— pasa por debajo. */
.srow { display: grid; align-items: center; gap: 3px var(--s3);
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "score title  when"
                       ".     meta   marks";
  padding: var(--s3) var(--s2); border-bottom: 1px solid var(--line); }
.srow:hover { background: color-mix(in srgb, var(--accent) 4%, transparent); }
.srow > .score { grid-area: score; align-self: start; margin-top: 2px; }
.srow-title { grid-area: title; font-size: var(--size-md); line-height: 1.3;
  font-weight: 650; margin: 0; }
.srow-title a:hover { color: var(--accent); }

/* La fila de debajo: todo lo que antes eran tres bloques. `flex-wrap` para que
   en una pantalla estrecha baje en vez de desbordar, y `row-gap` pequeño para
   que al bajar no abra un hueco. */
.srow-meta { grid-area: meta; display: flex; align-items: center; flex-wrap: wrap;
  gap: 3px var(--s2); font-size: var(--size-xs); color: var(--text-muted); min-width: 0; }
.srow-meta .withmark { gap: 0; }
.srow-meta .first-up { white-space: nowrap; }
.srow-meta .first-up b { color: var(--text); font-weight: 600; }

/* El punto medio como separador en vez de una pastilla por dato. Cuatro
   pastillas por fila en cien filas son cuatrocientos bordes redondeados, y lo
   que dicen son cuatro palabras. */
.srow-meta .sep { white-space: nowrap; }
.srow-meta .sep::before { content: "·"; margin-right: var(--s2); color: var(--text-faint); }
.srow-meta .sep b { color: var(--text); font-weight: 600; }
.srow-meta .ok-t { color: var(--ok); }
.srow-when { grid-area: when; align-self: start; margin-top: 3px; text-align: right;
  color: var(--text-faint); white-space: nowrap; font-size: var(--size-xs);
  font-variant-numeric: tabular-nums; }

/* Los temas sí siguen siendo pastillas: son enlaces, y un enlace necesita
   verse como algo que se puede pulsar. */
.chip.tiny { font-size: var(--size-2xs); padding: 0 7px; line-height: 17px; }

/* Las marcas, a la derecha de la fila en vez de en una línea propia. */
.srow > .mk { grid-area: marks; margin: 0; padding: 0; border: 0; }

@media (max-width: 760px) {
  /* En móvil la fecha vuelve a su sitio natural —al final de la fila— en vez
     de empujar contra el borde, y las marcas bajan debajo del titular: siete
     iconos y un titular no caben en 360 px por mucho que se aprieten. */
  /* En móvil la fecha baja con los datos y las marcas ocupan su propia fila:
     un titular y siete iconos no caben en 360 px por mucho que se aprieten. */
  .srow { grid-template-columns: auto minmax(0, 1fr);
    grid-template-areas: "score title"
                         ".     meta"
                         ".     marks"; }
  .srow-when { grid-area: meta; justify-self: end; align-self: center; margin-top: 0; }
  .srow-meta { padding-right: 96px; }
}


/* Las otras vistas del mismo protagonista (2026-10-12). Tres páginas hablaban
   de XRP —el precio, el hilo y la lista filtrada— y ninguna enlazaba a las
   otras dos. No se unifican porque contestan preguntas distintas; lo que
   faltaba era decirlo. */
.otras { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s2);
  margin: 0 0 var(--s3); font-size: var(--size-xs); }
.otras .faint { font-size: var(--size-2xs); text-transform: uppercase; letter-spacing: .05em; }


/* La columna «Latest» de los hilos: dos líneas y puntos suspensivos de verdad.
   Antes el titular se rebanaba en el servidor a 58 caracteres **sin señal** —se
   leía como un titular entero— y encima la celda lo recortaba a 28ch. */
/* **La columna «Latest», y por qué el arreglo del 2026-10-12 no sirvió**
   (2026-10-13). El usuario volvió a decirlo: «la columna Latest sigue cortando
   titulos».

   Lo de ayer fue poner dos líneas con puntos suspensivos. Era lo correcto y
   **estaba muerto al nacer**, por una regla escrita mucho antes y tres
   pantallas más arriba: esta tabla lleva `class="mkt"`, y `table.mkt td` pone
   `white-space: nowrap`, que es lo que tiene que hacer una tabla de cifras.
   Con el texto sin permiso para partir, un `-webkit-line-clamp: 2` no puede
   dar dos líneas nunca: da una, y lo que sobra se va por el lado.

   Medido en el navegador antes de tocarlo: el enlace ocupaba **277 px** con
   **1.074 px** de contenido dentro. Tres cuartas partes del titular, fuera.

   Así que primero se devuelve el permiso de partir, y después el recorte
   tiene algo que recortar. El orden importa y es lo que no vi ayer. */
td.ult { min-width: 24ch; max-width: 38ch; white-space: normal; }
/* **Y sin recorte ninguno.** Con el permiso de partir devuelto, 28 de los 30
   titulares caben en dos líneas; los otros dos piden cuatro o cinco. Recortar
   ahí para igualar las filas sería cortar dos titulares de verdad por un
   motivo de simetría, y esta casa ya pagó esa lección con el `[:58]` de esta
   misma columna. Dos filas más altas no se leen mal; un titular a medias sí. */
td.ult a { display: block; white-space: normal; overflow-wrap: anywhere;
  font-size: var(--size-xs); line-height: 1.35; }


/* La urgencia de cada cifra del estado de servicios, en una franja lateral.
   No en el número: «0 problemas» con el 0 en rojo dice lo contrario de lo que
   pasa. Y apagada cuando vale cero, porque una alarma encendida sobre un cero
   enseña a ignorar las alarmas. */
.statcards.urg .card { border-left: 3px solid var(--line); }
.statcards.urg .card.u-down.on { border-left-color: var(--down); }
.statcards.urg .card.u-warn.on { border-left-color: var(--warn); }
.statcards.urg .card.u-ok.on { border-left-color: var(--ok); }
.statcards.urg .card.u-unknown.on { border-left-color: var(--text-faint); }


/* El globo de un punto del calendario. Mismo aspecto que el de la «i» —misma
   casa, misma promesa— pero con sus propias reglas porque el punto va
   posicionado en absoluto dentro de su carril y no puede heredar las de
   `.hint`, que lo pondrían en relativo y lo mandarían al principio de la
   línea. Se ancla por el centro del punto y se recoloca solo si se saldría. */
.cal-dot { cursor: help; }
.cal-dot:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.cal-dot[data-info]::after {
  content: attr(data-info);
  position: absolute; top: calc(100% + 8px); left: 50%; transform: translateX(-50%);
  width: max-content; max-width: min(40ch, 70vw);
  padding: var(--s2) var(--s3);
  background: var(--bg-elevated); border: 1px solid var(--line-strong); border-radius: 6px;
  box-shadow: 0 6px 20px rgb(0 0 0 / 45%);
  color: var(--text); font-size: var(--size-xs); line-height: 1.45; text-align: left;
  opacity: 0; visibility: hidden; transition: opacity .12s ease;
  z-index: 60; pointer-events: none; white-space: normal;
}
.cal-dot:hover::after, .cal-dot:focus-visible::after { opacity: 1; visibility: visible; }
/* El carril recortaba el globo: tiene borde inferior y los puntos viven
   dentro. `overflow: visible` es lo que deja que salga. */
.cal-lane-track { overflow: visible; }


/* ============================================================
   LA LECTURA DEL MERCADO (2026-10-12)
   ============================================================
   Una tarjeta por cifra, y el borde izquierdo dice hacia dónde empuja. El
   color va en el borde y no en el número por la misma razón que en el estado
   de servicios: un número en rojo se lee como «este número es malo», y aquí
   lo que es favorable o contrario no es el número, es su dirección. */
.reads { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: var(--s3); }
.reads .card { border-left: 3px solid var(--line); }
.reads .card.lean-tailwind { border-left-color: var(--up); }
.reads .card.lean-headwind { border-left-color: var(--down); }
.reads .card.lean-both { border-left-color: var(--warn); }
.reads .card.lean-neutral { border-left-color: var(--line-strong); }
.lean-tag { font-size: var(--size-2xs); text-transform: uppercase; letter-spacing: .05em;
  white-space: nowrap; }
.lean-tag.lean-tailwind { color: var(--up); }
.lean-tag.lean-headwind { color: var(--down); }
.lean-tag.lean-both { color: var(--warn); }
.lean-tag.lean-neutral { color: var(--text-faint); }
.reads .what { font-size: var(--size-sm); color: var(--text-muted); }
.reads .says { font-size: var(--size-sm); color: var(--text); }

/* El bloque del precedente. El fino es el de «todavía no»: se ve que es otra
   cosa sin tener que leerlo. */
.prec { border-top: 1px solid var(--line); padding-top: var(--s3); display: grid; gap: 4px;
  font-size: var(--size-sm); }
.prec.thin { border-top-style: dashed; }

/* El salto del calendario a la lectura: una tarjeta que es un enlace. */
a.card.salto { display: block; text-decoration: none; color: inherit;
  border-left: 3px solid var(--accent); }
a.card.salto:hover { text-decoration: none; }

/* La secuencia de un evento: precio, salto, precio, salto, precio. Se lee de
   izquierda a derecha como una línea de tiempo porque **es** una línea de
   tiempo, y ése es todo el invento: esos cinco datos existen siempre y nunca
   están juntos. */
.seq { display: grid; gap: var(--s3); }
.seq-row { display: flex; align-items: center; flex-wrap: wrap; gap: var(--s2) var(--s3);
  margin-top: var(--s2); font-size: var(--size-sm); font-variant-numeric: tabular-nums; }
.seq-row i { font-style: normal; display: block; font-size: var(--size-2xs);
  color: var(--text-faint); text-transform: uppercase; letter-spacing: .04em; }
.seq-arrow { font-weight: 650; }
.seq-arrow::before { content: "→"; color: var(--text-faint); margin-right: 6px; font-weight: 400; }

/* ============================================================
   COLUMNAS QUE CAEN, EN VEZ DE UNA BARRA QUE APARECE (2026-10-12)
   ============================================================
   Pedido así: «si la informacion no cabe en el tamaño del usuario siempre se
   reduce, no se pone una barra para mover dentro de la caja. la barra vertical
   si la mantenemos».

   Es una regla de producto y vale para toda la casa, no solo para el terminal.
   Medido antes de escribir esto, a 390 px: la tabla de mercados medía 1.247
   dentro de una tarjeta de 366, la de hilos 1.187, la de rendimientos 875. Con
   la tarjeta recortando, las columnas de la derecha **no existían** para quien
   entra desde el móvil; con una barra, existían pero había que arrastrar
   dentro de una caja. Ninguna de las dos es lo que se quiere.

   **`d4` se va primero y `d1` la última.** El número no es un nivel de
   importancia abstracto: es el orden en que esa columna deja de hacer falta en
   esa tabla concreta, decidido mirando qué contesta cada una. Los cortes salen
   de medir la tarjeta, que es la ventana menos la barra lateral y los
   márgenes: a 1440 son 1176 px, a 1024 son 760 y en un móvil 366.

   Lo que **nunca** cae es la columna que identifica la fila y la cifra por la
   que está ordenada: sin esas dos, la tabla deja de ser esa tabla. */
@media (max-width: 1500px) { .d4 { display: none !important; } }
@media (max-width: 1200px) { .d3 { display: none !important; } }
@media (max-width: 1060px) { .d2 { display: none !important; } }
@media (max-width: 700px)  { .d1 { display: none !important; } }

/* La columna «Latest» de los hilos tenía un mínimo de 24 caracteres, que en un
   móvil es la mitad de la pantalla para una sola columna. */
@media (max-width: 700px) { td.ult { min-width: 0; max-width: none; } }

/* Los carriles del calendario llevan un ancho mínimo de 640 px para que los
   puntos de un mes no se amontonen. En un móvil eso es dos pantallas: se
   suelta el mínimo y los puntos se aprietan, que es peor que holgado y mejor
   que inalcanzable. */
@media (max-width: 700px) { .cal-lanes { min-width: 0; } }

/* El aire lateral de las celdas, en un móvil. Doce píxeles a cada lado por
   columna son veinticuatro, y con tres columnas eso es lo que separaba a la
   última tabla de estado de caber: 391 contra 366. Se recorta el relleno
   antes que quitar una columna que dice algo — el estado de un servicio roto
   es justo lo que esa tabla viene a decir. */
@media (max-width: 700px) {
  /* **Y el cinturón: en un móvil la tabla se reparte el ancho que hay.**
     Quitar columnas y dejar que las palabras partan cubre casi todo, pero
     «casi» no sirve para una regla que dice «nunca una barra horizontal»:
     quedaba una tabla de estado diez píxeles por fuera, y la siguiente que
     alguien añada quedará fuera también.

     `table-layout: fixed` lo garantiza por construcción: el ancho lo fija el
     contenedor y las columnas se lo reparten, en vez de que el contenido fije
     el ancho y el contenedor se desborde. El precio es que una celda larga se
     parte en más líneas, que en un teléfono es exactamente lo que se quiere.
     No se aplica en pantalla grande, donde el reparto automático coloca mejor
     una tabla de catorce columnas. */
  .card.flush table, .widget table { table-layout: fixed; width: 100%; }
  /* **Y el reparto sólo manda si el contenido deja partirse** (2026-10-13).
     `table-layout: fixed` reparte el ancho, pero una celda con un átomo
     irrompible —un nombre largo sin espacios, un logo pegado a su texto— pide
     más que su parte y la tabla vuelve a desbordar. Medido a 390 px tras el
     arreglo anterior: la celda de medios tenía 91 px y pedía 141; la última
     de la ficha de un activo, 69 y pedía 75.
     `min-width: 0` le quita el derecho a pedir y `overflow-wrap: anywhere` le
     da la forma de caber. Juntos cierran la regla: lo que no cabe se reduce,
     no se desplaza. */
  .card.flush td, .card.flush th, .widget td, .widget th {
    min-width: 0; overflow-wrap: anywhere;
  }
  /* **Y las pastillas dentro de una tabla**: lo último que quedaba fuera, y
     por seis píxeles. Una `<span class="pill">explained</span>` pide 75 px
     entre la palabra y su relleno, y la columna tenía 69. El relleno de una
     pastilla es decoración; seis píxeles de tabla asomando por el borde no lo
     son. El texto se queda igual de legible con la mitad. */
  .card.flush td .pill, .widget td .pill {
    padding-left: 5px; padding-right: 5px; white-space: normal;
  }
  table th, table td { padding-left: 7px; padding-right: 7px; }
  table th:first-child, table td:first-child { padding-left: var(--s3); }
  table th:last-child, table td:last-child { padding-right: var(--s3); }
}

/* Y lo que no se arregla quitando columnas, porque es **una** columna ancha:
   un nombre largo en una tabla de cuatro columnas se come la pantalla él solo.
   Medido a 390 px: «Asset» ocupaba 207 px de 366 en mercados, «Latest» 532 en
   hilos y «Newsroom» 216 en medios. Se les pone techo y lo que sobra lleva
   puntos suspensivos, que es la respuesta correcta a un nombre que no cabe. */
@media (max-width: 700px) {
  table.mkt .coin-link, table.mkt .coin-name { max-width: 108px; }
  table.mkt .coin-link b, table.mkt .coin-name div {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  td.ult { max-width: 132px; }
  td.ult a { -webkit-line-clamp: 3; }
  /* **150 px era más de lo que hay** (2026-10-13). A 390 px esta celda recibe
     91, así que un techo de 150 no la sujetaba y el nombre se montaba encima
     de la columna de al lado — se ve en «Spiko Amundi Overnight Swap Fund»
     pisando su propio «100 %». El techo tiene que ser relativo al reparto, no
     un número fijo mayor que él; y el hijo flexible necesita `min-width: 0`
     para poder encogerse, que es el valor que no trae por defecto. */
  .newsroom-cell { max-width: 100%; }
  /* **`inline-flex` se mide por su contenido y no encoge.** Era la pieza que
     faltaba, y `min-width: 0` en los hijos no servía de nada mientras el
     padre no tuviera un ancho que repartir: medido, 134 px de `.withmark`
     dentro de una celda de 91. En bloque sí llena la celda, y entonces los
     hijos con `min-width: 0` se reparten lo que hay y el nombre largo acaba
     en puntos suspensivos en vez de encima de la columna de al lado. */
  .newsroom-cell .withmark { display: flex; max-width: 100%; min-width: 0; }
  .newsroom-cell .withmark > *:not(img):not(.mark) { min-width: 0; flex: 1 1 auto; }
  .svc-name { max-width: 92px; }
  .svc-name a, .svc-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .newsroom-cell a, .newsroom-cell div {
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; display: block; }
}

/* Los tres del podio llevan a su ficha. El enlace envuelve el logo y el
   nombre —no solo el texto— porque el logo es la mitad del objetivo y pulsar
   al lado de un nombre y que no pase nada es lo que hacía el podio hasta hoy. */
.pod-link { display: flex; flex-direction: column; align-items: center; gap: 0;
  text-decoration: none; color: inherit; }
.pod-link:hover { text-decoration: none; }
.pod-link:hover .pod-name { color: var(--accent); }
.med-name a { color: inherit; }
.med-name a:hover { color: var(--accent); }

/* ============================================================
   LA FICHA DE UN MEDIO (2026-10-12)
   ============================================================
   Rehecha entera: tres de sus cuatro paneles eran datos de muestra, los mismos
   para los 211 medios. Lo que sigue viste la capa que no tiene nadie — cómo se
   comporta esa redacción, medido aquí. */
.src-tags { gap: var(--s2); flex-wrap: wrap; }

/* Lo que dicen de sí mismos. Entrecomillado y con su enlace: lo que se enseña
   es una cita, no una página ajena reproducida. */
.says-card { border-left: 3px solid var(--accent); }
.says-quote { margin: var(--s3) 0 var(--s2); padding-left: var(--s3);
  border-left: 2px solid var(--line); font-size: var(--size-base);
  line-height: 1.6; color: var(--text); max-width: 72ch; }
.discl { gap: 6px; flex-wrap: wrap; }
.pill.faint-pill { color: var(--text-faint); border-style: dashed; }

/* El cara a cara. La barra se lee de izquierda a derecha como una balanza: lo
   que gana este medio a la izquierda, lo que le ganan a la derecha. */
.h2h { display: grid; gap: 9px; }
.vs { display: grid; grid-template-columns: 38px minmax(60px, 1fr) 38px minmax(0, 1.4fr);
  gap: var(--s2); align-items: center; font-size: var(--size-sm); }
.vs-me { text-align: right; color: var(--up); font-weight: 650; }
.vs-them { color: var(--down); font-weight: 650; }
.vs-track { height: 9px; border-radius: 5px; background: var(--down); overflow: hidden; }
.vs-track i { display: block; height: 100%; background: var(--up); }
.vs-rival { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--text-muted); }
.vs-rival a { color: var(--text); }
.vs-rival a:hover { color: var(--accent); }
.vs-rival em { font-style: normal; font-size: var(--size-2xs); margin-left: 5px; }

@media (max-width: 700px) {
  .vs { grid-template-columns: 34px minmax(40px, 1fr) 34px; }
  .vs-rival { grid-column: 1 / -1; white-space: normal; }
}


/* El mapa de cuándo publica un medio. El SVG sale con `width="100%"`, y en una
   tarjeta de 722 px eso lo centra dentro de su caja con el dibujo pequeño a la
   derecha y medio panel vacío a la izquierda. Se le deja su tamaño natural,
   alineado a la izquierda como todo lo demás de la tarjeta. */
.heat-wrap { overflow: hidden; }
.heat-wrap svg { width: auto; max-width: 100%; height: auto; display: block; }


/* ======================================================================
   El selector de rango del gráfico de un activo            (2026-10-13)
   ======================================================================

   Pedido así: «los graficos deberian tener mas amplitud, ahora solo mostramos
   los 30 dias». Y el rango que una moneda no tiene **se tacha, no se
   esconde**: medido, BTC y ETH tienen 365 días y las otras 1.086 tienen 18.
   Un botón ausente haría pensar que el gráfico se diseñó así; uno tachado con
   «sólo tenemos 18 días» dice algo cierto sobre el dato. */
.rangos { display: flex; gap: 2px; align-items: center; }
.rg { font-size: var(--size-xs); padding: 3px 10px; border: 1px solid transparent;
  border-radius: 7px; color: var(--text-muted); text-decoration: none; }
.rg:hover { background: var(--surface-hover); color: var(--text); }
.rg.on { background: var(--accent-soft); color: var(--text);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent); }
.rg.off { color: var(--text-faint); opacity: .45; cursor: not-allowed;
  text-decoration: line-through; }
.rg.off:hover { background: none; color: var(--text-faint); }


/* La tarjeta de una marca del gráfico. Va en coordenadas de página —no fija a
   la ventana— porque se abre junto a un punto del dibujo y tiene que seguirlo
   al desplazar. */
.mvcard {
  position: absolute;
  z-index: 70;
  width: min(330px, calc(100vw - 32px));
  padding: 11px 30px 11px 13px;
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  background: var(--bg-elevated);
  box-shadow: var(--shadow);
}
.mvcard .f { font-size: var(--size-2xs); color: var(--text-faint);
  font-variant-numeric: tabular-nums; }
.mvcard .t { font-size: var(--size-sm); line-height: 1.4; margin: 4px 0 6px; }
.mvcard .c { font-size: var(--size-2xs); color: var(--text-muted);
  font-variant-numeric: tabular-nums; }
.mvcard .a { display: flex; gap: 12px; margin-top: 9px; font-size: var(--size-xs); }
.mvcard .x { position: absolute; top: 4px; right: 5px; width: 24px; height: 24px;
  border: 0; border-radius: 6px; background: none; color: var(--text-faint);
  font-size: 17px; line-height: 1; cursor: pointer; }
.mvcard .x:hover { background: var(--surface-hover); color: var(--text); }


/* La tira de contexto, debajo del gráfico grande. */
.ctxwrap { margin-top: 2px; }
.ctxstrip { display: block; width: 100%; height: 40px;
  border: 1px solid var(--line); border-radius: 6px; background: var(--surface-sunken); }
.ctxejes { display: flex; justify-content: space-between; margin-top: 3px;
  font-size: var(--size-2xs); color: var(--text-faint); }


/* «Where this thread stands». El veredicto grande y los números debajo: son
   dos cosas distintas y la segunda es la que lo sostiene, así que la primera
   no puede parecer un titular suelto. */
.card.stand .stand-v { font-size: var(--size-lg); line-height: 1.3;
  letter-spacing: -.2px; margin: 0 0 var(--s2); }
.card.stand .stand-b { margin: 0; color: var(--text-muted);
  font-size: var(--size-sm); line-height: 1.6; }
.card.stand .stand-b b { color: var(--text); font-variant-numeric: tabular-nums; }
.stand-top { border-top: 1px solid var(--line); }
.stand-row { display: grid; grid-template-columns: 78px 1fr; gap: var(--s3);
  align-items: baseline; padding: 8px 0; border-bottom: 1px solid var(--line);
  font-size: var(--size-sm); }
.stand-row b { font-size: var(--size-xs); color: var(--text-muted);
  font-variant-numeric: tabular-nums; }
@media (max-width: 560px) {
  .stand-row { grid-template-columns: 1fr; gap: 2px; }
}


/* La lectura de la mira. En HTML y no dentro del SVG: un `<text>` en un
   `viewBox` se escala con el dibujo y acaba con el tamaño que le toque en vez
   de con el que se lee. Y **encima** del gráfico, no debajo: en una pantalla
   táctil el dedo tapa justo el punto que está señalando. */
.chart-card { position: relative; }
.xh-read {
  position: absolute;
  /* `top` lo pone el guion sobre el borde del área de trazado; este valor es
     sólo el de partida antes del primer movimiento. */
  top: 0;
  z-index: 3;
  padding: 2px 8px;
  border: 1px solid var(--line-strong);
  border-radius: 6px;
  background: var(--bg-elevated);
  font-size: var(--size-2xs);
  font-variant-numeric: tabular-nums;
  color: var(--text);
  white-space: nowrap;
  pointer-events: none;
}
/* Un suceso se señala al pasar por encima, como cualquier cosa pulsable. */
.mv.ev circle:last-child { transition: r .1s; }
.mv.ev:hover circle:last-child { r: 5; }


/* Las muestras de la leyenda del gráfico: el mismo dibujo que la marca, para
   que lo que se explica y lo que se ve sean la misma cosa y no dos parecidas. */
.lg-ev, .lg-mv, .lg-macro { display: inline-block; vertical-align: middle; margin: 0 2px 0 6px; }
/* La muestra de macro: el mismo tic gris que se dibuja en el eje. Lleva
   `title`, así que el cursor de pregunta dice que hay algo que leer. */
.lg-macro { width: 0; height: 8px; border-left: 2px solid var(--text-faint); }
.lg-ev[title], .lg-mv[title], .lg-macro[title] { cursor: help; }
.lg-ev { width: 9px; height: 9px; border: 2px solid var(--accent);
  border-radius: 50%; background: var(--surface); }
.lg-mv { width: 0; height: 11px; border-left: 1px dashed var(--text-muted); }

/* --- La curva de la cartera, lo mejor y lo peor, y las pools ------------
   (2026-10-13) Pedido así: «también le tendremos que mostrar estadísticas al
   usuario de forma fácil con gráficos, y muy visual de cómo está su
   portfolio». */

/* El pie del gráfico: la cima, lo que se ha bajado desde ella y desde cuándo
   hay precio. En línea y no en tarjetas: son notas sobre el dibujo que está
   justo encima, y cuatro tarjetas más harían que el dibujo pareciera un
   adorno entre dos filas de números. */
.pf-curvefoot {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s4);
  margin-top: var(--s3);
  font-size: var(--size-xs);
}
.pf-curvefoot .eyebrow { margin: 0 4px 0 0; }
.pf-curvefoot b { font-variant-numeric: tabular-nums; }

.pf-extremes {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--s3);
  margin-bottom: var(--s4);
}
.pf-extremes .pf-c b { display: flex; align-items: baseline; gap: var(--s2); }
.pf-extremes a { color: inherit; }

/* El formulario de una pool: los cinco de siempre, y los nueve opcionales
   plegados dentro del mismo envío. */
/* `.pf-poolf` se fue con su formulario el 2026-10-14: la pool se abre
   ahora desde la ventana de su franja. `.pf-adv` sigue, dentro de ella. */
.pf-adv { margin-top: var(--s3); }
.pf-adv > summary {
  cursor: pointer;
  font-size: var(--size-xs);
  color: var(--text-muted);
  padding: var(--s2) 0;
}
.pf-adv > summary:hover { color: var(--text); }
.pf-adv[open] > summary { color: var(--text); margin-bottom: var(--s2); }
.pf-poolf > button { margin-top: var(--s3); }

.pf-t .num small { display: block; font-variant-numeric: tabular-nums; }
/* Las dos referencias de una sola moneda van una debajo de otra y pegadas al
   importe de arriba: son notas sobre él, no columnas nuevas. */
.pf-t .num small + small { margin-top: 1px; }
.pf-t .num small.down { font-weight: 600; }

/* El aviso de «esto es inventado» de la cartera de ejemplo.
   Ámbar y no rojo: no es un error, es una advertencia sobre qué se está
   mirando. Y ocupa el ancho entero arriba del todo porque la regla de la casa
   sobre las maquetas dice que no se puede confundir con un dato real, y aquí
   son cifras de dinero. */
.demo-aviso {
  border-color: color-mix(in srgb, var(--warn) 45%, transparent);
  background: color-mix(in srgb, var(--warn) 7%, var(--surface));
  margin-bottom: var(--s4);
}
.demo-aviso b { color: var(--text); }

/* La regla del gráfico: dos puntos y lo que hay entre ellos. */
svg.chart.big.midiendo { cursor: crosshair; }
svg.chart.big.midiendo a.mv { cursor: crosshair; }
.regla-read {
  position: absolute;
  z-index: 3;
  padding: 4px 9px;
  border: 1px solid var(--line-strong);
  border-radius: 7px;
  background: var(--surface);
  box-shadow: var(--shadow);
  font-size: var(--size-2xs);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  pointer-events: none;
}
.btn.sm[data-measure][aria-pressed="true"] {
  background: var(--accent-soft);
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
  color: var(--text);
}
/* El área de trazado es pulsable: lleva al día de ese punto. El cursor lo
   dice, porque una zona que reacciona y no lo parece no se usa. */
svg.chart.big.pulsable .xh-hit { cursor: pointer; }
svg.chart.big.midiendo .xh-hit { cursor: crosshair; }

/* El buscador del catálogo de alertas. */
.al-buscar { display: flex; gap: var(--s2); align-items: center; margin-bottom: var(--s2); }
.al-buscar input[type="search"] {
  flex: 1 1 auto;
  min-width: 0;
  max-width: 54ch;
  padding: 9px 12px;
  border: 1px solid var(--line-strong);
  border-radius: 9px;
  background: var(--surface);
  color: var(--text);
  font-size: var(--size-sm);
}
.al-buscar input[type="search"]:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.al-tipo h3 { font-weight: 640; }


/* Los datos del buzón. Dos columnas, la primera estrecha: lo que se copia es
   el valor, así que la etiqueta no puede llevarse el ancho.

   Las dos anulaciones del `th` global no son gusto. La de `border-bottom` quita
   una raya suelta bajo la etiqueta —el `th` global la lleva porque allí es una
   cabecera de columna, y aquí es la etiqueta de una fila—. La de `white-space`
   deja que «What is not served» parta en dos líneas: con `nowrap` se sale de la
   tarjeta en el móvil.

   Y por debajo de 560 px se apilan, porque «mail.blockboard.net» no cabe al
   lado de una etiqueta. */
.ml-t th {
  width: 10.5rem; vertical-align: top; border-bottom: 0;
  white-space: normal; color: var(--text-muted);
}
.ml-t td { vertical-align: top; }
.ml-t .faint { font-size: var(--size-2xs); margin-top: 2px; }
@media (max-width: 560px) {
  .ml-t th, .ml-t td { display: block; width: auto; }
  .ml-t th { padding-bottom: 0; }
  .ml-t td { padding-top: 2px; }
}


/* Las acciones por fila: cerrar parte de una posición, cobrar comisiones,
   sacar liquidez. Plegadas ocupan una línea, que es lo que permite que estén
   en **cada** fila sin convertir la tabla en un muro de formularios. */
.pf-act > td { padding-top: 0; border-bottom: 1px solid var(--line); }
.pf-act summary {
  cursor: pointer; color: var(--text-muted); font-size: var(--size-2xs);
  list-style: none; display: inline-flex; align-items: center; gap: 6px;
  padding: 2px 0;
}
.pf-act summary::-webkit-details-marker { display: none; }
.pf-act summary::before { content: "›"; transition: transform .12s ease; }
.pf-act details[open] summary::before { transform: rotate(90deg); }
.pf-cf {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--s3);
  margin-top: var(--s3);
}
.pf-cf label {
  display: flex; flex-direction: column; gap: 3px; margin: 0;
  font-size: var(--size-2xs); color: var(--text-muted);
}
.pf-cf input, .pf-cf select { width: 9rem; }
/* El móvil: los campos a lo ancho, que a 9rem no caben dos por línea. */
@media (max-width: 560px) {
  .pf-cf { flex-direction: column; align-items: stretch; }
  .pf-cf input, .pf-cf select, .pf-cf button { width: 100%; }
}

/* Los gráficos de la cartera (2026-10-14). */
/* Tres tarjetas desde el 2026-10-15 —el anillo, los sectores y las barras—, y
   arriba de la pantalla. El anillo pide menos ancho que las barras y los
   sectores se acomodan a lo que quede, de ahí las tres medidas distintas. */
.pf-vis {
  display: grid; grid-template-columns: minmax(0, 300px) minmax(0, 320px) minmax(0, 1fr);
  gap: var(--s3); margin-bottom: var(--s3);
}
.pf-vis > .card { padding: var(--s4); align-content: start; }
@media (max-width: 1180px) { .pf-vis { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 720px) { .pf-vis { grid-template-columns: 1fr; } }

/* El anillo y su leyenda, uno al lado del otro mientras quepan. */
.ring { display: flex; align-items: center; gap: var(--s4); margin-top: var(--s3); flex-wrap: wrap; }
.ring > svg { flex: 0 0 auto; }
.ring-key { list-style: none; margin: 0; padding: 0; min-width: 9rem; flex: 1 1 9rem; }
.ring-key li {
  display: flex; align-items: center; gap: var(--s2);
  font-size: var(--size-2xs); padding: 2px 0;
}
.ring-key .k { width: 9px; height: 9px; border-radius: 2px; flex: 0 0 auto; }
.ring-key .n { flex: 1 1 auto; color: var(--text-muted); }
.ring-key .v { font-variant-numeric: tabular-nums; }

/* Las barras: el texto va en unidades del viewBox, así que a 420 de ancho
   pintado en 300 px se encoge igual que todo lo demás. 11 px aquí se leen. */
svg.chart.pnl .ax { font-size: 11px; }
svg.chart.pnl { margin-top: var(--s3); display: block; }

/* La comparación de una pool: cuatro celdas en una tira (2026-10-15).

   Era una tarjeta con cuatro barras apiladas debajo de la fila —130 px de alto,
   su propio borde y su propio fondo dentro de la tabla— y el usuario lo dijo
   así: «esta muy mal integrada, es un diseño feo, ocupa demasiado en vertical,
   se ve horrible». Ahora son cuatro celdas sin marco, 44 px en total, sobre el
   mismo fondo que la fila: la comparación se lee igual y el marco desaparece.

   `auto-fit` y no cuatro columnas fijas: en el móvil se parten en dos y dos, y
   la celda más estrecha sigue cabiendo con su importe. */
.pf-scen { display: grid; gap: 1px; grid-template-columns: repeat(auto-fit, minmax(118px, 1fr));
  margin: 0 0 var(--s2); }
.pf-scen-c { padding: 4px var(--s2) 5px; min-width: 0;
  border-left: 1px solid var(--line); }
.pf-scen-c:first-child { border-left: 0; }
/* La mejor de las cuatro, marcada sin color de signo: «mejor» no es «ganancia»
   —puede ser la menos mala— y pintarla de verde diría lo otro. */
.pf-scen-c.win { background: var(--surface-sunken); border-radius: 6px; }
.pf-scen-c i { display: block; font-style: normal; font-size: var(--size-2xs);
  color: var(--text-faint); white-space: nowrap; overflow: hidden;
  text-overflow: ellipsis; }
.pf-scen-c b { font-size: var(--size-xs); font-variant-numeric: tabular-nums; }
.pf-scen-c s { display: block; text-decoration: none; font-size: var(--size-2xs);
  font-variant-numeric: tabular-nums; }
.pf-scen-b { display: block; height: 3px; border-radius: 2px; margin-top: 3px;
  background: var(--line); overflow: hidden; }
.pf-scen-b u { display: block; height: 100%; text-decoration: none;
  background: var(--accent); }
.pf-scen-c.win .pf-scen-b u { background: var(--up); }

/* El rango de una pool concentrada: una regla de 60 px con la marca del precio
   de hoy. Avisa **antes** de la salida —al 90 % se ve venir— que es cuando
   todavía se puede mover la posición. */
.pf-rng { display: block; position: relative; width: 60px; height: 4px;
  margin: 3px 0 2px; border-radius: 2px;
  background: linear-gradient(90deg, var(--line), var(--accent), var(--line)); }
.pf-rng.out { background: var(--line); }
.pf-rng i { position: absolute; top: -3px; width: 3px; height: 10px;
  border-radius: 2px; background: var(--text); margin-left: -1px; }
.pf-rng.out i { background: var(--down); }
/* Fuera de rango, y lo que no encaja: el único aviso de la sección que pide
   hacer algo, así que lleva el color del problema y no el gris de lo demás. */
.pf-oor { color: var(--down); font-size: var(--size-2xs); }
/* El reparto de hoy dentro de la pool, y cuánto se ha movido. */
.pf-split { font-size: var(--size-2xs); color: var(--text-muted);
  font-variant-numeric: tabular-nums; }
.pf-split i { font-style: normal; color: var(--text-faint); }

/* La línea de treinta días: ancho fijo para que la columna no baile de fila
   en fila, y fuera en el móvil, donde noventa y seis píxeles son un cuarto de
   la pantalla. */
.pf-spark { width: 104px; }
@media (max-width: 760px) { th.pf-spark, td.pf-spark { display: none; } }

/* **La tabla se desplaza dentro de su tarjeta, no por encima de ella.**
   Con la columna de treinta días, las posiciones piden 1.267 px y a 1440 de
   pantalla quedan 1.174: la tabla se salía del borde redondeado y la última
   columna quedaba cortada contra el fondo. Desplazarse dentro no pierde
   ningún dato y además protege de la próxima columna que se añada; esconder
   una sí lo perdería. Por debajo de 760 px no hace falta, porque ahí cada
   fila ya es una ficha. */
.pf-scroll { overflow-x: auto; }
/* **Y la tabla tiene que poder crecer dentro.** La regla global le pone
   `width: 100%`, así que dentro de un contenedor que se desplaza se quedaba
   encogida al ancho del contenedor mientras su contenido pedía trescientos
   píxeles más: el navegador repartía ese exceso por su cuenta y la cabecera
   acababa alineada en un sitio y las filas en otro, una encima de la otra.
   `max-content` deja que mida lo que necesita; `min-width: 100 %` evita que
   una tabla de dos columnas se quede en un palmo a la izquierda. */
.pf-scroll > table { width: max-content; min-width: 100%; }
@media (max-width: 760px) {
  .pf-scroll { overflow-x: visible; }
  .pf-scroll > table { width: auto; min-width: 0; }
}

/* La lista de seguimiento, en el móvil. Cinco columnas de ancho fijo —130 px
   para el nombre, 70, 1fr, 90 y 54— piden 418 px dentro de una tarjeta de 332,
   y la página entera se desbordaba a 472 sobre 390. Se reparte en dos líneas:
   el nombre arriba y los números debajo, que es como se lee de todas formas. */
@media (max-width: 560px) {
  .watch .row { grid-template-columns: 1fr auto auto; row-gap: 2px; }
  .watch .who { grid-column: 1 / -1; }
  .watch .last { display: none; }
}

/* La carrera, ahora como pieza del terminal. Era la portada hasta el
   2026-10-14 y ocupaba la pantalla entera; aquí vive en una caja que se puede
   hacer pequeña, así que el titular se recorta en vez de empujar al gráfico. */
.rc-title {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; font-weight: 640; font-size: var(--size-sm);
  line-height: 1.3; margin-bottom: var(--s3);
}
.rc-wrap { margin: 0 calc(var(--s2) * -1); }
.rc-say { font-size: var(--size-2xs); color: var(--text-muted); margin: var(--s3) 0 0; }

/* --- El estilo de las cajas del terminal, en el resto del sitio ----------
   Pedido el 2026-10-14: «quiero que adoptes el estilo visual de las cajas de
   terminal al resto de las cajas de la pagina en cada uno de los sitios».

   **La diferencia entre una caja del terminal y una caja normal no eran los
   materiales**: las dos usan el mismo fondo, el mismo borde, el mismo radio y
   la misma sombra. Era que la del terminal tiene **una banda con su nombre** y
   una franja de acento a la izquierda, y la normal lleva el título suelto
   flotando encima. Medido: hay 25 sitios en el sitio donde un `<h2>` está
   justo encima de una `.card`, y en los 25 el título **es** el título de esa
   caja aunque esté fuera de ella.

   Así que se pegan, y la banda sale de la misma regla que la del terminal.
   Sin tocar ni una plantilla: el patrón ya estaba escrito, lo que faltaba era
   que la hoja de estilos lo reconociera.

   `@supports selector(:has(*))` no es cosmético. Sin `:has` no se puede saber
   si un título tiene una caja detrás, y la mitad del arreglo —quitarle el
   borde de arriba a la caja— dejaría una caja abierta por arriba con un
   título suelto encima. Dentro del `@supports`, un navegador que no lo
   entienda ve exactamente lo que veía ayer. */
@supports selector(:has(*)) {
  h2:has(+ .card),
  .svc-h:has(+ .card),
  /* **Y la otra mitad del patrón**: catorce sitios escriben la cabecera como
     un `div.meta` con el `<h2>` y la «i» dentro, que es exactamente la banda
     del terminal escrita a mano. Se reconoce igual. */
  .meta:has(> h2):has(+ .card) {
    margin: var(--s6) 0 0;
    padding: var(--s2) var(--s3) var(--s2) calc(var(--s3) - 2px);
    border: 1px solid var(--line);
    border-bottom: 0;
    border-left: 2px solid var(--accent);
    border-radius: var(--radius) var(--radius) 0 0;
    background: var(--surface-sunken);
    font-size: var(--size-base);
    font-weight: 700;
    letter-spacing: -0.015em;
    display: flex;
    align-items: center;
    gap: var(--s2);
  }
  /* `!important` en el margen de abajo, y por una vez está justificado: esos
     catorce `div.meta` llevan el margen **en un atributo `style`** —glue de la
     disposición anterior, cuando el título flotaba encima— y un atributo gana
     a la hoja. La alternativa era editar catorce plantillas para quitar una
     separación que sólo sobra cuando la cabecera y la caja se pegan, que es
     justo lo que esta regla sabe y la plantilla no. Va dentro del
     `:has(+ .card)`, así que no toca ninguna cabecera suelta. */
  .meta:has(> h2):has(+ .card) { margin-bottom: 0 !important; }
  .meta:has(> h2):has(+ .card) > h2 {
    font-size: var(--size-base);
    font-weight: 700;
    letter-spacing: -0.015em;
  }
  .meta:has(> h2):has(+ .card) > .info { margin-left: auto; }

  /* El primero de la página no necesita separarse de nada. */
  .page-head + h2:has(+ .card),
  .page-head + .svc-h:has(+ .card),
  .page-head + .meta:has(> h2):has(+ .card) { margin-top: var(--s4); }

  h2:has(+ .card) + .card,
  .svc-h:has(+ .card) + .card,
  .meta:has(> h2) + .card {
    margin-top: 0;
    border-top-left-radius: 0;
    border-top-right-radius: 0;
  }

  /* Lo que acompaña al título dentro de la banda —el recuento, la «i»— se
     alinea con él en vez de empujarlo, igual que en el terminal. */
  h2:has(+ .card) .faint,
  .svc-h:has(+ .card) .faint { font-weight: 500; }
  h2:has(+ .card) > .info,
  .svc-h:has(+ .card) > .info { margin-left: auto; }
}

/* --- La ventanita de una fila -------------------------------------------
   Pedido el 2026-10-14: «quizas dos botones a la derecha de la fila uno con
   add y otro sell […] y que se abra un pequeño popup», y sobre lo que había
   antes: «esta fuera de lugar no es bonito es gigante».

   Tenía razón: era un `<details>` que al abrirse empujaba la tabla entera
   hacia abajo con un formulario a lo ancho de la pantalla. Esto es el mismo
   `<details>` —así que **sigue funcionando con el script caído**, que es la
   regla de la casa para todo lo que escribe— con el panel sacado del flujo:
   se posiciona sobre la tabla en vez de partirla.

   No se usa `<dialog>` por eso mismo: un `<dialog>` sin JavaScript está
   `display:none` y el formulario sería inalcanzable. El `popover` nativo tiene
   el mismo problema. Un `<details>` abierto es HTML, sin más. */
.pop { position: relative; display: inline-block; }
.pop > summary {
  list-style: none; cursor: pointer; user-select: none;
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 9px; border: 1px solid var(--line-strong); border-radius: var(--radius-sm);
  font-size: var(--size-2xs); font-weight: 600; color: var(--text-muted);
  background: var(--surface); white-space: nowrap;
}
.pop > summary::-webkit-details-marker { display: none; }
.pop > summary:hover { color: var(--text); border-color: var(--accent); }
.pop[open] > summary { color: var(--text); border-color: var(--accent); background: var(--accent-soft); }
.pop > summary.buy:hover, .pop[open] > summary.buy { color: var(--up); border-color: var(--up); }
.pop > summary.sell:hover, .pop[open] > summary.sell { color: var(--down); border-color: var(--down); }

/* **`fixed` y centrada, no colgando del botón.** Medido en el navegador: con
   `position: absolute`, la tarjeta de la tabla la recortaba por abajo y sólo
   se veía el primer campo. La culpa es del `overflow-x: auto` que esas
   tarjetas necesitan para que una tabla ancha se desplace dentro en vez de
   salirse — y `overflow` recorta a los descendientes posicionados **salvo** a
   los `fixed`. Así que se centra en la pantalla, que además es lo correcto en
   un teléfono y no necesita saber si el botón está arriba o abajo del todo. */
.pop-panel {
  position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);
  z-index: 60; width: 21rem; max-width: calc(100vw - var(--s5) * 2);
  max-height: calc(100vh - var(--s6) * 2); overflow-y: auto;
  padding: var(--s5); text-align: left;
  background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: var(--radius); box-shadow: var(--shadow);
}
/* El velo. Sin él, una ventana centrada sobre una tabla llena de cifras no se
   lee como una ventana: se lee como un trozo suelto.

   Va en el `::after` del `summary` y **no** en el `::before` del panel, que es
   donde lo puse primero y se veía mal: el panel lleva `z-index`, así que crea
   su propio contexto de apilado, y dentro de él un `z-index: -1` queda por
   encima del fondo del panel en vez de por debajo. El resultado era la ventana
   atenuada y la página detrás intacta, justo al revés. Colgado del `summary`,
   que no crea contexto, el velo vive en la raíz y se apila como toca. */
.pop[open] > summary::after {
  content: ""; position: fixed; inset: 0; z-index: 55;
  background: rgba(8, 11, 18, 0.5);
}
/* **Ancha para lo que es una tabla y no un formulario** (2026-10-14): el
   registro de apuntes tiene ocho columnas, y a 21rem cada fila se parte en
   cuatro líneas. Sigue cabiendo en un teléfono por el `max-width`. */
.pop-panel.wide { width: 46rem; }
.pop-panel h4 { font-size: var(--size-sm); font-weight: 700; margin: 0 0 var(--s3); }
.pop-panel label {
  display: block; margin: 0 0 var(--s3);
  font-size: var(--size-2xs); color: var(--text-muted);
}
.pop-panel label input, .pop-panel label select { width: 100%; margin-top: 3px; }
.pop-panel .dos { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3); }
/* **`hidden` tiene que ganar, y aquí no ganaba** (2026-10-15).
   Y esto es la causa de la queja, no un detalle: «el formulario repite amount
   a, amount a now, avanzado… no es nada intuitivo». La regla de arriba pone
   `display: grid` con dos clases, y el `display: none` que el navegador trae
   para `[hidden]` vive en su hoja por defecto, así que **pierde siempre**.
   Resultado: el guion escondía el bloque que no tocaba —ponía el atributo y
   desactivaba sus campos, así que ni se enviaban— y se seguía viendo. La
   repetición que el usuario vio era exactamente eso.
   Medido con navegador antes y después: antes salían a la vez «Amount A inside
   today» y el rango; ahora sale uno u otro según el sitio elegido. */
.pop-panel [hidden] { display: none !important; }
.pop-panel .dos label { margin-bottom: 0; }
.pop-panel .pie { display: flex; align-items: center; gap: var(--s3); margin-top: var(--s4); }
.pop-panel .pie button { flex: 1; }
.pop-panel .nota {
  font-size: var(--size-2xs); color: var(--text-faint);
  margin: var(--s3) 0 0; line-height: 1.45;
}

/* El simulador de una pool (2026-10-15): una tabla estrecha dentro de su
   ventana, y debajo la casilla del precio a medida. */
.sim-t { font-size: var(--size-2xs); }
.sim-t td, .sim-t th { padding: 5px var(--s2); }
.sim-ask { display: flex; align-items: flex-end; gap: var(--s2); flex-wrap: wrap;
  margin-top: var(--s3); }
.sim-ask label { flex: 1 1 10rem; margin: 0; }
.sim-ask [data-sim-out] { flex: 1 1 100%; margin: 0; color: var(--text); }

/* El enlace a una pool concreta en la tabla de rendimientos (2026-10-15).
   Pequeño y al lado del nombre: es una salida, no la acción de la fila. */
.pool-go { font-size: var(--size-2xs); margin-left: 6px; white-space: nowrap; }

/* El fallo de un formulario, **dentro de su ventana** (2026-10-15). Antes la
   ventana se cerraba y el aviso salía arriba del todo, lejos de donde se
   estaba mirando y con lo escrito ya perdido: «si esta mal no debe cerrar,
   debe indicar que esta mal». */
.pop-error {
  margin: 0 0 var(--s3); padding: var(--s2) var(--s3);
  border: 1px solid var(--down); border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--down) 10%, transparent);
  color: var(--text); font-size: var(--size-xs); line-height: 1.45;
}

/* Los porcentajes de la venta (2026-10-15): encima de la caja que rellenan,
   que es donde se pidieron. Son botones de envío de verdad —sin JavaScript
   envían su porcentaje— y por eso llevan el aspecto de pastilla y no el de
   botón principal: lo que hacen es rellenar, no confirmar. */
.pf-pcts { display: flex; gap: var(--s2); margin-bottom: var(--s2); }
.pf-pct { flex: 1; padding: 5px 0; border: 1px solid var(--line-strong);
  border-radius: 999px; background: var(--surface); color: var(--text-muted);
  font-size: var(--size-2xs); font-weight: 600; cursor: pointer; }
.pf-pct:hover { border-color: var(--accent); color: var(--text); }
.pf-pct.on { border-color: var(--accent); color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent); }

/* La sugerencia del precio de hoy (2026-10-15). Nace vacía y la escribe
   `portfolio.js` al elegir la moneda: en acento, para que se distinga de la
   nota de ayuda de al lado —una dice qué escribir y la otra dice qué hemos
   puesto—, y con `:empty` sin margen para no dejar un hueco cuando no hay
   nada que decir. */
.pop-panel .quote-tip { color: var(--accent); }
.pop-panel .quote-tip:empty { margin: 0; }

/* La flechita que despliega el registro de una fila. */
.reg-abre {
  list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 4px;
  font-size: var(--size-2xs); color: var(--text-muted);
}
.reg-abre::-webkit-details-marker { display: none; }
.reg-abre::before { content: "›"; display: inline-block; transition: transform .12s ease; }
details[open] > .reg-abre::before { transform: rotate(90deg); }
.reg { width: 100%; margin-top: var(--s2); font-size: var(--size-2xs); }
.reg th { font-size: var(--size-2xs); padding: 3px var(--s3) 3px 0; border-bottom-color: var(--line); }
.reg td { padding: 4px var(--s3) 4px 0; border-bottom: 1px solid var(--line); }
.reg tr:last-child td { border-bottom: 0; }
.reg .k {
  display: inline-block; padding: 1px 6px; border-radius: 3px;
  background: var(--surface-sunken); font-size: var(--size-2xs); font-weight: 600;
}

/* --- La pantalla de marca del panel (2026-10-14) --------------------------
 *
 * Diez logotipos que hay que **comparar**, no leer. Así que van en rejilla y
 * no en lista: una lista vertical obliga a recordar el tercero cuando miras el
 * noveno, y elegir un dibujo es justo lo contrario: verlos todos a la vez.
 *
 * Cada ficha enseña el mismo dibujo tres veces porque un logotipo se rompe de
 * tres maneras distintas: pequeño se empasta, grande se queda vacío y en un
 * solo color pierde lo que separaba las partes. Los tres tamaños están en la
 * ficha para que el fallo se vea antes de elegir, y no un mes después.
 */
.logogrid {
  display: grid; gap: var(--s4); margin: var(--s4) 0 var(--s5);
  grid-template-columns: repeat(auto-fill, minmax(230px, 1fr));
}
.logo-op {
  display: grid; gap: var(--s2); padding: var(--s4); cursor: pointer;
  grid-template-rows: auto auto 1fr;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface); position: relative;
  transition: border-color .12s ease, background .12s ease;
}
.logo-op:hover { border-color: var(--line-strong); }
/* El elegido se marca con el borde entero y no con un puntito: a dos metros
   de la pantalla, el puntito no se ve y el borde sí. */
.logo-op.on,
/* Y al pulsar, sin recargar: `.on` lo pone el servidor con lo que está
   guardado, así que sin esto marcar otro no movería el borde hasta guardar. */
.logo-op:has(input:checked) {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
}
.logo-op input { position: absolute; top: var(--s3); right: var(--s3); accent-color: var(--accent); }
.logo-op .muestras {
  display: flex; align-items: center; gap: var(--s4); min-height: 68px;
}
.logo-op .s64 { line-height: 0; }
/* El plano va sobre fondo claro **siempre**, también con el sitio en oscuro:
   es la prueba que tiene que pasar —un favicon sobre una pestaña blanca— y
   enseñarlo sobre fondo oscuro sería enseñar justo lo que no hace falta. */
.logo-op .plano {
  line-height: 0; padding: 6px; border-radius: 6px;
  background: #fff; color: #0c0f16;
}
.logo-op b { font-size: var(--size-sm); }
.logo-op .idea {
  font-size: var(--size-2xs); color: var(--text-muted); line-height: 1.5;
}

/* --- Las tres piezas de quien mira (2026-10-14) ---------------------------
 *
 * La cartera, el reparto y el seguimiento dentro del terminal. Todo lo que hay
 * aquí existe por una razón: **una pieza del terminal puede medir tres
 * columnas o doce**, y lo que se lee bien ancho se amontona estrecho. Las
 * cifras van en una rejilla que se parte sola, la curva ocupa el ancho que
 * haya y las tablas sueltan columnas antes que encogerlas hasta lo ilegible.
 */
/* **Rehechas el 2026-10-14.** Queja textual: «los widget de portfolio son muy
 * basicos sin estilos visuales, no me gustan nada […] hasta ensucian lo bonito
 * que esta el terminal».
 *
 * Lo que fallaba no era el color, era la **jerarquía**: tres cifras del mismo
 * tamaño en fila y una tabla sin cabecera: nada decía qué mirar primero, así
 * que todo pesaba igual. Ahora hay una cifra grande con la curva detrás, una
 * tira de tres pequeñas y las posiciones con su barra de peso.
 */
.w-pf { display: flex; flex-direction: column; gap: var(--s3); }

/* El valor, con la curva de fondo. `position: relative` y la curva en absoluto
   detrás: ocupa el hueco que el número deja libre en vez de pedir su propia
   fila, que en una pieza de cuatro filas de alto es la mitad del sitio. */
.w-pf-hero { position: relative; padding: 2px 0 4px; }
.w-pf-bg { position: absolute; inset: auto 0 0; z-index: 0; opacity: .5;
  pointer-events: none; }
.w-pf-bg svg { width: 100%; height: 72px; display: block; }
.w-pf-hero .eyebrow, .w-pf-big, .w-pf-day { position: relative; z-index: 1; }
.w-pf-hero .eyebrow { display: block; margin-bottom: 2px; }
.w-pf-big { display: block; font-size: var(--size-xl); line-height: 1.1;
  font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
/* El día, en una píldora del color del signo: es la cifra que se busca
   después del valor, y suelta en gris se perdía entre las otras tres. */
.w-pf-day { display: inline-flex; align-items: baseline; gap: 6px; margin-top: 4px;
  padding: 2px 8px; border-radius: 999px; font-size: var(--size-xs); font-weight: 600;
  font-variant-numeric: tabular-nums; }
.w-pf-day.up { background: color-mix(in srgb, var(--up) 15%, transparent); }
.w-pf-day.down { background: color-mix(in srgb, var(--down) 15%, transparent); }
.w-pf-day i { font-style: normal; font-weight: 400; font-size: var(--size-2xs);
  color: var(--text-muted); }

/* Los sectores de la pieza del reparto: cuatro pares nombre/porcentaje en una
   rejilla que se parte sola. No llevan barra a propósito —no suman 100 %, y
   una barra sobre un total que no existe miente sobre la escala. */
.w-al-sec { display: grid; gap: 1px var(--s3); margin: var(--s2) 0 0;
  grid-template-columns: repeat(auto-fit, minmax(104px, 1fr));
  font-size: var(--size-2xs); }
.w-al-sec span { display: flex; justify-content: space-between; gap: var(--s2);
  border-bottom: 1px solid var(--line); padding: 2px 0; }
.w-al-sec i { font-style: normal; color: var(--text-muted); overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
.w-al-sec b { font-weight: 600; font-variant-numeric: tabular-nums; }

.w-pf-btc { font-size: .5em; font-weight: 500; color: var(--text-muted);
  margin-left: .4em; letter-spacing: 0; white-space: nowrap; }

/* Los plazos, como los de la cajita de una moneda: una tira fina que se parte
   sola y que es lo primero que sobra cuando la pieza encoge —son contexto. */
.w-pf-spans { display: flex; flex-wrap: wrap; gap: 2px var(--s3);
  margin: var(--s2) 0; font-size: var(--size-2xs); }
.w-pf-spans i { font-style: normal; color: var(--text-faint); margin-right: 3px;
  text-transform: uppercase; letter-spacing: .06em; }
.w-pf-spans b { font-weight: 600; font-variant-numeric: tabular-nums; }

/* Las tres que acompañan. Se parten solas: la misma pieza puede medir tres
   columnas o doce, y a tres columnas tres cajas en fila son ilegibles. */
.w-pf-stats { display: grid; gap: var(--s2);
  grid-template-columns: repeat(auto-fit, minmax(92px, 1fr)); }
.w-pf-stats > div { padding: var(--s2); border: 1px solid var(--line);
  border-radius: 8px; background: var(--bg-elevated); }
.w-pf-stats i { display: block; font-style: normal; font-size: var(--size-2xs);
  color: var(--text-faint); text-transform: uppercase; letter-spacing: .06em; }
.w-pf-stats b { font-size: var(--size-sm); font-variant-numeric: tabular-nums; }
.w-pf-stats s { display: block; text-decoration: none; font-size: var(--size-2xs);
  color: var(--text-muted); }

/* Las posiciones. Rejilla y no tabla: con cuatro columnas de ancho fijo, la
   barra de peso es lo primero que se queda sin sitio, y es el dato que dice si
   esto es una cartera o una apuesta con cinco nombres. */
.w-pf-pos { list-style: none; margin: 0; padding: 0; display: flex;
  flex-direction: column; }
.w-pf-pos li { display: grid; align-items: center; gap: var(--s2);
  grid-template-columns: minmax(56px, auto) 1fr auto auto;
  padding: 5px 0; border-bottom: 1px solid var(--line); font-size: var(--size-xs); }
.w-pf-pos li:last-child { border-bottom: 0; }
.w-pf-sym { display: inline-flex; align-items: center; gap: 5px; color: var(--text); }
.w-pf-sym img { border-radius: 50%; }
.w-pf-bar { display: block; height: 5px; border-radius: 3px; background: var(--line);
  overflow: hidden; min-width: 24px; }
.w-pf-bar i { display: block; height: 100%; background: var(--accent); }
.w-pf-v, .w-pf-c { font-variant-numeric: tabular-nums; text-align: right; }
.w-pf-c { min-width: 52px; }
.w-pf-more { font-size: var(--size-xs); }

/* El titular del reparto: la mayor posición y cuánto se come. Un anillo solo
   obliga a buscar en la leyenda cuál es el arco gordo, que es la respuesta. */
.w-al-top { margin-bottom: var(--s2); }
.w-al-top .eyebrow { display: block; }
.w-al-top b { font-size: var(--size-md); }
.w-al-pct { color: var(--accent); font-variant-numeric: tabular-nums; }
.w-al-top i { display: block; font-style: normal; font-size: var(--size-2xs); }

/* La tabla de la pieza de seguimiento vivía aquí y se fue con ella el
   2026-10-14: la pieza se retiró por repetir lo que hace el panel de mercado.
   La lista sigue entera en `/watchlist`, con sus propios estilos. */
/* El anillo centrado cuando la pieza es estrecha, y con la leyenda al lado
   cuando hay sitio: lo decide el ancho de la pieza, no el de la ventana. */
.piece .ring { justify-content: center; }

/* El selector de rango de una pool concentrada (2026-10-15).
   Pedido así: «uniswap te permite colocar la posicion arrastrando unas bandas
   sobre un grafico que te muestra el precio actual en el medio […] quiero que
   registrar una pool no lleve mas de un minuto».

   Tres capas en el mismo carril: el precio real de los noventa días al fondo,
   la banda elegida encima y las dos asas por delante. La escala es
   logarítmica —la hace el script— porque un rango se piensa en tanto por
   ciento y así ±20 % son dos tramos iguales a los dos lados. */
.pf-band { margin: 0 0 var(--s3); }
.pf-band-top {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--s2); margin-bottom: 6px; flex-wrap: wrap;
}
.pf-band-now { font-size: var(--size-2xs); color: var(--text-muted); }
.pf-band.fuera .pf-band-now { color: var(--down); }
.pf-band-btns { display: flex; gap: 4px; }
.pf-band-track {
  position: relative; height: 64px; border: 1px solid var(--line);
  border-radius: var(--radius-sm); background: var(--surface-sunken);
  touch-action: none; /* arrastrar no tiene que desplazar la página */
}
.pf-band-svg { position: absolute; inset: 0; width: 100%; height: 100%; }
.pf-band-svg path { stroke: var(--text-muted); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.pf-band-fill {
  position: absolute; top: 0; bottom: 0;
  background: color-mix(in srgb, var(--accent) 18%, transparent);
  border-left: 1px solid var(--accent); border-right: 1px solid var(--accent);
}
.pf-band.fuera .pf-band-fill {
  background: color-mix(in srgb, var(--down) 14%, transparent);
  border-color: var(--down);
}
/* El precio de hoy: una línea y no un punto, para que se vea si la banda lo
   contiene o se ha quedado a un lado. */
.pf-band-spot {
  position: absolute; top: -3px; bottom: -3px; width: 2px; margin-left: -1px;
  background: var(--text);
}
.pf-band-grip {
  position: absolute; top: 50%; width: 14px; height: 30px; margin: -15px 0 0 -7px;
  padding: 0; border: 1px solid var(--accent); border-radius: 3px;
  background: var(--surface); cursor: ew-resize;
}
.pf-band-grip::after {
  content: ''; position: absolute; inset: 40% 4px; border-top: 1px solid var(--accent);
  border-bottom: 1px solid var(--accent);
}
.pf-band-grip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* **El carril vacío: se ve, se entiende y no se puede arrastrar** (2026-10-16).
   Mientras no hay precio de la pareja no hay escala, así que arrastrar no
   significaría nada; lo que sí tiene que haber es el hueco a la vista, para que
   quien abre el formulario sepa que el rango se pone aquí y no en las dos
   casillas de abajo. */
.pf-band.vacia .pf-band-track {
  border-style: dashed;
  background:
    repeating-linear-gradient(135deg, transparent 0 7px,
      color-mix(in srgb, var(--line) 45%, transparent) 7px 8px);
}
.pf-band.vacia .pf-band-grip,
.pf-band.vacia .pf-band-fill,
.pf-band.vacia .pf-band-spot { display: none; }
.btn.xs { padding: 2px 6px; font-size: var(--size-2xs); line-height: 1.4; }
