/*
 * Las tres tipografías, servidas desde este dominio.
 *
 * ── Por qué se auto-alojan ───────────────────────────────────────────────
 *
 * Estaban en Google Fonts, y eso significa que **la IP de cada visitante
 * viajaba a Google** — incluida la de quien solo abre la landing y no se
 * registra. Un tribunal de Múnich condenó exactamente eso en 2022.
 *
 * Era, además, el único tercero al que llegaban todos los visitantes: la SEC y
 * Finnhub los llama el servidor, y Supabase solo entra en juego con sesión.
 * Auto-alojar quita a Google del mapa entero.
 *
 * El `index.html` ya lo tenía anotado como pendiente («alternativa a un paso:
 * auto-alojar los .woff2 en /public»), y `_headers` decía que al hacerlo «estos
 * dos dominios se pueden borrar y la CSP queda más cerrada». Hecho las dos
 * cosas el 5-sep-2026.
 *
 * ── Solo `latin` y `latin-ext` ───────────────────────────────────────────
 *
 * Google servía además cirílico y vietnamita. El navegador no los descargaba
 * —el `unicode-range` se lo impide— pero eran quince bloques de CSS que no
 * pintan nada en una web en castellano.
 *
 * ── Los `unicode-range` se conservan, y no es decoración ─────────────────
 *
 * Es lo que hace que un navegador que solo pinta «Patrimonio» descargue el
 * fichero `latin` y NO el `latin-ext`. Quitarlos obligaría a bajar los dos
 * siempre.
 *
 * ── Licencia ─────────────────────────────────────────────────────────────
 *
 * Las tres son SIL Open Font License 1.1, que permite alojarlas uno mismo
 * siempre que se acompañen el aviso de copyright y la licencia. Están en
 * `public/fuentes/OFL.txt`.
 *
 * GENERADO por `scripts/` a partir del CSS de Google. Si hay que añadir un peso
 * nuevo, se regenera; no se edita a mano.
 */

/* latin-ext */
@font-face {
  font-family: 'Fraunces';
  font-style: italic;
  font-weight: 300;
  font-display: swap;
  src: url('/fuentes/fraunces-300-italic-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: 'Fraunces';
  font-style: italic;
  font-weight: 300;
  font-display: swap;
  src: url('/fuentes/fraunces-300-italic-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* latin-ext */
@font-face {
  font-family: 'Fraunces';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('/fuentes/fraunces-300-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: 'Fraunces';
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url('/fuentes/fraunces-300-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* latin-ext */
@font-face {
  font-family: 'Fraunces';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fuentes/fraunces-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: 'Fraunces';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fuentes/fraunces-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* latin-ext */
@font-face {
  font-family: 'Hanken Grotesk';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fuentes/hanken-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: 'Hanken Grotesk';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fuentes/hanken-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* latin-ext */
@font-face {
  font-family: 'Hanken Grotesk';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fuentes/hanken-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: 'Hanken Grotesk';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fuentes/hanken-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* latin-ext */
@font-face {
  font-family: 'Hanken Grotesk';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fuentes/hanken-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: 'Hanken Grotesk';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fuentes/hanken-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* latin-ext */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fuentes/plexmono-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fuentes/plexmono-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* latin-ext */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fuentes/plexmono-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* latin */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fuentes/plexmono-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Estilos mínimos y provisionales. El diseño de verdad llega cuando estén
   los cuatro módulos: aquí lo único que importa es que se pueda usar y
   leer sin que duela. */

:root {
  --fondo: #0e1116;
  --superficie: #161b22;
  --borde: #2a313c;
  --texto: #e6edf3;
  --apagado: #9aa7b4;
  --acento: #4c9aff;
  --error: #ff6b6b;
  color-scheme: dark;
}

/* Variante clara de la paleta PROVISIONAL. Las pantallas sin portar (admin y
   el pipeline Pro) la siguen usando: sin esto quedarían texto claro sobre
   fondo claro en cuanto alguien tocara el tema. */
:root[data-theme='light'] {
  --fondo: #f6f4ef;
  --superficie: #ffffff;
  --borde: #ddd8cd;
  --texto: #1c1a17;
  --apagado: #6c7079;
  --acento: #1f6feb;
  --error: #c92a2a;
  color-scheme: light;
}

* {
  box-sizing: border-box;
}

/* El fondo de la página sale de los tokens del REDISEÑO, no de la paleta
   provisional: `--fondo` no tiene variante clara, así que con `data-theme=light`
   el body seguía pintándose azul oscuro y las pantallas portadas quedaban con
   tarjetas claras flotando sobre un fondo negro. El login no lo delataba porque
   pinta su propio fondo. */
body {
  margin: 0;
  /* El relleno del body, en variables para que quien lo necesite CANCELAR no
     tenga que repetir los números (ver `.ji-acceso`). El de abajo crece en
     móvil para dejar sitio a la barra inferior (`disenio.css`). */
  --ji-pad-x: 1.5rem;
  --ji-pad-y: 1.5rem;
  --ji-pad-abajo: 1.5rem;
  padding: var(--ji-pad-y) var(--ji-pad-x) var(--ji-pad-abajo);
  background: var(--ji-bg);
  color: var(--ji-text);
  font-family: system-ui, -apple-system, 'Segoe UI', sans-serif;
  line-height: 1.55;
}

h1 {
  font-size: 1.5rem;
  margin: 0 0 0.5rem;
}

h2 {
  font-size: 1.05rem;
  margin: 0 0 0.25rem;
}

a {
  color: var(--acento);
}

.tarjeta {
  max-width: 26rem;
  margin: 3rem auto;
  padding: 1.75rem;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: 12px;
}

.ancho {
  max-width: 60rem;
  margin: 0 auto;
}

.cabecera {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

form {
  display: flex;
  flex-direction: column;
  margin-top: 1.25rem;
}

label {
  font-size: 0.85rem;
  color: var(--apagado);
  margin-bottom: 0.3rem;
}

input {
  padding: 0.6rem 0.7rem;
  margin-bottom: 1rem;
  background: var(--fondo);
  border: 1px solid var(--borde);
  border-radius: 8px;
  color: var(--texto);
  font-size: 1rem;
}

input:focus {
  outline: 2px solid var(--acento);
  outline-offset: 1px;
}

/*
 * EL BOTÓN PRINCIPAL, DORADO (13-sep-2026). Era azul (`--acento`) y convivía
 * con el dorado del sistema de diseño (`.ji-btn-principal`): en la cuenta
 * «Guardar» salía azul, y en Solicitudes o en las nóminas, dorado. Javi pidió
 * unificarlo. Los selectores que usaban el azul como «apagado» —Sí/No/No sé y
 * la convicción de la criba, «Más antiguo primero»— tienen ahora su estado
 * apagado propio, más abajo.
 */
button {
  padding: 0.65rem 1rem;
  background: var(--ji-gold-solid);
  border: none;
  border-radius: 8px;
  color: #0d1119;
  font-size: 0.95rem;
  font-weight: 600;
  cursor: pointer;
}

button:disabled {
  opacity: 0.6;
  cursor: default;
}

button.secundario {
  background: transparent;
  border: 1px solid var(--borde);
  color: var(--texto);
  font-weight: 500;
}

.botonera {
  display: flex;
  gap: 0.6rem;
  margin-top: 1.25rem;
  flex-wrap: wrap;
}

.apoyo {
  color: var(--apagado);
  font-size: 0.92rem;
}

.pista {
  color: var(--apagado);
  font-size: 0.8rem;
  margin: -0.5rem 0 1rem;
}

.error {
  color: var(--error);
  font-size: 0.9rem;
  margin: 0 0 1rem;
}

.aviso {
  text-align: center;
  color: var(--apagado);
  margin-top: 4rem;
}

.rejilla {
  list-style: none;
  padding: 0;
  margin: 1.5rem 0 0;
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}

.modulo {
  padding: 1.1rem;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: 12px;
}

.modulo p {
  color: var(--apagado);
  font-size: 0.9rem;
  margin: 0 0 0.5rem;
}

.modulo.apagado {
  opacity: 0.55;
}

.modulo-enlace:hover .pista {
  color: var(--acento);
}

.volver {
  font-size: 0.9rem;
  text-decoration: none;
}

/* --- Módulos de cálculo ------------------------------------------- */

.dos-columnas {
  display: grid;
  gap: 2rem;
  grid-template-columns: minmax(0, 20rem) minmax(0, 1fr);
  align-items: start;
  margin-top: 1.5rem;
}

/* En pantalla estrecha, el formulario encima del resultado. */
@media (max-width: 46rem) {
  .dos-columnas {
    grid-template-columns: 1fr;
    gap: 1.25rem;
  }
}

select {
  padding: 0.6rem 0.7rem;
  margin-bottom: 1rem;
  background: var(--fondo);
  border: 1px solid var(--borde);
  border-radius: 8px;
  color: var(--texto);
  font-size: 1rem;
}

.semaforo {
  padding: 0.9rem 1rem;
  border-radius: 10px;
  border-left: 4px solid;
  margin-bottom: 1.25rem;
}

.semaforo p {
  margin: 0.35rem 0 0;
  font-size: 0.9rem;
  color: var(--apagado);
}

.semaforo.verde {
  border-color: #3fb950;
  background: rgb(63 185 80 / 10%);
}

.semaforo.ambar {
  border-color: #d29922;
  background: rgb(210 153 34 / 10%);
}

.semaforo.rojo {
  border-color: #f85149;
  background: rgb(248 81 73 / 10%);
}

.datos {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.4rem 1.25rem;
  margin: 0 0 1.5rem;
}

.datos dt {
  color: var(--apagado);
  font-size: 0.88rem;
}

.datos dd {
  margin: 0;
  font-variant-numeric: tabular-nums;
}

.destacado {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 1.25rem;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: 12px;
  margin-bottom: 1.25rem;
}

.cifra {
  font-size: 2rem;
  font-weight: 650;
  font-variant-numeric: tabular-nums;
}

.aviso-caja {
  padding: 0.75rem 0.9rem;
  border-left: 4px solid #d29922;
  background: rgb(210 153 34 / 10%);
  border-radius: 8px;
  font-size: 0.9rem;
  margin: 0 0 0.75rem;
}

.tabla {
  width: 100%;
  border-collapse: collapse;
  margin-top: 1.5rem;
  font-variant-numeric: tabular-nums;
}

.tabla caption {
  text-align: left;
  margin-bottom: 0.5rem;
}

.tabla td {
  padding: 0.45rem 0.6rem;
  border-top: 1px solid var(--borde);
}

.tabla td:first-child {
  color: var(--apagado);
}

.tabla td:not(:first-child) {
  text-align: right;
}

.tabla tr.activa td {
  background: rgb(76 154 255 / 12%);
  color: var(--texto);
  font-weight: 600;
}

/* Separador entre el bloque principal del formulario y el opcional. */
form hr {
  width: 100%;
  border: none;
  border-top: 1px solid var(--borde);
  margin: 0.75rem 0 1.1rem;
}

.pista.seccion {
  margin: 0 0 0.9rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-size: 0.72rem;
}

.bloque {
  padding-top: 1.25rem;
  margin-bottom: 1.25rem;
  border-top: 1px solid var(--borde);
}

.bloque h2 {
  margin-bottom: 0.9rem;
}

/* --- Cartera ------------------------------------------------------- */

/* Las tablas de posiciones tienen muchas columnas: en pantalla estrecha
   se desplazan dentro de su caja en vez de romper la página. */
.tabla-ancha {
  overflow-x: auto;
}

/* Desplegable dentro de una celda: compacto y sin el margen de los del
   formulario, que aquí descuadraría la fila. */
.selector-cartera select {
  margin: 0;
  padding: 0.25rem 0.4rem;
  font-size: 0.85rem;
}

.apagado {
  color: var(--apagado);
}

.tabla th {
  text-align: left;
  padding: 0.4rem 0.6rem;
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--apagado);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-bottom: 1px solid var(--borde);
  white-space: nowrap;
}

.tabla th:not(:first-child) {
  text-align: right;
}

.tabla .pista {
  margin: 0.1rem 0 0;
}

.positivo {
  color: #3fb950;
}

.negativo {
  color: #f85149;
}

.anios {
  list-style: none;
  padding: 0;
  margin: 0.75rem 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
}

.anio {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
  padding: 0.6rem 0.9rem;
  border: 1px solid var(--borde);
  border-radius: 10px;
  min-width: 6.5rem;
}

.anio .etiqueta {
  font-size: 0.8rem;
  color: var(--apagado);
}

.anio.positivo .cifra-pequena {
  color: #3fb950;
}

.anio.negativo .cifra-pequena {
  color: #f85149;
}

/* Botón que se comporta como enlace: acción secundaria dentro de un texto. */
button.enlace {
  background: none;
  border: none;
  padding: 0;
  color: var(--acento);
  font-size: inherit;
  font-weight: 400;
  text-decoration: underline;
  cursor: pointer;
}

/*
 * El mismo botón, cuando lo que hace no se puede deshacer.
 *
 * Va en rojo y SIN subrayado, para que no se lea como uno más de la fila: en la
 * ficha de una empresa, «Editar» y «Borrar» estaban pegados y con la misma
 * pinta, y el segundo se lleva por delante la criba y el historial. Un enlace
 * destructivo que viste de enlace normal es una trampa, no una opción.
 */
button.enlace.peligro {
  color: var(--ji-loss, #ef5350);
  text-decoration: none;
  font-weight: 500;
}
button.enlace.peligro:hover {
  text-decoration: underline;
}

input[type='file'] {
  padding: 0.8rem;
  border-style: dashed;
  cursor: pointer;
  max-width: 30rem;
}

input[type='file']::file-selector-button {
  padding: 0.4rem 0.8rem;
  margin-right: 0.8rem;
  background: var(--acento);
  border: none;
  border-radius: 6px;
  color: #04101f;
  font-weight: 600;
  cursor: pointer;
}

/* Selector de año: pestañas, no un desplegable. Son cinco años y verlos
   todos de un vistazo es más rápido que abrir una lista. */
.anios.selector {
  margin-bottom: 1.25rem;
}

.pestana {
  background: transparent;
  border: 1px solid var(--borde);
  border-radius: 999px;
  padding: 0.35rem 0.9rem;
  color: var(--apagado);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

.pestana.activa {
  background: var(--acento);
  border-color: var(--acento);
  color: #04101f;
  font-weight: 650;
}

/* Estrategias de opciones: las patas de una orden combinada se agrupan
   bajo una cabecera con el nombre. El borde marca dónde empieza y acaba
   cada grupo, que si no se pierden entre cientos de filas. */
tbody.estrategia {
  background: rgb(76 154 255 / 5%);
}

tbody.estrategia .cabecera-estrategia td {
  border-top: 1px solid var(--acento);
  color: var(--acento);
  font-size: 0.85rem;
  text-align: left;
}

tbody.estrategia .cabecera-estrategia td:nth-child(2) {
  text-align: right;
}

/* Cabecera plegable de una operativa: se comporta como enlace pero es un
   botón de verdad, para que funcione con teclado y lo anuncien los
   lectores de pantalla. */
button.desplegar {
  background: none;
  border: none;
  padding: 0;
  color: var(--acento);
  font-size: 0.85rem;
  font-weight: 500;
  text-align: left;
  cursor: pointer;
}

button.desplegar .flecha {
  display: inline-block;
  width: 0.9rem;
}

button.desplegar:hover {
  text-decoration: underline;
}

/* Lista dentro de una pista: viñetas discretas, sin el margen por defecto. */
.pista.lista {
  padding-left: 1.1rem;
  margin-top: -0.75rem;
}

.pista.lista li {
  margin-bottom: 0.35rem;
}

/* --- Rendimiento --------------------------------------------------- */

.rentabilidades {
  list-style: none;
  padding: 0;
  margin: 1.5rem 0 0;
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
}

.rentabilidad {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 1.1rem 1.25rem;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-radius: 12px;
}

.rentabilidad.destacada {
  border-color: var(--acento);
}

.rentabilidad .etiqueta {
  font-size: 0.85rem;
  color: var(--apagado);
}

/* Gráfico de barras mes a mes, sin librería: una sola serie no justifica
   300 kB de dependencia. Dos mitades con la línea de cero en medio. */
.grafico {
  display: flex;
  align-items: stretch;
  gap: 2px;
  height: 11rem;
  margin-top: 1rem;
  overflow-x: auto;
}

.grafico .mes {
  display: flex;
  flex-direction: column;
  flex: 1 0 6px;
  min-width: 6px;
}

.grafico .mitad {
  flex: 1;
  display: flex;
}

.grafico .mitad.arriba {
  align-items: flex-end;
  border-bottom: 1px solid var(--borde);
}

.grafico .mitad.abajo {
  align-items: flex-start;
}

.grafico .barra {
  width: 100%;
  border-radius: 2px;
}

.grafico .barra.positiva {
  background: #3fb950;
}

.grafico .barra.negativa {
  background: #f85149;
}

/* =====================================================================
   Panel de suscriptores
   ===================================================================== */

/* Fila de generar código: descripción + usos + botón, alineados abajo para
   que el botón quede a la altura de los campos y no de sus etiquetas. */
.fila-formulario {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.8rem;
  margin-bottom: 0.5rem;
}
.fila-formulario label {
  display: flex;
  flex-direction: column;
}
.fila-formulario input {
  margin-bottom: 0;
}
.fila-formulario input[type='number'] {
  width: 6rem;
}

/* El código recién creado: se enseña una vez, así que salta a la vista. */
.codigo-nuevo {
  margin: 0.8rem 0;
  padding: 0.7rem 0.9rem;
  background: rgba(76, 154, 255, 0.1);
  border: 1px solid var(--acento);
  border-radius: 8px;
  font-size: 0.9rem;
}
.codigo-nuevo code {
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  color: var(--texto);
}

/* Los cubos del cotejo: rejilla de tarjetas, una por resultado del cruce. */
.cubos {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: 1rem;
  margin-top: 1.25rem;
}
.cubo {
  padding: 0.9rem 1rem;
  background: var(--superficie);
  border: 1px solid var(--borde);
  border-left-width: 4px;
  border-radius: 8px;
}
.cubo-cabecera {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}
.cubo h3 {
  margin: 0;
  font-size: 1rem;
}
.cubo .cuenta {
  display: inline-block;
  min-width: 1.6rem;
  padding: 0 0.4rem;
  margin-left: 0.3rem;
  background: var(--fondo);
  border-radius: 999px;
  text-align: center;
  font-size: 0.85rem;
  color: var(--apagado);
}
.cubo button {
  margin-top: 0.7rem;
}
/* El borde de la izquierda dice de un vistazo si el cubo es acción buena,
   mala, de revisar, o solo informativo. */
.cubo-bien { border-left-color: #3fb950; }
.cubo-mal { border-left-color: var(--error); }
.cubo-ojo { border-left-color: #d29922; }
.cubo-neutro { border-left-color: var(--borde); }

.lista-emails {
  margin: 0.6rem 0 0;
  padding-left: 1.1rem;
  max-height: 12rem;
  overflow-y: auto;
  font-size: 0.85rem;
  color: var(--apagado);
}
.lista-emails li {
  word-break: break-all;
}

/* Botón de copiar pequeño, junto al código. */
button.secundario.copiar {
  padding: 0.15rem 0.5rem;
  font-size: 0.75rem;
  vertical-align: middle;
}
.codigo-celda code,
.codigo-nuevo code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: 0.03em;
}
.codigo-celda {
  white-space: nowrap;
}

/* Alarmas de renovación en la tabla de suscripciones. */
.alarma {
  display: inline-block;
  padding: 0.1rem 0.5rem;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 600;
  white-space: nowrap;
}
.alarma-bien { background: rgba(63, 185, 80, 0.15); color: #3fb950; }
.alarma-ojo { background: rgba(210, 153, 34, 0.18); color: #e3a72f; }
.alarma-mal { background: rgba(255, 107, 107, 0.15); color: var(--error); }

/* =====================================================================
   CALCULADORA DE OPCIONES — estilos portados de Options World.
   Provisionales hasta el rediseño. Todo va por clases propias
   (.app, .calc-*, .game-btn, .payoff-*...) salvo :root, que solo
   AÑADE variables. Se han quitado su `body` y su fuente global para
   no pisar el resto de jotainvestor.
   ===================================================================== */
:root {
  --bg: #0f172a;
  --panel: #1e293b;
  --panel-2: #273449;
  /* Superficie elevada (hover/activo) y hundida (inputs) — dan sensación de
     profundidad correcta: un input debe leerse "hundido" en el panel, no al
     mismo nivel o por encima de él. */
  --panel-raised: #24334a;
  --inset: #16213a;
  --border: #334155;
  --border-strong: #475569;
  --text: #e2e8f0;
  --muted: #94a3b8;
  --accent: #38bdf8;
  --accent-hover: #6cc9fa;
  --accent-active: #1a8fc9;
  /* Color de "chip" (fondo sólido + texto oscuro fijo `#0b1220` en ~10 sitios:
     pestañas activas, botones primarios, insignias del modo juego). Separado
     de --accent porque en modo claro --accent se oscurece para servir como
     color de TEXTO/borde legible sobre fondos claros — pero un chip necesita
     seguir siendo claro para que ese texto oscuro fijo no pierda contraste.
     En oscuro coincide con --accent (mismo aspecto que antes del modo claro). */
  --accent-chip: #38bdf8;
  --profit: #22c55e;
  --profit-hover: #4ade80;
  --profit-active: #16a34a;
  --loss: #ef4444;
  --loss-hover: #f87171;
  --loss-active: #dc2626;
  --strike: #fbbf24;
  /* Paleta por sesgo direccional (coherente con las pills de beneficio/pérdida).
     --bias-alcista NO se oscurece en modo claro (a diferencia de bajista/
     neutral) — mismo criterio conservador que --accent-chip. Su única razón
     original (fondo de chip con texto oscuro fijo en el modo juego) ya no
     aplica tras retirar el modo juego (ADR-0015) — se deja sin oscurecer de
     todos modos por precaución, revisar si alguna vez se quiere que el
     texto en --bias-alcista sí siga al tema como bajista/neutral. */
  --bias-alcista: #4ade80;
  --bias-bajista: #f87171;
  --bias-neutral: #fbbf24;
  /* Monoespaciada para todo dato numérico (inputs, tablas, métricas): las
     cifras alinean mejor y se distinguen del texto de interfaz de un vistazo.
     Pila de sistema — nada de red, coherente con la app 100% cliente. */
  --font-mono: ui-monospace, 'Cascadia Code', 'Segoe UI Mono', Consolas, 'SFMono-Regular', Menlo, monospace;
}

/**
 * Modo claro (v1.48.0) — activado por `<html data-theme="light">`
 * (`components/useTheme.ts`). Beta-tester real: "añadir modo claro la IA lo
 * hace en nada, y hay gente que lo prefiere". Solo cambian las superficies y
 * el texto (bg/panel/border/text/muted) y los colores que se usan como TEXTO
 * plano (accent/profit/loss/strike/bias-bajista/bias-neutral) — deliberado NO
 * oscurecer --accent-chip: sigue haciendo de fondo de chip con texto oscuro
 * fijo en varios sitios del CSS (pestañas activas, botones de vista), y
 * oscurecerlo ahí rompería ese contraste sin ganar nada a cambio.
 * --bias-alcista tampoco se oscurece, por el mismo criterio histórico,
 * aunque su único uso real como fondo de chip vivía en el modo juego, ya
 * retirado (ver comentario junto a su declaración arriba).
 */
:root[data-theme='light'] {
  --bg: #f2f4f8;
  --panel: #ffffff;
  --panel-2: #eef1f6;
  --panel-raised: #e3e8f0;
  --inset: #e9edf3;
  --border: #d8dee6;
  --border-strong: #b7c1cd;
  --text: #182230;
  --muted: #55606d;
  --accent: #0284c7;
  --accent-hover: #0369a1;
  --accent-active: #075985;
  --profit: #16a34a;
  --profit-hover: #15803d;
  --profit-active: #166534;
  --loss: #dc2626;
  --loss-hover: #b91c1c;
  --loss-active: #991b1b;
  --strike: #b45309;
  --bias-bajista: #b91c1c;
  --bias-neutral: #b45309;
}

* {
  box-sizing: border-box;
}

.app {
  max-width: 1200px;
  margin: 0 auto;
  padding: 24px;
}

/* Botón de tema (v1.48.0): montado una vez en App.tsx, fuera de <Routes> —
   alcanzable desde cualquier página, incluida .landing (con su propio
   color de texto, ver más arriba) y el modo juego. z-index alto porque
   convive con overlays de la propia app (popovers, pantalla completa del
   gráfico); posición fija en vez de dentro del flujo, para no repetir un
   punto de montaje en cada página como se hizo con HomeLink. */
.theme-toggle-btn {
  position: fixed;
  top: 14px;
  right: 14px;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--text);
  cursor: pointer;
}

.theme-toggle-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.theme-toggle-btn svg {
  width: 17px;
  height: 17px;
}

header h1 {
  margin: 0;
  font-size: 1.6rem;
}

.subtitle {
  margin: 4px 0 0;
  color: var(--muted);
  font-size: 0.9rem;
}

/* ==================== HUB (portada "/") ==================== *
 * Puerta de entrada a las dos partes del proyecto (calculadora y modo
 * juego). Placeholder funcional con la paleta global — a skinear estilo
 * CriptoATH (badge + título grande a dos tonos + tarjetas) en cuanto haya
 * un export de v0 específico para esta pantalla. */
.hub {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding-top: 64px;
  padding-bottom: 64px;
  text-align: center;
}

.hub-card:hover {
  border-color: var(--accent);
  background: var(--panel-2);
  transform: translateY(-2px);
}

.hub-card h2 {
  margin: 4px 0 0;
  font-size: 1.15rem;
}

.hub-card p {
  margin: 4px 0 0;
  color: var(--muted);
  font-size: 0.85rem;
  line-height: 1.5;
}

.presets {
  margin: 20px 0;
}

.preset-search {
  width: 100%;
  background: var(--inset);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: 0.9rem;
  margin-bottom: 12px;
}

.preset-search:focus {
  outline: none;
  border-color: var(--accent);
}

/* La landing redefine estos dos por dentro de .lp-search (icono + input +
   botón de borrar en un único wrapper con position:relative). */
.lp-search {
  position: relative;
  margin-bottom: 0;
}

.landing .preset-search {
  background: color-mix(in oklch, var(--lp-card) 70%, transparent);
  border: 1px solid var(--lp-border-strong);
  border-radius: 10px;
  padding: 11px 38px;
  margin-bottom: 0;
  backdrop-filter: blur(6px);
  color: var(--lp-fg);
  transition: border-color 150ms;
}

.landing .preset-search::placeholder {
  color: color-mix(in oklch, var(--lp-muted-fg) 70%, transparent);
}

.landing .preset-search:focus {
  border-color: oklch(0.78 0.12 195 / 55%);
}

.lp-search-clear svg {
  width: 15px;
  height: 15px;
}

.lp-search-clear:hover {
  background: oklch(1 0 0 / 5%);
  color: var(--lp-fg);
}

/* --- Filtros por sesgo/beneficio/pérdida (v1.49.0) --- */
.lp-filters {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 14px;
  margin-top: 12px;
}

/* Los toggles son <button>, no <span> como las pills estáticas — resetea el
   estilo nativo del navegador y añade el cursor; el color/fondo de cada
   estado (activo/inactivo) lo siguen dando las clases de variante de
   `.lp-pill` ya existentes (o `.lp-pill-active`, nueva, más abajo). */
.lp-filter-toggle {
  cursor: pointer;
  transition: border-color 150ms;
}

/* Estado activo genérico para los toggles de beneficio/pérdida — a
   diferencia del sesgo (bull/bear/neutral ya tienen color propio),
   "limitado"/"ilimitado" no tiene un color semántico de sobra que reciclar
   (`BoundPill` usa `lp-pill-muted` en 3 de sus 4 combinaciones), así que el
   estado activo usa el acento de la landing en vez de un color prestado. */
.lp-pill-active {
  border-color: oklch(0.78 0.12 195 / 35%);
  background: oklch(0.78 0.12 195 / 14%);
  color: var(--lp-primary);
}

.lp-filters-clear:hover {
  text-decoration: underline;
}

/* --- Empty states: buscador sin resultados / lienzo de leg vacío --- */
.empty-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 14px;
  padding: 40px 24px;
  border: 1px dashed var(--border);
  border-radius: 12px;
  margin: 8px 0;
}

.empty-state-icon-dim {
  stroke: var(--border);
}

.empty-state-icon-mid {
  stroke: var(--border-strong);
}

.empty-state-icon-accent {
  stroke: var(--accent);
}

.empty-state-title {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--text);
}

.empty-state-sub {
  font-size: 0.8rem;
  color: var(--muted);
  margin-top: 4px;
}

.empty-state-suggestions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: center;
}

.suggestion-pill {
  background: var(--panel);
  border: 1px solid var(--border);
  color: var(--text);
  font-size: 0.72rem;
  font-weight: 500;
  font-family: inherit;
  border-radius: 999px;
  padding: 6px 12px;
  cursor: pointer;
  text-decoration: none;
  transition: border-color 0.15s, background 0.15s;
}

.suggestion-pill:hover {
  border-color: var(--accent);
  background: var(--panel-2);
}

.empty-state-cta {
  background: var(--accent-chip);
  color: #0b1220;
  font-weight: 700;
  font-size: 0.85rem;
  border: none;
  border-radius: 8px;
  padding: 9px 18px;
  cursor: pointer;
  transition: filter 0.15s;
}

.empty-state-cta:hover {
  filter: brightness(1.08);
}

.empty-state-divider {
  font-size: 0.7rem;
  color: var(--muted);
}

.preset-group {
  border: 1px solid var(--border);
  border-radius: 10px;
  margin-bottom: 8px;
  overflow: hidden;
}

.group-header {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  background: var(--panel);
  color: var(--text);
  border: none;
  padding: 10px 14px;
  cursor: pointer;
  font-size: 0.8rem;
  text-align: left;
}

.group-header:hover:not(:disabled) {
  background: var(--panel-2);
}

.group-header:disabled {
  cursor: default;
}

.chevron {
  color: var(--muted);
  font-size: 0.75rem;
  width: 12px;
}

.preset-group-title {
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  font-weight: 600;
  flex: 1;
}

.group-count {
  color: var(--muted);
  background: var(--panel-2);
  border-radius: 10px;
  padding: 1px 8px;
  font-size: 0.72rem;
}

.preset-buttons {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: 8px;
  padding: 10px;
  background: var(--bg);
}

.preset {
  display: flex;
  flex-direction: column;
  gap: 6px;
  align-items: flex-start;
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 10px 12px;
  cursor: pointer;
  transition: all 0.15s;
}

.preset:hover {
  border-color: var(--accent);
}

.preset.active {
  border-color: var(--accent);
  box-shadow: 0 0 0 1px var(--accent);
}

.preset-label {
  font-size: 0.85rem;
  font-weight: 600;
}

.preset.active .preset-label {
  color: var(--accent);
}

.preset-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

/* Pills de sesgo: mismos colores que la paleta por sesgo (variables). */
.bias-alcista {
  color: var(--bias-alcista);
  background: rgba(74, 222, 128, 0.12);
  border-color: rgba(74, 222, 128, 0.35);
}

/* Beneficio/pérdida: acotado = neutro apagado; ilimitado = verde/rojo. */
.pill-neutral {
  color: var(--muted);
  background: rgba(148, 163, 184, 0.1);
  border-color: var(--border);
}

/* ==================== LANDING (rediseño v0.dev, v1.27.0) ==================== *
 * Paleta OKLCH y fondo de partículas propios, escopados bajo `.landing` para
 * no afectar al resto de la app (decisión: probar primero solo aquí antes de
 * extenderlo — ver CHANGELOG v1.27.0). `oklch()` con alpha `/ N%` requiere un
 * navegador moderno (Chrome 111+/Firefox 113+/Safari 15.4+); aceptable en una
 * herramienta 100% cliente sin matriz de compatibilidad declarada. */
.landing {
  --lp-bg: oklch(0.16 0.012 255);
  --lp-fg: oklch(0.96 0.004 255);
  --lp-card: oklch(0.2 0.014 255);
  --lp-card-open: oklch(0.235 0.016 255);
  --lp-primary: oklch(0.78 0.12 195);
  --lp-muted-fg: oklch(0.66 0.014 255);
  --lp-border: oklch(1 0 0 / 8%);
  --lp-border-strong: oklch(1 0 0 / 16%);
  --lp-bull: oklch(0.78 0.15 158);
  --lp-bear: oklch(0.68 0.19 22);
  --lp-neutral: oklch(0.82 0.11 90);
  position: relative;
  color: var(--lp-fg);
}

/* Variante clara de la paleta OKLCH de arriba (v1.48.0). `--lp-bull`/
   `--lp-bear`/`--lp-neutral` se oscurecen aquí a diferencia de sus
   equivalentes `--bias-*` globales: aquí SÍ son solo texto plano sobre un
   fondo translúcido del mismo tono (`.lp-pill-*`, ver más abajo, colores
   literales sin variable) — sin uso de "chip con texto oscuro fijo" que
   proteger, así que pueden oscurecerse sin condición especial. Mayor
   especificidad que `.landing` a secas para ganarle a esos valores por
   defecto sin depender del orden de las reglas en el archivo. */
:root[data-theme='light'] .landing {
  --lp-bg: oklch(0.97 0.004 255);
  --lp-fg: oklch(0.2 0.012 255);
  --lp-card: oklch(1 0 0);
  --lp-card-open: oklch(0.94 0.008 255);
  --lp-primary: oklch(0.5 0.14 195);
  --lp-muted-fg: oklch(0.42 0.014 255);
  --lp-border: oklch(0 0 0 / 8%);
  --lp-border-strong: oklch(0 0 0 / 16%);
  --lp-bull: oklch(0.42 0.15 158);
  --lp-bear: oklch(0.5 0.19 22);
  --lp-neutral: oklch(0.48 0.12 90);
}

/* --- Fondo de partículas (AnimatedBackground.tsx) --- */
/* `--lp-bg` autocontenida aquí (no solo heredada de `.landing`): así
   `AnimatedBackground` funciona igual montado en cualquier página, no solo
   en las que llevan la clase `.landing` — v1.30.0 lo extiende a
   `StrategyPage`/`ComparePage`. */
.landing-bg {
  --lp-bg: oklch(0.16 0.012 255);
  position: fixed;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  background: var(--lp-bg);
  pointer-events: none;
}

/* `--lp-bg` de `.landing-bg` se fija a sí misma (ver comentario arriba), así
   que no hereda la variante clara de `:root[data-theme='light'] .landing` —
   necesita su propio override, o el degradado de `.landing-bg-vignette`
   seguiría desvaneciendo a un valor oscuro fijo en modo claro. */
:root[data-theme='light'] .landing-bg {
  /* El mismo papel que `--ji-bg` del tema claro, no un blanco frío aparte: si
     no coinciden se ven dos blancos pegados y el borde del canvas se nota. */
  --lp-bg: #eae6dd;
}

.landing-bg-canvas {
  display: block;
  width: 100%;
  height: 100%;
  opacity: 0.9;
}

.landing-bg-vignette {
  position: absolute;
  inset: 0;
  /* Mantiene los bordes calmados y el texto legible en el centro. */
  background: radial-gradient(120% 80% at 50% 0%, transparent 45%, var(--lp-bg) 100%);
}

/* --- Cabecera --- */
.landing-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

.landing-logo svg {
  width: 20px;
  height: 20px;
}

.landing h1 {
  margin: 0;
  font-size: 1.15rem;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--lp-fg);
}

.landing .subtitle {
  margin: 2px 0 0;
  color: var(--lp-muted-fg);
  font-size: 0.8rem;
}

.lp-nav-link svg {
  width: 15px;
  height: 15px;
}

.lp-nav-link:hover {
  border-color: oklch(0.78 0.12 195 / 30%);
  background: oklch(1 0 0 / 5%);
  color: var(--lp-fg);
}

/* --- Entrada de estrategia personalizada --- */
.landing .custom-entry {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 0;
  padding: 16px 18px;
  border: 1px solid oklch(0.78 0.12 195 / 30%);
  border-radius: 12px;
  background: linear-gradient(to right, oklch(0.78 0.12 195 / 12%), oklch(0.78 0.12 195 / 3%));
  color: var(--lp-fg);
  text-decoration: none;
  transition: border-color 150ms, background 150ms;
}

.landing .custom-entry:hover {
  border-color: oklch(0.78 0.12 195 / 50%);
}

.custom-entry-plus svg {
  width: 19px;
  height: 19px;
}

.landing .custom-entry strong {
  display: block;
  font-size: 0.95rem;
  font-weight: 600;
}

.landing .custom-entry-sub {
  display: block;
  margin-top: 2px;
  color: var(--lp-muted-fg);
  font-size: 0.8rem;
}

@media (max-width: 640px) {
  .custom-entry-badge {
    display: none;
  }
}

/* --- Lista de categorías, cada una desplegable --- *
 * Antes era una rejilla multi-columna con cada tarjeta a la altura de su
 * propio listado completo — con recuentos tan distintos entre categorías
 * (2 estrategias vs. 8) se veían visiblemente desiguales. Ahora es una lista
 * de una columna, cerrada por defecto: todas las tarjetas arrancan con la
 * misma forma (cabecera + descripción breve), y solo crecen al desplegarse. */
.landing-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 8px;
}

.category-card:hover {
  border-color: var(--lp-border-strong);
  background: var(--lp-card);
}

.category-card.open {
  border-color: oklch(0.78 0.12 195 / 30%);
  background: var(--lp-card-open);
  box-shadow: 0 18px 40px -24px rgba(0, 0, 0, 0.8);
}

/* Barra de acento a la izquierda, solo visible con la categoría abierta. */
.category-accent-bar {
  position: absolute;
  inset: 0 auto 0 0;
  width: 2px;
  background: var(--lp-primary);
  opacity: 0;
  transition: opacity 200ms;
}

.category-card.open .category-accent-bar {
  opacity: 1;
}

.category-card.open .category-chevron {
  color: var(--lp-primary);
  transform: rotate(90deg);
}

.group-count {
  border: 1px solid var(--lp-border-strong);
  border-radius: 6px;
  padding: 1px 7px;
  background: oklch(1 0 0 / 3%);
  color: var(--lp-muted-fg);
  font-family: var(--font-mono);
  font-size: 0.68rem;
  transition: border-color 200ms, background 200ms, color 200ms;
}

.category-card.open .group-count {
  border-color: oklch(0.78 0.12 195 / 30%);
  background: oklch(0.78 0.12 195 / 10%);
  color: var(--lp-primary);
}

.strategy-item:hover {
  border-color: var(--lp-border-strong);
  background: oklch(1 0 0 / 4%);
}

.strategy-item:hover .strategy-dot {
  background: var(--lp-primary);
}

@media (min-width: 640px) {
  .strategy-item {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
  }
}

/* --- Pills de sesgo / beneficio / pérdida (icono lucide-react) --- */
.lp-pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 7px;
  border: 1px solid transparent;
  border-radius: 6px;
  font-family: var(--font-mono);
  font-size: 0.66rem;
  font-weight: 500;
  white-space: nowrap;
}

.lp-pill svg {
  width: 11px;
  height: 11px;
}

/* --- Página dedicada: cabecera con vuelta a la landing --- */
.strategy-header {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  gap: 16px;
  margin-bottom: 12px;
}

.back-link:hover {
  border-color: var(--accent);
}

/* Fila de "migas" (HomeLink + el back-link contextual de cada página): así
   se puede volver a "/" en un clic sin deshacer la cadena de "atrás" paso a
   paso, sin importar cuántos niveles de profundidad haya (p. ej. un reto
   del modo juego). */
.crumb-row {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: 8px;
}

.home-link {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  margin-top: 4px;
  border: 1px solid var(--border);
  border-radius: 8px;
  text-decoration: none;
  font-size: 0.95rem;
  line-height: 1;
}

.home-link:hover {
  border-color: var(--accent);
}

.strategy-heading h1 {
  margin: 0;
  font-size: 1.5rem;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}

/* Tutorial de la calculadora (`/como-usar`, ver Tutorial.tsx) — ancho
   acotado a 760px para que la prosa no se estire a los 1200px de .app y
   siga siendo cómoda de leer. */
.tutorial-toc {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 18px 0;
  max-width: 760px;
}

.tutorial-toc-link:hover {
  color: var(--accent);
  border-color: var(--accent);
}

.tutorial-section h2 {
  margin: 0 0 10px;
  font-size: 1.1rem;
  color: var(--accent);
}

.tutorial-section p {
  margin: 0 0 10px;
  line-height: 1.6;
  color: var(--text);
}

.tutorial-section p:last-child {
  margin-bottom: 0;
}

.tutorial-section ul {
  margin: 0;
  padding-left: 20px;
  line-height: 1.6;
}

/* Glosario (`/glosario`, ver Glossary.tsx) — reutiliza .tutorial-section
   para cada categoría, con su propio dt/dd para término/definición. */
.glossary-search {
  display: block;
  width: 100%;
  max-width: 760px;
  margin: 18px 0;
  padding: 10px 14px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 10px;
  color: var(--text);
  font-size: 0.9rem;
}

.glossary-search:focus {
  outline: none;
  border-color: var(--accent);
}

.glossary-entry dt {
  font-weight: 700;
  color: var(--accent);
  margin-bottom: 2px;
}

.glossary-entry dd {
  margin: 0;
  color: var(--text);
  line-height: 1.6;
  font-size: 0.92rem;
}

/* Diagramas esquemáticos del tutorial (ver TutorialDiagrams.tsx) — mockups
   propios en SVG, no capturas reales de la app. */
.tut-diagram {
  width: 100%;
  max-width: 460px;
  height: auto;
  display: block;
  margin: 14px 0 4px;
}

/* Diagramas del tutorial: mockups en SVG, no capturas. Sus colores se
   remapearon a los tokens del rediseño al portar la pantalla — antes
   usaban la paleta de Options World y desentonaban dentro de una
   tarjeta `.ji-card`. Solo los usa TutorialDiagrams.tsx. */
.td-box {
  fill: var(--ji-surface-2);
  stroke: var(--ji-border-strong);
  stroke-width: 1;
}

.td-box-accent {
  fill: var(--ji-surface-2);
  stroke: var(--ji-gold);
  stroke-width: 1.5;
}

.td-box-dim {
  fill: var(--ji-surface-2);
  opacity: 0.5;
}

.td-box-text {
  fill: var(--ji-text);
  font-size: 11px;
}

.td-box-text-sm {
  fill: var(--ji-text);
  font-size: 11px;
}

.td-col-label {
  fill: var(--ji-muted);
  font-size: 11px;
}

.td-section-label {
  fill: var(--ji-muted);
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.td-label {
  fill: var(--ji-muted);
  font-size: 11px;
}

.td-axis {
  stroke: var(--ji-border-strong);
  stroke-width: 1.5;
}

.td-dash {
  stroke: var(--ji-gold);
  stroke-width: 1.5;
  stroke-dasharray: 4 3;
}

.td-line {
  fill: none;
  stroke: var(--ji-gain);
  stroke-width: 2;
}

.td-line-b {
  stroke: var(--ji-loss);
}

.td-knob {
  fill: var(--ji-gold);
}

.td-knob-b {
  fill: var(--bias-bajista);
}

.td-arrow line {
  stroke: var(--accent);
  stroke-width: 1.5;
}

.td-arrow polygon {
  fill: var(--accent);
}

/* --- Asistente de estrategia (/asistente, v1.48.0) --- */
.wizard-progress {
  margin: 4px 0 0;
  font-size: 0.8rem;
  color: var(--muted);
}

.wizard-question h2 {
  font-size: 1.15rem;
  margin: 0 0 16px;
}

.wizard-option:hover {
  border-color: var(--accent);
  background: var(--panel-2);
}

.wizard-match-head h3 {
  margin: 0;
  font-size: 1.05rem;
}

.wizard-restart-btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.layout {
  display: grid;
  grid-template-columns: 440px 1fr;
  gap: 20px;
  align-items: start;
}

/* 440px obligaba a scroll horizontal dentro de la tabla de legs para ver
   todas las columnas (Cantidad quedaba fuera) — confirmado por dos
   beta-testers independientes en escritorio. 600px lo evita, pero solo a
   partir de aquí: `minmax()` en `.layout` no funcionó (el navegador seguía
   dándole a la columna de legs su máximo aunque no sobrara espacio,
   dejando el panel del gráfico en ~275px a 960px de ancho) — con un
   breakpoint explícito, por debajo de 1180px se mantiene el ancho
   original (sigue habiendo scroll en la tabla, pero el gráfico no se
   aplasta) y solo se ensancha cuando de verdad sobra sitio. */
@media (min-width: 1180px) {
  .layout {
    grid-template-columns: 600px 1fr;
  }
}

@media (max-width: 900px) {
  .layout {
    grid-template-columns: 1fr;
  }
}

.legs-panel,
.chart-panel {
  /* Sin esto, un hijo intrínsecamente ancho (la tabla de legs con varias
     columnas de inputs) empuja el propio item de grid más allá de su pista
     ("1fr" en móvil, ver arriba) — el grid contenedor se ajusta bien, pero
     el item no se encoge por debajo del ancho mínimo de su contenido, así
     que la página entera gana scroll horizontal en vez de que sea la tabla
     (que ya tiene su propio overflow-x) la que scrollee internamente. */
  min-width: 0;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 16px;
}

/* Fundido de entrada al cambiar de pestaña de vista (Gráfico/Tabla/Greeks/...).
   Remonta con `key={activeView}`, así que la animación se relanza sola en
   cada cambio sin JS extra. Opción "2d" (crossfade + leve subida) de
   Payoff Chart Animation Options.dc.html — se descartaron escalar desde el
   centro (⚠ se nota en textos/ejes) y el revelado escalonado eje→área→línea
   (al límite del rango de duración pedido). */
@keyframes view-fade-in {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.view-fade {
  animation: view-fade-in 200ms cubic-bezier(0.22, 1, 0.36, 1);
}

@media (prefers-reduced-motion: reduce) {
  .view-fade,
  .tooltip {
    animation: none;
  }
  .area-profit,
  .area-loss,
  .pnl-profit,
  .pnl-loss,
  .today-line,
  .gv-line-a,
  .gv-line-b,
  .strike-line,
  .breakeven-dot,
  .breakeven-label,
  .spot-line,
  .spot-label,
  .spot-pnl-dot,
  .spot-pnl-label {
    transition: none;
  }
}

.legs-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}

.legs-header h2 {
  margin: 0;
  font-size: 1.1rem;
}

.tag {
  font-size: 0.7rem;
  color: var(--accent);
  background: rgba(56, 189, 248, 0.12);
  padding: 2px 6px;
  border-radius: 4px;
  margin-left: 6px;
  vertical-align: middle;
}

.add-leg {
  background: transparent;
  color: var(--accent);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 6px 10px;
  cursor: pointer;
  font-size: 0.8rem;
}

.add-leg:hover {
  border-color: var(--accent);
}

.legs-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}

.legs-table th {
  text-align: left;
  color: var(--muted);
  font-weight: 500;
  padding: 4px 6px;
  font-size: 0.75rem;
}

.legs-table td {
  padding: 4px 6px;
}

/* Numeración de leg + franja lateral neutra alternada: un "carril" por fila
   para seguir cuál es cuál en estrategias de 3-4 legs, sin introducir un
   tercer color junto al verde/rojo de la píldora Long/Short. */
.legs-table th.leg-num-col {
  width: 22px;
  padding: 4px 0 4px 8px;
}

.legs-table td.leg-num-col {
  padding: 4px 4px 4px 8px;
  color: var(--muted);
  font-weight: 700;
  font-size: 0.72rem;
  text-align: center;
  border-bottom: 1px solid var(--border);
}

.legs-table td.leg-num-a {
  border-left: 3px solid var(--border-strong);
}

.legs-table td.leg-num-b {
  border-left: 3px solid #64748b;
}

.legs-table select,
.legs-table input {
  width: 100%;
  background: var(--inset);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px;
  font-size: 0.85rem;
}

.legs-table select:focus,
.legs-table input:focus {
  outline: none;
  border-color: var(--accent);
}

/* Los selects incluyen texto + flecha del desplegable: sin un mínimo, el
   auto-layout de la tabla los colapsa y trunca "Call"/"Short". */
.legs-table select {
  min-width: 68px;
}

/* Strike, prima, cantidad y fecha son datos numéricos: monoespaciada para
   que las cifras alineen y se lean de un vistazo. */
.legs-table input {
  min-width: 58px;
  font-family: var(--font-mono);
}

/* Long/short como píldora de color: se lee de un vistazo sin tener que
   fijarse en el texto, igual que el signo +/- que ya usa legShort() en la
   tabla de Greeks. */
.position-select.long {
  background: rgba(34, 197, 94, 0.14);
  color: var(--profit-hover);
  border-color: var(--profit);
  font-weight: 600;
}

.position-select.short {
  background: rgba(239, 68, 68, 0.14);
  color: var(--loss-hover);
  border-color: var(--loss);
  font-weight: 600;
}

.legs-table input.qty {
  width: 52px;
  min-width: 52px;
}

/* La pata de acción no tiene strike ni prima (solo `entryPrice`, ver
   engine/types.ts) — fusionar su precio de entrada bajo esas dos columnas
   (con colSpan) se leía ambiguo: el valor parecía un strike, o un número
   editable en "Prima". En vez de eso, el precio de entrada va junto al
   propio selector "Acción" (su identidad, no una métrica de la opción) y
   las columnas Strike/Prima quedan en blanco ("—", igual que ya hacía
   Vencimiento) para que no quede ninguna duda de que no aplican. */
.type-cell {
  display: flex;
  align-items: center;
  gap: 4px;
}

.stock-price-inline {
  display: flex;
  align-items: center;
  gap: 2px;
  font-size: 0.72rem;
  color: var(--muted);
}

.stock-price-inline input {
  width: 52px;
  min-width: 52px;
}

.legs-table td.dim-cell {
  text-align: center;
  color: var(--muted);
}

/* El input de fecha nativo necesita sitio para día/mes/año + el icono de
   calendario — con el ancho estrecho de .qty (pensado para "1 contrato") se
   recortaba y el icono se veía roto/superpuesto. */
.legs-table input.date-input {
  width: 118px;
  min-width: 118px;
}

/* Scrollbar a juego con el tema (por defecto el navegador la pinta gris
   claro sobre fondo oscuro, desentona). Firefox vía scrollbar-color/-width;
   Chrome/Edge/Safari vía los pseudo-elementos ::-webkit-scrollbar-*.
   Mismo tratamiento en las 4 tablas con scroll horizontal propio. */

.qty-cell {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 2px;
}

.qty-unit {
  font-size: 0.62rem;
  color: var(--muted);
  white-space: nowrap;
}

/* --- Tooltip/popover de info: sustituye el title nativo (17 sitios) --- */
.info-trigger {
  display: inline-flex;
  align-items: center;
  vertical-align: -2px;
  background: none;
  border: none;
  padding: 0;
  margin: 0;
  color: var(--accent);
  cursor: pointer;
  line-height: 0;
}

.info-trigger:hover {
  color: var(--accent-hover);
}

.info-backdrop {
  display: none;
}

.info-popover {
  position: fixed;
  /* Por encima de todo: va en un portal sobre `body`, así que compite con la
     barra de módulos (60) y con cualquier cabecera pegajosa. */
  z-index: 1200;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
}

.info-popover-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 8px;
  margin-bottom: 4px;
}

.info-popover-title {
  font-size: 0.75rem;
  font-weight: 700;
  color: var(--text);
}

.info-popover-close {
  background: none;
  border: none;
  color: var(--muted);
  cursor: pointer;
  padding: 0;
  line-height: 1;
  font-size: 0.95rem;
}

.info-popover-close:hover {
  color: var(--text);
}

.info-popover-body {
  font-size: 0.75rem;
  line-height: 1.55;
  color: var(--text);
  /* Las explicaciones dinámicas de metricExplain.ts usan \n para separar el
     desglose por-leg; sin esto, un <div> normal colapsa los saltos de línea. */
  white-space: pre-line;
}

/* Pantalla estrecha: hoja inferior con backdrop en vez de popover flotante
   (el trigger es difícil de alcanzar con precisión con el dedo, y no hay
   hover para "adivinar" dónde cae el popover — mismo componente, solo
   cambia el anclaje). !important porque las coordenadas fixed se fijan
   inline desde JS (medidas del disparador) y aquí las anulamos a propósito. */
@media (max-width: 640px) {
  .info-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.5);
    z-index: 1199;
  }

  .info-popover {
    top: auto !important;
    left: 0 !important;
    right: 0 !important;
    bottom: 0 !important;
    width: auto !important;
    border-radius: 12px 12px 0 0;
    padding: 16px 18px;
  }
}

.remove-leg {
  background: transparent;
  color: var(--muted);
  border: 1px solid transparent;
  border-radius: 6px;
  font-size: 1.2rem;
  cursor: pointer;
  line-height: 1;
  padding: 2px 6px;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}

.remove-leg:hover:not(:disabled) {
  background: rgba(239, 68, 68, 0.14);
  border-color: var(--loss);
  color: var(--loss-hover);
}

.remove-leg:disabled {
  color: var(--border);
  cursor: not-allowed;
}

.metrics {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px;
  margin-top: 16px;
}

.metric {
  min-width: 0;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
}

.metric-label-row {
  display: flex;
  align-items: center;
  gap: 6px;
}

.metric-icon {
  display: flex;
  color: var(--muted);
  flex-shrink: 0;
}

.metric-label {
  display: block;
  font-size: 0.72rem;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

.metric-value {
  display: block;
  font-size: 1.05rem;
  font-weight: 600;
  margin-top: 6px;
  font-family: var(--font-mono);
}

/* Beneficio/pérdida máx. son el "resultado en juego" — más peso visual que
   coste neto/breakeven (el "punto de partida"), con fondo e icono propios. */
.metric.profit {
  background: rgba(34, 197, 94, 0.1);
  border-color: rgba(34, 197, 94, 0.35);
  padding: 16px;
}

.metric.loss {
  background: rgba(239, 68, 68, 0.1);
  border-color: rgba(239, 68, 68, 0.35);
  padding: 16px;
}

.metric.profit .metric-icon,
.metric.profit .metric-label {
  color: var(--profit-hover);
}

.metric.loss .metric-icon,
.metric.loss .metric-label {
  color: var(--loss-hover);
}

.metric.profit .metric-value {
  color: var(--profit);
  font-size: 1.55rem;
  font-weight: 700;
}

.metric.loss .metric-value {
  color: var(--loss);
  font-size: 1.55rem;
  font-weight: 700;
}

/* Coste de oportunidad: solo aparece cuando aplica (pata de acción + techo),
   ocupa las dos columnas para no competir visualmente con las 4 métricas
   principales — es un dato complementario, no parte del resultado en juego. */
.metric-oppcost {
  grid-column: 1 / -1;
}

.chart {
  width: 100%;
}

.chart svg {
  width: 100%;
  height: auto;
}

.grid {
  stroke: var(--border);
  stroke-width: 0.5;
  opacity: 0.4;
}

.zero-line {
  stroke: var(--muted);
  stroke-width: 1;
  stroke-dasharray: 4 3;
}

.axis-label {
  fill: var(--muted);
  font-size: 11px;
}

.axis-title {
  fill: var(--muted);
  font-size: 12px;
}

/* Micro-interacción: la curva se redibuja al editar una leg o un parámetro
   de mercado en vez de saltar de golpe. El navegador interpola "d" punto a
   punto cuando el número de comandos del path coincide entre un render y el
   siguiente (caso normal: solo cambia el valor de un strike/prima/cantidad
   dentro del mismo rango de precios); si el nº de strikes inyectados en el
   grid cambia, no hay nada que interpolar y simplemente salta — no hay
   fallback que valga la pena montar para eso, se degrada con gracia sola. */
.area-profit,
.area-loss,
.pnl-profit,
.pnl-loss {
  /* Ease-out sin overshoot — validado en Claude Design (opción "1d",
     Payoff Chart Animation Options.dc.html) frente a una variante con rebote
     (spring, descartada: "puede sentirse juguetón en un dato financiero") y
     una simétrica mecánica. */
  transition: d 220ms cubic-bezier(0.22, 1, 0.36, 1);
}

.area-profit {
  fill: var(--profit);
  opacity: 0.06;
}

.area-loss {
  fill: var(--loss);
  opacity: 0.06;
}

.pnl-profit {
  stroke: var(--profit);
  stroke-width: 2.5;
}

.pnl-loss {
  stroke: var(--loss);
  stroke-width: 2.5;
}

.strike-line {
  stroke: var(--strike);
  stroke-width: 1;
  stroke-dasharray: 2 4;
  opacity: 0.6;
  transition: x1 200ms ease, x2 200ms ease;
}

.breakeven-dot {
  fill: var(--accent);
  stroke: #0b1220;
  stroke-width: 1.5;
  transition: cx 200ms ease, cy 200ms ease;
}

.breakeven-label {
  fill: var(--accent);
  font-size: 11px;
  font-weight: 600;
  transition: x 200ms ease, y 200ms ease;
}

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

/* --- Parámetros de mercado (pricing) --- */
.market-params {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

.market-params h3,
.greeks h3 {
  margin: 0 0 10px;
  font-size: 0.9rem;
}

/* S es un dato real que el usuario consulta fuera de la app (su bróker) y
   pega aquí — se separa visualmente de IV/r/q, que son supuestos del
   modelo que el usuario decide, con su propia fila + borde de acento. */
.market-live {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 0.72rem;
  color: var(--muted);
  margin-bottom: 12px;
}

.market-live-hint {
  color: var(--border-strong);
  margin-left: 4px;
}

.market-live-input {
  min-width: 0;
  width: 100%;
  background: var(--inset);
  color: var(--text);
  border: 1px solid var(--accent);
  border-radius: 6px;
  padding: 8px;
  font-size: 0.95rem;
  font-weight: 600;
  font-family: var(--font-mono);
}

.market-live-input:focus {
  outline: none;
  border-color: var(--accent-hover);
}

/* --- Buscador de ticker (v1.51.0, ADR-0014) --- */
.ticker-search {
  position: relative;
  margin-bottom: 14px;
}

.ticker-search-input-row {
  position: relative;
  display: flex;
  align-items: center;
}

.ticker-search-icon {
  position: absolute;
  left: 8px;
  width: 14px;
  height: 14px;
  color: var(--muted);
  pointer-events: none;
}

.ticker-search-input {
  width: 100%;
  background: var(--inset);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 7px 8px 7px 28px;
  font-size: 0.8rem;
}

.ticker-search-input:focus {
  outline: none;
  border-color: var(--accent);
}

.ticker-search-spinner {
  position: absolute;
  right: 8px;
  width: 12px;
  height: 12px;
  border: 2px solid var(--border-strong);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: ticker-search-spin 700ms linear infinite;
}

@keyframes ticker-search-spin {
  to {
    transform: rotate(360deg);
  }
}

.ticker-search-results {
  position: absolute;
  z-index: 20;
  top: calc(100% + 4px);
  left: 0;
  right: 0;
  max-height: 220px;
  overflow-y: auto;
  margin: 0;
  padding: 4px;
  list-style: none;
  background: var(--panel-raised);
  border: 1px solid var(--border);
  border-radius: 8px;
  box-shadow: 0 12px 24px -12px rgba(0, 0, 0, 0.6);
}

.ticker-search-result {
  display: flex;
  align-items: baseline;
  gap: 8px;
  width: 100%;
  background: transparent;
  border: none;
  border-radius: 6px;
  padding: 6px 8px;
  color: var(--text);
  text-align: left;
  cursor: pointer;
  font: inherit;
}

.ticker-search-result:hover {
  background: var(--panel-2);
}

.ticker-search-symbol {
  font-family: var(--font-mono);
  font-weight: 700;
  color: var(--accent);
  flex-shrink: 0;
}

.ticker-search-desc {
  font-size: 0.78rem;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ticker-search-error {
  margin: 4px 0 0;
  font-size: 0.7rem;
  color: var(--loss);
}

.market-assumptions-label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  margin-bottom: 6px;
}

.market-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px 10px;
}

.market-grid label {
  /* Sin esto, un item de grid con un <input> dentro no se encoge por debajo
     del ancho mínimo intrínseco del input (mismo problema de fondo que
     .legs-panel/.chart-panel arriba, aplicado ahora al grid interno de 2
     columnas) — en un panel estrecho, la columna "Tipo r" acababa fuera de
     la tarjeta en vez de quedar en su propia columna de ~150px. */
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 0.72rem;
  color: var(--muted);
}

.market-grid input {
  min-width: 0;
  width: 100%;
  background: var(--inset);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px;
  font-size: 0.85rem;
  font-family: var(--font-mono);
}

.market-grid input:focus {
  outline: none;
  border-color: var(--accent);
}

.market-note {
  margin: 8px 0 0;
  font-size: 0.7rem;
  color: var(--muted);
  line-height: 1.4;
}

/* Más visible que .market-note (que hereda) porque un beta-tester real se
   llevó "una sorpresa desagradable" al no darse cuenta de que las cifras son
   por-unidad — este aviso no debe pasar tan desapercibido como una nota al
   margen. */
.metrics-note {
  margin-top: 12px;
  padding: 8px 10px;
  border-left: 3px solid var(--accent);
  background: var(--panel-2);
  border-radius: 0 6px 6px 0;
  font-size: 0.78rem;
  color: var(--text);
}

.metrics-note .info-trigger {
  vertical-align: -2px;
}

.pnl-corner {
  text-align: left !important;
  color: var(--muted);
  font-weight: 500;
}

.pnl-th-days {
  font-weight: 700;
  color: var(--text);
}

.pnl-th-date {
  font-size: 0.62rem;
  color: var(--muted);
  font-weight: 400;
}

.pnl-price {
  text-align: left !important;
  color: var(--text);
  font-weight: 600;
  background: var(--panel-2);
  position: relative;
}

.pnl-spot-tag {
  display: inline-block;
  background: #a78bfa;
  color: #0b1220;
  font-size: 11px;
  font-weight: 700;
  border-radius: 4px;
  padding: 0 4px;
  margin-right: 5px;
}

.pnl-spot-row td {
  border-top: 2px solid #a78bfa;
  border-bottom: 2px solid #a78bfa;
}

.pnl-today-col .pnl-th-days {
  color: var(--accent-hover);
}

/* Celda donde ambos acentos se cruzan (fila S × columna Hoy): el violeta va
   como box-shadow inset en vez de border, porque con border-collapse los 4
   bordes de la celda (violeta arriba/abajo + cian izq/dcha) competirían por
   el mismo borde compartido y solo uno "ganaría" — el box-shadow no
   participa en ese cálculo, así que ambos acentos quedan visibles a la vez. */
.pnl-spot-row .pnl-spot-today {
  border-top: none;
  border-bottom: none;
  box-shadow:
    inset 0 2px 0 #a78bfa,
    inset 0 -2px 0 #a78bfa;
}

/* --- Slider de volatilidad con marcadores ×1/×2/×3 --- */
.sigma-slider {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

.sigma-slider-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 0.72rem;
  color: var(--muted);
  margin-bottom: 4px;
}

.sigma-mult {
  color: var(--accent);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.sigma-slider input[type='range'],
.range-slider input[type='range'] {
  width: 100%;
  accent-color: var(--accent);
  cursor: pointer;
}

.sigma-marks-labels {
  display: flex;
  justify-content: space-between;
  font-size: 0.62rem;
  color: var(--muted);
  margin-top: 2px;
}

/* --- Barra de herramientas del gráfico: pestañas de vista + rango --- */
.chart-toolbar {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  margin-bottom: 10px;
}

/* Pestañas del gráfico agrupadas en 2 filas: "Escala" (4 formas de ver el
   MISMO payoff) y "Vistas" (3 vistas alternativas: tabla/greeks/taylor),
   cada grupo envuelve de forma independiente en pantallas estrechas. */
.view-tabs-stack {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.view-tabs-group {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}

.view-tabs-label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--muted);
  flex-shrink: 0;
}

.view-tabs-alt {
  background: var(--inset);
  border-radius: 8px;
  padding: 4px;
  width: fit-content;
}

.view-tabs-alt .view-tabs-label {
  margin-left: 4px;
}

.view-tabs {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}

.view-tab {
  background: var(--panel-2);
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 5px 10px;
  font-size: 0.78rem;
  cursor: pointer;
  transition: all 0.15s;
}

.view-tab:hover:not(:disabled) {
  border-color: var(--accent);
  color: var(--text);
}

.view-tab.active {
  background: var(--accent-chip);
  color: #0b1220;
  border-color: var(--accent);
  font-weight: 600;
}

.view-tab:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.range-slider {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 0.72rem;
  color: var(--muted);
  min-width: 160px;
}

/* Avanzador de días (ver CalculatorPanel.tsx): barra completa encima del
   gráfico, no el control estrecho de la toolbar — es su propia fila, no
   comparte espacio con las pestañas de vista. */
.days-slider {
  width: 100%;
  margin-bottom: 10px;
}

/* --- Tabla de Greeks --- */
.greeks {
  margin-top: 16px;
  padding-top: 14px;
  border-top: 1px solid var(--border);
}

.greeks-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 6px;
}

.greeks-header h3 {
  margin: 0;
}

.greeks-mode {
  display: flex;
  gap: 4px;
}

.mode-btn {
  background: var(--panel-2);
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 4px 9px;
  font-size: 0.72rem;
  cursor: pointer;
  transition: all 0.15s;
}

.mode-btn:hover {
  border-color: var(--accent);
  color: var(--text);
}

.mode-btn.active {
  background: var(--accent-chip);
  color: #0b1220;
  border-color: var(--accent);
  font-weight: 600;
}

.greeks-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
  font-family: var(--font-mono);
}

.greeks-table th {
  text-align: right;
  color: var(--muted);
  font-weight: 500;
  padding: 4px 6px;
  font-size: 0.72rem;
}

.greeks-table th:first-child + th {
  text-align: left;
}

.greeks-table td {
  text-align: right;
  padding: 4px 6px;
  border-top: 1px solid var(--border);
}

/* El signo pesa más que el número, sin color: a diferencia del P&L, el
   signo de una Greek no es "bueno/malo" (Theta negativo comprando opciones
   es normal), así que verde/rojo implicaría un juicio que no corresponde. */
.greek-sign {
  font-weight: 700;
}

.greeks-table td:first-child + td {
  text-align: left;
  color: var(--muted);
  white-space: nowrap;
}

/* Fila Total como bloque propio (fondo, sin el borde-separador anterior)
   en vez de una fila más de la tabla — misma <tr> real (no una tabla
   aparte) para que las columnas sigan alineadas exactamente con las de
   arriba, a diferencia del mockup, que usa dos <table> independientes. */
.greeks-table .greeks-total td {
  font-weight: 700;
  /* Antes `#f1f5f9` fijo: en modo claro, sobre un `--panel-2` que pasa a ser
     claro, quedaba prácticamente ilegible. `var(--text)` sigue al tema. */
  color: var(--text);
  background: var(--panel-2);
  border-top: none;
  padding-top: 8px;
  padding-bottom: 8px;
}

.greeks-table .greeks-total td:first-child {
  border-radius: 6px 0 0 6px;
}

.greeks-table .greeks-total td:last-child {
  border-radius: 0 6px 6px 0;
}

.greeks-check-col {
  width: 22px;
  padding: 4px 2px !important;
  text-align: center !important;
}

.greeks-check-col input[type='checkbox'] {
  cursor: pointer;
}

.greeks-table tr.leg-excluded td {
  color: var(--muted);
  opacity: 0.5;
}

.link-btn {
  background: none;
  border: none;
  color: var(--accent);
  cursor: pointer;
  padding: 0;
  font-size: inherit;
  text-decoration: underline;
}

/* --- Leyenda y curvas del gráfico --- */
.chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-bottom: 8px;
  font-size: 0.78rem;
  color: var(--muted);
}

.legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.legend-swatch {
  width: 18px;
  height: 0;
  border-top-width: 2.5px;
  border-top-style: solid;
  display: inline-block;
}

.swatch-expiry {
  border-top-color: var(--profit);
}

.swatch-today {
  border-top-color: var(--accent);
  border-top-style: dashed;
}

.swatch-spot {
  border-top-color: #a78bfa;
  border-top-style: dashed;
}

.today-line {
  stroke: var(--accent);
  stroke-width: 2;
  stroke-dasharray: 5 4;
  opacity: 0.9;
  transition: d 220ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* Zona sombreada de la curva de referencia en el comparador (ver
   ComparisonChart.tsx) — mismo acento que su línea discontinua, pero muy
   sutil (más tenue que .area-profit/.area-loss del protagonista, 0.12) para
   que se lea como "la otra estrategia" sin competir por la atención. */
.area-reference {
  fill: var(--accent);
  opacity: 0.07;
  transition: d 220ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* La línea/etiqueta/punto de S siguen al arrastre 1:1 — sin transición
   mientras se arrastra (chart-dragging), o el pomo se sentiría con retraso
   respecto al ratón. Fuera del arrastre (al escribir un precio, o al mover
   una leg que reubica el propio punto sobre la curva) sí se anima: ease-out
   limpio sin overshoot, opción "1g" del mismo documento — se descartó la
   variante con rebote (~4%) por el mismo motivo que en el morph de la curva. */
.spot-line,
.spot-label,
.spot-pnl-dot,
.spot-pnl-label {
  transition: x1 200ms cubic-bezier(0.33, 1, 0.68, 1), x2 200ms cubic-bezier(0.33, 1, 0.68, 1),
    x 200ms cubic-bezier(0.33, 1, 0.68, 1), cx 200ms cubic-bezier(0.33, 1, 0.68, 1),
    cy 200ms cubic-bezier(0.33, 1, 0.68, 1);
}

.chart-dragging .spot-line,
.chart-dragging .spot-label,
.chart-dragging .spot-pnl-dot,
.chart-dragging .spot-pnl-label {
  transition: none;
}

.spot-line {
  stroke: #a78bfa;
  stroke-width: 1.5;
  stroke-dasharray: 4 3;
}

.spot-label {
  fill: #a78bfa;
  font-size: 11px;
  font-weight: 600;
}

/* P&L en el precio actual (S): punto sobre la curva + etiqueta, verde/rojo. */
.spot-pnl-dot {
  stroke: var(--panel, #0f172a);
  stroke-width: 2;
}
.spot-pnl-dot.profit {
  fill: #22c55e;
}
.spot-pnl-dot.loss {
  fill: #ef4444;
}
.spot-pnl-label {
  font-size: 12px;
  font-weight: 700;
  paint-order: stroke;
  stroke: var(--panel, #0f172a);
  stroke-width: 3;
  stroke-linejoin: round;
}
.spot-pnl-label.profit {
  fill: #22c55e;
}
.spot-pnl-label.loss {
  fill: #ef4444;
}

/* Pomo arrastrable de la línea de S */
.spot-handle {
  touch-action: none; /* evita el scroll/gesto del navegador al arrastrar */
}

.spot-knob {
  fill: #a78bfa;
  stroke: var(--panel, #0f172a);
  stroke-width: 2;
  cursor: ew-resize;
  transition: r 0.1s ease;
}

.spot-handle:hover .spot-knob {
  fill: #c4b5fd;
}

.spot-handle.dragging .spot-knob {
  fill: #c4b5fd;
  r: 7;
}

/* --- Panel de explicación de la estrategia --- */
.print-sheet-btn {
  margin-left: auto;
  flex-shrink: 0;
  margin-top: 4px;
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 7px 12px;
  font-size: 0.82rem;
  cursor: pointer;
  transition: border-color 120ms ease;
}

.print-sheet-btn:hover {
  border-color: var(--accent);
}

.expl-header:hover {
  background: var(--panel-2);
}

/* Por encima de este ancho, las 3 secciones (siempre son 3, número fijo)
   caben en una sola fila: formato pregunta + divisores verticales sutiles
   en vez de gap, para que se lean como 3 respuestas distintas. Por debajo,
   se apilan y basta con el gap — un border-left ahí no separaría nada. */
@media (min-width: 640px) {
  .expl-body {
    gap: 0;
  }

  .expl-section {
    padding: 0 18px;
  }

  .expl-section:first-child {
    padding-left: 0;
  }

  .expl-section:last-child {
    padding-right: 0;
  }

  .expl-section:not(:first-child) {
    border-left: 1px solid var(--border);
  }
}

.expl-section h4 {
  margin: 0 0 8px;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--text);
}

.expl-section p {
  margin: 0;
  font-size: 0.85rem;
  line-height: 1.55;
  color: var(--muted);
}

.expl-section strong {
  /* Antes `#fff` fijo: invisible sobre un panel que en modo claro pasa a ser
     blanco. `var(--text)` sigue al tema en vez de asumir un fondo oscuro. */
  color: var(--text);
  font-weight: 700;
}

/* --- Tooltip interactivo del gráfico --- */
.hover-line {
  stroke: var(--muted);
  stroke-width: 1;
  stroke-dasharray: 3 3;
  opacity: 0.7;
}

.hover-dot {
  fill: var(--accent);
  stroke: #0b1220;
  stroke-width: 1.5;
}

/* El tooltip se monta/desmonta con el estado `hover` (condicional en JSX), así
   que la animación se relanza sola cada vez que reaparece — sin JS extra.
   Opción "2a" (fade + leve escala) de Payoff Chart Animation Options.dc.html;
   se descartó el deslizamiento vertical por no aportar frente a esta y
   "sin animación" por sentirse brusco al mover el ratón rápido. */
@keyframes tooltip-fade-scale {
  from {
    opacity: 0;
    transform: scale(0.92);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

.tooltip {
  transform-box: fill-box;
  transform-origin: center;
  animation: tooltip-fade-scale 130ms cubic-bezier(0.22, 1, 0.36, 1) both;
}

.tooltip-box {
  fill: var(--panel-2);
  stroke: var(--border);
  stroke-width: 1;
}

.tooltip-text {
  fill: var(--text);
  font-size: 11px;
  font-weight: 500;
}

.tooltip-pnl-profit {
  fill: var(--profit);
  font-weight: 600;
}

.tooltip-pnl-loss {
  fill: var(--loss);
  font-weight: 600;
}

/* --- Comparar estrategias (/comparar) --- */
.compare-pickers {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
  margin: 16px 0;
}

/* Selector + editor de legs apilados por lado — el editor de legs completo
   (ver LegsEditor.tsx) reutiliza el mismo .legs-panel de la calculadora
   libre para que el resultado visual/de comportamiento sea idéntico. */
.compare-side {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 0;
}

.compare-metric-toggle input[type='checkbox'] {
  cursor: pointer;
}

.compare-select:focus {
  outline: none;
  border-color: var(--accent);
}

.compare-swap-btn:hover {
  border-color: var(--accent);
}

.compare-table th {
  text-align: right;
  padding: 8px 10px;
  font-weight: 600;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  border-bottom: 1px solid var(--border);
}

/* --- Visualización de Greeks (LineChart, selector, Taylor) --- */
.gv-line-a,
.gv-line-b {
  transition: d 220ms cubic-bezier(0.22, 1, 0.36, 1);
}

/* A diferencia del gráfico de payoff principal (que congela el eje X durante
   el arrastre vía drag.dragBounds), en LineChart la ventana de precios de
   greeksSeries/taylorData se recalcula en cada render directamente a partir
   de `spot` — así que al arrastrar la línea de S aquí, la curva entera se
   recalcula en cada pointermove, no solo el punto. Con la transición de "d"
   puesta, cada uno de esos cambios rapidísimos disparaba una animación
   nueva que nunca llegaba a completarse: la curva se veía distorsionada y
   nada fluida al arrastrar rápido. Mismo arreglo que en spot-line: sin
   transición mientras se arrastra. */
.chart-dragging .gv-line-a,
.chart-dragging .gv-line-b {
  transition: none;
}
.gv-line-a {
  stroke: var(--accent);
  stroke-width: 2.5;
}
.gv-line-b {
  stroke: #a78bfa;
  stroke-width: 2;
  stroke-dasharray: 5 4;
}
.gv-line-a-swatch {
  border-top-color: var(--accent);
}
.gv-line-b-swatch {
  border-top-color: #a78bfa;
  border-top-style: dashed;
}

.greek-picker {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 8px;
}

.greek-btn {
  background: var(--panel-2);
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 5px 10px;
  font-size: 0.78rem;
  cursor: pointer;
  transition: all 0.15s;
}
.greek-btn:hover {
  border-color: var(--accent);
  color: var(--text);
}
.greek-btn.active {
  background: var(--accent-chip);
  color: #0b1220;
  border-color: var(--accent);
  font-weight: 600;
}

.taylor-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 14px;
  margin-top: 12px;
  padding: 12px 14px;
  background: var(--panel-2);
  border: 1px solid var(--border);
  border-radius: 10px;
}

.taylor-field {
  display: flex;
  flex-direction: column;
  gap: 3px;
  font-size: 0.72rem;
  color: var(--muted);
}
.taylor-field input {
  width: 90px;
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  padding: 6px;
  font-size: 0.85rem;
}
.taylor-field input:focus {
  outline: none;
  border-color: var(--accent);
}

.taylor-reset {
  padding: 8px 12px;
  font-size: 0.8rem;
}
.taylor-reset:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}

.taylor-note {
  flex: 1 1 260px;
  margin: 0;
  font-size: 0.72rem;
  line-height: 1.5;
  color: var(--muted);
}

/* --- Pantalla completa del gráfico --- */
.fs-toggle {
  background: var(--panel-2);
  color: var(--muted);
  border: 1px solid var(--border);
  border-radius: 7px;
  padding: 5px 10px;
  font-size: 0.78rem;
  cursor: pointer;
  white-space: nowrap;
  transition: all 0.15s;
}
.fs-toggle:hover {
  border-color: var(--accent);
  color: var(--text);
}
/* --- Controles de la tabla P&L (mover S / desplazar precios) --- */
.table-controls {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  margin-bottom: 10px;
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--panel-2);
}
.tc-group {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.tc-label {
  font-size: 0.74rem;
  color: var(--muted);
}
.tc-btn {
  min-width: 30px;
  padding: 4px 9px;
  background: var(--panel);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 0.82rem;
  cursor: pointer;
  transition: border-color 0.15s;
}
.tc-btn:hover:not(:disabled) {
  border-color: var(--accent);
}
.tc-btn:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
.tc-btn.ghost {
  color: var(--muted);
}
.tc-value {
  min-width: 56px;
  text-align: center;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.tc-hint {
  font-size: 0.7rem;
  color: var(--muted);
}

.chart-panel.chart-fs {
  position: fixed;
  inset: 0;
  z-index: 1000;
  border-radius: 0;
  overflow: auto;
  padding: 20px clamp(16px, 5vw, 64px);
}

.chart-fs .chart-toolbar {
  position: sticky;
  top: 0;
  background: var(--panel);
  padding-bottom: 10px;
  z-index: 1;
}

.chart-fs .fs-toggle {
  background: var(--accent-chip);
  color: #0b1220;
  border-color: var(--accent);
  font-weight: 700;
}

/* En pantalla completa, el gráfico aprovecha el alto disponible. */
.chart-fs .chart svg {
  max-height: 78vh;
}

/* --- Captura PNG (gráfico/tabla + métricas) --- */
.capture-area.shooting {
  background: var(--bg);
  padding: 16px;
  border-radius: 10px;
}

.capture-strip {
  margin-bottom: 12px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--border);
}

.cap-title {
  font-size: 1rem;
  font-weight: 700;
  color: var(--text);
}

.cap-params {
  font-size: 0.75rem;
  color: var(--muted);
  margin-top: 3px;
}

.cap-metrics {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  margin-top: 8px;
  font-size: 0.8rem;
  color: var(--text);
}
.cap-metrics span {
  font-weight: 600;
}

.cap-greeks {
  margin-top: 6px;
  font-size: 0.75rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/*
 * Aquí había un `body * { visibility: hidden }` al imprimir, traído de Options
 * World para su hoja de estrategia —las `.sheet-*` de abajo—, que en esta web
 * no se usa. Dejaba en blanco cualquier página con Ctrl+P (Javi, 12-sep-2026).
 * Quitado; la criba tiene su propio documento para imprimir (`ImpresionCriba`).
 */
@media print {
  @page {
    size: A4 portrait;
    margin: 14mm;
  }
}

.sheet-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  padding-bottom: 14px;
  border-bottom: 2px solid #111827;
}

.sheet-title {
  font-size: 26px;
  font-weight: 800;
  letter-spacing: -0.01em;
}

.sheet-subtitle {
  font-size: 13px;
  color: #4b5563;
  margin-top: 4px;
}

.sheet-bias-badge {
  display: flex;
  align-items: center;
  gap: 8px;
  border: 1.5px solid #111827;
  border-radius: 999px;
  padding: 6px 14px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.03em;
  color: #111827;
}

.sheet-chart-label {
  font-size: 12px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: #4b5563;
  margin-top: 16px;
  margin-bottom: 6px;
}

.sheet-chart {
  width: 100%;
  height: auto;
  display: block;
}

.sheet-axis {
  stroke: #9ca3af;
  stroke-width: 1;
}

.sheet-spot-line {
  stroke: #4b5563;
  stroke-width: 1;
  stroke-dasharray: 3 3;
}

.sheet-spot-text {
  font-size: 11px;
  fill: #4b5563;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
}

.sheet-be-line {
  stroke: #111827;
  stroke-width: 1.3;
  stroke-dasharray: 2 3;
  opacity: 0.55;
}

.sheet-area-profit {
  fill: rgba(21, 128, 61, 0.14);
}

.sheet-area-loss {
  fill: rgba(185, 28, 28, 0.14);
}

.sheet-hatch {
  color: rgba(17, 24, 39, 0.45);
}

.sheet-line {
  stroke: #111827;
  stroke-width: 2.4;
}

.sheet-tick {
  font-size: 11px;
  fill: #4b5563;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
}

.sheet-metrics {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
  margin-top: 18px;
}

.sheet-metric-card {
  background: #f8fafc;
  border: 1.5px solid #cbd5e1;
  border-left: 4px solid #111827;
  border-radius: 6px;
  padding: 10px 12px;
}

.sheet-metric-label {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: #4b5563;
}

.sheet-metric-value {
  font-size: 18px;
  font-weight: 800;
  font-family: 'JetBrains Mono', ui-monospace, monospace;
  margin-top: 5px;
  color: #111827;
}

.sheet-metric-sub {
  font-size: 11px;
  color: #4b5563;
  margin-top: 2px;
}

.sheet-explanation {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
  margin-top: 22px;
}

.sheet-explanation h4 {
  font-size: 13px;
  font-weight: 700;
  border-bottom: 1.5px solid #111827;
  padding-bottom: 5px;
  margin: 0 0 7px;
}

.sheet-explanation p {
  font-size: 12.5px;
  line-height: 1.5;
  color: #4b5563;
  margin: 0;
}

.sheet-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 10px;
  margin-top: 24px;
  border-top: 1px solid #cbd5e1;
  font-size: 11px;
  color: #4b5563;
}

.sheet-footer-brand {
  font-weight: 700;
  color: #111827;
}

.sheet-footer-note {
  font-style: italic;
}

/* Banner de feedback para beta-testers (ver FeedbackBanner.tsx) — elemento
   normal dentro del flujo de la página (no flotante), montado donde debe
   aparecer: Landing.tsx (encima del listado de estrategias) y
   StrategyPage.tsx (encima de la explicación, o arriba del todo en la
   estrategia personalizada, que no tiene explicación). */
.feedback-banner {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 16px 0;
  background: var(--panel);
  border: 1px solid var(--accent);
  border-radius: 12px;
  padding: 14px 16px;
}

.feedback-banner-text {
  flex: 1;
  font-size: 0.85rem;
  line-height: 1.4;
  color: var(--text);
}

.feedback-banner-cta {
  flex-shrink: 0;
  white-space: nowrap;
  text-decoration: none;
}

.feedback-banner-close {
  flex-shrink: 0;
  background: transparent;
  border: none;
  color: var(--muted);
  font-size: 1rem;
  cursor: pointer;
  padding: 4px;
  line-height: 1;
}

.feedback-banner-close:hover {
  color: var(--text);
}

@media (max-width: 640px) {
  .feedback-banner {
    flex-direction: column;
    align-items: stretch;
  }
}

/* Enlaces auxiliares del índice de Opciones (lienzo, cómo se usa, glosario). */
.enlaces-opciones {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
}

/* Enlaces sueltos (índice de opciones, "analizar en la calculadora"). */
.modulo-enlace-suelto {
  color: var(--acento);
  font-weight: 600;
  text-decoration: none;
}
.modulo-enlace-suelto:hover {
  text-decoration: underline;
}
/* Selector "cargar mi posición" en la calculadora. */
.mis-posiciones {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  font-size: 0.85rem;
}
.mis-posiciones label {
  color: var(--muted, #94a3b8);
}

/* Pestañas de la Cartera (Posiciones · Operaciones · Rendimiento). */
.pestanas-cartera {
  display: flex;
  gap: 0.5rem;
  border-bottom: 1px solid var(--borde);
  margin-bottom: 1.5rem;
}
.pestanas-cartera .pestana {
  background: transparent;
  border: none;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  color: var(--apagado);
  padding: 0.6rem 0.9rem;
  font-size: 0.95rem;
  font-weight: 600;
  cursor: pointer;
}
.pestanas-cartera .pestana:hover {
  color: var(--texto);
}
.pestanas-cartera .pestana.activa {
  color: var(--texto);
  border-bottom-color: var(--acento);
}

/* Resultado de las herramientas de empresas. */
.linea-resultado {
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--borde);
}
.res-bien strong { color: #3fb950; }
.res-mal strong { color: var(--error); }
.res-ojo strong { color: #e3a72f; }

/* Ficha fundamental: el botón de autorrelleno alineado con los campos, y los
   grupos de métricas en una rejilla que se adapta al ancho. */
.acciones-formulario {
  display: flex;
  align-items: flex-end;
}
.rejilla-fichas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
  gap: 1.25rem 2rem;
}
.ficha-grupo h3 {
  margin: 0 0 0.3rem;
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--apagado);
}

/* Screener: panel de filtros por métrica + tabla ancha con scroll propio. */
.rejilla-filtros {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: 0.6rem 1rem;
  margin-top: 0.5rem;
}
.filtro-metrica {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}
.filtro-etiqueta {
  font-size: 0.85rem;
}
.filtro-rango {
  display: flex;
  gap: 0.4rem;
}
.filtro-rango input {
  width: 100%;
  min-width: 0;
  margin-bottom: 0;
}
.tabla-scroll {
  overflow-x: auto;
}
.tabla-screener {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.9rem;
  white-space: nowrap;
}
.tabla-screener th,
.tabla-screener td {
  padding: 0.4rem 0.6rem;
  border-bottom: 1px solid var(--borde);
  text-align: right;
}
.tabla-screener th:nth-child(-n + 3),
.tabla-screener td:nth-child(-n + 3) {
  text-align: left;
}
.tabla-screener .col-ticker {
  font-weight: 700;
}
.tabla-screener .col-empresa {
  max-width: 16rem;
  overflow: hidden;
  text-overflow: ellipsis;
}
.tabla-screener .col-sector {
  color: var(--apagado);
  max-width: 12rem;
  overflow: hidden;
  text-overflow: ellipsis;
}
.th-orden {
  background: none;
  border: 0;
  color: var(--apagado);
  font: inherit;
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  cursor: pointer;
  padding: 0;
}
.th-orden:hover {
  color: var(--texto);
}

/* Sello de la Cartera: "Cartera de Jota Investor · a fecha X". Deja claro que
   es una foto a una fecha, no un valor en vivo. */
.cartera-sello {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.2rem 0.7rem;
  margin-bottom: 0.2rem;
}

/* Watchlist: entradas plegables con la investigación dentro. */
.watchlist-cabecera {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  width: 100%;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: var(--texto);
  font: inherit;
  text-align: left;
}
.watchlist-cabecera strong {
  font-size: 1.05rem;
}

/* Pestañas de la watchlist: son 22, así que envuelven y hacen scroll. */
.pestanas-watchlist {
  display: flex;
  flex-wrap: wrap;
  gap: 0.3rem;
  margin-bottom: 1rem;
}
.pestanas-watchlist .pestana {
  font-size: 0.85rem;
  padding: 0.25rem 0.6rem;
}

/* Píldora de estado (idea/watch/skip/privada/cartera…). */
.estado-pill {
  font-size: 0.72rem;
  font-weight: 600;
  padding: 0.05rem 0.45rem;
  border-radius: 5px;
  white-space: nowrap;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}
.investigacion {
  margin-top: 0.8rem;
  max-width: 46rem;
  line-height: 1.6;
}
.investigacion p {
  margin: 0 0 0.8rem;
}
.campo-ancho {
  display: flex;
  flex-direction: column;
  margin-top: 0.6rem;
}
.campo-ancho textarea {
  width: 100%;
  font: inherit;
  resize: vertical;
}

/* =====================================================================
   WATCHLIST REDISEÑADA (Fase 1, ADR-0009) — sobre tokens --ji-* de
   disenio.css, tema-aware. Solo van aquí los estados que no se pueden
   hacer inline (:hover, foco, animación); el resto del estilo vive inline
   en la propia página con var(--ji-*), igual que el prototipo.
   ===================================================================== */
.wl-wrap {
  max-width: 1120px;
  margin: 0 auto;
  padding: 8px 0 60px;
}

/* Variante ANCHA para las pantallas que son una herramienta y no un texto.
   Los 1120 px de arriba son una medida de lectura: por encima de unos 90
   caracteres por línea el ojo se pierde al saltar de renglón. Pero eso vale
   para prosa, no para un analizador — ahí el límite deja medio monitor en
   negro, que es lo que Javi señaló.

   `min()` y no un valor fijo: en un portátil manda el 96 % del ancho y en un
   monitor grande manda el tope, para que la gráfica no acabe siendo una franja
   de dos metros de ancho y un palmo de alto. */
.wl-wrap--ancho {
  max-width: min(1720px, 96vw);
  font-family: var(--ji-ui);
  color: var(--ji-text);
}

/* Tarjeta de universo (rejilla). */
.wl-card {
  transition: background 0.2s, border-color 0.2s, transform 0.2s;
}
.wl-card:hover {
  background: var(--ji-surface-2);
  border-color: color-mix(in srgb, var(--ji-gold) 35%, transparent);
  transform: translateY(-2px);
}
.wl-card:hover .wl-card-nombre {
  color: var(--ji-gold);
}

/* Fila de la lista / de un universo. */
.wl-row {
  transition: background 0.15s, border-color 0.15s;
}
.wl-row:hover {
  background: var(--ji-surface-2);
}

/* Controles: switch de vista, filtros, toggle de modo. */
.wl-btn {
  cursor: pointer;
  transition: color 0.15s, background 0.15s, border-color 0.15s;
  font-family: var(--ji-ui);
}

.wl-search {
  font-family: var(--ji-ui);
  transition: border-color 0.15s;
}
.wl-search:focus {
  outline: none;
  border-color: color-mix(in srgb, var(--ji-gold) 40%, transparent);
}

.wl-back {
  font-size: 12px;
  color: var(--ji-muted);
  background: none;
  border: none;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 0;
  font-family: var(--ji-ui);
  transition: color 0.15s;
}
.wl-back:hover {
  color: var(--ji-text);
}

/* Reveal suave al entrar/cambiar de vista. */
@keyframes wl-fade {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.wl-fade {
  animation: wl-fade 0.4s cubic-bezier(0.16, 1, 0.3, 1) both;
}
@media (prefers-reduced-motion: reduce) {
  .wl-fade {
    animation: none;
  }
}

/* Iconos de sector "encender la luz": contorno apagado + capa dorada que se
   revela con clip-path al pasar el ratón por la tarjeta/fila, o forzada (.on). */
.sicon {
  position: relative;
  display: inline-block;
  flex-shrink: 0;
  line-height: 0;
}
.sicon .base,
.sicon .gold {
  position: absolute;
  inset: 0;
}
.sicon .base {
  color: color-mix(in srgb, var(--ji-muted) 55%, transparent);
}
.sicon .base svg,
.sicon .gold svg {
  display: block;
  width: 100%;
  height: 100%;
}
.sicon .gold {
  color: var(--ji-gold);
  overflow: hidden;
  clip-path: inset(100% 0 0 0);
  transition: clip-path 0.45s cubic-bezier(0.16, 1, 0.3, 1);
}
.sicon .gold.on {
  clip-path: inset(0 0 0 0);
}
.wl-card:hover .sicon .gold,
.wl-row:hover .sicon .gold {
  clip-path: inset(0 0 0 0);
}
@media (prefers-reduced-motion: reduce) {
  .sicon .gold {
    transition: none;
  }
}

/* Tablas del rediseño (reutilizables: Cartera, y lo que venga). */
.ji-table-wrap {
  border: 1px solid var(--ji-border);
  border-radius: 14px;
  overflow: hidden;
}
.ji-table-scroll {
  overflow-x: auto;
}
.ji-table {
  width: 100%;
  border-collapse: collapse;
  font-family: var(--ji-ui);
}
.ji-table th {
  text-align: left;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--ji-muted);
  font-weight: 500;
  padding: 11px 14px;
  background: var(--ji-surface);
  border-bottom: 1px solid var(--ji-border);
  white-space: nowrap;
}
.ji-table td {
  padding: 12px 14px;
  border-top: 1px solid var(--ji-border);
  font-size: 13px;
  color: var(--ji-text);
}
.ji-table tbody tr:first-child td {
  border-top: none;
}
.ji-table th.num,
.ji-table td.num {
  text-align: right;
  font-family: var(--ji-mono);
  font-variant-numeric: tabular-nums;
}
.ji-table td .sub {
  display: block;
  font-size: 11px;
  color: var(--ji-muted);
  margin-top: 2px;
}
/* Divisa de un precio: «20,45 USD». Apagada y pequeña para que no compita con
   la cifra, pero presente — el número solo no dice en qué moneda está.
   Los códigos ISO son siempre de tres letras, así que la columna sigue
   cuadrando en vertical. */
.ji-table td .divisa {
  margin-left: 4px;
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--ji-muted);
}

/* Operaciones: grupos de operativa (spread) dentro de la tabla. */
.ji-table tbody.grupo {
  background: color-mix(in srgb, var(--ji-gold) 4%, transparent);
}
.ji-table tbody.grupo .cab-grupo td {
  border-top: 1px solid color-mix(in srgb, var(--ji-gold) 28%, transparent);
}
.ji-desplegar {
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font-family: var(--ji-ui);
  font-size: 13px;
  color: var(--ji-gold);
  text-align: left;
}
.ji-desplegar:hover {
  text-decoration: underline;
}
.ji-desplegar .flecha {
  display: inline-block;
  width: 0.9em;
}
.ji-desplegar .apagado {
  color: var(--ji-muted);
}
.ji-enlace-op {
  color: var(--ji-blue);
  text-decoration: none;
  font-size: 13px;
}
.ji-enlace-op:hover {
  text-decoration: underline;
}

/* Pares clave/valor (Riesgo, La otra cara). */
.ji-kv {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 9px 20px;
  margin: 4px 0 0;
}
.ji-kv dt {
  font-size: 13px;
  color: var(--ji-muted);
}
.ji-kv dd {
  margin: 0;
  font-size: 13px;
  color: var(--ji-text);
  font-family: var(--ji-mono);
  font-variant-numeric: tabular-nums;
}
.ji-kv dd .apagado {
  color: var(--ji-muted);
  font-family: var(--ji-ui);
}

/* Barras de rentabilidad mes a mes (sin librería). */
.ji-bars {
  display: flex;
  align-items: stretch;
  gap: 2px;
  height: 150px;
  margin-top: 12px;
  overflow-x: auto;
}
.ji-bars .mes {
  display: flex;
  flex-direction: column;
  flex: 1 0 5px;
  min-width: 5px;
}
.ji-bars .mitad {
  flex: 1;
  display: flex;
}
.ji-bars .mitad.arriba {
  align-items: flex-end;
  border-bottom: 1px solid var(--ji-border);
}
.ji-bars .mitad.abajo {
  align-items: flex-start;
}
.ji-bars .barra {
  width: 100%;
  border-radius: 2px;
}
.ji-bars .barra.pos {
  background: var(--ji-gain);
}
.ji-bars .barra.neg {
  background: var(--ji-loss);
}
.ji-bars-ext {
  display: flex;
  justify-content: space-between;
  font-size: 11px;
  color: var(--ji-muted);
  margin-top: 6px;
}

/* Ficha: dos columnas que colapsan en estrecho. */
.wl-ficha {
  display: grid;
  grid-template-columns: 1fr 340px;
  gap: 40px;
  align-items: start;
  margin-top: 28px;
}
@media (max-width: 820px) {
  .wl-ficha {
    grid-template-columns: 1fr;
    gap: 24px;
  }
}

/* =====================================================================
   ACCESO Y HUB (rediseño) — la puerta de entrada.
   Formularios y botones del design-system, usados por login, registro,
   recuperar contraseña y el hub. Igual que el resto de `.ji-*`: opt-in,
   no pisa nada de lo viejo.
   ===================================================================== */

/* Pantalla de acceso: tarjeta centrada sobre el fondo de marca. */
.ji-acceso {
  /*
   * SE COME EL RELLENO DEL BODY.
   *
   * Esta pantalla pide `100dvh` y vive DENTRO de un body con relleno, así que
   * medía la altura de la pantalla más 80 px y sobraba siempre ese trozo: el
   * login se desplazaba sin tener nada que enseñar debajo, y en el registro
   * —que lleva un campo más— el enlace de «Inicia sesión» se quedaba 7 px por
   * debajo del corte. Siete píxeles no se ven: la página parece acabar ahí.
   *
   * De esos 80, 56 son para la barra inferior del móvil, QUE EN LAS PANTALLAS
   * DE ACCESO NO EXISTE. Se reservaba sitio para algo que no está.
   *
   * Los márgenes negativos salen de las mismas variables que el relleno, así
   * que si alguien cambia una, esto sigue cuadrando.
   */
  margin: calc(-1 * var(--ji-pad-y)) calc(-1 * var(--ji-pad-x)) calc(-1 * var(--ji-pad-abajo));

  /*
   * `dvh` Y NO `vh`, con `vh` de reserva para navegadores viejos.
   *
   * En Safari de iOS, `100vh` vale la altura de la pantalla SIN la barra de
   * direcciones, o sea más de lo que se ve. Con `justify-content: center` sobre
   * una caja más alta que la pantalla, la tarjeta se centra respecto a algo
   * invisible: queda baja y los enlaces del pie —«¿Olvidaste tu contraseña?»,
   * «Crear cuenta con código»— caen por debajo del corte. En un login, tener que
   * descubrir que hay que bajar es exactamente el momento en que la gente se va.
   *
   * `dvh` mide lo que de verdad se ve y se ajusta al recogerse la barra.
   *
   * `disenio.css` ya usaba `dvh` en la landing; esto se quedó atrás. Y tampoco
   * se ve en la vista previa: Blink no tiene la barra que se esconde.
   */
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 32px 20px;
  background: var(--ji-bg);
}
.ji-acceso-caja {
  width: 100%;
  max-width: 26rem;
  /* Por encima de la galaxia. Sin esto, el vídeo y la tarjeta compiten por el
     mismo nivel y gana el que se pinte después. */
  position: relative;
  z-index: 1;
}

/* =====================================================================
   `.ji-acceso-galaxia` · el mismo vídeo de la portada, detrás del acceso
   =====================================================================

   NO reutiliza `.lp-galaxia`: aquella mide 124vh y se desvanece hacia abajo
   para coser la portada con la sección de cifras. Aquí el hueco es la ventana
   entera y el problema es el contrario —no hay costura que tapar, hay una
   tarjeta que tiene que seguir leyendo como tarjeta—.

   POR QUÉ HACE FALTA UNA VIÑETA, medido y no supuesto:

   La primera sospecha fue que el núcleo brillante de la galaxia —luminancia
   media 40,7 sobre 255 en el centro del clip, contra 16,7 del fondo del sitio—
   dejaría la tarjeta más oscura que lo que la rodea. ERA FALSA: el núcleo cae
   JUSTO DETRÁS de la caja, que es opaca, y la banda de 40 px que la rodea mide
   13,8 — más oscura que el propio fondo. La tarjeta se lee perfectamente.

   El problema real es otro y solo aparece midiendo contraste: sobre el vídeo no
   queda solo la tarjeta, quedan el rótulo «Jota Investor» (11 px), el título
   (30 px) y los enlaces del pie (13 px). Y por ahí pasan ESTRELLAS. Contraste
   mínimo del peor píxel, en siete fotogramas repartidos por el clip:

                          sin viñeta      con esta viñeta     pide AA
     rótulo 11 px           1,54 : 1         5,32 : 1          4,5
     título 30 px           2,68 : 1         6,27 : 1          3,0
     pie 13 px              2,69 : 1         6,57 : 1          4,5

   O sea que sin viñeta el rótulo de la marca se borra contra una estrella.

   LOS NÚMEROS DE LA ELIPSE SALEN DEL MÓVIL, no del escritorio. En 1440×900 casi
   cualquier valor pasa; en 375×812 no, porque `object-fit: cover` sobre un clip
   16:9 en una pantalla alta amplia un 13 % y recorta 534 px por lado, metiendo
   el núcleo entero dentro. Ahí una elipse de 55 × 65 dejaba el rótulo en 4,20 y
   suspendía. La de 70 × 62 con la parada intermedia al 0,62 pasa en los tres
   tamaños probados y solo cuesta bajar el brillo máximo de la galaxia de 26,9
   a 23,8, que no se nota.
   ===================================================================== */
/* Ancla de la galaxia, que va en posición absoluta. Sin `overflow` aquí: el
   propio `.ji-acceso-galaxia` ya recorta el vídeo, y un recorte de más en el
   contenedor solo serviría para comerse el anillo de foco de un campo que
   toque el borde. */
.ji-acceso {
  position: relative;
}
.ji-acceso-galaxia {
  position: absolute;
  inset: 0;
  z-index: 0;
  /* Decoración: no debe comerse ni un clic ni una pulsación del formulario. */
  pointer-events: none;
  overflow: hidden;
}
.ji-acceso-galaxia video,
.ji-acceso-galaxia img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  opacity: 0.55;
  display: block;
}
/* La viñeta. En proporciones y no en píxeles: así sigue cayendo sobre el texto
   en cualquier ventana, que es justo lo que un valor en píxeles no hace.

   La elipse desborda la ventana por los cuatro lados, así que solo las esquinas
   quedan fuera: son las únicas que ven el vídeo a plena fuerza. Y como ahí el
   clip es cielo negro (8,5 de luminancia contra los 16,7 del fondo), el efecto
   neto es que la pantalla de acceso se oscurece por los bordes. */
.ji-acceso-galaxia::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(
    ellipse 70% 62% at 50% 50%,
    var(--ji-bg) 0%,
    color-mix(in srgb, var(--ji-bg) 62%, transparent) 55%,
    transparent 100%
  );
}
/* TEMA CLARO: una galaxia es un objeto de cielo oscuro y sobre papel no hay
   versión honesta de ella —a 0,55 sobre crema se ve una mancha grisácea, no un
   cielo—. Se queda como textura, muy por debajo, en vez de quitarla: así la
   puerta de entrada sigue teniendo algo detrás en los dos temas. */
:root[data-theme='light'] .ji-acceso-galaxia video,
:root[data-theme='light'] .ji-acceso-galaxia img {
  opacity: 0.14;
}

/* Campos de formulario. */
.ji-campo {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 16px;
}
.ji-campo > span {
  font-family: var(--ji-ui);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ji-muted);
}

/*
 * Las casillas legales del registro.
 *
 * Texto en minúscula y del tamaño de lectura, no la versalita de las etiquetas
 * de campo: esto hay que LEERLO, no reconocerlo de un vistazo. Una renuncia al
 * desistimiento escrita en 11 px y en mayúsculas no es una renuncia informada.
 */
.ji-check {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin-bottom: 14px;
  font-family: var(--ji-ui);
  font-size: 13px;
  line-height: 1.55;
  color: var(--ji-muted);
  cursor: pointer;
}
.ji-check strong {
  color: var(--ji-text);
  font-weight: 600;
}
/* La casilla no hereda el ancho completo de `.ji-campo input`. */
.ji-check input[type='checkbox'] {
  flex: none;
  width: 18px;
  height: 18px;
  margin: 1px 0 0;
  accent-color: var(--ji-gold);
  cursor: pointer;
}
.ji-check input[type='checkbox']:focus-visible {
  outline: 2px solid var(--ji-gold);
  outline-offset: 2px;
}
.ji-campo input,
.ji-campo select,
.ji-campo textarea {
  width: 100%;
  font-family: var(--ji-ui);
  font-size: 15px;
  color: var(--ji-text);
  background: var(--ji-inset);
  border: 1px solid var(--ji-border);
  border-radius: 10px;
  padding: 11px 13px;
  margin: 0;
  transition: border-color 0.15s;
}
/*
 * Los enlaces del pie del acceso, separados en móvil.
 *
 * Iban a 9 px uno de otro y miden 17 y 20 px de alto: dos destinos distintos
 * —recuperar contraseña y registrarse— dentro de la superficie de un pulgar.
 * Agrandar la zona de toque los habría solapado, que es peor: tocas uno y se
 * abre el otro. Así que lo que se separa es el pie.
 *
 * No se persigue aquí el mínimo de 44 px: son enlaces de texto, uno de ellos
 * dentro de una frase, y forzarlo rompería la línea. Los botones de verdad
 * —«Entrar», «Crear cuenta»— sí lo cumplen: miden 44.
 */
@media (max-width: 768px) {
  .ji-acceso a.ji-enlace {
    display: inline-block;
    padding: 5px 4px;
  }
}

/*
 * EN MÓVIL, 16 px Y NO 15. No es estética: Safari de iOS HACE ZOOM sobre la
 * página al enfocar un campo con menos de 16 px, y luego el usuario se queda
 * con la pantalla ampliada y tiene que salir a pellizcos.
 *
 * Dónde duele: `ji-campo` viste el login, el registro con código y las dos
 * pantallas de contraseña — o sea el camino de entrada entero, que es justo lo
 * que se abre desde el móvil al llegar de un correo del Substack. Que las
 * herramientas sean de escritorio no salva a la puerta.
 *
 * Se cambia solo en móvil para no tocar el escritorio, donde 15 px es la
 * decisión de diseño.
 *
 * Y CÓMO SALIÓ, que importa: NO se vio. La vista previa emula Android sobre
 * Blink y ahí este zoom no existe; salió de MEDIR el `font-size` de los campos.
 * Es el ejemplo exacto del aviso del `CLAUDE.md` de la carpeta: redimensionar
 * el viewport no equivale a un móvil de verdad.
 */
@media (max-width: 768px) {
  .ji-campo input,
  .ji-campo select,
  .ji-campo textarea {
    font-size: 16px;
  }
}
.ji-campo input:focus,
.ji-campo select:focus,
.ji-campo textarea:focus {
  outline: none;
  border-color: color-mix(in srgb, var(--ji-gold) 55%, transparent);
}
.ji-campo input::placeholder {
  color: color-mix(in srgb, var(--ji-muted) 70%, transparent);
}

/* Botones. El primario usa el oro sólido con texto oscuro fijo, por eso
   `--ji-gold-solid` y no `--ji-gold` (que se oscurece en tema claro para
   servir como color de texto). */
.ji-btn-principal {
  width: 100%;
  font-family: var(--ji-ui);
  font-size: 15px;
  font-weight: 600;
  color: #0d1119;
  background: var(--ji-gold-solid);
  border: none;
  border-radius: 10px;
  padding: 12px 18px;
  cursor: pointer;
  transition: filter 0.15s;
}
.ji-btn-principal:hover:not(:disabled) {
  filter: brightness(1.06);
}
.ji-btn-principal:disabled {
  opacity: 0.55;
  cursor: default;
}
.ji-btn-secundario {
  font-family: var(--ji-ui);
  font-size: 13px;
  color: var(--ji-text);
  background: var(--ji-surface);
  border: 1px solid var(--ji-border);
  border-radius: 999px;
  padding: 7px 16px;
  cursor: pointer;
  transition: border-color 0.15s;
}
.ji-btn-secundario:hover {
  border-color: var(--ji-border-strong);
}

/* Enlaces dentro del rediseño. */
.ji a.ji-enlace,
.ji-acceso a.ji-enlace {
  color: var(--ji-gold);
  text-decoration: none;
}
.ji a.ji-enlace:hover,
.ji-acceso a.ji-enlace:hover {
  text-decoration: underline;
}

/* Aviso de error del rediseño. */
.ji-error {
  font-family: var(--ji-ui);
  font-size: 13px;
  color: var(--ji-loss);
  background: color-mix(in srgb, var(--ji-loss) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--ji-loss) 28%, transparent);
  border-radius: 10px;
  padding: 10px 13px;
  margin-bottom: 14px;
}

/* Rejilla de módulos del hub. */
.ji-modulos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  gap: 16px;
  list-style: none;
  padding: 0;
  margin: 0;
}
.ji-modulo {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 24px 22px;
  background: var(--ji-surface);
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio);
  color: inherit;
  text-decoration: none;
  position: relative;
  overflow: hidden;
  transition: background 0.2s, border-color 0.2s, transform 0.2s;
}
a.ji-modulo:hover {
  background: var(--ji-surface-2);
  border-color: color-mix(in srgb, var(--ji-gold) 35%, transparent);
  transform: translateY(-2px);
}
a.ji-modulo:hover .ji-modulo-abrir {
  color: var(--ji-gold);
}
.ji-modulo-abrir {
  margin-top: auto;
  padding-top: 6px;
  font-size: 12px;
  color: var(--ji-muted);
  transition: color 0.2s;
}

/* =====================================================================
   RESPONSIVE del rediseño. Se auditó leyendo el código (rejillas de ancho
   fijo, gestos que solo existen con ratón) en vez de esperar a probar en
   un dispositivo — los tres fallos que salieron eran reales.
   ===================================================================== */

/* Analizador de opciones: parámetros | gráfico | Greeks.
   Con 270px + 210px fijos, en un móvil de 375px el gráfico se quedaba sin
   sitio (el mismo fallo que ya apareció en el prototipo). */
.ji-analizador {
  display: grid;
  grid-template-columns: 270px 1fr 210px;
  gap: 20px;
  align-items: start;
  margin-bottom: 20px;
}
/* Tableta: los Greeks bajan a una fila completa y el gráfico recupera ancho. */
@media (max-width: 1100px) {
  .ji-analizador {
    grid-template-columns: 250px 1fr;
  }
  .ji-analizador > :last-child {
    grid-column: 1 / -1;
    flex-direction: row;
    flex-wrap: wrap;
  }
  .ji-analizador > :last-child > * {
    flex: 1;
    min-width: 210px;
  }
}
/* Móvil: todo apilado. */
@media (max-width: 720px) {
  .ji-analizador {
    grid-template-columns: 1fr;
  }
}

/* Filas de la Lista de la Watchlist: 400px de columnas mínimas no caben en
   un móvil, así que la tabla se desplaza dentro de su caja en vez de romper
   la página. */
.wl-lista-scroll {
  overflow-x: auto;
}
.wl-lista-scroll > * {
  min-width: 520px;
}

/* =====================================================================
   PROSA del rediseño: tutorial y glosario. Ancho de lectura acotado —
   estirar un párrafo a 1120px hace ilegible cualquier texto.
   ===================================================================== */
.ji-prosa {
  max-width: 46rem;
}
.ji-prosa p {
  font-family: var(--ji-ui);
  font-size: 15px;
  line-height: 1.7;
  color: var(--ji-text);
  margin: 0 0 0.9rem;
}
.ji-prosa p:last-child {
  margin-bottom: 0;
}
.ji-prosa ul {
  margin: 0 0 0.9rem;
  padding-left: 1.2rem;
  font-family: var(--ji-ui);
  font-size: 15px;
  line-height: 1.7;
  color: var(--ji-text);
}
.ji-prosa li {
  margin-bottom: 0.4rem;
}
.ji-prosa strong {
  color: var(--ji-text);
  font-weight: 600;
}

/* Glosario: término y definición. */
.ji-glosario {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.ji-glosario dt {
  font-family: var(--ji-ui);
  font-weight: 600;
  font-size: 14px;
  color: var(--ji-gold);
  margin-bottom: 3px;
}
.ji-glosario dd {
  margin: 0;
  font-family: var(--ji-ui);
  font-size: 14px;
  line-height: 1.65;
  color: var(--ji-text);
}

/* =====================================================================
   ANALIZADOR DE OPCIONES — disposición de ancho completo (28-ago-2026)
   Antes eran tres columnas y la gráfica se quedaba con un tercio del ancho.
   Petición de Javi, y el argumento es el bueno: la gráfica es lo que se
   mira, y era lo más pequeño de la pantalla.
   ===================================================================== */

/* Barras horizontales de controles, encima de la gráfica. */
/* DOS COLUMNAS: un cuarto para los controles, tres cuartos para la gráfica.
   Propuesta de Javi, primero a 1/3 y luego ajustada a 1/4 al verlo. En barras
   de ancho completo, un campo de strike medía 230 px para escribir tres cifras
   y la curva no cabía sin bajar la página.

   El suelo baja a 180 px porque el campo ya sabe encogerse: por debajo de
   210 px de columna, la etiqueta se pone ENCIMA del control en vez de al lado
   (ver la consulta de contenedor más abajo). Sin eso, 1/6 no cabía. */
.op-cols {
  display: grid;
  grid-template-columns: minmax(180px, 1fr) 5fr;
  gap: 16px;
  align-items: start;
  margin-bottom: 16px;
}
/* La columna de controles se queda clavada: cambias un número y ves el efecto
   sin moverte. `--alto-barra` es lo que mide la barra de módulos (`.bm`), que
   ya está pegada arriba: 58 px, o 100 cuando va en dos filas (15-sep-2026). */
.op-lateral {
  position: sticky;
  top: var(--alto-barra, 58px);
  display: flex;
  flex-direction: column;
  gap: 12px;
  /* Si los controles crecen más que la ventana, que hagan su propio scroll en
     vez de tapar la gráfica. */
  max-height: calc(100vh - var(--alto-barra, 58px) - 16px);
  overflow-y: auto;
}
.op-principal {
  min-width: 0; /* sin esto, el lienzo impide que la columna se encoja */
}
@media (max-width: 1000px) {
  .op-cols {
    grid-template-columns: 1fr;
  }
  .op-lateral {
    position: static;
    max-height: none;
    overflow: visible;
  }
}

.op-barra {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px 14px;
  /* Consulta de CONTENEDOR y no de ventana: lo que decide si el campo cabe en
     una línea es el ancho de ESTA columna, no el del monitor. Con una consulta
     de ventana habría que adivinar la correspondencia entre las dos, y se
     rompería en cuanto cambiara la proporción — que es justo lo que ha pasado
     tres veces hoy. */
  container-type: inline-size;
  background: var(--ji-surface);
  border: 1px solid var(--ji-border);
  border-radius: 12px;
}

/* Los campos, uno por línea dentro de la columna: la etiqueta a la izquierda y
   el control a la derecha, que es como se lee un panel de parámetros. */
.op-barra-campos {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.op-campo-mercado {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.op-campo-control {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

/* Columna estrecha: la etiqueta se pone encima. Es lo que permite bajar a 1/6
   sin que el campo se parta.

   El umbral son 250 px de CONTENEDOR y no menos: «Volatilidad (σ)» mide unos
   105 px y su control otros 110, así que por debajo de eso no caben en la
   misma línea. Se midió, no se estimó — con 210 se salían por la derecha en
   una ventana de 1600. */
@container (max-width: 250px) {
  .op-campo-mercado {
    flex-direction: column;
    align-items: stretch;
    gap: 3px;
  }
  .op-campo-control {
    justify-content: space-between;
  }
  .op-barra-tit {
    min-width: 0;
  }
}
.op-campo-etq {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ji-muted);
  white-space: nowrap;
}
.op-campo-control {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

/* Columna estrecha: la etiqueta se pone encima. Es lo que permite bajar a 1/6
   sin que el campo se parta.

   El umbral son 250 px de CONTENEDOR y no menos: «Volatilidad (σ)» mide unos
   105 px y su control otros 110, así que por debajo de eso no caben en la
   misma línea. Se midió, no se estimó — con 210 se salían por la derecha en
   una ventana de 1600. */
@container (max-width: 250px) {
  .op-campo-mercado {
    flex-direction: column;
    align-items: stretch;
    gap: 3px;
  }
  .op-campo-control {
    justify-content: space-between;
  }
  .op-barra-tit {
    min-width: 0;
  }
}
/* Campo propio en vez del `.op-campo` del analizador clásico: aquel nace sin
   borde ni alto para vivir dentro de una línea de texto, y en una barra con
   botones al lado se descuadraba. */
/* `margin: 0` NO es decorativo: `styles.css` trae de Options World un
   `input { margin-bottom: 1rem }` global. Con `align-items: center`, el
   navegador centra la caja de MARGEN, así que ese rem de más subía el campo
   ocho píxeles y lo dejaba descolocado respecto a los botones +/−. Fue lo que
   Javi vio torcido dos veces. */
.op-campo-num {
  margin: 0;
  /* El ancho lo pone el componente según lo que muestre; aquí solo el suelo,
     para que un campo vacío no se cierre del todo. */
  min-width: 5ch;
  height: 24px;
  padding: 0 6px;
  font-size: 13px;
  line-height: 24px;
  text-align: right;
  color: var(--ji-gold);
  background: var(--ji-inset);
  border: 1px solid var(--ji-border);
  border-radius: 5px;
}
.op-campo-num:focus {
  outline: none;
  border-color: var(--ji-gold);
}
.op-campo-uni {
  font-family: var(--ji-mono);
  font-size: 12px;
  color: var(--ji-muted);
}

/* Patas: DOS POR FILA como mucho, y la tercera baja.
   Petición de Javi: en fila libre, una estrategia de cuatro patas se estiraba
   a lo ancho y la página crecía sin control. Con dos por fila, un iron condor
   ocupa dos filas y se ve entero sin hacer scroll. */
.op-patas {
  display: grid;
  /* Una por fila en la columna estrecha, dos si hay sitio.
     `min(240px, 100%)` y no `240px` a secas: un mínimo fijo mayor que el
     contenedor NO se encoge — la pista se queda en 240 y la tarjeta se sale por
     la derecha. Con `min()`, el mínimo cede cuando la columna es más estrecha
     que él. */
  grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr));
  align-items: start;
  gap: 10px;
  flex: 1;
  /* `minmax(0, 1fr)` y no `1fr` a secas: sin el 0, el contenido impone un
     ancho mínimo y las columnas se desbordan en vez de encogerse. */
}
/* Cabecera de una pata: compra/venta, tipo y el botón de quitar. */
.op-pata-cab {
  display: flex;
  align-items: center;
  gap: 5px;
}
.op-pata-cab select {
  min-width: 0;
}

/* Los tres campos de una pata (strike, prima, cantidad). */
.op-pata-campos {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 5px;
}
.op-pata-campos--accion {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
/* En columna estrecha, tres campos en fila dejan cajas de 40 px donde no cabe
   ni el rótulo. Dos y uno se lee mucho mejor que tres apretados. */
@container (max-width: 250px) {
  .op-pata-campos {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  /* Y el desplegable de tipo se lleva su propia línea: encogido junto al botón
     de compra/venta se quedaba en 34 px, donde no cabe ni «Call». */
  .op-pata-cab {
    flex-wrap: wrap;
  }
  .op-pata-cab select {
    flex: 1 0 100%;
    order: 3;
  }
}

.op-pata {
  display: flex;
  flex-direction: column;
  gap: 5px;
  min-width: 0;
  padding: 8px 10px;
  background: var(--ji-surface-2);
  border: 1px solid var(--ji-border);
  border-radius: 8px;
}
/* Los campos de dentro se reparten el ancho de su tarjeta en vez de tener uno
   fijo: es lo que hace que la pata se autoajuste. */
.op-pata input,
.op-pata select {
  min-width: 0;
  /* Mismo `input { margin-bottom: 1rem }` global: era lo que estiraba las
     tarjetas de pata a lo alto. */
  margin: 0;
}
@media (max-width: 760px) {
  .op-patas {
    grid-template-columns: 1fr;
  }
}
.op-anadir-pata {
  align-self: center;
  font-size: 12px;
  color: var(--ji-muted);
  background: var(--ji-surface);
  border: 1px dashed var(--ji-border);
  border-radius: 8px;
  padding: 7px 12px;
}

/* Paso del tiempo. Aquí el riel SÍ tiene sentido: el rango es real (del
   vencimiento a cero). Es la excepción a haberlos quitado de los campos. */
.op-dte {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 10px;
}
.op-dte-tit {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ji-muted);
  white-space: nowrap;
}
.op-dte-riel {
  flex: 1;
  /* Sin esto el riel no encoge por debajo de su ancho propio (~130 px) y en
     un móvil empujaba «30 DTE» fuera de la pantalla (13-sep-2026). */
  min-width: 0;
  accent-color: var(--ji-gold);
  cursor: pointer;
}
.op-dte-val {
  min-width: 7ch;
  text-align: right;
  font-size: 13px;
  color: var(--ji-gold);
}
.op-dte-hoy {
  font-size: 11px;
  padding: 3px 9px;
  border-radius: 6px;
  color: var(--ji-muted);
  background: var(--ji-surface-2);
  border: 1px solid var(--ji-border);
}

/* La gráfica, grande. El alto de la clásica era 420 y a Javi le parecía mejor
   que los 340 de esta; con el ancho entero, 420 vuelve a cuadrar. */
.op-lienzo {
  display: block;
  width: 100%;
  height: 420px;
  cursor: crosshair;
}
/* Con la variante ancha, 420 px de alto sobre 1700 de ancho dan una franja muy
   aplastada: la curva pierde relieve. Se sube el alto con el ancho. */
@media (min-width: 1500px) {
  .op-lienzo {
    height: 500px;
  }
}
@media (max-width: 700px) {
  .op-lienzo {
    height: 300px;
  }
  .op-barra {
    flex-direction: column;
    gap: 10px;
  }
}

/* Resumen: una sola tarjeta con rejilla de cifras.
   Antes eran dos tarjetas de altura distinta y medio vacías — el `align-items:
   start` de la rejilla vieja hacía que cada una midiera lo que quisiera, y con
   dos cifras en una y una lista corta en la otra, el descuadre era evidente. */
.op-resumen {
  padding: 16px 18px;
  margin-bottom: 16px;
}
.op-resumen-rejilla {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 18px 26px;
  margin-top: 12px;
}
.op-cifra {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}
.op-cifra-etq {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--ji-muted);
}
.op-cifra-val {
  font-family: var(--ji-mono);
  font-variant-numeric: tabular-nums;
  font-size: 20px;
  line-height: 1.15;
  color: var(--ji-text);
  overflow-wrap: anywhere;
}
.op-cifra-nota {
  font-size: 11px;
  line-height: 1.4;
  color: var(--ji-muted);
}

/* Perfil de Greeks: tarjetas más anchas, que a 240px la curva era una raya. */
.op-greeks-rejilla {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 14px;
}
.op-greeks-eje {
  display: flex;
  justify-content: space-between;
  margin-top: 4px;
  font-family: var(--ji-mono);
  font-size: 11px;
  color: var(--ji-muted);
}

/* Explicación de la estrategia, traída del motor congelado. «Qué es» siempre a
   la vista; el resto desplegable, que quien viene a calcular no viene a leer. */
.op-explica {
  padding: 14px 18px;
  margin-bottom: 12px;
  background: var(--ji-surface);
  border: 1px solid var(--ji-border);
  border-left: 2px solid var(--ji-gold);
  border-radius: 12px;
}
.op-explica-que {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--ji-text);
}
.op-explica details {
  margin-top: 8px;
}
.op-explica summary {
  cursor: pointer;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ji-gold);
  list-style: none;
}
.op-explica summary::-webkit-details-marker {
  display: none;
}
.op-explica summary::before {
  content: '▸ ';
}
.op-explica details[open] summary::before {
  content: '▾ ';
}
.op-explica details p {
  margin: 10px 0 0;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--ji-muted);
}
.op-explica details p strong {
  color: var(--ji-text);
}

/* Desglose de Greeks por pata. Solo aparece con más de una: en una posición de
   una sola pata el desglose ES el total. */
.op-porpata {
  margin-top: 12px;
  border-top: 1px solid var(--ji-border);
  padding-top: 10px;
}
.op-porpata summary {
  cursor: pointer;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ji-muted);
}
.op-porpata table {
  width: 100%;
  margin-top: 8px;
  border-collapse: collapse;
  font-family: var(--ji-mono);
  font-size: 11px;
}
.op-porpata th {
  font-weight: 400;
  color: var(--ji-muted);
  text-align: right;
  padding-bottom: 4px;
}
.op-porpata td {
  text-align: right;
  padding: 3px 0;
  color: var(--ji-text);
}
.op-porpata td:first-child,
.op-porpata th:first-child {
  text-align: left;
  color: var(--ji-gold);
}

/* Descargar la gráfica. Discreta: es para Javi, no para el suscriptor. */
/* --- Cabecera de la tarjeta de la gráfica -------------------------------
   Sin título es una fila normal: leyendas a la izquierda y controles empujados
   a la derecha. */
.op-cab {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 12px;
}
.op-leyendas {
  display: flex;
  align-items: center;
  gap: 16px;
  min-width: 0;
}

/* Con título —o sea en pantalla completa— pasa a TRES COLUMNAS.

   Y esto no es un capricho de maquetación: centrar el título con `margin:
   auto` dentro del flex lo centraría en el HUECO QUE SOBRA entre las leyendas y
   los botones, no en la tarjeta — y como las leyendas son más anchas que los
   botones, el título saldría escorado a la derecha sin que se sepa por qué.
   Con `1fr auto 1fr` los dos lados miden lo mismo por construcción y el centro
   es el centro de verdad.

   La otra salida era posición absoluta al 50 %, pero entonces el título puede
   montarse encima de las leyendas en una ventana estrecha. En rejilla no puede:
   se empujan. */
.op-cab--pc {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
}
.op-cab--pc .op-acciones {
  /* En rejilla el empujón lo da la celda, no el margen. */
  margin-left: 0;
  justify-self: end;
}

/* El nombre de la estrategia, centrado y con la MISMA clase que el `<h1>` de
   la página: así «la misma tipografía» es literal y no una copia que se
   desincroniza el día que se toque la otra. Aquí solo se decide el tamaño y
   que no lo encoja la rejilla. */
.op-titulo-pc {
  margin: 0;
  font-size: 24px;
  text-align: center;
  white-space: nowrap;
}

/* --- Descarga de la gráfica como imagen --------------------------------
   Los controles de la esquina, agrupados. El `margin-left: auto` vivía antes
   en el botón que tocara según cuáles estuvieran puestos, con un condicional
   en línea que había que recolocar cada vez que aparecía un control nuevo.
   Declarado una vez en el grupo, deja de ser un problema. */
.op-acciones {
  margin-left: auto;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex-shrink: 0;
}
/* En un móvil, los botones del gráfico bajan de línea en vez de salirse de la
   pantalla con «Ampliar» (13-sep-2026). Su fila también. */
@media (max-width: 520px) {
  .op-cab {
    flex-wrap: wrap;
    gap: 8px 16px;
  }
  .op-acciones {
    flex-shrink: 1;
    flex-wrap: wrap;
  }
  .op-acciones,
  .op-acciones * {
    min-width: 0;
  }
}
/* El icono, con la misma piel que «Ampliar» para que se lean como pareja. */
.op-descarga {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 4px 8px;
  line-height: 0;
}
.op-descarga.on {
  color: var(--ji-gold);
  border-color: color-mix(in srgb, var(--ji-gold) 45%, transparent);
  background: color-mix(in srgb, var(--ji-gold) 12%, transparent);
}
/* El nombre del botón para quien no ve el icono. Fuera de pantalla pero NO con
   `display: none`, que lo sacaría también del árbol de accesibilidad y dejaría
   el botón sin nombre. */
.ji-solo-lectores {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* La capa que cierra al pinchar fuera. Transparente a propósito: no oscurece
   la gráfica, que es justo lo que se está mirando para decidir qué descargar. */
.op-captura-fuera {
  position: absolute;
  inset: 0;
  z-index: 9;
}
.op-captura-panel {
  position: absolute;
  top: 46px;
  right: 16px;
  z-index: 10;
  width: 268px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 14px;
  background: var(--ji-surface-2);
  border: 1px solid var(--ji-border-strong, var(--ji-border));
  border-radius: var(--ji-radio-sm);
  box-shadow: var(--ji-sombra);
}
.op-captura-tit {
  margin: 0;
  font-family: var(--ji-ui);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ji-muted);
}
.op-captura-tit + .op-captura-casilla {
  margin-top: 2px;
}
.op-captura-casilla {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-family: var(--ji-ui);
  font-size: 12px;
  color: var(--ji-text);
  cursor: pointer;
}
.op-captura-casilla input {
  accent-color: var(--ji-gold-solid);
  margin: 0;
  flex-shrink: 0;
}
.op-captura-pista {
  font-size: 11px;
  color: var(--ji-muted);
}
.op-captura-formatos {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
}
.op-captura-formato {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 6px 8px;
  font-family: var(--ji-ui);
  font-size: 12px;
  color: var(--ji-muted);
  background: var(--ji-surface);
  border: 1px solid var(--ji-border);
  border-radius: 7px;
  cursor: pointer;
}
.op-captura-formato.on {
  color: var(--ji-text);
  border-color: color-mix(in srgb, var(--ji-gold) 55%, transparent);
  background: color-mix(in srgb, var(--ji-gold) 10%, transparent);
}
.op-captura-baja {
  margin-top: 4px;
  padding: 8px;
  font-family: var(--ji-ui);
  font-size: 13px;
  font-weight: 600;
  color: #0d1119;
  background: var(--ji-gold-solid);
  border: 1px solid var(--ji-gold-solid);
  border-radius: 8px;
  cursor: pointer;
}
.op-captura-otras {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
}
.op-captura-otras .wl-btn {
  font-size: 11px;
  padding: 6px 8px;
  border-radius: 7px;
  border: 1px solid var(--ji-border);
  background: var(--ji-surface);
  color: var(--ji-muted);
}
.op-captura-nota {
  margin: 2px 0 0;
  font-family: var(--ji-ui);
  font-size: 11px;
  line-height: 1.4;
  color: var(--ji-muted);
}

/* El contrato del que se ha llegado desde la Cartera: solo el identificador.
   Ticker, strike, tipo, sentido con su cantidad y vencimiento.

   Sin insignias y sin colores de estado. Llegó a tener una pastilla verde/roja
   en el tipo, y engañaba —pintaba de color una CATEGORÍA, así que una call
   vendida salía en verde como si fuera buena— y después una en el sentido, que
   Javi también cortó: la dirección ya la dice el nombre de la estrategia justo
   encima, y repetirla en color solo añade ruido. El dato se queda, el color no.

   El ticker en oro porque es el ancla de lectura; el resto, blanco. */
.op-contrato {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 12px;
  margin: 10px 0 0;
  font-family: var(--ji-mono);
  font-variant-numeric: tabular-nums;
  font-size: 24px;
  line-height: 1.15;
  color: var(--ji-text);
}
.op-contrato-tk {
  color: var(--ji-gold);
  letter-spacing: -0.01em;
}
/* Sentido y vencimiento, un punto por debajo: son el contexto del contrato, no
   su nombre. */
.op-contrato-sentido,
.op-contrato-venc {
  font-size: 15px;
  color: var(--ji-muted);
  letter-spacing: 0.04em;
}
@media (max-width: 620px) {
  .op-contrato {
    font-size: 19px;
    gap: 9px;
  }
  .op-contrato-sentido,
  .op-contrato-venc {
    font-size: 13px;
  }
}

/* Botones de paso de los campos de mercado. Un paso no impone un techo, así que
   conviven con la regla de no poner rieles a valores sin límite. */
.op-paso {
  width: 20px;
  height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--ji-mono);
  font-size: 13px;
  line-height: 1;
  color: var(--ji-muted);
  background: var(--ji-surface-2);
  border: 1px solid var(--ji-border);
  border-radius: 5px;
  cursor: pointer;
  transition: color 0.12s, border-color 0.12s;
}
.op-paso:hover {
  color: var(--ji-gold);
  border-color: color-mix(in srgb, var(--ji-gold) 45%, transparent);
}

/* Banda de Greeks bajo la gráfica. Están aquí y no en la fila de abajo porque
   cambian mientras miras la curva, y allí quedaban fuera de la vista. */
.op-griegas {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 20px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--ji-border);
}
.op-griegas-tit {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ji-muted);
  margin-right: 4px;
}
.op-griega {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
}
.op-griega-s {
  font-family: var(--ji-serif);
  font-style: italic;
  font-size: 15px;
  color: var(--ji-gold);
}
/* 17 y no 14: la queja de Javi sobre los números pequeños vale para toda la
   pantalla, y estas cinco cifras son de las que más se miran. */
.op-griega-v {
  font-family: var(--ji-mono);
  font-variant-numeric: tabular-nums;
  font-size: 17px;
  color: var(--ji-text);
}
.op-griega-s {
  font-size: 17px;
}

/* Cabecera del mapa de calor: la lectura de la celda ocupa el hueco que
   quedaba vacío a la derecha del título, y con cifras de tamaño legible. */
/* El hueco de la nota del valor temporal: alto fijo, con nota o sin ella, para
   que la barra de zoom y el mapa no suban y bajen una línea cada vez que se
   señala una casilla sin valor temporal. */
.op-hm-nota-hueco {
  min-height: 18px;
  margin: -6px 0 6px;
}

/*
   REJILLA Y NO `flex` CON `wrap`.

   Con `space-between` + `flex-wrap`, el bloque de cifras cambiaba de lado solo:
   cuando crecía —al aparecer la nota de «ya no queda valor temporal»— dejaba de
   caber, envolvía y caía a la IZQUIERDA, arrastrando el ancho del mapa. Javi lo
   cazó con captura.

   Dos columnas fijas lo clavan a la derecha pase lo que pase, y la nota se ha
   sacado fuera de la cabecera para que no pueda empujar a nadie.
*/
.op-hm-cab {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: end;
  gap: 24px;
  margin-bottom: 14px;
}
/* Por debajo de esto las dos columnas no caben y sí conviene apilar: entonces
   la lectura va debajo del título, no a su izquierda. */
@media (max-width: 860px) {
  .op-hm-cab {
    grid-template-columns: minmax(0, 1fr);
  }
}
/* Alto fijo: sin él, la lectura aparece y desaparece con el ratón y el mapa
   entero da un salto cada vez. */
.op-hm-lectura {
  display: flex;
  align-items: flex-end;
  justify-content: flex-end;
  gap: 28px;
  min-height: 44px;
  flex-shrink: 0;
}
.op-hm-dato {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.op-hm-etq {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--ji-muted);
}
.op-hm-val {
  font-family: var(--ji-mono);
  font-variant-numeric: tabular-nums;
  font-size: 22px;
  line-height: 1;
  color: var(--ji-text);
}
.op-hm-pyg {
  color: var(--ji-gain);
}
.op-hm-pyg.baja {
  color: var(--ji-loss);
}
/* Desglose de las cifras del resumen: de dónde sale cada número, pata por pata.
   Plegado por defecto — es material de estudio, no de vistazo, y desplegado
   siempre empujaría hacia abajo la gráfica, que es lo que se viene a ver. */
.op-desglose {
  margin-top: 16px;
  border-top: 1px solid var(--ji-border);
  padding-top: 12px;
}
.op-desglose > summary {
  cursor: pointer;
  font-size: 12px;
  color: var(--ji-muted);
  letter-spacing: 0.02em;
}
.op-desglose > summary:hover {
  color: var(--ji-text);
}
.op-desglose-cuerpo {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 18px 28px;
  margin-top: 14px;
}
.op-desglose-tit {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  color: var(--ji-gold);
  margin: 0 0 5px;
}
.op-desglose-nota {
  font-size: 11px;
  line-height: 1.4;
  color: var(--ji-muted);
  margin: 0 0 6px;
}
.op-desglose-filas {
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 12px;
}
.op-desglose-filas li {
  display: flex;
  justify-content: space-between;
  gap: 14px;
  padding: 2px 0;
  color: var(--ji-text);
}
.op-desglose-filas li > span:last-child {
  font-family: var(--ji-mono);
  font-variant-numeric: tabular-nums;
  color: var(--ji-gain);
}
.op-desglose-filas li > span:last-child.baja {
  color: var(--ji-loss);
}
.op-desglose-filas li.total {
  border-top: 1px solid var(--ji-border);
  margin-top: 4px;
  padding-top: 5px;
}

/* Aviso de precio inventado, dentro de la barra de Mercado. Ámbar y no rojo:
   no es un error, es un dato que falta y que el usuario puede poner. */
.op-aviso-spot {
  font-size: 11px;
  line-height: 1.4;
  color: var(--ji-muted);
  border-left: 2px solid var(--ji-gold);
  padding-left: 9px;
  margin: 10px 0 0;
}
.op-aviso-spot strong {
  color: var(--ji-gold);
  font-weight: 600;
}
.op-hm-tiempo {
  color: var(--ji-muted);
}
/* La explicación del cero, al lado y en pequeño: es una nota, no un dato.
   `max-width` en caracteres para que no se estire a todo el ancho del panel. */
/* UNA SOLA LÍNEA, SIEMPRE. El hueco de arriba tiene alto fijo para que el mapa
   no salte, y eso solo se sostiene si la nota no envuelve: con el `max-width:
   34ch` que tenía, el texto —aun acortado— caía a tres líneas y desbordaba el
   hueco, que es el problema que se venía a arreglar.

   Si la ventana es tan estrecha que no cabe, se recorta con puntos suspensivos
   y el texto entero queda en el `title`. Prefiero eso a que el mapa se mueva. */
.op-hm-nota {
  font-size: 11px;
  line-height: 1.35;
  color: var(--ji-muted);
  margin: 0;
  max-width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
@media (max-width: 700px) {
  .op-hm-val {
    font-size: 17px;
  }
  .op-hm-lectura {
    gap: 18px;
  }
}

/* Mapa de calor con ejes: DTE a la izquierda, precio arriba.
   Rejilla de dos por dos — esquina, eje X, eje Y y mapa— para que las
   etiquetas queden pegadas a lo que rotulan sin cálculos a mano. */
.op-hm {
  /* Alto de fila del mapa. En variable porque el NÚMERO de filas se fija con un
     estilo en línea (depende de los datos) y un estilo en línea gana a
     cualquier regla de aquí; la variable sí se puede redefinir desde CSS. */
  --hm-fila: 20px;
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto 1fr;
  gap: 4px 8px;
  align-items: stretch;
}
.op-hm-esquina {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ji-muted);
  align-self: end;
  text-align: right;
}
/* Eje de precios. Las etiquetas van en posición ABSOLUTA sobre el ancho del
   mapa: así caen justo en el centro de su columna aunque solo se rotule una de
   cada cuatro. Repartirlas en una rejilla propia las descuadraría. */
.op-hm-ejex {
  position: relative;
  height: 14px;
}
.op-hm-ejex span {
  position: absolute;
  transform: translateX(-50%);
  font-family: var(--ji-mono);
  font-size: 11px;
  color: var(--ji-muted);
  white-space: nowrap;
}
/* Eje de días: misma rejilla de filas que el mapa, así cada número queda a la
   altura exacta de su franja. */
.op-hm-ejey {
  display: grid;
  justify-items: end;
  padding-right: 2px;
}
.op-hm-ejey span {
  font-family: var(--ji-mono);
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  line-height: var(--hm-fila);
  color: var(--ji-muted);
}
.op-hm-mapa {
  display: grid;
  gap: 1.5px;
  border: 1px solid var(--ji-border);
  border-radius: 8px;
  overflow: hidden;
  min-width: 0;
}
.op-hm-pie {
  margin: 6px 0 0;
  text-align: center;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ji-muted);
}

/* Zoom del mapa de calor: rango de precio y de días. */
.op-hm-zoom {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 14px;
  margin-bottom: 12px;
}
.op-hm-zoom-tit {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ji-muted);
}

/* --- Pantalla completa de la gráfica y de las pestañas ------------------ */
.op-ampliable {
  position: relative;
}
/* En línea dentro de su cabecera, NO flotando: en posición absoluta se montaba
   encima de la última pestaña y del botón del cono. */
.op-pc {
  flex-shrink: 0;
  align-self: center;
  font-size: 11px;
  padding: 4px 10px;
  border-radius: 7px;
  color: var(--ji-muted);
  background: var(--ji-surface-2);
  border: 1px solid var(--ji-border);
  cursor: pointer;
}
.op-pc:hover {
  color: var(--ji-gold);
  border-color: color-mix(in srgb, var(--ji-gold) 45%, transparent);
}
/* El navegador pinta el fondo de un elemento a pantalla completa en NEGRO por
   defecto; sin esto, una tarjeta con fondo semitransparente se ve sobre negro
   y los tokens del tema dejan de cuadrar. */
.op-ampliable:fullscreen {
  background: var(--ji-bg);
  padding: 28px 36px;
  overflow: auto;
  border-radius: 0;
}
/* En pantalla completa, la gráfica se come el alto disponible: es lo que se ha
   pedido al ampliar. Se descuentan la leyenda, la barra de días y la banda de
   Greeks. */
.op-ampliable:fullscreen .op-lienzo {
  height: calc(100vh - 260px);
}
/* Y las filas del mapa crecen. Van por variable porque el número de filas se
   fija con un estilo en línea, que gana a cualquier regla de aquí. */
.op-ampliable:fullscreen .op-hm {
  --hm-fila: 30px;
}

/* Los SVG de Greeks y Taylor llevan el alto en CSS y no en el atributo, para
   que puedan crecer en pantalla completa. Con `preserveAspectRatio="none"` el
   trazo se estira a la caja, así que basta con cambiar la altura. */
.op-greek-svg {
  display: block;
  height: 130px;
}
.op-taylor-svg {
  display: block;
  height: 260px;
}
/* Ampliar es para ver MÁS, no lo mismo más grande: en pantalla completa las
   dos vistas se comen el alto disponible en vez de dejar dos tercios en negro.
   Los descuentos son lo que ocupan cabecera, rótulos y controles. */
/* Dos columnas y no cuatro: con `preserveAspectRatio="none"` el trazo se estira
   a la caja, y cuatro tarjetas estrechas y muy altas convertirían la campana de
   gamma en una aguja. En 2×2 cada tarjeta es ancha y el estiramiento vertical y
   el horizontal quedan parecidos, así que la forma se respeta. */
.op-ampliable:fullscreen .op-greeks-rejilla {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
/* Restan la barra ademas de su propio hueco: sin el termino nuevo, el SVG
   medía el viewport entero y la barra lo empujaba fuera por abajo. */
.op-ampliable:fullscreen .op-greek-svg {
  height: calc((100vh - 420px - var(--op-mando-alto)) / 2);
  min-height: 150px;
}
.op-ampliable:fullscreen .op-taylor-svg {
  height: calc(100vh - 330px - var(--op-mando-alto));
  min-height: 200px;
}

/* --- Mando de la vista ampliada ----------------------------------------
   Una barra a lo ANCHO, pegada al fondo de la pantalla completa, con
   estrategia, mercado y patas. Solo existe dentro de `:fullscreen`, porque
   fuera de ella esos mismos controles ya están en `.op-lateral`.

   PRIMERO FUE UN CARRIL A LA IZQUIERDA Y ESTABA MAL. Javi, con captura:
   *«no queda bien, corta toda la gráfica por el lateral»*. Y tenía razón por
   partida doble:

     1. Robaba 356 px de ANCHO a una gráfica cuyo eje es el precio del
        subyacente. Estrechar ese eje es estrechar justo lo que se ha ampliado
        para ver mejor.
     2. Al ser `position: fixed` no participaba en el reparto del espacio, así
        que la tarjeta seguía midiendo el viewport entero y el `padding-left`
        la empujaba fuera por la derecha. Se perdían el botón de salir y el
        rótulo de DTE.

   Abajo no pasa ninguna de las dos cosas: la gráfica conserva TODO el ancho,
   que es su dimensión cara, y cede alto, que es la barata. Y la barra entra en
   el flujo como una fila más de la columna flex, así que el reparto lo hace el
   navegador y no un `padding` calculado a mano.

   EL ALTO ES LA VARIABLE Y NO EL ANCHO. `--op-mando-alto` lo fija de una vez
   para las dos vistas ampliables; el lienzo se come lo que queda con `flex: 1`
   —tiene un `ResizeObserver` que repinta al cambiar de tamaño, así que crecer
   no le cuesta nada— y los SVG del mapa y de Greeks, que van con `calc` de
   `100vh`, restan la misma variable. Un número en un sitio. */
.op-ampliable:fullscreen {
  --op-mando-alto: clamp(160px, 26vh, 264px);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* ── LO QUE NO CABE, SE DESPLAZA ──────────────────────────────────────────
 *
 * Javi, con cuatro capturas: *«todos se cortan por abajo»*. Y era exacto — la
 * tarjeta es `overflow: hidden` (lo necesita, para que las esquinas redondeadas
 * recorten) y su cuerpo no tenía forma de desplazarse, así que todo lo que
 * pasaba del alto del viewport desaparecía. La tabla de P&L, que son 17 filas,
 * es el caso evidente; pero también se comía la BARRA DE MANDOS, que es un
 * hermano más abajo en la columna: si el cuerpo mide de más, la barra queda
 * fuera del recorte y ni se ve ni se puede usar.
 *
 * `min-height: 0` es la parte que no se ve venir: un elemento flexible se niega
 * por defecto a encogerse por debajo de su contenido, así que sin esto
 * `overflow: auto` no llega a activarse nunca — el cuerpo sigue midiendo lo que
 * pide y el recorte sigue igual.
 *
 * La barra de mandos y la fila de pestañas se quedan fijas (`flex: none`), que
 * es justo lo que se quiere: se desplaza el contenido, no los controles.
 */
.op-ampliable:fullscreen .op-pest-tabs {
  flex: none;
}
.op-ampliable:fullscreen .op-pest-cuerpo {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  /* Que el contenido no quede pegado al canto de la barra de abajo. */
  padding-bottom: 8px;
}
/* ── El tirador que pliega el mando ─────────────────────────────────────
 *
 * Pedido por Javi: *«un botón para ocultar el selector de estrategias, mercado
 * y patas, para que se pueda ver el mapa de calor al completo. En el centro de
 * esa tabla, con una flecha hacia abajo, y al tocarlo que baje y se convierta
 * en una flecha hacia arriba»*.
 *
 * Va montado a caballo del canto superior de la barra (`top: -14px`), que es
 * donde se agarra un cajón. Cuando la barra está plegada el tirador sigue ahí:
 * si desapareciera con ella, no habría forma de volver a abrirla.
 */
.op-mando-tirador {
  position: absolute;
  top: -14px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 26px;
  padding: 0;
  border: 1px solid var(--ji-border-strong);
  border-radius: 999px;
  background: var(--ji-surface-2);
  color: var(--ji-muted);
  cursor: pointer;
  transition: color 0.16s, border-color 0.16s;
}
.op-mando-tirador:hover {
  color: var(--ji-gold);
  border-color: color-mix(in srgb, var(--ji-gold) 45%, transparent);
}
.op-mando-tirador svg {
  transition: transform 0.22s;
}
.op-mando.oculto .op-mando-tirador svg {
  transform: rotate(180deg);
}
/* Plegada: `overflow: hidden` para que el contenido no asome mientras encoge. */
.op-mando.oculto {
  max-height: 0;
  padding-top: 0;
  padding-bottom: 0;
  overflow: hidden;
  border-top-color: transparent;
}
/*
   EL TIRADOR, CUANDO LA BARRA ESTÁ PLEGADA.
   ---------------------------------------------------------------------
   Aquí arriba ponía que el tirador «sigue ahí» al plegar. NO ERA VERDAD, y Javi
   lo cazó: *«no puedo regresarlo hacia arriba, el botón desaparece
   totalmente»*. El `overflow: hidden` de la regla de al lado recorta el
   contenido de la barra, y el tirador va montado por FUERA de su canto
   (`top: -14px`), así que lo recortaba también.

   `position: fixed` lo saca del recorte: un descendiente fijo no lo clipa un
   ancestro con `overflow` mientras ese ancestro no cree bloque contenedor —y
   `.op-mando` no lleva `transform` ni `filter`—. Dentro de `:fullscreen` el
   viewport ES la tarjeta, así que queda pegado al borde de abajo de la pantalla
   ampliada, que es donde se busca.

   Y NO SE QUEDA VISIBLE. Podría, y sería más simple. Pero esta vista existe
   para grabar el vídeo de la landing, así que un botón permanente estropea
   justo aquello para lo que se pliega la barra: asoma al bajar el ratón y se va
   al subirlo.
*/
.op-mando.oculto .op-mando-tirador {
  position: fixed;
  top: auto;
  bottom: 10px;
  opacity: 0;
  /* Invisible Y sin capturar clics: si no, se come pulsaciones sobre la
     gráfica en una franja donde no se ve nada. */
  pointer-events: none;
  transition: opacity 0.18s;
}
.op-mando.oculto .op-mando-tirador.asomado,
/* Con el teclado también se llega: si solo asomara con el ratón, quien navegue
   tabulando no podría volver a abrir la barra nunca. */
.op-mando.oculto .op-mando-tirador:focus-visible {
  opacity: 1;
  pointer-events: auto;
}
/* SIN RATÓN NO HAY ASOMO POSIBLE. En táctil no existe el «acercarse», así que
   ahí se queda visible siempre: mejor un botón de más que una barra que no se
   puede volver a abrir. */
@media (hover: none) {
  .op-mando.oculto .op-mando-tirador {
    opacity: 1;
    pointer-events: auto;
  }
}
/*
   Y EL HUECO QUE RESERVAN LOS DEMÁS TAMBIÉN SE ENCOGE.
   `--op-mando-alto` es lo que restan los `calc` del mapa y de Greeks; si no se
   bajara, plegar la barra dejaría un agujero negro de su tamaño en vez de dar
   el sitio al gráfico, que es justo para lo que se pliega.
*/
.op-ampliable:fullscreen:has(.op-mando.oculto) {
  --op-mando-alto: 26px;
}

.op-mando {
  /* Ancla del tirador, que va en posición absoluta sobre su canto. */
  position: relative;
  /* `flex: none` para que la barra NO se encoja cuando el lienzo pide sitio:
     sin esto, un flex-item con contenido se comprime y las patas se cortan. */
  flex: none;
  /*
   * TECHO Y NO ALTURA FIJA. Con `height` la barra media lo mismo para una long
   * call de una pata que para una iron condor de cuatro, y en el primer caso
   * eran 264 px de vacio robados al lienzo.
   *
   * Con `max-height` la barra mide lo que pide su contenido y solo topa en el
   * limite; el lienzo, que va con `flex: 1`, se queda con la diferencia. Y los
   * `calc` del mapa y de Greeks restan el techo, o sea el peor caso: como
   * mucho dejan un hueco, nunca desbordan.
   *
   * El numero sale de medir el marcado real: una pata mide 133 px de alto y
   * 246 de ancho, asi que las CUATRO de una iron condor caben en una sola fila
   * a partir de 1.100 px de ancho, y el bloque entero pide 242 px con el boton
   * de anadir. Redondeado a 264 para que quepa sin scroll.
   */
  max-height: var(--op-mando-alto);
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--ji-border);
  /* Tres bloques a lo ancho, con las patas llevándose la parte del león: son
     lo único que crece con la estrategia (una iron condor trae cuatro). */
  display: grid;
  grid-template-columns: minmax(180px, 0.8fr) minmax(270px, 1.15fr) minmax(360px, 2.6fr);
  gap: 16px;
  align-items: stretch;
}
/* Cada bloque hace SU scroll, no la barra entera: si la barra desbordase, un
   solo scroll movería también la estrategia y el mercado, que siempre caben. */
.op-mando > .op-barra {
  min-height: 0;
  overflow-y: auto;
}
/* --- Selector de estrategia: lista abierta, nunca desplegable -----------
   Un `<select>` pegado al borde inferior de la pantalla abre su menú HACIA
   ARRIBA, encima del payoff, y eso no lo mueve ningún CSS porque el menú lo
   pinta el sistema operativo fuera del documento. Como la vista ampliada es la
   que se va a grabar para la landing, tapar la gráfica al cambiar de
   estrategia era justo lo que no podía pasar.

   Una lista ya abierta no tapa nada porque no se despliega. Cuesta sitio, pero
   sitio EN LA BARRA, que es lo que sobra. */
.op-mando-estrategia {
  min-height: 0;
}
.op-mando-cab {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.op-mando-pasos {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.op-mando-cuenta {
  font-size: 11px;
  color: var(--ji-muted);
  min-width: 5ch;
  text-align: center;
}
.op-mando-propia {
  margin: 0;
  font-family: var(--ji-mono);
  font-size: 11px;
  color: var(--ji-gold);
}
/* `position: relative` NO es decorativo: el auto-desplazado usa el `offsetTop`
   de la fila activa, que se mide contra el ancestro posicionado más cercano.
   Sin esto se mediría contra otro y la lista saltaría a un sitio cualquiera. */
.op-mando-lista {
  position: relative;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 6px;
  /* Sitio para la barra de scroll, que si no se come el final de los nombres. */
  padding-right: 4px;
}
.op-mando-familia {
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.op-mando-familia-tit {
  font-family: var(--ji-ui);
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ji-muted);
  opacity: 0.7;
  padding: 4px 0 2px;
  /* Pegado arriba: con 31 filas y nueve familias, al desplazar se pierde de
     vista de qué familia es lo que estás mirando. */
  position: sticky;
  top: 0;
  background: var(--ji-surface);
}
.op-mando-fila {
  text-align: left;
  font-family: var(--ji-ui);
  font-size: 12px;
  line-height: 1.25;
  color: var(--ji-muted);
  background: none;
  border: 1px solid transparent;
  border-radius: 6px;
  padding: 4px 8px;
  cursor: pointer;
}
.op-mando-fila:hover {
  color: var(--ji-text);
  background: var(--ji-surface-2);
}
.op-mando-fila.on {
  color: #0d1119;
  background: var(--ji-gold-solid);
  border-color: var(--ji-gold-solid);
  font-weight: 600;
}
.op-mando-fila:focus-visible {
  outline: 2px solid var(--ji-gold);
  outline-offset: 1px;
}
/* Los cuatro campos de mercado se quedan APILADOS, como en la columna lateral.
   Los puse en dos columnas para gastar menos alto y salía mal: con el bloque
   en 306 px, cada celda quedaba en 130 px y la etiqueta se comía al control
   —medido: «VOLATILIDAD» encima del «− 30 % +»—. Apilados tienen 278 px cada
   uno, el mismo ancho con el que ya funcionan, y las cuatro filas caben. */

/* El lienzo se queda con lo que sobre. Sustituye al `calc(100vh - 260px)` que
   había: con una barra de alto variable debajo, restar un número fijo dejaba
   un hueco o se comía la barra. */
.op-ampliable:fullscreen .op-lienzo {
  flex: 1 1 0;
  height: auto;
  min-height: 180px;
}

/* Bajo 1000 px las tres columnas no caben —suman 810 px de mínimos más los
   huecos— así que la barra pasa a una sola columna con scroll. Va DESPUÉS y
   con la misma especificidad: una consulta de medios no gana por serlo. */
@media (max-width: 1000px) {
  .op-mando {
    grid-template-columns: minmax(0, 1fr);
    height: auto;
    max-height: 40vh;
    overflow-y: auto;
  }
  .op-mando > .op-barra {
    overflow-y: visible;
  }
}

/* El contrato, como enlace al analizador. Enlace de verdad y no un `onClick`:
   así el clic central y el menú del botón derecho hacen lo que se espera. */
.go-analizar {
  font-family: var(--ji-mono);
  font-weight: 500;
  color: var(--ji-gold);
  text-decoration: none;
  border-bottom: 1px dashed color-mix(in srgb, var(--ji-gold) 40%, transparent);
}
.go-analizar:hover {
  border-bottom-color: var(--ji-gold);
}
.go-analizar span {
  font-size: 11px;
  opacity: 0.7;
}

/* Bautizar una estrategia que no está en el catálogo. */
.op-bautizo {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  padding: 10px 14px;
  margin-bottom: 12px;
  background: var(--ji-surface);
  border: 1px dashed var(--ji-border-strong);
  border-radius: 10px;
}
.op-bautizo-nota {
  font-size: 12px;
  color: var(--ji-muted);
}

/* --- Trades guardados --------------------------------------------------
   Misma barra que el bautizo, con borde CONTINUO en vez de discontinuo: el
   discontinuo del bautizo dice «esto es un hueco por rellenar, ponle nombre»,
   y este bloque está siempre y no pide nada. Que se distingan de un vistazo
   importa, porque están uno encima del otro y hacen cosas parecidas con
   nombres parecidos. */
.op-trades {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  padding: 10px 14px;
  margin-bottom: 12px;
  background: var(--ji-surface);
  border: 1px solid var(--ji-border);
  border-radius: 10px;
}
.op-trades-sel {
  font-family: var(--ji-ui);
  font-size: 12px;
  padding: 5px 8px;
  max-width: 15rem;
  color: var(--ji-text);
  background: var(--ji-inset);
  border: 1px solid var(--ji-border);
  border-radius: 7px;
  cursor: pointer;
}
.op-trades-sel:hover {
  border-color: var(--ji-border-strong);
}
/* El aviso de un trade corrupto se lee como aviso, no como pie de foto. */
.op-trades .op-bautizo-nota {
  margin-left: auto;
}
.op-bautizo-campo {
  flex: 1;
  min-width: 180px;
  max-width: 320px;
  height: 28px;
  padding: 0 9px;
  margin: 0;
  font-size: 13px;
  color: var(--ji-text);
  background: var(--ji-inset);
  border: 1px solid var(--ji-border);
  border-radius: 6px;
}
.op-bautizo-campo:focus {
  outline: none;
  border-color: var(--ji-gold);
}

/* Los días del mapa de calor, en deslizador. Un contrato a 476 días no se puede
   explorar con botones de 7/30/90: los tres miran el primer quinto. */
.op-hm-dias {
  display: flex;
  align-items: center;
  gap: 10px;
  flex: 1;
  min-width: 200px;
}
.op-hm-dias-val {
  min-width: 6ch;
  text-align: right;
  font-size: 13px;
  color: var(--ji-gold);
}

/* =====================================================================
   EDITOR DE LA WATCHLIST (30-ago-2026)
   Antes era un solo `.fila-formulario` con catorce campos en flex-wrap:
   se colocaban donde cupieran, las etiquetas de dos líneas descuadraban
   la fila entera y los dos textos largos se quedaban fuera del flujo con
   el ancho por defecto del navegador. De ahí las cajitas flotantes.
   Ahora es una rejilla de cuatro columnas por GRUPOS con sentido, y cada
   campo declara cuánto ocupa.
   ===================================================================== */
.wl-editor {
  display: grid;
  gap: 26px;
}

/* El título de cada grupo. Pequeño y en versalitas: separa sin gritar. */
.wl-editor-grupo > h3 {
  grid-column: 1 / -1;
  margin: 0;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ji-muted);
}
/* Los dos bloques de estudio SÍ llevan color: son la parte editorial. */
.wl-editor-grupo--estudio > h3 {
  color: var(--ji-gold);
  letter-spacing: 0.04em;
  font-size: 12px;
}
.wl-editor-grupo--estudio {
  padding-top: 20px;
  border-top: 1px solid var(--ji-border);
}

.wl-editor-grupo {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px 16px;
}
/*
 * Cada campo son TRES bandas —etiqueta, caja, pista— y con `subgrid` las
 * comparte con sus vecinos de fila. Sin esto, un campo con pista debajo
 * empuja su caja hacia arriba y se descuadra respecto al de al lado; y una
 * etiqueta de dos líneas hace lo mismo al revés.
 *
 * Donde no haya `subgrid`, la declaración se ignora y queda el apilado
 * normal: se pierde la alineación fina, no la maqueta.
 */
.wl-editor-grupo > label {
  display: grid;
  grid-template-rows: subgrid;
  grid-row: span 3;
  align-content: start;
  row-gap: 6px;
  min-width: 0;
  margin-bottom: 0;
  font-size: 12px;
  color: var(--ji-muted);
}
/* Sin `margin-bottom`: aquí el aire lo pone el `gap` de la rejilla. */
.wl-editor-grupo input,
.wl-editor-grupo select,
.wl-editor-grupo textarea {
  width: 100%;
  box-sizing: border-box;
  margin-bottom: 0;
  font-size: 14px;
  font-family: inherit;
}
/* Anula el ancho fijo de 6rem que traen los numéricos del formulario viejo. */
.wl-editor-grupo input[type='number'] {
  width: 100%;
}
.wl-editor-grupo textarea {
  resize: vertical;
  line-height: 1.55;
  padding: 0.6rem 0.7rem;
  background: var(--fondo);
  border: 1px solid var(--borde);
  border-radius: 8px;
  color: var(--texto);
}

.wl-editor-2 {
  grid-column: span 2;
}
/* Tres de las cuatro: para el campo que acompaña a una fecha estrecha. */
.wl-editor-3 {
  grid-column: span 3;
}
.wl-editor-todo {
  grid-column: 1 / -1;
}

/* ── Los enlaces de la tesis ─────────────────────────────────────────────
   Una lista de filas, cada una con tipo, dirección, fecha y sus botones, y
   debajo el título. El título va aparte y a lo ancho porque es el campo más
   largo y en la misma fila dejaba a la dirección en un hilo. */
.wl-enlaces {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.wl-enlaces-tit {
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-family: var(--ji-ui);
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ji-muted);
}

.wl-enlaces-tit .pista {
  text-transform: none;
  letter-spacing: 0;
}

.wl-enlaces-lista {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.wl-enlace {
  display: flex;
  flex-direction: column;
  gap: 5px;
  padding: 9px 10px;
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio-sm);
  background: var(--ji-surface);
}

/* La que no se va a pintar en la ficha se marca aquí, no al guardar: es donde
   se puede arreglar sin tener que buscar cuál de las cinco era. */
.wl-enlace.roto {
  border-color: color-mix(in srgb, var(--ji-loss) 45%, transparent);
}

.wl-enlace-fila {
  display: grid;
  /* La dirección se queda con lo que sobra; lo demás tiene ancho propio. */
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  gap: 8px;
  align-items: center;
}

.wl-enlace-botones {
  display: flex;
  gap: 4px;
}

.wl-enlace-botones button {
  padding: 3px 8px;
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio-sm);
  background: transparent;
  color: var(--ji-text);
  cursor: pointer;
}

.wl-enlace-botones button:disabled {
  opacity: 0.35;
  cursor: default;
}

.wl-enlace-quitar:not(:disabled):hover {
  color: var(--ji-loss);
  border-color: color-mix(in srgb, var(--ji-loss) 45%, transparent);
}

.wl-enlace-aviso {
  margin: 0;
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--ji-loss);
}

/* ── La criba entera, por bloques plegables (21-sep-2026) ───────────────── */

.criba-volver {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 18px;
  padding: 8px 14px;
  border: 1px solid var(--ji-border-strong);
  border-radius: 10px;
  background: var(--ji-surface);
  color: var(--ji-text);
  font: inherit;
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
}

.criba-volver:hover {
  background: var(--ji-surface-2);
}

/* El del pie no lleva caja: ahi ya no se busca, se sale. */
.criba-volver--pie {
  margin: 22px 0 0;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ji-gold);
}

.criba-volver--pie:hover {
  background: none;
  text-decoration: underline;
}

.criba-cuenta {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin: 18px 0;
}

.criba-cuenta > div {
  flex-grow: 1;
  min-width: 150px;
  padding: 14px 18px;
  border: 1px solid var(--ji-border);
  border-radius: 12px;
  background: var(--ji-surface);
}

.criba-cuenta strong {
  display: block;
  font-size: 25px;
  line-height: 1.2;
}

.criba-cuenta span {
  font-size: 12.5px;
  color: var(--ji-muted);
}

.criba-arriba {
  margin-bottom: 14px;
  padding: 18px 22px;
  border: 1px solid var(--ji-border);
  border-radius: 14px;
  background: var(--ji-surface);
}

.criba-arriba h3 {
  margin: 0 0 8px;
  display: flex;
  align-items: baseline;
  gap: 11px;
  flex-wrap: wrap;
}

.criba-arriba p {
  margin: 0;
  line-height: 1.6;
  color: var(--ji-text);
}

.criba-arq {
  padding: 4px 11px;
  border: 1px solid rgba(224, 178, 77, 0.3);
  border-radius: 999px;
  background: rgba(224, 178, 77, 0.12);
  color: var(--ji-gold);
  font-size: 12.5px;
  font-weight: 600;
}

.criba-bloque {
  margin-bottom: 10px;
  border: 1px solid var(--ji-border);
  border-radius: 14px;
  background: var(--ji-surface);
}

.criba-bloque > summary {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 22px;
  list-style: none;
  cursor: pointer;
}

.criba-bloque > summary::-webkit-details-marker {
  display: none;
}

.criba-bloque-tit {
  font-family: var(--ji-serif);
  font-size: 18px;
  font-weight: 600;
}

.criba-bloque-n {
  font-size: 12.5px;
  color: var(--ji-muted);
}

.criba-bloque-que {
  margin: 0 22px 14px;
  padding-top: 14px;
  border-top: 1px solid var(--ji-border);
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--ji-muted);
}

.criba-bloque .criba-lista {
  margin: 0 22px 18px;
}

.criba-flecha {
  color: var(--ji-muted);
  transition: transform 140ms ease;
}

.criba-bloque[open] > summary .criba-flecha {
  transform: rotate(90deg);
}

@media (prefers-reduced-motion: reduce) {
  .criba-flecha {
    transition: none;
  }
}

/* La criba resumida dentro de «La empresa» (21-sep-2026). */
.emp-proceso {
  margin-bottom: 16px;
}

.emp-proceso-cab {
  display: flex;
  align-items: baseline;
  gap: 14px;
  margin-bottom: 10px;
}

.emp-proceso-cab h3 {
  margin: 0;
}

/* Un boton que se lee como enlace: cambia de pestaña, no navega fuera. */
.emp-a-criba {
  margin-left: auto;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ji-gold);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}

.emp-a-criba:hover {
  text-decoration: underline;
}

/* «· comprada» al lado del veredicto. Gris y pequeño a proposito: el veredicto
   es lo que Javi decide y esto solo es el hecho de que la posicion existe. */
.est-tenida {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  color: var(--ji-muted);
  font-size: 12px;
}

.est-tenida svg {
  color: var(--ji-gain);
}

/* El conmutador «Enlace / Nota» del estudio inicial (0083). */
.wl-radar-cab {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 6px;
}

.wl-conmutador {
  display: inline-flex;
  gap: 3px;
  padding: 3px;
  border: 1px solid var(--ji-border-strong);
  border-radius: 9px;
  background: var(--ji-inset);
}

.wl-conmutador button {
  padding: 5px 11px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--ji-muted);
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  cursor: pointer;
}

.wl-conmutador button[aria-pressed='true'] {
  background: var(--ji-gold);
  color: #17130a;
}

/* La nota que explica por qué no hay informe. No es un error: es una respuesta,
   así que ni roja ni con aire de aviso. */
.wl-sin-informe {
  margin: 0;
  padding: 10px 13px;
  border: 1px dashed var(--ji-border-strong);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.03);
  color: var(--ji-muted);
  font-size: 12.5px;
  font-style: italic;
  line-height: 1.55;
}

.wl-enlaces-anadir {
  display: flex;
  gap: 8px;
}

/* Las partes de la tesis en el bloque de «Estudio profundo»: en fila mientras
   quepan y en varias líneas cuando no, que HITI tiene tres. */
.wl-estudio-enlaces {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
}

@media (max-width: 720px) {
  /* En estrecho, cada control a su línea: cuatro en fila dejan la dirección
     en dos centímetros y no se puede ni leer lo que se escribe. */
  .wl-enlace-fila {
    grid-template-columns: 1fr;
  }
}

/* Una pista bajo el campo, para lo que no cabe en la etiqueta. */
.wl-editor-pista {
  font-size: 11px;
  line-height: 1.45;
  color: var(--ji-muted);
  opacity: 0.75;
}

/* Los obligatorios de «reevaluar» se marcan: la base los exige. */
.wl-editor-grupo--exige {
  padding: 14px 16px;
  border-radius: 10px;
  background: color-mix(in srgb, var(--ji-gold) 5%, transparent);
  border: 1px solid color-mix(in srgb, var(--ji-gold) 22%, transparent);
}

@media (max-width: 900px) {
  .wl-editor-grupo {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 560px) {
  .wl-editor-grupo {
    grid-template-columns: minmax(0, 1fr);
  }
  .wl-editor-2,
  .wl-editor-3 {
    grid-column: auto;
  }
}

/*
 * 16 px en móvil, por lo mismo que en `.ji-campo`: Safari de iOS amplía la
 * página al enfocar un campo de menos de 16 px y deja al usuario con la
 * pantalla ampliada. Aquí solo entra el admin, pero el admin también corrige
 * una ficha desde el sofá — y la regla no distingue quién teclea.
 */
@media (max-width: 768px) {
  .wl-editor-grupo input,
  .wl-editor-grupo select,
  .wl-editor-grupo textarea {
    font-size: 16px;
  }
}

/* --- Editor por fases: lo que aún no toca, y el veredicto derivado ----- */

/* La línea que explica qué pestaña falta y por qué. Va pegada a la barra. */
.wl-editor-guia {
  margin: -8px 0 18px;
}

/*
 * EL VEREDICTO NO ES UN CAMPO, y tiene que verse que no lo es. Antes era un
 * desplegable; ahora sale de la convicción de la criba, así que se pinta como
 * un dato —etiqueta, valor, de dónde viene— y no como algo que se rellena.
 */
.wl-veredicto {
  display: grid;
  row-gap: 4px;
  align-content: start;
  padding: 12px 14px;
  border-radius: 10px;
  background: color-mix(in srgb, var(--ji-gold) 4%, transparent);
  border: 1px solid var(--ji-border);
}
.wl-veredicto-etq {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ji-muted);
}
.wl-veredicto-val {
  font-size: 18px;
  font-weight: 600;
  color: var(--ji-text);
}
/* Cada salida con el color de su fase, el mismo que usa el embudo público. */
.wl-veredicto-val.fase-descartada {
  color: var(--ji-loss);
}
.wl-veredicto-val.fase-vigilancia {
  color: var(--ji-gold);
}
.wl-veredicto-val.fase-pendiente-tesis {
  color: var(--ji-gain);
}
.wl-veredicto-val.fase-sin-estudiar {
  color: var(--ji-muted);
}

/* --- Sectores y temas: fichas con aspa, no un campo con comas ---------- */
.wl-sectores {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.wl-sectores li {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 6px 5px 12px;
  border-radius: 999px;
  border: 1px solid var(--ji-border);
  background: color-mix(in srgb, var(--ji-gold) 6%, transparent);
  font-size: 13px;
  color: var(--ji-text);
}
/* El aspa: área de pulsación de sobra, sin que la ficha crezca. */
.wl-sectores li button {
  width: 20px;
  height: 20px;
  padding: 0;
  display: grid;
  place-items: center;
  border: none;
  border-radius: 50%;
  background: none;
  color: var(--ji-muted);
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}
.wl-sectores li button:hover {
  background: color-mix(in srgb, var(--ji-loss) 20%, transparent);
  color: var(--ji-text);
}
/* El campo y su botón, en la misma banda de la rejilla. Ver el JSX. */
.wl-sectores-add {
  display: flex;
  gap: 8px;
  align-items: stretch;
  min-width: 0;
}
.wl-sectores-add input {
  flex: 1;
  min-width: 0;
}
.wl-sectores-add button {
  margin: 0;
  white-space: nowrap;
}

/* =====================================================================
   ESTADOS FINANCIEROS (ficha) — tabla por ejercicio fiscal (31-ago-2026)
   ===================================================================== */
.ef-bloque {
  margin-top: 1.4rem;
}
.ef-bloque h3 {
  font-size: 0.95rem;
  margin-bottom: 0.5rem;
  color: var(--ji-gold);
}
/* Scrollea la tabla, nunca el cuerpo: con cinco columnas en móvil, si no, se
   desborda la página entera y no hay forma de volver. */
.ef-scroll {
  overflow-x: auto;
}
.ef-tabla {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.85rem;
}
.ef-tabla th,
.ef-tabla td {
  padding: 0.4rem 0.6rem;
  white-space: nowrap;
  border-bottom: 1px solid var(--borde);
}
.ef-tabla thead th {
  font-weight: 600;
  color: var(--apagado);
  border-bottom-width: 2px;
}
/* El concepto va a la izquierda y las cifras a la derecha, que es como se lee
   una columna de números: por la unidad, no por la primera cifra. */
.ef-tabla th[scope='row'] {
  text-align: left;
  font-weight: 400;
  color: var(--texto);
  /* Lo único que no encoge: el nombre de la línea, siempre visible. */
  position: sticky;
  left: 0;
  background: var(--fondo);
}
.ef-tabla td,
.ef-tabla thead th:not(:first-child) {
  text-align: right;
  font-variant-numeric: tabular-nums;
}
/* Subtotales (beneficio bruto, total activo…): son los que se buscan primero. */
.ef-tabla .ef-total th[scope='row'],
.ef-tabla .ef-total td {
  font-weight: 600;
  color: var(--texto);
}

/* La fórmula, bajo la definición del término en el glosario. Es dato, no
   adorno: por eso va en monoespaciada y en su propia línea. */
.ji-formula {
  display: block;
  margin-top: 8px;
  padding: 7px 11px;
  border-radius: 8px;
  background: var(--ji-inset);
  border: 1px solid var(--ji-border);
  font-family: var(--ji-mono);
  font-size: 12px;
  line-height: 1.5;
  color: var(--ji-gold);
  /* Una fórmula larga se parte en vez de desbordar la tarjeta. */
  white-space: normal;
  overflow-wrap: anywhere;
}

/* Los dos repartos —tipo y sector— uno al lado del otro. Se apilan cuando no
   caben, que es lo que pasa en cuanto la ventana baja de un portátil. */
/*
 * Uno DEBAJO del otro, no dos columnas (Javi, 31-ago-2026: «que estén una
 * debajo de la otra y a mayor tamaño. Para mi gusto, muy pequeño»).
 *
 * En dos columnas cada donut se quedaba en 168 px y la leyenda en media línea:
 * caben los dos en el ancho, sí, pero no se lee ninguno. Y no son dos vistas de
 * lo mismo que haya que comparar de un vistazo — son dos preguntas distintas,
 * así que apiladas no se pierde nada.
 */
.reparto-doble {
  display: flex;
  flex-direction: column;
  gap: 26px;
}

/* Los dos desplegables de la columna «Tipo y sector»: apilados, porque en una
   fila de tabla no caben dos selects lado a lado sin estrangular el resto. */
.clasificacion-edicion,
.clasificacion-lectura {
  display: flex;
  flex-direction: column;
  gap: 5px;
  align-items: flex-start;
}
/* --- Con qué convicción se entró ---------------------------------------
   La etiqueta que ve el suscriptor. Tres estados y los tres se enseñan: la
   AUSENCIA es información —«todavía no lo he declarado»— y taparla sería
   volver a la cortina que se quitó con la 0044.

   Colores prestados de los semánticos que ya usa el proyecto: el oro para lo
   que tiene trabajo detrás, el azul para el trade declarado, y el apagado para
   lo que falta. Nada de rojo: un trade de momentum declarado no es un error,
   es una decisión contada. */
.clas-entrada {
  align-self: flex-start;
  font-size: 11px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 2px 7px;
  border-radius: 999px;
  border: 1px solid var(--ji-border);
  color: var(--ji-muted);
  cursor: help;
  white-space: nowrap;
}
.clas-entrada.es-tesis {
  color: var(--ji-gold);
  border-color: color-mix(in srgb, var(--ji-gold) 40%, transparent);
}
.clas-entrada.es-momentum {
  color: var(--ji-blue);
  border-color: color-mix(in srgb, var(--ji-blue) 40%, transparent);
}
/* Sin declarar: se ve, pero no grita. Es un hueco, no una alarma. */
.clas-entrada.sin {
  opacity: 0.65;
  border-style: dashed;
}

/* --- El motivo, en el editor ------------------------------------------- */
.clas-motivo {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-top: 2px;
}
/* Ya escrito: se enseña, no se ofrece editar. La base lo sella con un trigger
   y un campo que va a dar error al guardar sería mentir sobre lo que se puede
   hacer. El cursor de ayuda lo dice al pasar por encima. */
.clas-motivo.sellado {
  font-size: 11px;
  line-height: 1.4;
  color: var(--ji-muted);
  max-width: 22rem;
  cursor: help;
  border-left: 2px solid color-mix(in srgb, var(--ji-gold) 35%, transparent);
  padding-left: 8px;
  border-radius: 0;
}
.clas-motivo-campo {
  font-family: var(--ji-ui);
  font-size: 11px;
  padding: 4px 7px;
  width: 20rem;
  max-width: 100%;
  color: var(--ji-text);
  background: var(--ji-inset);
  border: 1px dashed var(--ji-border-strong);
  border-radius: 6px;
}
.clas-motivo-campo::placeholder {
  color: var(--ji-muted);
  opacity: 0.8;
}
.clas-motivo-error {
  font-size: 11px;
  color: var(--ji-loss);
  max-width: 20rem;
}

.clasificacion-edicion select {
  margin-bottom: 0;
  font-size: 0.85rem;
  padding: 0.35rem 0.5rem;
}

/* =====================================================================
   GLOSARIO — cada categoría, un desplegable (31-ago-2026)
   Con 128 términos, una sola lista era un scroll sin fondo.
   ===================================================================== */
.glos-grupo {
  padding: 0;
  overflow: hidden;
}
.glos-grupo > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 15px 22px;
  cursor: pointer;
  /* Fuera el triángulo del navegador: se dibuja uno propio a la izquierda. */
  list-style: none;
  user-select: none;
}
.glos-grupo > summary::-webkit-details-marker {
  display: none;
}
.glos-grupo > summary:hover {
  background: var(--ji-surface-2);
}
.glos-grupo > summary:focus-visible {
  outline: 2px solid var(--ji-gold);
  outline-offset: -2px;
}
/* La flecha, que gira al abrir. */
.glos-grupo > summary::before {
  content: '';
  width: 7px;
  height: 7px;
  flex-shrink: 0;
  border-right: 1.6px solid var(--ji-muted);
  border-bottom: 1.6px solid var(--ji-muted);
  transform: rotate(-45deg);
  transition: transform 0.18s ease;
}
.glos-grupo[open] > summary::before {
  transform: rotate(45deg);
}
@media (prefers-reduced-motion: reduce) {
  .glos-grupo > summary::before {
    transition: none;
  }
}
/* El eyebrow ocupa el hueco para que se pueda pulsar toda la barra. */
.glos-grupo > summary > .ji-eyebrow {
  flex: 1;
  margin: 0;
}
/* Cuántos términos hay dentro: se ve sin abrir. */
.glos-cuenta {
  font-size: 11px;
  color: var(--ji-muted);
  background: var(--ji-inset);
  border: 1px solid var(--ji-border);
  border-radius: 999px;
  padding: 1px 8px;
}
.glos-grupo > .ji-glosario {
  padding: 4px 22px 20px;
  border-top: 1px solid var(--ji-border);
  margin-top: 0;
}

/* Aviso de cifras reexpresadas. En dorado y no en rojo: no es un error, es
   información sobre la empresa — y a veces la más interesante de la tabla. */
/* Ya no es un cartel: desde el 6-sep-2026 es una línea plegada que solo ve el
   admin. Sin caja ni borde dorado — llamaba la atención como si fuera una
   advertencia, y no lo es. */
.ef-reexpresado {
  margin: 12px 0 0;
  font-size: 0.85rem;
}
.ef-reexpresado p {
  margin: 0 0 6px;
}
.ef-reexpresado ul {
  margin: 0;
  padding-left: 18px;
  color: var(--apagado);
  line-height: 1.7;
}
.ef-delta {
  color: var(--ji-gold);
  font-variant-numeric: tabular-nums;
}
.ef-menores {
  margin: 8px 0 0;
  font-size: 0.8rem;
  color: var(--apagado);
  opacity: 0.85;
}

/* =====================================================================
   FICHA DE EMPRESA (ADR-0013) — pestañas y subpestañas
   ===================================================================== */
.emp-pestanas {
  display: flex;
  gap: 2px;
  border-bottom: 1px solid var(--ji-border);
  margin-bottom: 20px;
  /* En móvil se desplazan en horizontal en vez de apilarse: tres pestañas
     apiladas ocupan media pantalla antes de leer nada. */
  overflow-x: auto;
  /* Y en vertical, nada: con `overflow-x: auto` el navegador pone el otro eje
     en auto, y el subrayado de la pestaña activa sobresale un píxel. En
     Windows eso pintaba una barra de desplazamiento con flechas al lado de las
     pestañas (13-sep-2026). */
  overflow-y: hidden;
}
.emp-pestana {
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  border-radius: 0;
  color: var(--ji-muted);
  font-family: var(--ji-ui);
  font-size: 14px;
  font-weight: 500;
  padding: 10px 16px;
  white-space: nowrap;
  cursor: pointer;
  margin-bottom: -1px;
}
.emp-pestana:hover {
  color: var(--ji-text);
}
.emp-pestana.activa {
  color: var(--ji-gold);
  border-bottom-color: var(--ji-gold);
}
.emp-pestana:focus-visible,
.emp-sub:focus-visible {
  outline: 2px solid var(--ji-gold);
  outline-offset: -2px;
}

.emp-subs {
  display: flex;
  gap: 6px;
  flex-wrap: nowrap;
  overflow-x: auto;
  margin-bottom: 18px;
  padding-bottom: 2px;
}
.emp-sub {
  background: transparent;
  border: 1px solid var(--ji-border-strong);
  border-radius: 999px;
  color: var(--ji-muted);
  font-family: var(--ji-ui);
  font-size: 12.5px;
  padding: 5px 13px;
  white-space: nowrap;
  cursor: pointer;
}
.emp-sub.activa {
  color: var(--ji-gold);
  border-color: color-mix(in srgb, var(--ji-gold) 45%, transparent);
  background: color-mix(in srgb, var(--ji-gold) 10%, transparent);
}

/* El recuadro de la tesis: es el destino editorial de la ficha. */
.emp-tesis {
  margin-top: 26px;
  padding: 16px 18px;
  border-radius: 12px;
  border: 1px solid color-mix(in srgb, var(--ji-gold) 24%, transparent);
  background: color-mix(in srgb, var(--ji-gold) 5%, transparent);
}
.emp-tesis h3 {
  margin: 0 0 8px;
  font-size: 14px;
  color: var(--ji-gold);
}
.emp-tesis ul {
  margin: 0;
  padding-left: 18px;
  line-height: 1.9;
}

/* El nombre del ratio con su «?» al lado, sin que se separen al envolver. */
.ratio-nombre {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

/* La celda de la empresa entera es enlace, sin parecer un enlace. */
.celda-empresa {
  display: block;
  color: inherit;
  text-decoration: none;
}
.celda-empresa:hover strong {
  text-decoration: underline;
}

/* =====================================================================
   LA TABLA VIVA — fila que se ilumina, partida pinchable, variación
   (31-ago-2026)
   ===================================================================== */
.ef-tabla--viva tbody tr:hover {
  background: var(--ji-surface-2);
}
/* La celda del concepto es sticky y tiene fondo propio: sin esto, al iluminar
   la fila se quedaría con el suyo y parecería un trozo despegado. */
.ef-tabla--viva tbody tr:hover th[scope='row'] {
  background: var(--ji-surface-2);
}
.ef-partida {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
/* La partida es un botón, pero tiene que leerse como el texto que era. */
.ef-abrir {
  background: none;
  border: none;
  padding: 0;
  border-radius: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  cursor: pointer;
  border-bottom: 1px dashed transparent;
}
.ef-abrir:hover {
  color: var(--ji-gold);
  border-bottom-color: color-mix(in srgb, var(--ji-gold) 55%, transparent);
}
.ef-abrir:focus-visible {
  outline: 2px solid var(--ji-gold);
  outline-offset: 2px;
}
.ef-valor {
  display: block;
}
/* La variación, debajo y pequeña: acompaña a la cifra, no compite con ella. */
.ef-delta-fila {
  display: block;
  font-size: 0.72rem;
  line-height: 1.3;
  opacity: 0.8;
}
.ef-sube {
  color: var(--ji-gain);
}
.ef-baja {
  color: var(--ji-loss);
}

/* =====================================================================
   LA GRÁFICA DE UNA PARTIDA
   ===================================================================== */
.gp-fondo {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.62);
  z-index: 1300;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
  overflow-y: auto;
}
.gp-caja {
  background: var(--ji-bg);
  border: 1px solid var(--ji-border-strong);
  border-radius: 16px;
  box-shadow: var(--ji-sombra);
  padding: 22px 24px 20px;
  /* Más ancha que antes: con veinte trimestres, 760 px obligaban a recorrer
     la gráfica desde el primer momento. */
  width: min(1080px, 100%);
  max-height: 92vh;
  overflow-y: auto;
}
.gp-caja:focus {
  outline: none;
}
.gp-cab {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 14px;
}
.gp-cab h2 {
  font-family: var(--ji-serif);
  font-size: 22px;
  font-weight: 400;
  margin: 0;
}
.gp-sub {
  margin: 5px 0 0;
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ji-muted);
}
.gp-cerrar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 1px solid var(--ji-border-strong);
  border-radius: 8px;
  color: var(--ji-muted);
  font-size: 19px;
  line-height: 1;
  width: 32px;
  height: 30px;
  padding: 0;
  flex-shrink: 0;
  cursor: pointer;
}
.gp-cerrar:hover {
  color: var(--ji-text);
}

.gp-controles {
  display: flex;
  gap: 6px;
  margin-bottom: 14px;
}
.gp-controles button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--ji-border-strong);
  border-radius: 8px;
  color: var(--ji-muted);
  width: 32px;
  height: 30px;
  padding: 0;
  cursor: pointer;
}
.gp-controles button:hover {
  color: var(--ji-text);
  border-color: var(--ji-muted);
}
.gp-controles button[aria-pressed='true'] {
  color: var(--ji-gold);
  border-color: color-mix(in srgb, var(--ji-gold) 55%, transparent);
  background: color-mix(in srgb, var(--ji-gold) 14%, transparent);
}

/* El lienzo va a TAMAÑO REAL y lo que sobra se recorre. Escalarlo al ancho de
   la caja es lo que dejaba el texto en cuatro píxeles con veinte columnas. */
.gp-desplaza {
  position: relative;
  overflow-x: auto;
  padding-bottom: 4px;
}
.gp-svg {
  display: block;
  /* Con pocas columnas el lienzo es más estrecho que la caja y se estira para
     no dejar hueco. SIN `max-width`: con veinte, encogerlo a la caja es
     exactamente el fallo que se estaba arreglando. */
  min-width: 100%;
  height: auto;
}
/* La rejilla es casi invisible a propósito: da una escala que leer sin
   convertir el fondo en papel milimetrado. */
.gp-rejilla {
  stroke: var(--ji-border);
  stroke-width: 1;
}
.gp-cero {
  stroke: var(--ji-border-strong);
  stroke-width: 1;
  stroke-dasharray: 3 3;
}
.gp-eje-linea {
  stroke: var(--ji-border-strong);
  stroke-width: 1;
}
/* El área bajo la línea: da cuerpo sin robar protagonismo a la trayectoria. */
.gp-area {
  fill: color-mix(in srgb, var(--ji-blue) 14%, transparent);
  stroke: none;
}
/* El periodo más reciente va en oro y el resto apagado: la serie se lee de un
   vistazo y el ojo sabe dónde está el presente. */
.gp-barra {
  fill: color-mix(in srgb, var(--ji-blue) 48%, transparent);
}
.gp-barra.gp-ultimo {
  fill: var(--ji-gold);
}
.gp-linea {
  fill: none;
  stroke: var(--ji-blue);
  stroke-width: 2.2;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.gp-punto {
  fill: var(--ji-blue);
  stroke: var(--ji-surface);
  stroke-width: 2;
}
.gp-punto.gp-ultimo {
  fill: var(--ji-gold);
}
.gp-valor {
  fill: var(--ji-muted);
  font-family: var(--ji-mono);
  font-size: 11.5px;
  text-anchor: middle;
}
.gp-valor-ultimo {
  fill: var(--ji-text);
  font-weight: 600;
}
.gp-eje {
  fill: var(--ji-muted);
  font-family: var(--ji-ui);
  font-size: 11px;
  text-anchor: middle;
}
.gp-eje-ultimo {
  fill: var(--ji-text);
  font-weight: 600;
}

.gp-cifras {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 10px;
  margin-top: 18px;
}
.gp-cifra {
  border: 1px solid var(--ji-border);
  border-radius: 10px;
  padding: 11px 13px;
  background: var(--ji-surface);
}
.gp-cifra-tit {
  margin: 0 0 4px;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ji-muted);
}
.gp-cifra-val {
  margin: 0;
  font-family: var(--ji-mono);
  font-size: 17px;
  font-weight: 600;
  color: var(--ji-text);
}
.gp-bien {
  color: var(--ji-gain);
}
.gp-mal {
  color: var(--ji-loss);
}
.gp-cifra-pie {
  margin: 2px 0 0;
  font-size: 11px;
  color: var(--ji-muted);
}
.gp-definicion {
  margin: 18px 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--ji-border);
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--ji-muted);
}

/* El panel que sale al señalar un periodo. HTML sobre el SVG, porque un
   `<text>` no envuelve ni admite fondo redondeado. */
.gp-lienzo {
  position: relative;
}
.gp-panel {
  position: absolute;
  z-index: 2;
  pointer-events: none;
  background: var(--ji-surface-2);
  border: 1px solid var(--ji-border-strong);
  border-radius: 10px;
  padding: 9px 13px;
  box-shadow: 0 10px 28px -14px rgba(0, 0, 0, 0.8);
  white-space: nowrap;
}
.gp-panel-per {
  margin: 0 0 3px;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ji-muted);
}
.gp-panel-val {
  margin: 0;
  font-family: var(--ji-mono);
  font-size: 17px;
  font-weight: 600;
  color: var(--ji-text);
}
.gp-panel-var {
  margin: 3px 0 0;
  font-size: 11.5px;
  font-family: var(--ji-mono);
}
/* La guía vertical del periodo señalado. */
.gp-guia {
  stroke: var(--ji-border-strong);
  stroke-width: 1;
  stroke-dasharray: 4 4;
}
/* Lo señalado se ilumina; el resto se queda como está. */
.gp-barra.gp-sobre {
  fill: color-mix(in srgb, var(--ji-blue) 85%, transparent);
}
.gp-barra.gp-ultimo.gp-sobre {
  fill: color-mix(in srgb, var(--ji-gold) 88%, white 12%);
}
.gp-punto.gp-sobre {
  stroke-width: 2.5;
}

/* Las marcas del eje vertical, a la derecha: el ojo entra por la serie y sale
   por la escala, que es como lo hace un terminal financiero. */
.gp-marca {
  fill: var(--ji-muted);
  font-family: var(--ji-mono);
  font-size: 11px;
  opacity: 0.75;
}

/* La leyenda: qué significa cada color y cuántos periodos se ven. */
.gp-leyenda {
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--ji-border);
  font-size: 11.5px;
  color: var(--ji-muted);
}
.gp-leyenda span {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
.gp-cuadro {
  width: 9px;
  height: 9px;
  border-radius: 2px;
  display: inline-block;
}
.gp-cuadro-serie {
  background: color-mix(in srgb, var(--ji-blue) 70%, transparent);
}
.gp-cuadro-ultimo {
  background: var(--ji-gold);
}
.gp-leyenda-cuenta {
  margin-left: auto;
}
.gp-leyenda-cuenta strong {
  color: var(--ji-text);
}

/* El detalle de las correcciones: solo para el admin, y plegado. */
.ef-detalle-admin > summary {
  cursor: pointer;
  font-size: 0.8rem;
  color: var(--ji-gold);
  margin-top: 6px;
}
.ef-detalle-admin > summary:focus-visible {
  outline: 2px solid var(--ji-gold);
  outline-offset: 2px;
}
.ef-detalle-admin ul {
  margin-top: 8px;
  max-height: 260px;
  overflow-y: auto;
}

/* Anual / trimestral. Encima de las subpestañas porque manda sobre todas: no
   es un filtro de la tabla que se esté viendo, son otros datos. */
.emp-periodicidad {
  display: inline-flex;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--ji-border);
  border-radius: 999px;
  background: var(--ji-inset);
  margin-bottom: 14px;
}
.emp-per {
  background: none;
  border: none;
  border-radius: 999px;
  color: var(--ji-muted);
  font-family: var(--ji-ui);
  font-size: 12.5px;
  padding: 5px 15px;
  cursor: pointer;
}
.emp-per.activa {
  color: var(--ji-bg);
  background: var(--ji-gold-solid);
  font-weight: 600;
}
.emp-per:focus-visible {
  outline: 2px solid var(--ji-gold);
  outline-offset: 2px;
}

/* Cabecera de bloque dentro de una tabla: «Activo corriente», «De la
   explotación». Con treinta filas seguidas hay que saberse de memoria dónde
   acaba el activo y empieza el pasivo. */
.ef-seccion th {
  position: sticky;
  left: 0;
  background: var(--ji-surface-2);
  text-align: left;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ji-muted);
  padding: 9px 10px 8px;
  border-bottom: 1px solid var(--ji-border-strong);
}
.ef-tabla--viva tbody tr.ef-seccion:hover,
.ef-tabla--viva tbody tr.ef-seccion:hover th {
  background: var(--ji-surface-2);
}

/* La tabla se arrastra con el ratón: con veinte trimestres, apuntar a la barra
   de 8 px del fondo es incómodo, y sin rueda horizontal no hay forma. */
.ef-arrastrable {
  cursor: grab;
}
.ef-arrastrable.arrastrando {
  cursor: grabbing;
  /* Sin esto, arrastrar selecciona el texto de las celdas por el camino. */
  user-select: none;
}
/* La barra, visible en vez de escondida: es la pista de que hay más a la
   derecha, y el arrastre es un atajo, no el único camino. */
.ef-arrastrable::-webkit-scrollbar {
  height: 10px;
}
.ef-arrastrable::-webkit-scrollbar-thumb {
  background: var(--ji-border-strong);
  border-radius: 999px;
}
.ef-arrastrable::-webkit-scrollbar-thumb:hover {
  background: var(--ji-muted);
}
.ef-arrastrable::-webkit-scrollbar-track {
  background: transparent;
}

/* =====================================================================
   HISTORIAL DE VEREDICTOS — cómo cambió de opinión, y cuándo
   El embudo enseña dónde está hoy; esto, el camino. Es lo que no se puede
   fabricar después.
   ===================================================================== */
.hv {
  margin-top: 26px;
  padding-top: 20px;
  border-top: 1px solid var(--ji-border);
}
.hv-linea {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.hv-linea li {
  display: flex;
  gap: 14px;
  position: relative;
}
/* El hilo que une los puntos: hace que se lea como una secuencia y no como
   una lista de sucesos sueltos. */
.hv-linea li:not(:last-child)::before {
  content: '';
  position: absolute;
  left: 4px;
  top: 16px;
  bottom: -16px;
  width: 1px;
  background: var(--ji-border-strong);
}
.hv-punto {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex-shrink: 0;
  margin-top: 5px;
  position: relative;
  z-index: 1;
}
.hv-cab {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 0 0 2px;
}
.hv-fecha {
  font-size: 11px;
  color: var(--ji-muted);
}
.hv-cual {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ji-muted);
  opacity: 0.75;
}
.hv-cambio {
  margin: 0;
  font-size: 14px;
  color: var(--ji-text);
}
.hv-motivo {
  margin: 5px 0 0;
  font-family: var(--ji-serif);
  font-style: italic;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--ji-muted);
  max-width: 46rem;
}

/* =====================================================================
   REPARTO EN DONUT (Cartera) — idea traída de Portfolio Tracker, dibujado
   a mano en SVG: el proyecto no lleva librería de gráficas.
   ===================================================================== */
.rd {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.rd-cab {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}
.rd-titulo {
  color: var(--ji-muted);
  margin: 0;
}
.rd-pista {
  font-size: 11px;
  color: var(--ji-muted);
  opacity: 0.8;
}
.rd-volver {
  background: none;
  border: none;
  padding: 0;
  color: var(--ji-gold);
  font-family: var(--ji-ui);
  font-size: 12px;
  cursor: pointer;
}
.rd-cuerpo {
  display: flex;
  align-items: center;
  gap: 34px;
  flex-wrap: wrap;
}
.rd-svg {
  width: 260px;
  height: 260px;
  flex-shrink: 0;
}

/*
 * LA ANIMACIÓN DE ENTRADA.
 *
 * El arco es un `<circle>` con el guión recortado a su longitud, y crecer ese
 * guión de cero a su medida es lo único que hace falta: la interpola el
 * navegador, sin una línea de JavaScript por fotograma. El retardo de cada
 * porción lo pone el componente, para que el reparto se dibuje en el sentido
 * de las agujas del reloj — como se lee.
 *
 * `cubic-bezier` que sale rápido y frena al final: así el barrido parece que
 * llega a su sitio en vez de pararse en seco.
 */
.rd-arco {
  transition:
    stroke-dasharray 620ms cubic-bezier(0.22, 0.61, 0.36, 1),
    opacity 220ms ease;
}
.rd-abrible {
  cursor: pointer;
}
.rd-abrible:hover {
  opacity: 0.85;
}
/* Al abrir una categoría, el resto se apaga en vez de desaparecer: así se
   sigue viendo cuánto pesaba dentro del total. */
.rd-apagado {
  opacity: 0.2;
}
.rd-centro-tit {
  fill: var(--ji-muted);
  font-family: var(--ji-ui);
  font-size: 12px;
  text-anchor: middle;
}
.rd-centro-val {
  fill: var(--ji-text);
  font-family: var(--ji-mono);
  font-size: 19px;
  font-weight: 600;
  text-anchor: middle;
}

.rd-lista {
  flex: 1;
  min-width: 260px;
  /* Con tope de ancho: sin él la columna del nombre se estiraba y dejaba treinta
     caracteres de vacío entre la etiqueta y su cifra, que es justo lo que hace
     que una leyenda deje de leerse de un vistazo. */
  max-width: 440px;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.rd-fila {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  align-items: center;
  gap: 10px;
  padding: 7px 8px;
  border-radius: 8px;
  font-size: 13.5px;
  text-align: left;
  width: 100%;
}
.rd-fila-btn {
  background: none;
  border: none;
  color: inherit;
  font-family: var(--ji-ui);
  cursor: pointer;
  transition: background 0.15s ease;
}
.rd-fila-btn:hover:not(:disabled) {
  background: var(--ji-surface-2);
}
.rd-fila-btn:disabled {
  cursor: default;
}
.rd-fila-btn:focus-visible {
  outline: 2px solid var(--ji-gold);
  outline-offset: -2px;
}
.rd-punto {
  width: 10px;
  height: 10px;
  border-radius: 2px;
  flex-shrink: 0;
}
.rd-nombre {
  color: var(--ji-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* En el desglose, la barra sustituye al punto: la proporción dentro de la
   categoría se lee mejor en longitud que en color. */
.rd-barra {
  height: 6px;
  border-radius: 999px;
  background: var(--ji-inset);
  overflow: hidden;
}
.rd-barra-relleno {
  display: block;
  height: 100%;
  border-radius: 999px;
  /* Crece desde cero como el donut. Animación y no transición: la fila nace
     con la vista de desglose, y una transición necesita un estado previo que
     aquí no existe. `backwards` mantiene el ancho cero durante el retardo. */
  animation: rd-crecer 520ms cubic-bezier(0.22, 0.61, 0.36, 1) backwards;
  transform-origin: left center;
}
@keyframes rd-crecer {
  from {
    transform: scaleX(0);
  }
  to {
    transform: scaleX(1);
  }
}
.rd-valor {
  color: var(--ji-muted);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}
.rd-pct {
  color: var(--ji-text);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  min-width: 52px;
  text-align: right;
}
.rd-aviso {
  font-size: 11.5px;
  margin: 0;
}

/* Quien pide menos movimiento no lo pide a medias: se queda el resultado, sin
   el camino. El donut sale ya dibujado. */
@media (prefers-reduced-motion: reduce) {
  .rd-arco,
  .rd-fila-btn {
    transition: none;
  }
  .rd-barra-relleno {
    animation: none;
  }
}

/* =====================================================================
   VIEJAS GLORIAS (Cartera) — las empresas que Javi tuvo y ya no tiene.
   Idea de un suscriptor; ver `components/ViejasGlorias.tsx`.
   ===================================================================== */
.vg-cab {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 18px;
}
.vg-resumen {
  margin: 0;
  font-size: 12.5px;
}
/* Fichas y no filas de tabla: cada empresa es una historieta con cinco datos,
   y en una tabla de cinco columnas ninguno destaca sobre los demás. */
.vg-lista {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(310px, 1fr));
  gap: 14px;
}
.vg-ficha {
  background: var(--ji-surface);
  border: 1px solid var(--ji-border);
  border-radius: 14px;
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.vg-id {
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
}
.vg-ticker {
  font-family: var(--ji-serif);
  font-size: 17px;
  color: var(--ji-text);
  text-decoration: none;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.vg-ticker:hover {
  color: var(--ji-gold);
}
.vg-sim {
  font-family: var(--ji-mono);
  font-size: 11px;
  color: var(--ji-muted);
  flex-shrink: 0;
}
.vg-cifra {
  display: flex;
  align-items: baseline;
  gap: 10px;
  font-family: var(--ji-mono);
  font-variant-numeric: tabular-nums;
}
.vg-cifra > span:first-child {
  font-size: 19px;
  font-weight: 600;
}
.vg-pct {
  font-size: 13px;
  opacity: 0.85;
}
/* `--ji-gain` y `--ji-loss`, los mismos que el resto de la web usa para ganancia
   y pérdida. Es la única pantalla donde el rojo es información, no alarma. */
.vg-bien {
  color: var(--ji-gain);
}
.vg-mal {
  color: var(--ji-loss);
}
.vg-datos {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 8px 14px;
  margin: 0;
}
.vg-datos dt {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ji-muted);
}
.vg-datos dd {
  margin: 2px 0 0;
  font-size: 13px;
  color: var(--ji-text);
  font-variant-numeric: tabular-nums;
}
.vg-nota {
  margin-top: 20px;
  font-size: 12px;
  max-width: 68ch;
}

/* --- Tira de pestañas de la cartera ------------------------------------ */
.cart-pestanas {
  display: flex;
  gap: 6px;
  background: var(--ji-surface);
  border: 1px solid var(--ji-border);
  border-radius: 12px;
  padding: 5px;
  width: fit-content;
  margin-bottom: 24px;
  /* Que se desplace ESTO y no la página. */
  max-width: 100%;
  overflow-x: auto;
  /* Sin esto los botones se aplastan en vez de salirse, y con cinco pestañas
     los rótulos se parten en dos líneas dentro de la píldora. */
  scrollbar-width: thin;
}
.cart-pestanas .wl-btn {
  flex-shrink: 0;
  white-space: nowrap;
}

/* --- Batallitas (`bt-*`) ------------------------------------------------
   Comparten TODO lo de arriba con Viejas Glorias, a propósito: son pareja y el
   parecido es el mensaje. Solo cambia lo que una operativa de opciones tiene y
   una empresa cerrada no — el nombre de la estrategia y sus patas. */
.bt-acierto {
  font-family: var(--ji-mono);
  font-size: 13px;
  color: var(--ji-muted);
  /* En una línea con un título en serif de 22 px, el mismo peso haría que
     compitieran. Aquí es un apunte, no un segundo titular. */
  font-weight: 400;
}
.bt-estrategia {
  margin-left: auto;
  padding: 2px 8px;
  border: 1px solid var(--ji-border);
  border-radius: 999px;
  font-size: 11px;
  color: var(--ji-muted);
  white-space: nowrap;
  flex-shrink: 0;
}
/* Las patas, en monoespaciada: son `−1 put 16 / +1 put 14`, y con espaciado
   proporcional los signos y los números dejan de alinearse entre fichas. */
.bt-patas {
  margin: 0;
  font-family: var(--ji-mono);
  font-size: 12px;
  color: var(--ji-muted);
  overflow-x: auto;
  white-space: nowrap;
}

/* ── El histórico del rolo ──────────────────────────────────────────────
   Solo sale en las operativas que encadenaron vencimientos. Va debajo de los
   datos de la ficha, separado por una línea, para que se lea como un apéndice
   y no compita con el resultado. */
.bt-historico {
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px solid var(--ji-border);
}

.bt-movs {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.bt-movs li {
  display: grid;
  /* La fecha y la cifra se quedan fijas; las patas absorben lo que sobre y
     se desplazan solas si no caben, que en un rolo de cuatro patas pasa. */
  grid-template-columns: auto 1fr auto;
  gap: 10px;
  align-items: baseline;
  padding: 5px 7px;
  border-radius: 5px;
  font-size: 12px;
}

.bt-movs li.es-rolo {
  background: var(--ji-surface-2, rgba(255, 255, 255, 0.03));
}

.bt-mov-fecha {
  color: var(--ji-muted);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.bt-mov-patas {
  font-family: var(--ji-mono);
  /*
    PARTE DE LÍNEA, no desplaza. El primer intento copió el `nowrap` de
    `.bt-patas`, que está en la cabecera y tiene la ficha entera de ancho; aquí
    la columna es lo que sobra en una tarjeta a dos columnas, y un movimiento de
    rolo —dos patas con sus vencimientos— no cabe. Salía cortado y con barra de
    desplazamiento propia, que además descuadraba la altura de las filas.

    El corte se hace por el « / » que separa las patas, que es justo donde se
    quiere: la que cierra arriba y la que abre debajo.
  */
  color: var(--ji-text);
}

/* Cada pata en su renglón y sin partirse nunca por dentro. */
.bt-pata {
  display: block;
  white-space: nowrap;
}

.bt-etq-rolo {
  margin-left: 7px;
  padding: 1px 5px;
  border-radius: 3px;
  border: 1px solid var(--ji-border);
  font-family: var(--ji-sans, inherit);
  font-size: 10px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ji-muted);
}

.bt-mov-cifra {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
  text-align: right;
}

@media (max-width: 560px) {
  /* En móvil la cifra se va debajo: tres columnas en 375 px dejan las patas
     en un hilo de dos caracteres. */
  .bt-movs li {
    grid-template-columns: auto 1fr;
  }

  .bt-mov-cifra {
    grid-column: 2;
    text-align: left;
  }
}

/* --- Filtro, totales y barras (ampliación pedida por Javi el 31-ago-2026) --- */
.vg-filtros {
  display: flex;
  gap: 4px;
  background: var(--ji-surface);
  border: 1px solid var(--ji-border);
  border-radius: 10px;
  padding: 4px;
}
.vg-filtro {
  background: none;
  border: none;
  border-radius: 7px;
  padding: 6px 13px;
  font-family: var(--ji-ui);
  font-size: 12px;
  color: var(--ji-muted);
  cursor: pointer;
  transition: background 0.15s ease;
}
.vg-filtro:hover {
  background: var(--ji-surface-2);
}
.vg-filtro-on {
  background: var(--ji-surface-2);
  color: var(--ji-text);
  font-weight: 600;
}
.vg-filtro:focus-visible {
  outline: 2px solid var(--ji-gold);
  outline-offset: -2px;
}

.vg-bloque {
  margin-bottom: 24px;
}
.vg-totales {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px;
  margin-bottom: 18px;
}
.vg-total {
  background: var(--ji-surface);
  border: 1px solid var(--ji-border);
  border-radius: 12px;
  padding: 13px 16px;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
/* El neto se distingue del resto: es el único de los tres que responde a
   «entonces, ¿cuánto?». Los otros dos son sus dos mitades. */
.vg-total-neto {
  border-color: var(--ji-border-strong);
  background: var(--ji-surface-2);
}
.vg-total-etq {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ji-muted);
}
.vg-total-cifra {
  font-family: var(--ji-mono);
  font-size: 19px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.vg-total-sub {
  font-size: 11px;
  color: var(--ji-muted);
}

.vg-barras {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-bottom: 4px;
}
.vg-barra-fila {
  display: grid;
  grid-template-columns: 62px 1fr 104px;
  align-items: center;
  gap: 10px;
  font-size: 11.5px;
}
.vg-barra-tk {
  font-family: var(--ji-mono);
  font-size: 11px;
  color: var(--ji-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* El riel entero es la escala, y el cero cae justo en el medio: las ganancias
   crecen a la derecha y las pérdidas a la izquierda desde el mismo punto. */
.vg-barra-riel {
  position: relative;
  height: 15px;
  background: var(--ji-inset);
  border-radius: 4px;
  overflow: hidden;
}
.vg-barra-cero {
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 1px;
  background: var(--ji-border-strong);
}
.vg-barra {
  position: absolute;
  top: 2px;
  bottom: 2px;
  border-radius: 3px;
  min-width: 2px;
}
.vg-barra-bien {
  background: var(--ji-gain);
}
.vg-barra-mal {
  background: var(--ji-loss);
}
.vg-barra-cifra {
  font-family: var(--ji-mono);
  font-size: 11.5px;
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* =====================================================================
   AVISOS DE FICHERO en el motor fiscal.
   Existen porque un extracto mal configurado NO falla: da cero, y un cero
   en silencio parece un resultado. Ver `calc/validarExtracto.ts`.
   ===================================================================== */
.fx-problemas {
  list-style: none;
  margin: 0 0 20px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.fx-problemas li {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 11px 14px;
  border-radius: 10px;
  border: 1px solid var(--ji-border);
  background: var(--ji-surface);
  font-size: 12.5px;
  line-height: 1.5;
}
.fx-problemas b {
  color: var(--ji-text);
  font-weight: 600;
}
.fx-problemas span {
  color: var(--ji-muted);
}
/* Un borde de color y no un fondo: el aviso tiene que leerse, no gritar. */
.fx-error {
  border-left: 3px solid var(--ji-loss);
}
.fx-aviso {
  border-left: 3px solid var(--ji-gold);
}

/* =====================================================================
   NÓMINAS EN LOTE. Se leen varias de una vez y se ENSEÑAN antes de
   guardar: la promesa de la pantalla es «revisa siempre los importes».
   ===================================================================== */
.nm-lote {
  margin-top: 16px;
  padding: 14px 16px;
  border: 1px solid var(--ji-border-strong);
  border-radius: 12px;
  background: var(--ji-inset);
}
.nm-lote-cab {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
}
/* La tabla se desplaza sola en móvil en vez de desbordar la página. */
.nm-lote-tabla {
  overflow-x: auto;
}
.nm-lote-tabla table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12.5px;
}
.nm-lote-tabla th {
  text-align: right;
  font-weight: 500;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ji-muted);
  padding: 0 8px 6px;
  white-space: nowrap;
}
.nm-lote-tabla th:first-child,
.nm-lote-tabla td:first-child {
  text-align: left;
}
.nm-lote-tabla td {
  text-align: right;
  padding: 5px 8px;
  border-top: 1px solid var(--ji-border);
  color: var(--ji-text);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* Una nómina sin mes no se puede guardar: se apaga para que se vea de un
   vistazo cuál es la que hay que meter a mano. */
.nm-sin-mes td {
  color: var(--ji-muted);
  opacity: 0.7;
}
.nm-nota {
  font-size: 11px;
  color: var(--ji-muted);
  text-align: left !important;
  font-variant-numeric: normal;
}

/* Los años que este navegador recuerda, en el motor fiscal. Se enseña por
   AÑOS y no por nombres de fichero: importa qué ejercicios cubre el cálculo. */
.fx-guardados {
  margin-bottom: 20px;
  padding: 10px 14px;
  border-radius: 10px;
  border: 1px solid var(--ji-border);
  background: var(--ji-surface);
}

/* =====================================================================
   GUÍA DEL EXTRACTO (`/fiscal/guia`).
   Tres piezas propias sobre la piel que ya existe: la lista, el recuadro
   de trampa y la caja que hace scrollear la tabla POR DENTRO — en móvil,
   sin eso, es la página entera la que se va de lado.
   ===================================================================== */
.fg-lista {
  margin: 0 0 14px;
  padding-left: 18px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}
.fg-lista li {
  color: var(--ji-muted);
  line-height: 1.6;
}

/* Mismo lenguaje que los avisos del motor (`.fx-aviso`): un filo de color y
   nada de fondo. Una trampa tiene que leerse, no gritar. */
.fg-trampa {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin: 4px 0 14px;
  padding: 11px 14px;
  border: 1px solid var(--ji-border);
  border-left: 3px solid var(--ji-gold);
  border-radius: 10px;
  background: var(--ji-surface);
  font-size: 12.5px;
  line-height: 1.5;
}
.fg-trampa b {
  color: var(--ji-text);
  font-weight: 600;
}
.fg-trampa span {
  color: var(--ji-muted);
}

.fg-tabla-caja {
  overflow-x: auto;
  margin: 4px 0 14px;
}
.fg-tabla-caja .tabla {
  min-width: 460px;
}
.fg-tabla-caja .tabla td:not(:first-child),
.fg-tabla-caja .tabla th:not(:first-child) {
  text-align: left;
}

/* La captura de la pantalla de IBKR. Ancho completo de la tarjeta y con
   borde, porque el panel de IBKR es oscuro y sin filo se funde con el fondo
   en tema oscuro. */
.fg-figura {
  margin: 4px 0 16px;
}
.fg-figura img {
  display: block;
  /* NUNCA se agranda: `width: 100%` estiraba las capturas pequeñas — la del
     menú mide 275 px de ancho y se pintaba a 700, borrosa y gigante. Con
     `auto` + `max-width` cada una sale a su tamaño y solo se encogen las
     grandes. Centrada, porque si no las pequeñas quedan descolgadas. */
  width: auto;
  max-width: 100%;
  height: auto;
  margin: 0 auto;
  border: 1px solid var(--ji-border);
  border-radius: 10px;
  background: var(--ji-inset);
}
.fg-figura figcaption {
  margin-top: 7px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--ji-muted);
}

/* =====================================================================
   NOMINAS: los dos modos (automático y a mano).
   El automático ya existía pero vivía como una línea pequeña dentro del
   formulario de UN mes, o sea invisible. Separarlo en dos es lo que hace
   que se vea que puedes soltar las doce de golpe.
   ===================================================================== */
.nm-cab {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}
.nm-anio {
  min-width: 108px;
  flex: 0 0 auto;
}

.nm-modos {
  display: inline-flex;
  gap: 4px;
  padding: 3px;
  border: 1px solid var(--ji-border);
  border-radius: 999px;
  background: var(--ji-inset);
}
.nm-modo {
  border: 0;
  background: transparent;
  color: var(--ji-muted);
  font: inherit;
  font-size: 12.5px;
  padding: 6px 16px;
  border-radius: 999px;
  cursor: pointer;
  transition: background .15s, color .15s;
}
.nm-modo:hover {
  color: var(--ji-text);
}
.nm-modo.activo {
  background: var(--ji-surface);
  color: var(--ji-text);
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.18);
}
.nm-mes {
  max-width: 200px;
}

/* Aviso de una fila del lote de nóminas: no bloquea, señala dónde mirar. */
.nm-nota .nm-alerta {
  display: block;
  color: var(--ji-gold);
}
.nm-nota span + span {
  margin-top: 2px;
}

/* Los supuestos de la cuota estimada: pegados a la cifra, no en el pie.
   Una estimacion que depende de dos selectores sin tocar tiene que decirlo
   donde se lee el numero. */
/* UN SOLO contenedor manda el ancho de los dos textos. Antes cada uno
   llevaba su `max-width: 58ch`, y como el `ch` depende del tamaño de letra
   — el recuadro es más pequeño que el párrafo — salían de anchos distintos y
   el recuadro quedaba apretado. Nada de números mágicos: se mide una vez. */
.nm-textos {
  max-width: 58ch;
  font-size: 0.9rem;
}

.nm-supuestos {
  margin: 10px 0 0;
  padding: 9px 12px;
  border-left: 2px solid var(--ji-gold);
  border-radius: 0 8px 8px 0;
  background: var(--ji-inset);
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--ji-muted);
}
.nm-supuestos strong { color: var(--ji-text); }

/* La captura, pinchable. El botón no debe verse como botón: es la imagen. */
.fg-lupa {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
  border-radius: 10px;
}
.fg-lupa:focus-visible {
  outline: 2px solid var(--ji-gold);
  outline-offset: 3px;
}

/* Visor a pantalla completa. Sin animaciones: es una capa que aparece. */
.fg-visor {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgb(0 0 0 / 0.86);
  cursor: zoom-out;
}
.fg-visor img {
  /* Al revés que la miniatura: aquí SÍ se agranda, que es a lo que se viene.
     La caja ocupa la pantalla y `contain` escala la imagen dentro sin
     deformarla — sube las pequeñas y encoge las anchas. */
  width: 95vw;
  height: 90vh;
  object-fit: contain;
  border-radius: 8px;
  cursor: default;
}
.fg-visor-cerrar {
  position: absolute;
  top: 12px;
  right: 16px;
  width: 40px;
  height: 40px;
  border: 1px solid rgb(255 255 255 / 0.25);
  border-radius: 999px;
  background: rgb(0 0 0 / 0.4);
  color: #fff;
  font-size: 24px;
  line-height: 1;
  cursor: pointer;
}
.fg-visor-cerrar:hover {
  background: rgb(0 0 0 / 0.7);
}

/* =====================================================================
   EL CARTEL DE BETA del motor fiscal.
   Antes vivía en una línea de 12,5 px debajo de la zona de subida, o sea
   que para leerlo había que haber bajado ya. Un aviso que hay que buscar
   no es un aviso.
   ===================================================================== */
.fx-beta {
  margin-bottom: 16px;
  padding: 16px 18px;
  border: 1px solid var(--ji-border);
  border-left: 3px solid var(--ji-gold);
  border-radius: 12px;
  background: color-mix(in srgb, var(--ji-gold) 5%, var(--ji-surface));
}
.fx-beta-titulo {
  margin: 0 0 6px;
  font-family: var(--ji-ui);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ji-gold);
}
.fx-beta p:not(.fx-beta-titulo) {
  margin: 0 0 8px;
  font-family: var(--ji-ui);
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--ji-muted);
  max-width: 68ch;
}
.fx-beta p:last-child {
  margin-bottom: 0;
}
.fx-beta strong {
  color: var(--ji-text);
}

/* El aviso pegado a la cifra grande del resultado. Repite lo del cartel de
   arriba a proposito: a esta cifra se llega despues de subir ficheros y de
   bajar la pagina, y es la que se copia. */
.fx-aviso-cifra {
  margin: 14px 0 0;
  padding: 10px 13px;
  border-left: 2px solid var(--ji-gold);
  border-radius: 0 8px 8px 0;
  background: var(--ji-inset);
  font-family: var(--ji-ui);
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--ji-muted);
  max-width: 68ch;
}
.fx-aviso-cifra strong { color: var(--ji-text); }

/* Aviso de los anios incompletos en la serie de En claro. */
.ec-incompletos {
  margin: 0 0 12px;
  padding: 9px 12px;
  border-left: 2px solid var(--ji-gold);
  border-radius: 0 8px 8px 0;
  background: var(--ji-inset);
  font-family: var(--ji-ui);
  font-size: 12px;
  line-height: 1.55;
  color: var(--ji-muted);
}
.ec-incompletos strong { color: var(--ji-text); }

/* =====================================================================
   ACCESO A LA GUIA DEL FLEX.
   Era un enlace de 12,5 px bajo la zona de subida. La guia es justo lo
   que necesita quien AUN NO tiene el fichero, y ese es quien menos va a
   ponerse a leer letra pequenia.
   ===================================================================== */
.fx-guia-tarjeta {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: -4px 0 20px;
  padding: 14px 16px;
  border: 1px solid var(--ji-border);
  border-radius: 12px;
  background: var(--ji-surface);
  text-decoration: none;
  transition: border-color .15s, background .15s, transform .15s;
}
.fx-guia-tarjeta:hover {
  border-color: var(--ji-gold);
  background: color-mix(in srgb, var(--ji-gold) 5%, var(--ji-surface));
}
.fx-guia-icono {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: 10px;
  background: var(--ji-inset);
  color: var(--ji-gold);
}
.fx-guia-texto {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.fx-guia-texto strong {
  font-family: var(--ji-ui);
  font-size: 14px;
  color: var(--ji-text);
}
.fx-guia-texto span {
  font-family: var(--ji-ui);
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ji-muted);
}
.fx-guia-flecha {
  flex: 0 0 auto;
  color: var(--ji-muted);
  font-size: 18px;
}
.fx-guia-tarjeta:hover .fx-guia-flecha { color: var(--ji-gold); }

/* El resultado combinado: la pregunta que trae a la gente a esta pantalla. */
.ec-resultado {
  margin-top: 18px;
  padding: 14px 16px;
  border: 1px solid var(--ji-border);
  border-radius: 12px;
  background: var(--ji-inset);
}
.ec-resultado-cifra {
  margin: 0;
  font-family: var(--ji-serif);
  font-weight: 300;
  font-size: clamp(17px, 2.4vw, 22px);
  color: var(--ji-text);
}
.ec-resultado-cifra strong {
  font-family: var(--ji-mono);
  font-weight: 500;
  letter-spacing: -0.01em;
}
.ec-resultado-cuenta {
  margin: 6px 0 0;
  font-family: var(--ji-mono);
  font-size: 12px;
  color: var(--ji-muted);
}
.ec-resultado-nota {
  margin: 10px 0 0;
  padding-left: 10px;
  border-left: 2px solid var(--ji-gold);
  font-family: var(--ji-ui);
  font-size: 12px;
  line-height: 1.55;
  color: var(--ji-muted);
  max-width: 62ch;
}
.ec-resultado-nota strong { color: var(--ji-text); }

/*
 * Los tres campos del declarante del 720, en fila cuando cabe.
 * `auto-fit` con un mínimo de 200 px: en el móvil caen a una columna solos, sin
 * necesidad de otra consulta de medios.
 */
.m720-declarante {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 0 16px;
}

/*
 * Los pasos numerados de la guía del 720.
 *
 * `.fg-lista` es un `ul` con viñetas; aquí el orden importa —el paso 6 es
 * donde hay que pararse— así que se numera. El número en dorado porque es lo
 * que se busca con el ojo al ir siguiendo la pantalla de la sede.
 */
ol.fg-pasos {
  list-style: decimal;
  padding-left: 22px;
}
ol.fg-pasos li::marker {
  color: var(--ji-gold);
  font-family: var(--ji-ui);
  font-size: 13px;
}

/* --- Presentaciones ante la SEC ---------------------------------------- */
/* La tabla se desplaza SOLA en horizontal, no la página: es la regla del
   proyecto para todo lo ancho, y aquí muerde porque la descripción de un
   formulario de la SEC puede ser larguísima. */
.emp-filings {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  display: block;
  overflow-x: auto;
}
.emp-filings th {
  text-align: left;
  font-size: 11px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--ji-muted);
  font-weight: 500;
  padding: 6px 14px 6px 0;
  border-bottom: 1px solid var(--ji-border);
  white-space: nowrap;
}
.emp-filings td {
  padding: 7px 14px 7px 0;
  border-bottom: 1px solid var(--ji-border);
  color: var(--ji-text);
  vertical-align: top;
}
.emp-filings td.ji-num {
  white-space: nowrap;
  font-family: var(--ji-mono);
  font-variant-numeric: tabular-nums;
  color: var(--ji-muted);
}
/* El formulario es el enlace al documento: se marca como tal, que si no nadie
   descubre que se puede pinchar. */
.emp-filings a {
  color: var(--ji-gold);
  text-decoration: none;
}
.emp-filings a:hover {
  text-decoration: underline;
}


/* ── Documentos legales ──────────────────────────────────────────────────
 *
 * El aviso de datos que faltan usa `--ji-loss` a propósito: tiene que doler a
 * la vista. Es lo único que impide publicar un aviso legal sin NIF, que
 * incumple el art. 10 LSSI igual que si no existiera pero aparenta cumplir.
 *
 * Los encabezados usan la serif de la marca porque estos dos documentos son lo
 * único de la web que se LEE de arriba abajo, como un texto, no como una
 * pantalla de herramienta.
 */
.legal-incompleto {
  border: 1px solid var(--ji-loss);
  border-left-width: 4px;
  border-radius: var(--ji-radio-sm);
  background: color-mix(in srgb, var(--ji-loss) 10%, transparent);
  padding: 14px 18px;
  margin-bottom: 28px;
  max-width: 46rem;
}
.legal-incompleto p,
.legal-incompleto li {
  font-family: var(--ji-ui);
  font-size: 14px;
  line-height: 1.6;
  color: var(--ji-text);
  margin: 0 0 0.6rem;
}
.legal-incompleto p:last-child {
  margin-bottom: 0;
}
.legal-incompleto ul {
  margin: 0 0 0.6rem;
  padding-left: 1.2rem;
}
.legal-incompleto code {
  font-family: var(--ji-mono);
  font-size: 13px;
}

.legal-cuerpo h2 {
  font-family: var(--ji-serif);
  font-size: 21px;
  font-weight: 600;
  color: var(--ji-text);
  margin: 2rem 0 0.7rem;
  padding-top: 1.2rem;
  border-top: 1px solid var(--ji-border);
}
.legal-cuerpo h2:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: none;
}
.legal-cuerpo h3 {
  font-family: var(--ji-ui);
  font-size: 15px;
  font-weight: 600;
  color: var(--ji-gold);
  margin: 1.4rem 0 0.5rem;
}
.legal-cuerpo {
  padding-bottom: 3rem;
}

/* Los enlaces legales del pie de la landing. */
.lp-legal-pie a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.lp-legal-pie a:hover {
  color: var(--ji-gold);
}


/* Casilla del lote de Substack: la única del panel de administración, de ahí
 * que no hubiera clase previa que reutilizar. */
.adm-check {
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--ji-ui);
  font-size: 14px;
  color: var(--ji-muted);
  margin: 10px 0 4px;
  cursor: pointer;
}
.adm-check input {
  margin: 0;
  cursor: pointer;
}
.adm-check code {
  font-family: var(--ji-mono);
  font-size: 13px;
  color: var(--ji-text);
}

/* La salida del lote: mil líneas tienen que poder leerse sin desbordar. */
.lote-salida textarea {
  width: 100%;
  box-sizing: border-box;
  font-family: var(--ji-mono);
  font-size: 12px;
  line-height: 1.5;
  background: var(--ji-inset);
  color: var(--ji-text);
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio-sm);
  padding: 10px;
  resize: vertical;
  white-space: pre;
  overflow-x: auto;
}


/* ── Lista de cuentas del panel ──────────────────────────────────────────
 *
 * La columna de notas es el motivo de que este bloque exista: se escribía por
 * qué se activaba a alguien a mano y no se pintaba en ninguna parte. Lleva
 * `pre-line` porque la nota es un historial de varias líneas, una por cambio.
 */
.adm-estado {
  display: inline-block;
  font-family: var(--ji-ui);
  font-size: 12px;
  font-weight: 600;
  padding: 2px 9px;
  border-radius: 999px;
  border: 1px solid transparent;
}
.adm-estado.activa {
  color: var(--ji-gain);
  border-color: color-mix(in srgb, var(--ji-gain) 45%, transparent);
  background: color-mix(in srgb, var(--ji-gain) 12%, transparent);
}
.adm-estado.pendiente {
  color: var(--ji-gold);
  border-color: color-mix(in srgb, var(--ji-gold) 45%, transparent);
  background: color-mix(in srgb, var(--ji-gold) 12%, transparent);
}
.adm-estado.revocada {
  color: var(--ji-loss);
  border-color: color-mix(in srgb, var(--ji-loss) 45%, transparent);
  background: color-mix(in srgb, var(--ji-loss) 12%, transparent);
}
.adm-nota {
  white-space: pre-line;
  font-size: 12px;
  line-height: 1.5;
  color: var(--ji-muted);
  max-width: 34rem;
}


/* ── Primera columna fija al desplazar (5-sep-2026) ──────────────────────
 *
 * Las etiquetas de fila («ROE») ya se quedaban quietas, pero la cabecera
 * «Ratio» y los títulos de sección se iban con el desplazamiento — y una barra
 * de sección vacía parece la tabla rota, no una tabla desplazada.
 *
 * La cabecera solo necesitaba la regla, que no la tenía.
 *
 * LA SECCIÓN ES OTRA COSA, y explica por qué no bastaba con `position: sticky`
 * (que ya lo tenía y no servía de nada): su celda lleva `colSpan` de la fila
 * entera, y `sticky` solo puede desplazar un elemento DENTRO de su bloque
 * contenedor. Si la celda ya ocupa toda la fila, el margen para moverse es
 * cero. Por eso lo sticky pasa a ser el `<span>` de dentro, que sí tiene sitio.
 *
 * Medido con la tabla reproducida aparte antes y después: los tres elementos
 * pasan de irse a −599 px a quedarse en +1.
 */
.ef-tabla thead th:first-child {
  position: sticky;
  left: 0;
  background: var(--fondo);
  /* Por encima de las etiquetas de fila, que también son sticky y se cruzan
     con ella en la esquina. */
  z-index: 3;
}
.ef-tabla th[scope='row'] {
  z-index: 2;
}
/* El relleno se va al span: si se queda en la celda, el texto arranca
   desplazado y al pegarse a la izquierda pierde su margen. */
.ef-seccion th {
  position: static;
  padding: 0;
}
.ef-seccion th > span {
  position: sticky;
  left: 0;
  display: inline-block;
  padding: 9px 10px 8px;
}


/* ── Mi cuenta ───────────────────────────────────────────────────────────*/
.bm-cuenta {
  font-family: var(--ji-ui);
  font-size: 13px;
  color: var(--ji-muted);
  text-decoration: none;
  padding: 5px 10px;
  border-radius: var(--ji-radio-sm);
  white-space: nowrap;
}
.bm-cuenta:hover,
.bm-cuenta.active {
  color: var(--ji-text);
  background: var(--ji-surface-2);
}
.cuenta-datos {
  display: flex;
  flex-wrap: wrap;
  gap: 28px;
  margin-bottom: 14px;
}
.cuenta-etq {
  display: block;
  font-family: var(--ji-ui);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ji-muted);
  margin-bottom: 3px;
}
.cuenta-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-width: 26rem;
}
.cuenta-form .pista {
  margin: -4px 0 0;
}

/* El bloque de borrado va marcado en rojo: es lo único de esta página que no
   se puede deshacer, y tiene que leerse distinto del resto antes de pulsar. */
.cuenta-peligro {
  border: 1px solid color-mix(in srgb, var(--ji-loss) 40%, transparent);
  border-radius: var(--ji-radio);
  padding: 18px 20px;
}
.cuenta-peligro h2 {
  color: var(--ji-loss);
}
.cuenta-borrar {
  background: var(--ji-loss);
  border: none;
  color: #fff;
  font-weight: 600;
}
.cuenta-borrar:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}


/* ── Diálogo propio, en vez de confirm/prompt del navegador ──────────────
 *
 * `<dialog>` nativo: trae gratis el foco atrapado dentro, el cierre con Esc y
 * quedar por encima de todo sin pelear con z-index. Lo que se estiliza es la
 * caja de dentro, no el elemento, para no romper esos comportamientos.
 */
.dlg {
  border: none;
  padding: 0;
  background: transparent;
  color: inherit;
  max-width: min(30rem, calc(100vw - 32px));
}
.dlg::backdrop {
  background: rgba(0, 0, 0, 0.62);
  backdrop-filter: blur(2px);
}
.dlg-caja {
  background: var(--ji-surface);
  border: 1px solid var(--ji-border-strong);
  border-radius: var(--ji-radio);
  box-shadow: var(--ji-sombra);
  padding: 22px 24px 18px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.dlg-mensaje {
  margin: 0;
  font-family: var(--ji-ui);
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--ji-text);
  /* Los mensajes llevan saltos de línea a propósito: primero qué va a pasar,
     luego qué se pide. Sin esto se leen de corrido. */
  white-space: pre-line;
}
.dlg-campo {
  margin: 0;
}
.dlg-botones {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 2px;
}
.dlg-peligro {
  background: var(--ji-loss);
  border-color: var(--ji-loss);
  color: #fff;
  font-weight: 600;
}
.dlg-botones button:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}


/* ── Trades guardados, en el catálogo de opciones ────────────────────────
 *
 * Lista y no desplegable: un `<select>` esconde cuántos hay y obliga a abrirlo
 * para saberlo. Aquí se ven de un vistazo, que es de lo que iba moverlos.
 */
.op-trades-lista {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.op-trades-lista li {
  display: flex;
  align-items: stretch;
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio-sm);
  background: var(--ji-surface);
  overflow: hidden;
}
.op-trade-abrir {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  background: none;
  border: none;
  padding: 8px 12px;
  cursor: pointer;
  text-align: left;
  font-family: var(--ji-ui);
  color: var(--ji-text);
}
.op-trade-abrir strong {
  font-size: 13px;
  font-weight: 600;
}
.op-trade-abrir span {
  font-size: 11px;
  color: var(--ji-muted);
  font-variant-numeric: tabular-nums;
}
.op-trades-lista li:hover {
  border-color: var(--ji-gold);
}
/* La cruz de borrar, apagada hasta que se pasa por encima: está al lado de
   abrir y no debe competir con ella por la atención. */
.op-trade-borrar {
  background: none;
  border: none;
  border-left: 1px solid var(--ji-border);
  color: var(--ji-muted);
  padding: 0 11px;
  font-size: 16px;
  line-height: 1;
  cursor: pointer;
}
.op-trade-borrar:hover {
  color: var(--ji-loss);
  background: color-mix(in srgb, var(--ji-loss) 12%, transparent);
}


/* ── Selección múltiple de gráficas ──────────────────────────────────────
 *
 * La casilla va apagada y solo se enciende al pasar por la fila o al estar
 * marcada: hay cientos de filas, y cientos de casillas a plena luz convertirían
 * la tabla en un formulario. Lo que se viene a leer son las cifras.
 */
.ef-marca {
  margin: 0;
  accent-color: var(--ji-gold);
  cursor: pointer;
  opacity: 0.25;
  transition: opacity 0.12s;
  flex: none;
}
.ef-marca:checked,
.ef-marca:focus-visible,
tr:hover .ef-marca {
  opacity: 1;
}
.ef-barra-sel {
  position: sticky;
  bottom: 12px;
  z-index: 4;
  display: flex;
  align-items: center;
  gap: 12px;
  width: fit-content;
  margin: 14px auto 0;
  padding: 9px 14px;
  background: var(--ji-surface-2);
  border: 1px solid var(--ji-border-strong);
  border-radius: 999px;
  box-shadow: var(--ji-sombra);
  font-family: var(--ji-ui);
  font-size: 13px;
  color: var(--ji-text);
}
.ef-barra-sel button {
  font-size: 12.5px;
  padding: 5px 12px;
}

/* Cada partida apilada en la ventana ampliada, separada por una línea: sin
   ella, tres gráficas seguidas se leen como una sola con mucho ruido. */
.gp-serie-sep {
  margin-top: 26px;
  padding-top: 22px;
  border-top: 1px solid var(--ji-border);
}
.gp-serie-tit {
  font-family: var(--ji-serif);
  font-size: 17px;
  font-weight: 600;
  color: var(--ji-text);
  margin: 0 0 10px;
}


/* ── Gráfica combinada: leyenda y cuadro del ratón ───────────────────────*/
.gp-leyenda-lista {
  list-style: none;
  margin: 14px 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.gp-leyenda-lista li {
  position: relative;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 5px 8px;
  border-radius: 8px;
  font-family: var(--ji-ui);
  font-size: 13px;
  color: var(--ji-text);
}
.gp-leyenda-lista li:hover {
  background: var(--ji-surface-2);
}
/* El cuadrito de color ES el botón de color: no hace falta un icono aparte
   para algo que ya se está enseñando. */
.gp-ley-color {
  flex: none;
  width: 12px;
  height: 12px;
  border-radius: 3px;
  border: none;
  padding: 0;
  cursor: pointer;
}
.gp-ley-nom {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  font: inherit;
  color: inherit;
  text-align: left;
}
.gp-ley-eje {
  flex: none;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ji-muted);
  border: 1px solid var(--ji-border);
  border-radius: 4px;
  padding: 1px 5px;
}
.gp-ley-forma {
  flex: none;
  background: none;
  border: none;
  padding: 2px 4px;
  cursor: pointer;
  color: var(--ji-muted);
  display: flex;
}
.gp-ley-forma:hover {
  color: var(--ji-text);
}
/* La paleta, sobre la fila: ocho cuadros y fuera. Un desplegable con nombres
   de color para elegir un color es peor que ver los colores. */
.gp-paleta {
  position: absolute;
  left: 4px;
  top: 100%;
  z-index: 3;
  display: flex;
  gap: 5px;
  padding: 7px;
  background: var(--ji-surface-2);
  border: 1px solid var(--ji-border-strong);
  border-radius: 9px;
  box-shadow: var(--ji-sombra);
}
.gp-paleta button {
  width: 16px;
  height: 16px;
  border-radius: 4px;
  border: none;
  padding: 0;
  cursor: pointer;
}
/* Apagada: se ve que sigue ahí y que se puede volver a encender. Quitarla de
   la lista obligaría a volver a la tabla a buscarla. */
.gp-serie-off button {
  opacity: 0.4;
}
.gp-serie-off .gp-cuadro {
  background: var(--ji-muted) !important;
}
.gp-leyenda-nom {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gp-leyenda-cifra {
  font-size: 12px;
  color: var(--ji-muted);
  font-variant-numeric: tabular-nums;
  flex: none;
}

.gp-comb-cuadro {
  position: absolute;
  top: 10px;
  right: 14px;
  z-index: 2;
  pointer-events: none;
  background: var(--ji-surface-2);
  border: 1px solid var(--ji-border-strong);
  border-radius: 10px;
  padding: 9px 12px;
  box-shadow: 0 10px 28px -14px rgba(0, 0, 0, 0.8);
  font-family: var(--ji-ui);
  font-size: 12px;
  min-width: 190px;
}
.gp-comb-fila {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 3px 0 0;
  color: var(--ji-muted);
  white-space: nowrap;
}
.gp-comb-fila span {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.gp-comb-fila strong {
  color: var(--ji-text);
  font-variant-numeric: tabular-nums;
}


/* La cifra sobre cada barra de la combinada. En mono para que las columnas de
   dígitos queden alineadas entre periodos, y pequeña: es una ayuda de lectura,
   no la protagonista. */
.gp-cifra-barra {
  font-family: var(--ji-mono);
  font-size: 11px;
  fill: var(--ji-muted);
  pointer-events: none;
}


/* ── La comparación, fija encima de la tabla ─────────────────────────────
 *
 * Antes esto era una ventana. Se pasa a estar fijo porque comparar es un
 * TANTEO: marcas tres series, ves que sobra una, la quitas. Con una ventana de
 * por medio cada tanteo eran dos clics y perder la tabla de vista.
 */
.ef-comparacion {
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio);
  background: var(--ji-surface);
  padding: 16px 18px 14px;
  margin-bottom: 20px;
}
.ef-comp-cab {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 10px;
}
.ef-comp-cab h3 {
  font-family: var(--ji-ui);
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ji-muted);
  margin: 0;
}
.ef-comp-cab strong {
  color: var(--ji-gold);
}


/* ── Riel de periodos ────────────────────────────────────────────────────
 *
 * Dos `input[type=range]` sobre el mismo carril. El carril NO recibe el ratón y
 * solo lo reciben las asas: sin eso, el input de encima se comería los clics
 * del de debajo y una de las dos asas dejaría de agarrarse donde se solapan.
 */
.gp-rango {
  margin: 14px 2px 0;
}
.gp-rango-carril {
  position: relative;
  height: 20px;
}
.gp-rango-carril::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 9px;
  height: 3px;
  border-radius: 2px;
  background: var(--ji-border-strong);
}
.gp-rango-tramo {
  position: absolute;
  top: 9px;
  height: 3px;
  border-radius: 2px;
  background: var(--ji-gold);
}
.gp-rango-carril input {
  position: absolute;
  inset: 0;
  width: 100%;
  margin: 0;
  background: none;
  appearance: none;
  -webkit-appearance: none;
  pointer-events: none;
}
.gp-rango-carril input::-webkit-slider-thumb {
  -webkit-appearance: none;
  pointer-events: auto;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--ji-gold);
  border: 2px solid var(--ji-bg);
  cursor: grab;
}
.gp-rango-carril input::-moz-range-thumb {
  pointer-events: auto;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--ji-gold);
  border: 2px solid var(--ji-bg);
  cursor: grab;
}
.gp-rango-carril input:focus-visible::-webkit-slider-thumb {
  outline: 2px solid var(--ji-blue);
  outline-offset: 2px;
}
.gp-rango-pie {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 4px;
  font-family: var(--ji-mono);
  font-size: 11px;
  color: var(--ji-muted);
}
.gp-rango-pie button {
  font-size: 11px;
  padding: 3px 10px;
}


/* ── Barra de conmutadores de la tabla ───────────────────────────────────*/
.ef-barra-vista {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 16px;
}
/* Los tres modos, pegados en un grupo: dice sin palabras que son excluyentes,
   que es justo lo que fiscal.ai no deja claro con dos interruptores sueltos. */
.ef-modos {
  display: inline-flex;
  border: 1px solid var(--ji-border);
  border-radius: 999px;
  overflow: hidden;
}
.ef-modos button {
  background: none;
  border: none;
  border-radius: 0;
  padding: 6px 14px;
  font-family: var(--ji-ui);
  font-size: 12.5px;
  color: var(--ji-muted);
  cursor: pointer;
}
.ef-modos button + button {
  border-left: 1px solid var(--ji-border);
}
.ef-modos button:hover {
  color: var(--ji-text);
}
.ef-modos button.on {
  background: var(--ji-gold);
  color: #0b1220;
  font-weight: 600;
}
.ef-invertir {
  font-size: 12.5px;
  padding: 6px 14px;
  border-radius: 999px;
}
.ef-invertir.on {
  background: var(--ji-gold);
  border-color: var(--ji-gold);
  color: #0b1220;
  font-weight: 600;
}


/* La «×» de quitar: apagada hasta que se pasa por la fila. Es destructiva y no
   debe competir por la atención con el nombre de la serie. */
.gp-ley-quitar {
  flex: none;
  background: none;
  border: none;
  padding: 0 4px;
  font-size: 16px;
  line-height: 1;
  color: var(--ji-muted);
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.12s;
}
.gp-leyenda-lista li:hover .gp-ley-quitar,
.gp-ley-quitar:focus-visible {
  opacity: 1;
}
.gp-ley-quitar:hover {
  color: var(--ji-loss);
}


/* Desglose del CSV por tipo de suscripción. En verde lo que da acceso y en
   gris lo que no: un tipo que Substack renombre saltará a la vista en gris. */
.adm-tipos {
  list-style: none;
  margin: 10px 0 14px;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.adm-tipos li {
  display: flex;
  align-items: baseline;
  gap: 7px;
  font-family: var(--ji-ui);
  font-size: 12.5px;
  color: var(--ji-muted);
  border: 1px solid var(--ji-border);
  border-radius: 999px;
  padding: 4px 12px;
}
.adm-tipos li.si {
  border-color: color-mix(in srgb, var(--ji-gain) 45%, transparent);
  color: var(--ji-text);
}
.adm-tipos li.si strong {
  color: var(--ji-gain);
}
.adm-tipos li span {
  font-size: 11px;
  opacity: 0.75;
}


/* ── Editor de la criba ──────────────────────────────────────────────────*/
.criba {
  margin-top: 8px;
}
.criba-cab {
  display: flex;
  align-items: flex-end;
  flex-wrap: wrap;
  gap: 18px;
  margin-bottom: 18px;
}
.criba-marcador {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 8px 14px;
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio-sm);
  min-width: 150px;
}
/* Una criba a medias no es una criba mala: se lee distinto, no peor. */
.criba-marcador.parcial {
  border-color: color-mix(in srgb, var(--ji-gold) 40%, transparent);
}
.criba-marcador.completa {
  border-color: color-mix(in srgb, var(--ji-gain) 45%, transparent);
}
.criba-marcador-etq {
  font-family: var(--ji-ui);
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ji-muted);
}
.criba-marcador strong {
  font-size: 22px;
  color: var(--ji-text);
}
.criba-marcador-pie {
  font-family: var(--ji-ui);
  font-size: 11px;
  color: var(--ji-muted);
}

.criba-lista {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.criba-preg {
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio-sm);
  padding: 12px 14px;
  background: var(--ji-surface);
}
/* Sin contestar se ve apagada: de un vistazo se sabe qué queda por mirar. */
.criba-preg.sin-contestar {
  opacity: 0.72;
  border-style: dashed;
}
.criba-enunciado {
  display: flex;
  align-items: baseline;
  gap: 9px;
  margin: 0 0 8px;
  font-family: var(--ji-ui);
  font-size: 14.5px;
  line-height: 1.45;
  color: var(--ji-text);
}
.criba-num {
  flex: none;
  font-family: var(--ji-mono);
  font-size: 12px;
  color: var(--ji-muted);
  border: 1px solid var(--ji-border);
  border-radius: 4px;
  padding: 0 5px;
}
.criba-ayuda {
  margin: -4px 0 8px;
}
.criba-botones {
  display: flex;
  gap: 7px;
  margin-bottom: 9px;
}
.criba-op {
  font-size: 12.5px;
  padding: 5px 16px;
  border-radius: 999px;
  /* «No lo sé» son tres palabras y la píldora tiene que crecer con ellas, no
     partirlas: partido, el texto se sale de la caja. Pasó de verdad —una clase
     de la criba rápida le impuso un tamaño fijo— y esto lo hace imposible
     aunque alguien vuelva a apretar el ancho desde fuera. */
  white-space: nowrap;
}
.criba-op.si.on {
  background: var(--ji-gain);
  border-color: var(--ji-gain);
  color: #0b1220;
  font-weight: 600;
}
.criba-op.no.on {
  background: var(--ji-loss);
  border-color: var(--ji-loss);
  color: #fff;
  font-weight: 600;
}
/* «No sé» en gris y NUNCA en rojo: no es un no, y pintarlo como tal enseñaría
   a leer mal la propia criba. */
.criba-op.no-se.on {
  background: var(--ji-surface-2);
  border-color: var(--ji-border-strong);
  color: var(--ji-text);
  font-weight: 600;
}
.criba-explicacion {
  width: 100%;
  box-sizing: border-box;
  background: var(--ji-inset);
  border: 1px solid var(--ji-border);
  border-radius: 8px;
  padding: 8px 10px;
  color: var(--ji-text);
  font-family: var(--ji-ui);
  font-size: 13px;
  line-height: 1.5;
  resize: vertical;
}
.criba-explicacion:disabled {
  opacity: 0.5;
}
.criba-macro-tit {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-family: var(--ji-ui);
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ji-muted);
  margin: 26px 0 10px;
}
.criba-macro-tit span {
  font-size: 13px;
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
}
.wl-editor-tit {
  font-family: var(--ji-serif);
  font-size: 20px;
  margin: 30px 0 4px;
  padding-top: 22px;
  border-top: 1px solid var(--ji-border);
}


/* ── Criba: vista de lectura y sección Estado ────────────────────────────*/
.criba-resp {
  margin-left: auto;
  flex: none;
  font-family: var(--ji-ui);
  font-size: 12.5px;
  font-weight: 600;
  padding: 2px 10px;
  border-radius: 999px;
  border: 1px solid var(--ji-border);
  color: var(--ji-muted);
}
.criba-resp.si {
  color: var(--ji-gain);
  border-color: color-mix(in srgb, var(--ji-gain) 45%, transparent);
}
.criba-resp.no {
  color: var(--ji-loss);
  border-color: color-mix(in srgb, var(--ji-loss) 45%, transparent);
}
/* «No lo sé» en gris, NUNCA en rojo: no es un no, y pintarlo como tal
   enseñaría a leer mal la criba entera. */
.criba-resp.no-se,
.criba-resp.vacia {
  color: var(--ji-muted);
}
.criba-porque {
  margin: 0;
  font-family: var(--ji-ui);
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--ji-muted);
  border-left: 2px solid var(--ji-border);
  padding-left: 11px;
}
.criba-vista .criba-enunciado {
  gap: 12px;
}
/* La respuesta, pegada a la pregunta y no suelta al otro lado de la tarjeta
   (Javi, 13-sep-2026: «está aislada a la derecha»). */
.criba-vista .criba-enunciado .criba-resp {
  margin-left: 0;
}

.emp-estado {
  border: 1px solid color-mix(in srgb, var(--ji-gold) 30%, transparent);
  border-radius: var(--ji-radio);
  background: color-mix(in srgb, var(--ji-gold) 5%, transparent);
  padding: 16px 20px;
  margin: 24px 0;
  max-width: 52rem;
}
.emp-estado h3 {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin: 0 0 6px;
  font-family: var(--ji-serif);
  font-size: 18px;
  color: var(--ji-gold);
}
.emp-estado-conv {
  font-family: var(--ji-ui);
  font-size: 12px;
  font-weight: 400;
  color: var(--ji-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.emp-estado-conv strong {
  font-size: 18px;
  color: var(--ji-text);
  margin: 0 2px 0 6px;
}
.emp-estado-que {
  margin: 0 0 10px;
  font-family: var(--ji-ui);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ji-text);
}


/* El cierre de la criba: convicción y veredicto escrito. */
.criba-cierre {
  margin-top: 26px;
  padding-top: 22px;
  border-top: 1px solid var(--ji-border);
  max-width: 44rem;
}
.criba-cierre h3 {
  font-family: var(--ji-ui);
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ji-muted);
  margin: 0 0 10px;
}
.criba-conv {
  display: flex;
  gap: 6px;
  margin-bottom: 8px;
}
.criba-conv-op {
  width: 42px;
  font-family: var(--ji-mono);
  font-size: 14px;
  padding: 7px 0;
}
.criba-conv-op.on {
  background: var(--ji-gold);
  border-color: var(--ji-gold);
  color: #0b1220;
  font-weight: 700;
}
/* Lo que va a pasar, ANTES de guardar: elegir un número sin ver su
   consecuencia es elegir a ciegas. */
.criba-conv-que {
  margin: 0 0 12px;
  font-family: var(--ji-ui);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ji-gold);
}


/* Enlaces a la fuente de cada semáforo macro. Van junto a la pregunta y no en
   un pie: la gracia es abrir el dato ANTES de contestar. */
.criba-fuentes {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin: -2px 0 9px;
}
.criba-fuentes a {
  font-family: var(--ji-ui);
  font-size: 12px;
  color: var(--ji-blue);
  text-decoration: none;
}
.criba-fuentes a:hover {
  text-decoration: underline;
}


/* ── Presentaciones: filtro, glosario y enlaces ──────────────────────────*/
.fil-tipos {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 12px;
}
.fil-tipos button {
  font-family: var(--ji-mono);
  font-size: 11.5px;
  padding: 4px 11px;
  border-radius: 999px;
}
.fil-tipos button span {
  color: var(--ji-muted);
  margin-left: 5px;
}
.fil-tipos button.on {
  background: var(--ji-gold);
  border-color: var(--ji-gold);
  color: #0b1220;
  font-weight: 600;
}
.fil-tipos button.on span {
  color: #0b1220;
  opacity: 0.7;
}
.fil-glosario {
  margin-bottom: 16px;
  font-family: var(--ji-ui);
  font-size: 13px;
}
.fil-glosario summary {
  cursor: pointer;
  color: var(--ji-muted);
}
.fil-glosario dl {
  margin: 10px 0 0;
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 4px 14px;
}
.fil-glosario dl > div {
  display: contents;
}
.fil-glosario dt {
  font-family: var(--ji-mono);
  font-size: 12px;
  color: var(--ji-gold);
  white-space: nowrap;
}
.fil-glosario dd {
  margin: 0;
  color: var(--ji-muted);
  line-height: 1.5;
}
/* Los que conviene mirar con atención al estudiar una empresa: el 10-K, el
   13D del activista, el Form 4 del insider. */
.fil-clave {
  color: var(--ji-gold);
  font-weight: 600;
}
.fil-que {
  font-size: 12.5px;
  color: var(--ji-muted);
  max-width: 30rem;
}
.fil-enmienda {
  margin-left: 7px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ji-blue);
  border: 1px solid color-mix(in srgb, var(--ji-blue) 40%, transparent);
  border-radius: 4px;
  padding: 1px 5px;
}
.fil-enlaces {
  display: flex;
  gap: 12px;
  white-space: nowrap;
}
.fil-enlaces a {
  font-family: var(--ji-ui);
  font-size: 12px;
  color: var(--ji-blue);
  text-decoration: none;
}
.fil-enlaces a:hover {
  text-decoration: underline;
}

/* =====================================================================
   BUZÓN DE PROPUESTAS (7-sep-2026)
   ===================================================================== */
.prop-lista {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.prop-fila {
  padding: 16px 18px;
  border: 1px solid var(--ji-border);
  border-radius: 12px;
  background: var(--ji-surface);
}
/* El estado, también en el borde: en una lista larga el color se lee antes
   que la píldora. */
.prop-fila.estado-aceptada {
  border-left: 3px solid var(--ji-gain);
}
.prop-fila.estado-descartada {
  border-left: 3px solid var(--ji-loss);
}
.prop-cab {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 8px;
}
.prop-nombre {
  color: var(--ji-text);
  font-size: 14px;
}
.prop-fecha {
  margin-left: auto;
  font-size: 12px;
  color: var(--ji-muted);
}
.prop-pill {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 3px 9px;
  border-radius: 999px;
  border: 1px solid var(--ji-border);
  color: var(--ji-muted);
}
.prop-pill.aceptada {
  color: var(--ji-gain);
  border-color: color-mix(in srgb, var(--ji-gain) 45%, transparent);
}
.prop-pill.descartada {
  color: var(--ji-loss);
  border-color: color-mix(in srgb, var(--ji-loss) 45%, transparent);
}
.prop-pill.mirada {
  color: var(--ji-gold);
  border-color: color-mix(in srgb, var(--ji-gold) 45%, transparent);
}
.prop-porque {
  font-size: 14px;
  line-height: 1.6;
  color: var(--ji-text);
  margin: 0 0 8px;
  /* Lo escribe un usuario: puede venir con saltos de línea y conviene
     respetarlos, pero sin dejar que una parrafada rompa la caja. */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.prop-que,
.prop-respuesta {
  font-size: 13px;
  line-height: 1.55;
  color: var(--ji-muted);
  margin: 0;
}
.prop-respuesta {
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--ji-border);
  color: var(--ji-text);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}


/* Los selectores apagados: neutros, para que el encendido se distinga. Antes
   el apagado era el azul del botón por defecto; con el botón dorado, el
   apagado y el encendido de «Más antiguo primero» serían el mismo color. */
.criba-op:not(.on),
.criba-conv-op:not(.on),
.ef-invertir:not(.on) {
  background: transparent;
  border: 1px solid var(--ji-border);
  color: var(--ji-muted);
  font-weight: 500;
}
.criba-op:not(.on):hover:not(:disabled),
.criba-conv-op:not(.on):hover:not(:disabled),
.ef-invertir:not(.on):hover {
  color: var(--ji-text);
  border-color: var(--ji-border-strong);
}

/* =====================================================================
   DESIGN-SYSTEM del rediseño (Fase 1, ADR-0009).
   =====================================================================

   El lenguaje visual nuevo —Apple claro por defecto + "pantallas" oscuras
   estilo TradingView, con Fraunces / Hanken Grotesk / IBM Plex Mono— validado
   como artifacts durante la fase de diseño. Aquí vive su fuente de verdad en la
   app real.

   PRINCIPIO: aditivo y NAMESPACED. Todo va bajo el prefijo `--ji-*` / `.ji-*`
   (Jota Investor) para NO tocar los dos sistemas de tokens que ya cablean las
   pantallas actuales (`--fondo/--superficie…` y `--bg/--panel/--accent…` en
   `styles.css`). Las pantallas se pasan a este lenguaje AL PORTARLAS, una a una;
   hasta entonces conviven sin recolorear nada (componer, no modificar).

   TEMA: se engancha al mismo interruptor que el resto, `<html data-theme>`
   (siempre estampado por `components/useTheme.ts`). Oscuro en el `:root` pelado;
   claro en `:root[data-theme='light']`. No hace falta `prefers-color-scheme`
   porque la app siempre fija `data-theme` al montar, igual que el CSS existente.
   ===================================================================== */

:root {
  /* --- Tipografía --------------------------------------------------- */
  /* Cada pila lleva reserva del sistema: si Google Fonts no carga, sigue
     legible (Fraunces→serif, Hanken→sans del sistema, IBM Plex→mono). */
  --ji-serif: 'Fraunces', Georgia, 'Times New Roman', serif;
  --ji-ui: 'Hanken Grotesk', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --ji-mono: 'IBM Plex Mono', ui-monospace, 'Cascadia Code', Consolas, monospace;

  /* --- Superficies y texto (tema OSCURO, la "pantalla" TradingView) --- */
  --ji-bg: #0d1119;
  --ji-surface: #141a24;
  --ji-surface-2: #1a2130; /* elevada: hover / tarjeta sobre tarjeta */
  --ji-inset: #0f151e; /* hundida: inputs, huecos */
  --ji-border: rgba(255, 255, 255, 0.08);
  --ji-border-strong: rgba(255, 255, 255, 0.14);
  --ji-text: #f4f0e9; /* crema cálido, pega con Fraunces */
  --ji-muted: #868b99;

  /* --- Acento de marca (oro) y semánticos --------------------------- */
  /* Dos oros a propósito, mismo patrón que --accent / --accent-chip del CSS
     viejo: `--ji-gold` hace de acento y de TEXTO (se oscurece en claro para
     mantener contraste); `--ji-gold-solid` es el relleno de chip/píldora y se
     queda dorado brillante en ambos temas, porque encima lleva texto oscuro
     fijo. */
  --ji-gold: #e0b24d;
  --ji-gold-solid: #e0b24d;
  --ji-gain: #26a69a; /* verde ganancia (teal) */
  --ji-gain-soft: #7fc8a9; /* «valorando compra»: un si todavia sin ejecutar (0082) */
  --ji-loss: #ef5350; /* rojo pérdida */
  --ji-blue: #5b8dee; /* salario / línea "hoy" T+0 */
  --ji-purple: #a855f7; /* estado "privada" de la watchlist */

  /* --- Serie de colores para repartos (donut de la Cartera) -----------
     Ocho matices bien separados, anclados en los semánticos que ya existen.
     El ROJO NO entra: en esta web significa pérdida, y una porción roja de un
     reparto se leería como «esto va mal» cuando solo dice «esto pesa tanto». */
  --ji-serie-1: #5b8dee; /* azul */
  --ji-serie-2: #e0b24d; /* oro */
  --ji-serie-3: #26a69a; /* verde azulado */
  --ji-serie-4: #a855f7; /* púrpura */
  --ji-serie-5: #22d3ee; /* cian */
  --ji-serie-6: #f7931a; /* naranja */
  --ji-serie-7: #f472b6; /* rosa */
  --ji-serie-8: #94a3b8; /* pizarra — el «sin clasificar» */

  /* --- Formas ------------------------------------------------------- */
  --ji-radio: 16px; /* tarjeta */
  --ji-radio-sm: 10px; /* píldora / control */
  --ji-sombra: 0 18px 40px -24px rgba(0, 0, 0, 0.7);
}

/* --- Tema CLARO (Apple): superficies y texto se invierten; los semánticos
   se oscurecen lo justo para leer sobre fondo claro. El oro-chip y los verdes/
   rojos de relleno mantienen su tono; solo cambian cuando hacen de texto. --- */
:root[data-theme='light'] {
  /*
   * BAJADO UN PUNTO EL 7-SEP-2026. Javi, mirando el hub en claro: *«que el
   * blanco fuese un poco más opaco… demasiada luz y es molesto; que sea blanco
   * no quiere decir que tenga que deslumbrar»*.
   *
   * Lo que deslumbraba no era el papel, era la SUMA: el fondo casi blanco más
   * tarjetas de blanco PURO encima. Dos superficies a 0,95 de luminancia y sin
   * separación entre ellas — de ahí también su otra queja, que las tarjetas
   * «tapan el fondo»: no destacaban como objetos, se fundían en una plancha.
   *
   * Ahora el papel baja y las tarjetas suben un poco por encima de él. Se ve
   * menos luz total y MÁS jerarquía: la tarjeta se lee como tarjeta.
   */
  --ji-bg: #eae6dd; /* papel cálido, un punto por debajo del blanco */
  --ji-surface: #faf8f4; /* la tarjeta, por encima del papel y sin ser blanco puro */
  --ji-surface-2: #f2eee7;
  --ji-inset: #e2ddd2; /* hundida: por debajo del papel, no por encima */
  /* Cantos más marcados: con las dos superficies tan juntas, el borde es lo que
     de verdad dibuja el objeto. */
  --ji-border: rgba(28, 22, 14, 0.14);
  --ji-border-strong: rgba(28, 22, 14, 0.24);
  --ji-text: #1c1a17;
  /* El texto secundario sube de contraste: era lo que Javi no veía bien. Sobre
     la tarjeta pasa de ~4,9:1 a ~6,7:1. */
  --ji-muted: #545861;

  --ji-gold: #9a6f1c; /* oro oscurecido: legible como texto/acento en claro */
  --ji-gold-solid: #e0b24d; /* el chip sigue dorado brillante */
  --ji-gain: #15877c;
  --ji-loss: #d5423e;
  --ji-blue: #3d6fd6;
  --ji-purple: #8b3fd4;

  /* Los mismos ocho, oscurecidos: sobre papel claro los tonos brillantes
     pierden todo el contraste y las porciones pequeñas desaparecen. */
  --ji-serie-1: #3d6fd6;
  --ji-serie-2: #b8862a;
  --ji-serie-3: #15877c;
  --ji-serie-4: #8b3fd4;
  --ji-serie-5: #0e9bb5;
  --ji-serie-6: #c9760f;
  --ji-serie-7: #d1568e;
  --ji-serie-8: #6c7079;

  --ji-sombra: 0 18px 40px -28px rgba(20, 16, 10, 0.25);
}

/* =====================================================================
   PRIMITIVAS. Un puñado de clases que las pantallas portadas componen. No
   pretende ser exhaustivo: crece cuando una pantalla real lo necesita, no
   antes. Todo opt-in: nada de esto se aplica hasta que un elemento lleva su
   clase, así que no afecta a lo ya existente.
   ===================================================================== */

/* Contenedor raíz de una pantalla del rediseño: fija fuente y color base. NO
   fija el fondo (cada pantalla decide si va sobre --ji-bg claro o sobre una
   "pantalla" oscura). */
.ji {
  font-family: var(--ji-ui);
  color: var(--ji-text);
}

/* Cifras: siempre monoespaciadas y con dígitos de ancho fijo, para que las
   columnas de números cuadren. */
.ji-num {
  font-family: var(--ji-mono);
  font-variant-numeric: tabular-nums;
}

/* Etiqueta pequeña en mayúsculas sobre un título (el "eyebrow" dorado). */
.ji-eyebrow {
  font-family: var(--ji-ui);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ji-gold);
}

/* Título enorme de hero/hub (Apple): Fraunces fino, se equilibra en varias
   líneas y escala con el viewport. */
.ji-display {
  font-family: var(--ji-serif);
  font-weight: 300;
  font-size: clamp(2.4rem, 6vw, 4rem);
  line-height: 1.04;
  letter-spacing: -0.01em;
  color: var(--ji-text);
  text-wrap: balance;
}

/* Título de sección/módulo. */
.ji-title {
  font-family: var(--ji-serif);
  font-weight: 300;
  font-size: 1.5rem;
  line-height: 1.15;
  color: var(--ji-text);
  text-wrap: balance;
}

/* Subtítulo / texto de apoyo apagado. */
.ji-sub {
  font-family: var(--ji-ui);
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--ji-muted);
}

/* Tarjeta base: superficie + borde + radio de 16. */
.ji-card {
  background: var(--ji-surface);
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio);
}

.ji-card--elevada {
  background: var(--ji-surface-2);
}

/* Semánticos como color de texto (P&L, variaciones…). */
.ji-gain {
  color: var(--ji-gain);
}
.ji-loss {
  color: var(--ji-loss);
}

/* Foco visible accesible para controles del rediseño (teclado). */
.ji :focus-visible {
  outline: 2px solid var(--ji-gold);
  outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
   «Impuestos, en claro» (components/EnClaro.tsx)

   Solo dos reglas: lo demás va en línea, como el resto de la pantalla fiscal.
   Aquí están porque una necesita media query y la otra se repite en cinco
   sitios, que son justo las dos cosas que el estilo en línea no sabe hacer.
   --------------------------------------------------------------------------- */
.ec-grid2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

@media (max-width: 780px) {
  .ec-grid2 {
    grid-template-columns: 1fr;
  }
}

/* Rótulo de sección: versalita corta, el mismo tono que el resto de etiquetas. */
.ec-lbl {
  font-size: 11px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ji-muted);
  margin: 0;
}

/* ---------------------------------------------------------------------------
   Controles del universo de la Watchlist (components/UniversoGalaxias.tsx)

   Están aquí y no en línea porque un estilo en línea NO PUEDE tener `:hover`
   ni `:active`: por eso los botones se sentían muertos al tocarlos. Un control
   que no responde al dedo parece roto aunque funcione.
   --------------------------------------------------------------------------- */
.uni-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font: inherit;
  font-size: 13px;
  line-height: 1;
  color: #b9b3a6;
  background: rgba(14, 20, 30, 0.72);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 10px;
  cursor: pointer;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  transition:
    color 0.16s,
    border-color 0.16s,
    background 0.16s,
    transform 0.09s;
}

.uni-btn:hover {
  color: #f4f0e9;
  border-color: rgba(224, 178, 77, 0.45);
  background: rgba(24, 32, 46, 0.85);
}

/* El hundido al pulsar es lo que da la sensación de botón en una pantalla
   táctil, donde no hay `:hover` que valga. */
.uni-btn:active {
  transform: scale(0.93);
  border-color: rgba(224, 178, 77, 0.7);
}

.uni-btn:focus-visible {
  outline: 2px solid var(--ji-gold);
  outline-offset: 2px;
}

.uni-btn:disabled {
  opacity: 0.35;
  cursor: default;
  transform: none;
}

/* Cuadrados, para los de zoom y pantalla completa. */
.uni-btn--cuadro {
  width: 38px;
  height: 38px;
  font-size: 17px;
  padding: 0;
}

/* Con el dedo hace falta más blanco: 44 px es el mínimo cómodo. */
@media (pointer: coarse) {
  .uni-btn--cuadro {
    width: 44px;
    height: 44px;
  }
}

/* La pareja de zoom, unida en un solo bloque: son la misma función en dos
   sentidos, y separadas parecen dos controles distintos. */
.uni-zoom {
  display: flex;
  flex-direction: column;
  gap: 1px;
  border-radius: 11px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.12);
}

.uni-zoom .uni-btn {
  border: none;
  border-radius: 0;
}

.uni-zoom .uni-btn:first-child {
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

/* =====================================================================
   BARRA DE MÓDULOS · `.bm-*`
   =====================================================================

   La navegación de la aplicación, en todas las pantallas tras el login.
   Antes no existía: cada módulo tenía un «← Volver al inicio» y para ir de
   Cartera a Fiscal había que pasar por el hub y hacer scroll.
   ===================================================================== */

.bm {
  position: sticky;
  top: 0;
  z-index: 60;
  background: color-mix(in srgb, var(--ji-bg) 92%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--ji-border);
}
.bm-in {
  max-width: 1180px;
  margin-inline: auto;
  padding-inline: clamp(14px, 3vw, 28px);
  height: 58px;
  display: flex;
  align-items: center;
  gap: clamp(8px, 2vw, 22px);
}
.bm-marca {
  font-family: var(--ji-serif);
  font-size: 17px;
  letter-spacing: -0.01em;
  white-space: nowrap;
  color: var(--ji-text);
}
.bm-marca em {
  font-style: italic;
  color: var(--ji-gold);
}

.bm-modulos {
  display: flex;
  gap: 2px;
  margin-left: auto;
  overflow-x: auto;
  scrollbar-width: none;
}
.bm-modulos::-webkit-scrollbar {
  display: none;
}

.bm-mod {
  display: flex;
  align-items: center;
  gap: 8px;
  /* 40 px de alto real dentro de una barra de 58: pulsable sin engordarla. */
  min-height: 40px;
  padding: 0 13px;
  border-radius: var(--ji-radio-sm);
  text-decoration: none;
  white-space: nowrap;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--ji-muted);
  position: relative;
  transition: color 0.16s, background 0.16s;
}
.bm-mod:hover {
  color: var(--ji-text);
  background: var(--ji-surface);
}
.bm-mod.active,
.bm-mod[aria-current='page'] {
  color: var(--ji-text);
}
/* El activo se marca con un filete dorado abajo y no con un fondo: el fondo
   competiría con las tarjetas del hub y ensucia una barra que se ve en todas
   las pantallas. */
.bm-mod.active::after,
.bm-mod[aria-current='page']::after {
  content: '';
  position: absolute;
  left: 13px;
  right: 13px;
  bottom: -1px;
  height: 2px;
  border-radius: 2px 2px 0 0;
  background: var(--ji-gold);
}
.bm-mod svg {
  flex: none;
}

.bm-ctrl {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-left: 8px;
  padding-left: 12px;
  border-left: 1px solid var(--ji-border);
}
.bm-salir {
  font: inherit;
  font-size: 13px;
  color: var(--ji-muted);
  background: none;
  border: 0;
  padding: 0 4px;
  min-height: 40px;
  cursor: pointer;
  transition: color 0.16s;
}
.bm-salir:hover {
  color: var(--ji-text);
}

/*
   En móvil los módulos BAJAN, que es el patrón de cualquier aplicación de
   teléfono y aquí además es necesario: con la marca y los controles arriba,
   a los cinco iconos les quedaban 93 px y no cabían ni dos.

   Abajo tienen la fila entera, caen bajo el pulgar y de paso la parte de
   arriba se libera para el contenido. Mismo marcado, solo cambia el CSS.
*/
@media (max-width: 720px) {
  .bm-txt {
    display: none;
  }
  /*
    SIN `backdrop-filter` AQUÍ, y no es cosmético: un elemento con
    backdrop-filter crea contenedor de bloque para sus descendientes
    `position: fixed`, así que la barra de módulos se anclaba al fondo de ESTA
    barra en vez de al de la ventana —327 px de ancho y flotando arriba—.
    Arriba ya no hay nada que difuminar: solo quedan la marca y los controles.
  */
  .bm {
    background: var(--ji-bg);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
  .bm-modulos {
    position: fixed;
    inset: auto 0 0;
    margin: 0;
    justify-content: space-around;
    gap: 0;
    height: calc(56px + env(safe-area-inset-bottom, 0px));
    padding-bottom: env(safe-area-inset-bottom, 0px);
    align-items: center;
    background: color-mix(in srgb, var(--ji-bg) 94%, transparent);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border-top: 1px solid var(--ji-border);
    overflow: visible;
  }
  .bm-mod {
    flex: 1;
    justify-content: center;
    min-height: 48px;
    padding: 0;
    border-radius: 0;
  }
  .bm-mod:hover {
    background: none;
  }
  /*
    CUATRO FIJOS Y UN «MÁS» (16-sep-2026). Lo que no es de los cuatro sale de la
    barra y vive en la hoja; la regla está atada a `.bm-modulos` a propósito,
    porque los mismos módulos se vuelven a pintar DENTRO de la hoja y allí sí
    se ven.
  */
  .bm-modulos .bm-mod--extra {
    display: none;
  }
  /* Arriba el filete iba debajo; aquí, encima del borde superior. */
  .bm-mod.active::after,
  .bm-mod[aria-current='page']::after {
    top: 0;
    bottom: auto;
    left: 22%;
    right: 22%;
    border-radius: 0 0 2px 2px;
  }
  .bm-ctrl {
    margin-left: auto;
    gap: 6px;
    padding-left: 0;
    border-left: 0;
  }
  /* Que la barra de abajo no tape el final de ninguna pantalla. Va por la
     variable y no por `padding-bottom` directo para que `.ji-acceso` —donde esa
     barra NO existe— pueda cancelarla con el mismo número. */
  body {
    --ji-pad-abajo: calc(56px + env(safe-area-inset-bottom, 0px));
  }
}

/* =====================================================================
   HUB · panel de estado, `.hub-*`
   =====================================================================

   Reescrito el 26-ago-2026. Antes era una landing con login delante —titulares
   gigantes, descripción de cada módulo, cuatro secciones a pantalla completa—
   y le vendía el producto a quien ya estaba dentro. Ahora responde a «¿cómo
   voy?» y cabe en una pantalla.
   ===================================================================== */

.hub {
  /* Ancla del cielo, que va en posición absoluta detrás de todo. */
  position: relative;
  isolation: isolate;
  max-width: 1180px;
  margin-inline: auto;
  padding: clamp(18px, 3vh, 34px) clamp(14px, 3vw, 28px) 28px;
  display: flex;
  flex-direction: column;
  /* EXPLÍCITO Y NO POR DEFECTO: el CSS antiguo (`styles.css`) le mete
     `align-items: center` a este contenedor, y con eso la rejilla se encogía
     al ancho de su contenido —528 px en una pantalla de 1440— y salía a dos
     columnas en vez de cuatro. Es la colisión típica de tener dos sistemas de
     estilos conviviendo; se cierra aquí en vez de tocar el viejo. */
  align-items: stretch;
  /* Y POR LO MISMO, `text-align`. El CSS antiguo también le mete `center` a
     este contenedor. Con las tarjetas de antes no cantaba —eran cajas cortas—
     pero una lista de novedades centrada es ilegible: el ojo pierde el punto
     por donde bajar. Se vio en el navegador, no leyendo el código: en el
     fichero nuevo no hay ni un `text-align` que explique por qué pasaba. */
  text-align: left;
  gap: clamp(18px, 3vh, 28px);
}
.hub-aviso:empty {
  display: none;
}

/* --- Franja de estado ------------------------------------------------- */
.hub-estado {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: clamp(20px, 5vw, 54px);
  padding-bottom: clamp(18px, 3vh, 28px);
  border-bottom: 1px solid var(--ji-border);
}
.hub-jefe .k {
  font-family: var(--ji-serif);
  font-weight: 300;
  font-size: clamp(2.2rem, 6vw, 3.6rem);
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.hub-dato .k {
  font-family: var(--ji-mono);
  font-size: 1.12rem;
  font-variant-numeric: tabular-nums;
}
.hub-jefe .e,
.hub-dato .e {
  display: block;
  margin-top: 7px;
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ji-muted);
}
.hub-estado .positivo {
  color: var(--ji-gain);
}
.hub-estado .negativo {
  color: var(--ji-loss);
}

/* --- El cielo, detrás de toda la pantalla ------------------------------ */
/*
   PRIMERA VERSIÓN, DESCARTADA: la galaxia dentro de un panel de 150-250 px de
   alto, con las cifras encima. Javi: *«apenas se percibe ningún cambio»*, y con
   razón — `cover` sobre una caja de 7,5:1 recorta un clip 16:9 hasta dejar una
   tira donde no se distingue una galaxia de un degradado gris.

   Ahora es el fondo de la pantalla y las tarjetas son opacas. Eso además
   resuelve el contraste de casi todo el texto sin velo ninguno: lo único que
   toca el cielo son las cifras de arriba.
*/
.hub-hero {
  position: relative;
  z-index: 1;
}
/* El hub ya NO lleva vídeo (7-sep-2026): lleva `AnimatedBackground`, que se
   pinta solo en un canvas y trae su propio CSS en `styles.css`. Aquí vivían
   `.hub-galaxia` y su velo —dos degradados medidos contra los 36 fotogramas del
   clip— y se van con él. `FondoGalaxia` sigue existiendo: lo usa la pantalla de
   acceso. */

/* La franja de cifras, ya sobre el cielo: sin la línea de separación, que en un
   fondo con estrellas se lee como una raya y no como un canto. */
.hub-hero .hub-estado {
  position: relative;
  z-index: 1;
  padding-bottom: 0;
  border-bottom: none;
}

/* --- La corriente de novedades ----------------------------------------
   =====================================================================

   Sustituye a las cuatro tarjetas de módulo. Javi, el 7-sep-2026: *«ya tenemos
   las pestañas arriba, para qué quieres más accesos»*. Con ellas se van sus
   gráficos —la curva, el cielo, la escalera, el payoff— y el encendido al pasar
   el ratón que se había montado encima. Se borra en vez de dejarse tras un
   interruptor: CSS que no pinta nada solo estorba a quien venga después.

   Lo que queda es una LISTA, y una lista se lee de arriba abajo. Todo el diseño
   va detrás de eso: una columna, el día como cabecera, y a la izquierda una
   marca por clase para poder saltar con la vista a las cribas sin leer.
   ===================================================================== */

.hub-novedades {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 14px;
  /*
    MÁS ESTRECHA QUE LA PÁGINA, a propósito.
    ------------------------------------------------------------------
    A 1.180 px de ancho el titular queda en el centro y la hora a treinta
    centímetros, y para leer una fila hay que hacer un barrido de lado a lado.
    Una lista se lee en columna: se le da la medida de un texto y se acabó.
    La franja de patrimonio sí ocupa todo, y ese contraste ayuda — se ve que
    son dos cosas distintas.
  */
  max-width: 860px;
  width: 100%;
}

.hub-barra-filtros {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
}
.hub-barra-filtros h2 {
  font-family: var(--ji-serif);
  font-weight: 400;
  font-size: clamp(20px, 2vw, 26px);
  letter-spacing: -0.015em;
  /* Empuja los ajustes al otro extremo sin necesitar un contenedor de más. */
  margin-right: auto;
}
/* En pantalla estrecha el título manda solo y los filtros bajan enteros. */
@media (max-width: 620px) {
  .hub-barra-filtros h2 {
    flex: 1 0 100%;
    margin-right: 0;
  }
}

.hub-filtros {
  display: inline-flex;
  gap: 4px;
}
.hub-filtro {
  padding: 5px 11px;
  border: 1px solid var(--ji-border);
  border-radius: 999px;
  background: transparent;
  color: var(--ji-muted);
  font: inherit;
  font-size: 12.5px;
  cursor: pointer;
  transition: color 0.16s, border-color 0.16s, background 0.16s;
}
.hub-filtro:hover {
  color: var(--ji-text);
  border-color: var(--ji-border-strong);
}
/* El marcado ya lo dice con `aria-pressed`; esto es lo mismo, para el ojo. */
.hub-filtro.on {
  color: var(--ji-text);
  border-color: var(--ji-gold-solid);
  background: color-mix(in srgb, var(--ji-gold-solid) 12%, transparent);
}

.hub-ajustes-boton {
  padding: 5px 11px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: transparent;
  color: var(--ji-muted);
  font: inherit;
  font-size: 12.5px;
  cursor: pointer;
}
.hub-ajustes-boton:hover,
.hub-ajustes-boton[aria-expanded='true'] {
  color: var(--ji-text);
  border-color: var(--ji-border);
}

/* --- Ajustes ----------------------------------------------------------- */
.hub-ajustes {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px 18px;
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio);
  background: var(--ji-surface);
}
.hub-ajustes-txt {
  font-size: 12.5px;
  color: var(--ji-muted);
}
.hub-interruptor {
  display: grid;
  /* La casilla en su columna y el texto en la otra: así la explicación cae
     alineada con el rótulo y no debajo de la casilla. */
  grid-template-columns: auto 1fr;
  gap: 2px 10px;
  align-items: center;
  font-size: 13.5px;
  cursor: pointer;
}
.hub-interruptor input {
  grid-row: 1;
  accent-color: var(--ji-gold-solid);
}
.hub-interruptor span {
  grid-column: 2;
  font-size: 12px;
  color: var(--ji-muted);
}
.hub-ajustes-grupo {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
  border: 0;
  padding: 0;
}
.hub-ajustes-grupo legend {
  /* `float` y no `display:block`: un `legend` normal se sale del flujo flex y
     se queda encima de los botones en vez de a su lado. */
  float: left;
  padding-right: 10px;
  font-size: 12.5px;
  color: var(--ji-muted);
}

/* --- Los días ---------------------------------------------------------- */
.hub-dias {
  display: flex;
  flex-direction: column;
  gap: 20px;
  list-style: none;
  padding: 0;
}
.hub-dia {
  position: sticky;
  /* Se queda pegado arriba al pasar el día: en una lista larga es lo único que
     te dice de cuándo es lo que estás leyendo. El desplazamiento vive en la
     página, así que basta con `top`. */
  top: 0;
  z-index: 2;
  padding: 6px 0;
  background: var(--ji-bg);
  font-family: var(--ji-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ji-muted);
}
.hub-lista {
  display: flex;
  flex-direction: column;
  list-style: none;
  padding: 0;
}
.hub-novedad + .hub-novedad {
  border-top: 1px solid var(--ji-border);
}

.hub-novedad-cuerpo {
  display: grid;
  /* Marca · texto · hora. La hora en columna propia y con ancho fijo para que
     no baile de una fila a otra; la del medio es la que se estira. */
  grid-template-columns: 26px 1fr auto;
  align-items: baseline;
  gap: 4px 10px;
  padding: 11px 8px;
  border-radius: 8px;
  color: inherit;
  text-decoration: none;
  transition: background 0.16s;
}
a.hub-novedad-cuerpo:hover {
  background: var(--ji-surface-2);
}
a.hub-novedad-cuerpo:focus-visible {
  outline: 2px solid var(--ji-gold-solid);
  outline-offset: -2px;
}
.hub-marca {
  font-size: 13px;
  line-height: 1.4;
  color: var(--ji-gold);
  text-align: center;
}
.hub-texto {
  display: flex;
  flex-direction: column;
  gap: 3px;
  /* Sin esto, un titular largo estira la rejilla y empuja la hora fuera. */
  min-width: 0;
}
.hub-titulo {
  font-size: 14px;
  line-height: 1.4;
  color: var(--ji-text);
}
.hub-detalle {
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--ji-muted);
}
.hub-hora {
  font-family: var(--ji-mono);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--ji-muted);
  opacity: 0.8;
}

/* --- Cuando no ha pasado nada ------------------------------------------ */
/* No se rellena con nada: se dice, y se ofrece ensanchar la franja. */
.hub-vacio {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  padding: 26px 18px;
  border: 1px dashed var(--ji-border);
  border-radius: var(--ji-radio);
  font-size: 13.5px;
  color: var(--ji-muted);
}

.hub-pista {
  font-family: var(--ji-mono);
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--ji-muted);
  opacity: 0.75;
}

/* --- Administración ---------------------------------------------------- */
.hub-admin {
  position: relative;
  z-index: 1;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 20px;
  padding-top: 16px;
  border-top: 1px solid var(--ji-border);
}
.hub-admin a {
  font-size: 13px;
  color: var(--ji-muted);
  text-decoration: none;
  transition: color 0.18s;
}
.hub-admin a:hover {
  color: var(--ji-text);
}

@media (prefers-reduced-motion: reduce) {
  /*
    Aquí ya no queda casi nada que quitar: la portada pasó de cuatro gráficos
    que se encendían a una lista. Lo único que se mueve son los cambios de
    fondo al pasar por encima, y se van.
  */
  .hub-filtro,
  .hub-ajustes-boton,
  .hub-novedad-cuerpo,
  .hub-modulo {
    transition: none;
  }
}

/* La línea que se dibuja sola es de `vistasModulo`, pero su excepción de
   movimiento reducido vivía en el bloque del hub. Se conserva aquí. */
@media (prefers-reduced-motion: reduce) {
  .vm-linea {
    stroke-dashoffset: 0;
  }
  .visto .vm-linea {
    animation: none;
  }
}

/* =====================================================================
   PANEL DE ADMINISTRACIÓN · `.adm-*`
   =====================================================================

   Las dos pantallas de admin eran tablas y párrafos: correctas y ciegas. Las
   preguntas que traen aquí —«¿se ha actualizado la cartera?», «¿a quién le
   caduca?»— tienen respuesta en esos datos, pero había que leerlos fila a
   fila. Esto no añade ni un dato: le da forma a los que ya había.

   Sin canvas ni SVG: son barras y cuadros, y en CSS heredan el tema y se
   pueden comprobar leyendo el DOM.
   ===================================================================== */

/* Los cuatro tonos, una sola vez, como variable. */
.adm-t-bien { --adm-tono: var(--ji-gain); }
.adm-t-ojo { --adm-tono: var(--ji-gold); }
.adm-t-mal { --adm-tono: var(--ji-loss); }
.adm-t-neutro { --adm-tono: var(--ji-muted); }

/* --- Sello de frescura (Importaciones) ------------------------------- */
.adm-sello {
  border: 1px solid var(--ji-border);
  border-left: 3px solid var(--adm-tono, var(--ji-muted));
  border-radius: var(--ji-radio);
  background: var(--ji-surface);
  padding: 20px 22px;
  margin-bottom: 28px;
}
.adm-verde { --adm-tono: var(--ji-gain); }
.adm-ambar { --adm-tono: var(--ji-gold); }
.adm-rojo { --adm-tono: var(--ji-loss); }

.adm-sello-cab {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}
.adm-sello-cab h2 {
  margin: 0;
  font-family: var(--ji-serif);
  font-weight: 500;
  font-size: 1.4rem;
  letter-spacing: -0.02em;
  color: var(--ji-text);
}
.adm-sello-sub {
  margin: 4px 0 0;
  font-size: 14px;
  color: var(--ji-muted);
}
.adm-sello-sub strong {
  color: var(--ji-text);
  font-weight: 500;
}

.adm-punto {
  flex: none;
  width: 10px;
  height: 10px;
  margin-top: 9px;
  border-radius: 50%;
  background: var(--adm-tono, var(--ji-muted));
}
.adm-punto.vivo {
  box-shadow: 0 0 0 0 var(--adm-tono);
  animation: adm-latido 2.6s ease-out infinite;
}
@keyframes adm-latido {
  70% { box-shadow: 0 0 0 9px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}

.adm-lote-id {
  margin: 14px 0 0;
  font-family: var(--ji-mono);
  font-size: 12px;
  color: var(--ji-muted);
  overflow-wrap: anywhere;
}

.adm-cifras {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(84px, 1fr));
  gap: 10px;
  margin: 16px 0 0;
}
.adm-cifras div {
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio-sm);
  background: var(--ji-inset);
  padding: 10px 12px;
}
.adm-cifras dt {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--ji-muted);
}
.adm-cifras dd {
  margin: 2px 0 0;
  font-family: var(--ji-mono);
  font-size: 1.25rem;
  color: var(--ji-text);
  font-variant-numeric: tabular-nums;
}
.adm-cifras .cero dd {
  color: var(--ji-muted);
}

/* --- Tira de días ---------------------------------------------------- */
.adm-tira {
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid var(--ji-border);
}
.adm-tira-dias {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  margin-top: 8px;
}
.adm-dia {
  width: 15px;
  height: 15px;
  border-radius: 4px;
  border: 1px solid var(--ji-border);
  background: var(--ji-inset);
}
.adm-dia.finde {
  background: repeating-linear-gradient(
    -45deg,
    transparent 0 3px,
    var(--ji-border-strong) 3px 4px
  );
}
.adm-dia.lleno {
  background: var(--ji-blue);
  border-color: transparent;
}
.adm-dia.lleno.auto {
  background: var(--ji-gold-solid);
}

.adm-leyenda {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  align-items: center;
  margin-top: 12px;
  font-size: 12px;
  color: var(--ji-muted);
}
.adm-leyenda > span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.adm-leyenda .adm-dia {
  width: 11px;
  height: 11px;
  margin-right: 2px;
}
.adm-punto-leyenda {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--adm-tono, var(--ji-muted));
}

/* --- Chip de origen / estado ----------------------------------------- */
.adm-chip {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 999px;
  border: 1px solid var(--ji-border-strong);
  font-size: 11px;
  letter-spacing: 0.02em;
  color: var(--ji-muted);
  white-space: nowrap;
}
.adm-chip.auto,
.adm-chip.vivo {
  border-color: transparent;
  background: var(--ji-gold-solid);
  color: #0d1119;
  font-weight: 600;
}

/* --- Panorama de suscriptores ---------------------------------------- */
.adm-metricas {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: 10px;
  margin-bottom: 20px;
}
.adm-metrica {
  border: 1px solid var(--ji-border);
  border-top: 2px solid var(--adm-tono);
  border-radius: var(--ji-radio-sm);
  background: var(--ji-surface);
  padding: 14px 16px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.adm-metrica strong {
  font-family: var(--ji-serif);
  font-weight: 500;
  font-size: 2rem;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--adm-tono);
  font-variant-numeric: tabular-nums;
}
.adm-metrica span {
  font-size: 12px;
  color: var(--ji-muted);
}

.adm-barra {
  display: flex;
  height: 10px;
  border-radius: 999px;
  overflow: hidden;
  background: var(--ji-inset);
}
.adm-trozo {
  background: var(--adm-tono);
  min-width: 3px;
}

/* --- Calendario de renovaciones -------------------------------------- */
.adm-calendario {
  margin-top: 24px;
  padding-top: 18px;
  border-top: 1px solid var(--ji-border);
}
.adm-meses {
  display: grid;
  grid-template-columns: repeat(13, 1fr);
  gap: 4px;
  align-items: end;
  margin-top: 10px;
}
.adm-mes {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 5px;
  min-width: 0;
}
.adm-mes-n {
  font-family: var(--ji-mono);
  font-size: 11px;
  color: var(--ji-gold);
  min-height: 1em;
  font-variant-numeric: tabular-nums;
}
.adm-mes-barra {
  width: 100%;
  border-radius: 4px 4px 2px 2px;
  background: var(--ji-border-strong);
}
.adm-mes.con .adm-mes-barra {
  /* El segundo tramo se saca del propio token, no de un oro literal: si no,
     en tema claro el degradado arranca en el oro oscuro y termina en el
     brillante, y la barra se ve desvaída justo en la base. */
  background: linear-gradient(
    var(--ji-gold),
    color-mix(in srgb, var(--ji-gold) 45%, transparent)
  );
}
.adm-mes-etiqueta {
  font-size: 11px;
  color: var(--ji-muted);
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.adm-mes-etiqueta em {
  font-style: normal;
  opacity: 0.6;
}

/* --- Barra de progreso en tabla -------------------------------------- */
.adm-progreso {
  display: block;
  width: 72px;
  height: 5px;
  border-radius: 999px;
  background: var(--ji-inset);
  border: 1px solid var(--ji-border);
  overflow: hidden;
}
.adm-progreso-relleno {
  display: block;
  height: 100%;
  background: var(--adm-tono);
}
.adm-usos {
  display: block;
  font-variant-numeric: tabular-nums;
  margin-bottom: 4px;
}

/* --- Pestañas del panel ------------------------------------------------ */
/* Cada parte del panel de suscriptores en su pestaña: se ve una cosa cada vez
   y cabe sin scroll, en vez de una detrás de otra. */
.adm-pestanas {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
  margin-bottom: 22px;
  border-bottom: 1px solid var(--ji-border);
}
.adm-pestana {
  font: inherit;
  font-size: 13.5px;
  font-weight: 500;
  color: var(--ji-muted);
  background: none;
  border: 0;
  border-radius: var(--ji-radio-sm) var(--ji-radio-sm) 0 0;
  padding: 0 14px;
  min-height: 42px;
  cursor: pointer;
  position: relative;
  transition: color 0.16s, background 0.16s;
}
.adm-pestana:hover {
  color: var(--ji-text);
  background: var(--ji-surface);
}
.adm-pestana.on {
  color: var(--ji-text);
}
.adm-pestana.on::after {
  content: '';
  position: absolute;
  left: 12px;
  right: 12px;
  bottom: -1px;
  height: 2px;
  border-radius: 2px 2px 0 0;
  background: var(--ji-gold);
}

/* --- Acciones en lote y volcados --------------------------------------- */
.adm-acciones {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  margin: 18px 0 14px;
}
.adm-descargas {
  display: inline-flex;
  gap: 6px;
  /* Empujados al final: las descargas no compiten con activar o revocar. */
  margin-left: auto;
}

/* --- Cotejo lado a lado ------------------------------------------------ */
/* Una fila por persona, con lo que dice la web y lo que dice Substack. Antes
   eran seis cubos y para seguir un correo concreto había que buscarlo en los
   seis. */
.adm-web-activa {
  border-color: color-mix(in srgb, var(--ji-gain) 55%, transparent);
  color: var(--ji-gain);
}
.adm-web-pendiente {
  border-color: color-mix(in srgb, var(--ji-gold) 55%, transparent);
  color: var(--ji-gold);
}
.adm-web-revocada {
  border-color: color-mix(in srgb, var(--ji-loss) 55%, transparent);
  color: var(--ji-loss);
}
.adm-accion {
  font-size: 12px;
  color: var(--ji-muted);
}
.adm-acc-activar,
.adm-acc-reactivar {
  color: var(--ji-gain);
}
.adm-acc-revocar {
  color: var(--ji-loss);
}
.adm-acc-invitar,
.adm-acc-revisar {
  color: var(--ji-gold);
}

/* --- Tabla de importaciones ------------------------------------------- */
/* Los ids de lote son largos (`flex:2025-08-25:2026-08-24`) y empujaban la
   tabla fuera de la pantalla. Se acotan aquí; el id completo vive en el
   `title`, porque el id NO se puede cambiar: es la clave de idempotencia. */
.adm-celda-lote {
  max-width: 260px;
}
.adm-celda-lote strong {
  display: block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.adm-descarga {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 14px;
  margin-bottom: 18px;
}

@media (max-width: 640px) {
  .adm-meses {
    grid-template-columns: repeat(6, 1fr);
    row-gap: 12px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .adm-punto.vivo {
    animation: none;
  }
}

/* =====================================================================
   LANDING PÚBLICA · `.lp-*`
   =====================================================================

   La única pantalla que ve alguien sin cuenta. Portada del diseño hecho en
   Figma Make, traído a mano: sus 27 animaciones de `framer-motion` eran todas
   el mismo aparecer-al-entrar que ya tenía el hub, así que aquí se resuelven
   con `useRevelar` y una clase.

   Los anchos van por MEDIA QUERY y no por el `useIsMobile()` del prototipo,
   que medía `window.innerWidth` en JavaScript: eso repinta media landing en
   cada resize y, en el primer pintado, enseña la versión de escritorio en un
   móvil hasta que el efecto corre.
   ===================================================================== */

.lp {
  background: var(--ji-bg);
  color: var(--ji-text);
  overflow-x: hidden;
  /* Ancla del fondo de galaxia, que se posiciona contra la página entera y no
     contra una sección. Sin esto se colgaría del viewport. */
  position: relative;
  /*
   * SE COME EL RELLENO DEL BODY, igual que `.ji-acceso` (ver `styles.css`).
   *
   * El body lleva 1,5 rem por los cuatro lados y la landing vivía dentro. No se
   * notaba porque ese borde era del MISMO color que la portada: un marco
   * invisible sobre fondo liso.
   *
   * Con un vídeo detrás deja de ser invisible — se ve una franja oscura
   * rodeándolo y la portada no llega a los bordes de la ventana. Es el tipo de
   * fallo que solo aparece cuando cambias lo de al lado.
   *
   * Los márgenes negativos salen de las mismas variables que el relleno, así
   * que si alguien cambia una, esto sigue cuadrando.
   */
  margin: calc(-1 * var(--ji-pad-y)) calc(-1 * var(--ji-pad-x)) calc(-1 * var(--ji-pad-abajo));
}

/* --- Barra fija ------------------------------------------------------ */
.lp-nav {
  position: fixed;
  inset: 0 0 auto;
  z-index: 200;
  height: 64px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 clamp(24px, 6vw, 80px);
  transition: background 0.3s, border-color 0.3s;
  border-bottom: 1px solid transparent;
}
.lp-nav.rodado {
  background: color-mix(in srgb, var(--ji-bg) 85%, transparent);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border-bottom-color: var(--ji-border);
}
.lp-marca {
  font-family: var(--ji-serif);
  font-size: 19px;
  letter-spacing: -0.01em;
}
.lp-marca em,
.lp-h1 em {
  font-style: italic;
  color: var(--ji-gold);
}

/* --- Botones --------------------------------------------------------- */
.lp-btn {
  font-family: var(--ji-ui);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: -0.01em;
  /* Fijo y no `--ji-text`: encima siempre va el oro sólido, que se queda
     dorado brillante en los dos temas. */
  color: #0d1119;
  background: var(--ji-gold-solid);
  border: 0;
  border-radius: 10px;
  padding: 0 22px;
  text-decoration: none;
  /* 44 px de alto REAL, que es lo que cabe con holgura en una barra de 64.
     El área táctil llega a 48 con el `::after` de abajo, sin engordar el
     botón: se medía en 38 y eso en un pulgar se falla. */
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  position: relative;
  transition: filter 0.15s, transform 0.15s;
}
/* Extiende el área pulsable por encima y por debajo sin tocar el aspecto. */
.lp-btn::after {
  content: '';
  position: absolute;
  inset: -2px 0;
}
.lp-btn:hover {
  filter: brightness(1.08);
}
.lp-btn:active {
  transform: scale(0.97);
}
.lp-btn.grande {
  font-size: 16px;
  border-radius: 14px;
  padding: 0 52px;
  min-height: 56px;
}

.lp-fantasma {
  font-family: var(--ji-ui);
  font-size: 14px;
  color: var(--ji-muted);
  /* Medía 22 px de alto: el peor objetivo táctil de la página. El relleno
     vertical lo sube a 48 sin mover el subrayado, que sigue pegado al texto. */
  min-height: 48px;
  display: inline-flex;
  align-items: center;
  padding-inline: 8px;
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--ji-muted) 40%, transparent);
  text-underline-offset: 3px;
  transition: color 0.15s, text-decoration-color 0.15s;
}
.lp-fantasma:hover {
  color: var(--ji-text);
  text-decoration-color: color-mix(in srgb, var(--ji-text) 45%, transparent);
}

/* --- Portada --------------------------------------------------------- */
.lp-portada {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: clamp(100px, 14vh, 120px) clamp(24px, 6vw, 80px) 80px;
  background: radial-gradient(
      ellipse 80% 50% at 50% -10%,
      color-mix(in srgb, var(--ji-gold) 9%, transparent) 0%,
      transparent 70%
    ),
    var(--ji-bg);
  position: relative;
}
.lp-eyebrow {
  font-family: var(--ji-mono);
  font-size: 11px;
  color: var(--ji-gold);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  margin-bottom: 36px;
}
.lp-h1 {
  font-family: var(--ji-serif);
  font-size: clamp(48px, 9vw, 104px);
  font-weight: 300;
  line-height: 1;
  letter-spacing: -0.035em;
  margin-bottom: 16px;
}
.lp-lema {
  font-family: var(--ji-serif);
  font-size: clamp(26px, 5vw, 48px);
  font-weight: 300;
  font-style: italic;
  line-height: 1.15;
  letter-spacing: -0.02em;
  max-width: 640px;
  margin-bottom: 28px;
  text-wrap: balance;
}
.lp-entrada {
  font-size: clamp(16px, 2.2vw, 19px);
  color: var(--ji-muted);
  line-height: 1.68;
  max-width: 500px;
  margin-bottom: 52px;
}
/* La condición de acceso, en el color del texto y no en el apagado del
   párrafo. Es la única frase de esta sección que puede ahorrarle el viaje a
   alguien: en gris se lee como letra pequeña y justo esa no lo es. */
.lp-entrada strong {
  color: var(--ji-text);
  font-weight: 600;
}
.lp-cta {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
}
.lp-nota {
  font-size: 14px;
  color: var(--ji-muted);
  line-height: 1.6;
}

/* --- «En construcción»: lo que sale donde iría el botón de entrar ------
 *
 * Tiene que leerse como un ESTADO, no como algo que se pueda pulsar. Por eso
 * es un borde punteado y no el relleno dorado del botón: un cartel con la
 * misma pinta que un botón se intenta pulsar, y no pasa nada — que es la peor
 * forma de que no pase nada.
 */
.lp-obras {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 0 18px;
  border: 1px dashed var(--ji-gold);
  border-radius: 10px;
  font-family: var(--ji-ui);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ji-gold);
  /* Sin `cursor: pointer` y sin `:hover`: no es interactivo y no debe fingirlo. */
}
.lp-obras.grande {
  font-size: 15px;
  padding: 0 26px;
  min-height: 52px;
}
/* --- Y EL LIENZO DETRÁS DE LAS DOS, QUE NO SE VE DESDE AQUÍ -------------

   `.lp` y `.ji-acceso` cubren el viewport entero, así que en un navegador de
   escritorio el crema del `body` no asoma por ningún lado. Medido: la pantalla
   de registro en 375×812 mide 1.034 px y el documento entero también.

   En iOS NO basta. Al llegar al final y seguir arrastrando, Safari sigue
   moviendo la página y enseña un trozo de LIENZO —el color que el navegador
   propaga desde `html`, o desde `body` si `html` es transparente, que es el
   caso—. O sea: un destello crema al final de una pantalla que ha decidido ser
   oscura, justo en el gesto más común del móvil.

   Esto entra en la lista de cosas de iOS que no se ven desde aquí, con el zoom
   al enfocar un campo y `100vh` (`CLAUDE.md`). Javi tiene Android: se razona,
   se arregla y se anota.

   Va con `:has()` porque el color depende de QUÉ pantalla está montada, y eso
   `html` no lo sabe de otro modo sin que un componente le escriba encima. Si un
   navegador viejo no lo soporta, simplemente no aplica la regla y se vuelve al
   comportamiento de hoy: nada se rompe.
   ===================================================================== */
html:has(.lp),
html:has(.ji-acceso) {
  background: #0d1119;
}

/* --- LAS PANTALLAS DE ACCESO, TAMBIÉN OSCURAS ---------------------------

   Javi, el 7-sep-2026: *«la pantalla de login también quiero que no tenga fondo
   claro; solo oscuro y forzado, al igual que la landing»*.

   Y es coherente: `PantallaAcceso` —login, registro, recuperar, contraseña
   nueva y la pantalla de cuenta pendiente— lleva el mismo vídeo de galaxia que
   la portada. Mismo problema y misma solución: en tema claro el texto se
   pintaba oscuro sobre el cielo.

   Además es lo que ve alguien que llega desde el Substack y aún no ha entrado:
   sigue siendo escaparate, no pantalla de trabajo. El tema del sistema empieza
   a mandar DENTRO, que es donde hay tablas y cifras que se miran de noche.

   Los tokens son los mismos que los de `.lp`, y a propósito: la puerta y el
   escaparate tienen que ser la misma pieza. Si algún día cambia la paleta
   oscura, estos dos bloques cambian juntos.
   ===================================================================== */
.ji-acceso {
  --ji-bg: #0d1119;
  --ji-surface: #141a24;
  --ji-surface-2: #1a2130;
  --ji-inset: #0f151e;
  --ji-border: rgba(255, 255, 255, 0.08);
  --ji-border-strong: rgba(255, 255, 255, 0.14);
  --ji-text: #f4f0e9;
  --ji-muted: #868b99;
  --ji-gold: #e0b24d;
  --ji-gold-solid: #e0b24d;
  --ji-gain: #26a69a;
  --ji-loss: #ef5350;
  --ji-blue: #5b8dee;
  --ji-purple: #a855f7;

  color-scheme: dark;
  background: var(--ji-bg);
  color: var(--ji-text);
}

/* --- LA PORTADA ES OSCURA, DIGA LO QUE DIGA EL SISTEMA ------------------
   =====================================================================

   Un suscriptor la abrió desde el móvil el 7-sep-2026 y la vio con el TEXTO
   NEGRO sobre el cielo estrellado, ilegible. A Javi le había pasado abriéndola
   desde Substack.

   ── Por qué pasaba ───────────────────────────────────────────────────

   `theme.ts` respeta `prefers-color-scheme`. Correcto para la aplicación: quien
   tiene el móvil en claro entra y la web está en claro. Pero la portada lleva
   un vídeo de galaxia y un campo de estrellas, y los dos son oscuros y SOLO
   oscuros. Al aplicarse `:root[data-theme='light']`, el texto cogía `#1c1a17` y
   el cielo seguía siendo un cielo.

   Nadie del equipo lo vio nunca porque quien desarrolla tiene el sistema en
   oscuro, y desde Substack se abre en el navegador del sistema, que sí respeta
   la preferencia del teléfono.

   ── La decisión, y es de Javi ────────────────────────────────────────

   *«Que en la landing no se respete el fondo del sistema. Si es claro, que se
   joda, tiene que ser oscuro.»*

   Y se sostiene: la portada es un ESCAPARATE con una dirección de arte, no una
   pantalla de trabajo. No hay versión clara que hacer —el fondo es un vídeo de
   estrellas—, así que una landing en papel no sería la misma página con otros
   colores, sería otra página. El hub, que sí es pantalla de trabajo, se queda
   respetando el tema y por eso lleva partículas en vez de vídeo.

   Por lo mismo, el conmutador de tema no se enseña aquí (ver `App.tsx`): un
   botón que no hace nada es peor que no tener botón.

   ── Cómo funciona ────────────────────────────────────────────────────

   Redeclarar los tokens EN `.lp` gana sobre `:root[data-theme='light']` aunque
   tenga menos especificidad: las propiedades personalizadas se resuelven por
   elemento, y el valor puesto aquí es el que heredan todos sus descendientes.
   ===================================================================== */
.lp {
  --ji-bg: #0d1119;
  --ji-surface: #141a24;
  --ji-surface-2: #1a2130;
  --ji-inset: #0f151e;
  --ji-border: rgba(255, 255, 255, 0.08);
  --ji-border-strong: rgba(255, 255, 255, 0.14);
  --ji-text: #f4f0e9;
  --ji-muted: #868b99;
  --ji-gold: #e0b24d;
  --ji-gold-solid: #e0b24d;
  --ji-gain: #26a69a;
  --ji-loss: #ef5350;
  --ji-blue: #5b8dee;
  --ji-purple: #a855f7;

  /* Para que las barras de desplazamiento y los campos del navegador vayan a
     juego y no salgan claros sobre el cielo. */
  color-scheme: dark;

  /* Fondo explícito: si el sistema está en claro, el `body` es papel y asomaría
     por debajo del contenido. */
  background: var(--ji-bg);
  color: var(--ji-text);
  /* `100vh` primero como reserva y `100dvh` encima: en el Safari de iOS `100vh`
     vale la altura SIN la barra de direcciones, o sea más de lo que se ve. */
  min-height: 100vh;
  min-height: 100dvh;
}

/* --- Contador de plazas de la oferta ------------------------------------
   Barra + una línea. Se enseña lo que QUEDA, nunca lo vendido: con tres
   clientes, «3 de 50» dice «no compra nadie». La barra sí se llena por la
   izquierda, que es como se lee una barra — pero el número que la acompaña es
   el que falta. */
.lp-plazas {
  margin-top: clamp(18px, 3vh, 28px);
  display: flex;
  flex-direction: column;
  gap: 8px;
  /* La medida de la llamada, no la de la página: pegada al botón. */
  max-width: 420px;
}
.lp-plazas-riel {
  height: 4px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--ji-text) 14%, transparent);
  overflow: hidden;
}
.lp-plazas-lleno {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--ji-gold-solid);
  /* Con cero plazas cogidas la barra mide 0 y no se ve nada, que es correcto:
     no hay nada que enseñar todavía. */
  transition: width 0.6s ease;
}
.lp-plazas-txt {
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--ji-muted);
}
.lp-plazas-txt strong {
  color: var(--ji-text);
  font-weight: 500;
}

@media (prefers-reduced-motion: reduce) {
  .lp-plazas-lleno {
    transition: none;
  }
}

.lp-obras-texto {
  max-width: 34rem;
  margin: 0 auto;
  font-size: 15px;
  line-height: 1.65;
  color: var(--ji-muted);
}
.lp-obras-texto strong {
  color: var(--ji-text);
}

/* Guía de scroll: una línea que baja. Es adorno, así que no lleva texto y
   desaparece si el sistema pide menos movimiento. */
.lp-pista-scroll {
  position: absolute;
  bottom: 36px;
  left: 50%;
  width: 1px;
  height: 40px;
  background: linear-gradient(
    to bottom,
    color-mix(in srgb, var(--ji-gold) 50%, transparent),
    transparent
  );
}
@keyframes lp-vaiven {
  0%,
  100% {
    transform: translate(-50%, 0);
  }
  50% {
    transform: translate(-50%, 7px);
  }
}

/* --- Secciones ------------------------------------------------------- */
.lp-que,
.lp-modulo,
.lp-cierre {
  padding: clamp(80px, 12vh, 128px) clamp(24px, 6vw, 80px);
}
/*
 * Las secciones con superficie propia van SEMITRANSPARENTES.
 *
 * Es la pieza que hace que el campo de estrellas exista: va detrás de todo, así
 * que cualquier fondo opaco lo apaga por completo en su tramo. Con un fondo
 * liso eso no se notaba —negro sobre negro—, pero con estrellas detrás la
 * página se encendería y se apagaría por franjas.
 *
 * El 92 % deja pasar lo justo: la superficie sigue leyéndose como escalón sobre
 * el fondo y las estrellas siguen ahí, más tenues. Es el mismo criterio que con
 * el vídeo de la portada — el resplandor dorado se quedó y el relleno opaco se
 * fue.
 */
.lp-que,
.lp-modulo.alt {
  background: color-mix(in srgb, var(--ji-surface) 92%, transparent);
}
.lp-que > *,
.lp-cierre > * {
  max-width: 680px;
  margin-inline: auto;
}
.lp-cierre {
  text-align: center;
  padding-bottom: clamp(100px, 16vh, 140px);
}

.lp-h2 {
  font-family: var(--ji-serif);
  font-size: clamp(30px, 4vw, 44px);
  font-weight: 300;
  line-height: 1.1;
  letter-spacing: -0.025em;
  margin-bottom: 24px;
  text-wrap: balance;
}
.lp-h2.grande {
  font-size: clamp(34px, 6vw, 56px);
}
.lp-cuerpo {
  font-size: clamp(16px, 1.6vw, 18px);
  color: var(--ji-muted);
  line-height: 1.72;
}
.lp-cuerpo + .lp-cuerpo {
  margin-top: 20px;
}

.lp-rejilla {
  max-width: 1160px;
  margin-inline: auto;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 80px;
  align-items: center;
}
/* En los impares el texto va a la derecha. Solo en escritorio: en móvil, con
   una sola columna, el texto SIEMPRE va primero — invertirlo dejaría el
   gráfico antes de saber de qué habla. */
.lp-rejilla.vuelta .lp-texto {
  order: 1;
}

/* =====================================================================
   Ritmo de las secciones de módulo
   ---------------------------------------------------------------------
   Los cuatro módulos iban en rejilla 50/50 con el texto centrado en
   vertical. Estaba bien resuelto, pero repetido cuatro veces es el patrón
   editorial más previsible que existe: después del segundo, el lector ya
   sabe cómo van a ser el tercero y el cuarto.

   Probado primero en uno solo (3-sep-2026) y extendido a los cuatro con el
   visto bueno de Javi. Cambia tres cosas, ninguna toca el contenido:

   1. COLUMNAS DESIGUALES (0.82 / 1.18). El texto es una frase corta y una
      descripción; el gráfico es lo que hay que mirar. Dividir a la mitad da
      el mismo peso a dos cosas que no lo tienen.
   2. EL TEXTO SE APOYA ABAJO (`align-items: end`), en la misma línea que la
      base del gráfico en vez de flotar en su centro. Es lo que hace que una
      composición parezca compuesta: los elementos se apoyan en algo.
   3. MÁS AIRE ENTRE COLUMNAS, para que la asimetría se lea como decisión y
      no como descuadre.

   No hay sangrado fuera del contenedor a propósito: sería lo más vistoso y
   es justo lo que mete desbordes horizontales, que la pasada de WebKit
   vigila y que en móvil no se perdonan.
   ===================================================================== */
.lp-modulo .lp-rejilla {
  grid-template-columns: 0.82fr 1.18fr;
  gap: 104px;
  align-items: end;
}
/*
 * Y en las alternas hay que DARLE LA VUELTA a las columnas, no solo al orden.
 *
 * `.vuelta` mueve el texto a la segunda posición con `order: 1`. La rejilla
 * coloca por orden visual, así que con 0.82/1.18 fijo el gráfico caía en la
 * columna ESTRECHA y el texto en la ancha: justo al revés de lo que se busca,
 * y en dos de las cuatro secciones.
 *
 * Se ve solo al aplicarlo a más de una. Con la prueba en una sola sección no
 * salía, porque esa es par.
 */
.lp-modulo .lp-rejilla.vuelta {
  grid-template-columns: 1.18fr 0.82fr;
}
/* El texto pega abajo, así que el respiro va por arriba y no repartido. */
.lp-modulo .lp-texto {
  padding-bottom: 6px;
}

/* --- Variante ANCHA: texto arriba repartido, lienzo a todo lo ancho -----

   Para el módulo cuya vista previa es una grabación de la pantalla entera. En
   media columna se quedó en 589 px —el 0,308 del original— y ahí su título
   bajaba a 7,4 px y las griegas a 4,6: se veía que algo se mueve y nada más.
   A todo lo ancho el hueco pasa a ~1.368 px.

   Y el texto no se apila sin más: se REPARTE. Rótulo y titular a la izquierda,
   párrafo a la derecha, apoyados en la misma línea de abajo. Apilado en una
   sola columna, un titular de cuatro palabras dejaría media pantalla vacía
   antes de llegar al vídeo.

   VA AQUÍ ABAJO Y CON `.lp-modulo` DELANTE, y las dos cosas hacen falta. La
   primera versión usó `.lp-rejilla.ancho` a secas y **no aplicó**: empata en
   especificidad con `.lp-modulo .lp-rejilla` —dos clases cada una— y esa
   estaba más abajo, así que ganaba. Medido: la rejilla salía a 1.400 px de
   ancho, o sea que el `max-width` sí entraba, pero seguía partida en dos
   columnas de 531 y 765 px. Es el mismo error que ya está escrito para las
   consultas de medios, del revés: estar antes tampoco sirve de nada. */
.lp-modulo .lp-rejilla.ancho {
  /* Más que los 1.160 del resto, a propósito: cada píxel de ancho aquí es
     legibilidad del vídeo, que es la única vista que se lee de verdad. */
  max-width: 1400px;
  grid-template-columns: minmax(0, 1fr);
  gap: 40px;
  align-items: start;
}
.lp-modulo .lp-rejilla.ancho .lp-texto {
  display: grid;
  /* El titular manda un pelín sobre el párrafo: es serif grande contra texto
     corrido, y a la mitad exacta el titular parte en tres líneas y el párrafo
     en dos, que descuadra la línea de abajo. */
  grid-template-columns: minmax(0, 1.08fr) minmax(0, 1fr);
  gap: 10px 64px;
  /*
   * POR ARRIBA Y NO POR ABAJO.
   *
   * El resto de módulos apoya el texto abajo (`align-items: end`) y ahí
   * funciona, porque compara una columna de texto con un gráfico alto. Aquí se
   * comparan DOS TEXTOS de distinta longitud: el titular ocupa una línea y el
   * párrafo tres, así que cuadrar las bases empujaba el titular hacia abajo y
   * dejaba un hueco muerto entre el rótulo y él, con el párrafo flotando arriba.
   *
   * Alineados por arriba, las dos primeras líneas arrancan a la misma altura,
   * que es lo que el ojo lee como «repartido».
   */
  align-items: start;
  padding-bottom: 0;
}
.lp-modulo .lp-rejilla.ancho .ji-eyebrow {
  grid-column: 1;
  grid-row: 1;
}
.lp-modulo .lp-rejilla.ancho .lp-h2 {
  grid-column: 1;
  grid-row: 2;
  margin: 0;
}
.lp-modulo .lp-rejilla.ancho .lp-cuerpo {
  grid-column: 2;
  grid-row: 2;
  margin: 0;
}

/* EL TECHO VA EN ALTURA, NO EN ANCHURA, y esa es toda la gracia.

   Las tres grabaciones tienen formas distintas: la de opciones es 2,41:1 y las
   de cartera y fiscal 1,38:1. A todo lo ancho (1.366 px) la de opciones queda
   en 567 px de alto —cómoda— y las otras dos en 988, o sea el 99 % de una
   ventana de 1.000: pasan de no leerse a no caber, que es el mismo fallo por el
   otro lado.

   Acotando por `max-height` la regla se ajusta sola a cada forma: la de
   opciones ni la nota, porque ya cabe, y las altas se encogen hasta entrar
   dejando aire. Con `width: auto` la proporción se conserva y con los márgenes
   automáticos se queda centrada dentro del lienzo.

   78vh y no 100: por debajo tiene que caber la nota de los datos de demo, y por
   arriba se agradece ver dónde acaba la sección. */
.lp-modulo .lp-rejilla.ancho .vm-video {
  max-height: 78vh;
  width: auto;
  max-width: 100%;
  margin-inline: auto;
}

/* Y LA TARJETA SE AJUSTA AL VÍDEO, no al hueco.

   Javi: *«los laterales de los vídeos se ve un fondo distinto, queda raro»*.
   Y era eso: al acotar el vídeo por altura, se quedó en 1.092 px dentro de un
   lienzo de 1.366 — y `.lp-lienzo` trae su propio degradado y su borde, así que
   sobraban 137 px de tarjeta a cada lado, de otro color que el vídeo.

   Con `fit-content` la tarjeta mide lo que mide su contenido y el marco vuelve
   a ceñirse. El relleno de 16 px se queda: es lo que hace que se lea como
   tarjeta y no como un vídeo suelto. */
.lp-modulo .lp-rejilla.ancho .lp-lienzo {
  width: fit-content;
  max-width: 100%;
  margin-inline: auto;
}
/* La nota, alineada con la tarjeta y no con la sección: si la tarjeta se
   estrecha y centra, una nota pegada al margen izquierdo se lee como si fuera
   de otra cosa. */
.lp-modulo .lp-rejilla.ancho .lp-nota-demo {
  text-align: center;
}

/*
 * EL RECORTE MANDA SOBRE EL TAMANO. La del fiscal era una tira de 1130x150,
 * o sea 7,53:1, y a media columna se quedaba en 59 px de alto contra un bloque
 * de texto de 250. Javi: *«queda raro, la imagen tan pequeña y el texto
 * enorme»*. No era un problema de escala —ya iba al 100 % del hueco— sino de
 * proporcion: un recorte muy ancho y muy bajo no puede llenar una caja.
 *
 * Se rehizo encuadrando el modulo ENTERO (1156x622, 1,86:1): sus tres
 * pestañas, el aviso de beta, la promesa de privacidad y el selector foral.
 * Sigue sin una sola cifra, que es la regla de esta pagina.
 *
 * Capturas reales de los modulos, en vez de maquetas dibujadas a mano.
 *
 * Se recortan de grabaciones del modulo en MODO DEMO y se sirven en WebP a
 * resolucion nativa: 13-14 KB cada una. Bloque redondeado y sin marco propio,
 * porque el marco ya lo pone .
 */
/* La grabación del módulo. Mismo trato que una captura: es contenido de la
   tarjeta, no decoración de fondo. `object-fit: contain` y no `cover` —al
   revés que la galaxia de la portada— porque aquí recortar se comería el
   título o los ejes, que es justo lo que se quiere enseñar. */
.vm-video {
  display: block;
  width: 100%;
  height: auto;
  border-radius: calc(var(--ji-radio) - 6px);
  object-fit: contain;
  background: var(--ji-bg);
  user-select: none;
  /* No es un reproductor: no hay controles y no debe capturar el puntero. El
     botón de ampliar va por encima y sí los captura. */
  pointer-events: none;
}

/* El marco del vídeo: existe SOLO para colgar de él el botón de ampliar.

   `width: fit-content` es la línea delicada. La tarjeta que lo contiene se
   dimensiona con `fit-content` sobre el vídeo (ver `.lp-lienzo` más arriba), y
   un contenedor que se estirase al hueco disponible rompería ese ajuste y
   devolvería las franjas de otro color a los lados que Javi ya reportó una vez.

   Los selectores que dimensionan el vídeo —`.lp-modulo .lp-rejilla.ancho
   .vm-video`— usan combinadores de descendiente, no de hijo, así que siguen
   aplicando con el marco en medio. Comprobado midiendo antes y después. */
.vm-marco {
  position: relative;
  display: block;
  width: fit-content;
  max-width: 100%;
  margin-inline: auto;
}

/* «Ampliar»: discreto sobre el vídeo, y en la esquina que no tapa nada.

   Nace del móvil —una interfaz de escritorio en 350 px no se lee— pero se
   queda en escritorio: el vídeo también se ve pequeño dentro de la tarjeta. */
.vm-ampliar {
  position: absolute;
  right: 10px;
  bottom: 10px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  /* 40 px de alto real: por debajo de eso se falla con el pulgar. */
  min-height: 40px;
  padding: 0 14px;
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 999px;
  background: rgba(10, 14, 22, 0.72);
  backdrop-filter: blur(6px);
  color: #f2f4f8;
  font-family: var(--ji-ui);
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.vm-ampliar:hover {
  background: rgba(10, 14, 22, 0.9);
  border-color: var(--ji-gold);
}
.vm-ampliar:focus-visible {
  outline: 2px solid var(--ji-gold);
  outline-offset: 2px;
}

.vm-captura {
  display: block;
  width: 100%;
  height: auto;
  border-radius: calc(var(--ji-radio) - 6px);
  /* Sin seleccion ni arrastre: es una ilustracion, no un fichero que ofrecer. */
  user-select: none;
}

.lp-lienzo {
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio);
  background: linear-gradient(var(--ji-surface-2), var(--ji-surface));
  padding: 16px;
  position: relative;
}
.lp-modulo.alt .lp-lienzo {
  background: linear-gradient(var(--ji-inset), var(--ji-surface-2));
}
/* Qué hay dentro de cada módulo, y qué no. Debajo del vídeo.

   TIPOGRAFÍA DE LA CASA, sin inventar ninguna: el rotulillo usa las mismas
   variables que `.ji-eyebrow` —mono, 11 px, versalita espaciada— pero en gris y
   no en oro, porque el oro ya lo lleva el nombre del módulo doce líneas más
   arriba y dos rótulos dorados en la misma sección compiten entre ellos.

   La caja se ciñe al ancho del lienzo con `max-width` heredado del contenedor,
   así que la lista arranca donde arranca el vídeo. */
.lp-inventario {
  margin-top: 26px;
}
.lp-inventario-tit {
  margin: 0 0 14px;
  font-family: var(--ji-mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ji-muted);
}

/* La lista, en dos columnas. A todo lo ancho una sola columna dejaría seis
   líneas cortas con medio metro de blanco a la derecha; en dos, el bloque tiene
   la misma densidad que el resto de la página.

   Guiones y no puntos: son piezas de una herramienta, no una lista de la
   compra, y el guión pesa menos en una página que ya tiene mucho texto. */
.lp-dentro {
  list-style: none;
  margin: 0;
  padding: 0;
  /* Explícito: la landing centra por herencia y una lista centrada deja los
     bordes izquierdos en zigzag. */
  text-align: left;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 9px 48px;
}
.lp-dentro li {
  position: relative;
  padding-left: 18px;
  font-family: var(--ji-ui);
  font-size: 14px;
  line-height: 1.5;
  color: var(--ji-text);
}
.lp-dentro li::before {
  content: '—';
  position: absolute;
  left: 0;
  color: var(--ji-gold);
}

/* Y lo que NO hay, separado por una raya y en gris.

   Separado porque es de otra naturaleza: lo de arriba es lo que te llevas y
   esto es lo que no. Juntarlo en la misma lista lo escondería, y esconderlo es
   exactamente lo contrario de para lo que está. */
.lp-fuera {
  margin: 18px 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--ji-border);
  font-family: var(--ji-ui);
  font-size: 13px;
  line-height: 1.55;
  color: var(--ji-muted);
}

/* El enlace a una ficha publicada entera (21-sep-2026). Es lo único de la
   landing que se puede TOCAR antes de suscribirse, así que se ve como un
   botón y no como una nota al pie. */
.lp-muestra {
  display: inline-block;
  margin-top: 14px;
  padding: 9px 15px;
  border: 1px solid var(--ji-gold);
  border-radius: 999px;
  font-family: var(--ji-ui);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ji-gold);
  text-decoration: none;
  transition: background 0.15s ease;
}
.lp-muestra:hover,
.lp-muestra:focus-visible {
  background: color-mix(in srgb, var(--ji-gold) 14%, transparent);
}

@media (max-width: 860px) {
  .lp-dentro {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* La ficha, cuando se llega a ella con el universo a pantalla completa.

   Mismo mecanismo que usa el mapa: `position: fixed` y NO la API de pantalla
   completa del navegador, que no existe para elementos sueltos en Safari de
   iOS. El scroll de la página lo bloquea `Watchlist`, que es quien tiene el
   estado; aquí la ficha hace el suyo.

   Se le pone fondo opaco a propósito: sin él se transparentaría la página de
   debajo, que sigue montada. */
.wl-ficha-pc {
  position: fixed;
  inset: 0;
  z-index: 50;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--ji-bg);
  padding: clamp(16px, 3vw, 32px);
}

/* Botón de tapar importes. Mismo peso visual que el sello de importación, que
   es su vecino: los dos hablan de CÓMO se están viendo los números, no de los
   números. */
.ji-privacidad {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--ji-ui);
  font-size: 11px;
  letter-spacing: 0.04em;
  padding: 5px 11px;
  border-radius: 999px;
  color: var(--ji-muted);
  background: var(--ji-surface-2);
  border: 1px solid var(--ji-border);
  cursor: pointer;
}
.ji-privacidad:hover {
  color: var(--ji-text);
}
/* Encendido en oro y no en verde: no es un estado «correcto», es un estado
   ACTIVO que conviene no olvidarse puesto. */
.ji-privacidad.on {
  color: var(--ji-gold);
  background: color-mix(in srgb, var(--ji-gold) 12%, transparent);
  border-color: color-mix(in srgb, var(--ji-gold) 45%, transparent);
}
.ji-privacidad:focus-visible {
  outline: 2px solid var(--ji-gold);
  outline-offset: 2px;
}

/* La nota bajo el lienzo, con todas las letras.

   Idea de Javi, y resuelve limpiamente lo que la pastilla de la esquina solo
   insinúa: en las vistas que enseñan EUROS no basta con un «datos de ejemplo»
   en minúscula, porque quien ve 121.850 € y una curva subiendo asume que está
   viendo la cartera de alguien.

   Fuera del lienzo a propósito: dentro competiría con lo que hay que leer y
   encima taparía parte del vídeo. */
.lp-nota-demo {
  margin: 10px 2px 0;
  font-family: var(--ji-ui);
  font-size: 12px;
  line-height: 1.5;
  color: var(--ji-muted);
}

/* Etiqueta permanente en las dos vistas que enseñan una cartera y una lista de
   empresas. No es humildad: son datos de demostración, y decirlo evita que
   nadie los confunda con la cartera real, que de aquí no sale. */
.lp-marca-demo {
  position: absolute;
  top: 10px;
  right: 12px;
  font-family: var(--ji-mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ji-muted);
  background: color-mix(in srgb, var(--ji-bg) 70%, transparent);
  border: 1px solid var(--ji-border);
  border-radius: 999px;
  padding: 3px 9px;
}

/* --- Cierre ---------------------------------------------------------- */
.lp-adios {
  font-family: var(--ji-serif);
  font-size: clamp(52px, 8vw, 92px);
  font-weight: 300;
  font-style: italic;
  line-height: 1.05;
  letter-spacing: -0.035em;
  margin-bottom: 24px;
}
.lp-firma {
  margin-top: clamp(80px, 12vh, 100px);
  padding-top: 48px;
  border-top: 1px solid var(--ji-border);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.lp-firma p {
  font-family: var(--ji-serif);
  font-size: clamp(22px, 3vw, 28px);
  font-weight: 300;
  font-style: italic;
  color: var(--ji-muted);
  line-height: 1.4;
}
.lp-firma .lp-firma-nombre {
  font-family: var(--ji-mono);
  font-size: 13px;
  font-style: normal;
  color: var(--ji-gold);
  letter-spacing: 0.12em;
}

/* --- Tira de anti-posicionamiento ------------------------------------ */
/* Lo que NO es, dicho arriba y no enterrado en un párrafo. */
.lp-sin {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px 22px;
  list-style: none;
  margin: 0 0 44px;
  padding: 0;
  font-family: var(--ji-mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ji-muted);
}
.lp-sin li {
  position: relative;
}
.lp-sin li + li::before {
  content: '·';
  position: absolute;
  left: -13px;
  color: var(--ji-gold);
}

/* --- Cifras que sitúan ------------------------------------------------ */
.lp-cifras {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
  max-width: 1000px;
  margin-inline: auto;
  padding: clamp(52px, 8vh, 88px) clamp(24px, 6vw, 80px);
  border-bottom: 1px solid var(--ji-border);
}
.lp-cifra {
  text-align: center;
}
.lp-cifra strong {
  display: block;
  font-family: var(--ji-serif);
  font-weight: 300;
  font-size: clamp(2rem, 5vw, 3.1rem);
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--ji-gold);
  font-variant-numeric: tabular-nums;
}
.lp-cifra span {
  display: block;
  margin-top: 8px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--ji-muted);
}

/* --- Secciones de texto: el mismo aire y la misma medida --------------
   Los cuatro bloques del proceso (7-sep-2026) entran en esta lista y no
   traen padding propio: si cada sección se pusiera el suyo, acabarían
   descuadradas entre sí. Se vio en el navegador — nacieron fuera de la lista
   y salían pegadas al canto mientras las demás respiraban. */
.lp-filtro,
.lp-metodo,
.lp-faq,
.lp-pasos-bloque,
.lp-errores,
.lp-principios,
.lp-tuyas {
  padding: clamp(80px, 12vh, 128px) clamp(24px, 6vw, 80px);
}
.lp-filtro > *,
/* LAS CUATRO SECCIONES NUEVAS VAN CENTRADAS.
   Javi, mirándolas: *«deberías centrar los textos; quedan la mayoría muy a la
   izquierda y a la derecha queda un enorme espacio vacío»*. Y es verdad: el
   bloque de 900 px sí estaba centrado en la página, pero el texto DENTRO iba a
   la izquierda, así que un titular corto dejaba medio ancho en blanco a su
   derecha. Y el resto de la portada —titular, entradilla, cifras— va centrado,
   así que estas cuatro cantaban.

   Se centra lo que es TEXTO SUELTO: rótulo, titular y entradilla. Lo que es un
   OBJETO —las cajas de los principios, la cita— se queda alineado a la
   izquierda dentro de sí mismo, que es como se lee un párrafo dentro de una
   caja. Centrar también eso dejaría los bordes en zigzag, que es justo el
   defecto que acabamos de quitar de las listas. */
.lp-pasos-bloque,
.lp-errores,
.lp-principios,
.lp-tuyas {
  text-align: center;
}
.lp-pasos-bloque .lp-entrada,
.lp-errores .lp-entrada,
.lp-principios .lp-entrada,
.lp-tuyas .lp-entrada {
  /* La entradilla, centrada y con su medida: sin `margin-inline: auto` se
     quedaría pegada a la izquierda de su caja de 500 px. */
  margin-inline: auto;
  max-width: 58ch;
}

.lp-metodo > *,
.lp-faq > *,
.lp-pasos-bloque > *,
.lp-errores > *,
.lp-principios > *,
.lp-tuyas > * {
  max-width: 900px;
  margin-inline: auto;
}
.lp-metodo {
  background: var(--ji-surface);
}

.lp-columnas {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
  margin-top: 40px;
}
.lp-columna {
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio);
  background: var(--ji-surface);
  padding: 26px 28px;
}
/* El tono lo lleva el filete de arriba, no el texto: dos bloques enteros en
   rojo y verde gritarían más de lo que dice el contenido. */
.lp-columna.no {
  border-top: 2px solid var(--ji-loss);
}
.lp-columna.si {
  border-top: 2px solid var(--ji-gain);
}
.lp-columna h3 {
  font-family: var(--ji-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  margin-bottom: 18px;
}
.lp-columna.no h3 {
  color: var(--ji-loss);
}
.lp-columna.si h3 {
  color: var(--ji-gain);
}
.lp-columna ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 13px;
}
.lp-columna li {
  position: relative;
  padding-left: 24px;
  font-size: 15px;
  line-height: 1.5;
  color: var(--ji-muted);
}
.lp-columna li::before {
  position: absolute;
  left: 0;
  top: -1px;
  font-size: 13px;
}
.lp-columna.no li::before {
  content: '✕';
  color: var(--ji-loss);
}
.lp-columna.si li::before {
  content: '✓';
  color: var(--ji-gain);
}

/* --- El método -------------------------------------------------------- */
.lp-metodo-rejilla {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 32px;
  margin-top: 40px;
}
.lp-metodo-rejilla h3 {
  font-family: var(--ji-serif);
  font-weight: 400;
  font-size: 1.25rem;
  letter-spacing: -0.015em;
  margin-bottom: 10px;
}
.lp-metodo-rejilla p {
  font-size: 15px;
  line-height: 1.65;
  color: var(--ji-muted);
}

/* --- Preguntas frecuentes --------------------------------------------- */
/* `<details>` nativo: plegable, accesible por teclado y sin JavaScript. */
.lp-faq details {
  border-bottom: 1px solid var(--ji-border);
}
.lp-faq details:first-of-type {
  border-top: 1px solid var(--ji-border);
  margin-top: 36px;
}
.lp-faq summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  /* 48 px de alto: es el mínimo táctil, y aquí sale gratis. */
  min-height: 48px;
  padding: 14px 4px;
  font-size: clamp(16px, 1.6vw, 17px);
  color: var(--ji-text);
  transition: color 0.15s;
}
.lp-faq summary::-webkit-details-marker {
  display: none;
}
.lp-faq summary::after {
  content: '+';
  flex: none;
  font-family: var(--ji-mono);
  font-size: 20px;
  line-height: 1;
  color: var(--ji-gold);
  transition: transform 0.2s;
}
.lp-faq details[open] summary::after {
  transform: rotate(45deg);
}
.lp-faq summary:hover {
  color: var(--ji-gold);
}
.lp-faq details p {
  padding: 0 4px 22px;
  max-width: 68ch;
  font-size: 15px;
  line-height: 1.7;
  color: var(--ji-muted);
}

/* --- Aviso legal ------------------------------------------------------ */
.lp-legal {
  border-top: 1px solid var(--ji-border);
  padding: 44px clamp(24px, 6vw, 80px) 56px;
  background: var(--ji-inset);
}
.lp-legal p {
  max-width: 900px;
  margin-inline: auto;
  font-size: 12px;
  line-height: 1.65;
  color: var(--ji-muted);
}
.lp-legal p + p {
  margin-top: 12px;
}
.lp-legal strong {
  color: var(--ji-text);
  font-weight: 500;
}
.lp-legal-pie {
  padding-top: 20px;
  font-family: var(--ji-mono);
  letter-spacing: 0.06em;
}

/* --- Móvil ------------------------------------------------------------ */
@media (max-width: 860px) {
  .lp-rejilla {
    grid-template-columns: 1fr;
    gap: 48px;
  }
  /* El ritmo asimétrico de los módulos se CANCELA en móvil, y hace falta
     decirlo explícitamente: `.lp-modulo .lp-rejilla` tiene más especificidad
     que `.lp-rejilla`, así que sin esto sus dos columnas sobrevivirían aquí
     dentro y dejarían el gráfico en una tira de 100 px. Una media query NO
     gana por estar más abajo. */
  .lp-modulo .lp-rejilla,
  .lp-modulo .lp-rejilla.vuelta {
    grid-template-columns: 1fr;
    gap: 48px;
    align-items: stretch;
  }
  .lp-modulo .lp-texto {
    padding-bottom: 0;
  }
  /* Y el reparto INTERIOR del texto de la variante ancha, tambien. El bloque de
     arriba cancela la rejilla exterior, pero la de dentro —titular a un lado,
     parrafo al otro— es otra rejilla y sobrevivia: medido en 375 px, el titular
     se quedaba en 137 px de ancho y 132 de alto y el parrafo en 126 × 358. Dos
     columnas de texto en un movil no son un reparto, son dos tiras. */
  .lp-modulo .lp-rejilla.ancho .lp-texto {
    grid-template-columns: 1fr;
    gap: 10px;
  }
  /* Y HAY QUE SOLTAR TAMBIEN A LOS HIJOS, que es lo que no era obvio: con la
     rejilla ya en una sola pista, el `grid-column: 2` del parrafo se COLOCA
     FUERA de ella y el navegador le crea una segunda columna implicita. O sea
     que declarar una pista no impide que un hijo se ponga en la de al lado.
     Medido antes de verlo: `grid-template-columns` computaba «1fr» y la caja
     salia igualmente partida en 122,9 y 194,1 px. */
  .lp-modulo .lp-rejilla.ancho .ji-eyebrow,
  .lp-modulo .lp-rejilla.ancho .lp-h2,
  .lp-modulo .lp-rejilla.ancho .lp-cuerpo {
    grid-column: auto;
    grid-row: auto;
  }
  .lp-rejilla.vuelta .lp-texto {
    order: 0;
  }
  .lp-cifras {
    grid-template-columns: 1fr 1fr;
    gap: 28px 20px;
  }
  .lp-columnas,
  .lp-metodo-rejilla {
    grid-template-columns: 1fr;
  }
}

/* --- Revelado al entrar en pantalla ----------------------------------- */
/* Una sola regla para todas las secciones. `.lp-portada` es un <header> y
   queda fuera a propósito: entra sola al cargar, sin esperar scroll. */
.lp > section > * {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.75s cubic-bezier(0.16, 1, 0.3, 1),
    transform 0.75s cubic-bezier(0.16, 1, 0.3, 1);
}
.lp > section.visto > * {
  opacity: 1;
  transform: none;
}
/* En los módulos el hijo directo es la rejilla entera; se neutraliza para
   poder revelar texto y gráfico por separado, con el gráfico un pelín
   después. */
.lp-modulo > .lp-rejilla {
  opacity: 1;
  transform: none;
  transition: none;
}
.lp-modulo .lp-texto,
.lp-modulo .lp-lienzo {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.75s cubic-bezier(0.16, 1, 0.3, 1),
    transform 0.75s cubic-bezier(0.16, 1, 0.3, 1);
}
.lp-modulo.visto .lp-texto,
.lp-modulo.visto .lp-lienzo {
  opacity: 1;
  transform: none;
}
.lp-modulo.visto .lp-lienzo {
  transition-delay: 0.14s;
}
.lp > section.visto > *:nth-child(2) { transition-delay: 0.06s; }
.lp > section.visto > *:nth-child(3) { transition-delay: 0.12s; }
.lp > section.visto > *:nth-child(4) { transition-delay: 0.18s; }
.lp > section.visto > *:nth-child(5) { transition-delay: 0.24s; }

/* =====================================================================
   `.lp-galaxia` · el fondo animado de la portada
   ---------------------------------------------------------------------
   Cubre la portada entera por detrás del texto. El componente decide QUÉ
   se pinta; esto solo decide DÓNDE y con cuánta fuerza.

   La máscara de abajo es la pieza importante: sin ella, las estrellas
   llegan hasta el borde de la sección y la portada se corta en seco contra
   la sección siguiente. Con el desvanecido, el fondo muere antes de llegar
   y la costura no existe.
   ===================================================================== */
/* =====================================================================
   `.lp-estrellas` · el campo con paralaje, detrás de toda la página
   ---------------------------------------------------------------------
   `fixed` y no `absolute`: el efecto es que el fondo NO acompañe al texto,
   así que tiene que estar anclado a la ventana y no al documento. El
   desplazamiento lo aplica el componente estrella a estrella según su capa.

   Va en z-index 0 y las secciones en 1, dentro del contexto de apilado que
   crea `.lp`. Así queda por debajo de todo sin tocar nada.
   ===================================================================== */
.lp-estrellas {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  pointer-events: none;
}
/* Todo el contenido de la landing, por encima del campo. Sin esto las
   secciones sin fondo propio quedarían por debajo y no se verían. */
.lp > *:not(.lp-estrellas):not(.lp-galaxia) {
  position: relative;
  z-index: 1;
}

.lp-galaxia {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  /*
   * Más alto que la portada A PROPÓSITO: cubre la portada entera y buena parte
   * de la sección de cifras.
   *
   * La primera versión lo dejaba dentro de la portada, y se veía «una parte
   * pintada y el resto no», con el corte justo en la costura entre secciones.
   * Es el mismo problema que el tutorial resuelve pidiendo que el fondo abarque
   * dos secciones y que la transición sea un degradado.
   */
  /*
   * 124vh: la portada (100dvh) más la sección de cifras, y **ni un pixel más**.
   *
   * La primera versión ponía 168vh con el desvanecido acabando al 92 %, o sea
   * a ~154vh — que cae dentro de la TERCERA sección. Y esa sí tiene fondo
   * propio, así que la galaxia asomaba por encima y se veía una raya
   * horizontal justo en su borde: el mismo corte que se venía a arreglar,
   * movido una sección más abajo.
   *
   * Comprobado en la grabación de pantalla que pasó Javi: la costura estaba en
   * el arranque de «Esto no es un curso».
   */
  height: 124vh;
  z-index: 0;
  /* Decoración: no debe comerse ni un clic del botón de entrar. */
  pointer-events: none;
  overflow: hidden;
  /*
   * El desvanecido es la pieza clave: sin él, el fondo termina en una línea
   * recta y se ve la costura. Llega a CERO en el propio borde del lienzo, no
   * antes ni después, para que el final coincida con el final de las cifras.
   */
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 52%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 0%, #000 52%, transparent 100%);
}
/*
 * El vídeo llena el hueco recortando lo que sobre, nunca deformándose.
 *
 * `object-position` lo ancla ARRIBA: el contenedor mide 124vh y el vídeo es
 * 16:9, así que sobra alto. Centrado, el recorte se comería la parte de arriba
 * —que es la que se ve al abrir la página— para enseñar la de abajo, que queda
 * bajo el pliegue.
 *
 * Y la opacidad no es tímida por gusto: a plena potencia el polvo compite con
 * el titular. A 0,55 sigue leyéndose como galaxia y el texto manda.
 */
.lp-galaxia video,
.lp-galaxia img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 0%;
  opacity: 0.55;
  display: block;
}

/*
 * Las dos primeras secciones tienen que dejarlo ver: cualquier fondo opaco
 * encima lo tapa entero. `.lp-cifras` ya era transparente; a la portada se le
 * quita el color de relleno y se le deja SOLO su resplandor dorado, que es
 * translúcido y suma en vez de tapar. El color base lo pone `.lp`, debajo.
 */
.lp-portada,
.lp-cifras {
  position: relative;
  z-index: 1;
  background: transparent;
}
.lp-portada {
  background: radial-gradient(
    ellipse 80% 50% at 50% -10%,
    color-mix(in srgb, var(--ji-gold) 9%, transparent) 0%,
    transparent 70%
  );
}

/* La portada no espera a ningún scroll: entra sola al cargar. */
.lp-portada > * {
  animation: lp-entrar 0.75s cubic-bezier(0.16, 1, 0.3, 1) both;
}
.lp-portada > *:nth-child(2) { animation-delay: 0.08s; }
.lp-portada > *:nth-child(3) { animation-delay: 0.16s; }
.lp-portada > *:nth-child(4) { animation-delay: 0.24s; }
.lp-portada > *:nth-child(5) { animation-delay: 0.32s; }
.lp-portada > .lp-pista-scroll {
  animation: lp-entrar 1.2s 1.2s both, lp-vaiven 2.2s 1.2s ease-in-out infinite;
}
@keyframes lp-entrar {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .lp > section > *,
  .lp-modulo .lp-texto,
  .lp-modulo .lp-lienzo {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .lp-portada > *,
  .lp-portada > .lp-pista-scroll {
    animation: none;
  }
  .lp-pista-scroll {
    transform: translateX(-50%);
  }
  .lp-btn:active {
    transform: none;
  }
  .lp-faq details[open] summary::after {
    transition: none;
  }
}

/* =====================================================================
   FRANJA DE RESUMEN DE LA WATCHLIST · `.fw-*`
   =====================================================================

   Tres barras que dicen cómo está la watchlist. La forma viene de una franja
   de Investing.com; el contenido no se pudo copiar —ellos dicen
   «infravaloradas» porque tienen precios de mercado, aquí los precios se
   teclean a mano y envejecen (ADR-0006)—, así que las barras hablan de tesis
   puesta, cuadrante propio y frescura. El razonamiento, en
   `calc/watchlistResumen.ts`.
   ===================================================================== */

.fw {
  display: grid;
  /* Tres columnas fijas y no `auto-fit`: con tres barras, `auto-fit` daba
     cuatro columnas en pantalla ancha y dejaba un hueco desigual al final. */
  grid-template-columns: 1fr;
  gap: clamp(12px, 2vw, 22px);
  margin: 4px 0 22px;
  padding: 16px 18px;
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio);
  background: var(--ji-surface);
}

.fw-titulo {
  font-family: var(--ji-mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ji-muted);
  margin-bottom: 10px;
  /* Lleva `title` con la definición: la ayuda vive donde está el dato. */
  cursor: help;
  width: fit-content;
}

.fw-pista {
  display: flex;
  height: 8px;
  border-radius: 999px;
  overflow: hidden;
  background: var(--ji-inset);
}
.fw-trozo {
  min-width: 2px;
}

.fw-leyenda {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  margin-top: 9px;
  font-size: 12px;
  color: var(--ji-muted);
}
.fw-n {
  font-family: var(--ji-mono);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}

/* Un tono por concepto, y el mismo para el trozo de barra y para su cifra. */
.fw-bien {
  background: var(--ji-gain);
  color: var(--ji-gain);
}
.fw-mal {
  background: var(--ji-loss);
  color: var(--ji-loss);
}
.fw-oro {
  background: var(--ji-gold);
  color: var(--ji-gold);
}
.fw-flojo {
  background: var(--ji-border-strong);
  color: var(--ji-muted);
}
/* En la leyenda son texto, no barra: el fondo sobra. */
.fw-leyenda .fw-n {
  background: none;
}

.fw-vacio {
  font-size: 12px;
  color: var(--ji-muted);
  line-height: 1.45;
}

@media (min-width: 720px) {
  .fw {
    grid-template-columns: repeat(3, 1fr);
  }
}

/* =====================================================================
   CONMUTADOR DE MODO · `.cm-*`
   =====================================================================

   Asimétrico a propósito: entrar en demo es raro, saber que estás dentro es
   constante. Era un interruptor de dos posiciones y falló de las dos maneras
   el mismo día — se pulsó sin querer, y una vez dentro no se notó.
   ===================================================================== */

/* En datos reales: discreto. No compite con nada ni invita a pulsarlo. */
.cm-entrar {
  font: inherit;
  font-size: 12px;
  color: var(--ji-muted);
  background: none;
  border: 1px solid var(--ji-border);
  border-radius: 999px;
  padding: 0 12px;
  min-height: 32px;
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.16s, border-color 0.16s;
}
.cm-entrar:hover {
  color: var(--ji-text);
  border-color: var(--ji-border-strong);
}

/* En demo: imposible de ignorar, y su única acción es salir. */
.cm-salir {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  color: #0d1119; /* fijo: encima va el oro sólido, igual en los dos temas */
  background: var(--ji-gold-solid);
  border: 0;
  border-radius: 999px;
  padding: 0 6px 0 12px;
  min-height: 32px;
  cursor: pointer;
  white-space: nowrap;
}
.cm-etiqueta {
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.cm-accion {
  background: rgba(13, 17, 25, 0.16);
  border-radius: 999px;
  padding: 3px 9px;
  font-weight: 500;
  letter-spacing: 0.02em;
}
.cm-salir:hover .cm-accion {
  background: rgba(13, 17, 25, 0.3);
}
/* El punto late para que el ojo lo pille aunque no lo esté buscando. */
.cm-punto {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #0d1119;
  flex: none;
  animation: cm-late 2.4s ease-in-out infinite;
}
@keyframes cm-late {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.35;
  }
}

.cm-aviso {
  font-size: 12px;
  line-height: 1.5;
  color: var(--ji-gold);
  background: color-mix(in srgb, var(--ji-gold) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--ji-gold) 25%, transparent);
  border-radius: 10px;
  padding: 8px 12px;
  margin-bottom: 16px;
}

@media (prefers-reduced-motion: reduce) {
  .cm-punto {
    animation: none;
  }
}

/* --- Selector de franja de la gráfica de patrimonio -------------------- */
.gp-grupo {
  display: flex;
  gap: 2px;
  background: var(--ji-surface-2);
  border-radius: 999px;
  padding: 4px;
}
.gp-btn {
  font-family: var(--ji-mono);
  font-size: 12px;
  color: var(--ji-muted);
  background: none;
  border: 0;
  border-radius: 999px;
  padding: 5px 11px;
  min-height: 28px;
  cursor: pointer;
  transition: color 0.15s, background 0.15s;
}
.gp-btn:hover {
  color: var(--ji-text);
}
.gp-btn.on {
  color: var(--ji-text);
  font-weight: 600;
  background: var(--ji-surface);
}
/* Una franja que no aporta más histórico que la anterior se apaga: dos botones
   que dan la misma curva hacen dudar de si la gráfica funciona. */
.gp-btn:disabled {
  opacity: 0.35;
  cursor: default;
}
.gp-btn:disabled:hover {
  color: var(--ji-muted);
}

/* Las franjas van debajo del lienzo y centradas: se eligen DESPUÉS de mirar la
   curva, no antes. Es la disposición del extracto de IBKR. */
.gp-franjas {
  display: flex;
  justify-content: center;
  margin-top: 10px;
}

/* --- Griegas de las opciones: precios de subyacente escribibles --------- */
.go-spots {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}
.go-spot {
  display: inline-flex;
  align-items: baseline;
  gap: 6px;
  padding: 5px 10px;
  background: var(--ji-surface-2);
  border: 1px solid var(--ji-border);
  border-radius: 8px;
}
.go-spot-tk {
  font-family: var(--ji-mono);
  font-size: 11px;
  color: var(--ji-gold);
  letter-spacing: 0.04em;
}
/* Marca de que ese precio lo ha escrito el lector y no viene del extracto: sin
   ella, un número inventado se confunde con un dato. */
.go-spot-marca {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ji-blue);
}
/* Cotizado aparte, no escrito por el lector: otro color para que se distingan
   de un vistazo las dos procedencias que NO son el extracto. */
.go-spot-marca.mercado {
  color: var(--ji-muted);
}

/* --- El embudo de la watchlist, en columnas por fase -------------------- */
/* Cinco columnas que caben en pantalla y se apilan en móvil. Cada una scrollea
   por dentro: «sin estudiar» tiene 200 empresas y no puede empujar a las demás
   fuera de la vista — perderías de golpe lo que has venido a mirar. */
.wl-proceso {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 12px;
  align-items: start;
}
@media (max-width: 900px) {
  .wl-proceso {
    grid-template-columns: 1fr;
  }
}
.wl-proceso-col {
  background: var(--ji-surface);
  border: 1px solid var(--ji-border);
  border-radius: 14px;
  overflow: hidden;
}
.wl-proceso-cab {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 12px;
  border-top: 2px solid var(--ji-muted);
  border-bottom: 1px solid var(--ji-border);
}
.wl-proceso-lista {
  max-height: 62vh;
  overflow-y: auto;
  padding: 8px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.wl-proceso-vacio {
  text-align: center;
  padding: 10px 0;
  margin: 0;
}
.wl-proceso-tarjeta {
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 100%;
  text-align: left;
  background: var(--ji-inset);
  border: 1px solid var(--ji-border);
  border-radius: 10px;
  padding: 8px 10px;
  cursor: pointer;
  transition: border-color 0.15s;
}
.wl-proceso-tarjeta:hover {
  border-color: var(--ji-gold);
}
.wl-proceso-tk {
  font-size: 13px;
  color: var(--ji-gold);
}
.wl-proceso-nombre {
  font-size: 12px;
  color: var(--ji-text);
  line-height: 1.3;
}
.wl-proceso-origen {
  font-size: 11px;
  color: var(--ji-blue);
}
/* La antigüedad, apagada: está para poder verla, no para gritar. */
.wl-proceso-dias {
  font-size: 11px;
  color: var(--ji-muted);
}

/* --- Rentabilidad por periodo: puntos, una franja cada vez -------------- */
/* Tercera forma de esto. Fueron barras horizontales, luego columnas con las
   seis ventanas a la vez, y ahora puntos de la franja elegida — que no es solo
   otro dibujo: las ventanas se solapaban entre sí y los meses no. */
.gp-puntos {
  padding: 6px 0 2px;
}
.gp-puntos svg {
  display: block;
}
/* Los rótulos, en HTML y por encima del SVG: dentro se deformarían con el
   estiramiento del trazo. Se colocan en porcentaje sobre el ancho, igual que
   los del mapa de calor, para caer justo sobre su punto. */
.gp-puntos-eje {
  position: relative;
  height: 34px;
  margin-top: 2px;
}
.gp-puntos-eje span {
  position: absolute;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  font-family: var(--ji-mono);
  font-size: 11px;
  color: var(--ji-muted);
  white-space: nowrap;
}
.gp-puntos-eje strong {
  font-size: 11px;
  font-weight: 400;
}
.gp-puntos-eje .sube {
  color: var(--ji-gain);
}
.gp-puntos-eje .baja {
  color: var(--ji-loss);
}
.gp-pernota {
  margin: 10px 0 0;
  font-size: 11px;
  line-height: 1.45;
  color: var(--ji-muted);
}

/* --- Globo de la marca de aportación ----------------------------------- */
/* Se ancla al icono «A» de la banda de abajo y sale hacia arriba: si saliera
   hacia abajo se comería el borde de la tarjeta. `pointer-events: none` es
   imprescindible —el globo se dibuja bajo el ratón, y si capturase el puntero
   se taparía a sí mismo y parpadearía. */
.gp-globo {
  position: absolute;
  bottom: 26px;
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding: 6px 10px;
  white-space: nowrap;
  pointer-events: none;
  background: var(--ji-surface-2);
  border: 1px solid var(--ji-border-strong);
  border-radius: 8px;
  box-shadow: 0 6px 18px rgb(0 0 0 / 35%);
  font-size: 11px;
  line-height: 1.35;
  color: var(--ji-muted);
  z-index: 2;
}
.gp-globo .ji-num {
  font-size: 13px;
  color: var(--ji-text);
}

/* --- Campo numérico del analizador de opciones ------------------------- */
/* El valor de cada deslizador se puede escribir: arrastrar sirve para
   explorar, pero no para poner 101,37. */
.op-campo {
  width: 5.5ch;
  font-size: 13px;
  color: var(--ji-gold);
  background: none;
  border: 0;
  border-bottom: 1px dashed transparent;
  padding: 0;
  text-align: right;
  cursor: text;
}
.op-campo:hover {
  border-bottom-color: var(--ji-border-strong);
}
.op-campo:focus {
  outline: none;
  border-bottom-color: var(--ji-gold);
}
/* Fuera las flechitas: al lado hay un deslizador para eso. */
.op-campo::-webkit-outer-spin-button,
.op-campo::-webkit-inner-spin-button {
  appearance: none;
  margin: 0;
}

/* --- La banda de «en construcción» del 720 (Hub) ----------------------
   BANDA ANCHA y no una quinta tarjeta, por dos razones que van juntas:

   1. NO es una quinta puerta. Las cuatro tarjetas son los módulos del MVP
      (ADR-0008); esto anuncia una campaña con fecha. Que se vea distinto es
      información, no decoración.
   2. En dos columnas, un quinto cuadro se queda solo en una fila a medias y
      añade 172 px de alto a un hub cuya regla es caber sin scroll (medido el
      31-ago-2026). Cruzando la rejilla ocupa la mitad.

   Y no es un enlace: una tarjeta que se pulsa y no lleva a nada promete algo
   que no está. Ver `docs/pendiente.md`, punto 2. */
.hub-obras {
  position: relative;
  z-index: 1;
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  gap: 18px;
  flex-wrap: wrap;
  padding: 14px 18px;
  border: 1px dashed var(--ji-border-strong);
  border-radius: var(--ji-radio);
  background: var(--ji-inset);
}
.hub-obras-id {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}
.hub-obras-id h2 {
  margin: 0;
  font-family: var(--ji-serif);
  font-size: 17px;
  color: var(--ji-text);
}
.hub-obras-txt {
  margin: 0;
  flex: 1;
  min-width: 240px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ji-muted);
}
/* La fecha, apagada dentro del mismo párrafo: es el dato que importa cuando
   llegue enero, pero hoy todavía no es una llamada a la acción. */
.hub-obras-txt span {
  opacity: 0.75;
}
.hub-etiqueta {
  padding: 3px 9px;
  border-radius: 999px;
  border: 1px solid var(--ji-border-strong);
  background: var(--ji-surface);
  color: var(--ji-muted);
  font-family: var(--ji-ui);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* =====================================================================
   IDEAS · `.idea-*`
   =====================================================================

   Dos mitades en una pantalla porque son un circuito: arriba lo que se está
   construyendo, abajo de dónde salió. Comparten aire y tipografía a propósito
   — separadas visualmente parecerían dos páginas pegadas.
   ===================================================================== */

.idea {
  max-width: 820px;
  margin-inline: auto;
  padding: clamp(18px, 3vh, 34px) clamp(14px, 3vw, 28px) 48px;
  display: flex;
  flex-direction: column;
  gap: clamp(24px, 4vh, 40px);
  /* El CSS antiguo le mete `center` a los contenedores `.ji`. Aquí se lee de
     arriba abajo, como en el hub. */
  text-align: left;
}
.idea-cab {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* --- Lo que se está construyendo --------------------------------------- */
.idea-obras {
  display: flex;
  flex-direction: column;
  gap: 10px;
  list-style: none;
  padding: 0;
}
.idea-obra {
  padding: 16px 18px;
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio);
  background: var(--ji-surface);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
/* En obras se distingue por un filo dorado a la izquierda, no por otro color de
   fondo: son tres estados y tres fondos harían un semáforo. */
.idea-obra.idea-en-obras {
  border-left: 2px solid var(--ji-gold-solid);
}
.idea-obra.idea-hecho {
  opacity: 0.72;
}
.idea-obra-cab {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
}
.idea-obra-cab h2 {
  font-family: var(--ji-serif);
  font-weight: 400;
  font-size: 18px;
  margin: 0;
}
.idea-obra-txt {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--ji-muted);
}
.idea-obra-pie {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  font-size: 12px;
  color: var(--ji-muted);
}

.idea-sello {
  padding: 2px 9px;
  border: 1px solid var(--ji-border);
  border-radius: 999px;
  font-size: 11px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ji-muted);
  white-space: nowrap;
}
.idea-sello.abierta {
  border-color: var(--ji-gold-solid);
  color: var(--ji-gold);
}

/* --- El buzón ---------------------------------------------------------- */
.idea-buzon {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 20px 22px;
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio);
  background: var(--ji-surface-2);
}
.idea-campo {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--ji-border);
  border-radius: 10px;
  background: var(--ji-bg);
  color: var(--ji-text);
  font: inherit;
  font-size: 14px;
  line-height: 1.5;
  resize: vertical;
}
.idea-campo:focus-visible {
  outline: 2px solid var(--ji-gold-solid);
  outline-offset: -1px;
}
.idea-envio {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
}
.idea-error {
  margin: 0;
  font-size: 12.5px;
  color: var(--ji-loss);
}
.idea-aviso {
  margin: 0;
  font-size: 12.5px;
  color: var(--ji-gain);
}

/* --- Las de todos ------------------------------------------------------ */
.idea-lista {
  display: flex;
  flex-direction: column;
  gap: 10px;
  list-style: none;
  padding: 0;
  margin-top: 12px;
}
.idea-ficha {
  padding: 14px 16px;
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio);
  background: var(--ji-surface);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
/* La propia, marcada con un filo: en una lista larga es lo que hace que
   encuentres la tuya sin leerlas todas. */
.idea-ficha:has(.idea-tuya) {
  border-left: 2px solid var(--ji-gold-solid);
}
.idea-ficha-cab {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 10px;
}
.idea-autor {
  font-family: var(--ji-serif);
  font-size: 15px;
  color: var(--ji-text);
}
.idea-tuya {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ji-gold);
}
.idea-fecha {
  margin-left: auto;
  font-family: var(--ji-mono);
  font-size: 11px;
  color: var(--ji-muted);
}
.idea-texto {
  margin: 0;
  font-size: 14px;
  line-height: 1.55;
}
/*
   La respuesta, sangrada y con un filo: se lee como una réplica y no como más
   texto del mismo autor. Es la mitad que hace que esto parezca una
   conversación.
*/
.idea-respuesta {
  margin: 2px 0 0 2px;
  padding: 10px 14px;
  border-left: 2px solid var(--ji-gold-solid);
  background: var(--ji-surface-2);
  border-radius: 0 10px 10px 0;
}
.idea-respuesta p {
  margin: 4px 0 0;
  font-size: 13.5px;
  line-height: 1.55;
}
.idea-quien {
  font-family: var(--ji-serif);
  font-size: 13px;
  color: var(--ji-gold);
}
.idea-que-significa {
  margin: 0;
  font-size: 12px;
  color: var(--ji-muted);
}

.idea-admin {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: 8px;
  border-top: 1px dashed var(--ji-border);
}
.idea-acciones {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.idea-mini {
  align-self: flex-start;
  padding: 4px 10px;
  border: 1px solid var(--ji-border);
  border-radius: 999px;
  background: transparent;
  color: var(--ji-muted);
  font: inherit;
  font-size: 12px;
  cursor: pointer;
  transition: color 0.16s, border-color 0.16s;
}
.idea-mini:hover:not(:disabled) {
  color: var(--ji-text);
  border-color: var(--ji-border-strong);
}
.idea-mini:disabled {
  opacity: 0.5;
  cursor: default;
}

@media (prefers-reduced-motion: reduce) {
  .idea-mini {
    transition: none;
  }
}

/* --- Ideas: el buzón como protagonista --------------------------------- */
/* Javi: *«el botón de "¿tienes alguna idea?" me parece muy poco visible y
   tímido»*. El arreglo no era agrandar el botón, era darle la vuelta a la
   página: la invitación va primera y ocupa el ancho, en vez de ir debajo de un
   roadmap, que es donde una invitación parece un formulario de contacto. */
.idea-buzon-grande {
  padding: clamp(24px, 4vw, 36px) clamp(20px, 4vw, 34px);
  gap: 14px;
  border-color: var(--ji-border-strong);
}
.idea-pregunta {
  font-family: var(--ji-serif);
  font-weight: 300;
  font-size: clamp(26px, 3.4vw, 38px);
  letter-spacing: -0.02em;
  line-height: 1.1;
  margin: 2px 0 0;
  text-wrap: balance;
}
.idea-sub {
  margin: 0;
  max-width: 58ch;
  font-size: 14.5px;
  color: var(--ji-muted);
}
.idea-sub strong {
  color: var(--ji-text);
  font-weight: 500;
}
.idea-campo-grande {
  font-size: 15px;
  padding: 14px 16px;
}
/* El botón sí es un botón: relleno sólido y del oro de la marca. Es la única
   acción de la pantalla, así que no compite con nada. */
.idea-enviar {
  padding: 11px 22px;
  border: none;
  border-radius: 10px;
  background: var(--ji-gold-solid);
  color: #17130a;
  font: inherit;
  font-size: 14.5px;
  font-weight: 500;
  cursor: pointer;
  transition: filter 0.16s;
}
.idea-enviar:hover:not(:disabled) {
  filter: brightness(1.08);
}
.idea-enviar:disabled {
  opacity: 0.45;
  cursor: default;
}
.idea-enviar:focus-visible {
  outline: 2px solid var(--ji-text);
  outline-offset: 3px;
}
.idea-cupo {
  font-size: 13px;
  color: var(--ji-muted);
}
/*
   Safari de iOS amplía la página al enfocar un campo de menos de 16 px, y el
   usuario se queda con la pantalla ampliada. Estos iban a 14 y 15.
*/
@media (max-width: 720px) {
  .idea-campo {
    font-size: 16px;
  }
}

/* --- Empresas: el mismo buzón, con tres campos -------------------------- */
.prop-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.prop-campos {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  gap: 12px;
}
.prop-etq {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 12px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ji-muted);
}
.prop-etq .idea-campo {
  text-transform: none;
  letter-spacing: normal;
}
@media (max-width: 560px) {
  .prop-campos {
    grid-template-columns: minmax(0, 1fr);
  }
}
.idea-pie {
  border-top: 1px solid var(--ji-border);
  padding-top: 16px;
  max-width: 62ch;
}

/* --- Hub: lo que se está construyendo ---------------------------------- */
.hub-obras-lista {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 10px;
  max-width: 860px;
  width: 100%;
}
.hub-obras-lista ul {
  display: flex;
  flex-direction: column;
  gap: 10px;
  list-style: none;
  padding: 0;
}
.hub-obra {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 14px 16px;
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio);
  background: var(--ji-surface);
}
/* Lo que está en marcha se distingue por un filo, no por otro fondo: tres
   fondos distintos harían un semáforo de algo que no es un estado de alarma. */
.hub-obra-en-obras {
  border-left: 2px solid var(--ji-gold-solid);
}
.hub-obra-hecho {
  opacity: 0.72;
}
.hub-obra-cab {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
}
.hub-obra-cab h2 {
  font-family: var(--ji-serif);
  font-weight: 400;
  font-size: 17px;
  margin: 0;
}
.hub-obra-txt {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--ji-muted);
}
.hub-obra-pie {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  font-size: 12px;
  color: var(--ji-muted);
}
.hub-etiqueta.abierta {
  border-color: var(--ji-gold-solid);
  color: var(--ji-gold);
}

.hub-progreso {
  display: flex;
  align-items: center;
  gap: 10px;
}
.hub-progreso-riel {
  flex: 1;
  height: 5px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--ji-text) 12%, transparent);
  overflow: hidden;
}
.hub-progreso-riel span {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: var(--ji-gold-solid);
  transition: width 0.5s ease;
}
.hub-progreso-n {
  font-family: var(--ji-mono);
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--ji-muted);
  min-width: 3.4em;
  text-align: right;
}

/* --- Landing: el primer estado del contador ---------------------------- */
/* «Plazas limitadas», sin número, desde el día uno. */
.lp-plazas-aviso {
  font-family: var(--ji-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ji-gold);
}

@media (prefers-reduced-motion: reduce) {
  .idea-enviar,
  .hub-progreso-riel span {
    transition: none;
  }
}

/* --- Landing: los bloques del proceso (7-sep-2026) ----------------------
   Salen de reordenar el post de anuncio: la landing vendía ACCESO —una lista
   de herramientas— y el post vendía PROCESO. Estos bloques son el proceso. */

/* El contraste que sustituye a «Sin señales · Sin predicciones · Sin cursos».
   Dos columnas enfrentadas: nombrar al rival y ponerse al lado. */
.lp-frente {
  display: grid;
  /*
     `min(220px, 100%)` Y NO `220px` A SECAS.
     ---------------------------------------------------------------------
     Con el mínimo fijo, `auto-fit` mantenía DOS columnas de 220 en un móvil de
     375: la rejilla medía 443 dentro de un contenedor de 327 y la segunda
     —«la mía, con sus años malos», o sea la mitad que importa— se salía y la
     recortaba el `overflow: hidden` de arriba. Sin barra de desplazamiento y
     sin aviso: en el móvil simplemente no estaba.

     Con `min()`, el suelo de la pista se encoge hasta el ancho disponible y la
     rejilla cae sola a una columna. Salió midiendo, no leyendo.
  */
  grid-template-columns: repeat(auto-fit, minmax(min(220px, 100%), 1fr));
  gap: 1px;
  max-width: 620px;
  margin: 26px auto 0;
  background: var(--ji-border);
  border: 1px solid var(--ji-border);
  border-radius: 12px;
  overflow: hidden;
  text-align: left;
}
.lp-frente > div {
  padding: 16px 18px;
  background: var(--ji-bg);
}
.lp-frente span {
  display: block;
  font-family: var(--ji-mono);
  font-size: 11px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ji-muted);
  margin-bottom: 7px;
}
/* El lado propio se marca con el oro de la marca, no con verde: no es un
   «bueno/malo» de semáforo, es «los demás / yo». */
.lp-frente .aqui span {
  color: var(--ji-gold);
}
.lp-frente p {
  margin: 0;
  font-size: 14.5px;
  color: var(--ji-text);
}

/* Una entradilla alineada a la izquierda, para los bloques que no van
   centrados. La landing centra por defecto y aquí estorba: son párrafos que se
   leen, no titulares. */
/* RETIRADA (7-sep-2026): se creó para alinear a la izquierda las entradillas
   de las secciones nuevas, y Javi pidió justo lo contrario. Se deja el nombre
   sin efecto en vez de quitarlo del JSX en cuatro sitios: si vuelve a hacer
   falta una entradilla a la izquierda, aquí está el gancho. */
.lp-entrada-izq {
  margin-inline: auto;
}

/* --- Los cuatro pasos, como un RECORRIDO ------------------------------
   Javi: *«la parte de los 4 pasos pienso que lo puedes destacar mucho más; sé
   creativo»*. Antes eran cuatro celdas de una rejilla, todas iguales y con el
   número en pequeño: parecía una tabla de características, y esto no es una
   lista de features — es el camino por el que pasa CADA empresa y del que no
   sale sin veredicto.

   Así que se dibuja como lo que es: cuatro nodos sobre un raíl. El número deja
   de ser una viñeta y pasa a ser la estación.

   El raíl se pinta con un `::before` de la lista, a la altura del centro de los
   círculos, y los círculos llevan el fondo de la sección: la línea pasa por
   detrás y parece entrar y salir de cada nodo. En una sola columna se esconde,
   porque una línea horizontal entre elementos apilados no une nada. */
.lp-pasos-bloque {
  background: var(--ji-surface);
}
.lp-pasos {
  counter-reset: paso;
  position: relative;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
  gap: 32px 26px;
  /* `auto` a los lados, igual que la cita: un `0` pisa el `margin-inline: auto`
     de la regla compartida y deja el raíl pegado al canto izquierdo. */
  margin: 34px auto 0;
  padding: 0;
  list-style: none;
  text-align: left;
}
.lp-pasos::before {
  content: '';
  position: absolute;
  /* Centro del círculo: 44 px de alto, así que 22 desde arriba. */
  top: 22px;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(
    90deg,
    transparent,
    var(--ji-border-strong) 8%,
    var(--ji-border-strong) 92%,
    transparent
  );
}
.lp-pasos li {
  counter-increment: paso;
  position: relative;
  /* Centrado también dentro de cada paso: con el círculo arriba y el texto
     debajo, alinear a la izquierda dejaba el número descolgado del título. */
  text-align: center;
}
.lp-pasos li::before {
  content: counter(paso);
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin: 0 auto 16px;
  border: 1px solid var(--ji-gold-solid);
  border-radius: 50%;
  /* El fondo de la sección, para que el raíl pase por detrás. */
  background: var(--ji-surface);
  font-family: var(--ji-serif);
  font-size: 19px;
  line-height: 1;
  color: var(--ji-gold);
  /* Por encima del raíl. */
  position: relative;
  z-index: 1;
}
.lp-pasos h3 {
  font-family: var(--ji-serif);
  font-weight: 400;
  font-size: 20px;
  letter-spacing: -0.01em;
  margin: 0 0 8px;
  text-wrap: balance;
}
.lp-pasos p {
  margin: 0 auto;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ji-muted);
  max-width: 34ch;
}

@media (max-width: 620px) {
  /* En una columna el raíl no une nada: uniría un nodo con el borde. */
  .lp-pasos::before {
    display: none;
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   LO QUE SE TOMÓ DE LA LANDING DE QUALITY VALUE (15-sep-2026)
   Enlaces a las secciones en la barra, una ficha de ejemplo bajo la portada,
   quién está detrás y los planes con cómo se entra. Con los tokens de siempre:
   nada de aquí tiene un color propio.
   ───────────────────────────────────────────────────────────────────────── */

/* La barra: marca · enlaces · botón. `space-between` ya los reparte. */
.lp-nav-enlaces {
  display: flex;
  gap: 24px;
}
.lp-nav-enlaces button {
  background: none;
  border: 0;
  padding: 6px 0;
  font-family: var(--ji-ui);
  font-size: 13px;
  color: var(--ji-muted);
  cursor: pointer;
  transition: color 0.2s;
}
.lp-nav-enlaces button:hover,
.lp-nav-enlaces button:focus-visible {
  color: var(--ji-text);
}
@media (max-width: 860px) {
  .lp-nav-enlaces {
    display: none;
  }
}
/* Que la barra fija no tape el titular de la sección a la que se salta. */
.lp-que,
.lp-pasos-bloque,
.lp-planes,
.lp-faq {
  scroll-margin-top: 64px;
}

/* --- La ficha de ejemplo ---------------------------------------------- */
.lp-ejemplo,
.lp-quien,
.lp-planes {
  padding: clamp(80px, 12vh, 128px) clamp(24px, 6vw, 80px);
  text-align: center;
}
.lp-ejemplo > *,
.lp-quien > * {
  max-width: 900px;
  margin-inline: auto;
}
.lp-planes > * {
  max-width: 1040px;
  margin-inline: auto;
}
.lp-quien .lp-entrada,
.lp-planes .lp-entrada {
  margin-inline: auto;
  max-width: 58ch;
}
/* «En una página» (`components/UnaPagina.tsx`): la misma tarjeta en la landing
   y en cada ficha de la watchlist. El margen de arriba solo en la landing. */
.lp-ejemplo .una-pagina {
  margin-top: 36px;
}
.una-pagina {
  text-align: left;
  border: 1px solid var(--ji-border-strong);
  border-radius: var(--ji-radio);
  background: var(--ji-surface);
  box-shadow: var(--ji-sombra);
  padding: clamp(22px, 4vw, 36px);
  display: grid;
  gap: 24px;
}
.una-pagina-cab {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 14px 24px;
}
.una-pagina-tk {
  font-family: var(--ji-mono);
  font-size: 13px;
  letter-spacing: 0.08em;
  color: var(--ji-gold);
}
.una-pagina-nombre {
  font-family: var(--ji-serif);
  font-weight: 400;
  font-size: clamp(24px, 3.4vw, 32px);
  letter-spacing: -0.015em;
  margin: 4px 0 6px;
}
.una-pagina-meta {
  font-family: var(--ji-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ji-muted);
  margin: 0;
}
.una-pagina-veredicto {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
}
/* El morado de «vigilancia», el mismo que en la watchlist (`colorFase`). */
/* El color de la fase llega en `--fase` (el de `colorFase` en la watchlist); sin
   él, el morado de «vigilancia». */
.una-pagina-fase {
  font-family: var(--ji-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--fase, var(--ji-purple));
  background: color-mix(in srgb, var(--fase, var(--ji-purple)) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--fase, var(--ji-purple)) 34%, transparent);
  border-radius: 4px;
  padding: 3px 9px;
}
.una-pagina-titulo {
  margin: 0;
  font-family: var(--ji-mono);
  font-size: 11px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ji-gold);
}
.una-pagina-resumen {
  margin: 0;
  max-width: 70ch;
  font-family: var(--ji-serif);
  font-style: italic;
  font-weight: 300;
  font-size: 16px;
  line-height: 1.65;
  color: var(--ji-text);
}
/* Sin columna «a favor» (la watchlist no la tiene: saldría de 30 síes), los
   riesgos ocupan todo el ancho. */
.una-pagina-rejilla.sola {
  grid-template-columns: 1fr;
}
/* Sin `nowrap`: un dato de tres años («FY23 53 % · FY24 36 % · FY25 32 %»)
   no cabe en un móvil y desbordaba la tarjeta. */
.una-pagina-dato {
  font-family: var(--ji-mono);
  font-size: 12px;
  color: var(--ji-text);
}
.una-pagina-nada {
  margin: 0;
  font-size: 14px;
  color: var(--ji-muted);
}
/* LA FILA DE UN RIESGO: la pregunta a la izquierda y, a la derecha, su
   respuesta —«No»—, el dato y «Por qué ▸» si se despliega (15-sep-2026).
   Antes la fila era la pregunta a secas: las que llevaban dato parecían
   contestadas y las demás no, y nada decía que se pudiera pulsar. */
.una-pagina li details summary,
.una-pagina-fila {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 6px 14px;
}
.una-pagina li details summary {
  cursor: pointer;
  list-style: none;
  /* El fondo al pasar por encima dice «esto se abre». El margen negativo
     compensa el relleno para que el texto no se mueva de su sitio. */
  margin: -3px -6px;
  padding: 3px 6px;
  border-radius: 6px;
  transition: background 0.15s;
}
.una-pagina li details summary::-webkit-details-marker {
  display: none;
}
.una-pagina li details summary:hover,
.una-pagina li details summary:focus-visible {
  background: var(--ji-surface-2);
}
.una-pagina-pregunta {
  flex: 1 1 240px;
  min-width: 0;
}
/* Resaltada solo la que se abre; las frases fijas (el ejemplo de la landing)
   siguen en el gris de la lista, como las de «A favor». */
.una-pagina li details .una-pagina-pregunta {
  color: var(--ji-text);
}
.una-pagina-respuesta {
  display: inline-flex;
  flex: 0 1 auto;
  flex-wrap: wrap;
  justify-content: flex-end;
  align-items: baseline;
  gap: 4px 10px;
  min-width: 0;
}
.una-pagina-no {
  font-family: var(--ji-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--ji-loss);
  background: color-mix(in srgb, var(--ji-loss) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--ji-loss) 34%, transparent);
  border-radius: 4px;
  padding: 1px 7px;
}
.una-pagina-porque::before {
  content: 'Por qué ▸';
  font-size: 12px;
  color: var(--ji-gold);
  white-space: nowrap;
}
.una-pagina li details[open] .una-pagina-porque::before {
  content: 'Ocultar ▾';
}
.una-pagina li details p {
  margin: 10px 0 6px;
  max-width: 70ch;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ji-muted);
}
.una-pagina-extra {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr));
  gap: 18px 32px;
  border-top: 1px solid var(--ji-border);
  padding-top: 20px;
}
.una-pagina-extra p {
  margin: 0;
  font-size: 14px;
  line-height: 1.55;
  color: var(--ji-muted);
}
.una-pagina-enlace {
  margin: 0;
  font-size: 14px;
}
.una-pagina-enlace a {
  color: var(--ji-gold);
  text-decoration: none;
}
.una-pagina-enlace a:hover,
.una-pagina-enlace a:focus-visible {
  text-decoration: underline;
}
/* El «por qué» completo y «El negocio», plegados bajo la página de la ficha. */
.wl-desplegable > summary {
  cursor: pointer;
  font-size: 13px;
  color: var(--ji-gold);
}
.wl-desplegable > summary:hover,
.wl-desplegable > summary:focus-visible {
  text-decoration: underline;
}
.wl-desplegable[open] > summary {
  margin-bottom: 12px;
}
.una-pagina-conviccion {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--ji-muted);
}
.una-pagina-conviccion i {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  border: 1px solid var(--ji-gold-solid);
}
.una-pagina-conviccion i.lleno {
  background: var(--ji-gold-solid);
}
.una-pagina-conviccion span {
  margin-left: 4px;
}
.una-pagina-que {
  margin: 0;
  max-width: 70ch;
  font-size: 15px;
  line-height: 1.6;
  color: var(--ji-text);
}
.una-pagina-rejilla {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 22px 36px;
}
.una-pagina h4 {
  font-family: var(--ji-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  margin: 0 0 12px;
  color: var(--ji-muted);
}
.una-pagina .favor h4 {
  color: var(--ji-gain);
}
.una-pagina .riesgos h4 {
  color: var(--ji-loss);
}
.una-pagina ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.una-pagina li {
  position: relative;
  padding-left: 22px;
  font-size: 14px;
  line-height: 1.5;
  color: var(--ji-muted);
}
.una-pagina li::before {
  position: absolute;
  left: 0;
  top: -1px;
  font-size: 12px;
}
.una-pagina .favor li::before {
  content: '✓';
  color: var(--ji-gain);
}
.una-pagina .riesgos li::before {
  content: '!';
  left: 4px;
  font-weight: 700;
  color: var(--ji-loss);
}
.una-pagina-bien {
  border-top: 1px solid var(--ji-border);
  padding-top: 20px;
}
.una-pagina-bien p {
  margin: 0;
  font-family: var(--ji-serif);
  font-size: 18px;
  line-height: 1.5;
  text-wrap: pretty;
}
.una-pagina-pie {
  margin: 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--ji-muted);
}
@media (max-width: 720px) {
  .una-pagina-rejilla {
    grid-template-columns: 1fr;
  }
  .una-pagina-veredicto {
    align-items: flex-start;
  }
}

/* --- Quién está detrás ------------------------------------------------ */
.lp-quien-enlaces {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 12px 28px;
  margin-top: 26px;
  font-size: 14px;
}
.lp-quien-enlaces a {
  color: var(--ji-gold);
  text-decoration: none;
}
.lp-quien-enlaces a:hover,
.lp-quien-enlaces a:focus-visible {
  text-decoration: underline;
}

/* --- Planes y cómo se entra ------------------------------------------- */
.lp-planes-rejilla {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px;
  margin-top: 40px;
  text-align: left;
  align-items: start;
}
.lp-plan {
  display: flex;
  flex-direction: column;
  gap: 12px;
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio);
  background: var(--ji-surface);
  padding: 26px 26px 28px;
}
/* El que lleva la web se distingue por el filete, como las columnas del
   «para quién sí»: sin cambiarle el fondo, que gritaría. */
.lp-plan.anual {
  border-color: color-mix(in srgb, var(--ji-gold-solid) 40%, transparent);
  border-top: 2px solid var(--ji-gold-solid);
}
.lp-plan h3 {
  margin: 0;
  font-family: var(--ji-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ji-muted);
}
.lp-plan.anual h3 {
  color: var(--ji-gold);
}
.lp-plan p {
  margin: 0;
  font-size: 15px;
  line-height: 1.55;
  color: var(--ji-muted);
}
.lp-plan ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.lp-plan li {
  position: relative;
  padding-left: 22px;
  font-size: 14px;
  line-height: 1.5;
  color: var(--ji-text);
}
.lp-plan li::before {
  content: '✓';
  position: absolute;
  left: 0;
  top: -1px;
  font-size: 12px;
  color: var(--ji-gold);
}
.lp-plan .lp-plan-sin {
  font-size: 13px;
  color: var(--ji-text);
}
.lp-plan-precio {
  border-top: 1px solid var(--ji-border);
  padding-top: 14px;
}
.lp-plan .lp-plan-precio {
  font-size: 13px;
}
.lp-plan-precio strong {
  display: block;
  margin-bottom: 4px;
  font-family: var(--ji-serif);
  font-weight: 400;
  font-size: 22px;
  color: var(--ji-text);
}
.lp-planes-acceso {
  margin-top: 64px;
}
.lp-planes-acceso-tit {
  font-family: var(--ji-serif);
  font-weight: 400;
  font-size: 1.5rem;
  letter-spacing: -0.015em;
  margin: 0;
}
/* Los círculos de los pasos llevan el fondo de su sección para que el raíl
   pase por detrás. Esta sección no tiene fondo propio: el de la página. */
.lp-planes .lp-pasos li::before {
  background: var(--ji-bg);
}
@media (max-width: 860px) {
  .lp-planes-rejilla {
    grid-template-columns: 1fr;
  }
}

/* La cita de los errores. Es la frase más fuerte de la página, así que va sola
   y en serif grande: si compartiera bloque con otra cosa, se leería como una
   más. */
.lp-errores {
  background: var(--ji-surface);
}
.lp-errores blockquote {
  /* `0 auto` y no `0`: la regla compartida centra los hijos de la sección con
     `margin-inline: auto`, y un `margin: 0` aquí la pisaba —misma
     especificidad, esta va después— y dejaba la cita pegada a la izquierda con
     medio ancho en blanco a su derecha. */
  margin: 0 auto;
  text-align: left;
  padding: 24px 26px;
  border-left: 2px solid var(--ji-gold-solid);
  background: color-mix(in srgb, var(--ji-gold-solid) 5%, transparent);
  border-radius: 0 14px 14px 0;
  text-align: left;
}
.lp-errores blockquote p {
  margin: 0;
  font-family: var(--ji-serif);
  font-weight: 300;
  font-size: clamp(19px, 2.6vw, 27px);
  line-height: 1.3;
  letter-spacing: -0.015em;
  text-wrap: balance;
}
.lp-errores .lp-entrada {
  margin-top: 22px;
}

/* Los dos principios, como dos cajas de la MISMA medida.
   Javi: *«arregla los tamaños, están descuadrados»*. Y lo estaban: eran dos
   columnas de texto suelto con distinta cantidad de letra, así que una acababa
   cuatro líneas más abajo que la otra y no había nada que las emparejara.
   Con caja y `align-items: stretch` las dos miden lo mismo, y el `max-width`
   del párrafo se quita — dentro de una caja ya lo limita la propia caja. */
.lp-principios-rejilla {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  align-items: stretch;
  gap: 16px;
  margin-top: 24px;
  text-align: left;
}
.lp-principios-rejilla > div {
  text-align: left;
  padding: 22px 24px;
  border: 1px solid var(--ji-border);
  border-left: 2px solid var(--ji-gold-solid);
  border-radius: 0 14px 14px 0;
  background: var(--ji-surface);
}
.lp-principios-rejilla h3 {
  font-family: var(--ji-serif);
  font-weight: 400;
  font-size: 19px;
  line-height: 1.25;
  margin: 0 0 10px;
  text-wrap: balance;
}
.lp-principios-rejilla p {
  margin: 0;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ji-muted);
}
.lp-principios-rejilla strong {
  color: var(--ji-text);
  font-weight: 500;
}

/* «Somos N aquí dentro». Una línea sola, centrada, entre la portada y las
   cifras: es una cifra más, pero la única que se mueve, así que va suelta y no
   dentro de la rejilla de las fijas.

   SE LLAMÓ `.lp-dentro` Y ERA UN NOMBRE YA OCUPADO: esa clase es, desde antes,
   la lista de «lo que vas a encontrar aquí» de cada módulo. Como esta regla iba
   después, ganaba — y las cuatro listas de la página salían centradas, en
   mayúsculas y en monoespaciada. Se vio en pantalla; leyendo el fichero no
   salta, porque las dos reglas están a mil ochocientas líneas de distancia. */
.lp-somos {
  margin: 0;
  padding: 22px 24px 0;
  text-align: center;
  font-family: var(--ji-mono);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ji-muted);
}
.lp-somos strong {
  color: var(--ji-gold);
  font-weight: 400;
}

/* --- CRIBA RÁPIDA (admin) ------------------------------------------------

   ── LAS CLASES VAN CON `criba-rapida-`, Y NO ES VERBOSIDAD ──────────────

   La primera versión usó `criba-botones`, `criba-lista` y `criba-porque`, que
   YA EXISTÍAN en `styles.css` para el editor de la criba. Como `disenio.css`
   carga después, un `width: 38px; height: 38px` pensado para los botones de
   convicción de esta pantalla acabó aplastando los «Sí / No / No lo sé» del
   editor: el texto se salía de la caja. Javi lo vio en la primera criba que
   hizo.

   Es la segunda colisión de este tipo en el proyecto —la anterior fue
   `.lp-dentro` en la portada— y las dos salieron de dar por hecho que un nombre
   corto estaba libre. Con dos sistemas de estilos conviviendo, no lo está.

   La pantalla de la pasada 1: puntuar 159 empresas sin entrar y salir de un
   editor. El porqué entero está en `calc/cribaRapida.ts`.

   Es de administración, así que el criterio no es que sea bonita: es que la
   mano llegue rápido. De ahí los botones grandes y el porqué al lado, sin
   desplegables ni diálogos por medio.
   ===================================================================== */
.criba-rapida-progreso {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 20px;
  margin-bottom: 18px;
}
.criba-rapida-progreso-cifra {
  font-size: 1.5rem;
  font-weight: 600;
  margin: 0;
}
.criba-rapida-progreso-de {
  color: var(--ji-muted);
  font-weight: 400;
  font-size: 1rem;
}
.criba-rapida-barra {
  flex: 1 1 220px;
  height: 8px;
  border-radius: 999px;
  background: var(--ji-inset);
  border: 1px solid var(--ji-border);
  overflow: hidden;
}
.criba-rapida-barra-relleno {
  height: 100%;
  background: var(--ji-gold);
  transition: width 0.25s ease;
}
@media (prefers-reduced-motion: reduce) {
  .criba-rapida-barra-relleno {
    transition: none;
  }
}
.criba-rapida-reparto {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 0.8125rem;
  color: var(--ji-muted);
}

.criba-rapida-filtros {
  display: flex;
  gap: 8px;
  margin-bottom: 14px;
}
.criba-rapida-filtros button {
  padding: 6px 14px;
  border-radius: 999px;
  border: 1px solid var(--ji-border);
  background: var(--ji-surface);
  color: var(--ji-muted);
  font: inherit;
  font-size: 0.875rem;
  cursor: pointer;
}
.criba-rapida-filtros button.activo {
  border-color: var(--ji-gold);
  color: var(--ji-text);
}

.criba-rapida-lista {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.criba-rapida-fila {
  display: grid;
  /* Dos columnas en pantalla ancha: quién es, y qué decides. En estrecho se
     apila, que es lo único que cabe. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: 12px 20px;
  align-items: start;
  padding: 12px 14px;
  border: 1px solid var(--ji-border);
  border-radius: 10px;
  background: var(--ji-surface);
}
@media (max-width: 820px) {
  .criba-rapida-fila {
    grid-template-columns: minmax(0, 1fr);
  }
}

.criba-rapida-quien p {
  margin: 0;
}
.criba-rapida-ticker {
  font-weight: 600;
  font-size: 0.9375rem;
}
.criba-rapida-nombre {
  font-size: 0.9375rem;
}
.criba-rapida-contexto {
  font-size: 0.75rem;
  color: var(--ji-muted);
  margin-top: 2px !important;
}
.criba-rapida-resumen {
  font-size: 0.8125rem;
  color: var(--ji-muted);
  margin-top: 6px !important;
}

.criba-rapida-decision {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.criba-rapida-botones {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.criba-rapida-botones button {
  width: 38px;
  height: 38px;
  border-radius: 8px;
  border: 1px solid var(--ji-border);
  background: var(--ji-inset);
  color: var(--ji-text);
  font: inherit;
  font-variant-numeric: tabular-nums;
  font-size: 0.9375rem;
  cursor: pointer;
}
.criba-rapida-botones button:hover {
  border-color: var(--ji-border-strong);
}
.criba-rapida-botones button.activo {
  border-color: var(--ji-gold);
  background: var(--ji-gold);
  color: #12151c;
  font-weight: 600;
}
.criba-rapida-limpiar {
  color: var(--ji-muted) !important;
}
.criba-rapida-porque {
  width: 100%;
  padding: 8px 10px;
  border-radius: 8px;
  border: 1px solid var(--ji-border);
  background: var(--ji-inset);
  color: var(--ji-text);
  font: inherit;
  /* 16 px reales: por debajo, Safari en iOS amplía la página al enfocar y deja
     al usuario con la pantalla ampliada. Regla del `CLAUDE.md`. */
  font-size: 1rem;
}
.criba-rapida-implica {
  margin: 0;
  font-size: 0.75rem;
  color: var(--ji-muted);
}
.criba-rapida-estado {
  margin: 0;
  min-height: 1em;
  font-size: 0.75rem;
  color: var(--ji-muted);
}
.criba-rapida-estado--guardado {
  color: var(--ji-gain);
}
.criba-rapida-estado--error {
  color: var(--ji-loss);
}

/* --- CRIBA: LOS RIESGOS -------------------------------------------------

   La criba no da una nota, inventaría riesgos (Javi, 9-sep-2026). Los `no` son
   la lista de lo que hay que vigilar, y lo que distingue un riesgo asumido de
   uno olvidado es si lleva justificación escrita.

   Por eso lo único que se colorea aquí es «sin justificar»: no es una alarma
   —un riesgo justificado es una decisión, no un problema— es un recordatorio de
   que falta escribir por qué compensa.
   ===================================================================== */
.criba-riesgos {
  margin: 20px 0;
}
.criba-riesgos h3 {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 0 0 10px;
}
.criba-riesgos h3 span {
  font-size: 0.75rem;
  font-weight: 400;
  color: var(--ji-muted);
}
.criba-riesgos ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.criba-riesgos li {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  padding: 8px 10px;
  border: 1px solid var(--ji-border);
  border-radius: 8px;
  background: var(--ji-inset);
  font-size: 0.875rem;
}
.criba-riesgos li.pendiente {
  border-color: var(--ji-gold);
}
.criba-riesgo-bloque {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ji-muted);
}
.criba-riesgo-que {
  flex: 1 1 14rem;
}
.criba-riesgo-falta {
  font-size: 0.75rem;
  color: var(--ji-gold);
  white-space: nowrap;
}

/* El aviso al seleccionar. Dorado y no rojo a propósito: pasar a tesis con
   riesgos no es un error, es una decisión que hay que poder defender. */
.criba-aviso {
  margin: 8px 0 0;
  padding: 8px 10px;
  border-radius: 8px;
  border: 1px solid var(--ji-border);
  background: var(--ji-inset);
  font-size: 0.8125rem;
  color: var(--ji-muted);
}
.criba-aviso.pendiente {
  border-color: var(--ji-gold);
  color: var(--ji-text);
}

/* Separador «Actualizaciones» dentro de la lista de la tesis (0066). Es un
   `li` y no un `h4` para no romper la lista en dos: son el mismo bloque y el
   lector los recorre seguidos. */
.emp-tesis-sep {
  list-style: none;
  margin-top: 10px;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ji-muted);
}

/* --- CRIBA: LA EXPLICACIÓN DE CADA PREGUNTA -----------------------------

   Plegada por defecto. Cuarenta y nueve preguntas con tres párrafos cada una
   son once mil palabras: quien ya sabe leer un balance quiere el veredicto y
   la fuente, y quien está aprendiendo quiere el porqué. Un `details` sirve a
   los dos sin que ninguno pague por el otro.
   ===================================================================== */
.criba-explica {
  margin-top: 8px;
}
.criba-explica > summary {
  cursor: pointer;
  font-size: 13px;
  color: var(--ji-muted);
  /* Sin el triángulo del navegador, que en Safari y en Chrome no se parecen. */
  list-style: none;
}
.criba-explica > summary::-webkit-details-marker {
  display: none;
}
.criba-explica > summary::before {
  content: '＋ ';
  font-variant: none;
}
.criba-explica[open] > summary::before {
  content: '− ';
}
.criba-explica > summary:hover {
  color: var(--ji-text);
}
.criba-explica p {
  margin: 8px 0 0;
  padding-left: 12px;
  border-left: 2px solid var(--ji-border);
  font-size: 14px;
  line-height: 1.6;
  color: var(--ji-muted);
  /*
   * parrafosCriba ya une los saltos del editor; los que quedan son puntos de
   * lista, y ésos sí hay que respetarlos.
   */
  white-space: pre-line;
  max-width: 46rem;
}
/* Párrafos seguidos: el filete de la izquierda, continuo y no a trozos. */
.criba-explica p + p {
  margin-top: 0;
  padding-top: 10px;
}
.criba-explica-mira {
  color: var(--ji-text) !important;
}

/* ── Criba: explicación con fuentes enlazadas ─────────────────────────────
   Las respuestas que trae el importador llevan el porqué, el dato y la fuente
   en líneas separadas, y la fuente enlaza al documento en la SEC. */
.criba-porque {
  white-space: pre-line;
}
.criba-porque a,
.criba-importar-porque a {
  color: var(--ji-gold);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.criba-porque a:hover,
.criba-importar-porque a:hover {
  color: var(--ji-text);
}

/* ── Criba: importar el borrador del agente ──────────────────────────────
   Nombres propios (criba-importar-*) a propósito: .criba-botones y
   .criba-lista ya chocaron una vez entre disenio.css y styles.css. */
.criba-importar {
  margin: 0 0 20px;
  padding: 12px 14px;
  border: 1px dashed var(--ji-border-strong);
  border-radius: var(--ji-radio-sm);
  background: var(--ji-surface);
}
.criba-importar > summary {
  cursor: pointer;
  font-family: var(--ji-ui);
  font-size: 13px;
  font-weight: 600;
  color: var(--ji-text);
}
.criba-importar > .pista,
.criba-importar > input[type='file'] {
  margin-top: 10px;
}
.criba-importar-revision {
  margin-top: 14px;
  display: grid;
  gap: 10px;
}
.criba-importar-resumen {
  margin: 0;
  font-size: 13px;
  color: var(--ji-muted);
}
.criba-importar-lista {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 8px;
  max-height: 60vh;
  overflow-y: auto;
}
.criba-importar-fila {
  padding: 8px 10px;
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio-sm);
  background: var(--ji-bg);
}
.criba-importar-fila.cambia {
  border-color: var(--ji-gold);
}
.criba-importar-fila > label {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  cursor: pointer;
}
.criba-importar-fila input[type='checkbox'] {
  margin-top: 3px;
  flex: none;
}
.criba-importar-que {
  flex: 1;
  font-size: 13.5px;
  color: var(--ji-text);
}
.criba-importar-bloque {
  display: inline-block;
  margin-right: 8px;
  font-family: var(--ji-mono);
  font-size: 11px;
  color: var(--ji-muted);
  white-space: nowrap;
}
.criba-importar-estado {
  margin: 4px 0 0 26px;
  font-size: 11.5px;
  color: var(--ji-muted);
}
.criba-importar-fila.cambia .criba-importar-estado {
  color: var(--ji-gold);
}
.criba-importar-porque {
  margin: 4px 0 0 26px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ji-muted);
  white-space: pre-line;
  overflow-wrap: anywhere;
}
.criba-importar-fuera {
  font-size: 12.5px;
  color: var(--ji-muted);
}
.criba-importar-fuera > summary {
  cursor: pointer;
}
.criba-importar-fuera ul {
  margin: 6px 0 0;
  padding-left: 18px;
  display: grid;
  gap: 4px;
}

/* ── Solicitudes: las pestañas Ideas / Empresas ──────────────────────────
   Mismo aspecto que las de Cartera (.cart-pestanas), pero con enlaces: cada
   pestaña tiene su dirección. */
.sol-pestanas {
  margin-bottom: 0;
}
.sol-pestana {
  font-family: var(--ji-ui);
  font-size: 12px;
  font-weight: 400;
  color: var(--ji-muted);
  background: transparent;
  border-radius: 8px;
  padding: 7px 16px;
  text-decoration: none;
  white-space: nowrap;
}
.sol-pestana:hover {
  color: var(--ji-text);
}
.sol-pestana.on {
  font-weight: 600;
  color: var(--ji-text);
  background: var(--ji-surface-2);
}
.sol-pestana:focus-visible {
  outline: 2px solid var(--ji-gold);
  outline-offset: 2px;
}
.ancho > .sol-pestanas {
  margin-bottom: 18px;
}

/* ── Criba: la explicación, ordenada ─────────────────────────────────────
   El dato arriba, el porqué en puntos y las fuentes aparte (ExplicacionCriba).
   Antes era un solo párrafo con todo pegado: «una amalgama de datos
   compactados», en palabras de Javi. */
.criba-expl {
  display: grid;
  gap: 6px;
  margin: 0;
  padding-left: 11px;
  border-left: 2px solid var(--ji-border);
  font-family: var(--ji-ui);
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--ji-muted);
}
.criba-expl-etq {
  flex: none;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ji-muted);
}
.criba-expl-dato {
  margin: 0;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 10px;
}
.criba-expl-dato strong {
  font-size: 14.5px;
  font-weight: 600;
  color: var(--ji-text);
}
.criba-expl-texto {
  margin: 0;
  color: var(--ji-text);
}
.criba-expl-puntos {
  margin: 0;
  padding-left: 18px;
  display: grid;
  gap: 4px;
  color: var(--ji-text);
}
.criba-expl-puntos li::marker {
  color: var(--ji-gold);
}
.criba-expl-fuentes {
  margin: 2px 0 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 12px;
  font-size: 13px;
}
.criba-expl a {
  color: var(--ji-gold);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.criba-expl a:hover {
  color: var(--ji-text);
}
.criba-expl-editar {
  margin-top: 8px;
  padding: 3px 10px;
  font-family: var(--ji-ui);
  font-size: 12px;
  color: var(--ji-muted);
  background: transparent;
  border: 1px solid var(--ji-border);
  border-radius: 6px;
  cursor: pointer;
}
.criba-expl-editar:hover {
  color: var(--ji-text);
  border-color: var(--ji-border-strong);
}
.criba-importar-expl {
  margin: 6px 0 0 26px;
  font-size: 12.5px;
}
.criba-importar-expl .criba-expl-dato strong {
  font-size: 12.5px;
}

/* ── Criba: cada riesgo dice qué salió y por qué cuenta ──────────────────
   Tres líneas: la pregunta (botón que lleva a ella), lo que salió —el dato y
   el primer hecho— y la regla «Es riesgo si…». Antes era sólo la pregunta. */
.criba-riesgos li {
  display: grid;
  gap: 5px;
}
.criba-riesgo-cab {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  width: 100%;
  margin: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  text-align: left;
  background: none;
  border: 0;
  cursor: pointer;
}
.criba-riesgo-cab:hover .criba-riesgo-que {
  text-decoration: underline;
  text-underline-offset: 3px;
}
.criba-riesgo-cab:focus-visible {
  outline: 2px solid var(--ji-gold);
  outline-offset: 3px;
  border-radius: 4px;
}
.criba-riesgo-hallazgo {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 10px;
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--ji-text);
}
.criba-riesgo-hallazgo strong {
  color: var(--ji-loss);
  font-weight: 600;
}
.criba-riesgo-hallazgo a {
  color: var(--ji-gold);
}
.criba-riesgo-regla {
  margin: 0;
  font-size: 0.75rem;
  line-height: 1.45;
  color: var(--ji-muted);
}

.criba-importar-todas {
  margin: 0;
}

/* ── Criba: borrar respuestas guardadas, desde el importador ───────────── */
.criba-importar-borrar {
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--ji-border);
}
.criba-importar-borrar > summary {
  cursor: pointer;
  font-family: var(--ji-ui);
  font-size: 13px;
  font-weight: 600;
  color: var(--ji-muted);
}
.criba-importar-borrar > .pista,
.criba-importar-borrar > .aviso,
.criba-importar-borrar > .error,
.criba-importar-borrar > .criba-importar-todas {
  margin: 10px 0 0;
}
.criba-importar-borrar-lista {
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
  display: grid;
  gap: 4px;
  max-height: 50vh;
  overflow-y: auto;
}
.criba-importar-borrar-lista label {
  display: flex;
  align-items: baseline;
  gap: 10px;
  padding: 6px 10px;
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio-sm);
  background: var(--ji-bg);
  cursor: pointer;
}
.criba-importar-borrar .botonera {
  margin-top: 10px;
}
/* El segundo clic, en rojo: es el que borra de verdad. */
.criba-borrar-confirmar {
  padding: 7px 14px;
  font-family: var(--ji-ui);
  font-size: 13px;
  font-weight: 600;
  color: #fff;
  background: var(--ji-loss);
  border: 1px solid var(--ji-loss);
  border-radius: 8px;
  cursor: pointer;
}

/* ── La criba de un vistazo: barra por bloque y mapa de preguntas ─────────
   Javi, 11-sep-2026. Sustituye a los marcadores (`GraficoCriba.tsx`).
   Colores: sí verde, no rojo, «no lo sé» GRIS —nunca rojo, no es un no— y
   «sin mirar» hueco con borde discontinuo, como la pregunta en la lista. */
.criba-graf {
  container-type: inline-size;
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-bottom: 22px;
  padding: 14px 16px;
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio-sm);
  background: var(--ji-surface);
}
.criba-graf-resumen,
.criba-graf-mapa {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.criba-graf-fila {
  display: grid;
  grid-template-columns: 84px minmax(0, 1fr) minmax(0, 15rem);
  gap: 12px;
  align-items: center;
}
.criba-graf-fila.mapa {
  grid-template-columns: 84px minmax(0, 1fr);
  align-items: start;
}
/* El régimen no suma con la empresa: se separa con aire y una raya. */
.criba-graf-fila.aparte {
  margin-top: 6px;
  padding-top: 10px;
  border-top: 1px dashed var(--ji-border);
}
.criba-graf-nom {
  font-family: var(--ji-ui);
  font-size: 13px;
  color: var(--ji-text);
}
.criba-graf-fila.mapa .criba-graf-nom {
  padding-top: 4px;
}
.criba-graf-barra {
  display: flex;
  gap: 2px;
  height: 18px;
  border-radius: 4px;
  overflow: hidden;
}
.criba-graf-tramo {
  display: block;
  flex-basis: 0;
  min-width: 4px;
}
.criba-graf-tramo.si,
.criba-graf-celda.si {
  background: var(--ji-gain);
}
.criba-graf-tramo.no,
.criba-graf-celda.no {
  background: var(--ji-loss);
}
.criba-graf-tramo.no-se,
.criba-graf-celda.no-se {
  background: var(--ji-muted);
}
.criba-graf-tramo.vacia,
.criba-graf-celda.vacia {
  background: transparent;
  border: 1px dashed color-mix(in srgb, var(--ji-muted) 55%, transparent);
}
.criba-graf-pie {
  font-family: var(--ji-ui);
  font-size: 12px;
  color: var(--ji-muted);
  font-variant-numeric: tabular-nums;
}
.criba-graf-pie strong {
  font-size: 16px;
  margin-right: 1px;
  color: var(--ji-text);
}
.criba-graf-pie strong.hay {
  color: var(--ji-loss);
}
.criba-graf-leyenda {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 16px;
  margin: 0;
  font-family: var(--ji-ui);
  font-size: 11.5px;
  color: var(--ji-muted);
}
.criba-graf-leyenda span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.criba-graf-leyenda i {
  display: inline-block;
  flex: none; /* el tramo lleva flex-basis 0 y aquí lo encogería a una raya */
  width: 10px;
  height: 10px;
  border-radius: 2px;
}
.criba-graf-mapa {
  padding-top: 12px;
  border-top: 1px solid var(--ji-border);
}
.criba-graf-mapa-tit {
  margin: 0 0 2px;
  font-family: var(--ji-ui);
  font-size: 11.5px;
  color: var(--ji-muted);
}
.criba-graf-celdas {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
}
.criba-graf-celda {
  width: 26px;
  height: 26px;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--ji-mono);
  font-size: 11px;
  color: var(--ji-bg);
  border: 0;
  border-radius: 4px;
  cursor: pointer;
  font-variant-numeric: tabular-nums;
}
.criba-graf-celda.vacia {
  color: var(--ji-muted);
}
.criba-graf-celda:hover {
  outline: 2px solid var(--ji-text);
  outline-offset: 1px;
}
.criba-graf-celda:focus-visible {
  outline: 2px solid var(--ji-gold);
  outline-offset: 2px;
}
/* En estrecho, el pie baja debajo de la barra: tres columnas no caben. Por
   el ancho de la caja y no de la pantalla: la ficha y el editor no la pintan
   igual de ancha, y con la pantalla se aplastaba la barra a cero. */
@container (max-width: 560px) {
  .criba-graf-fila {
    grid-template-columns: 70px minmax(0, 1fr);
  }
  .criba-graf-pie {
    grid-column: 2;
  }
  .criba-graf-fila.mapa {
    grid-template-columns: 1fr;
    gap: 4px;
  }
}

/* ── El gráfico de cada respuesta de la criba (`GraficoRespuesta.tsx`) ─────
   Javi, 12-sep-2026: «graficar cada respuesta». Sin verde ni rojo —en la
   criba significan sí y riesgo, y el gráfico no juzga—. Paleta comprobada con
   el validador (daltonismo y contraste) en los dos temas; si se cambia un
   tono, se vuelve a pasar. La regla, siempre discontinua y con su texto. */
:root {
  --criba-g-1: #5b8dee;
  --criba-g-2: #d9770f;
  --criba-g-3: #a855f7;
  --criba-g-4: #b08a0c;
  --criba-g-5: #e0609a;
  --criba-g-resto: #5d6270;
  --criba-g-otros: #5d6270;
}
:root[data-theme='light'] {
  --criba-g-1: #3d6fd6;
  --criba-g-2: #c9760f;
  --criba-g-3: #8b3fd4;
  --criba-g-4: #a88410;
  --criba-g-5: #d1568e;
  --criba-g-resto: #a3a6ad;
  --criba-g-otros: #a3a6ad;
}
.criba-gr {
  margin: 4px 0 2px;
  padding: 10px 12px 8px;
  box-sizing: border-box;
  width: 100%;
  min-width: 0;
  max-width: 34rem;
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio-sm);
  background: var(--ji-bg);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.criba-gr-tit {
  font-family: var(--ji-ui);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ji-text);
}
.criba-gr-unidad {
  margin-left: 6px;
  font-weight: 400;
  color: var(--ji-muted);
}
.criba-gr-nota {
  margin: 0;
  font-family: var(--ji-ui);
  font-size: 12.5px;
  color: var(--ji-muted);
}
.criba-gr-lienzo {
  position: relative;
  width: 100%;
}
/* Fuera del flujo A PROPÓSITO: el SVG se dibuja al ancho medido, y si
   contara para el ancho de la caja, ésta no podría estrecharse nunca —el
   dibujo viejo la sostendría— y el gráfico se saldría en un móvil. */
.criba-gr-lienzo svg {
  position: absolute;
  top: 0;
  left: 0;
  display: block;
  overflow: visible;
}
.criba-gr svg text {
  font-family: var(--ji-ui);
  font-variant-numeric: tabular-nums;
}
.criba-gr-eje {
  font-size: 12px;
  fill: var(--ji-muted);
}
.criba-gr-valor {
  font-size: 12.5px;
  font-weight: 600;
  fill: var(--ji-text);
}
.criba-gr-fila {
  font-size: 13px;
  fill: var(--ji-muted);
}
.criba-gr-fila.propio {
  fill: var(--ji-text);
  font-weight: 600;
}
.criba-gr-rejilla {
  stroke: var(--ji-border);
  stroke-width: 1;
}
.criba-gr-cero {
  stroke: var(--ji-muted);
  stroke-width: 1;
  opacity: 0.6;
}
.criba-gr-regla {
  stroke: var(--ji-text);
  stroke-width: 1.25;
  stroke-dasharray: 4 3;
}
.criba-gr-regla-txt {
  font-size: 12px;
  fill: var(--ji-text);
}
.criba-gr-pista {
  fill: var(--ji-surface);
  stroke: var(--ji-border);
}
/* Relleno de las marcas: en SVG va en `fill`, en la leyenda HTML en `background`. */
path.criba-gr-c1, rect.criba-gr-c1 { fill: var(--criba-g-1); }
path.criba-gr-c2, rect.criba-gr-c2 { fill: var(--criba-g-2); }
path.criba-gr-otros { fill: var(--criba-g-otros); }
path.criba-gr-c1.claro { fill: color-mix(in srgb, var(--criba-g-1) 45%, transparent); }
circle.criba-gr-c1 { stroke: var(--criba-g-1); }
circle.criba-gr-c2 { stroke: var(--criba-g-2); }
circle.criba-gr-c3 { stroke: var(--criba-g-3); }
circle.criba-gr-c4 { stroke: var(--criba-g-4); }
circle.criba-gr-c5 { stroke: var(--criba-g-5); }
circle.criba-gr-resto { stroke: var(--criba-g-resto); }
i.criba-gr-c1 { background: var(--criba-g-1); }
i.criba-gr-c2 { background: var(--criba-g-2); }
i.criba-gr-c3 { background: var(--criba-g-3); }
i.criba-gr-c4 { background: var(--criba-g-4); }
i.criba-gr-c5 { background: var(--criba-g-5); }
i.criba-gr-resto { background: var(--criba-g-resto); }
i.criba-gr-c1.claro { background: color-mix(in srgb, var(--criba-g-1) 45%, transparent); }
.criba-gr-leyenda {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  font-family: var(--ji-ui);
  font-size: 12.5px;
  color: var(--ji-muted);
}
.criba-gr-leyenda span {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.criba-gr-leyenda i,
.criba-gr-partes i {
  flex: none;
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 2px;
}
.criba-gr-cifra {
  margin: 0;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 2px 10px;
  font-family: var(--ji-ui);
}
.criba-gr-cifra strong {
  font-size: 20px;
  font-weight: 600;
  color: var(--ji-text);
}
.criba-gr-cifra span {
  font-size: 13px;
  color: var(--ji-muted);
}
.criba-gr-reparto {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px 20px;
}
.criba-gr-reparto svg {
  flex: none;
}
.criba-gr-partes {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 5px;
  min-width: 0;
  font-family: var(--ji-ui);
  font-size: 12.5px;
}
.criba-gr-partes li {
  display: grid;
  grid-template-columns: 10px minmax(0, 1fr) auto;
  align-items: center;
  gap: 8px;
}
.criba-gr-parte-nom {
  color: var(--ji-text);
}
.criba-gr-parte-val {
  color: var(--ji-text);
  font-weight: 600;
}
.criba-gr-parte-val small {
  font-weight: 400;
  color: var(--ji-muted);
}
.criba-gr-pista-datos {
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(6.5rem, 1fr));
  gap: 6px 14px;
  font-family: var(--ji-ui);
}
.criba-gr-pista-datos dt {
  font-size: 12px;
  color: var(--ji-muted);
}
.criba-gr-pista-datos dd {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  color: var(--ji-text);
}
.criba-gr-pista-datos small {
  font-size: 13px;
  font-weight: 400;
  color: var(--ji-muted);
}
/* La muestra de la regla en la leyenda: la misma raya discontinua del gráfico. */
.criba-gr-leyenda i.criba-gr-regla-muestra {
  width: 14px;
  height: 0;
  border-radius: 0;
  border-top: 1.5px dashed var(--ji-text);
}

/* ── La criba para imprimir o guardar en PDF (`ImpresionCriba.tsx`) ────────
   Javi, 12-sep-2026. Un documento aparte, colgado de <body>: oculto en
   pantalla y lo único que sale en papel. Siempre en claro. */
.criba-imprimir {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 16px;
  margin: 0 0 12px;
  font-family: var(--ji-ui);
  font-size: 12.5px;
  color: var(--ji-muted);
}
.criba-imprimir label {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
}
@media screen {
  .criba-impresion {
    display: none;
  }
}
@media print {
  /* Fuera todo lo demás: con `display` y no con `visibility`, que deja el hueco
     y sacaría páginas en blanco delante. */
  body.imprimiendo-criba > :not(.criba-impresion) {
    display: none !important;
  }
  body.imprimiendo-criba {
    background: #fff !important;
  }
}
.criba-impresion {
  --ji-bg: #ffffff;
  --ji-surface: #ffffff;
  --ji-border: rgba(28, 22, 14, 0.16);
  --ji-text: #1c1a17;
  --ji-muted: #545861;
  --ji-gold: #9a6f1c;
  --ji-gain: #15877c;
  --ji-loss: #d5423e;
  --criba-g-1: #3d6fd6;
  --criba-g-2: #c9760f;
  --criba-g-3: #8b3fd4;
  --criba-g-4: #a88410;
  --criba-g-5: #d1568e;
  --criba-g-resto: #a3a6ad;
  --criba-g-otros: #a3a6ad;
  color: var(--ji-text);
  background: #fff;
  font-family: var(--ji-ui);
  font-size: 12.5px;
  line-height: 1.5;
  /* Sin esto el navegador quita los fondos al imprimir, y con ellos las barras
     del resumen y las muestras de color de las leyendas. */
  -webkit-print-color-adjust: exact;
  print-color-adjust: exact;
}
.ci-cab {
  padding-bottom: 10px;
  margin-bottom: 14px;
  border-bottom: 2px solid var(--ji-text);
}
.ci-marca {
  margin: 0;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ji-muted);
}
.ci-cab h1 {
  margin: 2px 0 2px;
  font-family: var(--ji-serif, var(--ji-ui));
  font-size: 24px;
  line-height: 1.2;
}
.ci-cab h1 span {
  font-family: var(--ji-mono);
  font-size: 15px;
  color: var(--ji-muted);
}
.ci-meta {
  margin: 0;
  color: var(--ji-muted);
}
.criba-impresion .criba-graf {
  background: #fff;
  break-inside: avoid;
}
.criba-impresion .criba-graf-pulsa {
  display: none;
}
.ci-bloque h2 {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 4px 10px;
  margin: 18px 0 8px;
  padding-bottom: 4px;
  font-size: 15px;
  border-bottom: 1px solid var(--ji-border);
  break-after: avoid;
}
.ci-bloque h2 span {
  font-size: 11.5px;
  font-weight: 400;
  color: var(--ji-muted);
}
.ci-preg {
  padding: 8px 0 10px;
  border-bottom: 1px solid var(--ji-border);
}
.ci-preg > * + * {
  margin-top: 6px;
}
/* Una pregunta con gráfico ocupa media hoja: si no se pudiera partir, cada
   una saltaría de página y el PDF sería medio blanco. Lo que no se parte es
   el gráfico, cada punto del porqué, y el enunciado se queda con lo que
   sigue. Y en bloque, no en flex: dentro de un flex los saltos de página
   no se respetan igual en todos los navegadores. */
/* `:not(:last-child)` A PROPÓSITO: una pregunta sin contestar sólo tiene el
   enunciado, y el «no partir después» del último hijo se hereda al final de
   la pregunta. Encadenadas, las 17 de un bloque se volvían un solo trozo que
   no se podía partir y saltaba entero a la hoja siguiente. */
.ci-enunciado:not(:last-child),
.criba-impresion .criba-expl-dato:not(:last-child) {
  break-after: avoid;
}
.criba-impresion .criba-expl-puntos li,
.criba-impresion .criba-expl-fuentes {
  break-inside: avoid;
}
.ci-preg.sin-contestar {
  color: var(--ji-muted);
}
.ci-enunciado {
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 13px;
  font-weight: 600;
}
.ci-num {
  flex: none;
  min-width: 18px;
  font-family: var(--ji-mono);
  font-size: 11px;
  font-weight: 400;
  color: var(--ji-muted);
}
.ci-texto {
  flex: 1;
}
.ci-ayuda {
  margin: 0;
  color: var(--ji-muted);
}
.criba-impresion .criba-gr {
  max-width: none;
  background: #fff;
  break-inside: avoid;
}
.ci-explica {
  padding: 6px 10px;
  border-left: 2px solid var(--ji-border);
  color: var(--ji-muted);
  font-size: 11.5px;
}
.ci-explica p {
  margin: 0 0 4px;
}
.ci-pie {
  margin-top: 18px;
  padding-top: 8px;
  border-top: 1px solid var(--ji-border);
  font-size: 11px;
  color: var(--ji-muted);
}

/* ── El régimen macro en la criba (`RegimenCriba.tsx`, ADR-0017) ───────────
   Ya no es una pregunta con botones: una tarjeta por semáforo con el
   veredicto automático, lo que dicen los datos, la gráfica y la regla. */
.rg-lista {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.rg-semaforo {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 14px;
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio-sm);
  background: var(--ji-surface);
}
/*
  EL SEMÁFORO SE LEE COMO UNA PREGUNTA DE LA CRIBA, no como otra cosa.

  Javi, 18-sep-2026: *«el resultado del régimen sale completamente a la derecha
  y en pequeño. Ponlo como el resto de la criba»*. Tenía dos diferencias con
  `.criba-enunciado` / `.criba-resp`, y las dos se notaban: `space-between`
  clavaba el veredicto contra el borde derecho aunque el nombre del semáforo
  fuese corto, y el texto iba un punto más pequeño que el de las respuestas.

  Ahora son las mismas reglas: mismo hueco, mismo tamaño, y dentro de la vista
  el veredicto va pegado al nombre igual que la respuesta va pegada al
  enunciado. La única diferencia que se queda es de color, porque los estados
  son otros —a favor / en contra / sin calcular—, no `sí` / `no`.
*/
.rg-cab {
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: 9px;
  font-family: var(--ji-ui);
  font-size: 14.5px;
  color: var(--ji-text);
}
.rg-estado {
  margin-left: auto;
  flex: none;
  font-family: var(--ji-ui);
  font-size: 12.5px;
  font-weight: 600;
  padding: 2px 10px;
  border-radius: 999px;
  border: 1px solid var(--ji-border);
  color: var(--ji-muted);
}
/* En la vista del suscriptor, pegado al nombre — igual que `.criba-resp`. */
.criba-vista .rg-cab .rg-estado {
  margin-left: 0;
}
.rg-estado.favor {
  color: var(--ji-gain);
  border-color: color-mix(in srgb, var(--ji-gain) 45%, transparent);
}
.rg-estado.contra {
  color: var(--ji-loss);
  border-color: color-mix(in srgb, var(--ji-loss) 45%, transparent);
}
.rg-estado.sin {
  border-style: dashed;
}
.rg-resumen {
  margin: 0;
  font-family: var(--ji-ui);
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--ji-text);
}
.rg-regla {
  margin: 0;
  font-family: var(--ji-ui);
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--ji-muted);
}
.criba-impresion .rg-semaforo {
  background: #fff;
  break-inside: avoid;
}
/* La teoría de cada semáforo: apartados con su título (12-sep-2026). */
.rg-teoria .rg-apartado {
  margin-top: 10px;
}
.rg-teoria h4 {
  margin: 0 0 3px;
  font-family: var(--ji-ui);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ji-muted);
}
.rg-teoria .rg-apartado p {
  margin: 0;
  max-width: 46rem;
  font-family: var(--ji-ui);
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--ji-text);
}

/* ── Las dos capas de una respuesta (12-sep-2026) ─────────────────────────
   Javi: «lo que prima es la didáctica». La explicación clara es el texto
   principal, a tamaño de lectura; el detalle, plegado y más pequeño. */
.criba-expl-claro {
  margin: 0;
  max-width: 46rem;
  font-size: 14.5px;
  line-height: 1.65;
  color: var(--ji-text);
}
.criba-expl-detalle > summary {
  cursor: pointer;
  font-size: 13px;
  color: var(--ji-muted);
  list-style: none;
}
.criba-expl-detalle > summary::-webkit-details-marker {
  display: none;
}
.criba-expl-detalle > summary::before {
  content: '＋ ';
}
.criba-expl-detalle[open] > summary::before {
  content: '− ';
}
.criba-expl-detalle > summary:hover {
  color: var(--ji-text);
}
.criba-expl-detalle .criba-expl-puntos,
.criba-expl-detalle .criba-expl-texto {
  margin-top: 6px;
  font-size: 13.5px;
  color: var(--ji-muted);
}

/* La pista de caja con varios extras y con el hito (12-sep-2026): los extras,
   en tonos cada vez más claros del mismo azul; el hito, una raya naranja. */
path.criba-gr-c1.tono1, i.criba-gr-c1.tono1 { fill: color-mix(in srgb, var(--criba-g-1) 55%, transparent); background: color-mix(in srgb, var(--criba-g-1) 55%, transparent); }
path.criba-gr-c1.tono2, i.criba-gr-c1.tono2 { fill: color-mix(in srgb, var(--criba-g-1) 36%, transparent); background: color-mix(in srgb, var(--criba-g-1) 36%, transparent); }
path.criba-gr-c1.tono3, i.criba-gr-c1.tono3 { fill: color-mix(in srgb, var(--criba-g-1) 24%, transparent); background: color-mix(in srgb, var(--criba-g-1) 24%, transparent); }
path.criba-gr-c1.tono4, i.criba-gr-c1.tono4 { fill: color-mix(in srgb, var(--criba-g-1) 16%, transparent); background: color-mix(in srgb, var(--criba-g-1) 16%, transparent); }
.criba-gr-hito {
  stroke: var(--criba-g-2);
  stroke-width: 2.5;
}
.criba-gr-leyenda i.criba-gr-hito-muestra {
  width: 3px;
  height: 12px;
  border-radius: 0;
  background: var(--criba-g-2);
}

/* ── La criba en mesa: preguntas a la izquierda, cierre clavado a la derecha
   Javi, 13-sep-2026: «cuando quiero escribir mis conclusiones para elegir su
   estado, tengo que estar mirando arriba y abajo todo una y otra vez». En
   ancha, la sección se sale de los 60rem del editor hasta el ancho de la barra
   de módulos (1180 px), para que las gráficas de las respuestas no encojan al
   ceder sitio a la columna. En estrecha, la columna va detrás de las preguntas,
   donde siempre estuvieron el cierre y los riesgos. `CierreCriba.tsx`. */
.criba-mesa {
  display: grid;
  gap: 24px;
}
.criba-mesa-preguntas {
  min-width: 0;
}
.criba-cierre-col {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio-sm);
  background: var(--ji-surface);
  font-family: var(--ji-ui);
}
.criba-cierre-cab {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px 16px 12px;
  border-bottom: 1px solid var(--ji-border);
}
.criba-cierre-cab h3,
.criba-cierre-col .criba-cierre h3 {
  margin: 0;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ji-muted);
}
.criba-cierre-resumen {
  margin: 0;
  font-size: 13px;
  font-style: italic;
  line-height: 1.5;
  color: var(--ji-text);
}
/* Las barras, sin marco propio: ya van dentro de la columna. */
.criba-graf.compacto {
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
}
.criba-cierre-regimen {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin: 0;
}
.criba-cierre-etq {
  font-size: 12px;
  color: var(--ji-muted);
  margin-right: 2px;
}
.criba-cierre-regimen .rg-estado {
  font-size: 11px;
  padding: 1px 8px;
}
.criba-cierre-vistas {
  display: flex;
  gap: 4px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--ji-border);
}
.criba-cierre-vista {
  flex: 1 1 0;
  font-size: 12.5px;
  padding: 5px 6px;
  white-space: nowrap;
}
.criba-cierre-vista.on {
  background: var(--ji-surface-2);
  border-color: var(--ji-text);
  color: var(--ji-text);
}
.criba-cierre-vista .ji-num {
  color: var(--ji-muted);
  margin-left: 2px;
}
.criba-cierre-lista {
  padding: 10px 12px;
}
.criba-cierre-lista ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.criba-cierre-lista li.criba-cierre-corte {
  margin-top: 6px;
  padding-top: 10px;
  border-top: 1px dashed var(--ji-border);
}
.criba-cierre-guia {
  margin: 0 0 10px;
  font-size: 12px;
  line-height: 1.45;
  color: var(--ji-muted);
}
/* Cada fila es un botón que lleva a su pregunta: sin aspecto de botón, pero
   con foco visible. Dos líneas: la pregunta (y su respuesta, en «Todas») y
   debajo el dato, que suele ser largo —«FY23 53 % · FY24 36 % · FY25 32 %»— y
   al lado de la pregunta la dejaba en una columna de dos palabras. */
.criba-cierre-fila {
  all: unset;
  box-sizing: border-box;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 3px 8px;
  width: 100%;
  cursor: pointer;
  font-size: 13px;
  line-height: 1.4;
  color: var(--ji-text);
}
.criba-cierre-fila:hover .criba-cierre-que {
  text-decoration: underline;
  text-decoration-color: var(--ji-border);
  text-underline-offset: 3px;
}
.criba-cierre-fila:focus-visible {
  outline: 2px solid var(--ji-blue);
  outline-offset: 2px;
  border-radius: 4px;
}
.criba-cierre-que {
  min-width: 0;
}
.criba-cierre-que .criba-riesgo-bloque {
  margin-right: 6px;
}
.criba-cierre-que .criba-riesgo-falta {
  margin-left: 6px;
}
.criba-cierre-dato {
  grid-column: 1 / -1;
  font-size: 12px;
  font-weight: 600;
  color: var(--ji-text);
  overflow-wrap: anywhere;
}
.criba-cierre-fila.no .criba-cierre-dato,
.criba-cierre-dato.no {
  color: var(--ji-loss);
}
.criba-cierre-fila.compacta {
  font-size: 12.5px;
}
.criba-cierre-fila .criba-resp {
  margin-left: 0;
  font-size: 11px;
  padding: 1px 7px;
}
/* Las barras de la columna, en una línea cada una: nombre, barra y riesgos. */
.criba-graf.compacto .criba-graf-resumen {
  gap: 6px;
}
.criba-graf.compacto .criba-graf-fila {
  grid-template-columns: 62px minmax(0, 1fr) 4.5rem;
  gap: 8px;
}
.criba-graf.compacto .criba-graf-pie {
  grid-column: auto;
  white-space: nowrap;
}
.criba-graf.compacto .criba-graf-nom {
  font-size: 12px;
}
.criba-graf.compacto .criba-graf-barra {
  height: 12px;
}
.criba-graf.compacto .criba-graf-pie strong {
  font-size: 13px;
}
.criba-cierre-claro {
  margin: 4px 0 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ji-muted);
}
.criba-cierre-col .criba-cierre {
  margin: 0;
  padding: 12px 16px 14px;
  max-width: none;
  border-top: 1px solid var(--ji-border);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.criba-cierre-col .criba-conv {
  margin: 0;
}
.criba-cierre-col .criba-conv-op {
  flex: 1 1 0;
  width: auto;
}
.criba-cierre-col .criba-conv-que {
  margin: 0;
  font-size: 13px;
}
.criba-cierre-col .criba-aviso {
  margin: 0;
}
.criba-cierre-col .criba-explicacion {
  width: 100%;
  box-sizing: border-box;
  resize: vertical;
}

@media (min-width: 75rem) {
  .criba-mesa {
    --mesa: min(1180px, calc(100vw - 48px));
    width: var(--mesa);
    margin-inline: calc((100% - var(--mesa)) / 2);
    grid-template-columns: minmax(0, 1fr) 23rem;
    align-items: start;
  }
  /* Clavada debajo de la barra de módulos (58 px, también pegada), y con el
     alto de la ventana: la lista de en medio hace su propio scroll y el
     cuadro de la conclusión se queda siempre a la vista. */
  .criba-cierre-col {
    position: sticky;
    top: 70px;
    max-height: calc(100vh - 86px);
    max-height: calc(100dvh - 86px);
    /* Si en una ventana baja no cabe todo, que baje la columna entera antes
       que dejar la lista sin sitio. */
    overflow-y: auto;
  }
  .criba-cierre-lista {
    flex: 1 1 auto;
    min-height: 10rem;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}

/* «El negocio» dentro de la columna de cierre, y en el importador. */
.criba-cierre-negocio summary {
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  color: var(--ji-text);
}
.criba-cierre-negocio[open] {
  max-height: 40vh;
  overflow-y: auto;
  padding-right: 4px;
}
.criba-importar-negocio {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 10px 0;
  padding: 10px 12px;
  border: 1px solid var(--ji-border);
  border-radius: 8px;
  background: var(--ji-inset);
}
.criba-importar-negocio label {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 13.5px;
}
.criba-importar-negocio summary {
  cursor: pointer;
  font-size: 12.5px;
  color: var(--ji-muted);
}

/* «Copiar para el Radar», en la pestaña Estudio inicial (ADR-0016). */
.wl-copiar-estudio {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.wl-copiar-estudio .botonera {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
}
.wl-copiar-estudio textarea {
  width: 100%;
  box-sizing: border-box;
  font-family: var(--ji-mono);
  font-size: 12px;
}

/* ── La respuesta con gráfico: el gráfico a la derecha, si hay sitio ─────
   Javi, 13-sep-2026: «queda un gran espacio a la derecha; podrías poner las
   gráficas ahí». Lo decide el ancho de la propia explicación (consulta de
   contenedor), no el de la ventana: la misma respuesta va en la ficha, el
   editor, el importador y el PDF, cada uno con su ancho. Por debajo de 48rem,
   todo en una columna, como antes. */
.criba-expl {
  display: block;
  container-type: inline-size;
}
.criba-expl-rejilla,
.criba-expl-cuerpo {
  display: grid;
  gap: 6px;
  min-width: 0;
}
.criba-expl-graf {
  min-width: 0;
}
@container (min-width: 48rem) {
  .criba-expl.con-grafico .criba-expl-rejilla {
    grid-template-columns: minmax(0, 1fr) minmax(18rem, 30rem);
    /* La fila de abajo se lleva el alto del gráfico: sin el 1fr, el hueco
       quedaría entre el dato y el texto. */
    grid-template-rows: auto 1fr;
    grid-template-areas:
      'dato graf'
      'cuerpo graf';
    column-gap: 28px;
    align-items: start;
  }
  .criba-expl.con-grafico .criba-expl-dato {
    grid-area: dato;
  }
  .criba-expl.con-grafico .criba-expl-graf {
    grid-area: graf;
  }
  .criba-expl.con-grafico .criba-expl-cuerpo {
    grid-area: cuerpo;
  }
  .criba-expl.con-grafico .criba-gr {
    margin-top: 0;
  }
}

/* «Ver más» de la tabla de presentaciones (13-sep-2026): llegan todas, por tandas. */
.fil-mas {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 12px 0 0;
}

/* ── Cronología de la SEC (13-sep-2026): acciones arriba, hechos en carriles
   debajo, sobre el mismo calendario. El color sólo para lo que pregunta la
   criba (dorado) y las emisiones (naranja, como sus rayas); lo demás, gris.
   Ancho mínimo para que los carriles no se aprieten: en móvil se desplaza
   dentro de su marco. `CronologiaSec.tsx`. */
.cron-intro {
  max-width: 52rem;
  margin-bottom: 12px;
}
.cron-marco {
  overflow-x: auto;
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio-sm);
  background: var(--ji-surface);
  padding: 12px 8px 4px;
}
.cron-lienzo {
  min-width: 640px;
  position: relative;
}
.cron-lienzo svg {
  display: block;
  overflow: visible;
}
.cron-lienzo text {
  font-family: var(--ji-ui);
}
.cron-eje {
  font-size: 12px;
  fill: var(--ji-muted);
  font-variant-numeric: tabular-nums;
}
.cron-etq {
  font-size: 12.5px;
  fill: var(--ji-muted);
}
.cron-etq.clave {
  fill: var(--ji-text);
  font-weight: 600;
}
.cron-rejilla {
  stroke: var(--ji-border);
  stroke-width: 1;
}
.cron-carril {
  stroke: var(--ji-border);
  stroke-width: 1;
  stroke-dasharray: 2 4;
}
/* ── Los seis colores de la cronología (`CronologiaSec.tsx`) ───────────────
   Javi, 21-sep-2026: «los puntos siguen siendo casi todos grises». Once
   carriles no se distinguen por color, así que el color agrupa —seis
   familias— y el nombre exacto lo sigue dando la fila. El gris queda para
   «otros», o sea para lo que nadie ha clasificado aún.

   Paleta pasada por el validador (daltonismo en las tres dicromacias y
   contraste sobre el fondo) en los dos temas. Los tres primeros intentos NO
   pasaron: rojo, oro y naranja a la vez son el mismo color para un deuteranope
   —el caso frecuente—, y púrpura y azul también si tienen la misma claridad.
   De ahí salen las dos decisiones que parecen raras y no lo son: la alerta usa
   un rojo más hondo que `--ji-loss`, y el púrpura y el azul van uno claro y
   otro oscuro a propósito. Si se cambia un tono, se vuelve a pasar. */
:root {
  --cron-f-alerta: #c62f2f;
  --cron-f-personas: #c79bfa;
  --cron-f-dinero: #d9770f; /* el mismo naranja que la raya de las emisiones */
  --cron-f-negocio: #26a69a;
  --cron-f-resultados: #4a7fe0;
  --cron-f-otros: #5d6270;
}
:root[data-theme='light'] {
  --cron-f-alerta: #b02525;
  --cron-f-personas: #9b5fd8;
  --cron-f-dinero: #c9760f;
  --cron-f-negocio: #15877c;
  --cron-f-resultados: #1f4a9c;
  --cron-f-otros: #a3a6ad;
}
.cron-linea {
  fill: none;
  stroke: var(--criba-g-1);
  stroke-width: 2;
}
.cron-punto-acc {
  fill: var(--criba-g-1);
  stroke: var(--ji-surface);
  stroke-width: 2;
}
.cron-emision {
  stroke: var(--criba-g-2);
  stroke-width: 1.25;
  stroke-dasharray: 4 3;
}
.cron-punto {
  stroke: var(--ji-surface);
  stroke-width: 2;
  cursor: pointer;
}
/* SEIS FAMILIAS, no once colores (21-sep-2026). El porqué, en
   `calc/cronologiaSec.ts`: cada carril ya lleva su nombre al lado, así que el
   color no identifica — agrupa. Y el gris queda sólo para lo que nadie ha
   clasificado, que así informa en vez de ser el color de casi todo. */
.cron-punto.f-alerta {
  fill: var(--cron-f-alerta);
}
.cron-punto.f-personas {
  fill: var(--cron-f-personas);
}
.cron-punto.f-dinero {
  fill: var(--cron-f-dinero);
}
.cron-punto.f-negocio {
  fill: var(--cron-f-negocio);
}
.cron-punto.f-resultados {
  fill: var(--cron-f-resultados);
}
.cron-punto.f-otros {
  fill: var(--cron-f-otros);
}
/* El folleto de reventa, hueco: no trae acciones nuevas y no debe leerse igual
   que una ampliación. Es información aparte del color de la familia. */
.cron-punto.hueco {
  fill: var(--ji-surface);
  stroke: var(--cron-f-dinero);
  stroke-width: 1.75;
}
.cron-punto:hover {
  stroke: var(--ji-text);
}

/* Los años: píldoras que bajan de línea. Con veinte años son dos filas, que se
   leen mejor que una tira que se desplaza escondiendo la mitad. */
.cron-anios {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 12px;
}
.cron-anio {
  padding: 5px 12px;
  border: 1px solid var(--ji-border);
  border-radius: 999px;
  background: transparent;
  color: var(--ji-muted);
  font: inherit;
  font-size: 13px;
  font-variant-numeric: tabular-nums;
  font-weight: 500;
  cursor: pointer;
}
.cron-anio:hover:not(.on) {
  color: var(--ji-text);
  border-color: var(--ji-border-strong);
}
.cron-anio.on {
  background: var(--ji-gold-solid);
  border-color: var(--ji-gold-solid);
  color: #0d1119;
}
.cron-anio:focus-visible {
  outline: 2px solid var(--ji-gold-solid);
  outline-offset: 2px;
}
.cron-pista {
  margin-top: 12px;
}

/* Lo del año, escrito: día, de qué trata, qué dice y el documento. La marca
   repite el color del punto del gráfico, para que se crucen con la vista. */
.cron-lista {
  margin-top: 18px;
  max-width: 60rem;
}
.cron-lista-tit {
  margin: 0 0 10px;
  font-size: 15px;
  font-weight: 600;
}
.cron-mes + .cron-mes {
  margin-top: 14px;
}
.cron-mes-nombre {
  margin: 0 0 4px;
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ji-muted);
}
.cron-mes ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
.cron-fila {
  display: grid;
  grid-template-columns: 2.2rem 11.5rem minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 4px 12px;
  padding: 7px 0;
  border-top: 1px solid var(--ji-border);
  font-size: 14px;
}
.cron-fila-fecha {
  font-family: var(--ji-mono);
  font-size: 12.5px;
  color: var(--ji-muted);
  text-align: right;
}
.cron-fila-sobre {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 12.5px;
  color: var(--ji-muted);
}
.cron-marca {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--criba-g-otros);
}
/* Las mismas seis familias que los puntos de arriba: la lista se lee mirando
   el gráfico, y dos códigos de color para lo mismo no es un código. */
.cron-fila.f-alerta .cron-marca {
  background: var(--cron-f-alerta);
}
.cron-fila.f-personas .cron-marca {
  background: var(--cron-f-personas);
}
.cron-fila.f-dinero .cron-marca {
  background: var(--cron-f-dinero);
}
.cron-fila.f-negocio .cron-marca {
  background: var(--cron-f-negocio);
}
.cron-fila.f-resultados .cron-marca {
  background: var(--cron-f-resultados);
}
.cron-fila.f-otros .cron-marca {
  background: var(--cron-f-otros);
}
/* Lo que pregunta la criba, además, en negrita: el color agrupa, esto destaca. */
.cron-fila.clave .cron-fila-sobre {
  color: var(--ji-text);
  font-weight: 600;
}
.cron-fila.hueco .cron-marca {
  background: transparent;
  border: 1.75px solid var(--cron-f-dinero);
}
.cron-fila.acc .cron-marca {
  background: var(--criba-g-1);
}
.cron-fila-que {
  line-height: 1.45;
}
.cron-cambio {
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.cron-cambio.sube {
  color: var(--criba-g-2);
}
.cron-fila-doc {
  font-family: var(--ji-mono);
  font-size: 12px;
  color: var(--ji-muted);
  text-decoration: none;
  white-space: nowrap;
}
.cron-fila-doc:hover {
  color: var(--ji-gold);
}
/* En estrecho, el tema sube encima del texto y el documento baja. */
@media (max-width: 640px) {
  .cron-fila {
    grid-template-columns: 2rem minmax(0, 1fr);
  }
  .cron-fila-sobre,
  .cron-fila-que,
  .cron-fila-doc {
    grid-column: 2;
  }
}
.fil-items {
  display: block;
  margin-top: 2px;
  font-size: 12.5px;
  color: var(--ji-text);
}

/* «Pulsa para ampliarla», bajo cada captura de la guía fiscal. */
.fg-pista-ampliar {
  color: var(--ji-gold);
  white-space: nowrap;
}

/* ── Seguir empresas en el hub (13-sep-2026): el botón de la cronología y la
   lista de los ajustes. Apagado neutro y encendido en oro, como los demás
   conmutadores. `SeguirEnHub.tsx` y `Hub.tsx`. */
.cron-cab {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 16px;
}
.seguir-hub {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
}
.seguir-hub-btn {
  padding: 6px 14px;
  border: 1px solid var(--ji-border);
  border-radius: 999px;
  background: transparent;
  color: var(--ji-muted);
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
}
.seguir-hub-btn:hover:not(:disabled):not(.on) {
  color: var(--ji-text);
  border-color: var(--ji-border-strong);
}
.seguir-hub-btn.on {
  background: var(--ji-gold-solid);
  border-color: var(--ji-gold-solid);
  color: #0d1119;
}
.seguir-hub-btn:focus-visible {
  outline: 2px solid var(--ji-gold-solid);
  outline-offset: 2px;
}
.seguir-hub-nota {
  font-size: 12px;
  color: var(--ji-muted);
}
.seguir-hub-nota.error {
  color: var(--ji-loss);
}
.hub-seguidas {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 10px 12px;
  border: 1px dashed var(--ji-border);
  border-radius: 10px;
}
.hub-seguidas-tit,
.hub-seguidas-vacio,
.hub-seguidas-aviso {
  margin: 0;
  font-size: 12.5px;
  color: var(--ji-muted);
}
.hub-seguidas-lista {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.hub-seguida {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 4px 2px 10px;
  border: 1px solid var(--ji-gold-solid);
  border-radius: 999px;
  font-size: 12.5px;
  color: var(--ji-gold);
}
.hub-seguida button {
  width: 22px;
  height: 22px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--ji-muted);
  font: inherit;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
}
.hub-seguida button:hover {
  color: var(--ji-text);
  background: var(--ji-surface-2);
}
.hub-seguidas-anadir {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.hub-seguidas-campo {
  flex: 1 1 12rem;
  min-width: 0;
  padding: 6px 10px;
  border: 1px solid var(--ji-border);
  border-radius: 8px;
  background: var(--ji-bg);
  color: var(--ji-text);
  font: inherit;
  font-size: 14px;
}
/* Safari de iOS amplía la página al enfocar un campo de menos de 16 px. */
@media (max-width: 720px) {
  .hub-seguidas-campo {
    font-size: 16px;
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   LA FICHA DE LA WATCHLIST, A LO ANCHO (15-sep-2026)
   Javi: «aprovechar los espacios laterales; la página queda muy
   verticalizada», y los botones arriba: «tener que bajar hasta abajo cada vez
   para ver la ficha completa es un engorro».
   ───────────────────────────────────────────────────────────────────────── */

/* La barra de arriba: volver a la izquierda, las acciones a la derecha. */
.wl-ficha-barra {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 20px;
  margin-bottom: 20px;
}
.wl-ficha-acciones {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
}
/* Mismo tamaño y misma forma que «Seguir en el hub», que va al lado. */
.wl-accion {
  display: inline-flex;
  align-items: center;
  padding: 6px 16px;
  border: 1px solid var(--ji-border-strong);
  border-radius: 999px;
  background: transparent;
  color: var(--ji-text);
  font: inherit;
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.wl-accion:hover {
  background: var(--ji-surface-2);
}
.wl-accion:focus-visible {
  outline: 2px solid var(--ji-gold-solid);
  outline-offset: 2px;
}
/* La que más se usa, la que se ve: dorada y rellena. */
.wl-accion.principal {
  background: var(--ji-gold-solid);
  border-color: var(--ji-gold-solid);
  color: #0d1119;
}
.wl-accion.principal:hover {
  background: color-mix(in srgb, var(--ji-gold-solid) 88%, #fff);
}
/* Borrar no viste como Editar: rojo, y solo el borde. */
.wl-accion.peligro {
  color: var(--ji-loss);
  border-color: color-mix(in srgb, var(--ji-loss) 45%, transparent);
}
.wl-accion.peligro:hover {
  background: color-mix(in srgb, var(--ji-loss) 12%, transparent);
}
/* Al lado de un botón dorado relleno, «la sigues» en dorado suave: dos
   rellenos juntos no dirían cuál es cuál. */
.wl-ficha-acciones .seguir-hub-btn.on {
  background: color-mix(in srgb, var(--ji-gold-solid) 14%, transparent);
  border-color: color-mix(in srgb, var(--ji-gold-solid) 45%, transparent);
  color: var(--ji-gold);
}

/* Con página resumen: ella a la izquierda, el segundo nivel a la derecha. */
.wl-ficha.con-pagina {
  grid-template-columns: minmax(0, 1.75fr) minmax(320px, 1fr);
  gap: 28px;
  margin-top: 0;
}
@media (max-width: 980px) {
  .wl-ficha.con-pagina {
    grid-template-columns: 1fr;
    gap: 20px;
  }
}
/* Contenedor: la página decide sus columnas por lo que mide ella, no la
   ventana, que con la columna lateral no es lo mismo. */
.wl-ficha-principal {
  container-type: inline-size;
  min-width: 0;
}
.wl-ficha-lateral {
  display: flex;
  flex-direction: column;
  gap: 16px;
  min-width: 0;
}

/* La página resumen, en un solo hilo.
   Aquí hubo dos columnas —el relato a la izquierda y los riesgos a la derecha—
   y se retiraron el 19-sep-2026: con dieciséis riesgos al lado de tres bloques
   cortos, la parte densa quedaba en la columna estrecha y las dos acababan a
   alturas muy distintas. Ahora `--ancha` sólo da más sitio, y quien reparte en
   dos es `.una-pagina-rejilla`, que es la que tiene dos cosas comparables:
   lo que está a favor y lo que está en contra. */
.una-pagina-cuerpo {
  display: grid;
  gap: 24px;
  align-content: start;
  min-width: 0;
}
.una-pagina-pastillas {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 6px;
}
.una-pagina-cartera {
  font-family: var(--ji-mono);
  font-size: 12px;
  letter-spacing: 0.06em;
  color: var(--ji-gain);
  background: color-mix(in srgb, var(--ji-gain) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--ji-gain) 34%, transparent);
  border-radius: 4px;
  padding: 3px 9px;
}

/* El historial en su propia caja, y lo anterior plegado. */
.hv.hv-caja {
  margin-top: 0;
  padding: 22px 24px;
  border: 1px solid var(--ji-border);
  border-radius: 16px;
  background: var(--ji-surface);
}
.hv-resto {
  margin-top: 12px;
}
.hv-resto > .hv-linea {
  margin-top: 12px;
}

/* ─────────────────────────────────────────────────────────────────────────
   LA BARRA DE MÓDULOS, EN DOS FILAS CUANDO NO CABE (15-sep-2026)
   Javi: «cuando la ventana se hace más pequeña, la barra superior se corta: se
   queda en Opciones y no se puede desplazar para ver el resto (Solicitudes,
   Glosario)». Sí se podía —`overflow-x: auto`—, pero con la barra de
   desplazamiento escondida y con un ratón, nada decía que se pudiera ni dejaba
   hacerlo sin Mayúsculas + rueda. Entera en una fila necesita unos 1.130 px
   (medido): por debajo, y hasta que en el móvil los módulos bajan al pie, van
   en una segunda fila, con sus nombres y sin carril oculto.
   ───────────────────────────────────────────────────────────────────────── */
:root {
  /* Lo que mide la barra de arriba: lo usan los elementos que se quedan pegados
     debajo de ella (la columna de controles de Opciones). */
  --alto-barra: 58px;
}
@media (min-width: 721px) and (max-width: 1180px) {
  :root {
    --alto-barra: 100px;
  }
  .bm-in {
    flex-wrap: wrap;
    height: var(--alto-barra);
    align-content: center;
    row-gap: 0;
  }
  .bm-marca {
    order: 1;
  }
  .bm-ctrl {
    order: 2;
    margin-left: auto;
  }
  .bm-modulos {
    order: 3;
    flex-basis: 100%;
    margin-left: -10px;
    flex-wrap: wrap;
    overflow: visible;
  }
  .bm-mod {
    padding: 0 10px;
  }
  .bm-mod.active::after,
  .bm-mod[aria-current='page']::after {
    left: 10px;
    right: 10px;
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   EL INTERRUPTOR DE TEMA: sol y luna, el pomo sobre el que está puesto.
   ───────────────────────────────────────────────────────────────────────── */
.tema-switch {
  position: fixed;
  left: 16px;
  bottom: 16px;
  z-index: 60;
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  width: 62px;
  height: 32px;
  padding: 0 8px;
  border: 1px solid var(--ji-border-strong);
  border-radius: 999px;
  background: var(--ji-surface);
  box-shadow: var(--ji-sombra);
  cursor: pointer;
}
.tema-switch:focus-visible {
  outline: 2px solid var(--ji-gold-solid);
  outline-offset: 2px;
}
/* Los dos iconos del carril, apagados: dicen qué hay a cada lado. */
.tema-switch-sol,
.tema-switch-luna {
  color: var(--ji-muted);
  opacity: 0.7;
}
.tema-switch-pomo {
  position: absolute;
  top: 3px;
  left: 3px;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: var(--ji-gold-solid);
  color: #0d1119;
  transition: transform 0.2s ease;
}
/* Oscuro: el pomo, a la derecha, sobre la luna. */
.tema-switch[aria-checked='true'] .tema-switch-pomo {
  transform: translateX(30px);
  background: var(--ji-surface-2);
  color: var(--ji-text);
  box-shadow: inset 0 0 0 1px var(--ji-border-strong);
}
@media (prefers-reduced-motion: reduce) {
  .tema-switch-pomo {
    transition: none;
  }
}
/* En el móvil los módulos van en una barra fija al pie: el interruptor sube
   por encima para no taparla. */
@media (max-width: 720px) {
  .tema-switch {
    bottom: calc(68px + env(safe-area-inset-bottom, 0px));
  }
}
/* Dentro de la barra de módulos (15-sep-2026): sin flotar ni sombra. El pomo
   va en `absolute`, así que el botón sigue siendo su referencia (`relative`). */
.tema-switch.en-barra {
  position: relative;
  left: auto;
  bottom: auto;
  z-index: auto;
  flex: none;
  box-shadow: none;
}
@media (max-width: 720px) {
  .tema-switch.en-barra {
    bottom: auto;
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   EL MENÚ, EN TRES FORMAS (16-sep-2026)
   Mismo marcado, tres maquetas según el ancho:
     · ≥ 1181 px  → menú LATERAL con los grupos rotulados.
     · 721-1180   → la barra de arriba en dos filas, sin rótulos de grupo.
     · ≤ 720 px   → la barra de abajo, solo iconos (lo de siempre).
   Los grupos vienen del Terminal de Quality Value; la idea es que el grupo
   diga qué es cada módulo sin tener que leer nada.
   ───────────────────────────────────────────────────────────────────────── */

/* En horizontal, el grupo no existe: sus módulos son hijos directos de la
   fila. `display: contents` lo consigue sin tocar el marcado. */
.bm-grupo {
  display: contents;
}
.bm-grupo-tit {
  display: none;
}

@media (min-width: 1181px) {
  :root {
    /* Sin barra arriba, lo que se queda pegado no tiene que esquivar nada. */
    --alto-barra: 16px;
    --ancho-menu: 236px;
  }
  .bm {
    position: fixed;
    inset: 0 auto 0 0;
    width: var(--ancho-menu);
    height: 100vh;
    height: 100dvh;
    overflow-y: auto;
    border-bottom: 0;
    border-right: 1px solid var(--ji-border);
    background: var(--ji-bg);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
  .bm-in {
    height: auto;
    min-height: 100%;
    max-width: none;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 20px 14px 16px;
  }
  .bm-marca {
    padding: 0 10px 18px;
    font-size: 18px;
  }
  .bm-modulos {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin: 0;
    overflow: visible;
  }
  .bm-grupo {
    display: flex;
    flex-direction: column;
    gap: 2px;
  }
  .bm-grupo + .bm-grupo {
    margin-top: 16px;
  }
  .bm-grupo-tit {
    display: block;
    margin: 0 0 4px;
    padding: 0 10px;
    font-family: var(--ji-mono);
    font-size: 10px;
    font-weight: 500;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--ji-muted);
  }
  /* Lo de Javi, al final y separado por una línea: es de otra naturaleza. */
  .bm-grupo--admin {
    margin-top: 22px;
    padding-top: 14px;
    border-top: 1px solid var(--ji-border);
  }
  .bm-mod {
    padding: 0 10px;
  }
  /* En vertical el filete de abajo no marca nada: la fila entera se enciende. */
  .bm-mod.active,
  .bm-mod[aria-current='page'] {
    background: var(--ji-surface);
  }
  .bm-mod.active::after,
  .bm-mod[aria-current='page']::after {
    left: 0;
    right: auto;
    top: 8px;
    bottom: 8px;
    width: 2px;
    height: auto;
    border-radius: 0 2px 2px 0;
  }
  /* Los controles, abajo del todo y en columna. */
  .bm-ctrl {
    margin: auto 0 0;
    padding: 14px 10px 0;
    border-left: 0;
    border-top: 1px solid var(--ji-border);
    flex-wrap: wrap;
    gap: 12px;
  }
  /* El lienzo deja el hueco del menú. */
  .app-lienzo {
    padding-left: var(--ancho-menu);
  }
  /* Lo que se pinta a pantalla completa (el universo de la watchlist) tapa
     también el menú: es un modo de mirar, no una pantalla más. */
  .wl-ficha-pc {
    left: 0;
  }
}
/* Lo de Javi solo en el menú lateral: en la barra horizontal serían doce
   iconos en fila, y en el móvil no se administra nada. Sigue estando en el
   bloque del final del hub. */
@media (max-width: 1180px) {
  .bm-grupo--admin {
    display: none;
  }
}

/* El grupo de administración se pliega (16-sep-2026): son cinco enlaces que
   solo usa Javi y que competían cada día con los módulos. */
@media (min-width: 1181px) {
  details.bm-grupo--admin {
    display: block;
  }
  .bm-grupo--admin > summary {
    display: flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
    list-style: none;
    padding: 4px 10px;
    border-radius: var(--ji-radio-sm);
  }
  .bm-grupo--admin > summary::-webkit-details-marker {
    display: none;
  }
  /* La flechita, a la izquierda del rótulo, girada cuando está abierto. */
  .bm-grupo--admin > summary::before {
    content: '▸';
    font-size: 9px;
    line-height: 1;
    transition: transform 0.15s;
  }
  .bm-grupo--admin[open] > summary::before {
    transform: rotate(90deg);
  }
  .bm-grupo--admin > summary:hover {
    color: var(--ji-text);
    background: var(--ji-surface);
  }
  .bm-grupo-lista {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-top: 2px;
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   LA PORTADA DEL HUB: lo último estudiado y los módulos en tarjetas
   (16-sep-2026, del Terminal de Quality Value).
   ───────────────────────────────────────────────────────────────────────── */
.hub-ultimo {
  margin: 28px 0 0;
}
.hub-ultimo .ji-eyebrow {
  margin-bottom: 12px;
}
.hub-modulos {
  display: flex;
  flex-direction: column;
  gap: 22px;
  margin: 32px 0 0;
}
.hub-modulos-grupo .ji-eyebrow {
  margin-bottom: 10px;
}
.hub-modulos-rejilla {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr));
  gap: 12px;
}
/* La tarjeta: icono, nombre y para qué sirve. Sin sombra: son puertas, no
   objetos que floten sobre la portada. */
.hub-modulo {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  align-items: center;
  gap: 4px 12px;
  padding: 16px 18px;
  border: 1px solid var(--ji-border);
  border-radius: var(--ji-radio);
  background: var(--ji-surface);
  color: var(--ji-muted);
  text-decoration: none;
  transition: border-color 0.16s, background 0.16s;
}
.hub-modulo:hover,
.hub-modulo:focus-visible {
  border-color: color-mix(in srgb, var(--ji-gold-solid) 40%, transparent);
  background: var(--ji-surface-2);
}
.hub-modulo svg {
  grid-row: span 2;
  color: var(--ji-gold);
}
.hub-modulo-nombre {
  font-family: var(--ji-serif);
  font-size: 17px;
  color: var(--ji-text);
}
.hub-modulo-que {
  font-size: 13px;
  line-height: 1.5;
}

/* ─────────────────────────────────────────────────────────────────────────
   LA BIENVENIDA (16-sep-2026). Cinco pasos, uno en pantalla, y el último es
   la rutina. Ancho de lectura de verdad —una columna estrecha—: es texto para
   leer, no un panel para vigilar, y aquí la tentación de aprovechar el ancho
   es justo la equivocada.
   ───────────────────────────────────────────────────────────────────────── */
.bienvenida {
  position: relative;
  isolation: isolate;
  max-width: 680px;
  margin-inline: auto;
  padding: clamp(18px, 3vh, 34px) clamp(16px, 4vw, 28px) 40px;
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 18px;
}
.bv-cabecera {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
}
.bv-salir {
  font-size: 13px;
  color: var(--ji-muted);
  text-decoration: none;
  transition: color 0.16s;
}
.bv-salir:hover,
.bv-salir:focus-visible {
  color: var(--ji-text);
}

/* Los pasos, en barras y no en puntos: una barra dice cuánto queda, y un punto
   solo dice cuántos hay. Son botones, así que se puede saltar a cualquiera. */
.bv-puntos {
  display: flex;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.bv-puntos li {
  flex: 1;
}
.bv-punto {
  display: block;
  width: 100%;
  height: 4px;
  padding: 0;
  border: 0;
  border-radius: 999px;
  background: var(--ji-border);
  cursor: pointer;
  transition: background 0.2s;
}
.bv-punto.hecho {
  background: color-mix(in srgb, var(--ji-gold-solid) 45%, transparent);
}
.bv-punto.on {
  background: var(--ji-gold-solid);
}
/* El área de pulsación real es mayor que la barra, que tiene 4 px de alto. */
.bv-punto::after {
  content: '';
  display: block;
  height: 18px;
  margin-top: -7px;
}

.bv-paso h1 {
  margin: 10px 0 0;
  font-family: var(--ji-serif);
  font-size: clamp(26px, 4.2vw, 34px);
  font-weight: 400;
  line-height: 1.18;
  text-wrap: balance;
}
.bv-entradilla {
  margin: 10px 0 18px;
  font-size: 17px;
  line-height: 1.5;
  color: var(--ji-gold);
}
.bv-paso p {
  margin: 0 0 14px;
  font-size: 15px;
  line-height: 1.7;
  color: var(--ji-muted);
}
.bv-paso p:last-child {
  margin-bottom: 0;
}

/* La rutina: cuándo, cuánto y qué. Cada momento con su filete a la izquierda,
   que es lo que hace que se lea como una agenda y no como un párrafo troceado. */
.bv-rutina {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 20px 0 0;
  padding: 0;
  list-style: none;
}
.bv-rutina li {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2px 16px;
  padding: 14px 16px;
  border-left: 2px solid color-mix(in srgb, var(--ji-gold-solid) 55%, transparent);
  background: var(--ji-surface);
}
.bv-rutina li:first-child {
  border-radius: var(--ji-radio) var(--ji-radio) 0 0;
}
.bv-rutina li:last-child {
  border-radius: 0 0 var(--ji-radio) var(--ji-radio);
}
.bv-rutina-cuando {
  font-family: var(--ji-serif);
  font-size: 17px;
  color: var(--ji-text);
}
.bv-rutina-tiempo {
  font-size: 12px;
  letter-spacing: 0.04em;
  color: var(--ji-muted);
  text-align: right;
}
.bv-rutina-que {
  grid-column: 1 / -1;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ji-muted);
}

.bv-pie {
  display: flex;
  gap: 10px;
  margin-top: 26px;
}
.bv-btn {
  padding: 11px 22px;
  border: 1px solid var(--ji-border);
  border-radius: 999px;
  background: transparent;
  color: var(--ji-text);
  font-family: var(--ji-ui);
  font-size: 14px;
  cursor: pointer;
  transition: border-color 0.16s, background 0.16s, color 0.16s;
}
.bv-btn:hover:not(:disabled),
.bv-btn:focus-visible {
  border-color: color-mix(in srgb, var(--ji-gold-solid) 45%, transparent);
  background: var(--ji-surface-2);
}
.bv-btn:disabled {
  opacity: 0.4;
  cursor: default;
}
/* El que sigue adelante, que es el que se busca sin mirar. */
.bv-btn--fuerte {
  margin-left: auto;
  border-color: color-mix(in srgb, var(--ji-gold-solid) 55%, transparent);
  background: color-mix(in srgb, var(--ji-gold-solid) 14%, transparent);
}
.bv-nota {
  margin: 30px 0 0;
  padding-top: 16px;
  border-top: 1px solid var(--ji-border);
  font-size: 13px;
  line-height: 1.6;
  color: var(--ji-muted);
}
.bv-nota a {
  color: var(--ji-gold);
}

@media (prefers-reduced-motion: reduce) {
  .bv-punto,
  .bv-btn,
  .bv-salir {
    transition: none;
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   LA COMUNIDAD (16-sep-2026). Misma columna de lectura que la bienvenida: es
   una pantalla que se lee una vez y de la que sale uno con un enlace.
   ───────────────────────────────────────────────────────────────────────── */
.comunidad {
  position: relative;
  isolation: isolate;
  max-width: 680px;
  margin-inline: auto;
  padding: clamp(18px, 3vh, 34px) clamp(16px, 4vw, 28px) 40px;
}
.cm-titulo {
  margin: 10px 0 0;
  font-family: var(--ji-serif);
  font-size: clamp(26px, 4.2vw, 34px);
  font-weight: 400;
  line-height: 1.18;
  text-wrap: balance;
}
.cm-entradilla {
  margin: 10px 0 0;
  font-size: 17px;
  line-height: 1.5;
  color: var(--ji-gold);
}
.cm-bloque {
  margin-top: 30px;
  padding-top: 24px;
  border-top: 1px solid var(--ji-border);
}
.cm-bloque h2 {
  margin: 0 0 12px;
  font-family: var(--ji-serif);
  font-size: 21px;
  font-weight: 400;
}
.cm-bloque p {
  margin: 0 0 12px;
  font-size: 15px;
  line-height: 1.7;
  color: var(--ji-muted);
}
.cm-bloque p:last-child {
  margin-bottom: 0;
}
.cm-bloque strong {
  color: var(--ji-text);
  font-weight: 600;
}
/* Lo que todavía no existe, dicho sin disimulo: caja aparte para que no se lea
   como si fuera parte de la descripción. */
.cm-pendiente {
  padding: 14px 16px;
  border-left: 2px solid color-mix(in srgb, var(--ji-gold-solid) 55%, transparent);
  background: var(--ji-surface);
  border-radius: 0 var(--ji-radio) var(--ji-radio) 0;
}
.cm-btn {
  display: inline-block;
  padding: 11px 22px;
  border: 1px solid color-mix(in srgb, var(--ji-gold-solid) 55%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--ji-gold-solid) 14%, transparent);
  color: var(--ji-text);
  font-size: 14px;
  text-decoration: none;
  transition: background 0.16s, border-color 0.16s;
}
.cm-btn:hover,
.cm-btn:focus-visible {
  background: color-mix(in srgb, var(--ji-gold-solid) 22%, transparent);
}
.cm-lista {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.cm-lista li {
  font-size: 15px;
  line-height: 1.65;
  color: var(--ji-muted);
  padding-left: 16px;
  border-left: 1px solid var(--ji-border);
}
.cm-nota {
  margin: 34px 0 0;
  padding-top: 16px;
  border-top: 1px solid var(--ji-border);
  font-size: 13px;
  line-height: 1.6;
  color: var(--ji-muted);
}
.cm-nota a {
  color: var(--ji-gold);
}

@media (prefers-reduced-motion: reduce) {
  .cm-btn {
    transition: none;
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   LAS PUBLICACIONES (16-sep-2026): el archivo del Substack, por categoría y
   por año. Lista, no tarjetas: son cincuenta entradas y lo que se hace con
   ellas es recorrerlas con la vista, no compararlas.
   ───────────────────────────────────────────────────────────────────────── */
.publicaciones {
  position: relative;
  isolation: isolate;
  max-width: 820px;
  margin-inline: auto;
  padding: clamp(18px, 3vh, 34px) clamp(16px, 4vw, 28px) 40px;
}
.pb-titulo {
  margin: 10px 0 0;
  font-family: var(--ji-serif);
  font-size: clamp(26px, 4.2vw, 34px);
  font-weight: 400;
  line-height: 1.18;
  text-wrap: balance;
}
.pb-entradilla {
  margin: 10px 0 0;
  max-width: 62ch;
  font-size: 15px;
  line-height: 1.6;
  color: var(--ji-muted);
}
.pb-aviso {
  margin: 20px 0 0;
  padding: 14px 16px;
  border-left: 2px solid color-mix(in srgb, var(--ji-gold-solid) 55%, transparent);
  background: var(--ji-surface);
  border-radius: 0 var(--ji-radio) var(--ji-radio) 0;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ji-muted);
}
.pb-aviso a {
  color: var(--ji-gold);
}

.pb-filtros {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 24px 0 0;
}
.pb-filtro {
  padding: 7px 14px;
  border: 1px solid var(--ji-border);
  border-radius: 999px;
  background: transparent;
  color: var(--ji-muted);
  font-family: var(--ji-ui);
  font-size: 13px;
  cursor: pointer;
  transition: border-color 0.16s, background 0.16s, color 0.16s;
}
.pb-filtro:hover,
.pb-filtro:focus-visible {
  color: var(--ji-text);
  border-color: color-mix(in srgb, var(--ji-gold-solid) 40%, transparent);
}
.pb-filtro.on {
  color: var(--ji-text);
  border-color: color-mix(in srgb, var(--ji-gold-solid) 55%, transparent);
  background: color-mix(in srgb, var(--ji-gold-solid) 14%, transparent);
}
.pb-cuantas {
  font-family: var(--ji-mono);
  font-variant-numeric: tabular-nums;
  font-size: 11px;
  opacity: 0.7;
}

.pb-anio {
  margin-top: 32px;
}
/* El año hace de separador, no de titular: pequeño, en la izquierda y con su
   línea, para que lo que resalte sean los títulos. */
.pb-anio h2 {
  margin: 0 0 6px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--ji-border);
  font-family: var(--ji-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.12em;
  color: var(--ji-muted);
}
.pb-lista {
  margin: 0;
  padding: 0;
  list-style: none;
}
.pb-post {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px 12px;
  margin: 0 -12px;
  border-radius: var(--ji-radio);
  text-decoration: none;
  transition: background 0.16s;
}
.pb-post:hover,
.pb-post:focus-visible {
  background: var(--ji-surface);
}
.pb-post-tit {
  font-family: var(--ji-serif);
  font-size: 18px;
  line-height: 1.3;
  color: var(--ji-text);
}
.pb-post-res {
  font-size: 14px;
  line-height: 1.55;
  color: var(--ji-muted);
}
.pb-post-pie {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 10px;
  margin-top: 2px;
  font-size: 12px;
  color: var(--ji-muted);
}
.pb-fecha {
  font-variant-numeric: tabular-nums;
}
.pb-cat {
  padding: 2px 8px;
  border: 1px solid var(--ji-border);
  border-radius: 999px;
}
.pb-cat--pago {
  border-color: color-mix(in srgb, var(--ji-gold-solid) 45%, transparent);
  color: var(--ji-gold);
}
.pb-min {
  font-variant-numeric: tabular-nums;
  opacity: 0.8;
}
.pb-nota {
  margin: 34px 0 0;
  padding-top: 16px;
  border-top: 1px solid var(--ji-border);
  font-size: 13px;
  line-height: 1.6;
  color: var(--ji-muted);
}
.pb-nota a {
  color: var(--ji-gold);
}

@media (prefers-reduced-motion: reduce) {
  .pb-filtro,
  .pb-post {
    transition: none;
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   «MÁS» Y SU HOJA (16-sep-2026, del Terminal de Quality Value).

   Solo existen en el teléfono: fuera de ahí la barra es un menú lateral o una
   fila en dos líneas, donde caben los diez módulos y esto sobra. De ahí que el
   botón nazca en `display: none` y lo encienda la consulta de 720 px.
   ───────────────────────────────────────────────────────────────────────── */
.bm-mas {
  display: flex;
  flex: 1;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 48px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--ji-muted);
  font-family: var(--ji-ui);
  font-size: 13px;
  cursor: pointer;
}
.bm-mas.on {
  color: var(--ji-gold);
}

/* El fondo: oscurece lo de detrás y cierra al tocarlo. Deja ver la barra, que
   es desde donde se ha abierto. */
.bm-hoja-fondo {
  position: fixed;
  inset: 0;
  z-index: 40;
  border: 0;
  padding: 0;
  background: color-mix(in srgb, var(--ji-bg) 72%, transparent);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  cursor: pointer;
}
.bm-hoja {
  position: fixed;
  z-index: 41;
  inset: auto 0 calc(56px + env(safe-area-inset-bottom, 0px));
  display: flex;
  flex-direction: column;
  gap: 4px;
  max-height: 70vh;
  overflow-y: auto;
  padding: 14px 12px 18px;
  background: var(--ji-bg);
  border-top: 1px solid var(--ji-border);
  box-shadow: 0 -18px 40px color-mix(in srgb, #000 28%, transparent);
}
.bm-hoja-grupo {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.bm-hoja-grupo + .bm-hoja-grupo {
  margin-top: 10px;
}
/* Dentro de la hoja los módulos vuelven a ser fila con su nombre: aquí sobra
   sitio y hay que poder leerlos, que es justo lo que la barra no permite. */
.bm-hoja .bm-mod {
  flex: none;
  justify-content: flex-start;
  min-height: 46px;
  padding: 0 12px;
  border-radius: var(--ji-radio-sm);
}
.bm-hoja .bm-txt {
  display: inline;
  font-size: 15px;
}
.bm-hoja .bm-mod:hover,
.bm-hoja .bm-mod:focus-visible {
  background: var(--ji-surface);
}
/* Los rótulos de grupo SÍ se ven aquí. En la barra estorbarían —no hay sitio—,
   pero la hoja es una lista y el grupo es lo que dice qué es cada cosa: es la
   misma idea que el menú lateral. */
.bm-hoja .bm-grupo-tit {
  display: block;
  margin: 0 0 4px;
  padding: 0 12px;
  font-family: var(--ji-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ji-muted);
}
/* Y el filete del activo pasa a la izquierda. Arriba, que es donde lo pone la
   barra de abajo, parecía de la fila anterior. */
.bm-hoja .bm-mod.active::after,
.bm-hoja .bm-mod[aria-current='page']::after {
  top: 8px;
  bottom: 8px;
  left: 0;
  right: auto;
  width: 2px;
  height: auto;
  border-radius: 0 2px 2px 0;
}
/* Si la ventana se ensancha con la hoja abierta, el botón que la cierra deja de
   existir. Que se vaya ella también: ahí está el menú entero. */
/*
  «Más» y su hoja son SOLO del teléfono. Se apagan aquí y no se encienden en la
  consulta estrecha, porque el bloque base va más abajo en el fichero y ganaría
  por orden — que es exactamente lo que dejó el botón invisible al escribirlo al
  revés.
*/
@media (min-width: 721px) {
  .bm-mas,
  .bm-hoja,
  .bm-hoja-fondo {
    display: none;
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   EL AVISO DE RENOVACIÓN (0075). Encima del contenido, dentro del lienzo: la
   idea es que EMPUJE la pantalla, no que la tape. Dos intensidades — cuando
   todavía no ha vencido es un recordatorio; cuando corre el margen de gracia
   es lo primero que hay que leer.
   ───────────────────────────────────────────────────────────────────────── */
.aviso-renovar {
  margin: 0 0 18px;
  padding: 12px 16px;
  border: 1px solid var(--ji-border);
  border-left: 3px solid color-mix(in srgb, var(--ji-gold-solid) 60%, transparent);
  border-radius: var(--ji-radio);
  background: var(--ji-surface);
  font-size: 14px;
  line-height: 1.6;
  color: var(--ji-muted);
}
.aviso-renovar a {
  color: var(--ji-gold);
  white-space: nowrap;
}
.aviso-renovar.urge {
  border-left-color: var(--ji-loss);
  color: var(--ji-text);
}

/* ─────────────────────────────────────────────────────────────────────────
   LO QUE VIENE: el próximo hecho con fecha y qué vigilar (16-sep-2026, del
   Terminal de Quality Value). Va arriba de la columna lateral de la ficha,
   porque contesta lo que se pregunta después de leer qué hace la empresa:
   cuándo se sabrá si la tesis iba bien.
   ───────────────────────────────────────────────────────────────────────── */
.wl-proximo {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 20px;
  border: 1px solid var(--ji-border);
  border-radius: 14px;
  background: var(--ji-surface);
}
.wl-evento {
  display: flex;
  align-items: center;
  gap: 16px;
}
/* El bloque de día y mes: lo único de la ficha que se lee de un vistazo desde
   lejos, como el taco de un calendario. */
.wl-evento-fecha {
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 58px;
  padding: 8px 0;
  border: 1px solid var(--ji-border);
  border-radius: 12px;
  background: var(--ji-bg);
}
.wl-evento-fecha .d {
  font-family: var(--ji-mono);
  font-variant-numeric: tabular-nums;
  font-size: 22px;
  line-height: 1;
  color: var(--ji-text);
}
.wl-evento-fecha .m {
  margin-top: 3px;
  font-family: var(--ji-mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  color: var(--ji-muted);
}
/* A menos de dos semanas, el taco se enciende. */
.wl-evento.cerca .wl-evento-fecha {
  border-color: color-mix(in srgb, var(--ji-gold-solid) 55%, transparent);
  background: color-mix(in srgb, var(--ji-gold-solid) 12%, transparent);
}
.wl-evento.cerca .wl-evento-fecha .d {
  color: var(--ji-gold);
}
/* Lo que ya pasó se apaga, NO se esconde: que la fecha pasara sin que la tesis
   se tocara es justo lo que hay que ver. */
.wl-evento.pasado {
  opacity: 0.55;
}
.wl-evento-txt {
  min-width: 0;
}
.wl-evento-que {
  margin: 4px 0 0;
  font-family: var(--ji-serif);
  font-size: 16px;
  line-height: 1.3;
  color: var(--ji-text);
}
.wl-evento-cuando {
  margin: 2px 0 0;
  font-size: 12px;
  color: var(--ji-muted);
}
.wl-vigilar ul {
  margin: 10px 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.wl-vigilar li {
  position: relative;
  padding-left: 16px;
  font-size: 14px;
  line-height: 1.55;
  color: var(--ji-muted);
}
.wl-vigilar li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 8px;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--ji-gold-solid) 70%, transparent);
}
/* Si hay las dos cosas, una línea las separa sin meter otra caja. */
.wl-evento + .wl-vigilar {
  padding-top: 14px;
  border-top: 1px solid var(--ji-border);
}

/* El vínculo con Discord (17-sep-2026): el botón, el estado y lo que trae la
   vuelta. Sobrio a propósito — es un trámite de una sola vez, no una fiesta. */
.cm-btn:disabled {
  opacity: 0.6;
  cursor: default;
}
.cm-pista {
  display: block;
  margin-top: 8px;
  font-size: 12px;
  line-height: 1.5;
  color: var(--ji-muted);
}
.cm-pista.error {
  color: var(--ji-loss);
}
.cm-conectado {
  padding: 12px 16px;
  border: 1px solid color-mix(in srgb, var(--ji-gain) 34%, transparent);
  border-radius: var(--ji-radio);
  background: color-mix(in srgb, var(--ji-gain) 10%, transparent);
  font-size: 14px;
}
.cm-conectado strong {
  color: var(--ji-text);
}
.cm-conectado a {
  color: var(--ji-gold);
  white-space: nowrap;
}
/* Lo que trae la vuelta de Discord. Va arriba del bloque porque es la respuesta
   a lo que la persona acaba de hacer. */
.cm-vuelta {
  padding: 12px 16px;
  border-left: 3px solid var(--ji-loss);
  border-radius: 0 var(--ji-radio) var(--ji-radio) 0;
  background: var(--ji-surface);
  font-size: 14px;
  line-height: 1.6;
}
.cm-vuelta.bien {
  border-left-color: var(--ji-gain);
}

/* ─────────────────────────────────────────────────────────────────────────
   LA PRESENTACIÓN DE CADA MÓDULO (17-sep-2026): sale la primera vez que se
   entra y se cierra para siempre. Empuja el contenido, no lo tapa — una capa
   flotante sobre una pantalla que no se conoce es justo lo que se cierra sin
   leer.
   ───────────────────────────────────────────────────────────────────────── */
.pv {
  display: flex;
  align-items: flex-start;
  gap: 20px;
  margin: 0 0 22px;
  padding: 20px 22px;
  border: 1px solid color-mix(in srgb, var(--ji-gold-solid) 30%, var(--ji-border));
  border-radius: var(--ji-radio);
  background: var(--ji-surface);
}
.pv-texto {
  min-width: 0;
  max-width: 68ch;
}
.pv-texto h2 {
  margin: 6px 0 10px;
  font-family: var(--ji-serif);
  font-size: 21px;
  font-weight: 400;
  line-height: 1.25;
  color: var(--ji-text);
}
.pv-texto p:not(.ji-eyebrow) {
  margin: 0 0 8px;
  font-size: 14px;
  line-height: 1.65;
  color: var(--ji-muted);
}
.pv-texto p:last-child {
  margin-bottom: 0;
}
.pv-cerrar {
  flex: none;
  margin-left: auto;
  padding: 9px 18px;
  border: 1px solid color-mix(in srgb, var(--ji-gold-solid) 45%, transparent);
  border-radius: 999px;
  background: color-mix(in srgb, var(--ji-gold-solid) 12%, transparent);
  color: var(--ji-text);
  font-family: var(--ji-ui);
  font-size: 13px;
  cursor: pointer;
  transition: background 0.16s;
}
.pv-cerrar:hover,
.pv-cerrar:focus-visible {
  background: color-mix(in srgb, var(--ji-gold-solid) 20%, transparent);
}
/* En el móvil, el botón debajo y a lo ancho: al lado del texto se queda en una
   columna de dos dedos. */
@media (max-width: 640px) {
  .pv {
    flex-direction: column;
    gap: 14px;
  }
  .pv-cerrar {
    margin-left: 0;
    width: 100%;
  }
}
@media (prefers-reduced-motion: reduce) {
  .pv-cerrar {
    transition: none;
  }
}
