/* Conexión C.O.R.E. — PWA
   =====================================================================
   El portal es el registro por dentro. Comparte identidad con la landing
   (paleta, voces y forma viven en /tema.css) pero NO comparte su
   temperamento: la landing se ve una vez y tiene que persuadir; esto se
   usa a diario y tiene que quitarse de en medio.

   De ahí las tres diferencias deliberadas:
     · Sin titulares grandes. Aquí nadie viene a leer una tesis.
     · Filas regladas en vez de tarjetas flotantes. Un registro son
       renglones, y los renglones se comparan de un vistazo; las tarjetas
       con sombra obligan a saltar de isla en isla.
     · El acento se reserva para lo accionable y lo excepcional. Si el
       rojo lo pinta todo, deja de avisar de nada.

   Sin framework ni build: CSS plano con variables.
   ===================================================================== */

/* ---------------------------------------------------------------------------
   REGLAS DE MOVIMIENTO — restricciones, no adjetivos.

   1. Nada se mueve solo. Toda animación responde a una acción del usuario o a
      la llegada de datos que él pidió. Cero bucles, cero autoplay.
   2. Ningún movimiento pasa de 240 ms. Esto es una herramienta de trabajo: la
      animación confirma que algo pasó, no entretiene.
   3. Solo se animan `opacity` y `transform`. Son las dos propiedades que el
      navegador compone en la GPU; animar `height`, `top` o `width` provoca
      recálculo de layout y tirones en móviles de gama baja.
   4. Los desplazamientos son de 6 px como máximo. Lo suficiente para leer la
      dirección del cambio, no para llamar la atención.
   5. Una sola curva (`--curva`) en toda la app. Varias curvas se perciben como
      inconsistencia aunque nadie sepa nombrar por qué.
   6. `prefers-reduced-motion` desactiva todo. No es un extra: para alguien con
      trastorno vestibular, el movimiento provoca mareo real.

   Si una animación no cabe en estas reglas, la respuesta es no ponerla.

   EL REDISEÑO DE 2026-08-07 NO TOCÓ NADA DE ESTO. Atractivo no es sinónimo
   de animado: todo lo que cambió fue jerarquía, voz y densidad.
--------------------------------------------------------------------------- */

:root {
  --margen: max(1.25rem, env(safe-area-inset-left));
}

/* --------------------------------- Voces --------------------------------- */

/* El título encabeza la pantalla, así que tiene que ganarla al bizquear.
 * Estaba en 1.35rem mientras las cifras del resumen iban a 2.1rem: el número
 * pesaba vez y media más que el sitio donde estás, y la jerarquía salía al
 * revés. Sube el título y baja la cifra (ver .metrica); ninguno de los dos
 * cambia de papel, solo dejan de competir. */
h1 {
  font-size: 1.8rem;
  font-weight: 800;
  letter-spacing: -0.025em;
  /* Pegado a lo que encabeza: el resumen es su pie de foto, no otra zona. */
  margin: 0 0 var(--e4);
}
h2 { font-size: 1rem; font-weight: 700; margin: 0 0 var(--e2); letter-spacing: -0.01em; }
p { margin: 0 0 var(--e3); }

/* El rótulo: etiqueta, no narra. Misma voz que en la landing. */
.rotulo {
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--tenue);
}

/* ------------------------------- Salto y foco ---------------------------- */

.saltar {
  position: fixed;
  left: 0.5rem;
  top: -4rem;
  z-index: 20;
  padding: 0.7rem 1.1rem;
  background: var(--acento);
  color: #fff;
  font-family: var(--mono);
  font-size: 0.74rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  text-decoration: none;
  transition: transform var(--normal) var(--curva);
}
.saltar:focus { transform: translateY(4.6rem); }

/* El foco se dibuja con el acento: contrasta contra papel y contra tinta. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible {
  outline: 2px solid var(--acento);
  outline-offset: 2px;
}

/* --------------------------------- Acceso -------------------------------- */

.centrado {
  max-width: 440px;
  margin: 0 auto;
  padding: 2.5rem var(--margen) 3rem;
}

.marca.grande { font-size: 1.6rem; text-align: center; }
.lema { text-align: center; font-weight: 700; margin: 0.5rem 0 0.4rem; letter-spacing: -0.015em; }
.portada { margin-bottom: 2rem; }
.portada .tenue { text-align: center; }

/* Pestañas: subrayado reglado, no píldoras. Una píldora es un botón; esto es
   un cambio de sección. */
.pestanas {
  display: flex;
  gap: 0;
  border-bottom: var(--regla);
  margin-bottom: 1.5rem;
}
.pestana {
  flex: 1;
  padding: 0.7rem 0.5rem;
  border: 0;
  border-bottom: 3px solid transparent;
  margin-bottom: -1.5px;
  background: transparent;
  color: var(--tenue);
  font-family: var(--mono);
  font-size: 0.74rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
}
.pestana.activa { color: var(--texto); border-bottom-color: var(--acento); }

/* --------------------------------- Bloques ------------------------------- */

/* Sin sombra y sin esquinas: un bloque del registro es un rectángulo con
   filete, no una tarjeta que levita. */
.tarjeta {
  background: var(--fondo-2);
  border: 1px solid var(--borde);
  padding: var(--e5);
}

label { display: block; margin-bottom: 0.9rem; font-size: 0.82rem; font-weight: 700; }
label small {
  display: block;
  font-weight: 400;
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.04em;
  color: var(--tenue);
  margin-top: 0.3rem;
}

input, select {
  width: 100%;
  margin-top: 0.4rem;
  padding: 0.7rem 0.75rem;
  background: var(--fondo);
  color: var(--texto);
  border: 1px solid var(--borde);
  border-radius: 0;
  font: inherit;
}
/* Lo que se teclea son datos del registro: teléfonos, correos, códigos. */
input[inputmode="numeric"], input[type="email"], input[type="password"] {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}
input:focus, select:focus { border-color: var(--acento); }

fieldset { border: 0; padding: 0; margin: 0 0 0.9rem; }
legend { font-size: 0.82rem; font-weight: 700; padding: 0; margin-bottom: 0.5rem; }

.opciones { display: grid; gap: 0; grid-template-columns: 1fr 1fr; border: 1px solid var(--borde); }
.opcion {
  padding: 0.75rem;
  text-align: center;
  border: 0;
  border-right: 1px solid var(--borde);
  background: var(--fondo);
  color: var(--tenue);
  font-family: var(--mono);
  font-size: 0.74rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
}
.opcion:last-child { border-right: 0; }
.opcion.activa { background: var(--texto); color: var(--fondo); }

button.primario {
  width: 100%;
  padding: 0.85rem;
  border: 1.5px solid var(--acento);
  border-radius: 0;
  background: var(--acento);
  color: #fff;
  font-family: var(--mono);
  font-size: 0.76rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
}
button.primario:disabled { opacity: 0.6; cursor: progress; }

/* Cambio de etiqueta sin que se vea el salto: el botón se desvanece, el texto
   cambia mientras está invisible y vuelve. Va DESPUÉS de `:disabled` a
   propósito: misma especificidad, manda el último. */
button.primario.cambiando { opacity: 0; }

.error { color: var(--error); font-size: 0.85rem; margin: 0.75rem 0 0; min-height: 1.2em; }
.pie { text-align: center; margin-top: 1.5rem; }

/* --------------------------------- Portal -------------------------------- */

.barra {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 0.9rem var(--margen);
  border-bottom: var(--regla);
  background: var(--fondo);
  position: sticky;
  top: 0;
  z-index: 3;
}
.enlace {
  background: 0;
  border: 0;
  color: var(--tenue);
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  cursor: pointer;
}

/* Baja de línea, NO se desplaza de lado.
 *
 * Con `overflow-x: auto` un móvil de 375 px enseñaba tres de las siete
 * pestañas y escondía las otras cuatro —incluida «Asesor»— sin ninguna pista
 * de que la barra se pudiera arrastrar. Es el mismo fallo que el cliente ya
 * reportó en las bandejas del panel ("no me aparece"): tenía razón desde donde
 * miraba, porque un desplazamiento lateral sin indicio es una función
 * escondida. Se corrigió allí y quedó aquí, que es la navegación PRINCIPAL.
 */
.navegacion {
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  padding: 0 var(--margen);
  border-bottom: 1px solid var(--borde);
  background: var(--fondo);
  position: sticky;
  top: 53px;
  z-index: 2;
}
.nav {
  padding: 0.7rem 0.9rem;
  border: 0;
  border-bottom: 3px solid transparent;
  margin-bottom: -1px;
  background: transparent;
  color: var(--tenue);
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
}
.nav.activa { color: var(--texto); border-bottom-color: var(--acento); }

.contenido { max-width: 900px; margin: 0 auto; padding: 2rem var(--margen) 4rem; }

/* Fichas con filete propio y un hueco real entre ellas.
   Se probó primero el filete continuo —fondo de la rejilla asomando por
   huecos de 1 px— porque parece más un libro reglado. No sobrevive a datos
   reales: con 4 fichas en 3 columnas, las 2 celdas vacías de la última fila
   se pintan como bloques sólidos de color borde. Una técnica que se rompe en
   cuanto cambia el número de filas no vale para una lista. */
/* El resumen es un vistazo, no el trabajo.
 *
 * En un móvil de 375 px las cinco fichas se apilaban a todo lo ancho y se
 * comían el 71 % de la primera pantalla: el asesor abría su herramienta diaria
 * y veía cinco números y ni una sola cosa que hacer. `minmax(230px, 1fr)` no
 * cabe dos veces en 375, así que caían siempre a una columna.
 *
 * Con 140 px caben dos por fila desde el móvil más estrecho. Cinco fichas
 * pasan de 574 px a unos 250, y la cola —que es el trabajo— sube a la primera
 * pantalla. */
.rejilla {
  display: grid;
  gap: var(--e2);
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  /* Cierra la zona del resumen. Es el hueco grande que faltaba: antes eran
     24 px, los mismos que separaban todo lo demás. */
  margin-bottom: var(--e6);
}

/* 150 px y no 200: el resumen del panel trae CINCO métricas y el contenido
   mide 900 px como mucho. Con 200 solo caben cuatro por fila y la quinta queda
   huérfana debajo, que es la rejilla desigual que ya tenía antes en 3+2. Con
   150 las cinco entran en una línea y el bloque se lee de un barrido. */
@media (min-width: 560px) {
  .rejilla { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--e3); }
}

/* En el móvil el resumen deja de ser fichas y pasa a ser RENGLONES.
 *
 * Aun a dos columnas, cinco fichas ocupaban 358 px —el 44 % de la pantalla— y
 * la cola seguía sin entrar en el primer golpe de vista. El asesor abre su
 * herramienta de trabajo en el teléfono y lo primero que ve son cifras que no
 * le piden hacer nada.
 *
 * Un renglón por dato: cifra y texto en la misma línea, sin caja, separados
 * por la regla del registro. Baja de ~110 px por dato a ~40. No es una versión
 * recortada de la ficha: es la forma que ya tiene el resto del producto, y en
 * una pantalla estrecha lee mejor que una cuadrícula de cajitas. */
@media (max-width: 559px) {
  .rejilla {
    display: block;
    border-top: 1px solid var(--borde);
    margin-bottom: var(--e6);
  }
  .rejilla .tarjeta {
    display: flex;
    align-items: baseline;
    gap: var(--e3);
    background: transparent;
    border: 0;
    border-bottom: 1px solid var(--borde);
    padding: var(--e3) 0;
  }
  .rejilla .metrica {
    font-size: 1.25rem;
    margin: 0;
    /* Ancho fijo para que las cifras queden en columna y se puedan comparar de
       arriba abajo, que es lo que se hace con un renglonado. */
    min-width: 2.5ch;
    text-align: right;
  }
  .rejilla .tarjeta p { margin: 0; }
}
.rejilla .tarjeta { padding: var(--e3); }

/* ------------------------------- El renglón ------------------------------
   La pieza central del portal. Un registro son renglones: etiqueta a la
   izquierda, dato a la derecha, filete debajo. El dato va en monoespaciada
   y con cifras tabulares para que las columnas se comparen sin esfuerzo.
--------------------------------------------------------------------------- */

/* Las filas de una ficha son un renglonado: por eso llevan regla y no hueco.
   Sube de 0.55 a 0.75rem —la fila pasa de 35 a 40 px— porque en una tarjeta
   con seis renglones seguidos el ojo necesita algo donde apoyarse entre uno y
   otro, y la regla sola no basta cuando van tan pegados. */
.dato {
  display: flex;
  justify-content: space-between;
  gap: var(--e4);
  padding: var(--e3) 0;
  border-bottom: 1px solid var(--borde);
}
.dato:last-child { border-bottom: 0; }
.dato span:first-child {
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--tenue);
  padding-top: 0.15rem;
  flex-shrink: 0;
}
.dato span:last-child {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.88rem;
  text-align: right;
  /* Un correo largo o un nombre de empresa largo no deben romper la fila. */
  overflow-wrap: anywhere;
}

/* La métrica: cifra grande en tinta, no en acento. El acento se reserva para
   lo accionable; un número no se pulsa. */
/* Baja de 2.1 a 1.7rem: sigue leyéndose de un vistazo, pero deja de pesar más
   que el título de la pantalla. Ver el comentario de h1. */
.metrica {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 1.7rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--texto);
  margin-bottom: var(--e1);
}

/* --------------------------------- Sellos -------------------------------- */

.etiqueta {
  display: inline-block;
  padding: 0.2rem 0.5rem;
  border: 1px solid var(--borde);
  background: transparent;
  color: var(--tenue);
  font-family: var(--mono);
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* Los sellos de verificación se distinguen por color, pero el texto SIEMPRE
   dice cuál es: en escala de grises o con daltonismo el color no informa. */
.sello-plata    { border-color: var(--tenue); color: var(--tenue); }
.sello-diamante { border-color: #a8862c; color: #a8862c; }
.sello-fundador { border-color: var(--acento); color: var(--acento); }

/* En el directorio, TODA ficha lleva la misma acción. Repetido en relleno
   sólido, el acento pinta media pantalla y deja de señalar nada; en contorno
   sigue leyéndose como el botón principal de su ficha y devuelve el rojo a lo
   que de verdad es excepcional. */
#lista-directorio button.primario {
  background: transparent;
  color: var(--acento);
}
@media (hover: hover) and (pointer: fine) {
  #lista-directorio button.primario:hover:not(:disabled) {
    background: var(--acento);
    color: #fff;
  }
}

.aviso { margin-top: 1.5rem; }
/* Un filtro cierra su banda de control: por eso el hueco grande va aquí y no
   entre las piezas de la banda. */
.filtro { max-width: 320px; margin-bottom: var(--e6); }

/* El interruptor de "solo lo mío": en línea, no apilado como los demás
   filtros. Es una casilla con su texto al lado, y el ancho de 320 px la
   dejaría flotando lejos de su etiqueta. */
.filtro-mios {
  display: flex;
  align-items: center;
  gap: var(--e2);
  max-width: none;
  /* Pegado a las pestañas: es parte de la misma banda de control. El hueco
     grande lo pone el filtro de estado que va debajo, o el contenido. */
  margin: 0 0 var(--e4);
  cursor: pointer;
}
.filtro-mios input { width: auto; margin: 0; }

/* Aviso que hay que leer antes de pulsar, no una nota al pie. Se distingue de
   .tenue a propósito: lo que advierte —que dar de alta abre el panel entero—
   es justo lo que nadie espera al escribir un nombre y un teléfono.

   Usa la MISMA regla que el resto del proyecto (`--regla`) y el acento ya
   definido, no un dorado propio. La primera versión inventaba dos variables
   —`--borde-fuerte` y `--fondo-aviso`— que no existen en ningún sitio, así que
   caía siempre al color escrito a mano: fuera de paleta y, peor, fijo. En modo
   oscuro se habría quedado clavado mientras todo lo demás cambiaba. */
.aviso-fuerte {
  border-left: var(--regla);
  padding: 0.6rem 0 0.6rem 0.9rem;
  margin: 0 0 1.25rem;
  background: var(--acento-suave);
  font-size: 0.9rem;
  line-height: 1.5;
}

/* -------------------------------- El brindis ------------------------------ */

.brindis {
  position: fixed;
  left: 50%;
  bottom: max(1.5rem, env(safe-area-inset-bottom));
  transform: translate(-50%, 0);
  background: var(--texto);
  color: var(--fondo);
  padding: 0.7rem 1.1rem;
  font-family: var(--mono);
  font-size: 0.76rem;
  letter-spacing: 0.06em;
  z-index: 10;
  /* Está siempre en la página (ver el comentario de index.html): sin esto
     taparía los clics de lo que tenga debajo. No lleva nada pulsable. */
  pointer-events: none;
}

/* Aquí estaba el forzado a UNA columna por debajo de 480 px, que es lo que
   hacía que el resumen se comiera el 71 % de la primera pantalla del móvil.
   Se quita: `minmax(140px, 1fr)` ya decide solo, y en 375 px caben dos.

   Dos columnas de cifras no aprietan nada —una métrica es un número corto y
   una línea de texto—, y lo que se gana es que el TRABAJO entre en la primera
   pantalla en vez de quedar debajo de cinco cajas. */

/* ------------------------------- Movimiento -------------------------------
   INTACTO desde antes del rediseño. Cumple las seis reglas de arriba.
--------------------------------------------------------------------------- */

/* Entrada de contenido recién cargado. Se dispara al añadir la clase desde JS,
   nunca al cargar la página: si todo entra animado a la vez, es ruido. */
@keyframes entrar {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

.entra { animation: entrar var(--normal) var(--curva) both; }

/* Escalonado corto en listas. Se corta a los 6 elementos: más allá, el último
   tarda tanto en aparecer que se percibe como lentitud, no como elegancia. */
.rejilla > *:nth-child(1) { animation-delay: 0ms; }
.rejilla > *:nth-child(2) { animation-delay: 30ms; }
.rejilla > *:nth-child(3) { animation-delay: 60ms; }
.rejilla > *:nth-child(4) { animation-delay: 90ms; }
.rejilla > *:nth-child(5) { animation-delay: 120ms; }
.rejilla > *:nth-child(n + 6) { animation-delay: 150ms; }

/* Realimentación táctil: el elemento cede al pulsarlo. Es el movimiento más
   valioso de una interfaz y el más barato. */
.pestana, .nav, .opcion, button.primario, .tarjeta {
  transition: transform var(--rapido) var(--curva),
              background-color var(--rapido) var(--curva),
              border-color var(--rapido) var(--curva),
              opacity var(--rapido) var(--curva);
}

button.primario:active:not(:disabled),
.opcion:active,
.pestana:active,
.nav:active { transform: scale(0.97); }

/* Las fichas del directorio solo reaccionan si son accionables. Elevar algo
   que no se puede pulsar promete una interacción que no existe. */
@media (hover: hover) and (pointer: fine) {
  #lista-directorio .tarjeta:hover { background: var(--fondo); }
}

/* El brindis entra Y SALE por el mismo eje. Transición y no keyframes: dos
   avisos seguidos deben reconducir desde donde esté el actual; con keyframes
   se reinicia desde cero y da un salto. El `translate()` lleva SIEMPRE el
   -50% del centrado: animar hacia `transform: none` con relleno `both` ganaba
   a la regla base y dejaba el aviso corrido media caja. */
.brindis {
  transition: opacity var(--normal) var(--curva),
              transform var(--normal) var(--curva);
}

.brindis.oculto {
  opacity: 0;
  transform: translate(-50%, 6px);
}

/* Cambio de sección: solo opacidad. Desplazar el contenido principal al navegar
   marea en pantallas pequeñas. */
.contenido section { animation: aparecer var(--normal) var(--curva) both; }

@keyframes aparecer {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Regla 6: si el sistema pide menos movimiento, no hay movimiento. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
    scroll-behavior: auto !important;
  }
}

/* --------------------------------- La marca -------------------------------
   El logotipo se pinta como MÁSCARA: el SVG aporta la forma y el color lo pone
   `background-color` desde aquí, que es la única capa que conoce el tema.

   Se llegó a esto tras dos intentos fallidos. `currentColor` no cruza la
   frontera de una imagen externa, y resolver `prefers-color-scheme` dentro del
   propio SVG funciona en Chrome de escritorio pero NO en móvil: en modo oscuro
   la marca no se veía. Con máscara no hay frontera que cruzar.
--------------------------------------------------------------------------- */

.marca .palabra {
  display: block;
  width: 108px;
  height: 18px;
  background-color: currentColor;
  -webkit-mask: url("/logotipo.svg") no-repeat center / contain;
  mask: url("/logotipo.svg") no-repeat center / contain;
}

/* En la pantalla de acceso la marca preside: va centrada y al doble. */
.marca.grande { display: flex; justify-content: center; }
.marca.grande .palabra { width: 208px; height: 35px; }

/* ----------------------------- Marca de carga -----------------------------
   El tercer acto de la presentación de la landing, y solo ese: los dos arcos
   llegan y frenan. Sin costura y sin firma.

   Aquí manda la doctrina de movimiento, no el escaparate: 500 ms en vez de los
   1800 de la landing. Es la diferencia entre una página que se ve una vez y
   una herramienta que se abre a diario. Se sale del techo de 240 ms porque es
   una pantalla de espera —no confirma una acción, entretiene el vacío
   mientras llega la sesión— y aun así se queda en la mitad que la landing.
--------------------------------------------------------------------------- */

.marca-carga {
  display: block;
  width: 76px;
  height: 76px;
  margin: 0 auto 1.25rem;
  color: var(--acento);
}

.carga-arco {
  fill: none;
  stroke: currentColor;
  stroke-width: 54;
  transform-origin: 256px 256px;
  /* Estado base = final. Si la animación no corre, la marca sale montada y no
     torcida ni ausente. */
  animation: carga-llega 500ms cubic-bezier(0.16, 1, 0.3, 1) backwards;
}
.carga-inf { --giro: -52deg; }
.carga-sup { --giro: 52deg; animation-delay: 90ms; }

@keyframes carga-llega {
  from { transform: rotate(var(--giro)); }
  to   { transform: rotate(0deg); }
}

@media (prefers-reduced-motion: reduce) {
  .carga-arco { animation: none; }
}

/* ========================= PANEL ADMINISTRATIVO ===========================
   Superficie de trabajo diario, no escaparate. Aquí manda la densidad: el
   asesor necesita ver muchas filas de un vistazo y compararlas, no
   contemplarlas de una en una.

   NO SE AÑADE NI UNA ANIMACIÓN. Las seis reglas de arriba siguen mandando, y
   una tabla que se re-anima en cada tecleo del buscador es ruido puro: el
   resultado tiene que aparecer, no entrar en escena.
--------------------------------------------------------------------------- */

/* Sub-pestañas: mismo recurso que la navegación principal —subrayado reglado—
   pero un escalón por debajo en peso, para que se lea como jerarquía y no
   como dos barras compitiendo. */
/* Las bandejas BAJAN DE LÍNEA, no se desplazan de lado.

   Nacieron cuatro y con `overflow-x: auto` cabían. Al llegar a nueve, en un
   móvil de 375 px solo se veían TRES — las otras seis quedaban fuera del borde
   sin ninguna pista de que la barra se pudiera arrastrar. El cliente no
   encontró la pestaña "Asesores" y dio por hecho que no existía.

   Un desplazamiento lateral sin indicio es una función escondida. Con
   `flex-wrap` ocupa dos o tres renglones en móvil y se ve todo de una vez, que
   es lo que necesita una herramienta de trabajo diario. */
/* Las pestañas y el filtro son UNA banda de control, no tres bloques.
 *
 * Antes, «bandejas», «ver solo lo mío» y el selector de estado quedaban
 * separados por 20 px cada uno — el mismo hueco que los separaba del contenido
 * y del resumen. Nada agrupaba con nada. Ahora el filtro se pega a las
 * pestañas (--e2) y el hueco grande va DESPUÉS de la banda entera (--e6): así
 * se lee "aquí se elige qué mirar" y luego, aparte, lo que hay que mirar. */
.subnav {
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  border-bottom: 1px solid var(--borde);
  margin: 0 0 var(--e3);
}
.subtab {
  padding: 0.55rem 0.85rem;
  border: 0;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  background: transparent;
  color: var(--tenue);
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
}
/* Diez bandejas en dos líneas, todas idénticas: encontrar en cuál se está
   costaba un barrido entero. La activa gana también PESO, no solo color y
   subrayado. El peso se nota al bizquear; el color de un texto de 11 px, no.
   Y `--acento-suave` de fondo la ancla a su fila cuando la barra baja de
   línea, que es donde más se perdía. */
.subtab.activa {
  color: var(--texto);
  border-bottom-color: var(--acento);
  font-weight: 700;
  background: var(--acento-suave);
}

/* ------------------------------- Buscador -------------------------------- */

.buscador {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.75rem 1rem;
  padding-bottom: 1rem;
  border-bottom: 1px solid var(--borde);
}
.buscador label { margin: 0; font-size: 0.72rem; }
.buscador select, .buscador input { width: auto; min-width: 8.5rem; }
.campo-busqueda { flex: 1 1 16rem; }
.campo-busqueda input { width: 100%; }

/* --------------------------------- Tabla ---------------------------------
   Tabla de verdad, no una rejilla de tarjetas. Comparar quince empresas por
   sector o por estado exige columnas alineadas; con tarjetas hay que saltar
   de isla en isla.
--------------------------------------------------------------------------- */

.tabla { width: 100%; border-collapse: collapse; font-size: 0.86rem; }

.tabla th {
  text-align: left;
  padding: 0.5rem 0.6rem;
  border-bottom: var(--regla);
  font-family: var(--mono);
  font-size: 0.64rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--tenue);
  font-weight: 700;
  white-space: nowrap;
}

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

/* Los datos del sistema, en su voz: folios, teléfonos y fechas alineados. */
.tabla .dato-col {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  font-size: 0.78rem;
  white-space: nowrap;
}

.tabla tbody tr { cursor: pointer; }
@media (hover: hover) and (pointer: fine) {
  .tabla tbody tr:hover { background: var(--fondo-2); }
}
.tabla tbody tr.abierta { background: var(--acento-suave); }

/* Un correo o una empresa larga no pueden ensanchar la tabla hasta empujarla
   fuera de la pantalla. */
.tabla .recorta {
  max-width: 16rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.envuelve-tabla { overflow-x: auto; }

.paginacion {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-top: 1rem;
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.08em;
}
.paginacion button {
  padding: 0.4rem 0.8rem;
  border: 1px solid var(--borde);
  background: var(--fondo);
  color: var(--texto);
  font: inherit;
  text-transform: uppercase;
  cursor: pointer;
}
.paginacion button:disabled { opacity: 0.4; cursor: default; }

/* --------------------------------- Estados ------------------------------- */

/* El estado se distingue por TEXTO además de por color: en escala de grises o
   con daltonismo el color no informa. Mismo criterio que los sellos. */
.estado { font-family: var(--mono); font-size: 0.64rem; letter-spacing: 0.1em; text-transform: uppercase; }
.estado-activo { color: var(--tenue); }
.estado-suspendido { color: var(--error); font-weight: 700; }
.estado-pendiente_verificacion { color: #a8862c; }

/* ---------------------------------- Ficha --------------------------------
   Panel lateral, no modal. El asesor compara la ficha con la lista; un modal
   le taparía justo lo que necesita al lado.
--------------------------------------------------------------------------- */

.ficha {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(420px, 100vw);
  z-index: 8;
  overflow-y: auto;
  overscroll-behavior: contain;
  background: var(--fondo);
  border-left: var(--regla);
  padding: 0 var(--margen) 3rem;
  box-shadow: -8px 0 24px #0000001f;
}

.ficha-barra {
  position: sticky;
  top: 0;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  padding: 1rem 0;
  background: var(--fondo);
  border-bottom: var(--regla);
}
.ficha-barra h2 { margin: 0; font-size: 1rem; }

.ficha h3 {
  font-family: var(--mono);
  font-size: 0.66rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--tenue);
  margin: 1.75rem 0 0.5rem;
}

.ficha-acciones { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.75rem; }
.ficha-acciones select { width: auto; flex: 1 1 8rem; margin: 0; }
.ficha-acciones button { flex: 0 0 auto; width: auto; padding: 0.6rem 1rem; }

/* Bitácora: se lee de arriba abajo como un libro de actas. */
.bitacora { list-style: none; padding: 0; margin: 0; }
.bitacora li { padding: 0.5rem 0; border-bottom: 1px solid var(--borde); font-size: 0.82rem; }
.bitacora .cuando {
  display: block;
  font-family: var(--mono);
  font-size: 0.64rem;
  letter-spacing: 0.08em;
  color: var(--tenue);
}

/* --------------------------------- Tareas -------------------------------- */

.nueva-tarea {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.75rem 1rem;
  padding-bottom: 1.25rem;
  border-bottom: 1px solid var(--borde);
  margin-bottom: 1.25rem;
}
.nueva-tarea label { margin: 0; font-size: 0.72rem; }
.nueva-tarea select, .nueva-tarea input { width: auto; min-width: 8rem; }
.nueva-tarea button { width: auto; flex: 0 0 auto; }

.tarea { padding: 0.75rem 0; border-bottom: 1px solid var(--borde); }
.tarea-cabecera { display: flex; justify-content: space-between; gap: 1rem; align-items: baseline; }
.tarea-acciones { display: flex; gap: 0.5rem; margin-top: 0.5rem; }
.tarea-acciones button {
  padding: 0.3rem 0.7rem;
  border: 1px solid var(--borde);
  background: var(--fondo);
  color: var(--texto);
  font-family: var(--mono);
  font-size: 0.64rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
}
.tarea.cerrada { opacity: 0.55; }

@media (max-width: 560px) {
  .ficha { width: 100vw; border-left: 0; }

  /* Al bajar de línea en vez de esconderse, las siete secciones pasaban a
     ocupar TRES filas de cabecera pegajosa: ~120 px comidos en todo scroll de
     una pantalla de 812. Apretando el relleno caben cuatro por fila y quedan
     en dos. Se aprieta el hueco, no el objetivo táctil: la altura de pulsación
     la sigue dando el relleno vertical. */
  .nav { padding: 0.7rem 0.5rem; }
  .subtab { padding: 0.55rem 0.6rem; }
}

/* Objetivos táctiles, por tipo de puntero y no por ancho de pantalla.
 *
 * `pointer: coarse` es la pregunta correcta —¿se toca con el dedo?—; el ancho
 * solo la aproxima, y una tableta ancha con dedos quedaría fuera.
 *
 * Las bandejas medían 33 px de alto y la casilla del filtro, 13. Por debajo de
 * 44 px se falla el toque y se pulsa la de al lado, que aquí significa cambiar
 * de bandeja sin querer. Venía de antes de este repaso; se arregla ahora
 * porque es el mismo trabajo. Crece el ÁREA, no la letra. */
@media (pointer: coarse) {
  .subtab, .nav { min-height: 44px; display: inline-flex; align-items: center; }
  .filtro-mios { min-height: 44px; }
  .filtro-mios input { width: 20px; height: 20px; }
}

/* ---------------------------------------------------------------------------
   SERVICIOS PROFESIONALES

   CERO movimiento nuevo. Las seis reglas de arriba siguen mandando: lo que
   entra aquí es tipografía, color y espacio. Hay una aserción en pruebas.js
   que falla si este bloque declara un fotograma clave o una transición.
--------------------------------------------------------------------------- */

/* Las estrellas SOLO se pintan cuando hay nota publicable. Cinco estrellas
   vacías se leen como "le pusieron cero", que es lo contrario de "todavía no
   hay opiniones suficientes"; ese caso se dice con palabras, en .sin-nota. */
.estrellas {
  margin: 0.55rem 0 0;
  display: flex;
  align-items: baseline;
  gap: 0.45rem;
  font-size: 0.95rem;
}

.estrellas span[aria-hidden] {
  color: var(--acento);
  letter-spacing: 0.06em;
  /* La monoespaciada evita que la fila de estrellas cambie de ancho entre
     tarjetas y desalinee la rejilla. */
  font-family: var(--mono);
}

.sin-nota {
  margin: 0.55rem 0 0;
  font-size: 0.85rem;
}

/* Formulario de calificar: en línea dentro de la tarjeta de la consulta. Un
   modal para poner una nota de 1 a 5 sería desproporcionado. */
.calificar {
  margin-top: 0.85rem;
  padding-top: 0.85rem;
  border-top: 1px solid var(--borde);
  display: grid;
  gap: 0.55rem;
}

.calificar label {
  display: grid;
  gap: 0.3rem;
  font-size: 0.85rem;
  color: var(--tenue);
}

.calificar .error:empty {
  display: none;
}

/* El enlace al otro directorio. Se distingue de los botones de acción: no
   hace nada irreversible, solo lleva a otra pantalla. */
#lista-directorio .enlace {
  font-size: 0.85rem;
  text-align: left;
  padding: 0;
}

/* ---------------------------------------------------------------------------
   ESPACIADO — clases en vez de atributos `style`

   Producción sirve una CSP estricta (`default-src 'self'`, sin
   `unsafe-inline`), así que el navegador BLOQUEA todo atributo de estilo en
   línea: el margen no se aplicaba y cada uno dejaba un error en la consola.
   En local no se veía porque el servidor de desarrollo no pasa por Nginx.

   Se descubrió abriendo el sitio ya desplegado. Era un fallo anterior a estas
   pantallas; al añadir más marcado se multiplicó, así que se arregla entero.
--------------------------------------------------------------------------- */

/* Salen de la escala de tema.css, no de valores propios.
 *
 * Antes eran 0.4 · 0.6 · 0.75 · 0.9 · 1.2 · 1.6 rem: una SEGUNDA escala,
 * inventada aquí, que convivía con los márgenes sueltos del resto del archivo.
 * Con dos escalas a la vez ningún hueco se parece a otro por diseño, solo por
 * casualidad, y esa es la mitad de por qué la pantalla no tenía ritmo. */
.sep-xs  { margin-top: var(--e1); }
.sep-s   { margin-top: var(--e2); }
.sep-m   { margin-top: var(--e3); }
.sep-l   { margin-top: var(--e4); }
.sep-xl  { margin-top: var(--e5); }
.sep-2xl { margin-top: var(--e6); }

/* Solo por arriba: el hueco de abajo lo pone la rejilla o el bloque siguiente,
   y sumar los dos deja el doble de aire del que se pidió. */
.sep-solo-arriba { margin: var(--e2) 0 0; }
.sep-solo-arriba-xs { margin: var(--e1) 0 0; }

.sep-abajo { margin-bottom: var(--e3); }

/* ---------------------------------------------------------------------------
   ASISTENTE

   El mockup venía en verde de WhatsApp. Aquí se usan los tokens del registro:
   el portal ya tiene identidad propia y meterle la paleta de otra aplicación
   lo haría parecer un injerto. La ESTRUCTURA sí es la del mockup —propio a la
   derecha, asistente a la izquierda, avisos centrados— porque esa disposición
   se lee sin explicación.

   CERO movimiento nuevo. Ni siquiera al aparecer una burbuja: el hilo se
   desplaza al final y ya. Las seis reglas siguen mandando.
--------------------------------------------------------------------------- */

.chat-barra {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 1rem;
  padding-bottom: 0.75rem;
  border-bottom: var(--regla);
  margin-bottom: 0.9rem;
}

.chat-titulo { margin: 0; }
.chat-estado { margin: 0.2rem 0 0; font-size: 0.8rem; }

/* Altura fija y desplazamiento propio: si creciera con el hilo, el campo de
   escritura se iría al fondo de la página y habría que perseguirlo. */
.chat-hilo {
  height: min(58vh, 460px);
  overflow-y: auto;
  padding: 0.9rem;
  background: var(--fondo-2);
  border: 1px solid var(--borde);
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.chat-fila { display: flex; }
.chat-fila.socio { justify-content: flex-end; }
.chat-fila.ia { justify-content: flex-start; }
.chat-fila.sistema { justify-content: center; }

.chat-burbuja {
  max-width: 78%;
  padding: 0.6rem 0.75rem;
  font-size: 0.9rem;
  line-height: 1.45;
  border: 1px solid var(--borde);
}

/* El propio lleva el acento tenue: se distingue del asistente sin gritar. */
.chat-burbuja.socio {
  background: var(--acento-suave);
  border-color: var(--acento);
}

.chat-burbuja.ia { background: var(--fondo); }

.chat-burbuja.sistema {
  background: transparent;
  border: 0;
  border-top: var(--regla);
  border-bottom: var(--regla);
  border-radius: 0;
  max-width: 100%;
  text-align: center;
  font-family: var(--mono);
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  color: var(--tenue);
  padding: 0.55rem 0.4rem;
}

.chat-quien {
  display: block;
  font-family: var(--mono);
  font-size: 0.62rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--tenue);
  margin-bottom: 0.25rem;
}

.chat-hora {
  display: block;
  margin-top: 0.3rem;
  font-family: var(--mono);
  font-size: 0.62rem;
  color: var(--tenue);
  text-align: right;
}

.chat-burbuja.sistema .chat-hora { display: none; }

/* El enlace a WhatsApp: es la acción, así que se ve como tal. */
.chat-whatsapp {
  display: inline-block;
  margin-top: 0.15rem;
  padding: 0.5rem 0.9rem;
  background: var(--acento);
  color: #fff;
  text-decoration: none;
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.chat-escritura {
  display: flex;
  gap: 0.6rem;
  align-items: flex-start;
  margin-top: 0.9rem;
}

.chat-campo { flex: 1; margin: 0; }
.chat-campo input { margin-top: 0; }
.chat-escritura button.primario { width: auto; padding: 0.7rem 1.1rem; }
.chat-escritura .error { flex-basis: 100%; margin: 0; }
.chat-escritura .error:empty { display: none; }

.chat-nota { font-size: 0.78rem; margin-top: 0.8rem; }

/* Etiqueta solo para lectores de pantalla. */
.oculto-visual {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
