/* ============================================================
   SOCIO LEGAL — Sistema de diseño v1.0
   "El socio que nunca duerme."
   ------------------------------------------------------------
   Paleta: navy (autoridad) + oro (prestigio) + marfil (papel legal)
   Tipografía: Playfair Display (marca/títulos) + Inter (UI)
   Tokens semánticos; dark mode por intercambio de variables.
   Los selectores conservan las clases/IDs que usa el JS existente.
   ============================================================ */

:root {
  /* Marca */
  --navy-950: #081019;
  --navy-900: #0d1b2a;
  --navy-800: #122438;
  --navy-700: #1a334e;
  --gold: #c5a059;
  /* Tinte del DESTELLO que señala una fila. A propósito NO es `--gold-soft`:
     ése es el del `:hover` y un destello que se ve igual que el ratón encima
     no señala nada. Ver `.doc-resaltado`. */
  --gold-flash: rgba(197, 160, 89, 0.42);
  --gold-strong: #a9853d;
  --gold-soft: rgba(197, 160, 89, 0.14);
  --wa: #25d366; /* verde WhatsApp — solo para la acción real de enviar por WhatsApp */

  /* Ámbar FIJO — no cambia con la paleta. Para estados semánticos
     (etiqueta "Para hoy") y el acento del KPI "Expedientes Activos". */
  --amber: #c5a059;
  --amber-strong: #a9853d;
  --amber-soft: rgba(197, 160, 89, 0.14);

  /* Acento para TEXTO/íconos según el fondo (legibilidad en toda paleta):
     --accent-ink     → sobre superficies claras/soft (oscuro en claro, claro en oscuro)
     --accent-on-deep → sobre el fondo institucional PROFUNDO (siempre claro) */
  --accent-ink: var(--gold-strong); /* respaldo */
  /* 78% y no 84%: al 84% se quedaba en 4.12 de contraste sobre el fondo
     marfil, por debajo del mínimo de 4.5. Al 78% da 4.65 con margen.
     A ojo la diferencia es nula (rgb 142,112,51 → 132,104,48), pero el
     texto dorado pequeño pasa de "se intuye" a "se lee".
     Se sigue derivando del dorado del estudio, así que un despacho que
     ponga su propio color hereda el mismo arreglo automáticamente. */
  --accent-ink: color-mix(in srgb, var(--gold-strong) 78%, #000000);
  --accent-on-deep: #ecd9a6; /* respaldo si el navegador no soporta color-mix */
  --accent-on-deep: color-mix(in srgb, var(--gold) 60%, #ffffff);

  /* Superficies (marfil cálido, no blanco hospital) */
  --bg: #f4f1ea;
  --paper: #fcfbf7;
  --card: #ffffff;
  --line: #e7e2d6;
  --line-strong: #d8d2c2;

  /* Tinta */
  --ink: #1c2534;
  --ink-2: #4c5567;
  /* Gris de los textos pequeños (fechas, contadores, notas al pie, rótulos).
     Era #7d8593 y se quedaba en 3.3 de contraste sobre el fondo marfil,
     por debajo del mínimo legible de 4.5. Afectaba a 81 textos de la app a
     la vez, casi todos de 9 a 12 px: justo los que más cuesta leer, y en la
     pantalla de alguien que revisa plazos a diario.
     Se oscureció conservando el mismo tono azulado (no cambia el aspecto,
     sólo se lee): ahora da 4.5 sobre el fondo, 4.9 sobre el papel y 5.1
     sobre las tarjetas blancas. El modo oscuro ya cumplía (5.3-6.1). */
  --ink-3: #686e7a;

  /* Semánticos */
  --danger: #b3362a;
  --danger-bg: #fbeeec;
  --success: #14735a;
  --success-bg: #e9f4f0;
  --warning: #a8721c;
  --warning-bg: #faf3e3;
  /* 🪦 `--vino` (#7b1e3a) SE RETIRÓ ENTERO el 2026-08-08, y en dos pasos.
     Pintaba DOS cosas a la vez: las audiencias y la advertencia jurídica, y por
     eso tocar una estropeaba la otra. Primero las audiencias salieron a su
     propio token (`--audiencia`); después las cuatro advertencias que quedaban
     pasaron a `--warning-txt`, porque una advertencia tiene que parecerse a las
     demás advertencias de la app y no a la marca del estudio.
     Sin usos, el token se borra en vez de dejarlo ahí: un color huérfano en la
     paleta acaba reapareciendo en el sitio equivocado. El motivo por el que se
     fue —tono 342°: a 3° del acento burdeos y a 23° del rojo de «vencido»—
     está medido junto al bloque AUDIENCIA de aquí abajo. */
  --info: #2b5b8f;

  /* ---------- NOTA (2026-08-31) ----------
     El color de lo que NO es un plazo: reuniones, diligencias, recordatorios.
     Lo pidió un estudio a través de Piero: *«no todo se basa en tareas,
     escritos y audiencias»*.
     🔴 Lo que este color tiene que hacer, y es lo único que importa: **no
     parecerse al rojo de vencido ni al ámbar de hoy.** Una nota de la semana
     pasada no es un plazo que se dejó pasar, y si se pinta igual, el rojo deja
     de significar nada — que es la misma avería del `--vino` de arriba por el
     otro lado.
     Se elige el verde azulado #1d6a5e (tono 170°):
       · a 165° del rojo de vencido (#b3362a, 5°) — imposible confundirlos
       · a 130° del ámbar de hoy (#a8721c, 40°)
       ·  a 40° del azul de pendiente (#2b5b8f, 210°): la distancia más corta,
         pero es la pareja menos peligrosa (ninguno de los dos es una alarma)
       · sobre él, texto blanco da 5,6 de contraste (el mínimo son 4,5)
     🪤 NO se reusa `--success` (#14735a), aunque se le parezca: ese token dice
     «salió bien», y una nota no ha salido de ninguna manera todavía. Dos
     significados en un color es de donde salió el problema del `--vino`. */
  --nota: #1d6a5e;
  --nota-bg: #e8f3f0;

  /* ---------- AUDIENCIA ----------
     🔴 2026-08-08, lo pidió Piero: «todo parece de color rojo, y cuando
     cambiamos de colores con las paletas no queda bien».
     Tenía razón y se puede medir. La audiencia iba en `--vino` #7b1e3a, que
     está en el tono 342°:
       · a 23° del rojo de «vencido» (#b3362a, tono 5°) ⇒ de un vistazo son el
         mismo color, y entonces el rojo deja de significar «se acabó».
       · a 3° del acento de la paleta BURDEOS (#a83250, tono 345°) ⇒ en esa
         paleta la audiencia y el color del estudio son indistinguibles.
     Se buscó el tono con MÁS sitio libre respecto de TODO lo que comparte
     pantalla —los 4 semánticos y los 6 acentos de paleta—. El hueco más ancho
     de todos cae en el verde (101°) y se descartó a propósito: el verde ya
     significa «hecho» en esta app, y una audiencia a la que todavía no has ido
     no puede pintarse de «hecho». El siguiente es este morado ciruela:
       · 60° del rojo de vencido (antes 23°)
       · 40° del acento más cercano en las seis paletas (antes 3°)
     Es FIJO, como el ámbar: un color que SIGNIFICA algo no puede cambiar
     cuando el estudio elige otro color de marca; lo que tiene que hacer es
     convivir con los seis, y por eso se eligió por distancia y no por gusto.
     Las tres variantes son las mismas familias que el resto del sistema:
     relleno (letra blanca encima), letra en claro (sobre el peor fondo real) y
     letra sobre superficie oscura. Ver el bloque «COLOR DE TEXTO QUE SE LEE EN
     LOS DOS MODOS», más abajo.

     🎨 2026-08-11 — SE AHONDA: #8e2d86 → #7d2a72. Piero: «el color ciruela que
     se parece un morado todavía no me convence […] ¿lo llegaste a comparar con
     todos los colores de las paletas?».
     RESPUESTA HONESTA: no del todo. Se había comparado contra los 6 ACENTOS y
     los 4 semánticos. Ahora sí contra los 40 colores del sistema —los 6 tonos
     de cada paleta (acento, acento fuerte y los cuatro azules de fondo) más los
     semánticos—, y el veredicto es que **no choca con nada**: lo más cercano en
     tono queda a 34° (el n800 de burdeos) y lo más cercano en distancia
     perceptiva a ΔE 29 (el n700 de púrpura), muy por encima del ~10-15 en que
     dos colores empiezan a confundirse.
     Y el hueco de 305° **es el único que queda**: los tonos ocupados son
     5·20·40·164·210·261·345, y de los huecos, el más ancho (102°, verde) está
     vetado porque el verde ya significa «hecho». Moverlo de sitio lo empeora.
     ⇒ No se cambia de SITIO, se cambia de PROFUNDIDAD, que es lo que hace que
     lea a ciruela y no a morado: L del 37% al 33%, tono 305°→308°. Y todos los
     números mejoran a la vez:
       · relleno con letra blanca .... 7,32 → 8,58
       · letra sobre el peor claro ... 5,42 → 6,36
       · distancia a púrpura ......... 44° → 47°
       · distancia a burdeos ......... 40° → 37° (sigue holgada)
     `--audiencia-claro` (#e39ad6, tono 311°) NO se toca: ya pertenece a esta
     familia y sigue midiendo 6,29 sobre el peor fondo oscuro y 6,11 sobre su
     propio tinte al 12% — que es el fondo que de verdad hay debajo.
     ↩️ Si a Piero le sigue sin convencer, se revierte tocando SOLO estas dos
     líneas (`--audiencia` y `--audiencia-txt`) a #8e2d86. */
  --audiencia: #7d2a72;

  /* Compat con código previo */
  --white: #ffffff;
  --gray: var(--ink-3);
  --light-bg: var(--paper);

  /* ---------- SISTEMA DE CUADROS ----------
     Se contaron 24 cuadros en la app con 18 rellenos distintos y 6 radios
     de esquina distintos. Había esquinas de 6 y de 7, de 9 y de 10: esa
     diferencia no se ve, y por eso mismo sólo aporta desorden. Y rellenos
     como "22 arriba, 26 a los lados, 18 abajo" en un mismo recuadro.
     El efecto era el que se nota al mirar la pantalla: cada cuadro parecía
     dibujado por una persona distinta.
     Ahora hay CUATRO niveles, y todo cuadro usa uno de ellos. El nivel se
     elige por el peso del cuadro, no por gusto:
        destacado → lo primero que se lee al entrar (el parte del sistema)
        normal    → una tarjeta o un bloque con contenido propio
        compacto  → una franja o una fila dentro de otro cuadro
        mínimo    → botones, campos y pastillas
     Los rellenos son SIMÉTRICOS salvo en los compactos, donde el aire
     lateral es mayor que el vertical a propósito (una franja baja y ancha
     necesita más margen a los lados para no verse apretada). */
  --caja-destacada: 40px;
  --caja-normal: 24px;
  --caja-compacta: 12px 16px;
  --caja-minima: 10px 12px;

  /* Sistema */
  --r-lg: 14px;   /* cuadros destacados y normales */
  --r-md: 10px;   /* cuadros compactos y columnas */
  --r-sm: 7px;    /* botones y campos */
  /* PASTILLA (los extremos totalmente redondos: chips, contadores, etiquetas
     de estado). Se conseguía de dos maneras distintas: unas con 999px y
     otras poniendo a mano la mitad de la altura (20, 21, 22, 26...). El
     problema del segundo método es que sólo sale redondo si el alto no
     cambia; en cuanto el texto salta a dos líneas o el usuario agranda la
     letra, esas esquinas dejan de ser semicírculos y quedan a medio camino,
     mientras las de al lado siguen perfectas. Con 999px el extremo es
     siempre semicircular, mida lo que mida. */
  --r-pastilla: 999px;
  --shadow-1: 0 1px 2px rgba(18, 26, 40, 0.05), 0 1px 6px rgba(18, 26, 40, 0.04);
  --shadow-2: 0 4px 14px rgba(18, 26, 40, 0.08), 0 2px 4px rgba(18, 26, 40, 0.05);
  --shadow-3: 0 18px 50px rgba(8, 16, 25, 0.28);
  /* ---------- TIPOGRAFÍA ----------
     Inter para la interfaz, Playfair Display para marca y títulos.
     Decisión de Piero (2026-07-28): se probó cambiarlas por IBM Plex Sans +
     Fraunces y prefirió conservar las de siempre. Lo que SÍ se conserva de
     aquella prueba es lo que no dependía de la letra: las cifras de ancho
     fijo (más abajo, en `body`) y la regla de que los NÚMEROS nunca van en
     la letra de títulos. Ambas AUTOALOJADAS en vendor/fonts. */
  --font-ui: "Inter", system-ui, -apple-system, sans-serif;
  --font-display: "Playfair Display", Georgia, serif;

  /* ---------- ESCALA DE TAMAÑOS ----------
     La app llegó a tener 34 tamaños de letra distintos, con parejas como
     11 y 11.5, 12 y 12.5, 9 y 9.5, y hasta un 11.8. Esa diferencia NO se
     ve — y ese es justamente el problema: dos rótulos que deberían leerse
     como iguales quedaban "casi iguales", y eso es lo que hace que una
     pantalla se sienta descuidada sin que se sepa señalar por qué.
     Se consolidó en ONCE pasos. Nadie se movió más de 1 px, salvo los
     textos de 8 y 9 px, que subieron a 10: por debajo de eso un abogado de
     cincuenta años no lee, y eran 41 sitios.
     Después se SUBIÓ UN ESCALÓN toda la franja pequeña (10→11, 11→12,
     12→13): el 74% del texto de la app estaba a 12 px o menos, mientras que
     el cuerpo declarado era de 15. Es decir, la app decía tener un cuerpo
     cómodo pero en la práctica casi todo era letra chica. Medido antes de
     aplicarlo: 370 textos afectados, nada se desborda ni se recorta, y la
     página sólo crece un 1,4%.
     🔎 06-09-2026 · SE MIDIÓ SI LA ESCALA SE CUMPLÍA, y no: **29 reglas
     estaban por debajo del suelo de 11 px** que este mismo bloque declara.
     No fue un descuido de nadie en concreto — es lo que le pasa a una regla
     escrita en un comentario que nada comprueba: se cumple el día que se
     escribe y va cediendo un 0,5 cada vez. Se subieron 17 (las que son TEXTO
     que se lee) y se dejaron doce a propósito:
        · 6 son ICONOS (glifos, no texto: un 10 px ahí es un tamaño de dibujo)
        · 3 viven en un `@media` de pantalla estrecha, donde el ancho está medido
        · 3 son la pastilla de fecha de la agenda y la barra 2–2 del celular,
          dos apreturas decididas a propósito el 31-08 y el 13-08
     Lo vigila `pruebas/la-escala-de-la-letra.test.js`, que lista las
     excepciones por nombre: una nueva hay que ponerla ahí, o sea decidirla.
     REGLA: al añadir algo nuevo, usar uno de estos pasos. Si ninguno vale,
     probablemente el problema es la jerarquía, no el tamaño.
        11  sello, contador diminuto        15  CUERPO (base de la app)
        12  metadato, pie                   17  subtítulo
        13  secundario                      19  título de bloque
        14  texto de apoyo / destacado      22  título de sección
                                            26  título de pantalla
                                            34  saludo grande
     LA LETRA DE TÍTULOS (Playfair) SÓLO DE 19 PX PARA ARRIBA, y sólo en la
     marca y los momentos ceremoniales (entrada, saludo, cabecera de modal).
     Es una serif de mucho contraste: por debajo de ese tamaño se deshilacha,
     y si se usa en todas partes deja de destacar. El trabajo diario va en la
     letra de interfaz. Los números, NUNCA en la de títulos: no alinean. */
  --speed: 180ms;
  --ease: cubic-bezier(0.25, 0.8, 0.25, 1);
}

body.dark-mode {
  /* Superficies NEUTRAS (baja saturación) para que cualquiera de las 6
     paletas de acento se vea limpia y no choque en modo oscuro. */
  --bg: #0d1117;
  --paper: #151a21;
  --card: #1a2029;
  --line: #2a313c;
  --line-strong: #37404d;
  --ink: #eef2f7;
  --ink-2: #b8c2d0;
  --ink-3: #8494a8;
  --light-bg: #101c2b;
  --white: #14212f;
  --danger-bg: rgba(179, 54, 42, 0.16);
  --success-bg: rgba(20, 115, 90, 0.16);
  --warning-bg: rgba(168, 114, 28, 0.16);
  /* 🪤 EL TINTE DE LA NOTA TAMBIÉN VA AQUÍ. En claro es un crema verdoso
     opaco (#e8f3f0); dejado tal cual sobre el fondo oscuro sería una mancha
     casi blanca. Es la trampa de los tintes que ya mordió con `--gold-soft`:
     un color de FONDO definido sólo en la paleta clara no falla, brilla. */
  --nota-bg: rgba(29, 106, 94, 0.18);
  --gold-soft: rgba(197, 160, 89, 0.12);
  /* En oscuro el mismo tinte rinde menos: el fondo ya es oscuro y el dorado
     al 42% se queda en un gris sucio. Sube a 52%. */
  --gold-flash: rgba(197, 160, 89, 0.52);
  /* Ámbar un punto más brillante para leerse sobre superficies oscuras */
  --amber: #d8b877;
  --amber-strong: #cba85f;
  --amber-soft: rgba(197, 160, 89, 0.16);
  /* En oscuro, el texto de acento sobre chips soft debe ACLARARSE */
  --accent-ink: #d8b877; /* respaldo */
  --accent-ink: color-mix(in srgb, var(--gold) 55%, #ffffff);
  --shadow-1: 0 1px 2px rgba(0, 0, 0, 0.3);
  --shadow-2: 0 4px 14px rgba(0, 0, 0, 0.4);
}

/* ---------- Base ---------- */
* { margin: 0; padding: 0; box-sizing: border-box; }
html {
  scroll-behavior: smooth;
  /* 🍎 EL IPHONE NO INFLA LA LETRA POR SU CUENTA (2026-08-13).
     Safari en iOS trae encendido su "ajuste automático de tamaño de texto":
     cuando le parece que un bloque es ancho para su letra, la agranda él solo.
     El resultado es que un rótulo medido aquí en 14px sale en el teléfono más
     grande y se parte donde no debería — que es como Piero vio «El Redactor»
     en dos líneas. Con `100%` se le dice que respete lo que dice la hoja.
     ⚠️ Esto NO impide hacer zoom con los dedos (eso sería `user-scalable=no`,
     que no se toca: hay abogados que lo necesitan para leer). */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}
body {
  font-family: var(--font-ui);
  font-size: 15px;
  line-height: 1.55;
  color: var(--ink);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  touch-action: manipulation;
  overflow-x: hidden; /* nada se desliza en horizontal salvo lo que tenga su propio scroll */

  /* CIFRAS DE ANCHO FIJO EN TODA LA APLICACIÓN.
     Antes esto se ponía a mano clase por clase (27 sitios) y había que
     acordarse en cada número nuevo. Aquí se resuelve UNA vez: todo dígito
     de la app ocupa lo mismo, así que importes, plazos, fechas y números
     de expediente quedan en columna sin tocar nada más. Un 1 y un 8 miden
     igual, y una tabla de honorarios se lee de un vistazo.
     Las 27 declaraciones sueltas quedan como refuerzo inofensivo. */
  font-variant-numeric: tabular-nums;
}
/* Los campos de formulario NO heredan font-variant-numeric del body: hay
   que dárselo aparte o el importe escrito baila respecto del calculado. */
input, select, textarea, table { font-variant-numeric: tabular-nums; }

h1, h2, h3 { line-height: 1.25; }
img { max-width: 100%; }
button { font-family: inherit; cursor: pointer; }
input, select, textarea {
  font-family: inherit;
  font-size: 14px;
  color: var(--ink);
  background: var(--card);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  padding: 10px 12px;
  width: 100%;
  transition: border-color var(--speed) var(--ease), box-shadow var(--speed) var(--ease);
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--gold);
  box-shadow: 0 0 0 3px var(--gold-soft);
}
/* 🍎 LOS CAMPOS DE FECHA Y HORA, EN SU SITIO EN EL IPHONE (2026-08-13)
   ------------------------------------------------------------
   🔴 Lo vio Piero en su celular: en «Facturación» los dos campos de fecha
   salían MÁS ANCHOS que los demás, con el valor centrado y el borde derecho
   cortado por el filo de la pantalla. Los otros campos estaban perfectos.
   La causa es de Safari en iOS, y por eso aquí no se reproduce: a
   `<input type="date">` le da un ANCHO PROPIO calculado por su contenido y no
   lo deja encoger, así que el `width:100%` de la regla de arriba se queda
   corto; y encima centra el valor con `::-webkit-date-and-time-value`. Como
   el `<body>` lleva `overflow-x:hidden`, lo que sobra no se puede desplazar:
   se CORTA. Eso es exactamente lo que se ve en su captura.
   ⚠️ No son dos campos: son 13 en toda la app (los plazos y las audiencias que
   se confirman cada día, la calculadora, la Carpeta y las sugerencias del
   Vigía). Por eso se arregla aquí, de una vez y para los que vengan, en vez de
   parchear Facturación.
   🔑 `min-width: 0` es la pieza que importa: sin ella `width:100%` no puede
   bajar del ancho intrínseco que iOS le pone. */
input[type="date"], input[type="time"], input[type="datetime-local"], input[type="month"] {
  -webkit-appearance: none;
  appearance: none;
  min-width: 0;
  max-width: 100%;
}
input[type="date"]::-webkit-date-and-time-value,
input[type="time"]::-webkit-date-and-time-value,
input[type="datetime-local"]::-webkit-date-and-time-value,
input[type="month"]::-webkit-date-and-time-value {
  text-align: left;
  margin: 0;
}
/* Botón que sustituye a un <select> y abre el buscador. Copia el aspecto del
   campo de arriba a propósito: quien lo mira tiene que entender que ahí se
   ELIGE algo, aunque por dentro sea otra cosa. Texto a la izquierda y la lupa
   a la derecha, donde el <select> ponía su flecha. */
.ed-selector {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; text-align: left; cursor: pointer;
  font-family: inherit; font-size: 14px; color: var(--ink);
  background: var(--card); border: 1px solid var(--line-strong);
  border-radius: var(--r-sm); padding: 10px 12px;
  transition: border-color var(--speed) var(--ease), box-shadow var(--speed) var(--ease);
}
.ed-selector:hover { border-color: var(--gold); }
.ed-selector i { color: var(--ink-3); font-size: 12px; flex: none; }
.ed-selector span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
::placeholder { color: var(--ink-3); }

/* ============================================================
   LOGIN — el primer apretón de manos
   ============================================================ */
#login-screen {
  position: fixed; inset: 0; z-index: 3000;
  display: grid; grid-template-columns: 1.1fr 1fr; grid-template-rows: 1fr;
  background: var(--bg); overflow: hidden;
}
/* ---- Panel izquierdo: hero de marca ---- */
.login-hero {
  position: relative; overflow: hidden;
  display: flex; align-items: center; padding: 56px;
  color: #f5efe2;
  background:
    radial-gradient(900px 600px at 80% -10%, rgba(197, 160, 89, 0.16), transparent 60%),
    radial-gradient(700px 520px at -10% 110%, rgba(27, 51, 78, 0.9), transparent 55%),
    linear-gradient(160deg, var(--navy-900), var(--navy-950));
}
.login-hero-grid {
  position: absolute; inset: 0; opacity: 0.16;
  background-image:
    linear-gradient(to right, rgba(197, 160, 89, 0.25) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(197, 160, 89, 0.25) 1px, transparent 1px);
  background-size: 54px 54px;
  -webkit-mask-image: radial-gradient(120% 80% at 25% 20%, #000 30%, transparent 75%);
          mask-image: radial-gradient(120% 80% at 25% 20%, #000 30%, transparent 75%);
}
.login-orb { position: absolute; border-radius: 50%; filter: blur(64px); pointer-events: none; }
.login-orb.orb-1 { width: 300px; height: 300px; left: -70px; top: 56px; background: rgba(197, 160, 89, 0.26); animation: orbFloat1 12s ease-in-out infinite; }
.login-orb.orb-2 { width: 340px; height: 340px; right: -60px; bottom: 24px; background: rgba(27, 51, 78, 0.7); animation: orbFloat2 15s ease-in-out infinite; }
@keyframes orbFloat1 { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(14px, -22px); } }
@keyframes orbFloat2 { 0%, 100% { transform: translate(0, 0); } 50% { transform: translate(-18px, 24px); } }
/* Aurora premium: sábana de luz oro/navy que gira lentísimo detrás del grid */
.login-hero::before {
  content: ""; position: absolute; z-index: 0; pointer-events: none;
  top: 50%; left: 50%; width: 150%; height: 150%; transform: translate(-50%, -50%);
  background: conic-gradient(from 0deg at 50% 50%,
    transparent 0deg,
    rgba(197, 160, 89, 0.12) 55deg,
    transparent 130deg,
    rgba(27, 51, 78, 0.40) 210deg,
    transparent 300deg,
    rgba(197, 160, 89, 0.08) 350deg,
    transparent 360deg);
  filter: blur(48px); opacity: 0.85;
  animation: heroAurora 28s linear infinite;
}
@keyframes heroAurora { to { transform: translate(-50%, -50%) rotate(360deg); } }
/* Viñeta: oscurece los bordes para dar profundidad y foco al texto */
.login-hero::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: radial-gradient(125% 105% at 50% 38%, transparent 52%, rgba(6, 12, 20, 0.58) 100%);
}
@media (prefers-reduced-motion: reduce) { .login-hero::before { animation: none; } }
.login-hero-inner { position: relative; z-index: 2; max-width: 470px; animation: fadeUp 0.7s var(--ease) both; }
.login-eyebrow {
  font-size: 11px; font-weight: 700; letter-spacing: 3px;
  text-transform: uppercase; color: var(--gold);
}
.login-eyebrow.sm { letter-spacing: 2px; font-size: 11px; }
.login-hero-title {
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(32px, 3.6vw, 52px); line-height: 1.05; letter-spacing: 0.3px;
  margin: 18px 0 16px;
}
.login-hero-title em { font-style: italic; color: var(--gold); }
.login-hero-sub { font-size: 15px; line-height: 1.7; color: rgba(238, 242, 247, 0.62); max-width: 410px; }
.login-hero-foot {
  position: absolute; left: 56px; right: 56px; bottom: 34px; z-index: 2;
  display: flex; justify-content: space-between;
  font-size: 11px; font-weight: 600; letter-spacing: 2px;
  text-transform: uppercase; color: rgba(238, 242, 247, 0.4);
}
/* ---- Panel derecho: formulario ---- */
.login-form-wrap { display: flex; flex-direction: column; align-items: center; justify-content: flex-start; padding: 40px 30px; overflow-y: auto; }
/* Los márgenes automáticos centran la tarjeta cuando hay espacio y la dejan
   deslizarse desde arriba (sin recortarse) cuando el formulario es alto —p. ej.
   el registro de estudio, que tiene más campos que el ingreso. */
.login-card { width: 100%; max-width: 400px; margin-top: auto; margin-bottom: auto; animation: fadeUp 0.55s var(--ease) both; }
.login-brandrow { display: flex; align-items: center; justify-content: center; gap: 12px; margin-bottom: 28px; }
.login-wordmark { width: 100%; max-width: 250px; height: auto; display: block; }
.login-brandrow .login-logo { width: 56px; height: 56px; flex-shrink: 0; object-fit: contain; filter: drop-shadow(0 3px 12px rgba(13, 27, 42, 0.22)); }
.login-brand2 { font-family: var(--font-ui); font-size: 15px; font-weight: 700; color: var(--ink); margin-top: 2px; }
.login-welcome {
  font-family: var(--font-display); font-size: 26px; font-weight: 700;
  line-height: 1.15; letter-spacing: 0.2px; color: var(--ink); margin-bottom: 28px;
  text-align: center;
}
.login-welcome span { display: block; color: var(--ink-3); font-weight: 600; }
.login-field { text-align: left; margin-bottom: 16px; }
.login-field label {
  display: block; font-size: 11px; font-weight: 700; letter-spacing: 1.5px;
  text-transform: uppercase; color: var(--ink-3); margin-bottom: 8px;
}
.login-inputwrap {
  display: flex; align-items: center; gap: 10px;
  background: var(--card); border: 1px solid var(--line-strong);
  border-radius: var(--r-pastilla); padding: 0 18px;
  transition: border-color var(--speed), box-shadow var(--speed);
}
.login-inputwrap i { color: var(--ink-3); font-size: 13px; }
.login-inputwrap:focus-within { border-color: var(--gold); box-shadow: 0 0 0 4px var(--gold-soft); }
.login-inputwrap:focus-within i { color: var(--acento-txt); }
.login-inputwrap input {
  flex: 1; height: 48px; padding: 0;
  border: none !important; background: transparent !important; box-shadow: none !important;
  color: var(--ink); font-size: 14px;
}
.login-ojo { cursor: pointer; padding: 6px; margin: -6px -6px -6px 0; }
.login-ojo:hover { color: var(--acento-txt) !important; }
/* Badge "Último uso" sobre el método de acceso usado la última vez */
.login-social-wrap { position: relative; }
.ultimo-uso-badge {
  position: absolute; top: -10px; right: 14px; z-index: 2;
  background: #1f2937; color: #fff; font-size: 11px; font-weight: 600;
  padding: 4px 10px; border-radius: var(--r-pastilla); box-shadow: 0 2px 6px rgba(0,0,0,.22);
}
.ultimo-uso-badge::after {
  content: ""; position: absolute; bottom: -4px; right: 16px;
  border: 5px solid transparent; border-top-color: #1f2937; border-bottom: 0;
}
.login-submit { position: relative; overflow: hidden; border-radius: var(--r-pastilla); height: 50px; margin-top: 8px; }
/* Separador "o" y botón de Google */
.login-o { display: flex; align-items: center; gap: 12px; margin: 16px 0; color: var(--ink-3); font-size: 12px; text-transform: uppercase; letter-spacing: 0.5px; }
.login-o::before, .login-o::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.btn-google { width: 100%; height: 48px; display: flex; align-items: center; justify-content: center; gap: 10px; border: 1px solid var(--line-strong); border-radius: var(--r-pastilla); background: var(--card); color: var(--ink); font-size: 14px; font-weight: 600; cursor: pointer; transition: background 0.15s, border-color 0.15s; }
.btn-google:hover { background: var(--paper); border-color: var(--gold); }
.g-logo-img { width: 18px; height: 18px; object-fit: contain; display: block; }
.login-submit::after {
  content: ""; position: absolute; inset: 0; transform: translateX(-120%);
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.38), transparent);
}
.login-submit:hover::after { transform: translateX(120%); transition: transform 0.7s ease; }
#login-error {
  display: none; margin-top: 14px; font-size: 13px;
  color: var(--danger-txt); background: var(--danger-bg);
  border: 1px solid rgba(179, 54, 42, 0.35);
  border-radius: var(--r-sm); padding: 10px 12px;
}
#login-error.ok {
  color: var(--success-txt); background: var(--success-bg);
  border-color: rgba(20, 115, 90, 0.35);
}
.login-forgot {
  font-size: 12px; font-weight: 600; color: var(--acento-txt);
  text-decoration: none; border-bottom: 1px solid transparent; transition: border-color var(--speed);
}
.login-forgot:hover { border-bottom-color: var(--acento-txt); }
.login-foot {
  margin-top: 24px; font-size: 11px; letter-spacing: 1px;
  color: var(--ink-3); text-transform: uppercase; text-align: center;
}
/* El pie del hero nunca debe encimarse con el texto centrado ni descuadrarse */
.login-hero-foot { flex-wrap: wrap; gap: 6px 16px; }
.login-hero { align-items: center; padding-bottom: 88px; } /* deja sitio al pie absoluto */

/* Responsive: apila el hero arriba y el formulario abajo.
   Punto de quiebre a 940px para que a "media pantalla" ya apile
   (en vez de comprimir dos columnas y descuadrarse). */
@media (max-width: 940px) {
  #login-screen { grid-template-columns: 1fr; grid-template-rows: auto auto; overflow-y: auto; }
  .login-hero { flex-direction: column; align-items: flex-start; justify-content: flex-start; padding: 30px 26px 22px; }
  .login-hero-foot { position: static; left: auto; right: auto; bottom: auto; margin-top: 20px; justify-content: flex-start; }
  .login-hero-title { font-size: clamp(24px, 6vw, 32px); margin: 10px 0 10px; }
  .login-hero-sub { font-size: 13px; }
  .login-form-wrap { padding: 28px 24px 44px; }
}
@media (max-width: 480px) {
  .login-hero { padding: 24px 20px 18px; }
  .login-hero-inner { max-width: 100%; }
  .login-hero-sub { max-width: 100%; }
  .login-welcome { font-size: 22px; }
  .login-form-wrap { padding: 24px 20px 40px; }
}

/* ---------- Botón principal (oro) ---------- */
.btn-gold {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%; min-height: 44px; padding: var(--caja-compacta);
  /* El primer tono era el dorado FIJO #d0ae69: en la paleta vino el botón
     salía degradado de dorado a vino, dos familias de color a la vez. */
  background: linear-gradient(180deg, var(--acento-btn-1), var(--acento-btn-2));
  color: var(--sobre-acento);
  border: none; border-radius: var(--r-sm);
  font-size: 13px; font-weight: 700; letter-spacing: 0.3px;
  transition: transform 120ms var(--ease), box-shadow var(--speed) var(--ease), filter var(--speed);
  box-shadow: 0 2px 10px rgba(197, 160, 89, 0.28);
}
.btn-gold:hover { filter: brightness(1.06); box-shadow: 0 4px 16px rgba(197, 160, 89, 0.4); }
.btn-gold:active { transform: scale(0.98); }
.btn-gold:disabled { opacity: 0.55; cursor: not-allowed; }
.btn-navy {
  background: linear-gradient(180deg, var(--navy-800), var(--navy-950));
  color: #f0e6cf; box-shadow: 0 2px 10px rgba(8, 16, 25, 0.35);
  border: 1px solid rgba(197, 160, 89, 0.35);
}
.btn-navy:hover { box-shadow: 0 4px 16px rgba(8, 16, 25, 0.45); }

/* ============================================================
   ESTRUCTURA — sidebar + contenido
   ============================================================ */
#app-layout { display: none; min-height: 100dvh; }

#sidebar {
  position: fixed; top: 0; left: 0; bottom: 0; z-index: 100;
  width: 244px;
  background: linear-gradient(180deg, var(--navy-900) 0%, var(--navy-950) 100%);
  border-right: 1px solid rgba(197, 160, 89, 0.16);
  display: flex; flex-direction: column;
  padding: 26px 16px 18px;
}
/* En oscuro el sidebar va NEUTRO (independiente de la paleta) para no
   chocar con el contenido; el acento de la paleta sigue en íconos/activos. */
body.dark-mode #sidebar {
  background: linear-gradient(180deg, #12161d 0%, #0b0e13 100%);
  border-right-color: var(--line);
}
.sidebar-logo { text-align: center; padding: 6px 6px 22px; border-bottom: 1px solid rgba(197, 160, 89, 0.14); }
.sidebar-logo svg { display: block; margin: 0 auto 2px; }
.sidebar-logo img { display: block; width: 92px; height: 92px; margin: 0 auto 2px; object-fit: contain; }
.brand-name {
  font-family: var(--font-display);
  font-size: 19px; font-weight: 700; color: #f5efe2;
  display: block; margin-top: 10px; letter-spacing: 0.3px; line-height: 1.15;
}
.brand-name em { font-style: normal; color: var(--accent-on-deep); }
.brand-tag {
  display: block; font-size: 11px; font-weight: 600;
  letter-spacing: 1.4px; text-transform: uppercase;
  color: rgba(197, 160, 89, 0.75); margin-top: 6px; line-height: 1.4;
  padding: 0 4px;
}
/* Acción primaria de la barra: la única cosa de la izquierda que NO es un
   lugar. Va en dorado sólido para que se distinga de la lista de pestañas. */
.nav-accion {
  display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%;
  margin-top: 22px; padding: 12px 14px; border: none; border-radius: var(--r-md);
  background: linear-gradient(180deg, var(--acento-btn-1) 0%, var(--acento-btn-2) 100%);
  color: var(--sobre-acento); font-family: inherit; font-size: 13px; font-weight: 800;
  letter-spacing: .01em; cursor: pointer; box-shadow: 0 2px 10px rgba(197,160,89,.25);
  transition: transform var(--speed), box-shadow var(--speed), filter var(--speed);
}
.nav-accion:hover { filter: brightness(1.06); box-shadow: 0 4px 16px rgba(197,160,89,.35); transform: translateY(-1px); }
.nav-accion:active { transform: none; }
.nav-accion i { font-size: 13px; }
.nav-menu { display: flex; flex-direction: column; gap: 4px; margin-top: 14px; flex: 1; }
/* El rótulo corto solo existe en el celular (ver el bloque de 860px). */
.nav-corto { display: none; }
.nav-btn {
  display: flex; align-items: center; gap: 12px;
  min-height: 44px; padding: 12px 14px;
  background: transparent; border: none; border-radius: var(--r-md);
  color: rgba(238, 242, 247, 0.62);
  font-size: 13px; font-weight: 500; text-align: left;
  transition: background var(--speed) var(--ease), color var(--speed) var(--ease);
  position: relative;
}
.nav-btn i { width: 20px; text-align: center; font-size: 15px; color: rgba(197, 160, 89, 0.6); transition: color var(--speed); }
.nav-btn:hover { background: rgba(197, 160, 89, 0.08); color: #eef2f7; }
.nav-btn.active {
  background: var(--gold-soft);
  color: #f5efe2; font-weight: 600;
}
.nav-btn.active::before {
  content: ""; position: absolute; left: -16px; top: 8px; bottom: 8px;
  width: 3px; border-radius: 0 3px 3px 0; background: var(--accent-on-deep);
}
.nav-btn.active i { color: var(--accent-on-deep); }
.dark-mode-toggle {
  display: flex; align-items: center; gap: 10px; justify-content: center;
  min-height: 42px; padding: 10px;
  border: 1px solid rgba(197, 160, 89, 0.22); border-radius: var(--r-md);
  color: rgba(238, 242, 247, 0.6); font-size: 12px; font-weight: 600;
  letter-spacing: 1px; cursor: pointer;
  transition: background var(--speed), color var(--speed);
}
.dark-mode-toggle:hover { background: rgba(197, 160, 89, 0.1); color: var(--gold); }

#main-content {
  flex: 1;           /* ocupa TODO el ancho disponible (el sidebar es fixed) */
  margin-left: 244px;
  padding: 22px 28px 90px;
  max-width: 100%;
  min-width: 0;      /* evita que hijos anchos (kanban/tablas) empujen el layout */
  overflow-x: hidden;
  transition: margin-right 280ms var(--ease); /* solo se corre al abrir el Socio */
}
/* Las tablas anchas hacen scroll DENTRO de su tarjeta, no mueven la página.
   (Aquí había además `#tabla-dashboard-urgentes`, que ya no existe en ningún
   HTML ni JS: se retiró el 2026-08-13.) */
.card-body, .alerta-dinamica-card > div { max-width: 100%; }

/* ---------- Cabecera ---------- */
header.glass {
  display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  padding: var(--caja-compacta);
  box-shadow: var(--shadow-1);
  position: sticky; top: 14px; z-index: 90;
}
.search-container { position: relative; flex: 1; min-width: 260px; }
.search-icon {
  position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
  color: var(--ink-3); font-size: 13px; pointer-events: none;
}
.search-bar {
  height: 42px; padding-left: 38px; border-radius: var(--r-pastilla);
  background: var(--paper); border-color: var(--line);
  font-size: 13px;
}
/* `.spotlight-results` vivía aquí y se retiró el 03-09-2026 con el segundo
   buscador (ver `buscarSpotlight` en app.js). `.spotlight-item` NO se toca: la
   usan las sugerencias de `#suggestions-list` en el registro de expedientes. */
.spotlight-item {
  padding: 12px 16px; font-size: 13px; cursor: pointer;
  border-bottom: 1px solid var(--line); color: var(--ink-2);
  transition: background 120ms;
}
.spotlight-item:last-child { border-bottom: none; }
.spotlight-item:hover { background: var(--gold-soft); }
.spotlight-item b { color: var(--ink); }
.header-actions { display: flex; align-items: center; gap: 16px; }
/* LA BANDEJA DE LOS DOS PORTALES (06-09-2026) — ver el comentario de
   `#btn-bandeja-portales` en app.html. Es un botón con texto, no un icono
   suelto: «El CEJ y el SINOE» no se adivina de un símbolo, y era justo lo que
   Piero quería ver sin buscarlo. En pantalla estrecha se queda el icono, que
   es lo que cabe al lado de la campana y el registro. */
.btn-portales {
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  height: 38px; padding: 0 14px; font-family: inherit;
  font-size: 12.5px; font-weight: 700; color: var(--accent-ink);
  background: var(--gold-soft); border: 1px solid var(--gold);
  border-radius: var(--r-pastilla); white-space: nowrap;
  transition: background var(--speed), filter var(--speed);
}
.btn-portales:hover { background: var(--card); }
.btn-portales i { font-size: 14px; }
/* 🆕 14-09 · La burbuja de «por leer» se cuelga de la esquina del botón, igual
   que la de la campana: `.badge-campana` ya está medida y pide un padre
   colocado. Un poco más afuera porque el botón es una pastilla, no un círculo. */
.btn-portales { position: relative; }
.btn-portales .badge-campana { top: -7px; right: -7px; }
/* 🪤 DOS CONDICIONES, NO UNA. El `@media` mide la VENTANA, y con el Socio
   abierto la ventana no encoge: encoge el sitio para trabajar. `body.estrecho`
   es LA condición que significa «no hay sitio» en esta casa —la puso el 13-08
   la cabecera de la Carpeta, que se salía justo por esto—, así que el botón se
   queda en icono también ahí. Sin la segunda, entre 1081 px y el punto en que
   el Socio aprieta, esta fila pelearía por el ancho con el buscador. */
@media (max-width: 1080px) {
  .btn-portales { padding: 0 12px; }
  .btn-portales-txt { display: none; }
}
body.estrecho .btn-portales { padding: 0 12px; }
body.estrecho .btn-portales-txt { display: none; }
.header-datetime-box {
  display: flex; align-items: center; gap: 8px;
  font-size: 13px; font-weight: 600; color: var(--ink-2);
  background: var(--paper); border: 1px solid var(--line);
  padding: 8px 14px; border-radius: var(--r-pastilla); white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.btn-campana {
  font-size: 15px; color: var(--ink-2); cursor: pointer;
  width: 40px; height: 40px; display: flex; align-items: center; justify-content: center;
  border-radius: 50%; transition: background var(--speed), color var(--speed);
}
.btn-campana:hover { background: var(--gold-soft); color: var(--acento-txt); }
.badge-campana {
  position: absolute; top: -2px; right: -2px;
  background: var(--danger); color: #fff;
  font-size: 11px; font-weight: 700;
  min-width: 17px; height: 17px; border-radius: var(--r-md);
  display: flex; align-items: center; justify-content: center;
  padding: 0 4px; pointer-events: none;
}
#panel-auditoria {
  display: none; position: absolute; right: 0; top: 48px; z-index: 400;
  width: 340px; max-height: 380px; overflow-y: auto;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-md); box-shadow: var(--shadow-2); padding: 16px;
}
#panel-auditoria h4 {
  font-size: 13px; color: var(--ink); letter-spacing: 0.4px;
  padding-bottom: 10px; border-bottom: 1px solid var(--line); margin-bottom: 8px;
}
.audit-item { font-size: 12px; color: var(--ink-2); padding: 8px 0; border-bottom: 1px dashed var(--line); }
.audit-date { display: block; font-size: 11px; color: var(--acento-txt); font-weight: 600; margin-bottom: 1px; }
/* Centro de notificaciones (campana) — avisos concretos y accionables */
#panel-notif {
  display: none; position: absolute; right: 0; top: 48px; z-index: 400;
  width: 380px; max-height: 420px; overflow-y: auto;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-md); box-shadow: var(--shadow-2); padding: 16px;
}
#panel-notif h4 {
  font-size: 13px; color: var(--ink); letter-spacing: 0.4px;
  padding-bottom: 10px; border-bottom: 1px solid var(--line); margin-bottom: 6px;
}
.notif-item {
  display: flex; gap: 10px; align-items: flex-start;
  font-size: 13px; line-height: 1.5; color: var(--ink-2);
  padding: 10px 8px; border-bottom: 1px dashed var(--line);
  cursor: pointer; border-radius: var(--r-sm); transition: background var(--speed);
}
.notif-item:hover { background: var(--gold-soft); }
.notif-item i { margin-top: 2px; flex-shrink: 0; }
.notif-item.leida { opacity: .62; }
.notif-item.n-crit i { color: var(--danger-txt); }
.notif-item.n-hoy i { color: #b45309; }
.notif-item.n-ok i { color: var(--acento-txt); }
.notif-item.n-vig i { color: #1a7f37; }
.notif-vacio { font-size: 12px; color: var(--ink-3); padding: 12px 4px; }
/* 🔴 EN EL CELULAR SE SALÍAN DE LA PANTALLA (arreglado 2026-08-06).
   Los dos paneles cuelgan del icono con `right: 0` y miden 380 y 340 px. En un
   teléfono de 375 px de ancho eso desborda por la IZQUIERDA y el texto queda
   cortado contra el borde: se leía "ociolegal.pe" en vez de "sociolegal.pe".
   Se anclan a la VENTANA (`fixed`) y no al icono, con un margen a cada lado, de
   modo que su ancho lo manda la pantalla y no puede volver a pasar.
   Comprobado que `fixed` funciona aquí: ningún ancestro tiene `transform`,
   `filter` ni `backdrop-filter`, que son los que lo convertirían en `absolute`
   sin avisar (`.glass` es solo fondo, borde y sombra). */
@media (max-width: 640px) {
  #panel-notif, #panel-auditoria {
    position: fixed; left: 10px; right: 10px; top: 68px;
    width: auto; max-width: none; max-height: 70vh;
  }
}
/* Opt-in elegante de avisos push (dentro de la campana) */
#notif-push-cta {
  margin-top: 8px; padding: 12px 12px; border-radius: var(--r-md);
  background: var(--gold-soft); border: 1px solid var(--line);
}
#notif-push-cta .npc-txt {
  display: block; font-size: 12px; line-height: 1.45; color: var(--ink-2);
}
#notif-push-cta .npc-txt i { color: var(--acento-txt); margin-right: 6px; }
#notif-push-cta .npc-btn {
  margin-top: 10px; width: 100%; padding: 8px 10px; cursor: pointer;
  font-size: 12px; font-weight: 700; letter-spacing: .3px;
  color: var(--accent-on-deep); background: var(--navy-900);
  border: 1px solid var(--gold); border-radius: var(--r-sm);
  transition: filter var(--speed);
}
#notif-push-cta .npc-btn:hover { filter: brightness(1.15); }
/* Las tres tandas de aviso. Antes esto era un desplegable con las 24 horas
   del día; ahora informa en vez de preguntar (ver `pintarTandasAvisos`). */
#notif-hora-row {
  margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line);
}
.notif-tandas-tit {
  font-size: 12px; font-weight: 700; color: var(--ink-2); margin-bottom: 6px;
}
.notif-tandas-tit i { color: var(--acento-txt); margin-right: 6px; }
.notif-tandas { list-style: none; margin: 0; padding: 0; }
.notif-tandas li {
  font-size: 12px; line-height: 1.5; color: var(--ink-2);
  padding: 3px 0 3px 10px; border-left: 2px solid var(--line);
}
.notif-tandas li b { color: var(--ink); font-variant-numeric: tabular-nums; }
.notif-tandas-pie { margin-top: 6px; font-size: 11px; line-height: 1.45; color: var(--ink-3); }
/* 🔔 09-09 · «Dónde te estoy avisando»: la lista de aparatos con su último
   acuse. Mismo bloque visual que las tandas —es la misma clase de dato, dentro
   de la misma campana— con una línea de estado por aparato.
   🎨 El color va por `--senal-*` y no por el token crudo: es una SEÑAL sobre
   el fondo de la campana, y en oscuro el token crudo se apaga contra ella (es
   la regla que nació el 07-09 con la pastilla hueca a 1,08:1).
   📐 Y el suelo de 11 px: aquí no baja de ahí ninguna línea. */
#notif-entregas { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--line); }
.notif-entregas-lista li { padding: 5px 0 5px 10px; }
.notif-entregas-lista .ent-ok { color: var(--success-txt); font-size: 11px; }
.notif-entregas-lista .ent-mal { color: var(--warning-txt); font-size: 11px; }
.notif-entregas-lista .ent-nada { color: var(--ink-3); font-size: 11px; }
.notif-entregas-lista .ent-ok i,
.notif-entregas-lista .ent-mal i { margin-right: 4px; }
#usuario-rol-header {
  background: var(--navy-900) !important; color: var(--accent-on-deep);
  border: 1px solid var(--gold) !important;
  border-radius: var(--r-pastilla); font-weight: 700; letter-spacing: 0.6px;
}

/* ---------- FRANJA DEL VIGÍA (sustituyó a la barra de Fuentes) ----------
   Datos reales del trabajo de anoche.
   ⚠️ 2026-08-06: aquí decía que los chips `.fuente-chip` de más abajo "siguen
   vivos porque los usa el modal de Consultas rápidas". Era falso por partida
   doble: ese modal pintaba `.fuente-card`, nunca `.fuente-chip`, y además se
   retiró junto con RUC/OSCE. Toda esa familia (`.fuente-chip`, `.fuentes-bar-tit`,
   `.fuentes-leyenda`, `.fuentes-ver`, `.fc-dot`, `.lg-dot` y las animaciones
   `fc-halo-*`) ya está BARRIDA: 45 líneas, cero elementos en pantalla y cero
   menciones en JS o HTML.
   🔑 Lección: la primera acotación decía "≈705-750" y era corta — quedaba una
   `.fuentes-leyenda` suelta en un @media de la línea 2820. La cazó el control
   de "nadie la nombra fuera del rango", no la lectura a ojo. Al barrer CSS,
   buscar la clase en TODO el archivo, no solo alrededor del bloque. */
/* 🎨 06-09-2026 · LA FRANJA, EN DOS PISOS. Antes era UNA fila elástica donde
   caían el rótulo, la alarma, el remedio, los números y los botones, todos con
   el mismo peso: el ojo no tenía por dónde empezar. Ahora la caja es una
   columna con una CABECERA fija (rótulo + lo que se pulsa) y un CUERPO con las
   zonas. Ver el bloque de las tres zonas en `renderFranjaVigia` (js/parte.js).
   🪤 El `flex-wrap` de antes es lo que permitía que el corte de línea cayera
   entre dos botones (medido el 10-08 en 32 de 51 anchos). Los botones siguen
   atados dentro de `.vg-acciones`; lo que cambia es que ahora viven en su
   propio piso y ni siquiera comparten fila con los datos. */
.vigia-bar {
  display: flex; flex-direction: column; gap: 10px;
  margin: 18px 0 6px; padding: var(--caja-compacta);
  background: var(--card); border: 1px solid var(--line);
  border-left: 3px solid var(--gold);
  border-radius: var(--r-lg); box-shadow: var(--shadow-1);
}
.vg-cab { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.vg-cuerpo { display: flex; flex-direction: column; gap: 8px; }
/* EL TITULAR: qué está pasando. La línea más grande de la franja.
   🪤 EN COLUMNA, no en fila. Medido en el banco: cuando coinciden dos avisos
   —«llevo 6 días sin revisar el CEJ» y «el CEJ ahora exige identificarse»—, en
   fila caben los dos en el mismo renglón y se leen como UNA frase, con la
   segunda alarma disfrazada de coletilla de la primera. Son dos problemas
   distintos, con dos remedios distintos: uno por renglón. */
.vg-titular { display: flex; flex-direction: column; align-items: flex-start; gap: 6px; font-size: 13.5px; }
/* 🪤 El titular se escribe como una FRASE, así que aquí `.vg-dato` deja de ser
   `inline-flex`: en flex, cada trozo de texto suelto es un elemento aparte, y
   al partirse en el celular «Llevo 3 días sin revisar el CEJ» y «— última vez,
   02/09 22:27» quedaban en dos columnas en vez de seguir uno detrás de otro.
   Medido a 375 px. En bloque, el texto envuelve como texto. */
.vg-titular .vg-dato { display: block; font-size: inherit; line-height: 1.45; }
.vg-titular .vg-dato > i:first-child { margin-right: 7px; }
/* EL REMEDIO: lo único que se pulsa aquí dentro, y por eso tiene forma de
   cosa que se pulsa. Antes era una línea gris igual que los datos. */
.vg-remedios { display: flex; flex-direction: column; gap: 6px; }
.vg-remedio {
  display: flex; align-items: center; gap: 9px; width: 100%; cursor: pointer;
  padding: 9px 12px; font-family: inherit; font-size: 12.5px; line-height: 1.45;
  text-align: left; color: var(--ink-2);
  background: var(--paper); border: 1px solid var(--line-strong);
  border-radius: var(--r-sm); transition: border-color var(--speed), background var(--speed);
}
.vg-remedio:hover, .vg-remedio:focus-visible { border-color: var(--gold); background: var(--gold-soft); }
.vg-remedio > span { flex: 1; min-width: 0; }
.vg-remedio i:first-child { color: var(--accent-ink); font-size: 13px; flex: none; }
.vg-remedio-ir { color: var(--ink-3); font-size: 11px; flex: none; }
/* LOS NÚMEROS, en pastillas: se leen de un vistazo y no obligan a leer una
   frase entera para saber cuántos son. */
.vg-chips { display: flex; flex-wrap: wrap; gap: 8px; }
/* 🪤 16-09 · LA MISMA TRAMPA QUE EN `.vg-titular .vg-dato`, Y AQUÍ SEGUÍA VIVA.
   Piero mandó la captura: «5 de tus 71 sin leer — ni una vez — cómo se
   arregla» salía en CUATRO COLUMNAS, con «ni / una / vez» una palabra por
   renglón. La causa es la de siempre: en `inline-flex` cada trozo de texto
   suelto y cada `<b>` es un ELEMENTO de la fila, no palabras de una frase; al
   no caber, flex los encoge uno a uno y cada uno envuelve por su cuenta.
   Reproducido en el banco a 320 px: la pastilla se quedaba en 233 px de los
   292 disponibles y ocupaba 2 renglones en columnas. En `inline-block` el
   texto envuelve COMO TEXTO y llena el ancho.
   🔑 El hueco del icono deja de ser `gap` y pasa a ser su margen: `gap`
   separaba TODOS los trozos, que es justo lo que los convertía en columnas. */
.vg-chip {
  display: inline-block; max-width: 100%;
  padding: 5px 11px; font-family: inherit; font-size: 12px; line-height: 1.4;
  color: var(--ink-2); background: var(--paper);
  border: 1px solid var(--line); border-radius: var(--r-pastilla);
  text-align: left;
}
button.vg-chip { cursor: pointer; transition: border-color var(--speed), background var(--speed); }
button.vg-chip:hover, button.vg-chip:focus-visible { border-color: var(--gold); background: var(--gold-soft); color: var(--accent-ink); }
button.vg-chip:disabled { cursor: default; opacity: .7; }
.vg-chip i { color: var(--ink-3); font-size: 11px; }
.vg-chip > i:first-child { margin-right: 6px; }
/* Lo que va en negrita aquí son números, fechas y dos o tres palabras que se
   leen de golpe («ni una vez», «cómo se arregla»): partirlas por la mitad es
   lo que hacía que la franja se leyera como una tabla rota. Son cortas: nunca
   se salen aunque la letra del teléfono venga agrandada. */
.vg-chip b, .vg-dato b { white-space: nowrap; }
.vg-chip b { color: var(--ink); font-weight: 700; font-variant-numeric: tabular-nums; }
.vg-chip-mal, .vg-chip-mal i { color: var(--warning-txt); }
.vg-chip-mal { border-color: color-mix(in srgb, var(--warning-txt) 34%, transparent); background: var(--warning-bg); }
.vg-chip-mal b { color: inherit; }
.vg-chip-ok, .vg-chip-ok i { color: var(--success-txt); }
.vg-chip-nuevo, .vg-chip-nuevo i, .vg-chip-nuevo b { color: var(--acento-txt); }
.vg-chip-nuevo { border-color: color-mix(in srgb, var(--acento-txt) 34%, transparent); }
.vg-chip-espera, .vg-chip-espera i { color: var(--ink-3); }
/* EL PIE: la explicación larga, si hace falta. */
.vg-pie { display: flex; flex-direction: column; gap: 4px; }
.vigia-bar-tit { font-size: 11px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: var(--accent-ink); display: inline-flex; align-items: center; gap: 8px; }
/* Las acciones de la franja van empujadas a la derecha del todo para que no se
   mezclen con los datos y se lean como lo que son: lo único que se PULSA aquí.
   🪤 2026-08-10 — el `margin-left:auto` estaba en `.vg-accion` (el botón) y no
   en esta caja, y los dos botones eran piezas sueltas de la fila elástica. El
   corte de línea podía caer entre ellos y los mandaba a esquinas opuestas
   (medido: se partían en 32 de 51 anchos, entre ellos todo 1140-1400 px; por
   eso al 90% de zoom se veían bien y al 100% no). Atados en una caja, la fila
   los mueve JUNTOS. El `auto` vive aquí ahora: no lo devuelvas al botón. */
.vg-acciones { margin-left: auto; display: inline-flex; align-items: center; gap: 8px; }
.vg-accion { display: inline-flex; align-items: center; justify-content: center;
  gap: 7px; cursor: pointer; white-space: nowrap; height: 34px; padding: 0 14px;
  font-family: inherit; font-size: 12.5px; font-weight: 700; color: var(--accent-ink);
  background: var(--card); border: 1px solid var(--gold); border-radius: var(--r-md);
  transition: background var(--speed), filter var(--speed); }
.vg-accion:hover { background: var(--gold-soft); }
.vg-accion:disabled { opacity: .65; cursor: default; }
/* La segunda acción de la franja («Traer un mes anterior») es del mismo tipo
   que la primera y tiene que verse igual: mismo alto, misma forma, mismo
   icono. Sólo cambia el borde, que va apagado para que «Revisar mi casilla
   ahora» siga siendo la acción principal. La separación entre ambos la pone
   el `gap` de `.vg-acciones`, no un margen de este botón. */
.vg-accion.vg-accion-sec { border-color: var(--line-strong); color: var(--ink-2); }
.vg-accion.vg-accion-sec:hover { border-color: var(--gold); background: var(--gold-soft); color: var(--accent-ink); }
.vigia-bar.vg-alarma .vg-accion { color: var(--danger-txt); border-color: var(--danger-txt); }
.vigia-bar.vg-aviso .vg-accion { color: var(--warning-txt); border-color: var(--warning-txt); }
.vigia-revisar-res { margin: 0 0 10px; padding: 12px 16px; font-size: 13px; line-height: 1.6;
  background: var(--card); border: 1px solid var(--line); border-left: 3px solid var(--gold);
  border-radius: var(--r-lg); box-shadow: var(--shadow-1); }
/* En pantalla estrecha las dos acciones dejan de ir a la derecha y pasan a
   ocupar el ancho entero, una debajo de otra. El `align-items:stretch` es lo
   que las hace anchas: en una columna flex, estirar ES el ancho completo — no
   hace falta `width:100%` en el botón. */
/* 🔴 06-09 · EN EL CELULAR, PRIMERO EL DIAGNÓSTICO Y DESPUÉS EL REMEDIO.
   Medido en el banco a 375 px: con la cabecera arriba, lo primero que salía
   eran los DOS botones a pantalla completa —«Revisar mi casilla ahora» y
   «Traer un mes anterior»— y la alarma («llevo 3 días sin revisar el CEJ»)
   quedaba debajo de ellos. O sea que en el teléfono, que es donde Piero mira
   esto, se ofrecía la solución antes de contar el problema.
   🔑 `display: contents` en la cabecera saca a sus dos hijos a la rejilla de la
   franja, y ahí se ordenan: rótulo, cuerpo, botones. Sin duplicar marcado ni
   pintar dos cabeceras distintas para el mismo estado. */
@media (max-width: 700px) {
  .vigia-bar { display: grid; grid-template-columns: 1fr; }
  .vg-cab { display: contents; }
  .vigia-bar-tit { order: 1; }
  .vg-cuerpo { order: 2; }
  .vg-acciones { order: 3; margin-left: 0; width: 100%; flex-direction: column; align-items: stretch; }
}
.vg-dato { font-size: 13px; color: var(--ink-2); display: inline-flex; align-items: center; gap: 8px; }
.vg-dato i { color: var(--ink-3); font-size: 12px; }
.vg-dato b { color: var(--ink); font-weight: 700; }
/* 🪦 06-09-2026 · `.vg-link`, `.vg-ok` y `.vg-nuevo` SE BARREN.
   Eran «un dato que además lleva a algún sitio», pintado igual que los demás
   con un subrayado de puntitos. Con las tres zonas nuevas ya no hacen falta y
   además eran parte del problema: lo pulsable se pintaba como lo que sólo
   informa. Lo que llevaba a algún sitio es ahora `.vg-remedio` (lo que se hace)
   o `button.vg-chip` (los números que se pulsan), y los estados de color viven
   en `.vg-chip-ok` / `.vg-chip-nuevo`.
   🔑 Se borran en vez de dejarlas: una clase huérfana acaba reapareciendo en el
   sitio equivocado, que es la misma lección del token `--vino`. Comprobado:
   cero menciones en JS y en HTML. */
.vg-dato.vg-espera, .vg-dato.vg-espera i { color: var(--ink-3); font-style: italic; }
/* El Vigía lleva días sin trabajar. El silencio del Vigía es idéntico a
   "no hay novedades", y esa confusión es la que cuesta un plazo: aquí la
   franja deja de informar y pasa a avisar. */
.vigia-bar.vg-aviso { border-color: var(--warning-txt); border-left-color: var(--warning-txt); background: var(--warning-bg); }
.vigia-bar.vg-alarma { border-color: var(--danger-txt); border-left-color: var(--danger-txt); background: var(--danger-bg, var(--warning-bg)); }
.vigia-bar.vg-aviso .vigia-bar-tit { color: var(--warning-txt); }
.vigia-bar.vg-alarma .vigia-bar-tit { color: var(--danger-txt); }
.vg-dato.vg-mal, .vg-dato.vg-mal i { color: var(--warning-txt); }
.vigia-bar.vg-alarma .vg-dato.vg-mal, .vigia-bar.vg-alarma .vg-dato.vg-mal i { color: var(--danger-txt); }
.vg-dato.vg-mal b { color: inherit; }
.vg-dato.vg-mal-sub { flex-basis: 100%; font-size: 12px; color: var(--ink-2); }
@media (max-width: 640px) {
  .vigia-bar { gap: 8px 12px; padding: 12px 14px; }
}
/* ---- El HISTORIAL del Vigía (dentro de su ventana) ----
   Lo pidió Piero el 2026-08-08: «si quiere volver a ver, podría entrar de nuevo
   a ver lo que trabajó el Vigía». Hasta hoy una novedad abierta se marcaba
   leída y desaparecía para siempre, porque la app sólo escucha las no leídas.
   Se reutilizan las variables de siempre y ni un color nuevo: esto es una
   lista, no una pantalla. */
.vg-hist-dia {
  font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .05em;
  color: var(--ink-3); margin: 14px 0 6px;
}
.vg-hist-dia:first-child { margin-top: 0; }
/* 🆕 15-09 · «Marcar las N como vistas»: a la derecha de las pestañas, con el
   mismo aspecto de pastilla pero sin competir con la activa (sin relleno). */
.vg-marcar-todas {
  margin-left: auto; font-family: inherit; font-size: 12px; font-weight: 600; cursor: pointer; width: auto;
  padding: 5px 11px; border-radius: var(--r-pastilla, 999px);
  border: 1px solid var(--line-strong); background: transparent; color: var(--ink-2);
}
.vg-marcar-todas:hover, .vg-marcar-todas:focus-visible { border-color: var(--gold); background: var(--gold-soft); color: var(--ink); }
.vg-marcar-todas i { margin-right: 3px; }
.vg-hist-it {
  display: flex; align-items: flex-start; gap: 10px; width: 100%; text-align: left;
  font-family: inherit; cursor: pointer; margin-bottom: 6px;
  padding: 10px 12px; background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-sm); transition: border-color var(--speed), background var(--speed);
}
.vg-hist-it:hover, .vg-hist-it:focus-visible { border-color: var(--gold); background: var(--gold-soft); }
.vg-hist-ico { color: var(--ink-3); font-size: 13px; margin-top: 2px; flex-shrink: 0; }
.vg-hist-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.vg-hist-tit { font-size: 13px; font-weight: 700; color: var(--ink); }
.vg-hist-sub { font-size: 12px; color: var(--ink-2); line-height: 1.45; }
.vg-hist-meta { font-size: 11px; color: var(--ink-3); }
/* 🆕 15-09 (noche) · A quién patrocinas, junto al número del expediente. */
.vg-hist-cli { font-size: 12px; font-weight: 600; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vg-hist-cli i { margin-right: 4px; font-size: 11px; color: var(--ink-3); }

/* Lo que YA he abierto desde esta lista (2026-08-10, lo pidió Piero: «marcar la
   notificación ya vista para no perder la ilación»).
   🔑 La barra va con `box-shadow: inset`, NO con `border-left`: un borde de 3px
   ensancharía sólo las filas vistas y la lista entera bailaría al ir marcándose.
   🔑 Y el texto NO se apaga. Bajar el contraste de lo ya visto es justo lo que
   impide releerlo, y aquí el caso de uso es volver. Tampoco palomita ni gris
   fuerte: los dos se leen como «resuelto» o «archivado», que es otra cosa. */
.vg-hist-it.vg-visto {
  background: var(--bg-2);
  box-shadow: inset 3px 0 0 var(--line-strong);
}
.vg-hist-it.vg-ultima { box-shadow: inset 3px 0 0 var(--gold); }
.vg-visto-sello { color: var(--ink-3); }
.vg-hist-it.vg-ultima .vg-visto-sello { color: var(--acento-txt); font-weight: 600; }

/* La fila de la Carpeta a la que se acaba de llegar desde el Vigía. Dura unos
   segundos: es una señal de «es ésta», no un estado que haya que apagar.
   🪤 2026-08-11 — Piero: «debería dirigirte abajo y parpadear […] eso no sale
   ahora». Eran dos cosas y ninguna era el CSS de fondo, pero ésta también
   fallaba: se pintaba con `--gold-soft`, que es el MISMO tinte al 12-14% del
   `:hover` de media app. Un destello que se ve igual que pasar el ratón por
   encima no dice «es ésta», dice «aquí está el cursor». Ahora PARPADEA —tres
   golpes— y con un tinte propio y un aro dorado alrededor, que es lo que hace
   que el ojo lo encuentre en una lista de cuarenta filas. */
.doc-resaltado {
  animation: docResaltado 2.4s ease-out 1;
  border-radius: var(--r-sm);
  position: relative;
  z-index: 1;
}
@keyframes docResaltado {
  0%, 22%, 44% { background: var(--gold-flash); box-shadow: 0 0 0 2px var(--gold), inset 4px 0 0 var(--gold); }
  11%, 33%     { background: transparent;      box-shadow: 0 0 0 2px transparent, inset 4px 0 0 transparent; }
  /* Después de los tres golpes se queda encendido un momento y se apaga: sin
     esa cola, el último parpadeo deja la fila igual que las demás justo cuando
     el abogado termina de bajar la vista hasta ella. */
  75%          { background: var(--gold-flash); box-shadow: 0 0 0 2px var(--gold), inset 4px 0 0 var(--gold); }
  100%         { background: transparent;      box-shadow: 0 0 0 2px transparent, inset 4px 0 0 transparent; }
}
/* Quien pide menos movimiento no se queda sin la señal: se queda sin el
   parpadeo. La fila sigue marcada el mismo tiempo, encendida y quieta. */
@media (prefers-reduced-motion: reduce) {
  .doc-resaltado { animation: docResaltadoQuieto 2.4s ease-out 1; }
  @keyframes docResaltadoQuieto {
    0%, 80% { background: var(--gold-flash); box-shadow: 0 0 0 2px var(--gold), inset 4px 0 0 var(--gold); }
    100%    { background: transparent;      box-shadow: 0 0 0 2px transparent, inset 4px 0 0 transparent; }
  }
}


/* Rótulos que agrupan los desplegables del panel del Redactor: separan lo que
   cambia ESTE escrito de lo que cambia TODOS los del estudio. Deliberadamente
   discretos — ordenan, no compiten con los desplegables que rotulan. */
.ed-grupo {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em;
  color: var(--ink-3); margin: 14px 0 6px; padding-bottom: 4px;
  border-bottom: 1px solid var(--line);
}
.ed-grupo:first-child { margin-top: 2px; }

/* ---------- Pestañas ---------- */
.tab-pane { display: none; animation: fadeUp 320ms var(--ease); }
.tab-pane.active { display: block; }
@keyframes fadeUp { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; transition-duration: 0.01ms !important; }
}

/* ---------- Tarjetas ---------- */
.card, .glass {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-1);
}
.card { padding: 24px; }
/* ============================================================
   🏷️ 06-09-2026 · EL TÍTULO DE UNA PANTALLA SE ESCRIBE DE UNA SOLA MANERA
   ------------------------------------------------------------
   Lo pidió Piero, y con la razón medida: *«las letras de Agenda, Carpeta de
   expedientes, Escritor y Facturación llevan diferente tamaño… mantener el
   mismo formato para todo SocioLegal, si no se ve todo informal y no tan
   profesional»*. Así estaban los cuatro títulos de las cuatro pantallas que
   más usa:

       Agenda .................. 19 px   <h2 class="tudia-titulo">   icono accent
       Carpeta de Expedientes .. 17 px   <span class="ch-k">         SIN ICONO
       El Redactor ............. 14 px   <div class="card-title">    icono --gold
       Facturación ............. 19 px   <h2 style="…"> EN LÍNEA     icono accent

   Cuatro tamaños, cuatro etiquetas, dos colores de icono y uno sin icono. Y el
   de Facturación con el estilo escrito dentro del HTML, así que ni siquiera se
   podía cambiar desde aquí.

   🔑 LA CAUSA NO ES EL DESCUIDO, ES QUE NO HABÍA DÓNDE: no existía una clase
   para «título de pantalla», así que cada uno se resolvió con lo que tenía a
   mano. Ahora existe, y sólo hay DOS escalones en toda la app:

       .titulo-pantalla  19 px — Agenda · Carpeta · El Redactor · Facturación
       .card-title       14 px — lo de DENTRO (Documentos, Emitidas, Contacto…)

   ⛔ Al añadir una pantalla o una tarjeta, usa una de las dos. Si ninguna vale,
   el problema es la jerarquía, no el tamaño (misma regla que la escala de la
   letra, más arriba). Lo vigila `pruebas/la-escala-de-la-letra.test.js`.
   ============================================================ */
.titulo-pantalla {
  font-family: var(--font-ui); font-size: 19px; font-weight: 700;
  letter-spacing: -0.01em; color: var(--ink); margin: 0;
  display: flex; align-items: center; gap: 10px; min-width: 0;
}
.titulo-pantalla > i { color: var(--accent-ink); font-size: 17px; flex: none; }

/* ============================================================
   🎨 07-09-2026 · LAS CUATRO CABECERAS CIERRAN IGUAL
   ------------------------------------------------------------
   Piero: *«me gustaría que salga como El Redactor y con una línea abajo… sentí
   que algunas cosas sin cuadro no queda bien; como sale uno, creo que deberían
   salir todos»*. Tenía razón en lo que veía, aunque la causa era otra: los
   cuatro títulos ya se escriben igual desde ayer, pero **cerraban distinto** —
   El Redactor con línea, la Agenda sin nada, y la Carpeta y Facturación
   flotando sobre el fondo sin ningún remate. Falta el punto y aparte, no el
   cuadro.

   ⛔ POR QUÉ NO SE METEN LOS CUATRO EN UNA TARJETA, que fue lo que él propuso:
   sus pantallas tienen VARIAS tarjetas debajo (Facturación: los tres importes,
   el formulario y «Emitidas»; la Carpeta: la barra de filtros y la lista). Un
   título dentro de su propia tarjeta sería una caja que sólo contiene un
   título —y, peor, quedaría al mismo nivel que las tarjetas de contenido, o
   sea que dejaría de mandar sobre ellas—. El título de una pantalla va POR
   ENCIMA de sus tarjetas; si baja a ser una más, se pierde la jerarquía que
   este repaso vino a poner.

   🔑 Lo que sí unifica es el CIERRE: una línea fina debajo de la cabecera
   entera —título y, si los hay, sus botones—. Da el mismo acabado a los
   cuatro, marca dónde empieza el contenido y no inventa cajas vacías.
   ============================================================ */
.cabecera-pantalla {
  padding-bottom: 14px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--line);
}

.card-title {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  font-size: 14px; font-weight: 700; color: var(--ink);
  padding-bottom: 16px; margin-bottom: 18px;
  border-bottom: 1px solid var(--line);
}
/* 🎨 06-09 · El icono va en `--accent-ink`, no en `--gold` crudo. Es el mismo
   que usan los otros títulos de la app, y el oro puro sobre blanco se queda en
   2,4 de contraste — por debajo de lo legible; el propio bloque de la paleta,
   arriba, explica por qué existe `--accent-ink`. */
.card-title i { color: var(--accent-ink); margin-right: 6px; }
/* 🔴 «El Redactor» EN UNA SOLA LÍNEA (2026-08-13, lo vio Piero en su celular).
   El rótulo le salía partido en «El» / «Redactor». Medido aquí a 375 px: el
   texto pide 96 px y la fila tiene 298 — o sea que con la letra que dice la
   hoja NO PUEDE partirse, y en este navegador no se reproduce. La causa
   probable es el inflado de letra de Safari en iOS, que se apaga arriba
   (`text-size-adjust`); esta línea es el cinturón además de los tirantes: con
   el triple de sitio del que necesita, prohibirle el salto no puede pasarle
   factura a nadie.
   ⚠️ Va SÓLO en este título. Las tarjetas tienen rótulos largos
   («Distribución por etapa procesal»), y ahí el salto de línea es lo correcto:
   un `nowrap` general las sacaría de su caja.
   🔄 06-09 · El rótulo dejó de ser un `.card-title` y pasó a `.titulo-pantalla`
   —los cuatro títulos de pantalla se escriben ya de una sola manera—, así que
   la regla le sigue. **Lo cazó la prueba, no la vista**: el marcado cambió y
   `pruebas/celular-descuadres.test.js` avisó de que este selector se había
   quedado apuntando a nada. Sin ella, el rótulo habría vuelto a partirse en el
   celular de Piero y nadie lo habría sabido hasta que lo viera él. */
#tab-editor .editor-side .titulo-pantalla,
.titulo-1linea { white-space: nowrap; }
/* 🔴 07-09 · «Nueva nota de honorarios» LE SALÍA PARTIDO EN DOS. Segunda vez
   que pasa lo mismo y por eso el arreglo deja de ser un selector a medida:
   `.titulo-1linea` es la marca de «este rótulo NO se parte», y se le pone al
   `.card-title` que la necesita en vez de escribir otra regla por su ruta.
   Medido aquí a 390 px: el texto pide 203 px en una fila de 317 — **1,56× de
   sobra**, o sea que con la letra de la hoja no puede partirse y en Chromium no
   se reproduce, exactamente como pasó con «El Redactor» el 13-08. El salto sale
   de Safari en iOS; con tanto sitio libre, prohibirlo no le cuesta nada a nadie.
   ⚠️ Se pone POR RÓTULO y nunca a `.card-title` entero: hay tarjetas con
   títulos largos («Distribución por etapa procesal») que SÍ deben partirse, y
   un `nowrap` general las sacaría de su caja. Lo vigila
   `pruebas/celular-descuadres.test.js`. */

.cmdk-pill { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); display: inline-flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 700; letter-spacing: .3px; color: var(--acento-txt); background: var(--gold-soft); border: 1px solid var(--gold); border-radius: var(--r-lg); padding: 6px 10px; cursor: pointer; transition: background .18s; }
.cmdk-pill:hover { background: var(--gold); color: var(--navy-950); }

/* ---------- CENTRO DE FUENTES ---------- */
.fuente-estado { font-size: 11px; font-weight: 700; padding: 4px 10px; border-radius: var(--r-lg); white-space: nowrap; display: inline-flex; align-items: center; gap: 6px; }
.fuente-estado.ok { background: var(--success-bg); color: var(--success-txt); }
.fuente-estado.warn { background: var(--warning-bg); color: var(--warning-txt); }
.fuente-estado.info { background: color-mix(in srgb, var(--senal-info) 12%, transparent); color: var(--info-txt); }
.fuente-estado.off { background: var(--paper); color: var(--ink-3); border: 1px solid var(--line); }

/* ---------- EL COMANDO (Ctrl+K) ---------- */
.cmdk-ov { position: fixed; inset: 0; z-index: 3500; display: none; align-items: flex-start; justify-content: center; padding-top: 13vh; background: rgba(8,16,25,.6); backdrop-filter: blur(6px); }
.cmdk-ov.open { display: flex; animation: fadeUp .16s var(--ease); }
.cmdk { width: 100%; max-width: 620px; background: var(--card); border: 1px solid var(--line); border-radius: var(--r-lg); overflow: hidden; box-shadow: var(--shadow-3); }
.cmdk-in { display: flex; align-items: center; gap: 12px; padding: 16px 20px; border-bottom: 1px solid var(--line); }
.cmdk-in i { color: var(--acento-txt); font-size: 15px; }
.cmdk-in input { flex: 1; border: none; background: none; outline: none; font-size: 15px; color: var(--ink); padding: 0; }
.cmdk-esc { font-size: 11px; color: var(--ink-3); border: 1px solid var(--line-strong); border-radius: var(--r-sm); padding: 4px 8px; }
.cmdk-list { max-height: 360px; overflow-y: auto; padding: 8px; }
.cmdk-sec { font-size: 11px; font-weight: 700; letter-spacing: 1.4px; text-transform: uppercase; color: var(--ink-3); padding: 12px 14px 6px; }
.cmdk-it { display: flex; align-items: center; gap: 14px; padding: 12px 14px; border-radius: var(--r-md); cursor: pointer; }
.cmdk-it.sel { background: var(--gold-soft); }
.cmdk-ic { width: 30px; height: 30px; flex-shrink: 0; border-radius: var(--r-md); background: var(--paper); display: flex; align-items: center; justify-content: center; color: var(--acento-txt); font-size: 13px; }
.cmdk-it.sel .cmdk-ic { background: var(--card); }
.cmdk-txt { min-width: 0; }
.cmdk-lb { font-size: 13px; font-weight: 500; color: var(--ink); }
/* La segunda línea: cliente · materia · juzgado en un expediente, y el
   expediente y la fecha en una actuación. Es lo que hace que el resultado se
   reconozca sin abrirlo. En una sola línea y con puntos suspensivos: un
   nombre largo no puede empujar el ancho del diálogo. */
.cmdk-sub { font-size: 11.5px; color: var(--ink-3); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ---------- EL PARTE (pantalla de entrada) ---------- */
/* PUESTA EN MARCHA (onboarding.js) — la guía de los seis pasos del abogado
   nuevo, arriba de El Parte. Sustituye a la vieja tarjeta suelta del SINOE. */
.pm {
  position: relative; overflow: hidden;
  background: var(--card, var(--paper));
  border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: var(--caja-normal); margin-bottom: 18px;
  box-shadow: 0 1px 2px rgba(16, 24, 40, .04), 0 10px 30px -14px rgba(16, 24, 40, .18);
}
/* Filo dorado superior: la firma de la casa, sin gritar. */
.pm-filo { position: absolute; inset: 0 0 auto 0; height: 3px; background: linear-gradient(90deg, var(--gold-strong), var(--gold) 45%, transparent); }
/* Halo tenue en la esquina, para que no sea una caja plana. */
.pm::after {
  content: ""; position: absolute; top: -70px; right: -70px; width: 220px; height: 220px;
  background: radial-gradient(circle, var(--gold-soft), transparent 68%); pointer-events: none;
}
.pm-head { display: flex; align-items: center; gap: 16px; position: relative; }
.pm-head-txt { flex: 1; min-width: 0; }
.pm-eyebrow { font-size: 11px; letter-spacing: .16em; text-transform: uppercase; font-weight: 700; color: var(--acento-txt); }
.pm-tit { font-family: var(--font-ui); font-size: 19px; font-weight: 700; color: var(--ink); margin-top: 6px; line-height: 1.3; letter-spacing: -.01em; }
.pm-cerrar { background: none; border: none; color: var(--ink-3); font-size: 12px; cursor: pointer; padding: 6px 10px; flex-shrink: 0; border-radius: var(--r-pastilla); border: 1px solid transparent; transition: color .18s ease, border-color .18s ease; }
.pm-cerrar:hover { color: var(--ink-2); border-color: var(--line); }

/* Anillo de avance: cuenta pasos resueltos DE VERDAD (no se llena solo). */
.pm-medidor { position: relative; width: 52px; height: 52px; flex-shrink: 0; display: grid; place-items: center; }
.pm-medidor svg { position: absolute; inset: 0; width: 52px; height: 52px; transform: rotate(-90deg); }
.pm-ring-bg { fill: none; stroke: var(--line); stroke-width: 3; }
.pm-ring-fg { fill: none; stroke: var(--gold); stroke-width: 3; stroke-linecap: round; transition: stroke-dasharray .5s cubic-bezier(.4,0,.2,1); }
.pm-medidor-n { font-family: var(--font-ui); font-size: 17px; font-weight: 600; color: var(--ink); line-height: 1; font-variant-numeric: tabular-nums; }
.pm-medidor-n small { font-size: 11px; font-weight: 600; color: var(--ink-3); }

/* Raíl vertical: los pasos como un recorrido, no como una lista suelta. */
.pm-lista { list-style: none; margin: 18px 0 0; padding: 0; }
.pm-paso { display: flex; gap: 14px; align-items: flex-start; position: relative; padding-bottom: 6px; }
.pm-paso::before {
  content: ""; position: absolute; left: 12px; top: 26px; bottom: -6px; width: 1px;
  background: var(--line);
}
.pm-paso.es-ultimo::before { display: none; }
.pm-paso.es-hecho::before { background: rgba(20,115,90,.35); }
.pm-marca {
  flex-shrink: 0; width: 25px; height: 25px; border-radius: 50%; z-index: 1;
  display: inline-grid; place-items: center; font-size: 12px; font-weight: 700;
  background: var(--paper); color: var(--ink-3); border: 1px solid var(--line-strong);
  transition: background .2s ease, color .2s ease, border-color .2s ease;
}
.pm-cuerpo { min-width: 0; flex: 1; padding-bottom: 12px; }
.pm-paso-tit { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; color: var(--ink-2); line-height: 1.45; padding: 4px 0; }
.pm-chevron { font-size: 11px; color: var(--ink-3); margin-left: auto; transition: transform .18s ease; }
.pm-paso-tit[role="button"] { cursor: pointer; border-radius: var(--r-sm); transition: color .18s ease; }
.pm-paso-tit[role="button"]:hover { color: var(--acento-txt); }
.pm-paso-tit[role="button"]:hover .pm-chevron { transform: translateY(2px); color: var(--acento-txt); }
.pm-paso-tit[role="button"]:focus-visible { outline: 2px solid var(--gold); outline-offset: 3px; }

.pm-paso.es-hecho .pm-marca { background: var(--success); color: #fff; border-color: var(--success-txt); }
.pm-paso.es-hecho .pm-paso-tit { color: var(--ink-3); }
.pm-paso.es-omitido .pm-paso-tit { color: var(--ink-3); }
.pm-paso.es-abierto .pm-marca { background: var(--gold); color: var(--navy-950); border-color: var(--gold); box-shadow: 0 0 0 5px var(--gold-soft); }
.pm-paso.es-abierto .pm-paso-tit { font-family: var(--font-ui); font-size: 15px; font-weight: 700; color: var(--ink); }

/* El paso abierto se apoya en su propio panel, para que se lea como una ficha. */
.pm-panel {
  margin-top: 10px; padding: var(--caja-compacta);
  background: var(--gold-soft); border: 1px solid rgba(197,160,89,.28);
  border-radius: var(--r-md, 10px);
}
.pm-paso-txt { font-size: 13px; line-height: 1.7; color: var(--ink-2); margin: 0; }
.pm-tag { font-size: 11px; text-transform: uppercase; letter-spacing: .09em; font-weight: 700; color: var(--ink-3); border: 1px solid var(--line-strong); border-radius: var(--r-pastilla); padding: 2px 8px; }
.pm-tag.es-ok { color: var(--success-txt); border-color: rgba(20,115,90,.4); }
.pm-acciones { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin-top: 14px; }
.pm-btn { width: auto !important; padding: 10px 16px !important; font-size: 13px !important; }
.pm-btn[disabled] { opacity: .45; cursor: not-allowed; box-shadow: none; }
.pm-nota { font-size: 12px; color: var(--ink-3); display: inline-flex; align-items: center; gap: 6px; }
.pm-saltar { background: none; border: none; color: var(--ink-3); font-size: 12px; cursor: pointer; text-decoration: underline; text-underline-offset: 3px; padding: 0; }
.pm-saltar:hover { color: var(--ink-2); }

/* Estado final: los seis pasos resueltos. Un sello, no una alerta. */
.pm-fin { display: flex; align-items: center; gap: 18px; }
.pm-fin-sello {
  flex-shrink: 0; width: 46px; height: 46px; border-radius: 50%;
  display: grid; place-items: center; font-size: 17px;
  color: var(--success-txt); border: 1.5px solid rgba(20,115,90,.45); background: var(--success-bg);
}
.pm-fin-txt { flex: 1; min-width: 0; }
.pm-fin-txt b { display: block; font-family: var(--font-ui); font-size: 17px; color: var(--ink); margin: 6px 0 4px; }
.pm-fin-txt span { display: block; font-size: 13px; line-height: 1.65; color: var(--ink-2); }

@media (max-width: 640px) {
  .pm { padding: 18px 16px 14px; }
  .pm-head { gap: 12px; flex-wrap: wrap; }
  .pm-tit { font-size: 17px; }
  .pm-cerrar { order: 3; margin-left: auto; }
  .pm-btn { width: 100% !important; }
  .pm-acciones { gap: 10px; }
  .pm-fin { flex-direction: column; align-items: flex-start; gap: 12px; }
}
@media (prefers-reduced-motion: reduce) {
  .pm-ring-fg, .pm-marca, .pm-chevron, .pm-paso-tit, .pm-cerrar { transition: none; }
}

.parte-hero {
  background: linear-gradient(150deg, var(--navy-900) 0%, var(--navy-950) 100%);
  border: 1px solid rgba(197,160,89,.28);
  border-radius: var(--r-lg); padding: var(--caja-destacada); color: var(--ink);
  box-shadow: var(--shadow-2); position: relative; overflow: hidden;
  margin-bottom: 24px;
}
body:not(.dark-mode) .parte-hero { color: #eef2f7; }
.p-eyebrow { font-size: 12px; font-weight: 700; letter-spacing: 2px; text-transform: uppercase; color: var(--acento-claro); margin-bottom: 14px; }
.p-dot { display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--success); margin-right: 8px; box-shadow: 0 0 0 4px rgba(20,115,90,.22); }
/* El saludo grande de la entrada. Es el único sitio del trabajo diario donde
   se usa la letra de títulos, y se justifica: es la frase con la que el
   sistema saluda al abogado cada mañana. */
.p-saludo { font-family: var(--font-display); font-size: 34px; font-weight: 700; color: #f5efe2; margin-bottom: 20px; line-height: 1.15; }
.p-parrafo { font-size: 17px; line-height: 1.85; color: #dfe5ee; max-width: 760px; font-weight: 400; }
.p-parrafo .p-n { color: var(--acento-claro); font-weight: 600; }
.p-acc { color: #f5efe2; font-weight: 600; cursor: pointer; border-bottom: 2px solid rgba(197,160,89,.5); padding-bottom: 1px; transition: color .18s, border-color .18s; }
.p-acc:hover { color: var(--gold); border-bottom-color: var(--gold); }
.p-cierre { margin-top: 22px; font-size: 15px; color: #aeb9c9; }
.p-cierre b { color: #eef2f7; }
/* 🎠 15-09-2026 · LOS CARRILES DE EL PARTE (antes `.p-momentos`, seis tarjetas
   en rejilla). Cada carril se desliza de lado: con el dedo en el celular, con
   la rueda o sus flechas en la computadora, y con el teclado (la pista es
   enfocable). Se ve un trozo de la tarjeta siguiente para que se entienda
   que hay más sin tener que decirlo.
   🪤 Dentro de la pista el relieve 3D se apaga: Safari no recorta lo que está
   en 3D dentro de un `overflow` (memoria «safari-no-recorta-lo-que-esta-en-3d»)
   y la tarjeta girada se pintaría fuera del carril. */
.p-carriles { display: flex; flex-direction: column; gap: 22px; margin-top: 26px; }
.p-carril-cab { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.p-carril-t { margin: 0; font-size: 15px; font-weight: 700; color: #f5efe2; letter-spacing: .2px; display: inline-flex; align-items: center; gap: 8px; }
.p-carril-n { font-size: 12px; font-weight: 800; min-width: 22px; height: 22px; padding: 0 7px; border-radius: var(--r-pastilla); display: inline-flex; align-items: center; justify-content: center; background: rgba(197,160,89,.18); border: 1px solid rgba(197,160,89,.45); color: #f0ece2; font-variant-numeric: tabular-nums; }
.p-carril-ayuda { font-size: 12px; color: #98a4b6; flex: 1 1 200px; }
.p-carril-flechas { display: none; gap: 6px; margin-left: auto; }
.p-carril.desborda .p-carril-flechas { display: inline-flex; }
.p-carril-fl { width: 32px; height: 32px; border-radius: 50%; border: 1px solid rgba(255,255,255,.28); background: rgba(255,255,255,.06); color: #f5efe2; cursor: pointer; display: inline-flex; align-items: center; justify-content: center; font-size: 12px; }
.p-carril-fl:hover:not(:disabled) { border-color: var(--gold); background: rgba(197,160,89,.14); }
.p-carril-fl:disabled { opacity: .35; filter: none; }
.p-carril-pista {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(250px, 292px);
  gap: 12px; overflow-x: auto; overflow-y: hidden; overscroll-behavior-x: contain;
  scroll-snap-type: x proximity; scroll-padding-inline: 2px;
  padding: 6px 2px 10px; /* arriba: la tarjeta sube 3 px al pasar el ratón */
  scrollbar-width: thin; scrollbar-color: rgba(255,255,255,.25) transparent;
}
.p-carril-pista:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; border-radius: var(--r-md); }
.p-carril-pista > .p-m { scroll-snap-align: start; display: flex; flex-direction: column; transform-style: flat; will-change: auto; }
.p-carril-pista > .p-m.tilt-on { transform: translateY(-3px); box-shadow: none; }
.p-carril-pista > .p-m.tilt-on .p-m-go { transform: none; }
.p-carril-pista > .p-m .p-m-d { flex: 1 1 auto; }
@media (max-width: 600px) {
  .p-carril-pista { grid-auto-columns: 84%; }
  /* En el celular se desliza con el dedo: las flechas sólo ocupaban un renglón. */
  .p-carril.desborda .p-carril-flechas { display: none; }
}
.p-m-pie { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-top: 10px; }
.p-m-pie .p-m-go { margin-top: 0; }
.p-m-btn { font: inherit; font-size: 12px; font-weight: 700; padding: 7px 12px; border-radius: var(--r-md); border: 1px solid var(--success-claro); background: rgba(34,193,151,.16); color: #eafff8; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; }
.p-m-btn:hover:not(:disabled) { background: rgba(34,193,151,.28); }
/* La cédula que actualiza un plazo ya agendado: sigue siendo una propuesta
   (punteado), pero verde — es la única con una acción de un solo clic. */
.p-m.sug.sug-llego { border-color: rgba(34,193,151,.65); background: rgba(34,193,151,.08); }
.p-m.sug.sug-llego .p-m-tag { color: var(--success-claro); }
.p-m.sug.sug-llego .p-m-go { margin-top: 0; padding: 7px 12px; }
/* La agenda, en los colores de siempre: nota (verde azulado, nunca roja),
   provisional (azul, nunca roja), audiencia (morado) y lo que viene (neutro). */
.p-m.nota { border-color: rgba(92,201,178,.45); background: rgba(92,201,178,.07); }
.p-m.nota .p-m-tag { color: #7fd8c5; }
.p-m.prov { border: 1px dashed rgba(103,155,209,.6); background: rgba(103,155,209,.08); }
.p-m.prov .p-m-tag { color: #9cc0e8; }
.p-m.aud { border-color: rgba(227,154,214,.5); background: rgba(227,154,214,.08); }
.p-m.aud .p-m-tag { color: var(--audiencia-claro); }
.p-m.prox .p-m-tag { color: #c9d2de; }
.p-m.p-m-mas { font: inherit; text-align: left; color: #f5efe2; font-size: 14px; font-weight: 700; display: flex; flex-direction: column; justify-content: center; gap: 6px; align-items: flex-start; }
.p-m.p-m-mas i { font-size: 20px; color: var(--acento-claro); }
.p-m.p-m-mas span { font-size: 12px; font-weight: 500; color: #98a4b6; }
.p-m { background: rgba(255,255,255,.05); border: 1px solid rgba(197,160,89,.2); border-radius: var(--r-lg); padding: 16px 16px; cursor: pointer; transition: transform .16s var(--ease), border-color .16s, background .16s; }
.p-m:hover { transform: translateY(-3px); border-color: var(--gold); background: rgba(197,160,89,.08); }
.p-m-tag { font-size: 11px; font-weight: 700; letter-spacing: 1px; text-transform: uppercase; }
.p-m-tag i { font-size: 11px; margin-right: 3px; }
/* TRES ESTADOS QUE NO SE PUEDEN CONFUNDIR (2026-08-01, lo pidió Piero).
   Cada uno con su color Y su icono: quien no distinga los colores igual los
   distingue.
     · rojo   = vencido o vence hoy (ya no hay margen)
     · ámbar  = confirmado, vence pronto (hay que moverse)
     · gris azulado punteado = SUGERIDO: todavía no es un plazo, es una
       propuesta que el sistema leyó y que nadie ha confirmado. */
.p-m.crit .p-m-tag { color: var(--danger-claro); }
.p-m.crit { border-color: rgba(197,48,48,.55); background: rgba(197,48,48,.10); }
.p-m.pronto .p-m-tag { color: var(--warning-claro); }
.p-m.pronto { border-color: rgba(214,158,46,.5); background: rgba(214,158,46,.09); }
.p-m.hoy .p-m-tag { color: var(--acento-claro); }
/* El tono del SUGERIDO se saca del BLANCO a baja opacidad, no de un gris
   azulado fijo. Motivo: esta tarjeta cambia de color con la paleta del estudio
   (vino burdeos, cobre, púrpura, esmeralda…) y un azul grisáceo fijo se veía
   como un parche frío pegado encima del vino o del cobre. El blanco rebajado
   es el MISMO color del fondo aclarado, así que se apaga igual en las seis.
   Un solo sitio donde se define: lo usan la tarjeta y la pastilla de arriba. */
.parte-hero {
  /* .42 y no .34: medido sobre las seis paletas, con .34 el punteado se quedaba
     en 2,92:1 sobre el esmeralda y el azul — por debajo del 3:1 mínimo para que
     un borde con significado se distinga del fondo. Con .42 las seis pasan. */
  --sug-linea: rgba(255,255,255,.42);
  --sug-linea-fuerte: rgba(255,255,255,.62);
  --sug-texto: rgba(255,255,255,.78);
  --sug-fondo: rgba(255,255,255,.07);
}
.p-m.sug {
  border: 1px dashed var(--sug-linea);
  background: var(--sug-fondo);
  box-shadow: none;
}
.p-m.sug .p-m-tag { color: var(--sug-texto); }
.p-m.sug:hover { border-color: var(--sug-linea-fuerte); background: rgba(255,255,255,.13); }
/* El sugerido con la fecha ya pasada: sigue siendo una propuesta (por eso
   conserva el punteado), pero avisa. */
.p-m.sug.sug-tarde { border-color: rgba(197,48,48,.6); background: rgba(197,48,48,.09); }
.p-m.sug.sug-tarde .p-m-tag { color: var(--danger-claro); }
/* En el sugerido, "Revisar y confirmar" es la acción de todo el cartel: se
   pinta como botón, no como un enlace más. */
.p-m.sug .p-m-go {
  margin-top: 12px; display: inline-flex; padding: 7px 14px;
  border: 1px solid var(--sug-linea-fuerte); border-radius: var(--r-md);
  color: #fff; font-weight: 700;
}
.p-m.sug:hover .p-m-go { background: rgba(255,255,255,.16); }
.p-m.sug.sug-tarde .p-m-go { border-color: var(--danger-claro); color: #f3b7b7; }
.p-m.vigia { border-color: var(--gold); background: rgba(197,160,89,.12); box-shadow: 0 0 0 1px rgba(197,160,89,.2); }
.p-m.vigia .p-m-tag { color: var(--acento-claro); }
.p-m.vigia .p-m-go { color: var(--acento-claro); }
/* El número de expediente es un DATO que hay que leer, no un adorno: va en
   tinta clara, no en el color del acento. Con el acento se quedaba en 3,92:1
   sobre la tarjeta esmeralda (el chip suma su propio velo dorado encima del
   verde de la tarjeta y el fondo sube hasta #364c37). El borde dorado ya lo
   identifica como chip; el número tiene que LEERSE. */
.p-m-exp { display: inline-flex; align-items: center; gap: 6px; margin-top: 8px; padding: 2px 10px; border-radius: var(--r-pastilla); background: rgba(197,160,89,.14); border: 1px solid rgba(197,160,89,.35); font-size: 11px; font-weight: 700; letter-spacing: .3px; color: #f0ece2; font-variant-numeric: tabular-nums; }
.p-m-exp i { font-size: 11px; color: var(--acento-claro); }
/* 🆕 15-09 (noche) · El patrocinado, debajo del número: una línea que se corta
   con «…» (entero en el `title`), para que la tarjeta no crezca de alto. */
.p-m-cli { display: block; margin-top: 6px; max-width: 100%; font-size: 12.5px; font-weight: 600; color: #e9e2d2; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.p-m-cli i { margin-right: 5px; font-size: 11px; color: var(--acento-claro); }
.p-m-t { font-size: 14px; font-weight: 600; color: #f5efe2; margin: 8px 0 4px; line-height: 1.35; }
.p-m-d { font-size: 12px; color: #98a4b6; }
.p-m-go { margin-top: 10px; font-size: 12px; font-weight: 600; color: var(--acento-claro); display: flex; align-items: center; gap: 6px; }
.p-quick { display: flex; gap: 10px; margin-top: 30px; flex-wrap: wrap; }
.p-qbtn { display: inline-flex; align-items: center; gap: 8px; min-height: 42px; padding: 0 18px; background: rgba(255,255,255,.06); border: 1px solid rgba(197,160,89,.3); border-radius: var(--r-pastilla); color: #eef2f7; font-size: 13px; font-weight: 600; transition: background .18s, border-color .18s; }
.p-qbtn:hover { background: rgba(197,160,89,.14); border-color: var(--gold); }
.p-qbtn i { color: var(--acento-claro); }
/* En móvil el cuadro destacado baja al nivel "normal": mismo relleno que
   las demás tarjetas, y simétrico (antes era 26 arriba y 22 a los lados). */
@media (max-width: 640px) { .parte-hero { padding: var(--caja-normal); } .p-saludo { font-size: 26px; } .p-parrafo { font-size: 15px; } }

/* Chips-métrica de El Parte (absorben el Centro de Salud) */
.p-chips { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 22px; align-items: center; }
.p-chip { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; padding: 8px 14px; border-radius: var(--r-pastilla); background: rgba(255,255,255,.06); color: #e9edf3; border: 1px solid rgba(255,255,255,.12); cursor: pointer; transition: background .15s, border-color .15s, transform .15s; }
.p-chip:hover { background: rgba(255,255,255,.12); transform: translateY(-1px); }
.p-chip b { font-variant-numeric: tabular-nums; color: #f7f2e6; }
.p-chip .pc-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; }
.p-chip.venc .pc-dot { background: var(--danger); }
.p-chip.hoy .pc-dot { background: var(--warning); }
.p-chip.prox .pc-dot { background: var(--info); }
.p-chip.firma .pc-dot { background: var(--gold); }
/* «Por redactar» = mismo asunto que «por firmar» (un escrito), pero todavía
   vacío → punto HUECO. Con relleno = escrito listo esperando la firma. */
.p-chip.redac .pc-dot { background: transparent; box-shadow: inset 0 0 0 2px var(--gold); }
.p-chip.mov .pc-dot { background: var(--ink-3); }
/* «Por confirmar» llevaba EL MISMO ROJO que «vencidos», y no es lo mismo: son
   propuestas que el Vigía leyó y que todavía NO son un plazo. Mismo lenguaje
   que las tarjetas de abajo: apagado, punteado y con su bombilla, para que se
   distinga también sin mirar el color. Los tonos salen de `--sug-*`. */
.p-chip.sug { background: transparent; border-style: dashed; border-color: var(--sug-linea); color: var(--sug-texto); }
.p-chip.sug:hover { background: var(--sug-fondo); border-color: var(--sug-linea-fuerte); }
.p-chip.sug .pc-dot { background: transparent; box-shadow: inset 0 0 0 2px var(--sug-linea-fuerte); }
.p-chip.sug i { font-size: 11px; opacity: .85; }
.p-chip.saved { margin-left: auto; background: transparent; border-color: transparent; color: #aeb9c9; cursor: default; font-weight: 500; font-size: 12px; }
.p-chip.saved:hover { transform: none; background: transparent; }
.p-chip.saved i { color: var(--gold); margin-right: 2px; }
@media (max-width: 560px) { .p-chip.saved { margin-left: 0; } }

/* Estado de PRIMER DÍA (bienvenida) */
.p-bienvenida { margin-top: 26px; }
.p-cta { display: inline-flex; align-items: center; gap: 10px; background: var(--gold); color: var(--navy-900); border: 0; font-family: inherit; font-size: 14px; font-weight: 700; padding: 14px 24px; border-radius: var(--r-lg); cursor: pointer; transition: filter .15s, transform .15s; box-shadow: 0 4px 16px rgba(197,160,89,.28); }
.p-cta:hover { filter: brightness(1.06); transform: translateY(-1px); }
.p-cta i { font-size: 13px; }
/* Los tres pasos que había aquí se retiraron: repetían la guía de Puesta
   en marcha (.pm), que es ahora el único sitio donde se explica por dónde
   empezar. Se quitó también su CSS para no dejar reglas huérfanas. */

/* ---------- Agenda "Tu día" (fusión de calendario + tabla) ---------- */
.tudia-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 16px 18px 12px; flex-wrap: wrap; }
.tudia-acciones { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* Título de BLOQUE: mismo trato que los demás (19px). Estaba a 15, el
   tamaño del cuerpo, así que no se leía como título sino como una frase
   suelta — y al lado de otros bloques a 19 parecía hundido. */
/* 🪦 06-09 · `.tudia-titulo` se queda SIN ESTILO PROPIO: lo que decía (19 px,
   700, icono en accent) es exactamente `.titulo-pantalla`, que ahora lo llevan
   las cuatro pantallas. La clase sobrevive porque el JS la usa para encontrar
   el título de la agenda; el aspecto ya no vive aquí. */
.tudia-toggle { display: inline-flex; background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-md); padding: 2px; gap: 2px; flex-shrink: 0; }
.tudia-toggle button { font-family: inherit; font-size: 13px; font-weight: 600; color: var(--ink-3); background: transparent; border: 0; padding: 6px 14px; border-radius: var(--r-sm); cursor: pointer; transition: background .15s, color .15s; }
.tudia-toggle button:hover { color: var(--ink); }
.tudia-toggle button.on { background: var(--card); color: var(--ink); box-shadow: var(--shadow-1); }
.tudia-pane { padding: 0 12px 14px; }
.tudia-lista-cont { display: flex; flex-direction: column; }
/* 📅 2026-08-30 · La columna de la fecha pasa de 52 a 64 px: ahora lleva encima
   el día de la semana ESCRITO ENTERO («miércoles» es la más larga, 9 letras a
   9 px). Se ensancha en vez de abreviar a propósito — abreviar es lo que hacía
   que «MAR 1» se leyera «1 de marzo» (ver la nota en calendario.js). */
.tudia-row { display: grid; grid-template-columns: 4px 64px 1fr auto; gap: 14px; align-items: center; padding: var(--caja-compacta); border-radius: var(--r-md); cursor: pointer; transition: background .13s; }
.tudia-row:hover { background: var(--gold-soft); }
.tudia-row + .tudia-row { border-top: 1px solid var(--line); }
.tudia-row:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }
/* ============================================================
   🎨 07-09-2026 (tarde) · LA FRANJA TAMBIÉN ES MACIZA O HUECA
   ------------------------------------------------------------
   La pastilla ya seguía la regla desde esta mañana; la franja de la izquierda
   no, y era la mitad de lo que Piero seguía viendo igual. Medido en oscuro con
   los tokens crudos: audiencia 1,91:1 contra la tarjeta, próximo 1,24:1 — las
   dos casi invisibles y **a 1,22:1 entre ellas**, que es el número exacto de la
   queja original. Con `--senal-*` suben a 7,69 y 5,60.
   🔑 Y aun así, entre ellas se quedan en 1,37:1 de claridad: dos colores vivos
   del mismo peso siguen siendo la misma mancha en 4 píxeles. Por eso la franja
   copia la regla de la pastilla y la dice con el GROSOR, que es lo que el ojo
   lee antes que el tono:
       MACIZO (vencido · hoy · audiencia) → 4 px de alto a alto
       HUECO  (próximo · nota)            → 2 px, centrada en la misma columna
   Así la fila se clasifica de un vistazo sin tener que distinguir un morado de
   un azul, que es justo lo que no funcionaba. */
.tudia-stripe { width: 4px; height: 36px; border-radius: 3px; background: var(--ink-3); }
.tudia-row.r-venc .tudia-stripe { background: var(--senal-danger); }
.tudia-row.r-hoy .tudia-stripe { background: var(--senal-warning); }
.tudia-row.r-aud .tudia-stripe { background: var(--senal-audiencia); }
.tudia-row.r-prox .tudia-stripe,
.tudia-row.r-nota .tudia-stripe { width: 2px; height: 26px; margin: 0 1px; }
.tudia-row.r-prox .tudia-stripe { background: var(--senal-info); }
/* El bloque de fecha de la agenda: MES · DÍA · AÑO. Antes era día-de-la-semana
   + número, sin mes ni año, y dos audiencias con un año de diferencia salían
   idénticas en pantalla. El porqué largo está en `_filaAgenda`.
   🪤 EL HUECO DEL AÑO SE RESERVA SIEMPRE (`min-height`) aunque casi nunca se
   pinte: si sólo ocupara sitio en las filas de otro año, ESAS filas serían más
   altas que el resto y la lista daría saltos al desplazarse. Es la misma regla
   del hueco para la palabra más larga.
   🪤 Y la ALTURA es FIJA con `box-sizing: border-box`, no un `min-height`: el
   chip del año añade 2px de relleno, así que reservar sólo la altura del texto
   dejaba las filas con año 3px más altas — el salto seguía ahí, medido (71px
   contra 68). Con la altura fija el relleno cabe DENTRO y todas miden igual.
   El año usa el par `--warning-bg`/`--warning-txt` —ya medido en las seis
   paletas y en claro/oscuro— y no `--warning` crudo, que daba 3,06 de
   contraste. Va en ámbar porque es una señal de «mira esto», no un error. */
/* ============================================================
   🎨 31-08-2026 · LA PASTILLA DE FECHA (antes: cuatro renglones sueltos)
   ------------------------------------------------------------
   Lo vio Piero: *«se ve muy pesado poner martes encima de SEP»*. Eran cuatro
   textos centrados del mismo peso apilados en 64 px. Ahora es UN objeto —una
   hojita de calendario— con tres alturas de lectura bien distintas:
     franja del mes (con el año dentro cuando toca) · número grande · día.
   🔑 Que sea un objeto con borde es lo que quita el peso, más que quitar una
   línea: cuatro textos sueltos compiten entre sí; dentro de una caja, se leen
   en orden.
   🪤 LA ALTURA SIGUE SIENDO FIJA, y por lo mismo de siempre (26-08): si las
   filas con año midieran distinto, la lista daría saltos al desplazarse. Ahora
   el año va DENTRO de la franja del mes, así que no añade altura ninguna —
   antes era un renglón más con su relleno, que es de donde salía el salto.
   ============================================================ */
.tudia-fecha {
  display: flex; flex-direction: column; align-items: stretch;
  text-align: center; letter-spacing: .3px; line-height: 1.15;
  font-variant-numeric: tabular-nums; overflow: hidden;
  border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--paper);
}
/* La franja del mes: es la «cabecera» de la hojita. En mayúscula y sobre el
   tinte de acento, así que no se puede confundir con el día de la semana, que
   va en minúscula y abajo. */
.tudia-fecha .mes {
  display: block; font-style: normal; font-size: 9.5px; font-weight: 700;
  letter-spacing: .8px; text-transform: uppercase;
  color: var(--acento-txt); background: var(--gold-soft);
  padding: 2.5px 0 2px; border-bottom: 1px solid var(--line);
}
/* El año, DENTRO de la franja: «SEP 2027». Sólo sale cuando no es el año en
   curso — ver el porqué en `_filaAgenda`. */
.tudia-fecha .mes em { font-style: normal; font-weight: 700; opacity: .9; }
.tudia-fecha.otro-anio .mes { color: var(--warning-txt); background: var(--warning-bg); }
.tudia-fecha b {
  display: block; font-family: var(--font-ui); font-size: 19px; font-weight: 700;
  color: var(--ink); font-variant-numeric: tabular-nums; padding: 3px 0 0;
}
/* El día de la semana va en MINÚSCULA (`text-transform: none`) justo para que
   no se confunda con el mes, que va en mayúscula. Es la diferencia entre
   «martes» y «MAR», y por eso se escribe ENTERO (se abrevió una vez y hubo que
   deshacerlo el 30-08). */
.tudia-fecha .dow {
  display: block; font-style: normal; font-size: 9px; font-weight: 600;
  text-transform: none; letter-spacing: 0; color: var(--ink-3);
  padding: 0 2px 4px;
}
/* 🪤 01-09-2026 · EL TÍTULO SE SALÍA POR DEBAJO DE LA PASTILLA.
   Lo vio Piero en el celular: «Audiencia preliminar de esclarecimiento de
   hechos» se partía en cuatro líneas y «esclarecimient…» quedaba TAPADO por la
   pastilla morada de AUDIENCIA.
   Dos causas, las dos aquí:
   · `min-width: 0` deja que la columna se encoja, pero SIN `overflow: hidden`
     el contenido se sigue PINTANDO fuera de ella — encima de la columna de al
     lado, que es donde vive la pastilla. Encoger la caja no encoge lo de
     dentro.
   · una palabra larga («esclarecimiento») no se parte por sí sola: el navegador
     sólo corta en los espacios, así que desborda entera.
   Es pariente de la rejilla que aplastaba una columna (`1fr` es
   `minmax(auto,1fr)`): la misma familia de fallos, por el otro extremo. */
.tudia-main { min-width: 0; overflow: hidden; }
.tudia-main .tt {
  font-size: 13px; font-weight: 600; color: var(--ink); margin: 0 0 2px;
  line-height: 1.3; overflow-wrap: anywhere;
}
.tudia-main .ss { font-size: 12px; color: var(--ink-3); margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* ============================================================
   🎨 07-09-2026 · MACIZO O HUECO — y no «de qué color»
   ------------------------------------------------------------
   Lo vio Piero en su agenda: *«los colores de audiencia y próximo no se
   diferencian a simple vista, son casi idénticos»*. Y al medirlo, la causa NO
   era la que parece:

       AUDIENCIA  tono 308°  ·  claridad 33%
       PRÓXIMO    tono 211°  ·  claridad 36%
       ⇒ 97° de distancia de TONO (muchísima)
       ⇒  3 puntos de CLARIDAD, contraste entre ellos 1,22:1 (1,00 = iguales)

   🔑 En una pastilla de 60 px con texto blanco encima, **el ojo no lee tono:
   lee claridad**. Dos manchas oscuras del mismo peso son la misma mancha
   aunque una sea morada y la otra azul. Cambiar el morado por otro morado no
   habría arreglado nada — el problema es que las cinco pastillas vivían en una
   banda de claridad estrechísima (26%–43%): todas «oscuras y saturadas».

   🔑 Y LA RESPUESTA YA ESTABA EN LA CASA: `.st.prox` y `.s-prox .kc-badge` —la
   Carpeta y el tablero— pintan «Próximo» HUECO desde siempre (fondo al 12% y
   texto de color). **La agenda era la única que lo pintaba macizo.** Aquí no se
   inventa un color: se le hace seguir la regla que el resto ya sigue.

   LA REGLA, en una frase que se puede decir en voz alta:
       MACIZO = tienes que estar en un sitio a una hora, o ya se te echó encima
       HUECO  = corre solo y lo haces cuando quieras antes de la fecha

       venc · hoy · aud   → macizas   (alarma, o cita con hora)
       prox · nota        → huecas    (un plazo que corre, algo que anotaste)

   ⚠️ NINGÚN COLOR CAMBIA. El verde de las notas —que Piero dice que queda
   bien— es el mismo `--nota` de siempre; lo que cambia es el relleno.
   ✅ Medido: audiencia macizo contra próximo hueco da **7,17:1**, frente al
   1,22:1 de antes — **5,9× más separación**. Y el texto dentro de la pastilla
   hueca queda en 5,85:1 (próximo) y 5,38:1 (nota), por encima del 4,5 mínimo.
   ============================================================ */
.tudia-pill { font-size: 11px; font-weight: 700; letter-spacing: .4px; text-transform: uppercase; padding: 4px 10px; border-radius: var(--r-lg); color: #fff; white-space: nowrap; border: 1px solid transparent; }
.tudia-pill.venc { background: var(--danger); }
.tudia-pill.hoy { background: var(--warning); }
.tudia-pill.aud { background: var(--audiencia); }
/* Las huecas. El borde no es adorno: es lo único que le da forma a la pastilla,
   porque el fondo al 12% se acerca mucho a la tarjeta.
   🔴 07-09 (tarde) · Y en oscuro NO TENÍA FORMA: mezclar el token crudo —una
   tinta oscura— sobre una tarjeta oscura daba 1,08:1 de fondo y 1,29:1 de
   borde. Ahora la mezcla se hace con `--senal-*`, que en oscuro es la versión
   clara del color, y el borde sube al 55%.
   ✅ Medido — borde contra la tarjeta: 2,66:1 en oscuro (era 1,29) y 2,55:1 en
   claro (era 1,72); el texto dentro, 4,65:1 y 5,85:1, los dos por encima de
   4,5. Es la MISMA regla en los dos modos: sólo cambia de qué color se mezcla. */
.tudia-pill.prox {
  background: color-mix(in srgb, var(--senal-info) 12%, transparent);
  border-color: color-mix(in srgb, var(--senal-info) 55%, transparent);
  color: var(--info-txt);
}
/* 🎨 07-09 (noche) · Y EN OSCURO, LA LETRA DE «PRÓXIMO» EN BLANCO. Lo pidió
   Piero mirando su agenda de noche, y el número le da la razón: el azul sobre
   su propio tinte da **4,65:1** —pasa el mínimo por poco— y en blanco sube a
   **13,59:1**, casi 3× más. El color no se pierde: lo lleva el borde, que es
   quien dice que la pastilla es hueca.
   ⚠️ SÓLO en oscuro. En claro el fondo de la pastilla es casi blanco y la letra
   blanca daría 1,20:1, o sea nada.
   🔄 09-09-2026 · Y LA DE «NOTA» TAMBIÉN, PORQUE ÉL LA PIDIÓ. Aquí decía que no
   se le hacía «por no tocar lo que funciona por simetría», y con el número
   delante (6,46:1, por encima del mínimo) era una decisión defendible. Pero la
   pedía mirando su agenda de noche, que es donde se ve, y el número le vuelve a
   dar la razón: **6,46 → 12,98:1, el doble**. El color no se pierde — lo lleva
   el borde, que da 3,42:1 contra la tarjeta y es quien dice que la pastilla es
   hueca. 🔺 Un contraste que pasa el mínimo no es lo mismo que uno que se lee
   cómodo a la una de la mañana, y quien lo lee es él. */
/* 📝 La nota: verde azulado, NUNCA rojo. Ver `--nota` y `esNotaLibre`. */
.tudia-pill.nota {
  background: color-mix(in srgb, var(--senal-nota) 12%, transparent);
  border-color: color-mix(in srgb, var(--senal-nota) 55%, transparent);
  color: var(--nota-txt);
}
/* 🪤 09-09 · Y LA REGLA DE OSCURO VA DESPUÉS DE LAS DOS BASES, no en medio.
   No es orden estético: `pruebas/macizo-hueco-y-la-senal.test.js` busca el
   bloque de cada pastilla por su selector, y `.tudia-pill.nota {` es una
   subcadena de `body.dark-mode .tudia-pill.nota {`. Puesta antes, la prueba
   leía la regla de oscuro —que sólo tiene `color`— creía que la pastilla ya no
   se pintaba con `color-mix` y se ponía roja midiendo lo que no era.
   La cascada no cambia: `body.dark-mode .tudia-pill.nota` gana por
   especificidad esté donde esté. */
body.dark-mode .tudia-pill.prox,
body.dark-mode .tudia-pill.nota { color: #fff; }
.tudia-row.r-nota .tudia-stripe { background: var(--senal-nota); }
/* ⚖️ 12-09-2026 · «SIN NOTIFICAR» — el plazo que aún no corre.
   🎨 Va HUECA y de 2 px, en el mismo grupo que «Próximo» y «Nota»: la regla de
   esta lista es que el grosor dice la urgencia antes que el tono, y un plazo
   que todavía no ha empezado no puede pesar lo que uno que vence hoy. El tono
   es el `--senal-info` de lo que viene, porque eso es: algo que llegará.
   ⛔ Nunca `--danger`: su fecha no es un vencimiento. Ver `esPlazoProvisional`. */
.tudia-row.r-prov .tudia-stripe { width: 2px; height: 26px; margin: 0 1px; background: var(--senal-info); }
.tudia-pill.prov {
  background: transparent;
  border-color: color-mix(in srgb, var(--senal-info) 55%, transparent);
  color: var(--info-txt); font-style: italic;
}
body.dark-mode .tudia-pill.prov { color: #fff; }
.tudia-vacio { text-align: center; padding: 28px 20px; color: var(--ink-3); font-style: italic; font-size: 13px; }
/* Franja de vencidos: UNA línea arriba de la agenda. No usa `--danger` crudo:
   se apoya en el par `--danger-bg`/`--danger-txt`, que ya está medido en las
   seis paletas y en claro/oscuro. Ver la memoria del contraste. */
.tudia-franja { display: flex; align-items: center; justify-content: space-between; gap: 12px; width: 100%; font-family: inherit; font-size: 13px; font-weight: 600; text-align: left; background: var(--danger-bg); color: var(--danger-txt); border: 1px solid var(--danger); border-radius: var(--r-md); padding: 9px 14px; margin-bottom: 6px; cursor: pointer; transition: filter .13s; }
.tudia-franja:hover { filter: brightness(0.97); }
.tudia-franja:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.tudia-franja .tf-txt { display: inline-flex; align-items: center; gap: 8px; }
.tudia-franja .tf-txt b { font-variant-numeric: tabular-nums; }
.tudia-franja .tf-ver { font-size: 12px; font-weight: 700; text-decoration: underline; flex-shrink: 0; }
/* 📝 05-09 · LA FRANJA DE LAS NOTAS DE DÍAS PASADOS. Misma forma que la de
   vencidos y color de NOTA, nunca rojo: no hay ningún plazo que se haya dejado
   pasar y el rojo tiene que seguir queriendo decir sólo eso. Ver `esNotaLibre`
   y `pendientesAgenda` en calendario.js. */
.tudia-franja.tf-nota { background: var(--nota-bg); color: var(--nota-txt); border-color: var(--nota); }
.tudia-nota-pie { margin: 2px 0 8px; padding: 0 4px; font-size: 12px; color: var(--ink-3); display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.tudia-nota-pie .tf-ver { font-size: 12px; font-weight: 700; color: var(--nota-txt); background: none; border: none; padding: 0; text-decoration: underline; cursor: pointer; font-family: inherit; }
.tudia-venc-lista { border-left: 3px solid var(--danger); margin: 0 0 8px 2px; padding-left: 4px; }
/* 🪤 Y la GEMELA del celular, que es donde se olvida siempre (la rejilla del
   19-08 se arregló en escritorio y siguió rota aquí un día entero). 60 px y el
   día de la semana a 8,5 px: «miércoles» sigue entrando en una línea. */
@media (max-width: 480px) {
  .tudia-row { grid-template-columns: 4px 60px 1fr auto; gap: 10px; }
  .tudia-fecha .dow { font-size: 8.5px; letter-spacing: -.1px; }
  .tudia-fecha b { font-size: 18px; }
  /* 🪤 01-09 · Y LA PASTILLA, QUE ES LA QUE SE COMÍA EL SITIO.
     En 375 px, «AUDIENCIA» a 11 px con su relleno se lleva ~95 px de los ~200
     que quedan para el texto: por eso un título largo salía en cuatro líneas.
     Se aprieta un punto —sigue leyéndose— y el título recupera un tercio de
     ancho. Sin `flex-shrink` de por medio: es una columna `auto` de la rejilla,
     así que lo que manda es su contenido. */
  .tudia-pill { font-size: 10px; padding: 3px 7px; letter-spacing: .2px; }
  /* El título, hasta tres líneas. Más que eso es un párrafo dentro de una
     lista: deja de leerse y descuadra la fila entera. El texto completo sigue
     en el `title` de la fila y dentro del expediente. */
  .tudia-main .tt {
    display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical;
    overflow: hidden;
  }
}

/* ---------- Aviso anticipado (Socio IA) ---------- */
.aviso-ia {
  margin: 16px 0 4px; padding: 18px 22px;
  background: linear-gradient(135deg, var(--navy-900), var(--navy-800));
  border: 1px solid rgba(197, 160, 89, 0.35);
  border-radius: var(--r-lg); color: #eef2f7;
  box-shadow: var(--shadow-2);
}
.aviso-head { display: flex; align-items: center; gap: 10px; margin-bottom: 8px; }
.aviso-estrella { color: var(--acento-claro); font-size: 17px; }
.aviso-ia h5 { font-size: 13px; letter-spacing: 1.2px; text-transform: uppercase; color: var(--acento-claro); font-weight: 700; }
.aviso-badge {
  margin-left: auto; background: var(--danger); color: #fff;
  font-size: 11px; font-weight: 800; letter-spacing: 0.8px;
  padding: 4px 12px; border-radius: var(--r-lg);
  animation: pulse-badge 2.4s infinite;
}
@keyframes pulse-badge { 0%,100% { opacity: 1; } 50% { opacity: 0.6; } }
.aviso-linea { font-size: 15px; }
.aviso-linea strong { color: var(--acento-claro); }
.aviso-detalle { font-size: 13px; color: rgba(238,242,247,0.75); margin-top: 6px; }
.aviso-acciones { display: flex; gap: 10px; margin-top: 16px; flex-wrap: wrap; }
.btn-aviso-sec { width: auto; padding: 10px 16px; font-size: 13px; background: transparent; color: var(--acento-claro); border: 1px solid var(--acento-claro); box-shadow: none; }
.btn-aviso-sec:hover { background: var(--gold-soft); }

/* Centro de Salud del estudio (fusiona los antiguos KPIs) */
/* Banda hero: el tiempo ahorrado (norte del producto) */
/* NÚMEROS: siempre en la letra de interfaz, nunca en la de títulos. Una
   serif de display no alinea cifras aunque se le pida; ese error ya obligó
   a deshacer el cambio en el panel de operaciones. Aquí no se repite. */
/* Fila de stats con divisores finos (sin cajas) */
/* Pie: carga por abogado con badge-contador */
.abg { display: inline-flex; align-items: center; gap: 6px; color: var(--ink); font-weight: 600; }
.abg-badge { display: inline-flex; align-items: center; justify-content: center; min-width: 19px; height: 19px; padding: 0 6px; border-radius: var(--r-pastilla); background: var(--paper); border: 1px solid var(--line-strong); font-size: 11px; font-weight: 700; color: var(--ink-2); font-variant-numeric: tabular-nums; }
.skeleton-box { position: relative; overflow: hidden; }
.skeleton-box::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.5), transparent);
  animation: shimmer 1.4s infinite;
}
@keyframes shimmer { from { transform: translateX(-100%); } to { transform: translateX(100%); } }

/* ---------- Layout de paneles ---------- */
.layout-panel { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; align-items: start; }
/* Panel Principal: UNA sola columna a ancho completo (calendario, resumen,
   pendientes y — al final — distribución por etapa). */
.layout-panel-resumen { grid-template-columns: 1fr; gap: 22px; }
/* min-width:0 en TODOS los hijos del grid: sin esto, un hijo con contenido
   ancho (calendario, tabla) infla la columna y desborda en móvil. */
.layout-panel > *, .layout-panel-resumen > *, .analisis-grid > * { min-width: 0; }
.col-derecha { display: flex; flex-direction: column; gap: 22px; min-width: 0; }
/* Carpeta de Expedientes: barra compacta "Añadir documento" + lista a ancho completo */
.doc-add-bar { margin-bottom: 18px; border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--card); box-shadow: var(--shadow-1); overflow: hidden; }
.doc-add-bar > summary { list-style: none; cursor: pointer; padding: 14px 18px; font-size: 13px; font-weight: 700; color: var(--accent-ink); display: flex; align-items: center; gap: 10px; user-select: none; }
.doc-add-bar > summary::-webkit-details-marker { display: none; }
.doc-add-bar > summary::after { content: "\f078"; font-family: "Font Awesome 6 Free"; font-weight: 900; margin-left: auto; font-size: 11px; color: var(--ink-3); transition: transform var(--speed); }
.doc-add-bar[open] > summary::after { transform: rotate(180deg); }
.doc-add-bar[open] > summary { border-bottom: 1px solid var(--line); }
.doc-add-form { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 12px 16px; align-items: end; padding: 16px 18px; }
.doc-add-form .form-group { margin: 0; }
.doc-add-form .doc-add-btn { width: auto; height: fit-content; white-space: nowrap; }
/* Lista de documentos: categorías repartidas a lo ancho (más aire, no apretadas) */
#contenedor-categories-archivos { padding-right: 4px; }
.doc-cats-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); gap: 14px 18px; align-items: start; margin-bottom: 8px; }
/* Distribución por etapa a lo ancho (barras en varias columnas) */
.da-etapas-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 6px 28px; }
/* Análisis de Resoluciones: las dos herramientas lado a lado a ancho completo */
.analisis-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; align-items: start; }
.analisis-grid .analisis-col { grid-template-columns: 1fr; }

/* Panel derecho del dashboard (llena el hueco de la Mesa de Partes) */
.dashboard-aside { display: flex; flex-direction: column; gap: 20px; }
.da-card { padding: 18px; }
.da-card .card-title { padding-bottom: 12px; margin-bottom: 12px; }
.da-list { display: flex; flex-direction: column; gap: 8px; }
.da-item { display: flex; align-items: center; gap: 12px; padding: 10px 10px; border: 1px solid var(--line); border-radius: var(--r-sm); cursor: pointer; transition: border-color var(--speed), background var(--speed); }
.da-item:hover { border-color: var(--gold); background: var(--gold-soft); }
.da-ic { width: 30px; height: 30px; flex-shrink: 0; border-radius: var(--r-md); display: flex; align-items: center; justify-content: center; font-size: 13px; color: #fff; }
.da-ic.aud { background: var(--audiencia); } .da-ic.tar { background: var(--gold-strong); }
.da-tx { min-width: 0; display: flex; flex-direction: column; }
.da-tx b { font-size: 13px; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.da-tx span { font-size: 11px; color: var(--ink-3); }
.da-vacio { font-size: 13px; color: var(--ink-3); font-style: italic; padding: 6px 2px; }
.da-bar-row { display: grid; grid-template-columns: 1fr 78px auto; align-items: center; gap: 10px; margin-bottom: 10px; }
.da-bar-lbl { font-size: 12px; color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.da-bar-track { height: 8px; background: var(--paper); border-radius: 5px; overflow: hidden; border: 1px solid var(--line); }
.da-bar-fill { display: block; height: 100%; background: linear-gradient(90deg, var(--gold), var(--gold-strong)); border-radius: 5px; }
.da-bar-n { font-size: 12px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.da-vigia { font-size: 13px; line-height: 1.55; color: var(--ink-2); background: var(--gold-soft); border: 1px solid var(--gold); border-radius: var(--r-sm); padding: 12px; cursor: pointer; }
.da-vigia b { color: var(--acento-txt); }
.da-vigia span { display: block; margin-top: 6px; font-size: 12px; font-weight: 700; color: var(--acento-txt); }
.da-vigia.off { background: var(--paper); border-color: var(--line); color: var(--ink-3); cursor: default; }
.da-vigia i { color: var(--acento-txt); margin-right: 4px; }

/* ---------- Calendario ---------- */
.cal-header-main { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.cal-header-main h2 {
  /* La letra de INTERFAZ, no la de títulos: aquí hay un AÑO. La de títulos
     no alinea cifras, así que "Julio 2026" se veía irregular y, al pasar de
     un mes a otro, los números cambiaban de sitio. Con la de interfaz todas
     las cifras miden lo mismo y el título se queda quieto. */
  font-family: var(--font-ui); font-size: 19px; font-weight: 700;
  color: var(--ink); text-transform: capitalize;
  font-variant-numeric: tabular-nums; letter-spacing: -.01em;
}
.btn-nav-cal {
  width: 36px; height: 36px; border-radius: 50%;
  border: 1px solid var(--line-strong); background: var(--card);
  color: var(--ink-2); font-size: 13px;
  transition: background var(--speed), color var(--speed), border-color var(--speed);
}
.btn-nav-cal:hover { background: var(--navy-900); color: var(--gold); border-color: var(--navy-900); }
/* ============================================================
   📅 31-08-2026 · EL CALENDARIO EN EL CELULAR
   ------------------------------------------------------------
   Lo trajo Piero con la captura del teléfono: *«el calendario en Agenda se ve
   muy apretado en celular… que salgan más anchos los cuadros y se pueda
   deslizar a la derecha sin que se rompa el calendario saliendo de los
   márgenes»*.
   Y la captura no engañaba: siete columnas a `1fr` dentro de 375 px dan
   casillas de 44 px de ancho por 92 de alto — columnas verticales donde no
   cabe ni el número del día con una etiqueta debajo.
   🔑 LA SOLUCIÓN: en el celular la rejilla deja de encogerse (`min-width`) y
   el CONTENEDOR se desliza. Los nombres de los días y las casillas viven en la
   MISMA rejilla, así que se deslizan juntos: no hay forma de que la cabecera
   se desalinee de su columna, que es como se rompen estos calendarios.
   ⚠️ `overflow: hidden` era justo lo que impedía deslizar. Se cambia por
   `overflow-x: auto` con `overscroll-behavior-x: contain`, para que llegar al
   final del calendario NO arrastre la página entera hacia atrás.
   🪤 Y el desbordamiento se queda DENTRO de la tarjeta: es el contenedor el
   que se desliza, no el `body`. Por eso `max-width: 100%` — sin él, la rejilla
   ancha empuja la tarjeta y el que se sale de los márgenes es el sitio entero,
   que es exactamente lo que él pedía evitar (y la trampa del `100vw`).
   ============================================================ */
.calendar-scroll-wrapper { overflow: hidden; max-width: 100%; }
.cal-grid-main { display: grid; grid-template-columns: repeat(7, 1fr); gap: 6px; }
.cal-day-name-main {
  text-align: center; font-size: 11px; font-weight: 700;
  letter-spacing: 1px; color: var(--accent-ink); padding: 8px 0 6px;
  position: sticky; top: 0; z-index: 1; background: var(--card);
}
.cal-day-cell {
  min-height: 92px; padding: 8px;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-sm);
  transition: border-color var(--speed), box-shadow var(--speed);
  overflow: hidden;
}
/* Al abrir el Socio, el panel se comprime en UNA columna ordenada (no desordenado) */
body.socio-abierto .layout-panel-resumen,
body.socio-abierto .layout-panel,
body.socio-abierto .analisis-grid { grid-template-columns: 1fr; }
.cal-day-cell:hover { border-color: var(--gold); }
.cal-day-cell.today { border: 2px solid var(--gold); background: var(--gold-soft); }
.cal-day-cell.today .day-number { color: var(--acento-txt); }
.day-number { font-size: 12px; font-weight: 700; color: var(--ink-2); margin-bottom: 4px; font-variant-numeric: tabular-nums; }
.event-tag {
  display: block; font-size: 11px; font-weight: 600; color: #fff;
  padding: 4px 8px; border-radius: 5px; margin-bottom: 4px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  cursor: pointer; transition: filter 120ms;
}
.event-tag:hover { filter: brightness(1.2); }
/* Sugerido por el Vigía y SIN confirmar: fantasma punteado. Debe leerse a
   simple vista que todavía no es un plazo agendado, solo una propuesta. */
.event-tag.sug {
  background: transparent; color: var(--acento-txt);
  border: 1px dashed var(--gold); font-style: italic;
}
/* ⚖️ 12-09-2026 · EL PLAZO QUE AÚN NO CORRE (aceptado desde un aviso del CEJ,
   sin cédula del SINOE todavía). Se ve como el sugerido —hueco y punteado, que
   es como se pinta lo que está a medias en este calendario— pero en el AZUL de
   lo que viene, no en el dorado de «falta que lo confirmes»: esto ya está
   aceptado, lo que falta no es tu decisión sino la notificación del juzgado.
   ⛔ NUNCA rojo ni ámbar: su fecha no es un vencimiento. Ver `esPlazoProvisional`. */
.event-tag.prov {
  background: color-mix(in srgb, var(--senal-info) 10%, transparent);
  color: var(--info-txt);
  border: 1px dashed color-mix(in srgb, var(--senal-info) 60%, transparent);
}

/* 📅 El calendario en pantalla estrecha: casillas ANCHAS y se desliza.
   Ver el porqué largo en `.calendar-scroll-wrapper`. 76 px de ancho es lo
   medido para que quepa «12» y una etiqueta corta debajo sin cortarla; a
   `1fr` salían 44 px y por eso se veía como una reja.
   🔑 El deslizamiento se anuncia con `scroll-snap` por columnas: al soltar,
   la semana queda encajada y no a medio día, que es lo que hace que estos
   calendarios parezcan rotos.
   ⚠️ Se aplica a 640 px y no a 480: entre esas dos medidas (tabletas de pie,
   ventanas a media pantalla) el problema es el mismo y hasta hoy no lo cubría
   nadie. */
@media (max-width: 640px) {
  .calendar-scroll-wrapper {
    overflow-x: auto; overflow-y: hidden;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity;
    /* Sitio para la barra de deslizar, para que no tape la última fila. */
    padding-bottom: 6px;
  }
  .cal-grid-main {
    grid-template-columns: repeat(7, 76px);
    min-width: max-content; gap: 5px;
  }
  .cal-day-cell, .cal-day-name-main { scroll-snap-align: start; }
  .cal-day-cell { min-height: 78px; padding: 6px; }
  .day-number { font-size: 13px; }
  .event-tag { font-size: 10.5px; padding: 3px 6px; margin-bottom: 3px; }
  /* La pista de que hay más a la derecha: una sombra en el borde que se va
     sola al llegar al final. Sin ella, el sábado y el domingo son invisibles
     y nadie desliza lo que no sabe que existe. */
  .calendar-scroll-wrapper {
    background:
      linear-gradient(to right, var(--card) 30%, rgba(0,0,0,0)) left center / 24px 100% no-repeat,
      linear-gradient(to left, var(--card) 30%, rgba(0,0,0,0)) right center / 24px 100% no-repeat,
      radial-gradient(farthest-side at 0 50%, rgba(0,0,0,.16), transparent) left center / 12px 100% no-repeat,
      radial-gradient(farthest-side at 100% 50%, rgba(0,0,0,.16), transparent) right center / 12px 100% no-repeat;
    background-attachment: local, local, scroll, scroll;
  }
}

/* ---------- Tablas ---------- */
table { width: 100%; border-collapse: collapse; font-size: 13px; }
thead th {
  text-align: left; font-size: 11px; font-weight: 700;
  letter-spacing: 0.8px; text-transform: uppercase; color: var(--ink-3);
  padding: 12px 16px; border-bottom: 2px solid var(--line);
  background: var(--paper);
}
tbody td { padding: 12px 16px; border-bottom: 1px solid var(--line); color: var(--ink-2); vertical-align: middle; }
tbody tr { transition: background 120ms; }
tbody tr:hover { background: var(--gold-soft); }
.summary-tasks-box { margin-top: 20px; }
.summary-tasks-box .card-body { overflow-x: auto; }
.badge { display: inline-block; font-size: 11px; font-weight: 700; padding: 4px 10px; border-radius: var(--r-lg); }
.badge-rojo { background: var(--danger-bg); color: var(--danger-txt); }
/* Insignias de estado en tablas — mismo estilo, texto blanco legible */
.tag-estado {
  display: inline-block; font-size: 11px; font-weight: 700;
  letter-spacing: 0.4px; text-transform: uppercase;
  padding: 4px 10px; border-radius: var(--r-lg); color: #fff; white-space: nowrap;
}
.tag-estado.te-vencido { background: var(--danger); }
.tag-estado.te-hoy { background: var(--warning); color: #fff; }
.tag-estado.te-prox { background: var(--info); }

.alerta-dinamica-card { margin-top: 20px; }
@keyframes pulse-alert {
  0%, 100% { box-shadow: var(--shadow-1); }
  50% { box-shadow: 0 0 0 4px rgba(179, 54, 42, 0.15); }
}

/* ---------- Formularios ---------- */
.form-group { margin-bottom: 16px; }
.form-group label,
/* Mismo aspecto, distinto significado. Una etiqueta <label> promete que
   debajo hay algo que RELLENAR: el lector de pantalla la anuncia como el
   nombre de un campo, y al pulsarla el cursor salta a él. Cuando lo que hay
   debajo es un dato que sólo se lee (el vencimiento, la hora, el historial),
   esa promesa es falsa: se anuncia un campo que no existe.
   Para esos casos va `.rotulo-dato`, que se ve exactamente igual pero no
   miente sobre lo que hay debajo. */
.rotulo-dato {
  display: block; font-size: 12px; font-weight: 600;
  letter-spacing: 0.4px; color: var(--ink-2); margin-bottom: 6px;
}
/* 🔴 07-09-2026 · Y LA MISMA REGLA PARA TODO `<label>`, ESTÉ DONDE ESTÉ.
   Ayer se les quitó a doce rótulos el tamaño que llevaban escrito en el HTML
   para que mandara la hoja… y **la hoja sólo hablaba de los que están dentro de
   `.form-group`**. Los diecisiete que viven fuera se quedaron sin ninguna regla
   y cayeron a los 16 px por defecto del navegador. Lo vio Piero en «No cerrar
   mi sesión por inactividad», que salió con la letra enorme.
   🔺 *Quitar un estilo suelto sólo es una mejora si LA HOJA cubre ese caso.*
   Comprobar «¿queda alguno sin regla?» era parte del cambio, y no se hizo.
   ⚠️ Se pone con la misma fuerza que `.form-group label`, así que quien tenga
   una clase propia (`.casilla-linea`, abajo) la sigue ganando. */
label { font-size: 12px; }
/* La casilla con una FRASE al lado no es un rótulo de campo: es algo que se
   lee. Va al tamaño del texto secundario y sin la negrita de los rótulos. */
.casilla-linea {
  display: flex; align-items: flex-start; gap: 10px; cursor: pointer;
  font-size: 13px; font-weight: 400; letter-spacing: 0; line-height: 1.5;
  color: var(--ink);
}
.casilla-linea input[type="checkbox"] { width: 16px; height: 16px; cursor: pointer; flex: none; margin-top: 1px; }
/* 🔴 15-09 (noche) · LOS REDONDOS TAMBIÉN. La regla general de `input` les da
   ancho completo, relleno de 10×12 y borde de campo de texto; el cuadro de la
   audiencia REPROGRAMADA salía con los círculos deformados y la frase pegada
   (lo vio Piero: «sale muy pegado el cuadro»). Mismo arreglo que ya tenían
   `.arn-op` y `.pp-op`, pero en la clase común. */
.casilla-linea input[type="radio"] { width: 16px; height: 16px; min-width: 16px; padding: 0; margin: 2px 0 0; border: 0; border-radius: 50%; box-shadow: none; cursor: pointer; flex: none; accent-color: var(--acento-txt); }

/* ⚖️ 15-09 (noche) · Plazo sugerido: los cuadros que se leen ANTES de decidir.
   El de la audiencia reprogramada lleva aire arriba y abajo: iba pegado al
   aviso del CEJ y a la rejilla de campos. */
.sug-reprog { border-radius: var(--r-sm); padding: 14px 16px; margin: 14px 0; }
.sug-reprog-ops { display: flex; flex-direction: column; gap: 10px; margin-top: 12px; }
.sug-caja { border-radius: var(--r-sm); padding: 12px 14px; margin-bottom: 14px; border: 1px solid var(--line); background: var(--bg-2); }
.sug-caja-aviso { border-color: var(--warning-txt); background: var(--warning-bg); }
.sug-caja-otra { border-color: var(--line-strong); background: var(--bg-2); }
.sug-caja-t { font-size: 13px; font-weight: 800; color: var(--ink); margin-bottom: 6px; }
.sug-caja-aviso .sug-caja-t { color: var(--warning-txt); }
.sug-caja-d { font-size: 13px; color: var(--ink-2); line-height: 1.55; }
.sug-partes { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.sug-parte-btn { display: inline-flex; flex-direction: column; align-items: flex-start; gap: 1px; max-width: 100%; padding: 8px 12px; border: 1px solid var(--line-strong); border-radius: var(--r-sm); background: var(--card); color: var(--ink); text-align: left; font-size: 13px; line-height: 1.3; }
.sug-parte-btn span { font-size: 11px; color: var(--ink-3); text-transform: uppercase; letter-spacing: .4px; }
.sug-parte-btn:hover, .sug-parte-btn:focus-visible { border-color: var(--gold); background: var(--gold-soft); }
.sug-nota-oculto { font-size: 12px; color: var(--ink-3); margin: -4px 0 14px; line-height: 1.5; }
.grid-2 { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 14px; }
.grid-3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 14px; }
/* ============================================================
   📐 09-09-2026 · LA FILA DE DOS CAMPOS SE PEGABA AL RÓTULO DE ABAJO
   ------------------------------------------------------------
   Lo vio Piero en «Nueva nota»: entre la fila de Fecha/Hora y el rótulo
   «¿Qué tienes que hacer?» no hay NADA de aire, mientras que entre los demás
   campos hay 16 px. No es un despiste de ese formulario: es una regla que
   faltaba, y por eso se repetía sola en cada sitio nuevo.

   🔑 LA CAUSA, en dos líneas. `.form-group` lleva `margin-bottom: 16px`, que es
   lo que separa un campo del siguiente. Cuando dos campos van en una fila, a
   los `.form-group` de dentro se les pone `style="margin:0"` —si no, la rejilla
   quedaría descuadrada por dentro— y **entonces la fila entera se queda sin
   margen inferior**: el rótulo de abajo se pega al borde del campo de arriba.
   Medido en `app.html`: pasaba en **9 filas** repartidas por cuatro modales.

   🔺 Y por eso NO se arregla poniendo `margin-bottom` a mano en la fila que él
   señaló: eso deja las otras ocho igual y la décima vuelve a nacer rota. La
   regla va en la hoja, dicha una vez y en el sitio donde se decide: *una fila
   de campos separa por debajo lo mismo que un campo suelto*.
   ⚠️ `:has()` no es adorno aquí: es lo que distingue una fila de FORMULARIO
   —la que hay que separar— de una rejilla de maquetación cualquiera, que no.
   Un navegador que no lo entendiera se queda exactamente como está hoy.
   ============================================================ */
.grid-2:has(> .form-group),
.grid-3:has(> .form-group) { margin-bottom: 16px; }
/* ============================================================
   📝 06-09-2026 · LA NOTA QUE EXPLICA EL CAMPO DE ARRIBA
   ------------------------------------------------------------
   Censadas en `app.html`: **59 notas de ayuda escritas en línea, con CINCO
   tamaños distintos** (11 · 11,5 · 12 · 12,5 · 13) y doce combinaciones de
   tamaño y color. Cuarenta y tres de ellas son literalmente lo mismo —la
   línea gris que explica el campo de encima— y se veían de tres tamaños
   según la pantalla en la que cayeras. Eso es lo que Piero llama «se ve todo
   informal»: no es una nota fea, son tres notas que deberían ser una.

   🔑 12 px es el paso de la escala para «metadato, pie» y además el
   mayoritario (22 de 43), así que unificar aquí es lo que menos mueve la app.
   ⛔ Las notas con color SEMÁNTICO (aviso, peligro, acento) NO entran: ahí el
   color dice algo, y pintarlas de gris borraría el aviso.
   ============================================================ */
.nota-ayuda {
  font-size: 12px; line-height: 1.55; color: var(--ink-3);
}
.section-label {
  font-size: 12px; color: var(--acento-txt); margin: 0 0 16px;
  font-weight: 700; text-transform: uppercase; letter-spacing: 1px;
}
.autocomplete-container { position: relative; }
#suggestions-list {
  display: none; position: absolute; top: 100%; left: 0; right: 0; z-index: 250;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-sm); box-shadow: var(--shadow-2);
  max-height: 230px; overflow-y: auto;
}
.chip-container {
  display: flex; flex-wrap: wrap; gap: 6px; align-items: center;
  min-height: 44px; padding: 8px 10px; cursor: text;
  background: var(--card); border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  transition: border-color var(--speed), box-shadow var(--speed);
}
.chip-container:focus-within { border-color: var(--gold); box-shadow: 0 0 0 3px var(--gold-soft); }
.chip {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--navy-900); color: #f0e6cf;
  font-size: 12px; font-weight: 600;
  padding: 6px 10px; border-radius: var(--r-lg);
}
.chip i { cursor: pointer; font-size: 11px; color: var(--gold); }
.chip i:hover { color: #fff; }
.chip-input { border: none !important; box-shadow: none !important; flex: 1; min-width: 90px; padding: 4px; background: transparent; }
.dropzone {
  border: 2px dashed var(--line-strong); border-radius: var(--r-md);
  background: var(--paper); padding: 22px; text-align: center;
  color: var(--ink-2); cursor: pointer;
  transition: border-color var(--speed), background var(--speed);
}
.dropzone:hover, .dropzone.drag-over { border-color: var(--gold); background: var(--gold-soft); }
.dropzone i { font-size: 19px; color: var(--gold); }

/* ===== ANÁLISIS Y TRANSCRIPCIÓN IA v2 (Sección 4) ===== */
.analisis-card { padding: 22px; }
/* 2026-08-13 · Se fueron las 4 reglas de `.an-seg`/`.an-seg-btn` con el selector
   de Análisis/Transcripción. Al retirar la transcripción quedaron sin un solo
   elemento que las llevara: CSS muerto que el día de mañana se copia como si
   significara algo. Ver la cascada en public/js/app.js. */
.analisis-card .an-grid-analisis { display: grid; grid-template-columns: 0.82fr 1.18fr; gap: 22px; align-items: start; }
.an-col-entrada .an-hint { font-size: 12px; color: var(--ink-3); margin: 8px 0 0; text-align: center; line-height: 1.5; }
.an-resbox { background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 16px; font-size: 13px; line-height: 1.65; min-height: 240px; max-height: 460px; overflow-y: auto; color: var(--ink); }
.an-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; min-height: 200px; color: var(--ink-3); }
.an-empty i { font-size: 26px; color: var(--gold); opacity: .55; margin-bottom: 12px; }
.an-empty-t { font-family: var(--font-ui); font-weight: 700; font-size: 13px; color: var(--ink-2); margin: 0 0 6px; }
.an-empty-d { font-size: 12px; line-height: 1.6; max-width: 34ch; margin: 0; }
.an-acciones { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); }
.an-acciones .btn-inline { width: auto; margin: 0; }
/* ============================================================
   EL BOTÓN SECUNDARIO — 03-09-2026
   ------------------------------------------------------------
   🪤 De dónde sale. Piero, sobre «Desconectar» y «Volver a conectar»:
   *«arréglalos estéticamente»*. Salían con el botón GRIS de fábrica del
   navegador y el icono pegado al texto, porque llevaban `btn-inline` a secas —
   y `btn-inline` es un MODIFICADOR (`display:inline-flex`), no un botón.
   🔑 Y ya había DOS copias de este mismo botón secundario, `.an-btn-ghost` (el
   análisis) y `.ed-btn-ghost` (el Redactor), idénticas salvo el color del
   borde. En vez de escribir una tercera se unifican: `.btn-ghost` es el nombre
   bueno y los dos viejos son alias, así que las pantallas que ya los usan no se
   tocan y a partir de aquí hay UN solo botón secundario.
   ============================================================ */
.btn-ghost, .an-btn-ghost, .ed-btn-ghost {
  background: transparent; color: var(--ink-2);
  border: 1px solid var(--line-strong, var(--line)); box-shadow: none;
}
.btn-ghost:hover, .an-btn-ghost:hover, .ed-btn-ghost:hover { border-color: var(--gold); color: var(--acento-txt); }
/* El destructivo: rojo SÓLO en la letra, no en el fondo. Un botón rojo entero
   pide que lo pulses; éste tiene que pedir lo contrario. El fondo rojo se
   reserva para la confirmación, que es donde la decisión ya está tomada. */
.btn-ghost-peligro { color: var(--danger-txt); }
.btn-ghost-peligro:hover { border-color: var(--danger); color: var(--danger-txt); background: var(--danger-bg); }
/* El aviso de vigencia normativa llevaba `--vino` (#7b1e3a) fijo, y en modo
   oscuro se quedaba en 1,72:1 — invisible. Y es justo el aviso que dice
   «verifique que esto siga vigente antes de usarlo en un escrito»: si no se
   lee, no avisa. Ahora usa la variante de texto, que sí cambia con el modo.
   🔴 Y el 2026-08-08 pasó de vino a ÁMBAR (lo decidió Piero). Motivo medido: el
   vino está en el tono 342°, o sea a 3° del acento de la paleta burdeos y a 23°
   del rojo de «vencido». Esto es una ADVERTENCIA, y una advertencia tiene que
   parecerse a las demás advertencias de la app, no a un error ni a la marca del
   estudio. Ver la memoria del color de audiencias. */
/* El fondo pasa del `color-mix` del propio texto al `--warning-bg` del sistema:
   el tinte hecho con el color de la letra le comía el contraste (4,25 en claro),
   y además éste ya es el fondo que llevan todas las demás advertencias. */
.an-vigencia { display: flex; align-items: flex-start; gap: 8px; font-size: 12px; line-height: 1.5; color: var(--warning-txt); background: var(--warning-bg); border-radius: var(--r-sm); padding: 10px 12px; margin-top: 14px; }
.an-vigencia i { margin-top: 1px; }
@media (max-width: 900px) { .analisis-card .an-grid-analisis { grid-template-columns: 1fr; } }
.asistente-ia-box {
  border: 1px dashed var(--gold); padding: 16px; border-radius: var(--r-md);
  background: var(--gold-soft); margin-bottom: 20px;
}
.form-divider { margin: 22px 0; border: 0; border-top: 1px dashed var(--line-strong); }
.form-actions-right { text-align: right; margin-top: 10px; }
.btn-inline { display: inline-flex; width: auto; }
.btn-calc-trigger {
  background: transparent; border: 1px solid var(--gold); color: var(--accent-ink);
  font-size: 12px; font-weight: 700; padding: 8px 14px; border-radius: var(--r-sm);
  transition: background var(--speed);
}
.btn-calc-trigger:hover { background: var(--gold-soft); }
.calculador-desplegable {
  display: none; background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 16px; margin-bottom: 18px;
}
#calc-resultado {
  font-size: 13px; font-weight: 700; color: var(--danger-txt); text-align: center;
  padding: 12px; background: var(--danger-bg); border-radius: var(--r-sm);
  margin: 10px 0 0; border: 1px dashed var(--danger); display: none;
}
#draft-saved-indicator {
  font-size: 11px; color: var(--success-txt); margin-right: 8px;
  display: none; align-items: center; gap: 4px; font-weight: 600;
}
#panel-audiencia-extra {
  display: none; background: var(--paper); padding: 16px;
  border-radius: var(--r-sm); border: 1px solid var(--line); margin-bottom: 16px;
}

/* ============================================================
   CARPETA DE EXPEDIENTES
   ============================================================ */
.carpeta-entrada {
  display: flex; gap: 12px; align-items: center; flex-wrap: wrap;
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 14px 18px; margin-bottom: 20px;
  box-shadow: var(--shadow-1);
}
.carpeta-entrada .hint { font-size: 12px; color: var(--ink-3); margin-left: auto; }
.carpeta-selector-bar {
  display: flex; align-items: center; gap: 12px;
  background: var(--navy-900); border-radius: var(--r-lg);
  padding: 14px 20px; margin-bottom: 18px;
  border: 1px solid rgba(197, 160, 89, 0.3);
}
.carpeta-selector-bar label { color: #eef2f7; font-size: 13px; font-weight: 600; margin: 0; white-space: nowrap; }
.carpeta-selector-bar i { color: var(--gold); font-size: 17px; }
.carpeta-selector-bar select {
  max-width: 480px; background: var(--navy-950); color: #eef2f7;
  border-color: rgba(197, 160, 89, 0.35);
}
.ficha-head-carpeta {
  display: none; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 1px; background: var(--line); border: 1px solid var(--line);
  border-radius: var(--r-md); overflow: hidden; margin-bottom: 18px;
}
.ficha-head-carpeta .it { background: var(--card); padding: 12px 16px; }
.ficha-head-carpeta .l {
  display: block; font-size: 11px; font-weight: 700;
  letter-spacing: 0.8px; text-transform: uppercase; color: var(--ink-3);
}
.ficha-head-carpeta .v { font-size: 13px; font-weight: 600; color: var(--ink); }
.subtabs-carpeta { display: flex; gap: 6px; margin-bottom: 16px; border-bottom: 2px solid var(--line); }
.subtab-carpeta {
  padding: var(--caja-compacta); font-size: 13px; font-weight: 600; color: var(--ink-3);
  cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -2px;
  transition: color var(--speed), border-color var(--speed);
}
.subtab-carpeta:hover { color: var(--ink); }
.subtab-carpeta.active { color: var(--accent-ink); border-bottom-color: var(--gold); }
.subtab-carpeta i { margin-right: 6px; }
.subpane-carpeta { display: none; }
.subpane-carpeta.active { display: block; animation: fadeUp 280ms var(--ease); }
.cuaderno-tit {
  font-family: var(--font-ui); font-size: 12px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em;
  color: var(--ink-2); margin: 16px 2px 12px; display: flex; align-items: center; gap: 8px;
}
.cuaderno-tit i { color: var(--gold); }
.doc-row:hover { border-color: var(--gold) !important; }

/* ---- Línea de tiempo del expediente ---- */
.tl { position: relative; padding: 4px 0 4px 6px; }
.tl::before { content: ""; position: absolute; left: 20px; top: 10px; bottom: 10px; width: 2px; background: var(--line-strong); }
.tl-item { position: relative; display: flex; gap: 16px; padding: 8px 0; cursor: pointer; }
.tl-dot { position: relative; z-index: 1; width: 30px; height: 30px; flex-shrink: 0; border-radius: 50%; display: flex; align-items: center; justify-content: center; color: #fff; font-size: 13px; box-shadow: 0 0 0 4px var(--card); }
/* 🔑 `min-width: 0` NO ES ADORNO. Un ítem flex no baja por defecto del ancho
   mínimo de su contenido, así que una sola pastilla ancha dentro empujaba la
   tarjeta entera fuera de la pantalla (medido: 416 px en un marco de 359).
   Es la misma pieza que le faltaba al visor de PDF el 06-09, en el otro eje. */
.tl-body { flex: 1; min-width: 0; background: var(--card); border: 1px solid var(--line); border-radius: var(--r-md); padding: 12px 14px; transition: border-color .16s var(--ease), transform .16s var(--ease), background .16s var(--ease); }
.tl-item:hover .tl-body { border-color: var(--gold); transform: translateX(2px); }
.tl-date { font-size: 11px; font-weight: 700; letter-spacing: .3px; color: var(--acento-txt); font-variant-numeric: tabular-nums; }
.tl-title { font-size: 13px; font-weight: 600; color: var(--ink); margin: 2px 0 4px; }
.tl-meta { font-size: 12px; color: var(--ink-3); }
/* 📄 28-08 · El motivo por el que un documento del CEJ no trae papel, en
   palabras del propio portal. Discreto a propósito: es una nota, no una
   alarma — que el Poder Judicial no publique los escritos no es un fallo. */
.tl-sinpapel {
  margin-top: 4px; font-size: 12px; color: var(--ink-3);
  display: flex; align-items: flex-start; gap: 6px; line-height: 1.4;
}
.tl-sinpapel i { margin-top: 2px; opacity: .7; flex: 0 0 auto; }
/* Cuando además hay algo que HACER (bajarlo del portal a mano), se destaca un
   poco: no es sólo una nota, es una acción pendiente del abogado. */
.tl-sinpapel-acc { color: var(--ink-2); }
.tl-sinpapel-acc i { color: #b3862a; opacity: 1; }
.tl-sinpapel-acc a { color: var(--oro, #8a6d1f); font-weight: 700; text-decoration: underline; }
.tl-sinpapel-acc a:hover { text-decoration: none; }
.tl-rebajar {
  margin-left: auto; flex: 0 0 auto; align-self: center;
  background: var(--tinta, #0d1b2a); color: #fff; border: 0; border-radius: 6px;
  padding: 6px 12px; font: 700 12px system-ui, sans-serif; cursor: pointer;
}
.tl-rebajar:hover { opacity: .88; }
/* 🆕 15-09 · Dos salidas en la misma fila («Traerlo ahora» del CEJ y «Traerla
   del SINOE»): van juntas a la derecha y bajan de línea si no caben. */
.tl-botones { margin-left: auto; flex: 0 0 auto; align-self: center; display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
.tl-botones .tl-rebajar { margin-left: 0; }
.tl-botones:empty { display: none; }

/* ---- Importador CEJ ---- */
#importador-cej { border-top: 4px solid var(--gold); }
.cej-casillas { display: flex; align-items: flex-end; gap: 6px; flex-wrap: wrap; margin: 10px 0 16px; }
.cej-cas { display: flex; flex-direction: column; gap: 4px; }
/* padding lateral mínimo: el ancho es para el número, no para el hueco. */
.cej-cas input { text-align: center; font-weight: 700; font-variant-numeric: tabular-nums; height: 44px; padding-left: 4px; padding-right: 4px; }
.cej-hint { font-size: 11px; color: var(--ink-3); text-align: center; font-weight: 600; letter-spacing: 0.3px; }
.cej-sep { color: var(--ink-3); font-weight: 700; padding-bottom: 22px; }
/* Aquí vivían `#cej-captcha-zona`, `#cej-captcha-img` y `#cej-captcha-input`:
   el cuadro donde el abogado copiaba a mano el código de seguridad del CEJ.
   Desde que el servidor lo resuelve con 2Captcha, esos tres elementos no
   existen en ningún HTML ni JS. Retirados el 2026-08-13. */
#cej-loader { display: none; margin-top: 12px; }
#cej-error {
  display: none; font-size: 13px; color: var(--danger-txt); font-weight: 600;
  margin-top: 10px; background: var(--danger-bg); padding: 10px 14px; border-radius: var(--r-sm);
}
.rep-seccion { background: var(--card); border: 1px solid var(--line); border-radius: var(--r-lg); overflow: hidden; margin-bottom: 16px; box-shadow: var(--shadow-1); }
/* ---- Repasar toda la carpeta contra el CEJ ---------------------
   El botón va en segundo plano al lado de "Nuevo expediente": es una acción
   de mantenimiento, no la principal. La franja de avance sale debajo porque
   el repaso dura varios minutos y hace falta ver por dónde va y poder parar. */
/* Los dos botones van en una sola línea y alineados por su centro. "Nuevo
   expediente" es más alto y más ancho a propósito: es lo que se hace a
   diario; repasar la carpeta es mantenimiento de vez en cuando. La jerarquía
   se ve sin leer. */
.carpeta-head-acc { display: flex; align-items: center; gap: 10px; flex-wrap: nowrap; }
.btn-repaso-cej { display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  cursor: pointer; white-space: nowrap; height: 38px; padding: 0 15px;
  font-family: inherit; font-size: 12.5px; font-weight: 700; color: var(--ink-2);
  background: var(--card); border: 1px solid var(--line-strong); border-radius: var(--r-md);
  transition: border-color var(--speed), background var(--speed), color var(--speed); }
.btn-repaso-cej:hover { border-color: var(--gold); background: var(--gold-soft); color: var(--ink); }
/* 🪦 06-09-2026 · SE BARRE `.carpeta-nuevo-btn` (las tres reglas de esta hoja).
   Su botón se retiró de la cabecera de la Carpeta por ser el mismo que el de la
   barra de la izquierda — ver el comentario en app.html. Sin elemento que
   vestir, estas reglas son CSS huérfano, y en esta casa el CSS huérfano acaba
   reapareciendo en el sitio equivocado (📖 la lección del token `--vino`).
   Comprobado: cero menciones de la clase en JS y en HTML. */
/* En pantalla estrecha dejan de competir por el ancho: uno debajo del otro,
   el principal primero.
   🔴 2026-08-13 · ESTO COLGABA DE `@media (max-width: 700px)` Y EL CORTE ESTABA
   MAL PUESTO. La app se considera apretada (`body.estrecho`) a partir de 860 px
   de ventana O cuando el Socio abierto deja menos de 900 px de sitio para
   trabajar — o sea que entre 701 px y ese punto los botones seguían peleándose
   por el ancho en una sola línea que no envuelve (`nowrap`, y su texto tampoco
   parte). Con dos botones se notaba poco; al entrar el tercero («Analizar un
   documento») la fila se salía de la columna con el Socio abierto.
   Ahora cuelga de `body.estrecho`, que es LA condición que significa «no hay
   sitio», y deja de haber dos umbrales distintos para lo mismo. */
/* 🪤 AQUÍ HABÍA UN CUARTO RENGLÓN, `.carpeta-head { align-items: stretch }`, Y
   LLEVABA MUERTO DESDE QUE SE ESCRIBIÓ. Vivía dentro del `@media`, con la misma
   fuerza que el `.carpeta-head { align-items: center }` de más abajo en esta
   misma hoja (hoy, línea ~1741) — y a igual fuerza gana el último, que es
   aquél. O sea: nunca alineó nada. Al mudarlo a `body.estrecho` habría pasado a
   ganar y HABRÍA CAMBIADO el aspecto de la cabecera en el celular, que es
   justo lo que no se puede juzgar desde aquí (regla 9). Se retira en vez de
   estrenarse de rebote: si alguna vez hace falta, que se ponga a propósito y
   mirándolo. */
body.estrecho .carpeta-head-acc { flex-wrap: wrap; width: 100%; }
body.estrecho .carpeta-head-acc > * { flex: 1 1 100%; }

.cej-masivo { display: flex; align-items: center; gap: 12px; margin-bottom: 14px;
  padding: 12px 16px; background: var(--gold-soft); border: 1px solid var(--gold);
  border-radius: var(--r-md); font-size: 13px; color: var(--ink-2); }
.cej-masivo > i { color: var(--accent-ink); flex-shrink: 0; }
.cej-masivo > div { flex: 1; min-width: 0; }
.cej-masivo b { color: var(--ink); font-variant-numeric: tabular-nums; }
.cej-masivo button { cursor: pointer; font-family: inherit; font-size: 12px; font-weight: 800;
  color: var(--ink-2); background: var(--card); border: 1px solid var(--line-strong);
  border-radius: var(--r-sm); padding: 6px 14px; flex-shrink: 0; }
.cej-masivo button:hover { border-color: var(--danger-txt); color: var(--danger-txt); }

/* Los estilos del bloque "¿A quién patrocinas?" (.mp-*) se retiraron con él:
   la pregunta se hace ahora en la tabla de partes de la ficha, con el botón
   "Es mi cliente" sobre cada parte. */
/* Aviso tras un cambio de lado: no se recalculó nada, hay que revisar. */
/* OJO: estos avisos viven DENTRO de la ficha, que tiene fondo navy oscuro.
   La tinta normal (--ink-2, gris plomo) era ilegible ahí. Todo el bloque va
   en tonos claros, pensado para leerse sobre azul oscuro. */
.fhc-revisar { position: relative; z-index: 1; display: flex; align-items: center; gap: 10px; margin-bottom: 12px; padding: 10px 12px; background: rgba(197,160,89,.16); border: 1px solid var(--gold); border-radius: var(--r-sm); font-size: 12px; color: #f2e9d6; line-height: 1.55; flex-wrap: wrap; }
.fhc-revisar b { color: #fff; font-weight: 700; }
/* ⚖️ 09-09 (noche) · «Casilla electrónica facultativa · 155-G» en la ficha del
   expediente (hasta el 15-09 decía «Sin defensa cautiva», y se leía como «no
   tienes defensa»).
   HUECA a propósito (borde y fondo apenas tintado, sin relleno macizo): es un
   dato del proceso que corre solo, no algo a lo que haya que ir a una hora.
   Es la regla de las pastillas de la casa. 📐 12 px, por encima del suelo de 11. */
.fhc-155g {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px; border-radius: var(--r-pastilla);
  font-size: 12px; font-weight: 700; letter-spacing: .2px;
  color: #e7dcc4; border: 1px solid rgba(197,160,89,.55);
  background: rgba(197,160,89,.10); white-space: nowrap;
}
.fhc-revisar > i { color: var(--gold); font-size: 14px; flex-shrink: 0; }
.fhc-revisar > div { flex: 1; min-width: 220px; }
.fhc-revisar button { margin-left: auto; flex-shrink: 0; cursor: pointer; border: 1px solid var(--gold); background: var(--gold); color: #17202b; font-family: inherit; font-size: 12px; font-weight: 800; border-radius: var(--r-sm); padding: 8px 12px; transition: filter var(--speed); }
.fhc-revisar button:hover { filter: brightness(1.1); }
/* Contradicción entre "tu parte" y "cliente": más grave que un recordatorio,
   porque con eso la IA argumentaría por la parte contraria. */
.fhc-choque { background: rgba(220, 38, 38, .22); border-color: #f87171; color: #ffe9e9; }
.fhc-choque b { color: #fff; }
.fhc-choque > i { color: #fca5a5; }
.fhc-choque button { border-color: #fecaca; background: #fff; color: #b91c1c; }
.fhc-choque button:hover { filter: none; background: #fee2e2; }
.rep-titulo {
  display: flex; align-items: center; justify-content: space-between;
  background: var(--navy-900); color: var(--gold);
  font-size: 13px; font-weight: 700; letter-spacing: 0.8px;
  padding: 14px 18px;
}
.rep-body { padding: 18px; }
.rep-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 10px 22px; }
.rep-item { font-size: 13px; padding: 4px 0; }
.rep-item .lbl { color: var(--ink-3); font-weight: 600; }
.rep-item .val { color: var(--ink); font-weight: 600; }
.rep-tabla th { background: var(--paper); }

/* ---- La ficha del expediente con el cuadro del CEJ -------------
   Mismo cuadro que la vista previa de "Traer del CEJ", pero aquí cada dato
   se corrige con un clic. La pista de que es editable se da al pasar por
   encima (subrayado de puntos): marcarlos todos siempre llenaría la ficha
   de rayas y se leería peor, que es justo lo que se venía a arreglar. */
.rep-ancho { grid-column: 1 / -1; }
.rep-edit { cursor: text; border-radius: 4px; padding: 1px 4px; margin: -1px -4px;
  border-bottom: 1px dashed transparent; transition: background var(--speed), border-color var(--speed); }
.rep-edit:hover, .rep-edit:focus-visible { background: var(--gold-soft); border-bottom-color: var(--gold); outline: none; }
.rep-vacio { color: var(--ink-3); font-weight: 600; font-style: italic; }
.rep-edit-inp { width: 100%; min-width: 120px; font-family: inherit; font-size: 13px; font-weight: 600;
  color: var(--ink); background: var(--card); border: 1px solid var(--gold); border-radius: var(--r-sm); padding: 3px 6px; }
.rep-edit-inp:focus { outline: none; box-shadow: 0 0 0 3px var(--gold-soft); }
.rep-nada { font-size: 13px; color: var(--ink-2); line-height: 1.6; margin: 0; }
/* Un botón dentro de una sección del reporte va sobre fondo BLANCO, no sobre
   el encabezado azul: `.fhc-qa` a secas es casi blanco sobre blanco y no se
   lee (pasó el 2026-08-04 con "Actualizar desde el CEJ" en Partes procesales).
   Aquí se usa siempre la variante `prim`, que es dorada con letra oscura. */
.rep-body .fhc-qa { margin-top: 10px; }

/* ---- «A quién patrocinas», dentro de PARTES PROCESALES (2026-08-20) ----
   Se mudó desde «Editar datos» porque es aquí, al lado de los nombres, donde
   el abogado decide. Va en dorado suave —el color de «esto lo pones tú»— y no
   en rojo: sin definir no es una avería, es un dato que falta.
   🪤 `max-width` en los <select>: la regla global `input, select { width:100% }`
   los estiraba de lado a lado de la ficha y el desplegable quedaba absurdo en
   una pantalla ancha. Ya mordió tres veces en este proyecto.

   🔴 2026-08-27 · LA CAJA YA NO SALE CUANDO EL DATO ESTÁ. Repetía «A quién
   patrocinas: Demandante · parte activa» encima de una tabla que ya lo dice
   mejor. Estos estilos se quedan porque siguen vistiendo los TRES casos en que
   la caja sí sale (sin partes · rol sin bando · deducido por el Vigía) y el
   aviso de «sin definir». `.tuparte-pie` pasó de renglón propio a coletilla
   dentro de esa línea: por eso ahora es `display:block` con menos margen. */
.tuparte { background: var(--gold-soft); border: 1px solid var(--gold); border-radius: var(--r-sm);
  padding: 12px 14px; margin-bottom: 14px; }
.tuparte-l { font-size: 13px; color: var(--ink); font-weight: 600; line-height: 1.6; }
.tuparte-l > i { color: var(--accent-ink); margin-right: 6px; }
.tuparte-sin { color: var(--warning-txt); font-weight: 800; }
.tuparte select { max-width: 420px; margin-top: 8px; font-size: 13px; }
.tuparte-lado { margin-top: 10px; padding: 10px 12px; background: var(--card);
  border: 1px dashed var(--gold); border-radius: var(--r-sm); }
.tuparte-lado label { display: block; font-size: 12px; color: var(--accent-ink); font-weight: 600; }
.tuparte-lado select { margin-top: 6px; }
.tuparte-auto { margin-top: 10px; padding: 8px 10px; background: var(--card);
  border: 1px solid var(--gold); border-radius: var(--r-sm);
  font-size: 11.5px; color: var(--accent-ink); line-height: 1.55; }
.tuparte-auto button { cursor: pointer; font-family: inherit; font-size: 11px; font-weight: 700;
  margin-left: 6px; padding: 3px 9px; color: var(--ink-2); background: var(--paper);
  border: 1px solid var(--line-strong); border-radius: var(--r-sm); }
.tuparte-auto button:hover { border-color: var(--gold); background: var(--gold-soft); color: var(--ink); }
.tuparte-pie { display: block; font-size: 11px; color: var(--ink-3); margin-top: 4px; line-height: 1.5; font-weight: 400; }

/* La parte que es tu cliente se ve de un vistazo, sin tener que leer. */
.rep-tabla tr.es-cliente > td { background: var(--gold-soft); }
.rep-tabla .rep-acc { text-align: right; white-space: nowrap; }
.pill-cliente { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 800;
  letter-spacing: .03em; text-transform: uppercase; color: var(--accent-ink); background: var(--card);
  border: 1px solid var(--gold); border-radius: var(--r-pastilla); padding: 4px 10px; }
.btn-es-cliente { cursor: pointer; font-family: inherit; font-size: 11px; font-weight: 700;
  color: var(--ink-2); background: var(--paper); border: 1px solid var(--line-strong);
  border-radius: var(--r-sm); padding: 5px 10px; transition: border-color var(--speed), background var(--speed), color var(--speed); }
.btn-es-cliente:hover { border-color: var(--gold); background: var(--gold-soft); color: var(--ink); }
/* 🆕 15-09 · Varios clientes del mismo lado. La ✕ quita a uno; «Cambiar de
   lado» va apagado a propósito (es la excepción, no la regla); y «¿Tu cliente?»
   es la pastilla hueca de lo deducido por el nombre, sin confirmar. */
.btn-quitar-cliente { cursor: pointer; font-family: inherit; width: 24px; height: 24px; margin-left: 4px;
  display: inline-flex; align-items: center; justify-content: center; vertical-align: middle;
  color: var(--ink-3); background: transparent; border: 1px solid var(--line); border-radius: 50%; }
.btn-quitar-cliente:hover, .btn-quitar-cliente:focus-visible { color: var(--danger-txt); border-color: var(--danger-txt); }
.btn-es-cliente.btn-otro-lado { color: var(--ink-3); border-style: dashed; background: transparent; }
.pill-cliente.pill-tentativo { border-style: dashed; color: var(--ink-2); text-transform: none; letter-spacing: 0; }
/* 15-09 (noche) · Con aire arriba y al MISMO margen que el cuerpo (18 px): pegada
   al título y dos píxeles más adentro que la tabla se veía descuadrada. */
.rep-nota-fuente { display: flex; gap: 8px; align-items: flex-start; margin: 14px 18px 14px; padding: 9px 12px;
  font-size: 12.5px; line-height: 1.5; color: var(--ink-2); border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--senal-info) 10%, transparent); border: 1px solid color-mix(in srgb, var(--senal-info) 45%, transparent); }
.rep-nota-fuente > i { color: var(--info-txt); margin-top: 3px; }

/* El expediente que el CEJ no puede consultar por falta de parte. Es un
   agujero silencioso: sin este aviso se caía de la ronda diaria y nadie lo
   sabía. Por eso va dentro de la ficha y no en una pantalla aparte. */
.ficha-sinparte { display: flex; gap: 12px; align-items: flex-start; margin-bottom: 14px;
  padding: 14px 16px; background: var(--gold-soft); border: 1px solid var(--gold);
  border-radius: var(--r-md); font-size: 13px; color: var(--ink-2); line-height: 1.6; }
.ficha-sinparte > i { color: var(--accent-ink); font-size: 16px; margin-top: 2px; flex-shrink: 0; }
.ficha-sinparte b { color: var(--ink); }
.ficha-sinparte-form { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.ficha-sinparte-form input { flex: 1 1 220px; font-family: inherit; font-size: 13px; color: var(--ink);
  background: var(--card); border: 1px solid var(--line-strong); border-radius: var(--r-sm); padding: 8px 10px; }
.ficha-sinparte-form input:focus { outline: none; border-color: var(--gold); box-shadow: 0 0 0 3px var(--gold-soft); }
.ficha-sinparte-form button { cursor: pointer; font-family: inherit; font-size: 12px; font-weight: 800;
  color: var(--navy-900); background: var(--gold); border: 1px solid var(--gold);
  border-radius: var(--r-sm); padding: 8px 16px; transition: filter var(--speed); }
.ficha-sinparte-form button:hover { filter: brightness(1.06); }
.ficha-sinparte-pista { display: block; margin-top: 8px; font-size: 12px; color: var(--ink-3); }

/* ============================================================
   CARPETA v4 — cabecera, navegador de casos, ficha-hero, docs monocromo
   ============================================================ */
/* Cabecera ligera */
.carpeta-head { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-bottom: 16px; flex-wrap: wrap; }
.ch-title { display: flex; align-items: baseline; gap: 10px; }
/* 🪦 06-09 · Y `.ch-k` igual: era el ÚNICO título de pantalla a 17 px y el
   único sin icono. El aspecto lo pone `.titulo-pantalla`. */
.ch-count { font-size: 12px; font-weight: 600; color: var(--ink-3); font-variant-numeric: tabular-nums; }

/* Navegador de casos */
.carpeta-nav { background: var(--card); border: 1px solid var(--line); border-radius: var(--r-lg); box-shadow: var(--shadow-1); overflow: hidden; margin-bottom: 18px; }

/* La vuelta a la lista, cuando el navegador está plegado (2026-08-11).
   Discreta a propósito: es una salida, no una acción del expediente, y
   compitiendo con la ficha se llevaría la atención que necesita el caso.
   🔴 Rehecha el 11-08 — la primera versión era un rectángulo suelto que no se
   parecía a nada más de la pantalla. Ahora hereda la misma altura, radio y
   peso que `.btn-repaso-cej` (el botón de al lado, arriba), para que se lea
   como parte del mismo sistema y no como un pegote. */
.carpeta-volver { margin-bottom: 14px; }
.carpeta-volver button {
  display: inline-flex; align-items: center; gap: 9px;
  height: 34px; padding: 0 15px 0 13px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-pastilla);
  color: var(--ink-2); font-family: inherit; font-size: 12.5px; font-weight: 700;
  cursor: pointer; box-shadow: var(--shadow-1);
  transition: border-color var(--speed), background var(--speed), color var(--speed);
}
.carpeta-volver button:hover { border-color: var(--gold); background: var(--gold-soft); color: var(--ink); }

/* El «regresa» de la ventana del Vigía (2026-08-12). Mismo gesto y mismo aspecto
   que la vuelta de la Carpeta: es la misma idea —deshacer un paso— y tenerla con
   dos caras distintas sería aprenderla dos veces. Va arriba a la IZQUIERDA, en
   diagonal con la X de cerrar, que está arriba a la derecha; por eso se reserva
   sitio con el margen inferior en vez de superponerse al título. */
.vigia-atras {
  display: inline-flex; align-items: center; gap: 8px;
  height: 30px; padding: 0 13px 0 11px; margin: 0 0 14px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-pastilla);
  color: var(--ink-2); font-family: inherit; font-size: 12px; font-weight: 700;
  cursor: pointer; box-shadow: var(--shadow-1);
  transition: border-color var(--speed), background var(--speed), color var(--speed);
}
.vigia-atras:hover { border-color: var(--gold); background: var(--gold-soft); color: var(--ink); }
.vigia-atras i { font-size: 11px; color: var(--ink-3); transition: transform var(--speed), color var(--speed); }
.vigia-atras:hover i { transform: translateX(-3px); color: var(--gold); }
@media (prefers-reduced-motion: reduce) { .vigia-atras:hover i { transform: none; } }
/* La flecha se corre a la izquierda al pasar por encima: dice «atrás» sin
   gastar una palabra más. Se queda quieta si el usuario pidió menos animación. */
.carpeta-volver button i { font-size: 11px; color: var(--ink-3); transition: transform var(--speed), color var(--speed); }
.carpeta-volver button:hover i { transform: translateX(-3px); color: var(--gold); }
@media (prefers-reduced-motion: reduce) { .carpeta-volver button:hover i { transform: none; } }
.cnav-search { display: flex; align-items: center; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--line); flex-wrap: wrap; }
.cnav-search > i { color: var(--ink-3); font-size: 13px; }
.cnav-search input { flex: 1 1 200px; border: 0; background: transparent; font-family: inherit; font-size: 13px; color: var(--ink); padding: 2px 0; outline: none; }
.cnav-search input::placeholder { color: var(--ink-3); }
/* Con el chip "Por materia" la fila llega justa en 375px: que envuelva
   antes de recortar ningún filtro. */
.cnav-filtros { display: flex; gap: 6px; flex-wrap: wrap; row-gap: 6px; }
/* ---- La barra propia de la vista «Etapas» (2026-08-13) ----
   Las ramas del derecho, «Solo míos» y «Excel» viajaron aquí desde la pestaña
   «Estado Procesal», que dejó de existir. Se centran verticalmente porque esta
   fila mezcla pastillas (30 px) con botones (36 px): sin esto las pastillas
   quedan colgando de la línea superior. */
.cnav-filtros-etapas { align-items: center; gap: 8px; }
/* El conmutador Lista/Etapas se va al extremo derecho de la barra, como el
   Lista/Mes de la Agenda. `.tudia-toggle` pone TODO el aspecto —es el mismo
   componente, no una copia—; esto sólo lo coloca. */
.cnav-vista { margin-left: auto; }
/* 🪤 16-09 · `white-space: nowrap`. Una pastilla es un BOTÓN con su rótulo, no
   un párrafo: partida en dos renglones («Lo último que / llegó») deja de
   parecer una cosa que se pulsa y la fila entera se lee como un amasijo. Si no
   caben tres, que se vaya la tercera a la fila de abajo —para eso la fila ya
   tiene `flex-wrap`—, pero cada rótulo entero. Los tres son cortos: el más
   largo pide 146 px de los 292 que hay en un teléfono de 320. */
.fchip { font-size: 11px; font-weight: 700; color: var(--ink-2); background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-pastilla); padding: 4px 12px; cursor: pointer; white-space: nowrap; transition: background var(--speed), color var(--speed), border-color var(--speed); }
.fchip:hover { border-color: var(--gold); }
.fchip.on { background: var(--navy-900); color: #f3ecd8; border-color: var(--navy-900); }
/* 🔢 05-09 · El conteo dentro de la pastilla. Cifras tabulares para que no
   baile el ancho al cambiar de 9 a 10, y un punto más apagado que el rótulo:
   lo que se lee primero es QUÉ filtra, y el número es el dato de apoyo.
   Vacío cuando es 0 —lo pone `renderNavegadorCasos`— y entonces no ocupa: un
   «0» pegado a un chip se confunde con parte del nombre. */
.fchip-n { font-variant-numeric: tabular-nums; opacity: .72; font-weight: 800; }
.fchip-n:empty { display: none; }

/* ---- Área del proceso (civil, penal, laboral…) ----
   Identidad, NO urgencia: tonos apagados y en un solo sitio. El color
   fuerte sigue siendo del tiempo (rojo vencido / ámbar hoy / ciruela audiencia). */
/* El rótulo corto de los filtros solo existe en el celular (bloque de 860px). */
.fchip-corto { display: none; }
.fchip-sep { margin-left: 6px; position: relative; }
.fchip-sep::before {
  content: ""; position: absolute; left: -6px; top: 15%; height: 70%;
  border-left: 1px solid var(--line);
}
.cnav-grupo {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 14px; background: var(--paper);
  border-bottom: 1px solid var(--line); border-left: 3px solid transparent;
  font-size: 11px; font-weight: 800; text-transform: uppercase;
  letter-spacing: .05em; color: var(--ink-2);
  position: sticky; top: 0; z-index: 2;
}
.cnav-grupo b {
  margin-left: auto; font-size: 12px; color: var(--ink-3);
  background: var(--bg-2); border-radius: var(--r-pastilla); padding: 1px 10px; letter-spacing: 0;
}
/* Botón "Buscar plazos y audiencias" en la cabecera de la Carpeta. Acción
   secundaria dorada, discreta pero visible. */
.btn-plazos-doc {
  display: inline-flex; align-items: center; gap: 8px;
  font-size: 12px; font-weight: 700; font-family: inherit;
  color: var(--acento-txt); background: var(--gold-soft);
  border: 1px solid var(--gold); border-radius: var(--r-pastilla); padding: 6px 14px;
  cursor: pointer; transition: background var(--speed), color var(--speed);
}
.btn-plazos-doc:hover { background: var(--gold); color: var(--navy); }
.btn-plazos-doc:disabled { opacity: .6; cursor: default; }
/* Novedad del Vigía sin ver en la fila del expediente: punto dorado en el
   cuadrito + pastilla "N nuevos" junto al número. */
.case-av { position: relative; }
.case-av-dot {
  position: absolute; top: -3px; right: -3px; width: 11px; height: 11px;
  background: var(--gold-strong); border: 2px solid var(--card, #fff); border-radius: 50%;
}
/* El «2 NUEVOS» de la Carpeta llevaba letra `--navy` (oscura) sobre `--gold`.
   Medido en las seis paletas: 6,10 en dorado pero **2,31 en burdeos**, 2,78 en
   púrpura y 2,97 en cobre — porque en esas cinco el acento ya ES un color
   oscuro y ponerle encima una letra oscura no puede salir bien.
   La pareja correcta ya existía: `--gold-strong` de relleno y `--sobre-acento`
   de letra (oscura sólo en el dorado, blanca en las demás). Mínimo 4,78. */
.case-nov {
  display: inline-block; margin-left: 8px; font-size: 11px; font-weight: 800;
  text-transform: uppercase; letter-spacing: .04em; color: var(--sobre-acento);
  background: var(--relleno-acento, var(--gold-strong)); border-radius: var(--r-pastilla); padding: 1px 8px; vertical-align: middle;
}
/* "Por confirmar" = una decisión tuya sobre un plazo QUE YA ESTÁ CORRIENDO.
   🔴 12-09-2026 · ESTABA HUECA Y NO SE VEÍA. Lo dijo Piero mirando su lista:
   «1 por confirmar no se ve bien visible, más porque es blanco». Y tenía razón
   medida: fondo transparente y borde `--line-strong` al lado de la pastilla
   dorada MACIZA de «N nuevos» — en esa fila el ojo sólo encontraba el dorado.
   El razonamiento de 2026-08 («va apagada porque el dorado se reserva a lo que
   acaba de llegar») protegía la jerarquía equivocada: una NOTICIA sin leer
   pesa menos que un PLAZO CORRIENDO sin confirmar, que es lo único de esta
   pantalla que puede perder un caso.
   🎨 Se resuelve con el par medido `--warning-bg`/`--warning-txt` (el mismo de
   los avisos del sistema, ya comprobado en las seis paletas y en oscuro), no
   con el dorado: así se ve desde lejos y sigue sin competir con «N nuevos»,
   porque son dos colores distintos y no dos intensidades del mismo. */
.case-nov-pend {
  background: var(--warning-bg); color: var(--warning-txt);
  border: 1px solid color-mix(in srgb, var(--warning-txt) 45%, transparent);
  font-weight: 800; text-transform: none; letter-spacing: 0;
}
/* ⏳ "N del CEJ" = un aviso temprano: lo vi publicado pero TODAVÍA no te han
   notificado, así que el plazo no corre. Se ve —es trabajo que se puede ir
   adelantando— pero va hueca y en el azul de lo que está por llegar: macizarla
   la pondría al mismo nivel que un plazo vivo, que es exactamente la confusión
   que este producto existe para evitar. Ver `sugerenciaProvisional`. */
.case-nov-cej {
  background: color-mix(in srgb, var(--senal-info) 12%, transparent);
  color: var(--info-txt);
  border: 1px dashed color-mix(in srgb, var(--senal-info) 60%, transparent);
  font-weight: 700; text-transform: none; letter-spacing: 0;
}
.case-nov-pend i, .case-nov-cej i { font-size: 9.5px; margin-right: 1px; }
/* 🆕 15-09 · Las dos pastillas son BOTONES (abren el plazo sugerido): se les
   quita el aspecto de botón del navegador y se les da el de algo que se pulsa. */
button.case-nov { font-family: inherit; line-height: inherit; cursor: pointer; }
button.case-nov:hover { filter: brightness(.96); box-shadow: 0 0 0 2px color-mix(in srgb, currentColor 25%, transparent); }
button.case-nov:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
/* "Ver datos del expediente" — desplegable dentro de la Ficha Judicial, para
   no repetir datos que ya se ven en la Carpeta y bajar el ruido del modal. */
.ficha-mas { margin: 4px 0 6px; }
.ficha-mas > summary {
  cursor: pointer; list-style: none; display: inline-flex; align-items: center; gap: 8px;
  font-size: 12px; font-weight: 700; color: var(--ink-2);
  padding: 6px 0;
}
.ficha-mas > summary::-webkit-details-marker { display: none; }
.ficha-mas > summary::before { content: "\f078"; font-family: "Font Awesome 6 Free"; font-weight: 900; font-size: 11px; transition: transform var(--speed); color: var(--acento-txt); }
.ficha-mas[open] > summary::before { transform: rotate(180deg); }
.ficha-mas > summary:hover { color: var(--ink); }
/* Pastilla de riesgo en la cabecera de la Ficha Judicial (antes texto suelto). */
.riesgo-chip {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11px; font-weight: 800; letter-spacing: .02em;
  padding: 4px 10px; border-radius: var(--r-pastilla); border: 1px solid;
}
.riesgo-chip.alto  { color: var(--danger-txt); background: var(--danger-bg); border-color: color-mix(in srgb, var(--danger) 40%, transparent); }
.riesgo-chip.medio { color: #b3701f; background: rgba(207,112,39,.12); border-color: rgba(207,112,39,.4); }
.riesgo-chip.bajo  { color: var(--ink-2); background: var(--paper); border-color: var(--line); }
.area-chip {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em;
  padding: 2px 10px; border-radius: var(--r-pastilla); border: 1px solid; white-space: nowrap;
}

.case-row { display: grid; grid-template-columns: auto 1fr auto; gap: 12px; align-items: center; padding: 12px 14px; border-bottom: 1px solid var(--line); cursor: pointer; transition: background var(--speed); }
.case-row:last-child { border-bottom: 0; }
.case-row:hover { background: var(--paper); }
.case-row.sel { background: linear-gradient(90deg, var(--gold-soft), transparent 72%); box-shadow: inset 3px 0 0 var(--gold); }
.case-av { width: 34px; height: 34px; border-radius: var(--r-md); background: var(--navy-900); color: var(--accent-on-deep); display: flex; align-items: center; justify-content: center; font-family: var(--font-ui); font-size: 15px; font-weight: 700; flex: none; }
.case-main { min-width: 0; }
.cm-top { font-size: 13px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; letter-spacing: .01em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cm-sub { font-size: 12px; color: var(--ink-3); margin-top: 1px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* Última notificación del juzgado. Renglón propio y en gris: es el dato que
   más se consulta al abrir la carpeta, pero NO es una urgencia — el color
   fuerte de esta lista está reservado a los plazos (.st de abajo). El icono
   de campana lo hace localizable de un vistazo sin pintar la fila. */
/* ---- EL PIE DE CADA FILA DE LA CARPETA (2026-08-20) -------------
   Dos datos en una línea: de qué te notificaron y de quién es el expediente.
   🪤 `flex-wrap: wrap` NO es decorativo: sin él los dos trozos se pelean por el
   ancho y en el celular el responsable se sale de la tarjeta. En una pantalla
   estrecha caen en dos renglones, que es lo correcto.
   La cédula del SINOE va con el color del texto normal y no en gris: es EL dato
   del que cuelga el plazo. El CEJ se queda en gris — es aviso, no reloj— y así
   la diferencia entre uno y otro se ve sin leer. */
.cm-pie { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 12px; margin-top: 4px; }
.cm-notif, .cm-ced, .cm-cej, .cm-resp {
  font-size: 11px; display: inline-flex; align-items: center; gap: 5px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0;
}
/* 🪤 EN EL CELULAR SE CORTABA LA FECHA DE LA CÉDULA, y era el peor sitio donde
   podía pasar: «Cédula 04/11/2025 · hace 289 días» salía como «Cédula
   04/11/2025 · hace…». Visto haciendo la captura a 375 px, no por una prueba —
   ninguna suite ve el ancho de la pantalla.
   En estrecho el trozo se PARTE en dos líneas en vez de recortarse: dos
   renglones se leen; media fecha, no. */
@media (max-width: 640px) {
  .cm-ced, .cm-cej, .cm-notif, .cm-resp {
    white-space: normal; overflow: visible; text-overflow: clip;
    align-items: flex-start; line-height: 1.45;
  }
  .cm-ced > i, .cm-cej > i, .cm-notif > i, .cm-resp > i { margin-top: 3px; }
}
.cm-notif, .cm-cej { color: var(--ink-3); }
.cm-ced { color: var(--ink-2); font-weight: 600; }
.cm-ced > i { color: var(--acento-txt); }
.cm-resp { color: var(--ink-3); }
.cm-resp-sin { color: var(--warning-txt); font-style: italic; }
.cm-notif > i, .cm-ced > i, .cm-cej > i, .cm-resp > i { font-size: 10px; opacity: .8; flex: none; }
.cm-notif-sin { font-style: italic; opacity: .8; }
.case-meta { text-align: right; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; flex: none; }
.case-when { font-size: 11px; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.st { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; padding: 2px 10px; border-radius: var(--r-pastilla); white-space: nowrap; }
.st.venc { background: var(--danger-bg); color: var(--danger-txt); }
.st.hoy  { background: var(--warning-bg); color: var(--warning-txt); }
/* 🔴 07-09 (tarde) · LAS DOS TINTADAS, con `--senal-*`. Su fondo era su única
   forma y en oscuro no existía: mezclar el token crudo —una tinta oscura— sobre
   la tarjeta oscura daba 1,05:1 y 1,08:1, o sea nada. Ahora 1,26 y 1,20, con el
   texto dentro en 6,12 y 4,65. Y el azul deja de estar escrito a mano:
   `rgba(43,91,143)` era `--info` copiado, que es como se separan dos sitios. */
.st.aud  { background: color-mix(in srgb, var(--senal-audiencia) 12%, transparent); color: var(--audiencia-txt); }
.st.prox { background: color-mix(in srgb, var(--senal-info) 12%, transparent); color: var(--info-txt); }
.st.ok   { background: var(--success-bg); color: var(--success-txt); }
.cnav-empty { text-align: center; padding: 38px 20px; color: var(--ink-3); }
.cnav-empty i { font-size: 34px; color: var(--gold); opacity: .5; }
.cnav-empty p { font-size: 13px; margin: 12px 0 16px; }
.cnav-nores { padding: 26px 16px; text-align: center; font-size: 13px; color: var(--ink-3); font-style: italic; }

/* Ficha-cabecera jerárquica del expediente abierto */
.ficha-hero-carpeta { position: relative; overflow: hidden; background: linear-gradient(160deg, var(--navy-900), var(--navy-800)); border: 1px solid rgba(197,160,89,.28); border-radius: var(--r-lg); padding: 14px 16px; margin-bottom: 12px; box-shadow: var(--shadow-2); }
.ficha-hero-carpeta::after { content: ""; position: absolute; right: -46px; top: -46px; width: 170px; height: 170px; background: radial-gradient(circle, rgba(197,160,89,.16), transparent 66%); pointer-events: none; }
.fhc-top { position: relative; z-index: 1; display: flex; align-items: flex-start; justify-content: space-between; gap: 14px; }
.fhc-exp { font-size: 11px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--accent-on-deep, #ecd9a6); display: block; }
.fhc-num { font-size: 17px; font-weight: 700; color: #fff; font-variant-numeric: tabular-nums; letter-spacing: .01em; display: block; margin-top: 1px; }
.fhc-cli { font-size: 12px; color: rgba(234,238,244,.72); display: block; margin-top: 4px; }
.fhc-riesgo { flex: none; display: inline-flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .03em; padding: 6px 12px; border-radius: var(--r-pastilla); }
.fhc-riesgo .rd { width: 7px; height: 7px; border-radius: 50%; }
.fhc-riesgo.alto { background: rgba(179,54,42,.20); color: #f7c3bc; border: 1px solid rgba(179,54,42,.5); }
.fhc-riesgo.alto .rd { background: #ef6b5c; }
.fhc-riesgo.ok { background: rgba(20,115,90,.20); color: #a7dcc9; border: 1px solid rgba(20,115,90,.5); }
.fhc-riesgo.ok .rd { background: #37b58f; }
.fhc-meta { position: relative; z-index: 1; display: flex; flex-wrap: wrap; gap: 6px 20px; margin-top: 10px; }
/* Rótulos RESPONSABLE / PRÓXIMA / TU PARTE. Estaban al 50% de opacidad y NO
   LLEGABAN AL MÍNIMO EN NINGUNA de las 6 paletas (3.73 esmeralda … 4.42
   dorado, mínimo 4.5), y encima son mayúsculas de 11 px, que es de lo que peor
   se lee. Al 78% dan 6.78:1 en el peor caso. Cumplirían al 59%, pero el margen
   de más no cuesta nada y esta app la usa gente que lleva gafas. */
.fhc-meta .m .ml { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .05em; color: rgba(234,238,244,.78); display: block; }
.fhc-meta .m .mv { font-size: 12px; font-weight: 600; color: #eef2f7; margin-top: 1px; display: block; }
.fhc-actions { position: relative; z-index: 1; display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
/* La LETRA de estos botones ya se leía bien (9.7:1 en esmeralda, la peor de
   las 6). Lo que no se veía era el BOTÓN: con el fondo al 8% y el borde al 15%
   no había contorno que distinguir, así que parecían texto suelto flotando
   sobre el degradado — que es justo lo que se ve en la captura. El contorno de
   un control necesita 3:1 propio, no basta con que se lea la etiqueta.
   Borde al 42% → 3.37:1 en el peor caso, y el relleno sube del 8% al 14%. */
.fhc-qa { display: inline-flex; align-items: center; gap: 6px; font-family: var(--font-ui); font-size: 11px; font-weight: 700; padding: 6px 12px; border-radius: var(--r-md); background: rgba(255,255,255,.14); color: #f5f1e6; border: 1px solid rgba(255,255,255,.42); cursor: pointer; transition: background var(--speed), transform var(--speed); }
.fhc-qa:hover { background: rgba(255,255,255,.24); transform: translateY(-1px); }
/* El foco de teclado tiene que verse: hay quien no usa el ratón. */
.fhc-qa:focus-visible { outline: 2px solid var(--accent-on-deep, #ecd9a6); outline-offset: 2px; }
/* 🔴 La letra iba clavada a `--navy-900`, que sólo vale para el dorado clásico
   (donde el acento es CLARO). En las otras cinco paletas el acento es un color
   OSCURO, y poner encima una letra casi negra daba: burdeos 2.52:1, azul 3.07,
   púrpura 3.07, cobre 3.06 y esmeralda 4.12 — con el mínimo en 4.5. O sea que
   "Seguimiento cliente" era ilegible en 5 de las 6 paletas.
   `--sobre-acento` ya existía justo para esto (#17202b en dorado, #fff en las
   demás) y se usa en el resto de la app; aquí se había olvidado.
   Y el relleno pasa de `--gold` a `--gold-strong`: con el tono medio, la
   esmeralda NO llegaba ni con letra blanca (3.43) ni con letra oscura (4.12)
   —es un verde que se queda justo en mitad del rango y no admite ninguna de
   las dos—. Con el tono fuerte cumplen LAS SEIS: dorado 4.78, esmeralda 5.10,
   azul 6.64, cobre 7.02, púrpura 7.38 y burdeos 8.48. */
.fhc-qa.prim { background: var(--relleno-acento, var(--gold-strong)); color: var(--sobre-acento, var(--navy-900)); border-color: var(--acento-txt); }
.fhc-qa.prim:hover { filter: brightness(1.05); }

/* Documentos monocromáticos */
.docs-mono { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 12px; align-items: start; }
.fldr { background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-md); padding: 12px 12px; }
.fldr-h { display: flex; align-items: center; gap: 8px; font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-2); margin-bottom: 10px; }
.fldr-h i { color: var(--acento-txt); font-size: 13px; }
.fldr-cnt { margin-left: auto; font-size: 11px; font-weight: 700; color: var(--ink-3); background: var(--card); border: 1px solid var(--line); border-radius: var(--r-pastilla); padding: 1px 8px; font-variant-numeric: tabular-nums; }
/* 📐 2026-08-30 · `flex-start`, no `center`. Con el asunto debajo del título la
   fila tiene dos y tres líneas, y centrado dejaba el icono y el «Ver» flotando
   a media altura: eso es lo que se leía como «descuadrado». Y el icono se baja
   2 px para quedar a la altura de la primera línea de texto, no de la caja. */
.fldr-doc { display: flex; align-items: flex-start; gap: 10px; background: var(--card); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 8px 10px; margin-bottom: 6px; }
.fldr-doc:last-child { margin-bottom: 0; }
.fldr-doc:hover { border-color: var(--gold); }
.fldr-fi { color: var(--acento-txt); font-size: 13px; flex: none; margin-top: 2px; }
/* `min-width:0` deja que el hijo ENCOJA (sin él un flex item no baja de su
   contenido: es la misma trampa del `1fr` de la rejilla, apuntada en la
   memoria). Y `overflow-wrap` parte lo que no tiene espacios —un número de
   expediente entero— en vez de sacarlo por el borde de la tarjeta. */
.fldr-doc-main { min-width: 0; flex: 1; overflow-wrap: anywhere; }
.fldr-doc-tit { font-size: 12px; font-weight: 600; color: var(--ink); word-break: break-word; }
.fldr-doc-meta { display: block; font-size: 11px; color: var(--ink-3); margin-top: 2px; font-variant-numeric: tabular-nums; }
.fldr-doc-act { margin-left: auto; flex: none; display: flex; align-items: center; gap: 12px; }
.doc-ver { color: var(--info-txt); font-weight: 700; font-size: 12px; cursor: pointer; }
.doc-editar { color: var(--acento-txt); font-weight: 700; font-size: 12px; cursor: pointer; }
.doc-del { color: var(--danger-txt); cursor: pointer; font-size: 13px; }
.doc-rename { color: var(--ink-3); cursor: pointer; font-size: 13px; }
.doc-rename:hover { color: var(--acento-txt); }

/* Botón eliminar del editor de expediente: discreto, elegante, se torna rojo al pasar */
.edexp-del-btn {
  display: inline-flex; align-items: center; gap: 8px; width: auto;
  background: transparent; border: 1px solid var(--line-strong); color: var(--ink-3);
  padding: 10px 14px; font-size: 13px; font-weight: 600; border-radius: var(--r-md);
  cursor: pointer; transition: all .18s ease;
}
.edexp-del-btn i { font-size: 13px; }
.edexp-del-btn:hover {
  background: color-mix(in srgb, var(--danger) 8%, transparent);
  border-color: var(--danger-txt); color: var(--danger-txt);
}
.edexp-del-btn:disabled { opacity: .55; cursor: default; }
/* Botón re-analizar: acción secundaria dorada suave */
.edexp-reanalizar-btn {
  display: inline-flex; align-items: center; gap: 8px; width: auto;
  background: var(--gold-soft); border: 1px solid var(--gold); color: var(--acento-txt);
  padding: 10px 14px; font-size: 13px; font-weight: 700; border-radius: var(--r-md);
  cursor: pointer; transition: all .18s ease;
}
.edexp-reanalizar-btn:hover { background: var(--gold); color: var(--navy); }
.edexp-reanalizar-btn:disabled { opacity: .6; cursor: default; }
/* Encabezados de sección del editor de expediente (agrupan los campos) */
.edexp-sec {
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase;
  color: var(--acento-txt); margin: 16px 0 8px; padding-bottom: 6px;
  border-bottom: 1px solid var(--line);
}
.edexp-sec i { font-size: 12px; opacity: .85; }
.edexp-sec:first-of-type { margin-top: 6px; }
.badge-cej { font-size: 11px; font-weight: 800; letter-spacing: .03em; background: var(--gold-soft); color: var(--acento-txt); border-radius: var(--r-sm); padding: 1px 6px; margin-left: 6px; vertical-align: 1px; }
/* Sellos de procedencia: de dónde salió el papel (PJ vs estudio). */
.badge-cej.badge-sinoe { background: rgba(37, 99, 235, .12); color: #2563eb; }
/* Sello "dato del CEJ" en la ficha: lo dictó el portal, no lo escribió el estudio. */
.badge-cej-dato { font-size: 11px; font-weight: 800; letter-spacing: .04em; background: var(--gold-soft); color: var(--acento-txt); border: 1px solid var(--gold); border-radius: 5px; padding: 0 4px; margin-left: 6px; cursor: help; }

/* ---- Alta de expediente: 4 campos a la vista, el resto plegado ---- */
.alta-nota { font-size: 12px; color: var(--ink-3); line-height: 1.6; margin: 0 0 16px; }
.alta-mas { margin: 4px 0 14px; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--paper); }
.alta-mas > summary { cursor: pointer; padding: 10px 12px; font-size: 12px; font-weight: 700; color: var(--ink-2); list-style: none; display: flex; align-items: center; gap: 8px; }
.alta-mas > summary::-webkit-details-marker { display: none; }
.alta-mas > summary::after { content: "\f078"; font-family: "Font Awesome 6 Free"; font-weight: 900; margin-left: auto; font-size: 11px; color: var(--ink-3); transition: transform var(--speed); }
.alta-mas[open] > summary::after { transform: rotate(180deg); }
.alta-mas > summary i { color: var(--acento-txt); }
.alta-mas > summary span { font-weight: 500; color: var(--ink-3); }
.alta-mas-body { padding: 4px 12px 6px; border-top: 1px solid var(--line); }
/* "?" de ayuda junto a una etiqueta que se confunde con otra (Etapa vs Estado). */
.lbl-ayuda { display: inline-flex; align-items: center; justify-content: center; width: 13px; height: 13px; border-radius: 50%; background: var(--line); color: var(--ink-3); font-size: 11px; font-weight: 800; cursor: help; margin-left: 4px; }
.badge-cej.badge-estudio { background: var(--line); color: var(--ink-3); }

/* ============================================================
   LO PRESENTADO POR EL ESTUDIO — Mesa de Partes (2026-08-27)
   ------------------------------------------------------------
   Verde, y no dorado ni azul, porque significa otra cosa que los otros dos
   sellos: el dorado (CEJ) y el azul (SINOE) dicen «esto llegó»; éste dice
   «esto salió, y está hecho». Es el único de la Carpeta que marca una
   dirección en vez de una fuente.
   🪤 El color se toma de las variables que YA existen (`--success-*`): una
   variable CSS inventada no da error, no se dibuja y no avisa — mordió el
   26-08 con `--ok-txt`, que no existía.
   ============================================================ */
.badge-cej.badge-mpe { background: var(--success-bg); color: var(--success-txt); }

/* La hora sellada y quién presentó: lo único que no trae ninguna otra fuente. */
.mpe-pie { font-size: 11.5px; color: var(--ink-3); margin-top: 4px; line-height: 1.5; }
.mpe-pie i { margin-right: 3px; }
.mpe-sinarch { margin-top: 6px; padding: 6px 9px; background: var(--warning-bg);
  border: 1px solid var(--warning); border-radius: var(--r-sm);
  font-size: 11.5px; color: var(--ink-2); line-height: 1.5; }

/* EL RECUADRO DE ARCHIVOS. Lo pidió Piero así: una presentación es UN item y
   dentro se elige cuál abrir —Cargo · Documento · Anexos—, en vez de tres filas
   sueltas en la Carpeta.
   🪤 `flex-wrap` y no una rejilla: con tres o cuatro anexos, `1fr` no deja
   encoger la columna y la fila se sale (mordió el 19-08 en facturación). */
.mpe-caja { display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  margin-top: 8px; padding: 7px 9px; background: var(--paper);
  border: 1px dashed var(--line-strong); border-radius: var(--r-sm); }
.mpe-caja-t { font-size: 11px; font-weight: 700; color: var(--ink-3); letter-spacing: .02em; }
.mpe-arch { cursor: pointer; font-family: inherit; font-size: 11.5px; font-weight: 700;
  padding: 4px 10px; color: var(--ink-2); background: var(--card);
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  display: inline-flex; align-items: center; gap: 5px; }
.mpe-arch:hover { border-color: var(--gold); background: var(--gold-soft); color: var(--ink); }
.mpe-arch i { font-size: 11px; color: var(--acento-txt); }
/* 🔏 01-09 · El sello de «viene firmado digitalmente». Va DENTRO del botón, a
   la derecha del rótulo: es una propiedad de ESE archivo, no de la fila.
   Verde porque es lo único bueno que se puede decir de un papel —que acredita—,
   y pequeño porque no compite con el nombre del archivo. */
.mpe-arch .mpe-firmado { font-size: 11px; color: var(--success-txt); margin-left: 1px; vertical-align: 1px; }
/* «Todo junto»: destacado porque es lo que se abre para leer de corrido, pero
   sin gritar — el que ACREDITA sigue siendo el cargo original de al lado. */
.mpe-arch-todo { background: var(--gold-soft); border-color: var(--gold); color: var(--ink); }
.mpe-caja-fuera { font-size: 11px; color: var(--warning-txt); cursor: help; }
/* 🔴 02-09 · Lo que el portal ofrecía y no llegó. Ocupa su propia línea
   (`flex-basis:100%`) porque no es un botón más: es la diferencia entre un
   juego completo y uno a medias, y leerlo apretado al lado de los botones lo
   convierte en una etiqueta que nadie mira. */
.mpe-caja-falta { flex-basis: 100%; font-size: 11px; color: var(--warning-txt);
  font-weight: 600; cursor: help; display: inline-flex; align-items: center; gap: 5px; }
.mpe-caja-falta i { font-size: 10px; }

/* ⚖️ 02-09 · El aviso de un vencimiento calculado con la regla vieja. Va
   PEGADO a la fecha, no al pie de la ficha: el número que hay que dudar es el
   que se está mirando, y un aviso lejos del dato no se lee. Ocupa las dos
   columnas de su caja para que el botón quepa entero. */
.aviso-plazo-viejo { grid-column: 1 / -1; margin-top: 10px; padding: 10px 12px;
  display: flex; align-items: flex-start; gap: 9px; flex-wrap: wrap;
  background: var(--warning-bg, #fff8e6); border: 1px solid var(--warning-txt);
  border-radius: var(--r-sm); font-size: 12.5px; line-height: 1.5; color: var(--ink-2); }
.aviso-plazo-viejo > i { color: var(--warning-txt); margin-top: 2px; }
.aviso-plazo-viejo > span { flex: 1 1 240px; }
.aviso-plazo-viejo b { color: var(--ink); }
/* ⚖️ 12-09-2026 · El aviso del plazo que AÚN NO CORRE. Misma caja que el del
   155-C —va pegado a la misma fecha y se lee igual— pero en el azul de lo que
   está por llegar, no en el ámbar de «revisa esto»: no hay nada mal calculado
   ni nada que corregir, lo que falta es que el juzgado notifique. */
.aviso-plazo-viejo.aviso-plazo-prov {
  background: color-mix(in srgb, var(--senal-info) 10%, transparent);
  border-color: color-mix(in srgb, var(--senal-info) 55%, transparent);
}
.aviso-plazo-viejo.aviso-plazo-prov > i { color: var(--info-txt); }
/* 15-09 · Campo de texto que crece (Cliente(s) de la Ficha Judicial). */
textarea.campo-crece { resize: none; overflow: hidden; line-height: 1.45; min-height: 38px; font: inherit; }
/* ⚖️ 15-09 · Llegó la cédula del adelanto: verde, y con su botón al lado. */
.aviso-plazo-viejo.aviso-plazo-llego {
  background: color-mix(in srgb, var(--success-txt) 9%, transparent);
  border-color: color-mix(in srgb, var(--success-txt) 50%, transparent);
}
.aviso-plazo-viejo.aviso-plazo-llego > i { color: var(--success-txt); }

/* ---- Carpeta: selector de vista + línea de tiempo documental ---- */
.carpeta-vistas { display: flex; align-items: center; gap: 8px; margin: 0 0 14px; flex-wrap: wrap; }
.carpeta-vistas-cnt { margin-left: auto; font-size: 12px; color: var(--ink-3); font-weight: 600; }
/* El color fuerte está reservado al TIEMPO (vencimientos y audiencias);
   los documentos son historia, así que van en tinta neutra y no compiten. */
.tl-docs .tl-dot-doc { background: var(--ink-3); }
.tl-docs .tl-item { cursor: default; align-items: flex-start; }
.tl-docs .tl-item:hover .tl-body { transform: none; }
/* La tarjeta ENTERA abre el documento cuando hay algo que mostrar. */
.tl-docs .tl-item.abrible { cursor: pointer; }
.tl-docs .tl-item.abrible:hover .tl-body { background: var(--gold-soft); }
.tl-docs .tl-item.abrible:focus-visible,
.fldr-doc.abrible:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; border-radius: var(--r-sm); }
.fldr-doc.abrible { cursor: pointer; }
/* ============================================================
   📐 07-09-2026 · LAS NOTIFICACIONES CABEN EN EL CELULAR
   ------------------------------------------------------------
   Cuatro capturas de Piero: las filas de la Carpeta **se salían por la
   derecha**. Medido a 390 px con la Resolución N° 7 real, antes de tocar nada:

       .noti   ancho mínimo 386 px   (y no puede encoger más)
       .tl-body        416 px        dentro de una tarjeta de 359
       17 elementos fuera del marco · la página pedía 447 px

   🔑 LA CAUSA, en dos piezas que se necesitan las dos:
   1. `.noti` era `inline-flex` **sin `flex-wrap`**: una fila que no parte por
      dentro, así que su ancho MÍNIMO es su línea entera (nombre + rol + fecha +
      canal + n° de cédula). Ahora envuelve, y su mínimo pasa a ser el de su
      trozo más largo.
   2. `.tl-body` es un `flex: 1` **sin `min-width: 0`**, y un ítem flex no baja
      por defecto de la anchura mínima de su contenido: por eso el mínimo de la
      pastilla empujaba a la tarjeta entera fuera de la pantalla. Es la misma
      pieza que faltaba en el visor de PDF del 06-09, en el otro eje.
   🪤 Y ESTABA AVISADO: el 30-08 se quitaron las notificaciones de «Por carpeta»
   porque «en 300 px no cabe: se salía de la tarjeta». El celular es esa misma
   columna estrecha y allí no se volvió a mirar. Arreglada la pastilla, cabe en
   las dos.

   Y la forma cambia con el sitio: dejan de ser pastillas sueltas en una nube y
   pasan a ser FILAS, una por notificación, dentro de un `<details>` que se abre
   con un toque. Lo que separa lo tuyo de lo contrario es el filo izquierdo, no
   el borde entero: en una lista de filas el borde de color se lee mejor así.
   ============================================================ */
.tl-notis { margin-top: 8px; }
/* El resumen: la única línea que se ve sin abrir. Es un `<summary>`, así que
   abre y cierra sin una línea de JavaScript ni estado que mantener. */
.notis-resumen {
  display: flex; align-items: center; gap: 8px; cursor: pointer;
  font-size: 12px; color: var(--ink-2); line-height: 1.4;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: 6px 10px;
  list-style: none;   /* Firefox: quita el triángulo */
  transition: border-color var(--speed), background var(--speed);
}
.notis-resumen::-webkit-details-marker { display: none; }  /* y Safari */
.notis-resumen:hover { border-color: var(--gold); background: var(--gold-soft); }
.notis-resumen:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.notis-resumen .nr-ic { flex: none; font-size: 11px; color: var(--ink-3); }
.nr-txt { flex: 1 1 auto; min-width: 0; }
/* «Tu parte» es lo que se busca de un vistazo: va en el azul de la propia
   parte, el mismo del filo de su fila. */
.nr-tuya { font-weight: 700; color: var(--info-txt); }
.nr-cuenta { flex: none; font-size: 11px; font-weight: 700; color: var(--ink-3); font-variant-numeric: tabular-nums; }
/* 11 px, que es el suelo de la hoja: la flecha es pequeña, pero un icono a 10
   px en un teléfono ya no se distingue de una mota. Lo cazó
   `pruebas/la-escala-de-la-letra.test.js` en el mismo minuto en que se escribió. */
.nr-flecha { flex: none; font-size: 11px; color: var(--ink-3); transition: transform .16s var(--ease); }
.tl-notis[open] .nr-flecha { transform: rotate(180deg); }
.notis-detalle { display: flex; flex-direction: column; gap: 6px; margin-top: 6px; }
/* La fila. `flex-wrap` y `min-width: 0` son las dos piezas del arreglo de
   arriba: sin ellas vuelve a salirse por la derecha. */
.noti {
  display: flex; flex-wrap: wrap; align-items: center; gap: 4px 8px;
  width: 100%; min-width: 0; font-size: 11px; color: var(--ink-2);
  background: var(--paper); border: 1px solid var(--line);
  border-left: 3px solid var(--line-strong);
  border-radius: var(--r-sm); padding: 6px 10px; font-variant-numeric: tabular-nums;
}
.noti i { font-size: 11px; color: var(--ink-3); flex: none; }
.noti b { font-weight: 700; color: var(--ink); overflow-wrap: anywhere; }
.noti-cuando { color: var(--ink-3); }
.noti-rol { font-size: 11px; font-weight: 800; letter-spacing: .03em; text-transform: uppercase; padding: 0 6px; border-radius: 4px; background: var(--line); color: var(--ink-3); white-space: nowrap; }
/* 🎨 07-09 · Los dos lados dejan de estar escritos a mano. `#2563eb` era un
   azul suelto que nadie más usa y que en modo oscuro se queda en 3,0:1; ahora
   es el mismo `--info` de toda la app, con su versión clara en oscuro. */
.noti-nuestro { border-left-color: var(--senal-info); }
.noti-nuestro .noti-rol { background: color-mix(in srgb, var(--senal-info) 14%, transparent); color: var(--info-txt); }
.noti-nuestro i { color: var(--info-txt); }
/* Canal por el que salió: casilla electrónica o entrega física. Explica por
   qué la misma parte aparece dos veces sin que parezca un error. */
.noti-canal { font-size: 11px; font-weight: 700; letter-spacing: .03em; text-transform: uppercase; color: var(--ink-3); border: 1px solid var(--line); border-radius: 4px; padding: 0 4px; white-space: nowrap; }
/* Cuál de las varias fechas se toma para el cómputo. */
.noti-manda { border-left-width: 5px; }
.noti-manda-tag { font-size: 11px; font-weight: 800; letter-spacing: .03em; text-transform: uppercase; background: var(--ink); color: var(--bg); border-radius: 4px; padding: 1px 6px; white-space: nowrap; }
.noti-contrario { border-left-color: var(--gold); }
.noti-contrario .noti-rol { background: var(--gold-soft); color: var(--acento-txt); }
.noti-contrario i { color: var(--acento-txt); }.tl-aviso-notif { font-size: 11px; color: var(--ink-3); line-height: 1.6; margin: 16px 0 0; padding-top: 12px; border-top: 1px solid var(--line); }
.tl-aviso-notif i { color: var(--acento-txt); }
/* Previsión: cuándo debería notificarse una resolución que aún no lo está. */
/* 🪤 2026-08-11 — LA PREVISIÓN SALÍA PARTIDA EN COLUMNAS. Lo vio Piero en su
   Carpeta real: «Según el CEJ, se notificó a tu parte el | 25-09-2024 | . | Tu |
   cédula del SINOE | ha caído el | mismo día | …», cada trozo en su propia
   columna estrecha e ilegible.
   LA CAUSA no era el texto ni el ancho: era este `display: flex`. Un contenedor
   flex convierte en ÍTEM cada hijo, y aquí los hijos no son dos (icono + texto)
   sino DIECISÉIS: cada `<b>` y cada trozo de texto suelto entre etiquetas es su
   propio ítem, y flex los pone en fila. Se escribió pensando en dos hijos y el
   texto nunca se envolvió en nada.
   ⇒ El texto va dentro de un `<span>` (ver `_previsionCedula` y
   `_previsionNotificacion` en boveda.js) y aquí se blinda: si alguien vuelve a
   soltar texto suelto, `flex-wrap` y el `flex:1` del span evitan que la fila se
   parta en veinte columnas de una palabra. */
.tl-prevision { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 8px; margin-top: 8px; font-size: 11px; color: var(--ink-2); line-height: 1.55; background: var(--paper); border: 1px dashed var(--line-strong); border-radius: var(--r-sm); padding: 6px 10px; }
.tl-prevision > i { flex: 0 0 auto; color: var(--acento-txt); margin-top: 2px; }
.tl-prevision > span { flex: 1 1 200px; min-width: 0; }
/* La previsión de la CÉDULA es la que de verdad importa: con ella nace el
   plazo. Se marca en azul (el color del SINOE) y con más peso. */
.tl-prevision-cedula { border-style: solid; border-color: rgba(37,99,235,.45); background: rgba(37,99,235,.07); }
.tl-prevision-cedula i { color: #2563eb; }
.tl-prev-nota { display: block; margin-top: 4px; font-size: 11px; color: var(--ink-3); font-style: italic; }

/* ---- Zona de archivo: arrastrar, pegar o hacer clic ---- */
/* Compacta a propósito: el bloque gigante de antes ocupaba media pantalla
   para hacer lo que hace una línea. */
.zona-arch { display: flex; align-items: center; gap: 10px; padding: 10px 12px; border: 1px dashed var(--line-strong); border-radius: var(--r-sm); background: var(--paper); cursor: pointer; font-size: 12px; color: var(--ink-2); transition: border-color var(--speed), background var(--speed); }
.zona-arch:hover, .zona-arch:focus-visible { border-color: var(--gold); background: var(--gold-soft); outline: none; }
.zona-arch.drag-over { border-color: var(--gold); background: var(--gold-soft); border-style: solid; }
.zona-arch.con-archivo { border-style: solid; border-color: var(--success-txt); }
.zona-arch > i { color: var(--acento-txt); font-size: 13px; flex-shrink: 0; }
.zona-arch .za-txt { flex: 1; min-width: 0; line-height: 1.45; }
.zona-arch .za-txt b { color: var(--accent-ink); }
.zona-arch .za-file { font-size: 11px; font-weight: 700; color: var(--success-txt); max-width: 42%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.zona-arch-ia { margin-bottom: 12px; }
.tl-anio { position: relative; z-index: 1; display: inline-block; margin: 14px 0 4px 44px; font-size: 11px; font-weight: 800; letter-spacing: .08em; color: var(--ink-3); background: var(--bg); padding: 2px 8px; border: 1px solid var(--line); border-radius: var(--r-pastilla); }
.tl-anio:first-child { margin-top: 0; }
.tl-acts { display: flex; align-items: center; gap: 10px; padding-top: 12px; flex-shrink: 0; }
@media (max-width: 720px) {
  .tl-docs .tl-item { flex-wrap: wrap; }
  /* 🔑 07-09 · LA FILA DE BOTONES BAJA SIEMPRE, y ahora hay que DECIRLO.
     Bajaba sola por accidente: el ancho mínimo de la pastilla de notificación
     era tan grande que empujaba a «Ver» a la línea siguiente. Al arreglar el
     desborde (`min-width: 0` en `.tl-body`) ese empujón desapareció y los tres
     botones volvieron al lado del texto, dejándolo en 208 px de los 356 que hay.
     Con `flex-basis: 100%` la fila de botones ocupa su propia línea porque así
     se decide, no porque algo de al lado no quepa. El texto pasa de 208 a 310 px.
     🪤 Y el sangrado va en `padding`, no en `margin`: con `box-sizing: border-box`
     el padding vive DENTRO del 100% y el margen se le suma por fuera — medido,
     46 px de margen sacaban la fila 21 px de la pantalla. */
  .tl-acts { padding-top: 0; margin-left: 0; padding-left: 46px; flex-basis: 100%; }
}
.carpeta-vacia-msg { color: var(--ink-3); font-size: 13px; font-style: italic; padding: 16px; }
/* `.carpeta-vacio-card` se retiró el 11-08 con su elemento: ver la nota en
   app.html, donde estaba el cartel de «Selecciona un expediente». */
.add-act-btn { margin-left: auto; }

/* Modal "Nuevo expediente" */
.cm-overlay { display: none; position: fixed; inset: 0; z-index: 2000; background: rgba(8,16,25,.55); backdrop-filter: blur(4px); align-items: flex-start; justify-content: center; padding: 40px 20px; overflow-y: auto; }
.cm-panel { width: 100%; max-width: 660px; background: var(--bg); border: 1px solid var(--line-strong); border-radius: var(--r-lg); box-shadow: var(--shadow-3); overflow: hidden; animation: fadeUp 220ms var(--ease); }
.cm-head { display: flex; align-items: center; justify-content: space-between; padding: 14px 18px; background: var(--navy-900); color: #f3ecd8; font-size: 13px; font-weight: 700; }
.cm-head i { color: var(--gold); }
.cm-close { background: transparent; border: 0; color: rgba(243,236,216,.7); font-size: 15px; cursor: pointer; padding: 4px 8px; border-radius: var(--r-sm); transition: background var(--speed), color var(--speed); }
.cm-close:hover { background: rgba(255,255,255,.1); color: #fff; }
.cm-tabs { display: flex; gap: 4px; padding: 12px 16px 0; background: var(--card); border-bottom: 1px solid var(--line); }
.cm-tab { display: inline-flex; align-items: center; gap: 8px; font-family: var(--font-ui); font-size: 13px; font-weight: 700; color: var(--ink-3); background: transparent; border: 0; border-bottom: 2px solid transparent; padding: 10px 14px; margin-bottom: -1px; cursor: pointer; transition: color var(--speed), border-color var(--speed); }
.cm-tab:hover { color: var(--ink); }
.cm-tab.on { color: var(--acento-txt); border-bottom-color: var(--gold); }
.cm-body { padding: 18px; max-height: calc(88vh - 110px); overflow-y: auto; }
.cm-body .card { box-shadow: none; }

@media (max-width: 560px) {
  .docs-mono { grid-template-columns: 1fr; }
  .cnav-filtros { width: 100%; }
  .fhc-top { flex-direction: column; }
}

/* ============================================================
   KANBAN — Estado procesal
   ============================================================ */
.kanban-board {
  display: flex; gap: 14px; overflow-x: auto;
  padding: 4px 2px 18px; scroll-snap-type: x proximity;
}
.kanban-col {
  flex: 0 0 250px; scroll-snap-align: start;
  background: var(--paper); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 12px;
  min-height: 320px;
  transition: border-color var(--speed), background var(--speed);
}
.kanban-col.drag-over { border-color: var(--gold); background: var(--gold-soft); }
.kanban-header {
  font-size: 11px; font-weight: 700; letter-spacing: 0.8px;
  text-transform: uppercase; color: var(--ink-2);
  padding: 4px 6px 12px; border-bottom: 2px solid var(--gold);
  margin-bottom: 12px;
}
.kanban-card {
  background: var(--card); border: 1px solid var(--line);
  border-left: 3px solid var(--gold);
  border-radius: var(--r-sm); padding: 12px 14px; margin-bottom: 10px;
  cursor: grab; font-size: 13px;
  box-shadow: var(--shadow-1);
  transition: transform 140ms var(--ease), box-shadow var(--speed);
}
.kanban-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-2); }
.kanban-card:active { cursor: grabbing; }

/* ============================================================
   ESTADO PROCESAL v2 (Sección 3, 2026-07-21) — toolbar con chips
   de rama, buscador y Excel secundario; tarjetas semáforo (reusan
   el motor de urgencia de la Carpeta); riel de columnas vacías;
   menú "mover a etapa". Todo por tokens (modo oscuro se hereda).
   ============================================================ */
.kanban-toolbar-2 { display: flex; align-items: center; justify-content: space-between; gap: 14px 18px; flex-wrap: wrap; margin-bottom: 16px; }
.kt2-left { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; min-width: 0; }
.kt2-title { font-family: var(--font-ui); font-size: 15px; font-weight: 700; color: var(--ink); white-space: nowrap; }
.kt2-right { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

.kb-ramas { display: flex; gap: 6px; flex-wrap: wrap; }
.kb-rchip { font-family: var(--font-ui); font-size: 13px; font-weight: 600; padding: 6px 12px; border-radius: var(--r-pastilla); border: 1px solid var(--line-strong); background: var(--card); color: var(--ink-2); cursor: pointer; display: inline-flex; align-items: center; gap: 6px; transition: background var(--speed), color var(--speed), border-color var(--speed); }
.kb-rchip:hover { border-color: var(--gold); color: var(--ink); }
.kb-rchip .b { font-size: 11px; font-weight: 700; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.kb-rchip.on { background: var(--navy-900); color: #fff; border-color: var(--navy-900); }
.kb-rchip.on .b { color: var(--acento-claro); }  /* el chip activo va sobre navy: hace falta el tono claro (con --gold daba 2,52 en burdeos) */

.kb-search { display: inline-flex; align-items: center; gap: 8px; background: var(--card); border: 1px solid var(--line-strong); border-radius: var(--r-md); padding: 0 12px; height: 36px; }
.kb-search i { color: var(--ink-3); font-size: 13px; }
.kb-search input { border: none; background: transparent; outline: none; font-size: 13px; color: var(--ink); width: 190px; max-width: 42vw; padding: 0; }
.kb-search input::placeholder { color: var(--ink-3); }

/* 🪦 05-09-2026 · .kb-toggle y .kb-export SE RETIRAN CON SUS BOTONES.
   El interruptor era el SEGUNDO «Solo míos» (ahora hay uno solo, la pastilla
   .fchip del navegador) y el botón de Excel subió a la fila de acciones, donde
   usa .btn-repaso-cej como sus dos vecinos. Se borran en vez de dejarlos: una
   clase huérfana con buen aspecto acaba puesta en el sitio equivocado, que es
   justo lo que pasó con las dos barras de filtros. */

/* Tarjeta semáforo (sobre .kanban-card base) */
.kanban-card.kc { border-left-width: 4px; padding: 12px 14px; position: relative; }
.kc.s-venc { border-left-color: var(--danger-txt); }
.kc.s-hoy  { border-left-color: var(--warning-txt); }
.kc.s-aud  { border-left-color: var(--audiencia-txt); }
.kc.s-prox { border-left-color: var(--info-txt); }
.kc.s-ok   { border-left-color: var(--success-txt); }

.kc-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 6px; }
.kc-num { font-size: 11px; font-weight: 700; color: var(--ink-3); letter-spacing: .2px; font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kc-more { flex-shrink: 0; border: none; background: transparent; color: var(--ink-3); cursor: pointer; width: 22px; height: 22px; border-radius: var(--r-sm); font-size: 13px; display: inline-flex; align-items: center; justify-content: center; }
.kc-more:hover { background: var(--gold-soft); color: var(--acento-txt); }
.kc-cli { font-size: 13px; font-weight: 700; color: var(--ink); line-height: 1.25; margin-bottom: 8px; }

.kc-badge { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 700; padding: 4px 8px; border-radius: var(--r-sm); margin-bottom: 10px; font-variant-numeric: tabular-nums; }
.kc-badge i { font-size: 11px; }
.s-venc .kc-badge { background: var(--danger-bg); color: var(--danger-txt); }
.s-hoy  .kc-badge { background: var(--warning-bg); color: var(--warning-txt); }
/* Mismo arreglo que en `.st.aud` / `.st.prox`: ver la nota de allí. */
.s-aud  .kc-badge { background: color-mix(in srgb, var(--senal-audiencia) 12%, transparent); color: var(--audiencia-txt); }
.s-prox .kc-badge { background: color-mix(in srgb, var(--senal-info) 12%, transparent); color: var(--info-txt); }
.s-ok   .kc-badge { background: var(--success-bg); color: var(--success-txt); }

.kc-foot { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.kc-resp { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; color: var(--ink-3); min-width: 0; }
.kc-resp span:last-child { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.kc-av { width: 19px; height: 19px; border-radius: 50%; background: var(--navy-900); color: var(--accent-on-deep); font-size: 11px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
.kc-av.vacio { background: var(--line-strong); color: var(--ink-2); }
.kc-inst { font-size: 11px; font-weight: 700; background: var(--gold-soft); color: var(--acento-txt); padding: 1px 8px; border-radius: var(--r-md); flex-shrink: 0; }
/* Rama que dedujo el sistema (nadie la confirmó): subrayado punteado, para
   distinguirla de la que eligió el abogado sin gritarlo. */
/* Aviso «el CEJ no publica este expediente»: informa, no alarma. Por eso va
   en azul de información y no en rojo — no está roto, es que ahí no hay nada. */
/* 🔴 2026-08-04 — ESTE AVISO ERA ILEGIBLE, y de largo lo peor de la app.
   Vive SIEMPRE dentro de `.ficha-hero-carpeta` (fondo oscuro, cej.js:254) pero
   pintaba su texto con `--ink-2`, que es el gris OSCURO pensado para fondos
   claros. Medido sobre el n800 de cada paleta: 2.10 en dorado, 1.87 burdeos,
   1.80 púrpura, 1.72 azul, 1.71 cobre y **1.56 en esmeralda** — cuando el
   mínimo legible es 4.5. Prácticamente texto invisible, y justo en el aviso que
   explica por qué un expediente no se consulta en el CEJ.
   Ahora va en blanco azulado al 92%: 8.74:1 en el peor caso (esmeralda).
   El borde y el icono dejan de ser azul fijo —que chocaba con las paletas
   verde, burdeos y cobre— y siguen al acento de cada una. */
.fhc-nopub {
  display: flex; align-items: flex-start; gap: 10px; flex-wrap: wrap;
  margin: 12px 0 0; padding: 10px 12px;
  background: rgba(255,255,255,.07);
  border: 1px solid var(--accent-on-deep, #ecd9a6); border-radius: var(--r-md);
  font-size: 12px; line-height: 1.5; color: rgba(234,238,244,.92);
}
.fhc-nopub b { color: #fff; }
.fhc-nopub > i { color: var(--accent-on-deep, #ecd9a6); margin-top: 2px; flex-shrink: 0; }
.fhc-nopub > div { flex: 1; min-width: 200px; }
.fhc-nopub button { flex-shrink: 0; }

.kc-rama-deducida { border-bottom: 1px dotted currentColor; cursor: help; }

/* 🆕 05-09 · «SIN ETAPA» — la columna de lo que no consta.
   Va con la franja ÁMBAR en vez de la dorada de las demás y con el fondo
   rayado: no es una fase del proceso, es un hueco por rellenar, y tiene que
   distinguirse de un vistazo de las siete que sí lo son. Sin esto sería una
   columna más y el abogado la leería como «etapa: sin etapa», que es
   exactamente lo contrario de lo que dice. */
.kanban-col-sindato { border-style: dashed; background: transparent; }
.kanban-col-sindato .kanban-header { border-bottom-color: var(--warning); color: var(--warning-txt); }
/* De dónde sale la etapa cuando no la escribió nadie. Pequeña y sin fondo:
   es una nota al pie de la tarjeta, no una segunda etiqueta compitiendo con
   la de urgencia, que es la que tiene que saltar a la vista. */
.kc-etapa-nota {
  display: flex; align-items: center; gap: 5px;
  font-size: 11px; line-height: 1.3; color: var(--ink-3);
  margin: -4px 0 8px; cursor: help;
}
.kc-etapa-nota i { font-size: 10px; opacity: .85; }
.kc-etapa-nota.sin { color: var(--warning-txt); font-weight: 600; }
/* Punto de la materia: 7 px, pegado al nombre de la rama. Es lo más pequeño
   que se distingue de un vistazo sin convertir el tablero en un semáforo.
   El color sale de la misma tabla que la Carpeta (areas.js), así que un
   expediente se reconoce por su color en las dos pantallas. */
.kc-materia-punto {
  display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  margin-right: 5px; vertical-align: 1px; flex-shrink: 0;
}

/* Menú "mover a etapa" */
.kc-menu { position: absolute; top: 30px; right: 8px; z-index: 30; background: var(--card); border: 1px solid var(--line-strong); border-radius: var(--r-md); box-shadow: var(--shadow-3, 0 12px 30px rgba(13,27,42,.20)); padding: 6px; min-width: 190px; max-height: 262px; overflow-y: auto; }
.kc-menu-h { font-size: 11px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; color: var(--ink-3); padding: 4px 8px 6px; }
.kc-menu-it { display: block; width: 100%; text-align: left; border: none; background: transparent; color: var(--ink-2); font-size: 13px; padding: 8px 8px; border-radius: var(--r-sm); cursor: pointer; }
.kc-menu-it:hover { background: var(--gold-soft); color: var(--ink); }
.kc-menu-it.activo { color: var(--acento-txt); font-weight: 700; }

/* Riel de columnas vacías */
.kanban-rail { flex: 0 0 160px; display: flex; flex-direction: column; gap: 8px; padding-top: 30px; }
.kb-rail-cap { font-size: 11px; font-weight: 700; letter-spacing: .6px; text-transform: uppercase; color: var(--ink-3); padding: 0 2px 2px; }
.kb-rail-it { display: flex; align-items: center; justify-content: space-between; gap: 8px; background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--caja-compacta); font-size: 12px; color: var(--ink-3); opacity: .75; transition: opacity var(--speed), border-color var(--speed), background var(--speed); }
.kb-rail-it:hover { opacity: 1; }
.kb-rail-it.drag-over { border-color: var(--gold); background: var(--gold-soft); opacity: 1; }
.kb-rail-it b { font-weight: 700; font-variant-numeric: tabular-nums; }

/* Tablero vacío */
.kb-vacio { text-align: center; padding: 48px 20px; color: var(--ink-3); }
.kb-vacio i { font-size: 26px; color: var(--gold); opacity: .5; margin-bottom: 12px; display: block; }
.kb-vacio p { font-size: 13px; margin: 0; }

/* ============================================================
   MODAL — Ficha Judicial
   ============================================================ */
.modal-overlay {
  display: none; position: fixed; inset: 0; z-index: 2000;
  background: rgba(8, 16, 25, 0.55); backdrop-filter: blur(4px);
  align-items: center; justify-content: center; padding: 24px;
}
.modal-content {
  width: 100%; max-width: 880px; max-height: 90vh; overflow-y: auto;
  padding: 28px 30px; position: relative;
  animation: modalIn 260ms var(--ease);
}
@keyframes modalIn { from { opacity: 0; transform: translateY(14px) scale(0.98); } to { opacity: 1; transform: none; } }
.close-modal {
  position: absolute; top: 16px; right: 18px;
  font-size: 22px; color: var(--ink-3); cursor: pointer;
  transition: color var(--speed);
}
.close-modal:hover { color: var(--danger-txt); }
.modal-head {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 22px; border-bottom: 1px solid var(--line);
  padding-bottom: 14px; gap: 16px; flex-wrap: wrap;
}
.modal-head h3 {
  font-family: var(--font-display);
  color: var(--ink); font-size: 19px; font-weight: 700;
  display: flex; align-items: center; gap: 10px; margin: 0;
}
.modal-head h3 i { color: var(--gold); }
#btn-desbloquear-ficha {
  background: none; border: 1px solid var(--gold); color: var(--acento-txt);
  padding: 8px 14px; border-radius: var(--r-sm); font-weight: 700;
  font-size: 12px; margin-left: auto; cursor: pointer;
  display: flex; align-items: center; gap: 6px;
  transition: background var(--speed);
}
#btn-desbloquear-ficha:hover { background: var(--gold-soft); }
/* Comparador de versiones (diff por líneas) */
.diff-l { font-size: 13px; line-height: 1.5; padding: 2px 8px; border-radius: 4px; margin: 1px 0; color: var(--ink-2, var(--ink)); white-space: pre-wrap; word-break: break-word; }
.diff-l.diff-add { background: var(--success-bg); color: var(--success-txt); border-left: 3px solid var(--success); }
.diff-l.diff-del { background: rgba(200, 45, 45, 0.10); color: var(--danger-txt); border-left: 3px solid var(--danger); text-decoration: line-through; text-decoration-color: rgba(200, 45, 45, 0.6); }
/* Cuadro comparativo LADO A LADO (izquierda = antes · derecha = corregido).
   Lo comparten el comparador de versiones y la propuesta de cambio del Socio. */
.difs-tabla { width: 100%; border-collapse: collapse; table-layout: fixed; font-size: 13px; }
.difs-h {
  position: sticky; top: 0; z-index: 1;
  background: var(--card); color: var(--ink-3);
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px;
  text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--line-strong);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.difs-h + .difs-h { border-left: 1px solid var(--line); }
.difs-c {
  width: 50%; vertical-align: top; padding: 6px 10px;
  line-height: 1.55; color: var(--ink-2, var(--ink));
  white-space: pre-wrap; word-break: break-word;
  border-bottom: 1px solid var(--line);
}
.difs-c + .difs-c { border-left: 1px solid var(--line); }
.difs-igual { color: var(--ink-3); }
.difs-add { background: var(--success-bg); color: var(--success-txt); font-weight: 600; }
.difs-del { background: rgba(200, 45, 45, 0.10); color: var(--danger-txt); text-decoration: line-through; text-decoration-color: rgba(200, 45, 45, 0.55); }
.difs-vacia { background: repeating-linear-gradient(45deg, transparent, transparent 6px, var(--line) 6px, var(--line) 7px); opacity: .25; }
@media (max-width: 700px) { .difs-tabla { font-size: 12px; } .difs-c { padding: 4px 6px; } }
.modal-grid-datos {
  background: var(--paper); padding: 18px; border-radius: var(--r-md);
  border: 1px solid var(--line); margin-bottom: 18px;
}
.modal-actuacion-box {
  background: var(--card); padding: 18px; border-radius: var(--r-md);
  border: 1px solid var(--line); margin-bottom: 18px;
}
.modal-actuacion-box label { color: var(--acento-txt) !important; }
#modal-tarea { font-weight: 700; font-size: 15px; margin: 4px 0 0; color: var(--ink); }
#modal-fecha, #modal-hora { color: var(--danger-txt); font-size: 13px; font-weight: 700; margin: 4px 0 0; }
#modal-info-audiencia {
  display: none; margin-bottom: 18px; background: var(--warning-bg);
  padding: 14px 16px; border-left: 4px solid var(--audiencia);
  font-size: 13px; border-radius: 0 var(--r-sm) var(--r-sm) 0;
}
#modal-aud-modalidad { color: var(--audiencia-txt); font-weight: 700; }
#modal-anotacion {
  background: var(--paper); padding: 14px; border: 1px solid var(--line);
  border-radius: var(--r-sm); font-size: 13px; font-style: italic;
  min-height: 48px; color: var(--ink-2);
}
.proofs-container { border: 2px dashed var(--line-strong); padding: 14px; border-radius: var(--r-sm); background: var(--paper); margin-top: 8px; }
.timeline-box {
  background: var(--paper); padding: 14px; border-radius: var(--r-sm);
  border: 1px solid var(--line); max-height: 230px; overflow-y: auto;
}
#modal-timeline { list-style: none; padding-left: 12px; font-size: 12px; border-left: 2px solid var(--gold); margin: 0; line-height: 2.1; color: var(--ink-2); }
.modal-completar-box {
  margin-top: 18px; background: var(--paper); padding: 16px;
  border-radius: var(--r-sm); border: 1px solid var(--line);
}
.modal-completar-box .fila { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; gap: 10px; flex-wrap: wrap; }
.modal-completar-box .fila label { font-size: 12px; font-weight: 700; text-transform: uppercase; color: var(--ink-3); margin: 0; }
.modal-footer-actions {
  display: flex; gap: 10px; margin-top: 22px; padding-top: 18px;
  border-top: 1px solid var(--line); flex-wrap: wrap; align-items: center;
}
.modal-footer-actions .grupo-derecha { margin-left: auto; display: flex; gap: 8px; flex-wrap: wrap; }
.btn-sm { width: auto; padding: 10px 16px; font-size: 12px; display: inline-flex; min-height: 40px; }
.btn-danger { background: var(--danger); color: #fff; box-shadow: none; border: none; }
.btn-danger:hover { filter: brightness(1.1); }
/* Era #cf7027: con letra blanca daba 3,50:1 y es el botón de BORRAR una
   actuación — el que más claro tiene que verse antes de pulsarlo. #a04d15
   conserva el mismo naranja de aviso y sube a 5,89:1. */
.btn-warn { background: #a04d15; color: #fff; box-shadow: none; border: none; }
.btn-warn:hover { filter: brightness(1.1); }
.btn-success { background: var(--success); color: #fff; box-shadow: none; border: none; }
.btn-success:hover { filter: brightness(1.1); }

/* ---------- Visor ---------- */
#visor-overlay {
  display: none; position: fixed; inset: 0; z-index: 2500;
  background: rgba(8, 16, 25, 0.8); align-items: center; justify-content: center;
  /* El fondo oscuro tampoco encadena: si el dedo cae al lado del papel, no se
     lleva la Carpeta consigo. Ver `_visorFondoQuieto` en js/boveda.js. */
  overscroll-behavior: contain;
}
/* Con un documento abierto, la página de detrás se queda quieta. Lo pone y lo
   quita `_visorFondoQuieto`, en un solo sitio. */
body.visor-abierto { overflow: hidden; }
.visor-close {
  position: absolute; top: 18px; right: 26px; color: #fff;
  font-size: 26px; cursor: pointer; z-index: 10;
}
.visor-panel {
  padding: 16px; border-radius: var(--r-lg); width: 90%; max-width: 920px;
  height: 86vh; display: flex; flex-direction: row; gap: 14px;
}
/* La columna del documento. Es EXACTAMENTE lo que era el panel entero antes de
   que existiera el costado, y por eso conserva `flex-direction: column`: dentro
   siguen viviendo la cabecera y los cuatro cuerpos con su `flex: 1`.
   `min-width: 0` no es adorno: sin él, el iframe del PDF impone su ancho mínimo
   y empuja la lista fuera del panel. */
/* 🔴 06-09-2026 · `min-height: 0` — POR ESTO NO SE DESLIZABA EL PDF.
   Piero: *«en vez de deslizarse el PDF se desliza lo que hay detrás»*. Medido en
   el banco a 375 px, con las 6 hojas pintadas:

       panel .............  696 px  (86vh)
       .visor-main ....... 1279 px  ← se sale 583 px de su propio panel
       #visor-hojas ...... 1182 px de alto y 1182 de contenido
       ⇒ scrollHeight === clientHeight: NO HAY NADA QUE DESLIZAR DENTRO

   En una columna flex, un ítem con `flex: 1` **nunca encoge por debajo de su
   contenido** mientras no se le diga `min-height: 0`. Así que el hueco del
   documento crecía hasta la altura de las seis hojas en vez de quedarse en el
   alto del panel, el desbordamiento interno no llegaba a existir, y el dedo
   arrastraba lo único que sí desbordaba: la página de detrás.

   🪤 Y LA TRAMPA ES QUE YA ESTABA AVISADA, EN EL OTRO EJE: ahí al lado dice
   «`min-width: 0` no es adorno». Es la misma regla del mismo `flex`, escrita
   para el ancho y no para el alto. Cuando arregles un eje, mira el otro.
   🔑 Va en `.visor-main` y cura de una vez los CUATRO cuerpos que cuelgan de
   ella con `flex:1` —las hojas del PDF, el `<iframe>`, el texto y el Word—, no
   sólo el que se señaló. */
.visor-main { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; }

/* EL COSTADO DEL VISOR: la lista de documentos del expediente (2026-08-11).
   Oculto por defecto y encendido SOLO por `.con-lista`, que pone boveda.js
   cuando el visor se abre desde la Carpeta y hay al menos dos documentos. El
   visor tiene otras dos puertas (archivo de una actuación, medio probatorio)
   que llegan sin expediente detrás: ahí no debe aparecer un hueco vacío. */
.visor-lista { display: none; }
.visor-panel.con-lista { max-width: 1220px; }
.visor-panel.con-lista .visor-lista {
  display: block; width: 268px; flex: none; overflow-y: auto;
  border-right: 1px solid var(--line); padding-right: 12px;
}
.vl-h { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-3); padding: 2px 4px 8px; }
.vl-cua { display: flex; align-items: center; gap: 7px; font-size: 11px; font-weight: 800; color: var(--ink-2); margin: 12px 0 6px; padding: 0 4px; }
.vl-cat { display: flex; align-items: center; gap: 7px; font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-2); margin: 12px 0 6px; padding: 0 4px; }
.vl-cat i { color: var(--acento-txt); font-size: 12px; }
.vl-doc { display: flex; align-items: flex-start; gap: 9px; background: var(--card); border: 1px solid var(--line); border-left: 3px solid transparent; border-radius: var(--r-sm); padding: 7px 9px; margin-bottom: 5px; cursor: pointer; }
.vl-doc:hover { border-color: var(--gold); }
.vl-doc:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
/* El que se está mirando. Lo que lo marca es la RAYA dorada del costado
   izquierdo, no el color del texto: los colores de texto son de donde salieron
   los problemas de contraste, así que aquí no se toca ninguno. */
.vl-doc.actual { background: var(--paper); border-color: var(--gold); border-left-color: var(--gold); }
.vl-fi { color: var(--acento-txt); font-size: 13px; flex: none; margin-top: 2px; }
.vl-doc-main { min-width: 0; flex: 1; }
.vl-doc-tit { display: block; font-size: 12px; font-weight: 600; color: var(--ink); word-break: break-word; }

.visor-top { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: 10px; gap: 10px; }
/* El nombre del papel y su expediente, uno encima del otro. En el escritorio
   caben en una línea de sobra; en el celular el número baja solo y se lee
   entero — que era lo que se perdía cuando iban pegados con un guión. */
.visor-ident { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
/* Hasta DOS renglones antes de cortar. Medido a 375 px: en una sola línea,
   «Completo (copia de trabajo) — ADJUNTA CONSTANCIA DE SEGUNDO DEPÓSITO…» se
   quedaba en «Completo (copia de trab…», que no distingue un papel de otro. */
#visor-title {
  color: var(--ink); font-size: 13px; min-width: 0; line-height: 1.35;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
/* 🆕 09-09-2026 · LA BARRA DE HERRAMIENTAS DEL PAPEL (Imprimir · Descargar ·
   zoom). Vino de una queja de Piero: al dejar de meter el PDF en un <iframe>
   —para que el iPhone no enseñara sólo la primera hoja— se fue con él la barra
   del navegador, que era de donde salían descargar e imprimir.
   El zoom va a la IZQUIERDA y con la letra pequeña porque es un ajuste de
   lectura; las dos acciones que sacan el papel del sistema van a la derecha, y
   el botón macizo sigue siendo uno solo. */
.visor-zoom {
  display: inline-flex; align-items: center; gap: 2px;
  border: 1px solid var(--line-strong, var(--line)); border-radius: var(--r-sm);
  padding: 2px; background: var(--card);
}
.visor-zoom > span {
  min-width: 46px; text-align: center; font-size: 11px; font-weight: 700;
  color: var(--ink-2); font-variant-numeric: tabular-nums;
}
.visor-tool {
  width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center;
  background: transparent; border: none; border-radius: var(--r-sm);
  color: var(--ink-2); font-size: 12px; cursor: pointer; padding: 0; min-height: 0;
}
.visor-tool:hover { background: var(--paper); color: var(--acento-txt); }
.visor-tool:focus-visible { outline: 2px solid var(--gold); outline-offset: 1px; }
/* Ampliada, la hoja es MÁS ANCHA que su hueco: sin esto no hay forma de llegar
   al margen derecho de una cédula al 200 %, que es justo para lo que se amplía. */
#visor-hojas.con-zoom { overflow-x: auto; }
#visor-hojas.con-zoom .visor-hoja { max-width: none; }

/* En el celular la acción baja debajo del nombre y ocupa el ancho: arriba se
   comía media cabecera y cortaba justo el número de expediente, que es el dato
   que Piero pidió ver aquí.
   🆕 09-09 · Con tres controles ya no vale «cada botón al 100 %»: serían tres
   franjas y la cabecera se comería la pantalla del teléfono. Se reparten la
   fila y sólo saltan de línea si de verdad no caben. */
@media (max-width: 700px) {
  .visor-top { flex-direction: column; align-items: stretch; gap: 8px; }
  .visor-acciones { flex-wrap: wrap; }
  .visor-acciones .btn-sm { flex: 1 1 auto; justify-content: center; }
  .visor-zoom { flex: 0 0 auto; }
}
.visor-exp {
  font-family: 'SF Mono', ui-monospace, 'Cascadia Mono', Menlo, Consolas, monospace;
  font-size: 11px; letter-spacing: .02em; color: var(--ink-3); white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.visor-acciones { display: flex; gap: 8px; flex-shrink: 0; }
#visor-frame { width: 100%; flex: 1; border: 1px solid var(--line); border-radius: var(--r-sm); background: #fff; }
/* ---- Las hojas del PDF, pintadas por pdf.js (06-09-2026) ----
   Ver `_visorPintarHojas` en js/boveda.js: Safari de iOS sólo enseña la
   primera página de un PDF metido en un <iframe>, y no lo dice. */
#visor-hojas {
  flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden;
  /* Que el arrastre NO se encadene con la página de detrás al llegar al final
     de la última hoja: sin esto, el gesto sigue y la Carpeta se mueve debajo
     del documento abierto. */
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 10px;
}
.visor-hoja { position: relative; margin: 0 auto 12px; background: #fff; box-shadow: var(--shadow-1); border-radius: 2px; overflow: hidden; }
.visor-hoja:last-child { margin-bottom: 0; }
.visor-hoja canvas { display: block; width: 100%; height: auto; }
/* El número de hoja va DENTRO del papel y en pequeño: es una ayuda para saber
   por dónde vas y cuánto queda, no un elemento de la resolución. */
.visor-hoja-n {
  position: absolute; right: 8px; bottom: 6px; padding: 2px 7px; border-radius: 999px;
  font-size: 11px; font-weight: 700; letter-spacing: .03em;
  color: var(--ink-2); background: rgba(255, 255, 255, .88); border: 1px solid var(--line);
}
.visor-hoja-mal { padding: 22px 16px; text-align: center; font-size: 12px; color: var(--warning-txt); }
/* El aviso de cuando el PDF lo pinta el navegador y puede quedarse en la
   primera hoja. Va PEGADO al documento, que es donde se mira. */
.visor-nota {
  margin-bottom: 8px; padding: 8px 11px; font-size: 12px; line-height: 1.5;
  color: var(--warning-txt); background: var(--warning-bg);
  border: 1px solid var(--warning-txt); border-radius: var(--r-sm);
}
.visor-nota i { margin-right: 6px; }
/* En el móvil el costado no cabe al lado del PDF: se pliega ARRIBA, con su
   propio desplazamiento, en vez de desaparecer —que dejaría al abogado del
   teléfono con el problema que este panel viene a resolver—. */
@media (max-width: 680px) {
  .visor-panel { flex-direction: column; gap: 10px; }
  .visor-panel.con-lista .visor-lista {
    width: auto; max-height: 124px; padding-right: 0; padding-bottom: 8px;
    border-right: none; border-bottom: 1px solid var(--line);
  }
}
/* Word (.docx) convertido a HTML: apariencia de documento legal */
#visor-doc { color: #1a1a1a; font-family: 'Times New Roman', Georgia, serif; font-size: 14px; line-height: 1.8; }
#visor-doc p { margin: 0 0 10px; text-align: justify; }
#visor-doc h1, #visor-doc h2, #visor-doc h3 { font-family: 'Playfair Display', Georgia, serif; color: #0d1b2a; margin: 18px 0 8px; }
#visor-doc table { border-collapse: collapse; width: 100%; margin: 12px 0; }
#visor-doc td, #visor-doc th { border: 1px solid #b8b8b8; padding: 6px 10px; }
#visor-doc img { max-width: 100%; height: auto; }
/* Editor Jurídico — barra de formato del borrador */
#redactor-toolbar { display: flex; }
.red-tool {
  width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center;
  background: var(--card); border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  color: var(--ink-3); font-size: 13px; cursor: pointer;
  transition: background var(--speed), color var(--speed), border-color var(--speed);
}
.red-tool:hover { border-color: var(--gold); color: var(--acento-txt); background: var(--gold-soft); }
/* El separador respira más que el hueco entre botones: si mide lo mismo, deja
   de separar grupos y sólo añade ruido. Botones a 6 px, separador a 6+6. */
.red-sep { width: 1px; height: 22px; background: var(--line-strong); margin: 0 6px; }
#redactor-resultado.editable { cursor: text; outline: none; }

/* ---- Editor Jurídico: sección de página completa ---- */
.editor-layout { display: flex; gap: 18px; align-items: flex-start; }
.editor-side { width: 330px; flex-shrink: 0; }
.editor-side .card { position: sticky; top: 12px; }
.editor-main { flex: 1; min-width: 0; }
.editor-bar { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.editor-actions { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }

/* ---- El Redactor CON el Socio al lado ----
   Al abrir el Socio dentro del Redactor, el panel de herramientas se pliega:
   si no, pelean por el ancho el menú, el panel, la hoja A4 y el chat, y la hoja
   se parte. Vuelve solo al cerrar el Socio (lo hace `sincronizarRedactorSocio`). */
body.editor-plegado .editor-side { display: none; }
/* Aviso que sustituye a la casilla de "pídele un cambio": un solo camino. */
#redactor-derivar-socio {
  font-size: 12.5px; line-height: 1.5; color: var(--ink-2);
  background: rgba(197, 160, 89, .08); border: 1px solid rgba(197, 160, 89, .3);
  border-radius: var(--r-sm); padding: 10px 12px; margin-bottom: 4px;
}

/* ===== EDITOR JURÍDICO v2 (Sección 5): divulgación progresiva + exportación tokenizada ===== */
/* Herramientas avanzadas en acordeón nativo */
.ed-adv { display: flex; flex-direction: column; gap: 6px; margin-top: 14px; }
.ed-acc { border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--paper); overflow: hidden; }
.ed-acc > summary { list-style: none; cursor: pointer; padding: 10px 12px; font-size: 12px; font-weight: 700; color: var(--ink-2); display: flex; align-items: center; gap: 8px; user-select: none; }
.ed-acc > summary::-webkit-details-marker { display: none; }
.ed-acc > summary i { color: var(--acento-txt); }
.ed-acc > summary::after { content: "\203A"; margin-left: auto; color: var(--ink-3); font-size: 14px; transition: transform .15s ease; }
.ed-acc[open] > summary::after { transform: rotate(90deg); }
.ed-acc > summary:hover { color: var(--ink); }
.ed-acc-body { padding: 0 12px 12px; }

/* ============================================================
   «EN QUÉ SE BASA ESTE ESCRITO» — los documentos de la Carpeta
   ------------------------------------------------------------
   🪤 POR QUÉ ESTO ES CSS Y NO ESTILO EN LÍNEA, y la trampa que costó.
   La primera versión pintaba las filas con `style="…"` y salió ROTA en
   producción: filas vacías, la casilla flotando en el centro y una barra de
   desplazamiento horizontal. La causa no estaba en la fila sino en la regla
   GLOBAL de arriba —`input, select, textarea { width:100%; padding:10px 12px;
   border; border-radius; background }`—, que también pilla a las casillas.
   Lo que se veía como «rectángulos redondeados vacíos» ERAN las casillas
   infladas al ancho completo, con el título empujado fuera de la caja.
   Y lo peor: esta misma trampa YA ESTABA DOCUMENTADA en `.val-check`, unas
   3.000 líneas más abajo. Se cayó dos veces en el mismo sitio.
   ⇒ Toda casilla nueva de la app necesita su regla de tamaño, o la global se
   la come. No se puede confiar en `flex:none`: eso fija el crecimiento, no el
   ancho.
   ============================================================ */
/* Los DOS selectores comparten regla, no una copia: el del Redactor y el del
   chat del Socio son el mismo control en dos sitios, y una segunda regla se
   habría quedado atrás el día que se toque esta (que ya se ha tocado dos veces
   por fallos vistos en producción). */
#redactor-base-lista, #socio-base-lista {
  display: flex; flex-direction: column; gap: 6px;
  max-height: 220px; overflow-y: auto;
  /* Nunca una barra horizontal: si un título se pasa de largo, se recorta con
     puntos suspensivos (abajo), no se empuja la caja. */
  overflow-x: hidden;
}
/* En el chat el sitio es más estrecho y hay menos alto útil: la lista se queda
   más baja para que no se coma la conversación. */
#socio-base-lista { max-height: 160px; }
#socio-base-acc { margin: 0 16px 6px; }   /* los 16px del panel del Socio */
#socio-base-acc > summary {
  cursor: pointer; font-size: 11.5px; color: var(--ink-2); font-weight: 600;
  padding: 5px 8px; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--paper); list-style: none; display: flex; align-items: center; gap: 6px;
}
#socio-base-acc > summary::-webkit-details-marker { display: none; }
#socio-base-acc > summary:hover { border-color: var(--gold); }
#socio-base-cuerpo { padding: 8px 2px 0; }
#socio-base-resumen { font-size: 11px; color: var(--ink-3); margin: 6px 0 0; line-height: 1.4; }
.base-doc {
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; background: var(--paper);
  border: 1px solid var(--line); border-radius: 6px;
  padding: 6px 8px; cursor: pointer;
  /* Un elemento flex no baja de su contenido salvo que se le diga. Sin esto,
     un título largo ensancha la fila y con ella toda la lista. */
  min-width: 0;
}
.base-doc.puesto { border-color: var(--gold); }
.base-doc.off { opacity: .5; cursor: default; }
.base-doc input[type="checkbox"] {
  width: 16px; height: 16px; min-width: 16px; flex: 0 0 16px;
  margin: 0; padding: 0; border-radius: 4px;
  accent-color: var(--acento-txt); cursor: pointer;
}
.base-doc.off input[type="checkbox"] { cursor: default; }
.base-doc-tit { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.base-doc-meta { font-size: 11px; color: var(--ink-3); white-space: nowrap; flex: none; }
.base-doc-pie { font-size: 11px; color: var(--ink-3); margin: 2px 0 0; line-height: 1.4; }
/* ============================================================
   ANTES DE GENERAR — la línea de estado encima del botón (2026-08-09)
   El aspecto vive AQUÍ y no en la plantilla de JS: en línea ya se coló una
   fila rota en producción (ver .base-doc y .val-check).
   Los tres tonos son los mismos tokens que usa el panel de Confiabilidad, para
   que «ámbar = ojo con esto» signifique lo mismo antes y después de generar.
   ============================================================ */
.prep-linea {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 8px;
  font-size: 11.5px; line-height: 1.45; color: var(--ink-2);
  background: var(--paper); border: 1px solid var(--line);
  border-left: 3px solid var(--line-strong, var(--line));
  border-radius: var(--r-sm); padding: 8px 10px; margin: 10px 0 8px;
  /* Un tipo de escrito largo no puede ensanchar el panel del Editor. */
  min-width: 0;
}
.prep-linea > i { flex: none; color: var(--ink-3); position: relative; top: 1px; }
.prep-txt { flex: 1 1 220px; min-width: 0; }
.prep-enlaces { display: flex; flex-wrap: wrap; gap: 10px; flex: none; }
/* Enlaces de verdad: son <button> porque no navegan a ninguna parte (abren un
   acordeón), pero no deben parecer botones ni heredar el ancho de los del
   formulario. */
.prep-link {
  background: none; border: 0; padding: 0; margin: 0; width: auto;
  font-family: var(--font-ui); font-size: 11.5px; font-weight: 600;
  color: var(--acento-txt); cursor: pointer;
  border-bottom: 1px solid transparent;
}
.prep-link:hover, .prep-link:focus-visible { border-bottom-color: currentColor; }
/* `.prep-apagado` no lleva regla y es a propósito: es el estado NORMAL, o sea
   `.prep-linea` a secas. Va en el marcado igual que los otros dos para que el
   estado se lea en el DOM al depurar, no para pintar nada. */
.prep-warn { border-left-color: var(--warning-txt); background: var(--warning-bg); }
.prep-warn > i { color: var(--warning-txt); }
.prep-ok { border-left-color: var(--success-txt); }
.prep-ok > i { color: var(--success-txt); }
/* ============================================================
   LA PREGUNTA DE LA CUANTÍA — el arancel, antes de escribir (2026-08-11)
   Se pinta DENTRO de `#redactor-resultado`, en el sitio del folio, y no en una
   pantalla nueva: es un paso del mismo acto, no otro sitio al que ir.
   🪤 LOS RADIOS LLEVAN ANCHO PROPIO, Y NO ES ADORNO. La regla global
   `input { width:100% }` de este archivo también pilla a los `radio` y a los
   `checkbox`: ya se comió las casillas del selector de documentos DOS veces
   (los «rectángulos vacíos» que se veían en pantalla ERAN las casillas). Misma
   defensa que en `.base-doc input[type="checkbox"]`; si se toca una, mirar la
   otra.
   ============================================================ */
.arn-caja {
  border: 1px solid var(--line); border-left: 3px solid var(--gold);
  border-radius: var(--r-sm); background: var(--paper);
  padding: 14px 16px; margin: 0; min-width: 0;
}
.arn-tit { font-size: 14px; font-weight: 800; color: var(--ink); display: flex; align-items: center; gap: 8px; }
.arn-tit > i { color: var(--acento-txt); }
/* 📨 2026-08-11 — DOS PREGUNTAS, DOS BLOQUES. El arancel del recurso y las
   cédulas de notificación son dos tasas, con dos códigos y dos anexos. Seguidas
   en la misma lista invitaban a contestar la segunda pensando en la primera.
   El separador es una línea, no una caja dentro de otra caja: anidar marcos
   hace que el panel parezca un formulario y esto son dos preguntas. */
.arn-bloque + .arn-bloque { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--line); }
.arn-bloque-tit {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
  color: var(--ink-3); display: flex; align-items: center; gap: 7px;
}
.arn-bloque-tit > i { color: var(--acento-txt); }
.arn-sub { font-size: 12.5px; line-height: 1.5; color: var(--ink-2); margin: 6px 0 0; }
.arn-nota { font-size: 11px; line-height: 1.45; color: var(--ink-3); margin: 8px 0 0; }
.arn-lista { display: flex; flex-direction: column; gap: 6px; margin-top: 12px; }
.arn-op {
  display: flex; align-items: flex-start; gap: 10px;
  border: 1px solid var(--line); border-radius: 6px;
  padding: 8px 10px; cursor: pointer; min-width: 0;
  background: var(--bg, transparent);
}
.arn-op:hover { border-color: var(--gold); }
.arn-op input[type="radio"] {
  width: 16px; height: 16px; min-width: 16px; flex: 0 0 16px;
  margin: 2px 0 0; padding: 0; accent-color: var(--acento-txt); cursor: pointer;
}
.arn-op:has(input:checked) { border-color: var(--gold); }
.arn-cuerpo { display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; min-width: 0; }
.arn-monto { font-size: 13px; font-weight: 700; color: var(--ink); }
/* La cita puede ser larga: se deja partir en varias líneas, nunca ensanchar. */
.arn-cita { font-size: 11.5px; line-height: 1.45; color: var(--ink-2); overflow-wrap: anywhere; }
.arn-meta { font-size: 11px; color: var(--ink-3); }
.arn-marca {
  font-size: 11px; font-weight: 600; color: var(--success-txt);
  border: 1px solid currentColor; border-radius: 999px; padding: 1px 6px;
  vertical-align: middle; white-space: nowrap;
}
.arn-marca-off { color: var(--ink-3); }
/* La casilla de «Otro monto» sí quiere el ancho de la fila, pero no el 100% del
   panel: va dentro de un flex con `min-width:0`, así que se le da su propio
   máximo para que no empuje. */
.arn-otro { width: 100%; max-width: 260px; margin-top: 4px; font-size: 12.5px; padding: 5px 8px; }
.arn-red {
  display: flex; align-items: flex-start; gap: 10px; margin-top: 12px;
  font-size: 12px; line-height: 1.45; color: var(--ink-2); cursor: pointer; min-width: 0;
}
.arn-red input[type="checkbox"] {
  width: 16px; height: 16px; min-width: 16px; flex: 0 0 16px;
  margin: 2px 0 0; padding: 0; border-radius: 4px; accent-color: var(--acento-txt); cursor: pointer;
}
.arn-pie { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
/* `.btn-gold` nace con `width:100%` (es el botón de un formulario en columna).
   Aquí son DOS acciones en una fila: sin esto se apilarían una debajo de otra y
   la salida de «no decidirlo» quedaría con el mismo peso visual que la de
   decidirlo. `.btn-inline` ya lo hace en el resto de la app; se repite el
   `flex:0 0 auto` porque dentro de un flex el ancho automático no basta. */
.arn-pie > .btn-gold { flex: 0 0 auto; }
/* Botones de la barra del folio (tokenizados: sin azul/rojo sueltos) */
/* `.ed-btn-ghost` se unificó el 03-09-2026 con `.an-btn-ghost` y `.btn-ghost`:
   la regla está arriba, junto a `.btn-ghost`. Aquí no queda nada. */
.ed-btn-gold { background: transparent; color: var(--acento-txt); border: 1px solid var(--gold); box-shadow: none; }
/* Menús desplegables (Descargar / Formato) con <details> */
.ed-menu { position: relative; }
.ed-menu > summary.ed-menu-btn { list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; font-family: var(--font-ui); font-size: 13px; font-weight: 600; color: var(--ink-2); background: transparent; border: 1px solid var(--line-strong, var(--line)); border-radius: var(--r-sm); padding: 8px 12px; user-select: none; }
.ed-menu > summary.ed-menu-btn::-webkit-details-marker { display: none; }
.ed-menu > summary.ed-menu-btn::after { content: "\25BE"; color: var(--ink-3); font-size: 11px; }
.ed-menu > summary.ed-menu-btn:hover { border-color: var(--gold); color: var(--acento-txt); }
.ed-menu[open] > summary.ed-menu-btn { border-color: var(--gold); color: var(--acento-txt); }
.ed-menu-panel { position: absolute; right: 0; top: calc(100% + 6px); z-index: 40; min-width: 190px; background: var(--card); border: 1px solid var(--line); border-radius: var(--r-sm); box-shadow: 0 12px 30px rgba(0,0,0,.18); padding: 8px; display: flex; flex-direction: column; gap: 6px; }
.ed-menu-item { display: flex; align-items: center; gap: 8px; width: 100%; justify-content: flex-start; text-align: left; background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 8px 10px; font-size: 12px; font-weight: 600; color: var(--ink); cursor: pointer; }
.ed-menu-item:hover { border-color: var(--gold); background: var(--gold-soft); }
/* Item del menú que está ACTIVO (p. ej. la marca de agua encendida). */
.ed-menu-item.ed-menu-item-on { border-color: var(--gold); color: var(--acento-txt); background: var(--gold-soft); }
/* «recomendado» junto a Justificado. Va al final de la fila y en tono menor:
   informa, no compite con el nombre de la opción. */
.ed-menu-nota { margin-left: auto; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .3px; color: var(--acento-txt); }
/* El desplegable de alineación vive DENTRO de la barra de formato, no en la de
   acciones: se le da el tamaño de un `.red-tool` para que no rompa la fila, y
   el panel se abre hacia la izquierda porque el botón queda a media barra. */
.red-menu > summary.red-tool-menu { padding: 7px 9px; font-size: 13px; }
.red-menu .ed-menu-panel { right: auto; left: 0; min-width: 210px; }

/* ===== FACTURACIÓN v2 (Sección 6): KPIs, tabular-nums, badges tokenizados, borrado en menú ===== */
.money { font-variant-numeric: tabular-nums; }
.fac-kpis { display: flex; gap: 12px; margin-bottom: 18px; flex-wrap: wrap; }
.fac-kpi { flex: 1; min-width: 150px; background: var(--card); border: 1px solid var(--line); border-radius: var(--r-md); padding: 12px 14px; }
.fac-kpi .k-n { font-size: 11px; text-transform: uppercase; letter-spacing: .5px; color: var(--ink-3); font-weight: 700; }
.fac-kpi .k-v { font-size: 17px; font-weight: 800; color: var(--ink); margin-top: 4px; }
.fac-kpi.hero { border-color: var(--gold); background: var(--gold-soft); }
.fac-kpi.hero .k-v { color: var(--acento-txt); font-size: 22px; }
.fac-kpi.venc .k-v { color: var(--danger-txt); }
.fac-row { display: flex; align-items: center; gap: 10px; background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 10px 12px; }
.fac-row-main { flex: 1; min-width: 0; }
.fac-row-t { font-weight: 700; color: var(--ink); font-size: 13px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.fac-row-s { font-size: 12px; color: var(--ink-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fac-badge { font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: var(--r-md); white-space: nowrap; }
.fac-badge.pag { background: color-mix(in srgb, var(--success) 14%, transparent); color: var(--success-txt); }
.fac-badge.pen { background: var(--gold-soft); color: var(--acento-txt); }
.fac-badge.venc { background: color-mix(in srgb, var(--danger) 12%, transparent); color: var(--danger-txt); }
.fac-kebab { position: relative; }
.fac-kebab > summary { list-style: none; cursor: pointer; width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center; border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--card); color: var(--ink-3); font-size: 13px; user-select: none; }
.fac-kebab > summary::-webkit-details-marker { display: none; }
.fac-kebab > summary:hover { border-color: var(--gold); color: var(--acento-txt); }
.fac-kebab-panel { position: absolute; right: 0; top: calc(100% + 6px); z-index: 40; min-width: 176px; background: var(--card); border: 1px solid var(--line); border-radius: var(--r-sm); box-shadow: 0 12px 30px rgba(0,0,0,.18); padding: 6px; }
.fac-kebab-item { display: flex; align-items: center; gap: 8px; width: 100%; justify-content: flex-start; text-align: left; background: transparent; border: none; border-radius: 5px; padding: 8px 10px; font-size: 13px; font-weight: 600; color: var(--ink); cursor: pointer; }
.fac-kebab-item:hover { background: var(--paper); }
.fac-kebab-item.danger { color: var(--danger-txt); }
.fac-vacio { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 28px 12px; color: var(--ink-3); }
.fac-vacio i { font-size: 22px; color: var(--gold); opacity: .5; margin-bottom: 10px; }

/* ---- Recordatorio de SUNAT (aparece bajo la proforma recién cobrada) ----
   Va PEGADO a su fila, dentro del mismo bloque, porque el aviso vive junto al
   control que se pulsó y no como nota al final de la lista. No guarda nada:
   el comprobante no se puede emitir desde aquí (ver el comentario largo en
   `app.js`), así que lo único que hace es dejar los datos listos para pegar. */
.fac-bloque { display: flex; flex-direction: column; gap: 6px; }
.fac-sunat { background: var(--gold-soft); border: 1px solid var(--gold); border-radius: var(--r-sm); padding: 12px 14px; }
.fac-sunat-t { display: flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 800; color: var(--acento-txt); margin-bottom: 9px; }
.fac-sunat-t .cerrar { margin-left: auto; background: transparent; border: none; color: var(--ink-3); cursor: pointer; font-size: 13px; padding: 2px 4px; width: auto; }
.fac-sunat-t .cerrar:hover { color: var(--ink); }
.fac-sunat-datos { display: flex; flex-direction: column; gap: 6px; }
.fac-sunat-dato { display: flex; align-items: flex-start; gap: 8px; background: var(--card); border: 1px solid var(--line); border-radius: 5px; padding: 6px 8px; font-size: 12.5px; }
.fac-sunat-dato .et { color: var(--ink-3); font-weight: 700; flex: 0 0 auto; min-width: 78px; padding-top: 1px; }
.fac-sunat-dato .vl { color: var(--ink); flex: 1; min-width: 0; white-space: normal; overflow-wrap: anywhere; line-height: 1.4; }
.fac-sunat-pie { display: flex; align-items: center; gap: 10px; margin-top: 11px; flex-wrap: wrap; }
.fac-sunat-nota { flex: 1; min-width: 190px; font-size: 11.5px; color: var(--ink-3); line-height: 1.45; }
.editor-sheet-wrap {
  background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-sm);
  /* `dvh` en vez de `vh`: en el navegador del iPhone la barra de direcciones
     aparece y desaparece, y con `vh` el alto se calcula con la pantalla
     entera → el final del cuadro queda fuera. `vh` se deja de respaldo para
     los navegadores que no entiendan `dvh`. */
  padding: 20px 18px 48px; max-height: calc(100vh - 120px); max-height: calc(100dvh - 120px);
  min-height: 70vh; overflow: auto;
}
/* ZOOM DE LA HOJA (como el de un procesador de textos): la hoja sigue midiendo
   A4 —lo que se guarda, imprime y exporta no cambia—, solo se ve más chica para
   que quepa entera junto al Socio. Se aplica DENTRO de la caja, así el clon que
   se usa al exportar (que vive fuera) nunca hereda el zoom. */
.editor-sheet-wrap > .editor-sheet { zoom: var(--folio-zoom, 1); }
/* HOJA A4 REAL: 21cm de ancho con los márgenes del foro (2.5/3cm). El fondo
   dibuja una separación cada 29.7cm, así se ve dónde termina una página y
   empieza la siguiente mientras se desplaza hacia abajo. */
.editor-sheet {
  background: #fff; color: #1a1a1a; margin: 0 auto;
  width: 21cm; min-height: 29.7cm; /* A4 real: no se comprime (si no cabe, se desplaza) */
  padding: 2.5cm 3cm; /* márgenes del foro: 2.5 arriba/abajo, 3 a los lados */
  border-radius: 3px; box-shadow: 0 4px 24px rgba(8, 16, 25, 0.14);
  /* ⚠️ 12 PUNTOS y centímetros, FUERA de la escala de la interfaz A PROPÓSITO.
     La hoja del escrito se mide como la mide el juzgado, no como se mide la
     app. Es la única parte del sistema que no sigue la escala de arriba, y
     no debe unificarse con ella nunca. */
  font-family: 'Times New Roman', Georgia, serif; font-size: 12pt; line-height: 1.15;
  text-align: justify; /* el JUSTIFICADO es el formato por defecto del foro */
}
.editor-sheet:focus { outline: none; }
/* 📐 12-09-2026 · LA LÍNEA QUE SE ENVUELVE PARA PODER SANGRARLA.
   `ajustarSangria` mete la línea tocada en un <p> para tener a qué pegarle el
   estilo (ver la cabecera de la sangría en redactor.js). Sin este margen a
   cero se vería DISTINTA que antes de tocarla: los párrafos de verdad llevan
   10pt de aire debajo y una línea suelta con su <br> no lleva ninguno. */
.editor-sheet p.parrafo-folio { margin: 0; }
/* ============================================================
   📏 LA REGLA DE LA HOJA (12-09-2026) — la de Word, con sus tiradores
   ------------------------------------------------------------
   Va DENTRO de `.editor-sheet-wrap` y justo encima de la hoja, así hereda su
   `zoom`: cuando el folio se encoge para caber al lado del Socio, la regla se
   encoge con él y sus centímetros siguen cayendo donde cae el texto.
   ⚠️ `position: sticky` para que no se vaya al desplazar el escrito: una regla
   que se pierde arriba del todo sólo sirve para el primer párrafo.
   ============================================================ */
.editor-sheet-wrap > .folio-regla { zoom: var(--folio-zoom, 1); }
.folio-regla {
  width: 21cm; margin: 0 auto 6px; position: sticky; top: 0; z-index: 4;
  /* La hoja tiene fondo blanco; la regla también, para que al desplazar el
     escrito por debajo no se transparente el texto a través de ella. */
  background: var(--card, #fff);
}
.folio-regla .fr-papel {
  position: relative; height: 22px; background: #e9e4d8;
  border: 1px solid var(--line); border-radius: 3px;
  font-family: var(--font-ui); font-size: 8.5px; color: #6b6250;
  user-select: none; -webkit-user-select: none;
}
/* La caja del texto: lo blanco entre los dos márgenes de 3 cm del foro. */
.folio-regla .fr-caja {
  position: absolute; left: 3cm; width: 15cm; top: 0; bottom: 0;
  background: #fdfcf8; box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .06);
}
.folio-regla .fr-num,
.folio-regla .fr-tick { position: absolute; transform: translateX(-50%); }
.folio-regla .fr-num { top: 5px; line-height: 1; }
.folio-regla .fr-num-margen { color: #a79b82; }
.folio-regla .fr-tick { top: 9px; width: 1px; height: 4px; background: #b3a88f; }
/* Los cuatro tiradores. Se pintan con `border` (triángulos) para no depender
   de ninguna fuente de iconos: la regla tiene que salir igual sin red. */
.folio-regla .fr-tirador {
  position: absolute; width: 0; height: 0; cursor: ew-resize;
  /* La zona de agarre es mayor que el dibujo: un triángulo de 9 px es
     imposible de coger con el dedo, y con el ratón se falla la mitad de las
     veces. `::before` pone 18×22 px de superficie invisible alrededor. */
}
.folio-regla .fr-tirador::before {
  content: ""; position: absolute; left: -9px; right: -9px; top: -11px; bottom: -11px;
}
.folio-regla .fr-primera,
.folio-regla .fr-izq,
.folio-regla .fr-der {
  border-left: 5px solid transparent; border-right: 5px solid transparent;
}
/* ▽ primera línea: apunta hacia abajo, arriba del todo */
.folio-regla .fr-primera { top: 1px; margin-left: -5px; border-top: 7px solid var(--navy-900, #16283c); }
/* △ izquierda y derecha: apuntan hacia arriba, abajo del todo */
.folio-regla .fr-izq,
.folio-regla .fr-der { top: 12px; margin-left: -5px; border-bottom: 7px solid var(--navy-900, #16283c); }
/* ▭ el cuadro que mueve el párrafo entero, colgado bajo el triángulo izquierdo */
.folio-regla .fr-todo {
  top: 19px; margin-left: -5px; width: 10px; height: 4px; cursor: move;
  background: var(--navy-900, #16283c); border-radius: 1px;
}
.folio-regla .fr-tirador:hover { filter: brightness(1.6); }
/* Sin párrafo debajo del cursor no hay nada que mover: se apagan y dejan de
   invitar a arrastrar. Los ± de la barra siguen diciendo qué hacer. */
.folio-regla.fr-apagada .fr-tirador { opacity: .3; pointer-events: none; }
/* El número exacto mientras se arrastra. Sin él hay que soltar y mirar el
   folio para saber cuánto has movido, que es media herramienta. */
.folio-regla .fr-globo {
  position: absolute; top: 24px; transform: translateX(-50%);
  background: var(--navy-900, #16283c); color: #fff;
  font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: var(--r-pastilla, 999px);
  white-space: nowrap; pointer-events: none;
}
/* Mientras se arrastra, el puntero manda en toda la ventana: sin esto el
   cursor cambia de forma al pasar por encima del texto y parece que se soltó. */
body.arrastrando-regla { cursor: ew-resize; user-select: none; }
/* En el celular la hoja es fluida (`width: 100%`) y la regla en centímetros
   dejaría de caer donde cae el texto: se retira en vez de mentir. */
/* 🔴 16-09 · EN EL TELÉFONO, LA HOJA DEJA DE SIMULAR UN A4 Y PASA A SER TEXTO.
   Piero mandó la captura: «EXPEDIENTE N°: 99075-20…» cortado por el filo de la
   pantalla, y debajo un folio en blanco larguísimo y vacío.
   La causa: la hoja mide `21cm` (794 px) SIEMPRE, y el ajuste automático de
   `escrito-refinar.js` tiene un suelo de 0,55 — a propósito, para que la letra
   no baje de ~9 px. En un teléfono de 390 px eso deja 437 px de hoja dentro de
   una caja de 326: 111 px se salen por la derecha. O sea que hasta hoy el
   escrito en el celular estaba a la vez ILEGIBLE (letra al 55 %) y CORTADO.
   🪤 Y el comentario de `_aplicarZoomFolio` decía que «por debajo de 900 px el
   CSS convierte la hoja en fluida»: la regla ya no existía. Se cayó en la
   limpieza del 13-08 —cuando se quitó uno de los dos mecanismos que se
   peleaban— y el comentario se quedó describiendo un arreglo que ya no estaba.
   Vuelve, y con ella el cálculo del zoom vuelve a ser cierto: si la hoja mide
   lo que la caja, no hay nada que encoger y la letra se queda a su tamaño.
   ⚖️ Lo que se GUARDA, IMPRIME y EXPORTA sigue siendo A4 con los márgenes del
   foro (2,5/3 cm): eso lo hace un clon que vive FUERA de esta caja. Aquí sólo
   cambia lo que se ve mientras se escribe desde el teléfono. */
@media (max-width: 900px) {
  .folio-regla { display: none; }
  .editor-sheet-wrap { padding: 12px 10px 36px; }
  .editor-sheet { width: 100%; min-height: 40vh; padding: 20px 16px; box-shadow: 0 2px 10px rgba(8, 16, 25, 0.10); }
}
.editor-sheet h3 { font-family: inherit; text-align: left; color: #0d1b2a; font-size: 12pt; font-weight: 700; margin: 12pt 0 6pt; }
.editor-sheet p { margin: 0 0 10pt; }
.editor-sheet ul, .editor-sheet ol { margin: 6px 0 10px 26px; text-align: left; }
.editor-sheet .membrete-identidad { text-align: center; }
.editor-sheet .bloque-firmas td { border: none !important; text-align: center; vertical-align: bottom; }
/* Bloque a la derecha: sumilla / encabezado / identificación de la parte */
.editor-sheet .der-block { margin-left: 7.5cm; text-align: left; margin-bottom: 10pt; }
/* La identificación de la parte SÍ se justifica (es un párrafo corrido); las
   etiquetas del encabezado quedan a la izquierda para no salir con huecos. */
.editor-sheet .der-block.der-parte { text-align: justify; }
/* Cada apartado del cuerpo es una sección: así se reordena desde la Estructura */
.editor-sheet .sec-escrito { display: block; }
/* Vista de impresión (overlay con hojas paginadas) */
#preview-overlay {
  display: none; position: fixed; inset: 0; z-index: 3000;
  flex-direction: column; background: rgba(10, 15, 22, 0.55);
}
.preview-top {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 20px; background: #1f2937; color: #fff; font-size: 13px; font-weight: 600;
}
#preview-frame { flex: 1; width: 100%; border: none; background: #565b63; }
/* Marca de agua «BORRADOR» sobre la hoja (no se guarda en el contenido) */
.editor-sheet.con-marca-agua { position: relative; }
.editor-sheet.con-marca-agua::before {
  content: "BORRADOR";
  position: absolute; top: 42%; left: 50%;
  transform: translate(-50%, -50%) rotate(-35deg);
  font-size: 90px; font-weight: 800; letter-spacing: 8px;
  color: rgba(13, 27, 42, 0.07); pointer-events: none; z-index: 0; white-space: nowrap;
}
.editor-sheet .pie-estudio { font-size: 9.5pt; color: #444; text-align: center; border-top: 1px solid #999; padding-top: 6pt; margin-top: 24pt; }
/* Panel de Confiabilidad de la IA (transparencia: citas + revisión humana) */
/* ============================================================
   🔤 2026-08-11 — EL TAMAÑO DE ESTE PANEL, MEDIDO
   ------------------------------------------------------------
   Piero: «me gustaría que salga en una letra más parecida a lo que ya tenemos
   en el app». La sospecha era que el panel usaba OTRA tipografía. NO era eso:
   medido en el navegador, todo el panel ya se pinta en Inter, la misma del
   resto de la app (`document.fonts.check("13px Inter")` = true, y el ancho a
   peso 700 y a 800 sale idéntico, o sea que tampoco hay engorde sintético).
   Lo que pasaba es que el panel entero vivía a 11-12px —contados: 17 elementos
   a 11px y 16 a 12px— mientras el cuerpo de la app va a 15px y Configuración a
   13px. Inter a 11px comprime las formas y se lee como otra letra, más
   técnica. Es EL MISMO fallo del hallazgo 9 (`.cfg-hint`), en otro panel: la
   letra que desentona no es la que cambió de familia, es la que se quedó a un
   tamaño que no es el de la casa.
   ⇒ El cuerpo del panel sube a 13px (el de Configuración) y lo secundario a
   11.5-12px. Sigue siendo compacto; deja de parecer otra fuente.
   ============================================================ */
/* 🔑 LA VACUNA DEL HALLAZGO 9, aquí de raíz: el CONTENEDOR lleva el tamaño de
   la casa. Medido, los tres `div` que envuelven este panel heredaban los 15px
   del documento; hoy ninguno pinta texto directamente —así que no se ve—, pero
   es exactamente la situación en la que nació `.cfg-hint`: basta que alguien
   añada una línea suelta sin clase para que salga a 15px al lado de vecinas a
   13. Con la base puesta aquí, lo que se olvide de vestir nace bien. */
#redactor-confiabilidad-box, #redactor-confiabilidad-cont { font-size: 13px; }
.conf-sello { font-size: 12px; line-height: 1.5; color: var(--ink-2); background: var(--gold-soft); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 9px 11px; }
.conf-sello i { color: var(--acento-txt); margin-right: 4px; }
.conf-fila { display: flex; align-items: center; gap: 8px; font-size: 13px; line-height: 1.45; color: var(--ink-2); margin-top: 8px; }
.conf-fila .conf-num { font-weight: 700; color: var(--ink); min-width: 18px; text-align: center; font-variant-numeric: tabular-nums; }
.conf-fila.conf-warn .conf-num { color: var(--danger-txt); }
.conf-fila.conf-ok .conf-num { color: #1a7f37; }
.conf-citas { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.conf-cita { font-size: 11.5px; background: rgba(26,127,55,.10); color: #1a7f37; border: 1px solid rgba(26,127,55,.30); border-radius: var(--r-pastilla); padding: 3px 10px; }

/* ============================================================
   🗂️ LOS TRES BLOQUES DEL PANEL (2026-08-11)
   ------------------------------------------------------------
   «Toda esa información se ve desordenada a simple vista» (Piero). Lo era: once
   filas idénticas, un número gordo y una línea gris cada una, dijeran algo que
   hay que arreglar o algo que ya está bien. Ahora se agrupan por lo que tiene
   que HACER el abogado, y cada grupo se distingue por una banda de color al
   costado —no por una caja—: cajas dentro de la caja del panel convertirían
   esto en un formulario, y son tres lecturas, no tres formularios.
   ============================================================ */
.conf-grupo { margin-top: 14px; padding-left: 10px; border-left: 2px solid var(--line); }
.conf-grupo:first-child { margin-top: 12px; }
.conf-grupo-tit {
  font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .07em;
  color: var(--ink-3); display: flex; align-items: center; gap: 6px;
}
.conf-grupo-tit > i { font-size: 10px; }
/* La primera fila de cada bloque no necesita su margen: ya lo pone el rótulo. */
.conf-grupo > .conf-fila:first-of-type { margin-top: 6px; }
.conf-g-hacer { border-left-color: var(--danger); }
.conf-g-hacer .conf-grupo-tit { color: var(--danger-txt); }
.conf-g-ok { border-left-color: rgba(26,127,55,.45); }
.conf-g-base { border-left-color: var(--line-strong, var(--line)); }
/* Cita RESPALDADA por la Biblioteca jurídica del estudio (dorado + libro) */
.conf-cita-bib { background: var(--gold-soft); color: var(--acento-txt); border-color: var(--gold); cursor: help; }
.conf-cita-bib i { font-size: 11px; margin-right: 4px; }
/* Número de caso que NADIE ha verificado (casación, expediente, sentencia).
   Va en rojo a propósito: una casación inventada tiene el mismo aspecto que
   una real hasta que alguien la busca. */
.conf-cita-nover {
  background: rgba(197, 48, 48, 0.08); color: var(--danger-txt);
  border-color: rgba(197, 48, 48, 0.45); cursor: help;
}
.conf-cita-nover i { font-size: 11px; margin-right: 4px; }
.conf-socio-alerta {
  display: flex; align-items: flex-start; gap: 6px; margin-top: 8px;
  font-size: 11.5px; line-height: 1.45; color: var(--danger-txt);
}
.conf-socio-alerta i { margin-top: 2px; flex: none; }
/* La procedencia del arancel se lee de verdad —es el «de dónde salió este
   número»—, así que no puede quedarse en la letra más pequeña del panel. */
.conf-nota { font-size: 11.5px; line-height: 1.5; color: var(--ink-3); margin-top: 6px; }
/* Barra de confiabilidad dentro de las burbujas del SOCIO */
.conf-socio { margin-top: 10px; padding-top: 8px; border-top: 1px dashed var(--line); }
.conf-socio-sello { font-size: 11px; color: var(--ink-3); }
.conf-socio-sello i { color: var(--acento-txt); margin-right: 4px; }
/* El sello de IA: sale SIEMPRE, así que va deliberadamente discreto y el
   último. Si compitiera con los avisos de arriba —que sí piden una acción—,
   en dos días nadie leería ninguno de los dos. */
.conf-socio-ia { margin-top: 8px; font-size: 11px; line-height: 1.5; color: var(--ink-3); opacity: .9; }
.conf-socio-ia i { color: var(--ink-3); margin-right: 4px; }
/* El botón Justificar se resalta: es el más usado en escritos */
/* `.red-tool-just` se fue con los 4 botones de alineación (2026-08-06): marcaba
   en dorado el de justificar. Ahora esa preferencia la dice el desplegable, con
   la palabra «recomendado» — que se lee, en vez de un color que hay que
   adivinar. Regla de la cascada: sin botón, sobra la regla. */
/* Botón e indicador de [CORCHETES] pendientes por completar */
/* Botón de la barra CON TEXTO. Antes se llamaba .red-tool-corchetes y sólo la
   llevaba «Pendientes»; «Completar datos» se quedó con el ancho fijo de 30 px de
   .red-tool y su texto se salía por encima del botón vecino (lo ve Piero en
   pantalla, 2026-08-06). El nombre dice lo que hace, para que el siguiente
   botón con texto no vuelva a nacer roto. */
.red-tool.red-tool-txt { width: auto; padding: 0 10px; gap: 6px; font-size: 12px; font-weight: 700; white-space: nowrap; }
.corchete-pend {
  background: #fff3cd; color: #8a5a00; font-weight: 700;
  border-radius: 3px; padding: 0 2px; box-shadow: inset 0 -1px 0 #e0a800;
}
@media (prefers-color-scheme: dark) {
  .corchete-pend { background: #6b5300; color: #ffe9a8; box-shadow: inset 0 -1px 0 #a67c00; }
}
:root[data-theme="dark"] .corchete-pend { background: #6b5300; color: #ffe9a8; box-shadow: inset 0 -1px 0 #a67c00; }
:root[data-theme="light"] .corchete-pend { background: #fff3cd; color: #8a5a00; box-shadow: inset 0 -1px 0 #e0a800; }
/* Cita legal detectada dentro del documento (verde sutil, sin recolorear el texto) */
.cita-legal { background: rgba(26,127,55,.10); box-shadow: inset 0 -1px 0 rgba(26,127,55,.55); border-radius: 3px; padding: 0 1px; }
@media (prefers-color-scheme: dark) { .cita-legal { background: rgba(45,164,78,.18); box-shadow: inset 0 -1px 0 rgba(45,164,78,.7); } }
:root[data-theme="dark"] .cita-legal { background: rgba(45,164,78,.18); box-shadow: inset 0 -1px 0 rgba(45,164,78,.7); }
:root[data-theme="light"] .cita-legal { background: rgba(26,127,55,.10); box-shadow: inset 0 -1px 0 rgba(26,127,55,.55); }
/* ══ VER LA HOJA LIMPIA (2026-08-08, lo pidió Piero) ═══════════════════════
   El dorado de los [corchetes] y el verde de las citas son AYUDAS de trabajo,
   no parte del escrito. Con el escrito casi terminado estorban: el abogado
   quiere ver la hoja como la verá el juzgado.
   🔑 Se apagan SOLO con CSS, y esa es la decisión que importa: los `<span>`
   siguen en el folio, así que el conteo de corchetes, el aviso al descargar,
   «Completar datos» y `huecosDelEscrito()` funcionan exactamente igual. Si se
   apagara quitando los spans del DOM, apagar el color apagaría también el
   freno que impide firmar un escrito con huecos — y ese freno es lo último
   que puede depender de una preferencia de vista. */
.editor-sheet.sin-marcas .corchete-pend,
.editor-sheet.sin-marcas .cita-legal {
  background: none; box-shadow: none; color: inherit; font-weight: inherit;
}
@media (max-width: 900px) {
  .editor-layout { flex-direction: column; }
  .editor-side { width: 100%; }
  .editor-side .card { position: static; }
  .editor-sheet { width: 100%; min-height: auto; padding: 30px 22px; background-image: none; }
  .editor-sheet .der-block { margin-left: 35%; }
  .editor-sheet-wrap { max-height: none; overflow-x: hidden; }
}
/* Editor Jurídico — bloques arrastrables (estructura) */
.est-mini {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11px; font-weight: 600; color: var(--acento-txt);
  background: var(--gold-soft); border: 1px solid var(--gold);
  padding: 4px 10px; border-radius: var(--r-lg); cursor: pointer; white-space: nowrap;
}
.est-mini:hover { background: var(--gold); color: var(--navy-950); }
.est-mini:disabled { opacity: .5; cursor: progress; }

/* ============================================================
   🆕 01-09-2026 · «…O UN TRAMO EXACTO», en «Traer un mes atrás»
   ------------------------------------------------------------
   Piero: «ver desde la fecha inicial hasta la fecha final y traer lo que hay
   en el SINOE tanto en bandeja de notificaciones como mesa de partes».
   🪤 `flex-wrap` y `min-width` en los campos: sin ellos, dos `input[type=date]`
   y un botón no caben en el móvil y el último se sale de la ventana. Es la
   trampa de `input{width:100%}` mirada por el lado del contenedor.
   ============================================================ */
.mes-rango { margin: 2px 0 14px; padding: 12px 14px; background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-sm); }
.mes-rango-t { font-size: 12px; font-weight: 700; color: var(--ink-2); margin-bottom: 9px; }
.mes-rango-campos { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px; }
.mes-rango-campos label {
  display: flex; flex-direction: column; gap: 4px; flex: 1 1 140px; min-width: 0;
  font-size: 11px; font-weight: 600; color: var(--ink-3);
}
.mes-rango-campos input[type="date"] {
  box-sizing: border-box; width: 100%; min-width: 0;
  padding: 7px 10px; font: inherit; font-size: 12.5px;
  color: var(--ink); background: var(--card);
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
}
.mes-rango-campos .est-mini { padding: 8px 14px; font-size: 12px; }
.est-bloque {
  display: flex; align-items: center; gap: 10px;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-md);
  padding: 8px 10px; font-size: 13px; color: var(--ink); cursor: grab;
}
.est-bloque:hover { border-color: var(--gold); }
.est-bloque.arrastrando { opacity: 0.5; }
.est-grip { color: var(--ink-3); font-size: 13px; cursor: grab; }
.est-txt { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.est-acc { display: inline-flex; gap: 10px; color: var(--ink-3); }
.est-acc i { cursor: pointer; font-size: 13px; }
.est-acc i:hover { color: var(--acento-txt); }
.est-acc .fa-xmark:hover { color: var(--danger-txt); }
/* El apartado que exige una norma (2026-08-11). No lleva ✕ —no se puede quitar—
   y la balanza dice cuál es la norma al posar el ratón. Usa `--acento-txt`, el
   mismo de los iconos de acción: aquí NO se estrena ningún color de texto. */
.est-ley { color: var(--acento-txt); font-size: 12px; flex: none; cursor: help; }

/* ============================================================
   SOCIO IA — panel lateral acoplado (estilo Gemini/Canva)
   El panel vive a la derecha y PERSISTE al cambiar de pestaña:
   el abogado navega el sistema mientras conversa. El contenido
   principal se encoge para dejarle sitio (split view), no lo tapa.
   ============================================================ */
#ai-floating-button {
  position: fixed; bottom: 26px; right: 26px; z-index: 1400;
  display: flex; align-items: center; gap: 10px;
  height: 52px; padding: 0 20px 0 16px; border-radius: var(--r-pastilla);
  background: linear-gradient(135deg, var(--navy-800), var(--navy-950));
  border: 1.5px solid var(--gold);
  color: var(--gold); font-size: 14px; font-weight: 700;
  cursor: pointer; box-shadow: 0 6px 24px rgba(8, 16, 25, 0.35);
  transition: transform 160ms var(--ease), box-shadow var(--speed), opacity 200ms;
}
#ai-floating-button::after { content: "Socio IA"; font-family: var(--font-ui); letter-spacing: 0.2px; }
.socioia-logo { width: 34px; height: 34px; object-fit: contain; display: block; flex-shrink: 0; }
.socioia-logo-header { width: 22px; height: 22px; margin-right: 8px; vertical-align: middle; }
.ai-header span { display: inline-flex; align-items: center; }
#ai-floating-button:hover { transform: translateY(-2px); box-shadow: 0 8px 30px rgba(197, 160, 89, 0.4); }
#ai-floating-button.tiene-aviso::before { content: ""; position: absolute; top: -3px; right: -3px; width: 13px; height: 13px; border-radius: 50%; background: var(--danger); border: 2px solid var(--navy-950); animation: pulse-badge 1.6s infinite; }

/* ---- ANCHO DEL SOCIO: UN SOLO NÚMERO ----
   Antes el 396 estaba escrito a mano en DOS sitios (aquí y en el ancho de la
   ventana). Con dos copias, ensanchar el panel dejaba el contenido de al lado
   recortado al ancho viejo. Ahora es una variable y los dos la leen.
   El ancho por defecto NO cambia: el segundo ancho es opcional y se recuerda. */
body { --socio-ancho: 396px; }
body.socio-ancho2 { --socio-ancho: min(720px, 60vw); }
/* El contenido se recorta cuando el Socio está abierto (split view) */
body.socio-abierto #main-content { margin-right: var(--socio-ancho); }
body.socio-abierto #ai-floating-button { opacity: 0; pointer-events: none; }

/* 🪤 `max-width: 100%`, NO `100vw`. Son distintos y la diferencia se ve:
   `100vw` mide la ventana CON la barra de desplazamiento incluida, mientras que
   el panel está anclado a `right: 0`, que es el borde ÚTIL (sin barra). Con una
   barra clásica —Chrome en Windows— el panel sale ~15px más ancho que el hueco
   y, al no poder crecer hacia la derecha, se desplaza hacia la IZQUIERDA: todo
   el contenido se descuadra y al icono de la cinta se le come el borde.
   `100%` en un elemento `fixed` se mide contra el bloque contenedor inicial,
   que ya excluye la barra. */
#ai-cloud-window {
  position: fixed; top: 0; right: 0; bottom: 0; z-index: 1450;
  width: var(--socio-ancho); max-width: 100%;
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--card);
  border-left: 1px solid var(--line);
  box-shadow: -8px 0 34px rgba(8, 16, 25, 0.16);
  transform: translateX(100%);
  /* `width` va aquí junto a `transform`: si se declara en otra línea, la
     segunda `transition` pisa a la primera y el panel deja de deslizarse. */
  transition: transform 280ms var(--ease), width 200ms var(--ease);
}
body.socio-abierto #ai-cloud-window { transform: translateX(0); }
/* ---- El Socio trabajando SOBRE el escrito ----
   La pastilla dice qué texto va a leer: lo seleccionado (barato) o todo el
   escrito (caro). Y el botón dorado es el ÚNICO que puede tocar la hoja, y solo
   a través del cuadro de antes y después. */
#socio-escrito-bar {
  display: flex; flex-direction: column; gap: 8px;
  padding: 10px 12px 0; background: var(--card);
}
#socio-sel-pill {
  display: flex; align-items: center; gap: 8px; padding: 7px 11px;
  border-radius: var(--r-pastilla); font-size: 11.5px; line-height: 1.35;
  background: var(--paper); border: 1px dashed var(--line); color: var(--ink-3);
}
#socio-sel-pill.con-seleccion {
  background: var(--gold-soft); border: 1px solid var(--gold);
  color: var(--acento-txt); font-weight: 600;
}
#socio-sel-txt { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.socio-sel-x { cursor: pointer; font-size: 12px; opacity: .7; }
.socio-sel-x:hover { opacity: 1; }
#btn-socio-proponer {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; padding: 9px 12px; cursor: pointer;
  font-family: var(--font-ui); font-size: 12.5px; font-weight: 700;
  color: var(--acento-txt); background: transparent;
  border: 1px solid var(--gold); border-radius: var(--r-sm);
  transition: background 160ms var(--ease), color 160ms var(--ease);
}
#btn-socio-proponer:hover:not(:disabled) { background: var(--gold-soft); }
#btn-socio-proponer:disabled { opacity: .6; cursor: default; }
#socio-sel-ayuda {
  margin: 0; font-size: 11px; line-height: 1.55; color: var(--ink-3);
  border-left: 2px solid var(--gold); padding-left: 9px;
}
.socio-ayuda-mas {
  display: inline-flex; align-items: center; justify-content: center;
  width: 15px; height: 15px; margin-left: 3px; cursor: pointer;
  border-radius: 50%; border: 1px solid var(--gold); color: var(--acento-txt);
  font-size: 11px; font-weight: 700; line-height: 1; vertical-align: middle;
}
.socio-ayuda-mas:hover { background: var(--gold-soft); }
/* ⚖️ LOS 16px DEL PANEL DEL SOCIO (2026-08-10, lo pidió Piero).
   Las bandas del panel tenían cada una su sangría —cabecera 18, cinta 14,
   acordeón 10, cuerpo 16, barra de interruptores 10, caja de escribir 12— y de
   arriba abajo el borde izquierdo se leía dentado. Todas a 16, que es la del
   cuerpo del chat: es la banda más alta y la que manda.
   ⚠️ Si añades una banda nueva al panel, va con 16px de sangría horizontal. */
.ai-header {
  display: flex; align-items: center; justify-content: space-between;
  background: var(--navy-900); color: var(--gold);
  padding: 14px 16px; font-weight: 700; font-size: 13px; letter-spacing: 0.4px;
}
.ai-header i { color: rgba(238,242,247,0.6); cursor: pointer; }
.ai-header i:hover { color: #fff; }
/* ---- Chat del Socio v2: barra del hilo + cajón de conversaciones ---- */
/* LA CINTA del Socio: la ÚNICA fila que dice sobre qué expediente se trabaja.
   Número arriba, cliente debajo, botón de cambiar a la derecha. Antes esto
   eran tres filas apiladas que repetían el mismo número tres veces.
   Gris apagado cuando es una consulta general. */
.socio-exp-cinta {
  display: flex; align-items: center; gap: 10px;
  padding: 9px 16px;   /* alineado con el resto del panel; ver los 16px arriba */
  background: var(--navy-900); color: var(--gold);
  border-bottom: 1px solid rgba(var(--gold-rgb), 0.35);
}
.socio-exp-cinta > i { flex: none; font-size: 13px; opacity: 0.9; }
.socio-cinta-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.socio-cinta-exp {
  font-size: 12.5px; font-weight: 700; color: #fff; letter-spacing: 0.2px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
#socio-conv-titulo {
  font-size: 11px; font-weight: 500; color: rgba(var(--gold-rgb), 0.85);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.socio-exp-cinta.vacia {
  background: var(--card); color: var(--ink-3);
  border-bottom: 1px solid var(--line);
}
.socio-exp-cinta.vacia .socio-cinta-exp { color: var(--ink); }
.socio-exp-cinta.vacia #socio-conv-titulo { color: var(--ink-3); }
/* Botón de cambiar de expediente: abre el buscador del Ctrl+K filtrado a
   expedientes. Antes llevaba un <select> nativo invisible encima; se retiró
   con él la regla `.socio-exp-cambiar select`, que ya no tenía a quién pintar. */
.socio-exp-cambiar {
  flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: var(--r-md);
  background: transparent; color: inherit; padding: 0;
  border: 1px solid rgba(var(--gold-rgb), 0.4); cursor: pointer;
}
.socio-exp-cambiar i { font-size: 11px; pointer-events: none; }
.socio-exp-cambiar:hover { background: rgba(var(--gold-rgb), 0.16); }
.socio-exp-cambiar:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
.socio-exp-cinta.vacia .socio-exp-cambiar { border-color: var(--line-strong); }
/* Nota del sistema dentro del chat (cambio de cuaderno, expediente que no
   está en la Carpeta). No es respuesta de la IA: no se guarda ni se manda. */
.socio-nota {
  display: flex; align-items: flex-start; gap: 7px;
  align-self: center; max-width: 92%;
  font-size: 12px; line-height: 1.45; color: var(--ink-3);
  background: rgba(var(--gold-rgb), 0.09);
  border: 1px dashed rgba(var(--gold-rgb), 0.45);
  border-radius: var(--r-md); padding: 7px 11px;
}
.socio-nota i { color: var(--acento-txt); margin-top: 2px; flex: none; }
.socio-nota b { color: var(--ink); }
.conv-nueva-ayuda {
  margin: 0 12px 10px; font-size: 11px; line-height: 1.4; color: var(--ink-3);
}

.conv-menu-btn { color: rgba(238,242,247,0.75); }
.conv-menu-btn:hover { color: #fff; }

#socio-conv-drawer {
  position: absolute; top: 0; left: 0; bottom: 0; z-index: 20;
  width: 84%; max-width: 320px;
  display: flex; flex-direction: column;
  background: var(--card); border-right: 1px solid var(--line);
  box-shadow: 8px 0 30px rgba(8,16,25,0.22);
  transform: translateX(-104%);
  transition: transform 240ms var(--ease);
}
#socio-conv-drawer.abierto { transform: translateX(0); }
.conv-drawer-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 14px 16px; background: var(--navy-900); color: var(--gold);
  font-weight: 700; font-size: 13px;
}
.conv-drawer-head i { color: rgba(238,242,247,0.7); cursor: pointer; }
.conv-drawer-head i:hover { color: #fff; }
.conv-nueva-btn {
  margin: 12px; padding: 10px 12px;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  border: 1px solid var(--gold); background: var(--gold-soft);
  color: var(--acento-txt); border-radius: var(--r-md);
  font-size: 13px; font-weight: 700; cursor: pointer;
  transition: background var(--speed), color var(--speed);
}
.conv-nueva-btn:hover { background: var(--gold); color: var(--navy-950); }
#socio-conv-lista {
  flex: 1; overflow-y: auto; padding: 0 8px 12px;
  display: flex; flex-direction: column; gap: 6px;
}
.conv-vacio { color: var(--ink-3); font-size: 12px; font-style: italic; padding: 8px 10px; line-height: 1.5; }
.conv-item {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 10px 10px; border: 1px solid var(--line); border-radius: var(--r-md);
  cursor: pointer; transition: border-color var(--speed), background var(--speed);
}
.conv-item:hover { border-color: var(--gold); }
.conv-item.activa { border-color: var(--gold); background: var(--gold-soft); }
.conv-item.legacy { border-style: dashed; }
.conv-item-main { min-width: 0; flex: 1; }
.conv-item-titulo { font-size: 13px; font-weight: 600; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.conv-item-prev { font-size: 11px; color: var(--ink-3); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 2px; }
.conv-exp-chip {
  display: inline-flex; align-items: center; gap: 4px; margin-top: 6px;
  font-size: 11px; font-weight: 700; background: var(--navy-900); color: var(--gold);
  padding: 2px 8px; border-radius: var(--r-md);
}
.conv-item-acc { display: flex; flex-direction: column; gap: 10px; opacity: 0.6; }
.conv-item-acc i { font-size: 12px; color: var(--ink-3); cursor: pointer; }
.conv-item-acc i:hover { color: var(--acento-txt); }

.ai-body { flex: 1; overflow-y: auto; padding: 16px; background: var(--paper); display: flex; flex-direction: column; gap: 10px; }
/* El 70ch es el TOPE DE LECTURA, no un capricho: una línea de 150 caracteres se
   lee peor que una de 80 porque el ojo pierde el renglón al volver. Con el ancho
   por defecto (396 px) el 85% manda y esto no cambia nada; solo muerde cuando el
   Socio se ensancha, que es justo cuando aparece el problema. */
.ai-bubble { max-width: min(85%, 70ch); padding: 12px 14px; border-radius: var(--r-lg); font-size: 13px; line-height: 1.55; overflow-wrap: anywhere; word-break: break-word; }
.ai-bubble .ia-link { color: var(--acento-txt); font-weight: 600; text-decoration: underline; text-underline-offset: 2px; }
.ai-bubble .ia-link:hover { color: var(--navy-900); }
/* Cuando el Socio redacta un escrito largo, lo que llega es un documento, no
   un párrafo de chat. Estas reglas son las que lo hacen legible: antes salían
   los `###` y los `***` crudos en pantalla. Los colores van por variables
   —nunca fijos— para que aguanten las 6 paletas y el modo oscuro. */
.ai-bubble .ia-p { margin: 0 0 8px; }
.ai-bubble .ia-p:last-child { margin-bottom: 0; }
.ai-bubble .ia-h1 {
  font-weight: 700; font-size: 14px; letter-spacing: 0.01em;
  color: var(--acento-txt); margin: 14px 0 6px; padding-bottom: 4px;
  border-bottom: 1px solid var(--line);
}
.ai-bubble .ia-h2 { font-weight: 700; font-size: 13px; color: var(--ink-1); margin: 12px 0 4px; }
.ai-bubble .ia-h1:first-child, .ai-bubble .ia-h2:first-child { margin-top: 0; }
.ai-bubble .ia-lista { margin: 0 0 8px; padding-left: 20px; }
.ai-bubble .ia-lista li { margin: 0 0 4px; }
.ai-bubble .ia-lista li::marker { color: var(--acento-txt); font-weight: 700; }
.ai-bubble .ia-sep { border: 0; border-top: 1px solid var(--line); margin: 12px 0; }
.ai-bubble code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 12px;
  background: var(--paper); border: 1px solid var(--line); border-radius: 4px; padding: 1px 5px;
}
/* Barra del toggle "Verificar en internet" — comparte fila con el cupo de
   consultas: eran dos franjas apiladas encima del cuadro de escribir. */
.ai-toggle-bar { display: flex; align-items: center; justify-content: space-between; gap: 6px; padding: 6px 16px 0; background: var(--card); }
/* El cupo es un dato al margen, no un control: sin caja ni marco, para que no
   compita con el interruptor que sí se pulsa. Cuando queda poco, las reglas
   `plan-poco`/`plan-agotado` (más abajo) le devuelven el fondo de aviso. */
.ai-toggle-bar .plan-marca {
  margin: 0; padding: 3px 4px; border: none; background: none;
  /* 10.5px: medido a 375 px de ancho, con 11px la frase completa («26 de 30
     consultas al Socio este mes») se cortaba por un par de píxeles. */
  font-size: 11px; gap: 5px; min-width: 0; justify-content: flex-end; text-align: right;
}
.ai-toggle-bar .plan-marca span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ia-toggle {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; font-weight: 600; color: var(--ink-3);
  background: var(--paper); border: 1px solid var(--line-strong);
  padding: 6px 12px; border-radius: var(--r-lg); cursor: pointer;
  transition: background var(--speed), color var(--speed), border-color var(--speed);
}
.ia-toggle:hover { border-color: var(--gold); color: var(--acento-txt); }
.ia-toggle.activo { background: var(--gold-soft); border-color: var(--gold); color: var(--acento-txt); }
.ia-toggle.activo i { color: var(--acento-txt); }
.ai-bubble-bot { background: var(--card); border: 1px solid var(--line); color: var(--ink); align-self: flex-start; border-bottom-left-radius: 4px; }
.ai-bubble-user { background: var(--navy-900); color: #eef2f7; align-self: flex-end; border-bottom-right-radius: 4px; }
.ia-sugerencias { display: flex; flex-wrap: wrap; gap: 8px; }
.ia-chip {
  font-size: 12px; font-weight: 600; color: var(--acento-txt);
  background: var(--gold-soft); border: 1px solid var(--gold);
  padding: 6px 12px; border-radius: var(--r-lg); cursor: pointer;
  transition: background var(--speed), color var(--speed);
}
.ia-chip:hover { background: var(--gold); color: var(--navy-950); }
.ia-acciones { display: flex; gap: 12px; margin-top: 10px; padding-top: 8px; border-top: 1px dashed var(--line); }
.ia-acc-btn { font-size: 11px; font-weight: 600; color: var(--acento-txt); cursor: pointer; }
.ia-acc-btn:hover { color: var(--ink); }
.ai-input-wrapper {
  display: flex; gap: 8px; align-items: flex-end;
  padding: 12px 16px; background: var(--card); border-top: 1px solid var(--line);
}
.ai-mic-btn {
  width: 40px; height: 40px; border-radius: 50%; flex-shrink: 0;
  border: 1px solid var(--line-strong); background: var(--paper); color: var(--ink-2);
  transition: background var(--speed), color var(--speed);
}
.ai-mic-btn:hover { color: var(--acento-txt); border-color: var(--gold); }
.ai-mic-btn.recording { background: var(--danger); color: #fff; border-color: var(--danger-txt); animation: pulse-badge 1.2s infinite; }
#ai-textarea { border: 1px solid var(--line-strong); border-radius: var(--r-sm); padding: 10px; font-size: 13px; line-height: 1.5; resize: none; overflow-y: auto; min-height: 40px; max-height: 200px; }
#btn-send-ia { width: 40px; height: 40px; min-height: 40px; padding: 0; border-radius: 50%; flex-shrink: 0; }
#ai-cloud-typing { font-size: 12px; padding-left: 4px; color: var(--ink-3); font-style: italic; }

/* ============================================================
   RESPONSIVE
   ============================================================ */
@media (max-width: 1100px) {
  .layout-panel, .layout-panel-resumen, .analisis-grid { grid-template-columns: 1fr; }
}
/* ============================================================
   ESTRECHO — el mismo trato que en el móvil, pero por el HUECO QUE QUEDA
   ------------------------------------------------------------
   🔴 2026-08-10, hallazgo 8 de Piero. Estas reglas vivían dentro de
   `@media (max-width: 860px)`, y un @media mide LA VENTANA. Con el Socio
   abierto la ventana sigue siendo de 1.280 —«esto es un escritorio, no hagas
   nada»— mientras la zona de trabajo se ha quedado en 640 px, o en 301 con el
   Socio ancho. Ahí la barra azul de 244 px se come casi la mitad de lo que
   queda, y el @media no se enteraba porque no era a él a quien había que
   preguntarle.

   Son LAS MISMAS REGLAS, no una copia: se han movido aquí enteras y ahora
   cuelgan de `body.estrecho`, que tiene DOS motivos para encenderse
   (`_medirEstrecho`, en public/js/ui.js):
     · la ventana es de móvil (≤860px) — el caso de siempre; o
     · al trabajo le quedan menos de 900px de ancho REAL, sea por lo que sea.

   ⚠️ NO devuelvas esto a un @media: se perdería el segundo motivo, que es
   justo el que faltaba. Y si añades una regla de móvil, va AQUÍ dentro, con
   su `body.estrecho` delante.
   ============================================================ */
body.estrecho #sidebar {
  position: fixed; top: auto; bottom: 0; left: 0; right: 0;
  width: 100%; flex-direction: row; align-items: center;
  border-right: none;
  border-top: 1px solid rgba(197, 160, 89, 0.25);
  z-index: 900;
  /* La franja de gestos del iPhone se come la parte de abajo de la pantalla:
     sin esto, los botones del menú quedan medio tapados y cuesta acertarles.
     Necesita `viewport-fit=cover` en la etiqueta viewport (app.html), o el
     sistema devuelve cero y esto no hace nada. */
  height: calc(64px + env(safe-area-inset-bottom, 0px));
  padding: 6px 10px calc(6px + env(safe-area-inset-bottom, 0px));
}
/* 🔴 2026-08-10 (Piero, en pantalla): «se pone abajo el panel, pero no sale
   entero, se queda hasta Analizar». Cierto, y medido: la barra iba de borde a
   borde (0→1280) mientras el Socio ocupa desde 884; los siete destinos se
   reparten TODO el ancho, así que «Redactar» (864-1062) y «Facturación»
   (1062-1260) quedaban DEBAJO del panel. Se veía hasta «Analizar», que termina
   justo en 884. La barra tiene que acabar donde empieza el Socio.
   🪤 Hace falta `width: auto`: con `left`, `right` y `width` puestos a la vez
   el navegador descarta el `right` y se queda con el ancho — el arreglo no
   haría nada y parecería que el problema es otro. */
body.estrecho.socio-abierto #sidebar { right: var(--socio-ancho); width: auto; }
body.estrecho .sidebar-logo, body.estrecho .dark-mode-toggle, body.estrecho .producto-marca { display: none; }
/* `display: contents` disuelve el contenedor del menú y deja a los seis
   destinos como hijos directos de la barra. Así el botón de acción se puede
   colocar EN MEDIO de ellos con `order`, sin mover nada en el HTML. */
body.estrecho .nav-menu { display: contents; }
body.estrecho .nav-btn { flex-direction: column; gap: 3px; font-size: 10px; padding: 6px 2px; min-height: 52px; flex: 1 1 0; min-width: 0; text-align: center; justify-content: center; }
body.estrecho .nav-btn.active::before { display: none; }
body.estrecho .nav-btn i { font-size: 17px; width: auto; }
body.estrecho .nav-largo { display: none; }
body.estrecho .nav-corto { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; line-height: 1.2; }
/* DOS destinos · el «+» · DOS destinos (2026-08-13). El pulgar llega al centro
   sin estirarse, y «Nuevo expediente» deja de robarle sitio a los rótulos.
   🔴 Aquí estaba el desnivel que vio Piero: nació como 3 – ➕ – 3, y al irse
   «Estado Procesal» el 13-08 quedó en 2 – ➕ – 3. El ➕ ya estaba en el centro
   por `order`; lo que faltaba era el otro lado. Ahora «Analizar resolución»
   vive dentro de la Carpeta y vuelven a ser dos y dos.
   🪤 `#nav-estado` (order: 3) siguió AQUÍ un día entero después de que su botón
   dejara de existir. No rompía nada —un `order` sobre lo que no está no hace
   nada—, pero la prueba que vigila los restos de aquella mudanza sólo miraba el
   HTML y los `.js`: el CSS es el sexto sitio de la cascada y no estaba en la
   lista. Por eso la prueba de hoy sí lee esta hoja. */
body.estrecho #nav-panel { order: 1; }
body.estrecho #nav-boveda { order: 2; }
body.estrecho .nav-accion { order: 3; }
body.estrecho #nav-editor { order: 4; }
body.estrecho #nav-facturacion { order: 5; }
body.estrecho .nav-accion {
  width: 50px; height: 50px; flex: 0 0 50px; margin: 0 6px; padding: 0;
  border-radius: 50%; gap: 0; align-self: center;
}
body.estrecho .nav-accion i { font-size: 20px; }
body.estrecho .nav-accion span { display: none; }
/* El hueco de abajo cuenta también con la franja de gestos del iPhone: si
   no, la última tarjeta queda debajo del menú y no se puede leer entera. */
/* 🔴 16-09 · ARRIBA TAMBIÉN HAY ZONA SEGURA, Y NO SE ESTABA RESPETANDO.
   Piero mandó cuatro capturas de su iPhone con la hora y la señal ENCIMA del
   texto de la app: «02:03» pisando «Membrete y firma», «02:04» pisando las
   pestañas del expediente. La app está instalada en la pantalla de inicio
   (sin barra de Safari) y el `viewport-fit=cover` del `<head>` hace que la
   página ocupe la pantalla ENTERA, también el trozo donde el teléfono pinta la
   hora, la cobertura y la batería. Abajo ya se respetaba
   (`env(safe-area-inset-bottom)` en la barra de navegación); arriba, no.
   🔑 Dos piezas, y hacen falta las dos:
     · el relleno separa el contenido del filo — pero al desplazar, el texto
       volvería a pasar por debajo de la hora;
     · la cinta fija tapa esa franja con el color del fondo, así lo que sube se
       esconde detrás en vez de mezclarse con el reloj del teléfono.
   En un ordenador `env(safe-area-inset-top)` vale 0: la cinta mide cero y no
   se ve. No se pinta ningún color nuevo, es el fondo de siempre. */
body.estrecho::before {
  content: ""; position: fixed; inset: 0 0 auto 0;
  height: env(safe-area-inset-top, 0px);
  background: var(--bg); z-index: 9999; pointer-events: none;
}
body.estrecho #main-content { margin-left: 0; padding: calc(14px + env(safe-area-inset-top, 0px)) 14px calc(120px + env(safe-area-inset-bottom, 0px)); }
/* «Ctrl K» se montaba encima del texto del buscador… y además en un celular
   no hay tecla Ctrl: era un atajo imposible tapando lo que sí se usa. */
/* 🔧 05-09-2026 · VUELVE A ENVOLVER, Y MEDIDO. El `nowrap` se puso cuando la
   fila eran cuatro filtros y «Por materia» se caía sola a una segunda línea,
   que parecía un descuelgue. Hoy la fila es otra: tres filtros + dos
   interruptores («Solo míos» sale con equipo). Medido en un banco con el CSS
   real, en la vista Lista de un estudio CON equipo:
       a 320 px, con `nowrap` → los chips llegaban a 350 px con la tarjeta
                                acabando en 298: dos pastillas pintadas FUERA.
       a 320 px, con `wrap`   → 267 ≤ 298, en dos líneas.
   🔺 Y el corte cae donde tiene sentido —los tres filtros arriba, los dos
   interruptores debajo—, así que ya no es un descuelgue: es un grupo.
   🪤 El criterio de la medida es DÓNDE SE PINTA el último chip contra el
   borde de la tarjeta. `scrollWidth` aquí decía «se sale» en los dos casos y
   no distinguía el que se ve del que no: contesta «¿se puede desplazar?», no
   «¿cabe todo?». Misma lección que la ronda de Safari del 03-09. */
body.estrecho .cnav-filtros { flex-wrap: wrap; gap: 5px; }
/* Las ramas del derecho SÍ envuelven: son de número variable (una por materia
   que tenga el estudio) y con `nowrap` se saldrían de la tarjeta. Los cuatro
   filtros de la lista son siempre cuatro; éstas, no. */
body.estrecho .cnav-filtros-etapas { flex-wrap: wrap; }
/* El conmutador Lista/Etapas no cabe a la derecha de los filtros en un celular
   (medido: 318 + 136 > 347 de tarjeta). En vez de dejarlo colgando en una
   cuarta línea pegado al borde, ocupa su línea entera a mitad y mitad — se lee
   como una decisión y no como un descuelgue, y de paso los dos rótulos quedan
   del mismo tamaño, que es justo lo que se pidió. */
body.estrecho .cnav-vista { margin-left: 0; width: 100%; }
body.estrecho .cnav-vista button { flex: 1; }
/* 📐 16-09 · EL SUELO DE LA LETRA Y DEL DEDO, SÓLO EN EL TELÉFONO.
   Piero preguntó si la letra del celular debería ser más grande o más chica.
   Censo de esta hoja: de las ~604 medidas de letra que hay, **479 están entre
   11 y 13 px** (176 de ellas clavadas en 11). Eso es una escala pensada para un
   monitor, y en un monitor está bien: el abogado repasa 82 expedientes de un
   vistazo y la densidad es una ventaja. En un teléfono, 11 px queda por debajo
   de lo que recomienda cualquiera (Apple no baja de 11 pt ≈ 14,7 px en su
   estilo más pequeño; la costumbre de la web es 16).
   ⚖️ LA DECISIÓN: no se agranda TODO —eso reharía la app entera y es justo el
   cambio que rompe cosas—. Se sube **el suelo**: en el celular, nada que lleve
   palabras baja de 12 px. El cuerpo se queda en 15: está bien y tocarlo mueve
   cada pantalla.
   👆 Y DE PASO, EL DEDO. Medido en el banco: las pastillas medían 27 y 28 px de
   alto; un dedo pide 44 (Apple) y la norma de accesibilidad exige 24 como
   mínimo. Con el aire de aquí pasan a ~36 y ~39: no llegan a 44 sin estirar la
   franja hasta lo absurdo, pero salen del terreno en el que se falla el toque. */
body.estrecho .fchip { font-size: 12px; padding: 8px 11px; flex-shrink: 0; }
body.estrecho .carpeta-vistas-cnt { font-size: 12.5px; }
body.estrecho .vg-chip { font-size: 12.5px; padding: 8px 12px; }
body.estrecho .vg-dato { font-size: 13px; }
body.estrecho .vg-titular { font-size: 14px; }
body.estrecho .vg-remedio { font-size: 13px; }
body.estrecho .fchip-largo { display: none; }
body.estrecho .fchip-corto { display: inline; }
/* 🪤 `minmax(0, 1fr)` Y NO `1fr`, POR LA MISMA RAZÓN QUE LA REGLA DE `.grid-2`
   DE ARRIBA (2026-08-20). El 19-08 se arregló la de escritorio y esta línea
   —su gemela de celular— se quedó con el fallo puesto: en Grid, `1fr` es
   `minmax(auto, 1fr)`, y ese `auto` impide que la columna baje del ancho
   mínimo de su contenido. Medido en `app.html` de verdad a 375 px, en
   Facturación y con una línea de detalle escrita:
       antes → `#main-content` pedía 507 px para 375 de pantalla (132 de sobra)
       ahora → 375 y 375: no se sale nada
   Y como `#main-content` lleva `overflow-x: hidden`, esos 132 px no se podían
   ni arrastrar: se RECORTABAN. Es lo que Piero fotografió en su iPhone — los
   campos «RUC de tu estudio», «Fecha» y «Vence» cortados por el filo. */
body.estrecho .grid-2, body.estrecho .grid-3 { grid-template-columns: minmax(0, 1fr); }
/* En móvil el Socio ocupa toda la pantalla (no hay sitio para split) */
/* Aquí el Socio ya ocupa toda la pantalla: el interruptor de ancho no puede
   hacer nada, así que no se enseña. Un botón que no responde se lee como una
   avería. */
/* 👆 16-09 · EN EL TELÉFONO, EL SOCIO ES UN BOTÓN REDONDO.
   En las capturas de Piero la pastilla dorada (≈142 px de ancho) se comía el
   botón «Emitir» de Facturación —se leía «Emi…» y debajo estaba el Socio—, y
   tapaba media fila de «Ver · Editar · Eliminar» en la Carpeta. Un botón que
   flota encima no puede esconder OTRO botón: es la forma de pulsar lo que no
   se quería. En redondo pasa de 142 px a 52 y deja de tapar filas enteras.
   El rótulo no se pierde para quien no ve: el `aria-label` del botón sigue
   diciendo «Abrir Socio IA». Es lo que hacen todas las apps con su botón
   flotante en el celular, y aquí además el logo ya identifica al Socio. */
body.estrecho #ai-floating-button { bottom: calc(80px + env(safe-area-inset-bottom, 0px)); width: 52px; padding: 0; justify-content: center; }
body.estrecho #ai-floating-button::after { display: none; }

/* ---- Los menús del Redactor, en una pantalla estrecha ----
   🔴 2026-08-20, lo fotografió Piero: al pulsar «Ver» en el celular, el menú
   salía MEDIO FUERA DE LA PANTALLA por la izquierda y no se podían leer ni las
   opciones ni el tipo de letra.
   LA CAUSA: `.ed-menu-panel` se cuelga del BOTÓN (`.ed-menu` es `position:
   relative`) y se alinea con `right: 0`, o sea que crece hacia la izquierda
   190 px. En el escritorio el botón está a la derecha del todo y cabe; en el
   celular, sin borrador, «Ver» es el ÚNICO botón de la fila y queda pegado al
   borde izquierdo. Medido en `app.html` de verdad a 375 px:
       antes → el panel empezaba en −92 px (92 px fuera de la pantalla)
       ahora → de 14 a 361, dentro y a lo ancho de la barra
   EL ARREGLO: en estrecho el panel deja de colgar del botón y cuelga de la
   BARRA entera (`.editor-bar`), de borde a borde. Así no depende de dónde caiga
   el botón —que cambia según cuántos haya visibles— y no puede salirse por
   ningún lado. Vale para los cuatro menús (Descargar, Ver, Color, Alinear).
   🪤 Hace falta `position: static` en `.ed-menu`: mientras siga siendo
   `relative`, él es el bloque contenedor y `left/right` seguirían midiéndose
   contra el botón. */
body.estrecho .editor-bar { position: relative; }
body.estrecho .editor-bar .ed-menu { position: static; }
body.estrecho .editor-bar .ed-menu-panel,
body.estrecho .editor-bar .red-menu .ed-menu-panel {
  left: 0; right: 0; top: calc(100% + 6px);
  min-width: 0; width: auto; max-height: 60vh; overflow-y: auto;
}


/* Y estas se quedan atadas al TAMAÑO DE LA VENTANA, porque no van de que al
   trabajo le falte ancho: van de que esto es un teléfono. Que el Socio ocupe
   la pantalla entera es lo correcto en un móvil —no hay sitio para partir la
   pantalla— y sería un disparate en un escritorio de 1.280, donde lo que se
   quiere es ver el escrito Y el Socio a la vez. Igual «Ctrl K»: no se esconde
   porque falte sitio, se esconde porque en un celular no hay tecla Ctrl. */
@media (max-width: 860px) {
  header.glass { position: static; }
  .header-datetime-box { display: none; }
  .cmdk-pill { display: none; }
  .search-bar { padding-right: 14px; }
  body.socio-abierto #main-content { margin-right: 0; }
  /* 🪤 `100%`, no `100vw` — ver la nota larga en `#ai-cloud-window`. Con una
     barra de desplazamiento clásica, `100vw` empujaba el panel entero ~15px
     hacia la izquierda y le comía el borde al icono de la cinta. */
  #ai-cloud-window { width: 100%; border-left: none; }
  #btn-socio-ancho { display: none; }
  /* Aquí el Socio tapa la pantalla entera, así que la barra de abajo vuelve a
     ir de borde a borde: queda debajo del panel, que es lo que toca. Va DESPUÉS
     del bloque ESTRECHO a propósito — misma especificidad, gana la última. */
  body.estrecho.socio-abierto #sidebar { right: 0; width: 100%; }

  /* ---- 🔴 LA LETRA DE LOS CAMPOS, EN UN TELÉFONO: 16 px ----
     2026-08-20. Ésta es la otra mitad de «se descuadra en el celular», y no se
     ve mirando el CSS: **Safari de iOS ACERCA la pantalla él solo en cuanto
     tocas un campo cuya letra mide menos de 16 px**, y ya no la devuelve. A
     partir de ese momento TODA la página está ampliada, y por eso las capturas
     de Piero salían con los campos cortados por el filo derecho — en
     Facturación y en el Redactor, que es donde más se toca un campo.
     Medido en `app.html`: **130 campos** por debajo de 16 px (119 a 14 y 11 a
     13). O sea, prácticamente todos. Es un solo arreglo para los 130.
     🔑 Va atado al TAMAÑO DE LA VENTANA y no a `body.estrecho`: no habla de que
     al trabajo le falte ancho, habla de que esto es un teléfono. En el
     escritorio la letra sigue siendo de 14, que es la que está pensada.
     🪤 `!important` a propósito, y es el único sitio donde hace falta: ocho de
     esos campos llevan `style="font-size:13px"` ESCRITO EN LA ETIQUETA, y un
     estilo en línea gana a cualquier regla de la hoja que no lo lleve. Sin él,
     el chat del Socio y el buscador seguirían haciendo zoom.
     ⛔ Y lo que NO se hace: apagar el zoom de los dedos con `user-scalable=no`.
     Eso es lo que mucha gente confunde con esto, y deja sin acercar la pantalla
     al abogado que lo necesita para leer. Lo vigila `celular-descuadres`. */
  input, select, textarea { font-size: 16px !important; }
  /* La hoja del escrito NO entra aquí: es un documento, su letra es la que se
     va a imprimir, y al ser `contenteditable` no es de las que iOS acerca. */
}


/* ============================================================
   BORRADOR PREMIUM — toasts, confirmación, tema oscuro, responsive
   (aditivo; se puede revertir quitando este bloque + ui.js)
   ============================================================ */

/* ---------- Toasts ---------- */
.toast-cont {
  position: fixed; top: 18px; right: 18px; z-index: 4000;
  display: flex; flex-direction: column; gap: 10px; max-width: 360px;
}
.toast {
  display: flex; align-items: center; gap: 10px;
  background: var(--card); color: var(--ink);
  border: 1px solid var(--line); border-left: 4px solid var(--ink-3);
  border-radius: var(--r-md); padding: 12px 14px; box-shadow: var(--shadow-2);
  font-size: 13px; font-weight: 500; cursor: pointer;
  opacity: 0; transform: translateX(24px); transition: opacity .26s var(--ease), transform .26s var(--ease);
}
.toast.show { opacity: 1; transform: none; }
.toast > span { flex: 1; line-height: 1.4; }
.toast .toast-x { color: var(--ink-3); font-size: 12px; }
.toast-success { border-left-color: var(--success-txt); }
.toast-success > i:first-child { color: var(--success-txt); }
.toast-error { border-left-color: var(--danger-txt); }
.toast-error > i:first-child { color: var(--danger-txt); }
.toast-warn { border-left-color: var(--warning-txt); }
.toast-warn > i:first-child { color: var(--warning-txt); }
.toast-info { border-left-color: var(--info-txt); }
.toast-info > i:first-child { color: var(--info-txt); }

/* ---------- Diálogo de confirmación ---------- */
.confirm-overlay {
  position: fixed; inset: 0; z-index: 4100;
  background: rgba(8, 16, 25, 0.55); backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center; padding: 20px;
  opacity: 0; transition: opacity .2s var(--ease);
}
.confirm-overlay.show { opacity: 1; }
.confirm-box {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-lg); box-shadow: var(--shadow-3);
  max-width: 420px; width: 100%; padding: 22px;
  transform: translateY(12px) scale(.98); transition: transform .2s var(--ease);
}
.confirm-overlay.show .confirm-box { transform: none; }
.confirm-box h4 { font-size: 15px; color: var(--ink); margin: 0 0 8px; display: flex; align-items: center; gap: 10px; }
.confirm-box p { font-size: 13px; color: var(--ink-2); line-height: 1.6; margin: 0 0 20px; }
.confirm-acts { display: flex; justify-content: flex-end; gap: 10px; }
.confirm-btn { padding: 10px 18px; border-radius: var(--r-sm); font-size: 13px; font-weight: 700; cursor: pointer; border: 1px solid var(--line-strong); transition: all var(--speed); }
.confirm-cancel { background: transparent; color: var(--ink-2); }
.confirm-cancel:hover { background: var(--paper); }
.confirm-ok { background: var(--navy-900); color: #fff; border-color: var(--navy-900); }
.confirm-ok:hover { background: var(--navy-800); }
.confirm-danger { background: var(--danger); color: #fff; border-color: var(--danger-txt); }
.confirm-danger:hover { filter: brightness(1.08); }
/* ✍️ 31-08 · El campo de `pedirTextoUI`, que sustituye al `prompt()` del
   navegador (ver el porqué largo en ui.js).
   🪤 `width: 100%` con `box-sizing: border-box`. Sin el `box-sizing`, el
   relleno se SUMA al 100% y el campo se sale de la caja por la derecha — es la
   misma trampa que ya se pagó tres veces en esta casa con `input{width:100%}`.
   Y `font: inherit` porque un `input` no hereda la letra: sin eso, el nombre
   del documento saldría en la tipografía del sistema dentro de un diálogo de
   la marca. */
.confirm-input {
  box-sizing: border-box; width: 100%; margin: 0 0 12px;
  padding: 11px 13px; font: inherit; font-size: 14px;
  color: var(--ink); background: var(--card);
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
  transition: border-color var(--speed), box-shadow var(--speed);
}
.confirm-input:focus {
  outline: none; border-color: var(--gold);
  box-shadow: 0 0 0 3px var(--gold-soft);
}
.confirm-box .confirm-ayuda { font-size: 11.5px; color: var(--ink-3); margin: -6px 0 16px; line-height: 1.5; }

/* 🔎 01-09 · El buscador de expediente de «Agendar». Lo pidió Piero: con 75
   expedientes, un desplegable obliga a recorrerlos con el dedo.
   🪤 `box-sizing: border-box` y `width: 100%`: sin el `box-sizing`, el relleno
   se SUMA al 100% y el campo se sale de la ventana por la derecha. Es la
   trampa de `input{width:100%}` que ya se pagó tres veces en esta casa. */
.act-exp-buscar {
  box-sizing: border-box; width: 100%; margin: 0 0 6px;
  padding: 9px 12px; font: inherit; font-size: 13px;
  color: var(--ink); background: var(--card);
  border: 1px solid var(--line-strong); border-radius: var(--r-sm);
}
.act-exp-buscar:focus { outline: none; border-color: var(--gold); box-shadow: 0 0 0 3px var(--gold-soft); }
.act-exp-cuenta { font-size: 11px; color: var(--ink-3); margin-top: 5px; line-height: 1.4; }
/* Que la búsqueda no encuentre nada NO es un dato neutro: sin esto, el
   desplegable se queda con una sola línea y parece que se perdieron los
   expedientes. Va en ámbar, que es «mira esto», no en rojo: no está roto. */
.act-exp-cuenta.vacio { color: var(--warning-txt); font-weight: 600; }

/* ============================================================
   🆕 01-09 (tarde) · LAS SUGERENCIAS DE «AGENDAR», EN UNA SOLA CASILLA
   ------------------------------------------------------------
   Piero: «que mientras vas escribiendo el expediente o cliente te vaya
   apareciendo las opciones sin tener que dar clic en esa segunda ventana».
   🪤 La lista va ABSOLUTA sobre un contenedor `relative`. Si fuera parte del
   flujo, abrirla empujaría hacia abajo medio formulario cada vez que se
   teclea una letra — el modal daría un salto por pulsación.
   ============================================================ */
.act-exp-caja { position: relative; }
.act-exp-lista {
  position: absolute; left: 0; right: 0; z-index: 30;
  max-height: 244px; overflow-y: auto;
  background: var(--card); border: 1px solid var(--line-strong);
  border-radius: var(--r-sm); box-shadow: 0 10px 28px rgba(15, 23, 42, .16);
}
.act-exp-op {
  display: flex; flex-direction: column; gap: 1px;
  padding: 8px 12px; cursor: pointer; border-bottom: 1px solid var(--line);
}
.act-exp-op:last-child { border-bottom: 0; }
.act-exp-op:hover, .act-exp-op.on { background: var(--gold-soft); }
.act-exp-op .ae-n { font-size: 12.5px; font-weight: 700; color: var(--ink); letter-spacing: .01em; }
/* 🪤 `min-width: 0` NO basta para que un nombre largo no pise: hace falta el
   `overflow: hidden`, que es lo que se aprendió el 31-08 con el título de la
   audiencia pintándose por debajo de su pastilla. */
.act-exp-op .ae-c {
  font-size: 11px; color: var(--ink-3); min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* «(sin expediente)» es una decisión, no un expediente más: se distingue. */
.act-exp-op.nota .ae-n { font-weight: 600; color: var(--ink-2); font-style: italic; }
.act-exp-mas { padding: 7px 12px; font-size: 11px; color: var(--ink-3); background: var(--paper); }
/* Apagado: aceptar en vacío borraría el nombre del documento sin decirlo. */
.confirm-btn:disabled { opacity: .45; cursor: not-allowed; }
.confirm-btn:disabled:hover { filter: none; background: var(--navy-900); }

/* ============================================================
   ⚖️ ¿A QUIÉN PATROCINAS? — la lista de partes del papel (2026-08-18)
   ------------------------------------------------------------
   La usan DOS pantallas y por eso vive aquí una sola vez: el diálogo que sale
   antes de analizar (`preguntarAQuienPatrocinaUI`, ui.js) y el formulario de
   alta del expediente (`_bloquePartesDelAlta`, app.js). Dos copias de estos
   estilos acabarían pareciéndose cada vez menos.

   🪤 LOS RADIOS LLEVAN ANCHO PROPIO, Y ES LA TERCERA VEZ QUE ESTO MUERDE.
   La regla global de este archivo —`input, select, textarea { width:100% }`—
   también pilla a los `input[type="radio"]`, y les da ancho completo, relleno,
   borde y fondo: el círculo se dibuja flotando en mitad de un cajón enorme y
   empuja el nombre fuera de su sitio. Es EXACTAMENTE lo que vio Piero el 18-08,
   y ya se había comido las casillas del selector de documentos dos veces antes.
   Misma defensa que en `.arn-op` y `.base-doc`: medidas explícitas.
   ⚠️ `flex: none` NO sirve — fija el crecimiento, no el ancho.

   🔑 Y el segundo arreglo del mismo aviso: los nombres salían apretados. La
   caja del diálogo hereda `p { margin: 0 0 20px }` y no separaba las filas; el
   rol iba pegado al nombre. Aquí cada fila respira por su cuenta.
   ============================================================ */
.pp-lista { display: flex; flex-direction: column; gap: 8px; margin: 4px 0 16px; max-height: 42vh; overflow-y: auto; overflow-x: hidden; padding-right: 2px; }
.pp-op {
  display: flex; align-items: flex-start; gap: 12px; text-align: left;
  border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 11px 13px; cursor: pointer; min-width: 0;
  transition: border-color var(--speed), background var(--speed);
}
.pp-op:hover { border-color: var(--gold); }
/* 🪤 LA FILA ELEGIDA SE MARCA CON UNA CLASE, NO SÓLO CON `:has()` (18-08).
   `.pp-op:has(input:checked)` está escrito aquí abajo y CASA —`matches()` lo
   confirma y `querySelectorAll` la encuentra—, pero el navegador no repintaba:
   el fondo seguía saliendo transparente. Es un fallo de invalidación de estilo
   del propio motor, y pelearse con él es perder la tarde. La clase la pone el
   JavaScript en el `change` (`_pintarElegida` en ui.js y app.js), que es
   determinista y funciona en cualquier navegador. El `:has()` se queda como
   refuerzo: si un día el motor lo repinta bien, no sobra nada. */
.pp-op.pp-op-sel,
.pp-op:has(input:checked) { border-color: var(--gold); background: var(--gold-soft); }
.pp-op input[type="radio"] {
  width: 16px; height: 16px; min-width: 16px; flex: 0 0 16px;
  margin: 3px 0 0; padding: 0; border-radius: 50%;
  accent-color: var(--acento-txt); cursor: pointer;
}
/* `min-width: 0` para que un nombre largo parta en varias líneas en vez de
   ensanchar la fila y sacar una barra de desplazamiento horizontal. */
.pp-cuerpo { display: flex; flex-direction: column; gap: 3px; flex: 1 1 auto; min-width: 0; }
.pp-nombre { font-size: 13.5px; font-weight: 700; color: var(--ink); line-height: 1.35; overflow-wrap: anywhere; }
.pp-rol { font-size: 11px; font-weight: 600; color: var(--ink-3); text-transform: uppercase; letter-spacing: .05em; line-height: 1.3; }
.pp-op-otro { border-style: dashed; }
.pp-op-otro .pp-nombre { font-weight: 600; color: var(--ink-2); }
/* La casilla del nombre a mano quiere el ancho de SU fila, no el del diálogo. */
.pp-otro-nombre { width: 100%; margin-top: 7px; font-size: 12.5px; padding: 6px 9px; }

/* ---------- Ajustes puntuales de modo oscuro ---------- */
body.dark-mode { color-scheme: dark; }
body.dark-mode .badge { filter: brightness(1.06); }

/* Toggle de tema en el login */
.login-tema {
  margin-top: 14px; display: flex; justify-content: center; align-items: center; gap: 8px;
  font-size: 11px; font-weight: 700; letter-spacing: .5px; text-transform: uppercase;
  color: var(--ink-3); cursor: pointer; user-select: none; transition: color var(--speed);
}
.login-tema:hover { color: var(--acento-txt); }
.login-tema i { color: var(--gold); }

/* ---------- Responsive extra ---------- */
@media (max-width: 900px) {
  .layout-panel, .layout-panel-resumen { grid-template-columns: 1fr !important; }
}
@media (max-width: 560px) {
  .kpi-card { flex: 1 1 100%; }
  .toast-cont { left: 12px; right: 12px; max-width: none; }
}

/* Respeto a "reducir movimiento" también en toasts/confirm */
@media (prefers-reduced-motion: reduce) {
  .toast, .confirm-overlay, .confirm-box { transition: none !important; }
}

/* ============================================================
   PALETAS DE COLOR POR CUENTA (identidad del estudio)
   Solo cambian el ACENTO (familia --gold) y el color institucional
   profundo (familia --navy). El marfil (--bg/--paper/--card) se
   conserva. Compatibles con el modo oscuro (que toca otras variables).
   ============================================================ */
/* ---- COLOR DE LOS BOTONES DE ACCIÓN, PALETA A PALETA ----
   Los botones llenos (`Nuevo expediente`, `.btn-gold`) llevaban SIEMPRE letra
   azul oscura sobre el acento. Con el dorado se lee (4,78:1), pero medido en
   las demás se caía: vino 1,94:1, púrpura 2,23:1, cobre 2,34:1, azul 2,48:1
   — letra prácticamente ilegible sobre su propio fondo.
   La solución NO es aclarar el acento (es la identidad del estudio) sino
   cambiar la letra: blanca en las cinco paletas de color, oscura en el dorado.
   Y el degradado arranca en el tono FUERTE (no en el claro), porque el
   esmeralda con blanco sobre su tono claro se quedaba en 3,43:1; arrancando
   del fuerte sube a 5,10:1. Comprobado en las seis: mínimo 4,78:1.
   Un botón de acción que no se lee es un botón que no se pulsa. */
/* 🔴 EL DORADO CLÁSICO PASA A LETRA BLANCA (Piero, 2026-08-06): «las letras
   color azul se ven muy oscuras para el lector del abogado». Era la única de
   las seis con letra oscura sobre el acento, y se notaba.
   No basta con poner #fff encima del dorado de antes: sobre `--gold` (#c5a059)
   el blanco se queda en 2,46:1 y sobre `--gold-strong` (#a9853d) en 3,44:1 —
   medido—, muy por debajo del listón de 4,6 de esta app. Un botón que no se
   lee no se pulsa. Así que se hace lo MISMO que ya se hizo en las otras cinco:
   se baja el relleno a un bronce de la misma familia (mismo matiz 40°, misma
   saturación; sólo cambia la luminosidad) hasta que el blanco cumple.
   Resultado medido: 4,99 arriba y 6,00 abajo. Las seis siguen ≥ 4,78.
   `--relleno-acento` es para los rellenos PLANOS (el chip «N° NUEVO», los
   botones primarios de la ficha): usaban `--gold-strong` directo y con letra
   blanca se habrían quedado en 3,44. `--gold-strong` NO se toca — se usa en
   otros 14 sitios y aclararlo o oscurecerlo rompería ésos. */
:root {
  --acento-btn-1: #896b2f;
  --acento-btn-2: #7a5f2a;
  --sobre-acento: #fff;
  --relleno-acento: #896b2f;
}
html[data-palette="azul"] {
  --acento-btn-1: var(--gold-strong); --acento-btn-2: #1f4d96; --sobre-acento: #fff;
  --relleno-acento: var(--gold-strong);
}
html[data-palette="esmeralda"] {
  --acento-btn-1: var(--gold-strong); --acento-btn-2: #0a6a52; --sobre-acento: #fff;
  --relleno-acento: var(--gold-strong);
}
html[data-palette="burdeos"] {
  --acento-btn-1: var(--gold-strong); --acento-btn-2: #752338; --sobre-acento: #fff;
  --relleno-acento: var(--gold-strong);
}
html[data-palette="cobre"], html[data-palette="grafito"] {
  --acento-btn-1: var(--gold-strong); --acento-btn-2: #773b1d; --sobre-acento: #fff;
  --relleno-acento: var(--gold-strong);
}
html[data-palette="purpura"] {
  --acento-btn-1: var(--gold-strong); --acento-btn-2: #572ea2; --sobre-acento: #fff;
  --relleno-acento: var(--gold-strong);
}

html[data-palette="azul"] {
  --gold: #2f6fd0; --gold-strong: #245ab0; --gold-soft: rgba(47,111,208,.14);
  --navy-950: #081a30; --navy-900: #0f2747; --navy-800: #163257; --navy-700: #1e6091;
}
html[data-palette="esmeralda"] {
  --gold: #0f9d78; --gold-strong: #0c7d60; --gold-soft: rgba(15,157,120,.14);
  --navy-950: #062019; --navy-900: #08312b; --navy-800: #0b4034; --navy-700: #0f6b57;
}
html[data-palette="burdeos"] {
  --gold: #a83250; --gold-strong: #8a2942; --gold-soft: rgba(168,50,80,.14);
  --navy-950: #2a0a15; --navy-900: #3d0f1e; --navy-800: #52152a; --navy-700: #7b1e3a;
}
/* Cobre — sustituyó a "Grafito" el 31-07-2026. Motivo medido: el acento del
   grafito estaba en el tono 215° y el del azul corporativo en 216°: eran el
   MISMO color con distinta saturación, y por eso parecían repetidos. Además
   un acento gris es el color con el que las interfaces dicen "desactivado".
   El cobre está a 23°, aporta la familia tierra que no tenía ninguna paleta,
   y contrasta 4,75:1 sobre el marfil (el dorado clásico se queda en 2,32:1).
   Se descartó el tabaco (31°) por quedar a solo 8° del dorado.
   La regla `grafito` se conserva para no despintar a quien ya lo tuviera. */
html[data-palette="cobre"],
html[data-palette="grafito"] {
  --gold: #a85a2b; --gold-strong: #8c4522; --gold-soft: rgba(168,90,43,.14);
  --navy-950: #241511; --navy-900: #33201a; --navy-800: #452c22; --navy-700: #6b442f;
}
html[data-palette="purpura"] {
  --gold: #7c4dd6; --gold-strong: #6636bf; --gold-soft: rgba(124,77,214,.14);
  --navy-950: #170b2e; --navy-900: #241447; --navy-800: #33206a; --navy-700: #5a2ea6;
}

/* ============================================================
   COLOR DE TEXTO QUE SE LEE EN LOS DOS MODOS  (2026-08-05)
   ------------------------------------------------------------
   Medido con el medidor WCAG 2.1 sobre las 6 paletas × 2 modos. Salieron
   dos averías de fondo, las dos invisibles a ojo:

   1) `--ink-1` y `--bg-2` SE USAN EN 7 SITIOS Y NUNCA SE DEFINIERON.
      `color: var(--ink-1)` sin definir es una declaración inválida: el
      navegador la tira y el texto hereda el color del padre. Salía bien de
      casualidad. `background: var(--bg-2)` directamente no pintaba nada —
      el recuadro «lo que dice el documento» del modal del Vigía llevaba
      semanas sin su fondo y nadie lo notó. Se definen aquí.

   2) LOS COLORES SEMÁNTICOS VALÍAN LO MISMO EN CLARO Y EN OSCURO.
      `--danger` #b3362a se lee 5,35:1 sobre el marfil y 2,71:1 sobre el
      oscuro; `--vino` cae a 1,63:1 (invisible). Y con el acento pasa al
      revés: el dorado se queda en 3,05:1 sobre el marfil, y burdeos,
      cobre y púrpura se hunden sobre el fondo oscuro (1,93 · 2,33 · 2,22).

   La solución NO es cambiar `--danger` ni `--gold-strong`: los dos se usan
   también como RELLENO con letra blanca encima (14 sitios sólo --danger), y
   aclararlos rompería justo esos. Se añaden variantes *-txt que valen
   SOLO para letra, y que sí cambian con el modo. El relleno sigue igual.

   ⚠️ EL PEOR FONDO NO ES EL QUE PARECE, y esto costó una vuelta entera.
   Primero se calcularon los tonos contra `--bg` (#f4f1ea) y `--card`
   (#1a2029), que son los fondos "oficiales". Al volver a medir seguían
   fallando: sobre el papel el texto va encima de `--bg`, pero de verdad va
   encima de una caja `--gold-soft` dentro de un `.glass` dentro del modal, y
   esas capas semitransparentes SUMAN. Medido en la página, el peor fondo real
   es **#e6dcd5 en claro** y **#2f2f2f en oscuro** — bastante más exigentes.
   Los valores de abajo están calculados contra ESOS y ninguno baja de 4,5:1.
   Criterio de Piero: el público incluye gente mayor y con poca vista.

   SON DOS FAMILIAS, NO UNA (y confundirlas fue el segundo tropiezo):
   · `*-txt`   → letra sobre el fondo NORMAL de la app. Cambia con el modo.
   · `*-claro` → letra sobre una superficie OSCURA que es oscura en los DOS
     modos. El Parte es justo eso: su tarjeta va en azul profundo también de
     día (`.p-saludo` ya llevaba #f5efe2 clavado). Ahí un `--acento-txt`
     oscuro sería ilegible de día, así que hace falta el tono claro siempre.
   En modo oscuro las dos familias coinciden, y por eso allí `-txt` apunta
   a `-claro` en vez de repetir los valores.
   ============================================================ */
:root {
  --ink-1: #1c2534;   /* tinta principal — 11,6:1 sobre el peor fondo claro */
  --bg-2:  #efece3;   /* fondo secundario, un punto por debajo de --bg */
  /* --ink-3 se sube aquí de #686e7a a #5c626c: el anterior daba 3,80 sobre el
     peor fondo real y se usa en 189 sitios (135 en el CSS, 54 en los .js), o
     sea que era el fallo de contraste más repetido de toda la app. */
  --ink-3: #5c626c;        /* 4,57 */
  --danger-txt:  #af3529;  /* 4,64 */
  --success-txt: #136f57;  /* 4,55 */
  --info-txt:    #2b5b8f;  /* 5,19 */
  --audiencia-txt: #7d2a72;  /* 6,36 sobre el peor fondo claro real (era 5,42) */
  /* 📝 05-09 · LA NOTA TAMBIÉN NECESITA SU COLOR DE LETRA. `--nota` (#1d6a5e)
     vale para RELLENAR (blanco encima da 5,6), pero escrito SOBRE su propio
     tinte en modo oscuro da **1,56** sobre el peor fondo real (#413d34, la
     caja del Consejo): ilegible. Medido antes de ponerlo, no después.
     Es exactamente la trampa que ya documenta `--warning-claro` diez líneas
     más abajo: las capas semitransparentes ACLARAN el fondo y se comen el
     contraste, así que se mide contra el fondo que hay debajo de verdad. */
  --nota-txt: #1d6a5e;       /* 5,65 sobre su tinte claro (#e8f3f0) */
  --warning-txt: #815715;  /* 4,70 — el --warning crudo daba 3,06 */
  --acento-txt:  #755c2a;  /* dorado oscurecido: el original daba 3,05 */
  /* Familia para superficies oscuras (El Parte, cabeceras navy).
     Ojo con el fondo de referencia: no es el negro del panel, sino la
     TARJETA sobre él, que lleva un rgba del `--navy` de la paleta encima.
     En esmeralda esa mezcla sube hasta #343f29, que es bastante clara: por
     eso los tonos de abajo están calculados paleta a paleta contra el fondo
     más claro que se llegó a medir en cada una, y no contra un valor común.

     ⚠️ Y el peor fondo oscuro tampoco era el primero que salió. Con la app
     entera a la vista (la primera medición se hizo con `#app-layout` oculto y
     sólo alcanzaba 1.836 elementos de los 9.228 reales) apareció uno más claro
     todavía: #413d34, la caja del Consejo del Socio sobre el papel del Editor.
     Los tonos de abajo se recalcularon contra ése, con el listón en 4,6 en vez
     de 4,5 para dejar margen a la siguiente caja que aparezca. */
  --acento-claro:  #c8a461;   /* 4,61 sobre #413d34 */
  --danger-claro:  #e4958d;   /* 4,62 — el --danger crudo daba 1,84 ahí */
  --success-claro: #22c197;   /* 4,72 */
  /* 🔴 Subido de #de9d38 a #eab155 el 2026-08-08, y lo destapó una medición que
     casi no hago. El ámbar de letra se pinta MUY a menudo encima del ámbar de
     fondo (`.st.hoy`, `.s-hoy .kc-badge`, `.vigia-bar.vg-aviso`, `.plan-marca`,
     y ahora el aviso de vigencia normativa). Ese fondo es un rgba del propio
     ámbar al 16%, así que ACLARA el fondo oscuro —queda #514330— y se come el
     contraste: el #de9d38 daba 4,65 sobre el oscuro liso pero sólo **4,00**
     sobre su propio tinte, o sea por debajo del mínimo en todos esos sitios a
     la vez. Ahora: 4,87 sobre el tinte y 5,62 sobre el liso.
     🔑 Es el mismo error de método que ya costó una vuelta entera en este
     archivo: medir contra el fondo «oficial» y no contra el que hay DEBAJO de
     verdad. Las capas semitransparentes suman. */
  --warning-claro: #eab155;   /* 5,62 sobre el oscuro liso · 4,87 sobre su propio tinte */
  --audiencia-claro: #e39ad6; /* 5,08 — el --audiencia crudo daba 1,48 */

  /* ============================================================
     🎨 07-09-2026 (tarde) · LA TERCERA FAMILIA: `--senal-*`
     ------------------------------------------------------------
     Piero, mirando su agenda en modo OSCURO: *«todavía los veo idénticos, y lo
     de azul se ve mal en oscuro, ni se nota»*. Y al medirlo, otra vez la causa
     NO era la que parece — no es el tono, es que **en oscuro la pastilla hueca
     no tiene forma ninguna**:

         .tudia-pill.prox = color-mix(var(--info) 12%) sobre la tarjeta
         fondo  #1c2735 contra la tarjeta #1a2029 →  1,08:1
         borde  #20344c contra la tarjeta        →  1,29:1   (1,00 = invisible)

     🔑 **Mezclar una tinta OSCURA sobre un fondo OSCURO no produce nada.**
     `--info` (#2b5b8f) está al 36% de claridad y la tarjeta al 13%: al 12% de
     mezcla la diferencia es de un punto. En claro la misma regla da 1,72 de
     borde y funciona; en oscuro pintaba texto azul flotando en el aire. Lo
     mismo le pasaba a la FRANJA de la fila, que iba en el token crudo: 1,24:1
     contra la tarjeta el azul y 1,91:1 el morado — de ahí «los veo idénticos».

     Ya había DOS familias (`*-txt` para letra, `*-claro` para superficies
     oscuras en los dos modos). Falta la de las SEÑALES: el color cuando se usa
     como franja, tinte o borde encima del fondo de la app. En claro es el
     color de siempre —así ninguna pantalla clara cambia—; en oscuro, su
     versión clara.
     ✅ Medido con `--senal-info` al 12%/55%: borde 2,66:1 contra la tarjeta
     (era 1,29 ⇒ **2,1× más presencia**) y el texto dentro se queda en 4,65:1,
     por encima del 4,5 mínimo. Las franjas pasan de 1,2-1,9 a 5,6-8,5:1.
     ⚠️ NO se reusa `--*-txt` para esto aunque en claro coincidan casi todos:
     `--warning-txt` (#815715) es un ámbar oscurecido *para leerse*, y como
     franja pintaría de marrón lo que hoy es ámbar. Una familia por trabajo.
     ============================================================ */
  --senal-danger:    var(--danger);
  --senal-warning:   var(--warning);
  --senal-info:      var(--info);
  --senal-audiencia: var(--audiencia);
  --senal-nota:      var(--nota);
}
html[data-palette="azul"]      { --acento-txt: #245ab0; --acento-claro: #86ace4; } /* 4,64 */
html[data-palette="esmeralda"] { --acento-txt: #0b6f55; --acento-claro: #12c395; } /* 4,75 */
html[data-palette="burdeos"]   { --acento-txt: #8a2942; --acento-claro: #df94a7; } /* 4,60 */
html[data-palette="cobre"],
html[data-palette="grafito"]   { --acento-txt: #8c4522; --acento-claro: #dc9d76; } /* 4,70 */
html[data-palette="purpura"]   { --acento-txt: #6636bf; --acento-claro: #b9a0e9; } /* 4,76 */

body.dark-mode {
  --ink-1: #eef2f7;   /* 8,9:1 sobre el peor fondo oscuro */
  --bg-2:  #141920;
  --ink-3: #8a99ac;        /* 4,62 */
  --danger-txt:  var(--danger-claro);   /* el #b3362a original daba 2,71 */
  --success-txt: var(--success-claro);
  --info-txt:    #679bd1;  /* 4,57 */
  --audiencia-txt: var(--audiencia-claro);
  --warning-txt: var(--warning-claro);
  --nota-txt: #5cc9b2;     /* 4,97 sobre el peor fondo oscuro real · 7,06 sobre la tarjeta */
  --acento-txt:  var(--acento-claro);
  /* Y LAS SEÑALES (franjas, tintes y bordes de pastilla): la versión clara.
     Contra la tarjeta #1a2029, de 1,2-1,9:1 a esto: */
  --senal-danger:    var(--danger-claro);    /* 7,00 */
  --senal-warning:   var(--warning-claro);   /* 8,51 */
  --senal-info:      var(--info-txt);        /* 5,60 — era 1,24 */
  --senal-audiencia: var(--audiencia-claro); /* 7,69 — era 1,91 */
  --senal-nota:      var(--nota-txt);        /* 8,15 */
}

/* 🔴 CORTA LAS TRANSICIONES MIENTRAS SE CAMBIA DE MODO O DE PALETA.
   Sin esto, lo que tenga `transition: color` y pinte con `color: var(--x)` se
   queda con el color ANTERIOR: Chrome no reevalúa una propiedad en transición
   cuando la variable cambia en un ancestro. Comprobado con un control el
   2026-08-05 sobre `.ia-chip`: la variable ya valía #c5a059 y el color seguía
   en #755c2a; anulando la transición saltaba al correcto al instante.
   Son 18 reglas con `transition: … color`: se apagan todas de una vez en lugar
   de perseguirlas una a una. Lo pone y lo quita `_sinTransiciones()` (ui.js). */
html.cambiando-tema, html.cambiando-tema *,
html.cambiando-tema *::before, html.cambiando-tema *::after {
  transition: none !important;
}

/* ---------- Menú de perfil + Configuración ---------- */
.perfil-menu-wrap { position: relative; }
.perfil-btn {
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  background: transparent; border: 1px solid var(--line); border-radius: var(--r-pastilla);
  padding: 4px 10px 4px 4px; transition: border-color var(--speed), background var(--speed);
  /* Sin esto heredaba el tamaño que el navegador da por defecto a los
     botones (13,33 px), que no es ningún paso de la escala. */
  font-size: 13px;
}
.perfil-btn:hover { border-color: var(--gold); }
.perfil-avatar {
  width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0;
  background: linear-gradient(135deg, var(--gold), var(--gold-strong));
  color: #fff; display: inline-flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 13px; overflow: hidden;
}
/* Avatar con el logo del estudio (en vez de las iniciales) */
.perfil-avatar.con-logo {
  background-color: #fff; background-image: none;
  background-size: contain; background-position: center; background-repeat: no-repeat;
  color: transparent; box-shadow: inset 0 0 0 1px var(--line);
}
.perfil-dropdown {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 3000;
  min-width: 230px; background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-md); box-shadow: var(--shadow-3); padding: 6px;
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity var(--speed), transform var(--speed), visibility var(--speed);
}
.perfil-dropdown.abierto { opacity: 1; visibility: visible; transform: none; }
.perfil-dropdown .pd-head { padding: 10px 12px; border-bottom: 1px solid var(--line); margin-bottom: 6px; }
.perfil-dropdown .pd-nombre { font-weight: 700; font-size: 13px; color: var(--ink); }
.perfil-dropdown .pd-sub { font-size: 12px; color: var(--ink-3); margin-top: 2px; }
.perfil-item {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 10px 12px; border-radius: var(--r-sm); cursor: pointer;
  font-size: 13px; color: var(--ink-2); background: none; border: none; text-align: left;
  transition: background var(--speed);
}
.perfil-item:hover { background: var(--paper); color: var(--ink); }
.perfil-item i { width: 16px; text-align: center; color: var(--ink-3); }
.perfil-item.peligro { color: var(--danger-txt); }
.perfil-item.peligro i { color: var(--danger-txt); }
.perfil-sep { height: 1px; background: var(--line); margin: 6px 4px; }

/* Configuración: navegación por secciones */
.cfg-layout { display: grid; grid-template-columns: 190px 1fr; gap: 18px; }
.cfg-nav { display: flex; flex-direction: column; gap: 2px; }
.cfg-nav button {
  display: flex; align-items: center; gap: 10px; padding: 10px 12px; border-radius: var(--r-sm);
  background: none; border: none; cursor: pointer; font-size: 13px; font-weight: 600;
  color: var(--ink-2); text-align: left; transition: background var(--speed), color var(--speed);
}
.cfg-nav button i { width: 16px; text-align: center; }
.cfg-nav button:hover { background: var(--paper); }
.cfg-nav button.activo { background: var(--gold-soft); color: var(--acento-txt); }
/* Rótulo de grupo. Copia el aspecto de `.atajos-sec h4`, que es el rótulo de
   grupo que la app YA dibujaba: dos maneras distintas de rotular un grupo en la
   misma app se leerían como dos cosas distintas. */
.cfg-grupo {
  font-size: 11px; text-transform: uppercase; letter-spacing: .06em; font-weight: 700;
  color: var(--ink-3); padding: 14px 12px 4px;
}
.cfg-grupo:first-child { padding-top: 0; }

/* ============================================================
   🔴 2026-08-14 · EL MENÚ DE CONFIGURACIÓN SE IBA DE LA PANTALLA
   ------------------------------------------------------------
   Lo vio Piero y mandó la captura: el menú empezaba en «Apariencia» porque
   Perfil, Miembros, Casilla SINOE, Tu plan y Cómputo de plazos ya se habían
   ido por arriba. MEDIDO en el navegador dentro del Centro Legal, que es la
   sección más larga: al bajar del todo el menú sube 602 px y quedan
   **0 de 9 botones** a la vista. El abogado lee, y se queda sin forma de
   volver a nada: tiene que subir a ciegas.
   LA CAUSA: quien se desplazaba era la CAJA ENTERA (`.modal-content`, con
   `overflow-y:auto` y `max-height:90vh`), así que el menú viajaba dentro del
   contenido como un párrafo más — `.cfg-nav` es `position: static`.
   EL ARREGLO no es pegar el menú con `position: sticky`. Eso lo dejaría quieto
   pero seguiría desplazando la caja, y el título «Configuración» se iría
   igual. Se le QUITA el desplazamiento a la caja y se le da AL PANEL: cabecera
   y menú quietos, y sólo se mueve lo que se está leyendo.
   · `min-height: 0` no es adorno: sin él un hijo de un contenedor flexible no
     puede encoger por debajo de su contenido y el panel no llegaría a tener
     barra nunca — se desbordaría por abajo, escondido tras `overflow:hidden`.
   · El menú lleva su propia barra por si la ventana es MUY baja: once botones
     no caben en 300 px de alto, y sin ella los últimos quedarían inalcanzables
     — que es el fallo que esto viene a arreglar, sólo que al revés.
   🪤 SÓLO DE 641 PX PARA ARRIBA. Por debajo, menú y panel se APILAN (ver el
   `@media (max-width: 640px)` de más abajo): el menú deja de estar al lado y
   pasa a estar ENCIMA, y once botones pegados arriba se comerían media
   pantalla del celular. Ahí sigue desplazándose la caja entera, que es lo
   correcto cuando el menú va delante y no al lado. Comprobado a 375.
   ============================================================ */
@media (min-width: 641px) {
  #modal-config .modal-content { display: flex; flex-direction: column; overflow: hidden; }
  #modal-config .modal-head { flex: 0 0 auto; }
  #modal-config .cfg-layout { flex: 1 1 auto; min-height: 0; }
  #modal-config .cfg-nav { overflow-y: auto; }
  #modal-config .cfg-panel { overflow-y: auto; min-height: 0; }
}
.cfg-sec { display: none; }
.cfg-sec.activa { display: block; }
.cfg-sec h4 { font-size: 14px; color: var(--ink); margin: 0 0 4px; }
.cfg-sec .cfg-desc { font-size: 13px; color: var(--ink-3); margin: 0 0 16px; line-height: 1.5; }
/* 🪤 2026-08-10 — «en Configuración unas letras salen mucho más grandes que
   otras» (Piero). La sospecha era `rem` mezclado con `px` y `em` anidado: NO
   era eso. En toda Configuración no hay un solo `em` ni un solo `rem`. Lo que
   pasaba es más tonto: `.cfg-hint` —13 usos entre app.html y plan.js— nunca
   tuvo regla propia, así que heredaba los 15px del documento mientras todo lo
   de al lado estaba bajado a 12, 13 y 14. La letra que sobresalía no era la
   que se pasó de grande: era la única a la que se le olvidó vestirla, y
   acababa siendo MÁS GRANDE que el título de sección al que acompañaba.
   Va a 13px, que es el cuerpo de Configuración y el tamaño de `.cfg-desc`,
   que hace exactamente el mismo trabajo. */
.cfg-hint { font-size: 13px; line-height: 1.5; }

/* Bloques de "Cuenta y acceso" */
.cfg-block { border: 1px solid var(--line); border-radius: var(--r-md); padding: 14px 16px; margin-bottom: 14px; background: var(--paper); }
/* ============================================================
   🔔 CUÁNTO ANTES SUENA CADA COSA (Google Calendar) — 03-09-2026
   ------------------------------------------------------------
   🪤 LA REJILLA VA CON `minmax(0, …)` Y NO CON `1fr`, y es la tercera vez que
   esta trampa aparece en esta casa: `1fr` es `minmax(auto, 1fr)`, y ese `auto`
   es el min-content del hijo — o sea que una columna `1fr` NO DEJA ENCOGER lo
   que lleva dentro. Con un rótulo largo («Notas, reuniones y diligencias») la
   columna del desplegable se aplastaba. El mismo fallo que descuadró la
   rejilla de Facturación y el hero de la portada.
   🪤 Y LAS CASILLAS LLEVAN SU DEFENSA. La regla global de arriba pone
   `width:100%` a TODO `input`: sin esto, la casilla de «todo junto» se estira
   de lado a lado de la caja. Ya se comió los círculos tres veces.
   ============================================================ */
.gcal-av-rej {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(140px, 190px);
  gap: 10px 14px; align-items: center;
}
.gcal-av-rej label { font-size: 12.5px; color: var(--ink-2); display: flex; align-items: center; gap: 8px; min-width: 0; }
.gcal-av-rej label i { color: var(--acento-txt); width: 15px; text-align: center; flex: none; }
.gcal-av-sel { font-size: 12.5px; padding: 8px 10px; }
.gcal-av-fila input[type="checkbox"] {
  width: 16px; height: 16px; min-width: 16px; flex: 0 0 16px;
  margin: 0; padding: 0; border-radius: 4px;
  accent-color: var(--acento-txt); cursor: pointer;
}
/* En el móvil, el rótulo arriba y el desplegable debajo: a 375 px las dos
   columnas dejan al desplegable en 140 px y «15 minutos antes» no cabe. */
@media (max-width: 560px) {
  .gcal-av-rej { grid-template-columns: minmax(0, 1fr); gap: 4px 0; }
  .gcal-av-rej .gcal-av-sel { margin-bottom: 8px; }
}
.cfg-block-tit { font-size: 13px; font-weight: 700; color: var(--ink); display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.cfg-block-tit i { color: var(--acento-txt); }

/* ---- LAS CASILLAS DEL SINOE, UNA POR ABOGADO (2026-08-20) --------
   Una fila por casilla: de quién es, cómo va y —sólo en la propia— los botones.
   🪤 `grid-template-columns` con `minmax(0, …)` y no `1fr` a secas: `1fr` es
   `minmax(auto, 1fr)` y NO deja encoger la columna, así que un nombre largo
   ensancharía la fila y empujaría los botones fuera del bloque. Es la misma
   trampa que aplastó la rejilla de facturación el 19-08. */
.cas-fila { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr) auto;
  gap: 6px 14px; align-items: center; padding: 10px 0; border-bottom: 1px solid var(--line); }
.cas-fila:last-of-type { border-bottom: none; }
.cas-quien { font-size: 13px; color: var(--ink); display: flex; align-items: center; gap: 7px; min-width: 0; }
.cas-quien > i { color: var(--ink-3); font-size: 11px; flex: none; }
.cas-quien b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cas-tu { font-size: 11px; font-weight: 800; letter-spacing: .04em; text-transform: uppercase;
  color: var(--accent-ink); background: var(--gold-soft); border: 1px solid var(--gold);
  border-radius: var(--r-pastilla); padding: 1px 7px; flex: none; }
.cas-datos { font-size: 12px; color: var(--ink-2); line-height: 1.5; min-width: 0; }
.cas-acc { display: flex; gap: 6px; justify-content: flex-end; flex-wrap: wrap; }
.cas-otras-tit { font-size: 11px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase;
  color: var(--ink-3); margin: 14px 0 2px; }
.cas-nota, .cas-cupo { font-size: 11.5px; color: var(--ink-3); line-height: 1.55; margin-top: 10px; }
.cas-cupo { padding-top: 10px; border-top: 1px solid var(--line); }
.cas-cupo > i { color: var(--ink-3); margin-right: 5px; }
/* En el celular la fila se apila: tres columnas en 375 px dejan los botones
   en una tira de un carácter. 🪤 El aviso de iOS del 20-08 vale también aquí:
   nada de bajar el tamaño de letra por debajo de 16 px en campos. */
@media (max-width: 640px) {
  .cas-fila { grid-template-columns: 1fr; gap: 4px; }
  .cas-acc { justify-content: flex-start; margin-top: 4px; }
}
.cfg-estado { font-size: 12px; color: var(--ink-3); margin-bottom: 8px; min-height: 14px; }
.cfg-estado.err { color: var(--danger-txt); }
.cfg-estado.ok { color: var(--success-txt); }

/* Centro Legal — acordeón de documentos */
.legal-doc { border: 1px solid var(--line); border-radius: var(--r-md); margin-bottom: 8px; overflow: hidden; background: var(--paper); }
.legal-doc > summary { list-style: none; cursor: pointer; padding: 12px 14px; font-size: 13px; font-weight: 700; color: var(--ink); display: flex; align-items: center; gap: 10px; user-select: none; }
.legal-doc > summary::-webkit-details-marker { display: none; }
.legal-doc > summary i { color: var(--acento-txt); width: 16px; text-align: center; }
/* 🟡 2026-08-14 — «Términos y Condiciones y Política de Privacidad son lo mismo,
   cómo distinguirlos» (Piero). No lo son, pero el NOMBRE no dice qué hay dentro
   y los dos se leen igual de opacos. Cada documento lleva ahora una línea que
   dice de qué va. Va dentro del `<summary>`, que es lo único que se ve con el
   documento cerrado — ponerlo dentro del cuerpo no habría servido de nada. */
.legal-doc > summary small {
  display: block; font-weight: 400; font-size: 12px;
  color: var(--ink-3); margin-top: 3px; line-height: 1.45;
}
.legal-doc > summary::after { content: "\f078"; font-family: "Font Awesome 6 Free"; font-weight: 900; margin-left: auto; font-size: 11px; color: var(--ink-3); transition: transform var(--speed); }
.legal-doc[open] > summary::after { transform: rotate(180deg); }
.legal-doc[open] > summary { border-bottom: 1px solid var(--line); }
.legal-body { padding: 12px 16px 14px; font-size: 13px; line-height: 1.65; color: var(--ink-2); }
.legal-body p { margin: 0 0 10px; }
.legal-body b { color: var(--ink); }
.legal-body ul { margin: 4px 0 4px; padding-left: 18px; }
.legal-body li { margin-bottom: 4px; }
.legal-updated { font-size: 11px; color: var(--ink-3); margin-top: 12px; text-align: right; }

/* Paletas */
.paletas-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; }
/* ============================================================
   🌙 07-09-2026 · CLARO · OSCURO · AUTOMÁTICO
   ------------------------------------------------------------
   Un botón que alterna sólo puede decir DOS cosas, y ahora hay tres. Los tres
   van juntos y a la vista: cuál está puesto se lee sin pulsar nada, que es la
   diferencia entre un ajuste y una sorpresa.
   El botón de un toque de la barra lateral y el de la puerta NO se quitan: son
   el atajo de todos los días. Éste es el sitio donde se vuelve al automático.
   ⚠️ La fila envuelve en el celular: son tres rótulos y en 390 px no caben al
   lado del título. Medido con el ancho del modal, no supuesto. */
.tema-modo { margin-top: 18px; border-top: 1px solid var(--line); padding-top: 14px;
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 10px 12px; }
.tema-modo-cab { flex: 1 1 200px; min-width: 0; }
.tema-modo-tit { font-weight: 600; font-size: 13px; color: var(--ink); }
.tema-opciones { display: inline-flex; flex: 0 0 auto; border: 1px solid var(--line-strong); border-radius: var(--r-md); overflow: hidden; }
.tema-op { display: inline-flex; align-items: center; gap: 6px; font-family: inherit; font-size: 12px; font-weight: 700;
  color: var(--ink-3); background: var(--paper); border: 0; padding: 7px 12px; cursor: pointer; white-space: nowrap;
  transition: background var(--speed), color var(--speed); }
.tema-op + .tema-op { border-left: 1px solid var(--line-strong); }
.tema-op i { font-size: 11px; }
.tema-op:hover { background: var(--gold-soft); color: var(--ink); }
.tema-op:focus-visible { outline: 2px solid var(--gold); outline-offset: -2px; }
/* El elegido va MACIZO, como las pastillas de la agenda: la misma regla de la
   casa para decir «esto es lo que está puesto». */
.tema-op.on { background: var(--gold); color: var(--navy-950); }
.tema-auto-pie { flex-basis: 100%; margin: 0; }
.tema-auto-pie:empty { display: none; }
.paleta-opt {
  display: flex; align-items: center; gap: 10px; padding: 10px; cursor: pointer;
  border: 1.5px solid var(--line); border-radius: var(--r-md); transition: border-color var(--speed), transform 120ms var(--ease);
  background: var(--paper);
}
.paleta-opt:hover { transform: translateY(-1px); border-color: var(--gold); }
.paleta-opt.activa { border-color: var(--gold); box-shadow: 0 0 0 2px var(--gold-soft); }
.paleta-swatches { display: inline-flex; flex-shrink: 0; }
.paleta-swatches span { width: 18px; height: 18px; border-radius: 50%; border: 2px solid var(--card); margin-left: -6px; }
.paleta-swatches span:first-child { margin-left: 0; }
.paleta-nombre { font-size: 13px; font-weight: 600; color: var(--ink); }

@media (max-width: 640px) {
  .cfg-layout { grid-template-columns: 1fr; }
  .cfg-nav { flex-direction: row; flex-wrap: wrap; }
  /* 📌 LOS RÓTULOS NO SALEN EN EL CELULAR — lo decidió Piero el 14-08 tras ver
     el número: aquí el menú es una fila que se envuelve y va ENCIMA del
     contenido, no al lado, así que los tres rótulos lo estiraban de 340 a
     423 px — del 42% al 52% de la pantalla— y eso son 83 px más que recorrer
     antes de llegar a lo que has ido a leer.
     🔑 En el escritorio SÍ salen: allí el menú está quieto en su columna y
     agrupar no cuesta nada. El ORDEN de los botones es el mismo en los dos
     sitios, que es lo que de verdad pidió: primero lo del estudio, luego lo de
     la cuenta, y al final la información del producto. */
  .cfg-grupo { display: none; }
}

/* ---------- Banner de estado de cuenta (prueba / congelada) ---------- */
.cuenta-banner {
  display: flex; align-items: center; justify-content: center; gap: 14px;
  flex-wrap: wrap; padding: 10px 18px; font-size: 13px; font-weight: 600; text-align: center;
}
.cuenta-banner b { font-weight: 800; }
.cuenta-banner i { margin-right: 4px; }
.cuenta-banner button {
  border: none; border-radius: var(--r-md); padding: 8px 16px; font-size: 13px;
  font-weight: 700; cursor: pointer; white-space: nowrap; transition: filter var(--speed);
}
.cuenta-banner button:hover { filter: brightness(1.06); }
.cb-prueba { background: var(--amber-soft); color: var(--amber-strong); border-bottom: 1px solid rgba(197,160,89,.42); }
.cb-prueba button { background: var(--amber); color: #3a2c0e; }
.cb-congelada { background: rgba(43,91,143,.12); color: var(--info-txt); border-bottom: 1px solid rgba(43,91,143,.36); }
.cb-congelada button { background: var(--info); color: #fff; }
/* El estudio MARCADO PARA ELIMINACIÓN va en rojo, no en el azul informativo del
   congelado: no es un cambio de plan, es que en N días se borra todo y no se
   puede deshacer. Los dos estados compartían color y el más grave se leía como
   el más leve. Tokens, no colores sueltos (ver [[contraste-variables-texto]]). */
.cb-peligro { background: var(--danger-bg); color: var(--danger-txt); border-bottom: 1px solid var(--danger-txt); }
/* 🪤 El botón lleva `--danger` (el token CRUDO), no `--danger-txt`. En modo
   oscuro `--danger-txt` es un rojo CLARO —está pensado para leerse SOBRE el
   fondo oscuro—, y usarlo de fondo con letra blanca daba 2,34 de contraste:
   medido, no supuesto. El crudo es oscuro en los dos modos, que es lo que
   necesita un botón de letra blanca. Es lo mismo que hace `.cb-congelada` con
   `--info`, y por la misma razón. */
.cb-peligro button { background: var(--danger); color: #fff; }
/* Correo sin verificar: informativo, NO alarma. No hay nada roto ni nada que
   caduque — el abogado puede trabajar. Por eso va en el azul de `--info`, el
   mismo de «congelada», y no en el rojo de peligro ni en el ámbar de la prueba
   (que sí lleva cuenta atrás). Tokens, no colores sueltos. */
/* El preaviso de cambio de condiciones comparte el mismo azul informativo, y
   comparte la REGLA en vez de copiarle los valores: si algún día ese azul
   cambia, cambian los dos a la vez. Es informativo por lo mismo que el del
   correo — no hay nada roto, el abogado puede trabajar, y durante los quince
   días de preaviso sigue rigiendo la versión que ya aceptó. */
.cb-correo, .cb-legal { background: rgba(43,91,143,.12); color: var(--info-txt); border-bottom: 1px solid rgba(43,91,143,.36); }
.cb-correo button, .cb-legal button { background: var(--info); color: #fff; }

/* El mismo aviso, pero PEGADO al control que se va a encontrar frenado
   (regla 8: nada se calla, y se dice antes de pulsar). */
.freno-correo {
  margin: 8px 0 10px; padding: 9px 12px; border-radius: var(--r-md);
  background: rgba(43,91,143,.10); border: 1px solid rgba(43,91,143,.30);
  color: var(--info-txt); font-size: 12px; line-height: 1.6;
}
.freno-correo i { margin-right: 5px; }
.freno-correo a { color: var(--info-txt); font-weight: 700; text-decoration: underline; }

/* ---------- Marca de producto (white-label) al pie del sidebar ---------- */
.producto-marca { padding: 12px 16px 6px; margin-top: 6px; border-top: 1px solid rgba(255,255,255,0.08); text-align: center; }
.producto-marca .pm-por { display: block; font-size: 11px; letter-spacing: .6px; text-transform: uppercase; color: rgba(255,255,255,0.38); }
.producto-marca .pm-nombre { display: block; font-size: 13px; font-weight: 800; color: var(--gold); letter-spacing: .3px; margin-top: 2px; }
.producto-marca .pm-nombre i { font-size: 11px; margin-right: 4px; }
.producto-marca .pm-logo { display: block; width: 150px; max-width: 82%; height: auto; margin: 6px auto 0; opacity: .95; }

/* ---------- El menú en portátiles con la pantalla al 125% ---------- */
/* MEDIDO (no a ojo): el menú necesita 730 px de alto — logo 97 + botón 62 +
   opciones 364 + modo oscuro 42 + marca 121 + márgenes 44. Un portátil de
   1920×1080 con el escalado de Windows al 125% deja 864 px, y de ahí hay que
   descontar la barra del navegador: se queda corto. Lo último de la columna
   —la marca del producto— caía fuera de la pantalla, y NADIE se enteraba,
   porque el menú no tenía barra para bajar: simplemente desaparecía.
   Dos redes, no una: primero se comprime para que quepa entero, y si aun así
   no cabe (pantallas más bajas todavía), se puede desplazar. */
#sidebar { overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; }
#sidebar::-webkit-scrollbar { width: 6px; }
#sidebar::-webkit-scrollbar-thumb { background: rgba(255,255,255,.16); border-radius: 3px; }

@media (max-height: 820px) {
  #sidebar { padding-top: 14px; padding-bottom: 12px; }
  .sidebar-logo { padding: 4px 6px 10px; }
  .sidebar-logo img { width: 56px; height: 56px; }
  .brand-name { font-size: 16px; margin-top: 6px; }
  .producto-marca { padding: 8px 16px 4px; }
  .producto-marca .pm-logo { width: 112px; margin-top: 4px; }
}

/* ---------- Barra de herramientas del Estado Procesal ---------- */
/* Una sola línea: título a la izquierda · Rama centrada · Exportar a la derecha.
   Los flex:1 en título y export (con la Rama en medio) centran la Rama. */
.kanban-toolbar { display: flex; align-items: center; gap: 12px; justify-content: flex-start; flex-wrap: wrap; }
.kanban-toolbar .kt-title { flex: 1 1 220px; min-width: 0; white-space: nowrap; }
.kanban-toolbar .kt-rama { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; }
.kanban-toolbar .kt-rama label { font-size: 12px; font-weight: 700; color: var(--ink-2); margin: 0; }
.kanban-toolbar .kt-rama select { width: auto; max-width: 200px; min-width: 130px; font-size: 13px; padding: 8px 10px; }
.kanban-toolbar .kt-export-wrap { flex: 1 1 220px; display: flex; justify-content: flex-end; }
.kanban-toolbar .kt-export { width: auto; min-height: 38px; white-space: nowrap; }
@media (max-width: 620px) {
  /* En móvil (no cabe 1 línea): 3 filas ordenadas y centradas. */
  .kanban-toolbar { justify-content: center; text-align: center; }
  .kanban-toolbar .kt-title { flex: 1 1 100%; white-space: normal; justify-content: center; }
  .kanban-toolbar .kt-rama { flex: 1 1 100%; justify-content: center; }
  .kanban-toolbar .kt-export-wrap { flex: 1 1 100%; justify-content: center; }
  .kanban-toolbar .kt-export { width: 100%; max-width: 260px; }
}

/* ---------- Contador por columna del Kanban ---------- */
.kanban-header { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.kanban-count { background: var(--gold-soft); color: var(--acento-txt); font-size: 11px; font-weight: 700; padding: 1px 8px; border-radius: var(--r-md); flex-shrink: 0; }

/* ---------- Ficha estructurada del Socio IA (tabla resumen) ---------- */
.ficha-ia { margin: 0 0 14px; border: 1px solid var(--gold); border-radius: var(--r-md); overflow: hidden; background: var(--card); }
.ficha-ia__head { padding: 8px 12px; font-weight: 700; background: var(--gold-soft); color: var(--acento-txt); font-size: .9rem; display: flex; align-items: center; gap: 8px; }
.ficha-ia table { width: 100%; border-collapse: collapse; font-size: .92rem; }
.ficha-ia td { padding: 8px 12px; border-top: 1px solid var(--line-strong); vertical-align: top; }
.ficha-ia td.k { font-weight: 600; color: var(--acento-txt); white-space: nowrap; width: 38%; }
.ficha-ia td.k i { width: 16px; margin-right: 6px; text-align: center; }
.ficha-ia .sf { display: inline-block; padding: 1px 10px; border-radius: var(--r-pastilla); font-size: .78rem; font-weight: 700; }
.ficha-ia .sf-si { background: rgba(34,153,84,.16); color: #2e9e5b; }
.ficha-ia .sf-no { background: rgba(197,160,89,.16); color: var(--acento-txt); }
.ficha-ia .sf-na { background: var(--gold-soft); color: var(--gray); }

/* ============================================================
   CONSEJO DEL SOCIO AL REDACTAR (Editor Jurídico)
   ------------------------------------------------------------
   Vive en la columna izquierda del Editor (330px), así que todo
   es compacto: el detalle jurídico va en un <details> plegado.
   ============================================================ */
.cs-card { border: 1px solid var(--gold); border-radius: var(--r-sm); background: var(--gold-soft); padding: 12px 12px; margin: 0 0 12px; }
.cs-top { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .4px; color: var(--acento-txt); display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.cs-firma { font-size: 13px; line-height: 1; }
.cs-tipo { text-transform: none; letter-spacing: 0; color: var(--ink-2); font-weight: 600; }
.cs-motivo { margin-top: 8px; font-size: 12px; line-height: 1.5; color: var(--ink-2); background: var(--paper); border-left: 3px solid var(--gold-strong); border-radius: 0 var(--r-sm) var(--r-sm) 0; padding: 6px 8px; }
.cs-enfoque { margin: 8px 0 0; font-size: 13px; line-height: 1.55; color: var(--ink-1); }
.cs-h { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .4px; color: var(--ink-2); display: flex; align-items: center; gap: 6px; margin-bottom: 6px; }
.cs-falta { margin-top: 10px; background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 8px 10px; }
.cs-falta ul { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px; }
.cs-falta li { font-size: 12px; color: var(--ink-1); line-height: 1.4; display: flex; flex-direction: column; }
.cs-falta li span { font-size: 11px; color: var(--ink-3); }
.cs-ok { margin-top: 10px; font-size: 12px; color: var(--ink-2); display: flex; align-items: center; gap: 6px; }
.cs-ok i { color: var(--acento-txt); }
/* El pliegue del Consejo (2026-08-06). El Consejo se había comido la pantalla:
   quedaba encajado entre el paso 1 y el paso 2, así que el campo «Tema /
   indicación» y el botón «Generar borrador» —lo único que HACE algo— caían
   fuera de la vista. Fuera del pliegue se quedan solo los AVISOS (el del Vigía
   con su fecha y los datos que faltan); el consejo, que se lee una vez, entra
   aquí. Un aviso de vencimiento que no se ve es peor que un botón que hay que
   buscar, por eso no se plegó todo. */
.cs-mas { margin-top: 10px; border-top: 1px solid var(--line); padding-top: 8px; }
.cs-mas > summary {
  list-style: none; cursor: pointer; user-select: none;
  font-size: 12px; font-weight: 700; color: var(--acento-txt);
}
.cs-mas > summary::-webkit-details-marker { display: none; }
.cs-mas > summary::before { content: "▸ "; }
.cs-mas[open] > summary::before { content: "▾ "; }

.cs-det { margin-top: 10px; border-top: 1px solid var(--line); padding-top: 8px; }
.cs-det > summary { list-style: none; cursor: pointer; font-size: 12px; font-weight: 700; color: var(--acento-txt); display: flex; align-items: center; gap: 6px; user-select: none; }
.cs-det > summary::-webkit-details-marker { display: none; }
.cs-clave { margin: 8px 0 0; padding-left: 16px; display: flex; flex-direction: column; gap: 6px; }
.cs-clave li { font-size: 12px; line-height: 1.45; color: var(--ink-2); }
/* «Ojo con esto» del Consejo del Socio: ÁMBAR desde el 08-08, por lo mismo que
   `.an-vigencia` — es una advertencia, no un error ni la marca del estudio. */
.cs-ojo { margin-top: 8px; font-size: 12px; line-height: 1.45; color: var(--warning-txt); }
.cs-ia { margin-top: 10px; background: var(--paper); border: 1px solid var(--line); border-radius: var(--r-sm); padding: 10px 10px; }
.cs-ia-txt { font-size: 12px; line-height: 1.55; color: var(--ink-1); max-height: 260px; overflow: auto; }
.cs-btn { width: 100%; justify-content: center; margin-top: 10px; }
.cs-nota { margin: 8px 0 0; font-size: 11px; line-height: 1.4; color: var(--ink-3); }

/* ---------- Editor Jurídico: fases del panel (de-saturación) ---------- */
/* Rotulan las 3 etapas del panel lateral (elegir → redactar → herramientas)
   para que el abogado no vea un muro de controles sueltos. */
.ed-fase { display:flex; align-items:center; gap:8px; margin:16px 0 10px; font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.6px; color:var(--ink-3); }
.ed-fase:first-of-type { margin-top:4px; }
.ed-fase::after { content:""; flex:1; height:1px; background:var(--line); }
.ed-fase .n { display:inline-flex; align-items:center; justify-content:center; width:16px; height:16px; border-radius:50%; background:var(--gold-soft); color:var(--acento-txt); font-size:11px; }

/* ============================================================
   LA ESPERA (ui.js · iniciarEspera) — qué ve el abogado mientras
   el sistema trae el CEJ o revisa el SINOE. Sin barras de progreso:
   los pasos se resaltan, el reloj es real.
   ============================================================ */
.esp { border: 1px solid var(--line); border-radius: var(--r-sm); background: var(--paper); padding: 14px 16px; text-align: left; }
.esp-head { display: flex; align-items: center; gap: 12px; }
.esp-spin { color: var(--acento-txt); font-size: 17px; flex-shrink: 0; }
.esp-head-txt { min-width: 0; }
.esp-ahora { font-size: 13px; font-weight: 700; color: var(--ink); line-height: 1.4; }
.esp-reloj { font-size: 12px; color: var(--ink-3); margin-top: 2px; font-variant-numeric: tabular-nums; }
.esp-reloj.es-tarde { color: var(--warning-txt); font-weight: 600; }
.esp-lista { list-style: none; margin: 12px 0 0; padding: 0 0 0 4px; }
.esp-paso { display: flex; align-items: center; gap: 10px; font-size: 13px; color: var(--ink-3); padding: 4px 0; transition: color .25s ease; }
.esp-bolita { width: 7px; height: 7px; border-radius: 50%; background: var(--line-strong); flex-shrink: 0; transition: background .25s ease, transform .25s ease; }
.esp-paso.es-pasado { color: var(--ink-2); }
.esp-paso.es-pasado .esp-bolita { background: var(--gold-soft); border: 1px solid var(--gold); }
.esp-paso.es-ahora { color: var(--ink); font-weight: 700; }
.esp-paso.es-ahora .esp-bolita { background: var(--gold); transform: scale(1.45); box-shadow: 0 0 0 4px var(--gold-soft); }
.esp-consejo { margin-top: 14px; padding: 10px 12px; background: var(--gold-soft); border-radius: var(--r-sm); font-size: 12px; line-height: 1.6; color: var(--ink-2); }
.esp-consejo-tit { display: block; font-size: 11px; letter-spacing: .09em; text-transform: uppercase; font-weight: 700; color: var(--acento-txt); margin-bottom: 4px; }
.esp-consejo-txt { transition: opacity .22s ease; display: block; }
.esp-pie { margin-top: 10px; font-size: 11px; color: var(--ink-3); line-height: 1.5; font-style: italic; }
@media (prefers-reduced-motion: reduce) {
  .esp-paso, .esp-bolita, .esp-consejo-txt { transition: none; }
}

/* ============================================================
   MOVIMIENTO CON CRITERIO — 2026-07-28
   ------------------------------------------------------------
   Norma: en una herramienta que se abre diez veces al día, el
   movimiento tiene que DECIR algo (esto es nuevo / esto se puede
   tocar / esto acaba de cambiar). Si sólo decora, estorba: la
   primera semana gusta y la cuarta cansa.
   Por eso todo lo de aquí dura menos de 300 ms, no bloquea ningún
   clic, y muere entero con la regla de "reducir movimiento" que ya
   existe más arriba (línea ~659), que el sistema operativo activa
   para quien se marea con las animaciones.
   ============================================================ */

/* ---- 1. El trabajo de la noche aparece en cascada ----
   Las tarjetas de El Parte son lo que el sistema hizo mientras el
   abogado no estaba. Entrando escalonadas se leen como algo que
   ACABA de llegar, no como una pantalla que siempre estuvo ahí.
   45 ms entre una y otra: se percibe el orden sin que haya espera
   (las seis terminan en un cuarto de segundo). */
/* `backwards` y NO `both`, a propósito. Con `both` la animación se queda
   dueña del `transform` para siempre, y entonces el relieve del punto 2 no
   se aplicaba nunca: la tarjeta quedaba plana pasara lo que pasara.
   Con `backwards` la animación sólo manda ANTES de empezar (durante su
   retraso, para que la tarjeta no asome antes de tiempo) y suelta el control
   al terminar. Comprobado midiendo el giro real de la tarjeta. */
.p-m { animation: parteEntra .34s var(--ease) backwards; }
.p-m:nth-child(1) { animation-delay: 0ms; }
.p-m:nth-child(2) { animation-delay: 45ms; }
.p-m:nth-child(3) { animation-delay: 90ms; }
.p-m:nth-child(4) { animation-delay: 135ms; }
.p-m:nth-child(5) { animation-delay: 180ms; }
.p-m:nth-child(6) { animation-delay: 225ms; }
@keyframes parteEntra {
  from { opacity: 0; transform: translateY(10px) scale(.985); }
  to   { opacity: 1; transform: none; }
}

/* ---- 2. Relieve real en las tarjetas del panel ----
   El giro lo calcula ui.js siguiendo al cursor y lo escribe en dos
   variables. Aquí sólo se declara CÓMO se ve. Tope: 4 grados. Más
   que eso deja de parecer una tarjeta de papel y empieza a parecer
   un videojuego — y esto lo mira un abogado a las siete de la
   mañana. Sólo actúa en pantallas grandes y con ratón (abajo). */
.parte-hero { perspective: 1100px; }
.p-m {
  --tx: 0deg; --ty: 0deg;
  transform-style: preserve-3d;
  will-change: transform;
}
.p-m.tilt-on {
  /* Mientras el cursor está encima manda el giro, no la transición:
     con transición puesta el movimiento va a remolque y se siente
     gomoso en vez de sujeto al dedo. */
  transition: border-color .16s, background .16s, box-shadow .16s;
  transform: rotateX(var(--tx)) rotateY(var(--ty)) translateY(-3px) scale(1.012);
  box-shadow: 0 18px 40px rgba(8, 16, 25, .30);
}
/* El icono de la acción se despega un punto del plano: da la
   sensación de que la tarjeta tiene grosor, no de que gira un dibujo. */
.p-m.tilt-on .p-m-go { transform: translateZ(16px); }
.p-m-go { transition: transform .16s var(--ease); }

/* ---- 3. El botón principal tiene un reflejo, no un parpadeo ----
   Un solo barrido de luz al pasar por encima. Marca cuál es LA
   acción de la pantalla sin gritar. */
.btn-gold { position: relative; overflow: hidden; }
.btn-gold::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(105deg, transparent 38%, rgba(255,255,255,.30) 50%, transparent 62%);
  transform: translateX(-120%);
  transition: transform .62s var(--ease);
  pointer-events: none; /* el reflejo NUNCA se come el clic */
}
.btn-gold:hover::after { transform: translateX(120%); }

/* ---- 4. Estados que faltaban ----
   Un botón que no dice si está desactivado, o que no responde al
   ser pulsado, se siente roto aunque funcione. */
button:disabled, .btn-gold:disabled, .btn-navy:disabled {
  opacity: .5; cursor: not-allowed; filter: grayscale(.35);
}
button:disabled::after { display: none; }
.btn-gold:active, .btn-navy:active, .nav-btn:active { transform: translateY(1px) scale(.988); }
.nav-btn, .btn-gold, .btn-navy { transition: transform .12s var(--ease), background .16s, color .16s, border-color .16s; }

/* ---- 5. Nada de esto en móvil ni sin ratón ----
   En una pantalla táctil no hay "pasar por encima": el navegador
   simula el hover al tocar y la tarjeta se queda girada después
   del toque. Se apaga y punto. */
@media (hover: none), (max-width: 900px) {
  .p-m.tilt-on { transform: none; box-shadow: none; }
  .p-m.tilt-on .p-m-go { transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .p-m { animation: none; }
  .p-m.tilt-on { transform: none; }
  .p-m.tilt-on .p-m-go { transform: none; }
  .btn-gold::after { display: none; }
}

/* ---- Iconos dibujados (no de la tipografía de iconos) ----
   El de WhatsApp obligaba a descargar la familia "brands" entera (115 KB) y el
   círculo hueco, la familia "regular", para un solo uso. Dibujados aquí, pesan
   cero y heredan color y tamaño del texto. */
.ico-wa { width: 1em; height: 1em; fill: currentColor; display: inline-block; vertical-align: -0.125em; }
.circulo-hueco {
  display: inline-block; width: 9px; height: 9px; border: 2px solid currentColor;
  border-radius: 50%; vertical-align: middle; margin-right: 2px;
}

/* ============================================================
   SOCIO: DETENER Y VOLVER AL FINAL
   ------------------------------------------------------------
   El botón de detener ocupa exactamente el sitio del de enviar (se alternan),
   para que la barra no dé un salto al aparecer.
   ============================================================ */
.btn-stop-ia { background: var(--danger) !important; border-color: var(--danger-txt) !important; color: #fff !important; }
.btn-stop-ia:hover { filter: brightness(1.08); }
.ai-bubble.socio-detenido { color: var(--ink-3); font-style: italic; }
.btn-bajar-socio {
  position: absolute; right: 18px; bottom: 92px; z-index: 5;
  width: 34px; height: 34px; border-radius: 50%;
  align-items: center; justify-content: center;
  border: 1px solid var(--line-strong); background: var(--card); color: var(--ink-2);
  cursor: pointer; box-shadow: 0 3px 10px rgba(0, 0, 0, .16);
}
.btn-bajar-socio:hover { color: var(--acento-txt); border-color: var(--gold); }

/* ============================================================
   EL MARCADOR DEL PLAN (public/js/plan.js)
   ------------------------------------------------------------
   Dos piezas: la línea pequeña que va donde se gasta (dentro del Socio y en
   Mesa de Partes) y la tarjeta de Configuración → Tu plan.
   Todo con las variables del tema: hereda modo oscuro y el color del estudio
   sin una sola regla aparte. Nada de `transition: all` — congela el repintado
   del fondo cuando el estudio cambia de color (bug ya cazado dos veces).
   ============================================================ */
.plan-marca {
  display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
  font-size: 12px; font-weight: 600; color: var(--ink-3);
  padding: 6px 10px; margin: 0 0 8px; border-radius: 8px;
  border: 1px solid var(--line); background: var(--card);
}
.plan-marca i { font-size: 11px; opacity: .85; }
.plan-marca.plan-poco { color: var(--warning-txt); border-color: var(--warning-txt); background: var(--warning-bg); }
.plan-marca.plan-cortesia { color: var(--warning-txt); border-color: var(--warning-txt); background: var(--warning-bg); }
.plan-marca.plan-agotado { color: var(--danger-txt); border-color: var(--danger-txt); background: var(--danger-bg); }

/* ============================================================
   POR DÓNDE VA A IR LA CONSULTA AL CEJ — 2026-08-27
   ------------------------------------------------------------
   Hay dos caminos al portal y hasta hoy ninguno se anunciaba: el servidor
   (que el Poder Judicial lleva días rechazando) y la extensión del navegador
   (que sí entra). Piero instaló la extensión, pulsó, y se fue por el servidor
   sin que nada lo dijera. Este cartel lo dice antes de pulsar.
   🪤 NO es una `.plan-marca`: aquélla es un contador de cupo y ésta es una
   advertencia de dos estados. Reutilizar su clase habría atado dos cosas que
   cambian por motivos distintos — y el día que se retoque el cupo, esto se
   movería solo. Se apoya en los MISMOS tokens de color, que es lo que sí
   comparten. ============================================================ */
.cej-camino {
  display: flex; align-items: flex-start; gap: 8px; flex-wrap: wrap;
  font-size: 12px; line-height: 1.5; font-weight: 500;
  padding: 9px 12px; margin: 0 0 10px; border-radius: 8px;
  border: 1px solid var(--line); background: var(--card); color: var(--ink-2);
}
.cej-camino i { font-size: 12px; margin-top: 2px; flex: 0 0 auto; }
.cej-camino b { font-weight: 800; }
/* 🪤 `--success-txt` y `--success-bg`, que son los que EXISTEN (y tienen su
   pareja en modo oscuro). Una variable CSS inventada no da error: se queda en
   el color heredado y el cartel verde saldría gris sin que nadie se entere —
   la misma trampa del icono que no existe y no avisa. */
.cej-camino.ok { color: var(--success-txt); border-color: var(--success-txt); background: var(--success-bg); }
.cej-camino.aviso { color: var(--warning-txt); border-color: var(--warning-txt); background: var(--warning-bg); }

/* ============================================================
   🤖 LA VENTANA DEL ROBOT DEL CEJ — 2026-08-27
   ------------------------------------------------------------
   La pestaña del portal trabaja en SEGUNDO PLANO y esto es lo único que el
   abogado ve: qué está haciendo y, cuando toca, el código de seguridad.
   Lo pidió Piero: «una ventana como de robot que trabaja dentro de la app».
   ============================================================ */
.cej-robot { max-width: 460px; padding: 22px 24px 18px; }
.cej-robot-cab {
  display: flex; align-items: center; gap: 13px;
  padding-bottom: 14px; margin-bottom: 16px; border-bottom: 1px solid var(--line);
}
.cej-robot-icono {
  flex: 0 0 auto; width: 44px; height: 44px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--gold-soft); color: var(--acento-txt); font-size: 18px;
  overflow: hidden;   /* el escudo del estudio queda recortado en redondo */
}
/* 🏛️ 28-08 · El logo del estudio dentro del círculo. `contain` y no `cover`:
   un escudo con letras (como el de Gonzales Quesquén) recortado por los bordes
   pierde justo el nombre, que es lo que lo hace suyo. Con `contain` se ve
   entero, más pequeño, y se lee. El relleno deja que respire. */
.cej-robot-icono img {
  width: 100%; height: 100%; object-fit: contain; padding: 4px;
  display: block; background: transparent;
}
/* 🏛️ 30-08 · Las iniciales del estudio, para cuando aún no ha subido su logo.
   Antes ese hueco lo ocupaba el logo de SocioLegal, y eso hacía que el mismo
   sitio contara dos historias según un dato de configuración: con logo, el
   escudo del abogado; sin logo, el nuestro haciendo de suyo. */
.cej-robot-ini {
  font-family: var(--font-display); font-size: 16px; font-weight: 700;
  letter-spacing: .04em; cursor: help;
}
.cej-robot-cab h3 {
  font-family: var(--font-display); font-size: 17px; font-weight: 700;
  color: var(--ink); margin: 0 0 2px;
}
.cej-robot-cab p { font-size: 12.5px; color: var(--ink-2); margin: 0; }
.cej-robot-cuenta {
  font-size: 11px; font-weight: 700; color: var(--ink-3);
  background: var(--gold-soft); border-radius: 20px; padding: 1px 8px; margin-left: 4px;
}

.cej-robot-trabajando {
  display: flex; align-items: center; gap: 11px;
  font-size: 13.5px; color: var(--ink); font-weight: 600; line-height: 1.5;
  padding: 16px 0 6px;
}
.cej-robot-trabajando i { color: var(--gold); font-size: 15px; flex: 0 0 auto; }

/* La bitácora. `max-height` + scroll propio: los pasos se acumulan y sin tope
   la ventana crecería hasta empujar el código de seguridad fuera de la vista,
   que es justo lo que hay que tener delante. */
.cej-robot-bitacora {
  max-height: 108px; overflow-y: auto; margin-top: 12px;
  border-top: 1px solid var(--line); padding-top: 10px;
}
.cej-robot-bitacora:empty { display: none; }
.cej-robot-paso {
  display: flex; align-items: flex-start; gap: 8px;
  font-size: 11.5px; line-height: 1.45; color: var(--ink-3); margin-bottom: 5px;
}
.cej-robot-paso i { font-size: 9px; margin-top: 4px; flex: 0 0 auto; color: var(--success-txt); }
.cej-robot-paso.ahora { color: var(--ink); font-weight: 600; }
.cej-robot-paso.ahora i { color: var(--gold); }

.cej-robot-codigo p { font-size: 12.5px; color: var(--ink-2); line-height: 1.55; margin: 0 0 12px; }
.cej-robot-malo {
  color: var(--warning-txt) !important; background: var(--warning-bg);
  border-radius: 7px; padding: 7px 10px; font-weight: 600;
}
.cej-robot-captcha {
  display: block; margin: 0 auto 14px; border-radius: 8px;
  border: 1px solid var(--line-strong); background: #fff;
  /* El captcha del CEJ es pequeño y va escrito a mano alzada: se agranda para
     poder leerlo sin acercar la cara, y `pixelated` porque el suavizado de una
     imagen de 4 letras torcidas emborrona justo lo que hay que distinguir. */
  max-width: 260px; width: 100%; image-rendering: pixelated;
}
.cej-robot-fila { display: flex; gap: 10px; align-items: stretch; }
/* 🪤 `width` EXPLÍCITO. La regla global `input { width: 100% }` de esta hoja se
   ha comido ya tres veces un campo pequeño, y aquí dejaría el botón «Enviar»
   fuera de la ventana. `flex: 0 0 auto` sin ancho tampoco basta: el 100% sigue
   ganando como base. */
#cej-robot-cod {
  width: 132px; flex: 0 0 auto;
  text-align: center; text-transform: uppercase;
  font: 700 20px/1 var(--font-mono, ui-monospace, "SFMono-Regular", Menlo, monospace);
  letter-spacing: 5px; padding: 10px 8px;
}
.cej-robot-fila .btn-gold { flex: 1 1 auto; }
/* El aviso del lector automático. `:empty` para que no deje hueco cuando no
   hay nada que decir, que es el caso normal. */
.cej-robot-lector {
  margin: 10px 0 0 !important; font-size: 11.5px; line-height: 1.5;
  color: var(--warning-txt) !important; background: var(--warning-bg);
  border-radius: 7px; padding: 8px 10px;
}
.cej-robot-lector:empty { display: none; }

/* 🤖 La nota del repaso: «puedes dejarlo correr». Es información tranquila, no
   una advertencia, así que va en gris y NO en el amarillo de los avisos — un
   límite dicho en color de alarma se lee como que algo va mal. */
.cej-robot-nota {
  margin: 10px 0 0 !important; font-size: 11.5px; line-height: 1.5;
  color: var(--ink-3, var(--ink-2)) !important;
  background: var(--surface-2, var(--bg-soft, transparent));
  border-radius: 7px; padding: 8px 10px;
}

.cej-robot-aviso {
  font-size: 12.5px; line-height: 1.55; color: var(--ink-2);
  background: var(--warning-bg); border: 1px solid var(--warning-txt);
  border-radius: 8px; padding: 12px 14px; margin-bottom: 4px;
}
.cej-robot-aviso.malo { background: var(--danger-bg); border-color: var(--danger-txt); }
.cej-robot-aviso p { margin: 0 0 8px; }
.cej-robot-aviso p:last-of-type { margin-bottom: 0; }
.cej-robot-aviso .btn-gold { margin-top: 12px; }

.cej-robot-pie {
  display: flex; gap: 8px; flex-wrap: wrap;
  margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--line);
}
.cej-robot-link {
  background: none; border: 0; padding: 4px 2px;
  font-size: 11.5px; font-weight: 700; color: var(--ink-3);
  display: flex; align-items: center; gap: 6px;
  transition: color var(--speed);
}
.cej-robot-link:hover { color: var(--acento-txt); }
.cej-robot-link.peligro { margin-left: auto; }
.cej-robot-link.peligro:hover { color: var(--danger-txt); }
/* 🏛️ 30-08 · La firma. Arriba manda el escudo del estudio —porque la ventana
   es el sistema actuando EN SU NOMBRE dentro del portal— y la identidad de
   SocioLegal se dice aquí abajo, pequeña y siempre igual. Una marca no se
   afirma repitiéndose en todos los huecos. */
.cej-robot-firma {
  margin-top: 10px; text-align: center;
  font-size: 11px; letter-spacing: .03em; color: var(--ink-3); opacity: .75;
}
/* 🆕 31-08 · La regla del icono se queda por si algún día vuelve a haber uno,
   pero HOY no hay: la firma es sólo texto (lo pidió Piero, y además arriba ya
   manda el escudo del estudio). */
.cej-robot-firma i { margin-right: 4px; color: var(--acento-txt); }
.cej-robot-firma b { font-weight: 700; color: var(--ink-2); }

.plan-link {
  background: none; border: 0; padding: 0; font: inherit; cursor: pointer;
  color: var(--acento-txt); text-decoration: underline; font-weight: 700;
}
.plan-link:hover { color: var(--gold); }

/* --- La tarjeta de Configuración --- */
.plan-cab { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
.plan-nombre { font-size: 17px; font-weight: 800; color: var(--ink); }
.plan-fila { margin: 0 0 14px; }
.plan-fila-cab { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; font-size: 13px; color: var(--ink-2); margin-bottom: 6px; }
.plan-fila-cab b { color: var(--ink); font-variant-numeric: tabular-nums; }
.plan-barra { height: 7px; border-radius: 99px; background: var(--line); overflow: hidden; }
.plan-barra-int { display: block; height: 100%; border-radius: 99px; background: var(--gold); }
.plan-barra-int.plan-poco, .plan-barra-int.plan-cortesia { background: var(--warning); }
.plan-barra-int.plan-agotado { background: var(--danger); }
.plan-gente {
  display: flex; gap: 22px; flex-wrap: wrap; font-size: 13px; color: var(--ink-2);
  padding: 12px 0 4px; border-top: 1px solid var(--line);
}
.plan-gente b { color: var(--ink); font-size: 15px; }
.plan-nota { margin-top: 14px; line-height: 1.6; }

/* --- Recomienda SocioLegal (trae estudios nuevos) --- */
.rec-cab { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
/* 🪤 2026-08-10 — iba a 16px, y eso lo dejaba MÁS GRANDE que el título de la
   sección que lo contiene (`.cfg-sec h4`, 14px) siendo este el título de un
   bloque de dentro: la jerarquía al revés. Es el otro caso del hallazgo 9.
   A 14px, igual que los otros once `h4` de Configuración. Sigue destacando por
   el peso (800) y el icono en color, que es de donde tiene que venir el
   énfasis en un título pequeño — no del tamaño. */
.rec-cab h4 { margin: 0; font-size: 14px; font-weight: 800; color: var(--ink); }
.rec-cab h4 i { color: var(--acento-txt); margin-right: 6px; }
.rec-cupos {
  font-size: 12px; font-weight: 700; color: var(--accent-ink); white-space: nowrap;
  background: var(--gold-soft); border: 1px solid var(--gold); border-radius: 99px; padding: 3px 10px;
}
.rec-intro { line-height: 1.6; }
.rec-ganados {
  display: flex; align-items: center; gap: 8px; margin: 10px 0; padding: 9px 12px;
  border: 1px solid var(--gold); border-radius: 10px; background: var(--gold-soft);
  font-size: 13px; color: var(--accent-ink);
}
.rec-form { display: flex; gap: 8px; flex-wrap: wrap; margin: 12px 0 4px; }
.rec-form input {
  flex: 1 1 220px; min-width: 0; padding: 10px 12px; font: inherit; font-size: 14px;
  color: var(--ink); background: var(--bg); border: 1px solid var(--line); border-radius: 10px;
}
.rec-form input:focus { outline: none; border-color: var(--gold); }
.rec-form .btn-gold { white-space: nowrap; }
.rec-error { margin-top: 8px; font-size: 13px; color: var(--danger-txt); }
.rec-lista { list-style: none; margin: 14px 0 0; padding: 0; display: grid; gap: 10px; }
.rec-item { padding: 10px 12px; border: 1px solid var(--line); border-left-width: 3px; border-radius: 10px; }
.rec-item.rec-ok { border-left-color: var(--success, #1f9d55); }
.rec-item.rec-espera { border-left-color: var(--gold); }
.rec-item.rec-no { border-left-color: var(--danger-txt); }
.rec-item-cab { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.rec-correo { font-size: 13.5px; font-weight: 700; color: var(--ink); word-break: break-all; }
.rec-item-est { margin-top: 5px; font-size: 12.5px; color: var(--ink-2); line-height: 1.5; }
.rec-item-est i { margin-right: 5px; }
.rec-item.rec-ok .rec-item-est i { color: var(--success, #1f9d55); }
.rec-item.rec-no .rec-item-est i { color: var(--danger-txt); }
.rec-copiar { padding: 5px 10px; font-size: 12px; white-space: nowrap; }
.rec-pie { margin-top: 14px; line-height: 1.6; }
#rec-enlace { font-size: 12.5px; color: var(--ink-2); }

/* --- Valoración de 1 a 5 estrellas --- */
.val-estrellas { display: flex; gap: 6px; justify-content: center; margin: 6px 0 2px; }
.val-estrella {
  background: none; border: none; cursor: pointer; padding: 6px; line-height: 1;
  font-size: 30px; color: var(--line); transition: color .15s ease, transform .15s ease;
}
.val-estrella:hover { transform: scale(1.12); color: var(--gold); }
.val-estrella.puesta { color: var(--gold); }
.val-estrella:focus-visible { outline: 2px solid var(--gold); border-radius: 6px; }
.val-check {
  display: flex; gap: 10px; align-items: flex-start; margin: 10px 0;
  font-size: 12.5px; color: var(--ink-2); line-height: 1.5; cursor: pointer;
}
/* ⚠️ La regla global `input{width:100%;padding:10px 12px}` también pilla a las
   casillas: sin esto la casilla se comía todo el ancho y el texto quedaba en
   una columna de dos dedos, partido letra a letra. */
.val-check input[type="checkbox"] {
  width: 17px; height: 17px; min-width: 17px; flex: 0 0 17px;
  margin: 1px 0 0; padding: 0; border-radius: 4px; accent-color: var(--acento-txt);
  cursor: pointer;
}
.val-check > span { flex: 1 1 auto; min-width: 0; }
.val-legal { font-size: 11.5px; color: var(--ink-3); line-height: 1.55; margin: 8px 0 0; }

/* ============================================================
   LA COLA DE ESCRITOS del Editor (2026-08-05)
   ------------------------------------------------------------
   Lo primero que se ve al entrar en «Redactar escritos»: el trabajo que ya
   está esperando, en vez de un formulario en blanco. Colores tomados de las
   variables de texto medidas, para que cumpla en las 6 paletas y los 2 modos.
   ============================================================ */
.rc-caja { border: 1px solid var(--gold); border-radius: var(--r-md); padding: 10px; margin-bottom: 14px; background: var(--gold-soft); }
.rc-cab { font-size: 11px; text-transform: uppercase; letter-spacing: .5px; color: var(--acento-txt); font-weight: 700; margin-bottom: 8px; }
.rc-sep { font-size: 11px; text-transform: uppercase; letter-spacing: .5px; color: var(--ink-3); margin: 10px 0 6px; }
.rc-item {
  display: block; width: 100%; text-align: left; font-family: inherit; cursor: pointer;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-sm);
  padding: 9px 11px; margin-bottom: 6px; position: relative;
}
.rc-item:hover, .rc-item:focus-visible { border-color: var(--gold); }
.rc-item.rc-tarde { border-left: 3px solid var(--danger-txt); }
.rc-tit { font-size: 13px; font-weight: 600; color: var(--ink-1); line-height: 1.35; }
.rc-sub { font-size: 11px; color: var(--ink-3); margin-top: 2px; font-variant-numeric: tabular-nums; }
.rc-pie { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 6px; }
.rc-cuando { font-size: 11px; color: var(--ink-2); }
.rc-cuando.rc-urge { color: var(--danger-txt); font-weight: 700; }
.rc-marca { font-size: 11px; color: var(--ink-2); border: 1px solid var(--line); border-radius: var(--r-pastilla); padding: 1px 7px; }
.rc-marca.rc-estr { color: var(--acento-txt); border-color: var(--gold); }
.rc-ir { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; font-weight: 600; color: var(--acento-txt); margin-top: 7px; }
.rc-nota { font-size: 11px; color: var(--ink-3); line-height: 1.45; margin-top: 8px; }
/* Escrito sin expediente todavía. Es un <div> con botones dentro, no un botón
   entero como el resto de la cola: por eso se le quita el cursor de mano, que
   heredaba de `.rc-item` y prometía un clic que no existe. */
.rc-suelto { cursor: default; }
.rc-suelto:hover { border-color: var(--line); }
.rc-suelto-acc { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.rc-suelto-acc .est-mini { flex: 0 0 auto; }

/* Estado de guardado del folio (2026-08-07): saber si tu trabajo está a salvo. */
.ed-guardado {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11px; color: var(--ink-3); padding: 0 4px; white-space: nowrap;
}
.ed-guardado.mal { color: var(--danger-txt); font-weight: 700; }

/* ---- Paso 1 del Redactor, plegable (2026-08-05) ----
   Mismo aspecto que la cabecera de fase de siempre; sólo se le añade la
   flecha y el cursor, para que se vea que se puede abrir y cerrar. */
.ed-paso1 { margin: 0; }
.ed-paso1 > summary.ed-fase-sum { cursor: pointer; list-style: none; display: flex; align-items: center; gap: 8px; }
.ed-paso1 > summary.ed-fase-sum::-webkit-details-marker { display: none; }
.ed-paso1 > summary.ed-fase-sum::after {
  content: "\f078"; font-family: "Font Awesome 6 Free"; font-weight: 900;
  font-size: 10px; color: var(--ink-3); margin-left: auto; transition: transform var(--speed);
}
.ed-paso1[open] > summary.ed-fase-sum::after { transform: rotate(180deg); }
.ed-paso1 > summary.ed-fase-sum:hover { color: var(--acento-txt); }

/* ============================================================
   COMPLETAR LOS [CORCHETES] — rejilla y pie fijo (2026-08-06)
   ------------------------------------------------------------
   Piero: «no se ve bien». Medido con 7 huecos ANTES de tocarlo: la lista
   ocupaba 831 px dentro de una caja de 635 y el botón «Completar el escrito»
   quedaba FUERA de la pantalla — había que adivinar que estaba abajo. Cada
   campo medía 76 px porque debajo colgaba una casilla repetida.
   Tres cambios, ninguno decorativo: los campos van en dos columnas (son datos
   cortos: DNI, fecha, casilla), la casilla de guardar es una sola, y el pie se
   queda pegado abajo para que el botón esté siempre a la vista.
   Una sola columna por debajo de 560 px: en el móvil dos columnas dejarían
   cajas donde no cabe un domicilio. */
.huecos-rejilla { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px 14px; }
@media (max-width: 560px) { .huecos-rejilla { grid-template-columns: 1fr; } }
.huecos-rejilla .hueco-campo { margin-bottom: 0; min-width: 0; }
.huecos-rejilla .hueco-campo label { margin-bottom: 4px; }
.hueco-veces { color: var(--ink-3); font-weight: 400; font-size: 11px; }
/* De dónde sale o a dónde va el dato. Va debajo del campo y en pequeño: es
   contexto, no una decisión — la decisión es la casilla única del pie. */
.hueco-donde { display: block; font-size: 11px; color: var(--ink-3); margin-top: 3px; letter-spacing: .01em; }
.huecos-guardar { display: flex; align-items: flex-start; gap: 8px; margin: 14px 0 0;
  font-size: 12px; color: var(--ink-2); line-height: 1.5; cursor: pointer; }
.huecos-guardar input { width: auto; margin: 2px 0 0; flex: 0 0 auto; }
/* Pegado al fondo de la caja con scroll: el botón principal deja de esconderse
   al final de una lista larga. El fondo es opaco para que el texto que pasa
   por debajo al desplazarse no se lea a través. */
.huecos-pie { position: sticky; bottom: -18px; display: flex; gap: 10px; flex-wrap: wrap;
  margin-top: 16px; padding: 12px 0; background: var(--card); border-top: 1px solid var(--line); }

/* ============================================================
   LA CASILLA DE LOS TÉRMINOS (2026-08-12)
   ------------------------------------------------------------
   🪤 Antes de tocar esto, leer la memoria `regla-global-input-se-come-las-
   casillas`: hay una regla global para `input` que ya se comió dos veces una
   casilla de verificación (le pone ancho completo y padding, y el cuadro
   desaparece). Por eso aquí el `input[type=checkbox]` recupera a mano su
   tamaño, su ancho automático y su margen — no es adorno, es el arreglo.
   ============================================================ */
.acepta-terminos {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin: 14px 0 4px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--ink-2);
  cursor: pointer;
  text-align: left;
}
.acepta-terminos input[type="checkbox"] {
  width: 16px;            /* la regla global lo estiraría al 100% */
  min-width: 16px;
  height: 16px;
  margin: 2px 0 0;
  padding: 0;
  flex: 0 0 auto;
  accent-color: var(--gold-strong, #c5a059);
  cursor: pointer;
}
.acepta-terminos a { color: var(--gold-strong, #c5a059); text-decoration: underline; }
.acepta-terminos a:hover { text-decoration: none; }
/* «(las reglas del servicio)» · «(qué hacemos con tus datos)». Más apagado que
   el enlace a propósito: acompaña al nombre, no compite con él. */
.cond-que-es { font-style: normal; opacity: .72; font-size: .92em; }

/* Sin marcar y al pulsar «crear»: el aviso va PEGADO a la casilla, no en una
   nota al final de la página que en el móvil queda fuera de la pantalla. */
.acepta-terminos.falta {
  background: var(--danger-soft, #fdecec);
  border: 1px solid var(--danger, #d64545);
  border-radius: 8px;
  padding: 9px 11px;
  margin-left: -11px;
  margin-right: -11px;
}

/* El Centro Legal enseñado SIN sesión (art. 1397 CC). Reusa `.modal-overlay`
   y `.modal-box`: aquí sólo se le da alto y desplazamiento propio, porque son
   seis documentos y no caben en una pantalla. */

/* 🔴 2026-08-14 · SE ABRÍA DETRÁS DE LA PANTALLA DE ACCESO. Y por eso NADIE
   había podido leer nunca los Términos ni la Política antes de aceptarlos —
   que es exactamente lo que este modal existe para permitir (art. 1397 CC: no
   se puede aceptar lo que no se puede leer). Lo vio Piero: «le das click y no
   te enseña nada, no funciona esos clicks». Tenía razón.

   El modal funcionaba: se creaba, se poblaba con el documento correcto y
   quedaba centrado. Simplemente estaba DEBAJO. `.modal-overlay` va a 2000 y
   `#login-screen` a 3000, y este es el único modal que se abre CON la pantalla
   de acceso todavía puesta — los otros trece sólo existen ya dentro de la app.

   3600 y no más: tiene que quedar por encima del acceso (3000) y del Ctrl+K
   (3500), pero POR DEBAJO de los avisos (4000) y de las confirmaciones (4100),
   o un error al crear la cuenta se quedaría escondido detrás de los Términos.

   🪤 Y LA LECCIÓN DE MEDICIÓN, que costó dos falsos «funciona bien»: las dos
   primeras comprobaciones dieron verde porque para ver la app se había
   escondido `#login-screen` — con lo cual se apartaba justo lo que tapaba. Un
   navegador preparado a mano puede ser tan permisivo como un DOM de juguete.
   Aquí no basta con que el nodo exista y esté centrado: hay que preguntar
   `document.elementFromPoint()` QUIÉN ESTÁ ENCIMA. */
#legal-overlay { z-index: 3600; }

/* 🔴 2026-08-14 · ESTA VENTANA SE DIBUJABA CON DOS CLASES QUE NO EXISTEN.
   `registro.js` la montaba con `modal-box` y `modal-actions`, y ninguna de las
   dos estaba en este archivo — el comentario de arriba llegó a decir que
   «reusa `.modal-box`», que era falso. Una clase que no existe **no da ningún
   error**: simplemente no viste nada. Lo que se veía, en la captura de Piero:
   el texto legal flotando sobre el fondo oscuro sin tarjeta debajo, sin
   márgenes, y el «Cerrar» convertido en una barra dorada de lado a lado.
   Y era la única ventana de la app dibujada así — justo la que ve TODO el que
   crea una cuenta, y la que existe para cumplir el art. 1397 CC.
   Ahora usa `modal-content glass` + `modal-head` + `modal-footer-actions`, que
   es como se dibujan las otras catorce. Aquí sólo queda lo PROPIO de ésta:
   más estrecha, y con la cabecera y el «Cerrar» quietos mientras se lee.
   🪤 Se quitó el `width: 92vw` que llevaba: `vw` mide la ventana CON la barra
   de desplazamiento dentro, y `.modal-content` ya trae `width: 100%`, que se
   mide contra el hueco útil. Es la trampa de `100vw` otra vez. */
.legal-box { max-width: 780px; }
#legal-overlay .modal-content { display: flex; flex-direction: column; overflow: hidden; }
#legal-overlay .modal-head, #legal-overlay .modal-footer-actions { flex: 0 0 auto; }
.legal-cuerpo {
  flex: 1 1 auto; min-height: 0;
  overflow-y: auto;
  padding-right: 6px;
  text-align: left;
}
.legal-cuerpo .cfg-sec { display: block !important; }

/* ============================================================
   LA HOJA DE ATAJOS  (`?`)  —  2026-08-13
   ------------------------------------------------------------
   Un atajo que nadie conoce no existe: sin esta hoja, los demás son trabajo
   tirado. Reusa `.modal-overlay` y `.modal-content` de la casa, así que se
   cierra con el mismo Escape que todo lo demás y no estrena una segunda
   manera de dibujar una ventana.
   `kbd` copia el aspecto de `.cmdk-esc`, que es la tecla que la app ya
   dibujaba (la «esc» del Ctrl+K): dos estilos de tecla distintos en la misma
   app se leerían como dos cosas distintas.
   ============================================================ */
.atajos-rejilla { display: grid; grid-template-columns: 1fr 1fr; gap: 18px 24px; text-align: left; }
.atajos-sec h4 {
  font-size: 12px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--ink-3); margin: 0 0 8px; font-weight: 700;
}
.atajos-fila { display: flex; align-items: center; gap: 10px; padding: 5px 0; font-size: 13px; color: var(--ink-2); }
.atajos-fila kbd, .atajos-rejilla ~ p kbd, .modal-content kbd {
  font-family: inherit; font-size: 11px; white-space: nowrap;
  color: var(--ink-3); background: transparent;
  border: 1px solid var(--line-strong); border-radius: var(--r-sm); padding: 4px 8px;
}
.atajos-fila kbd { flex: 0 0 auto; min-width: 74px; text-align: center; }

/* En el móvil no hay teclado físico, pero sí teclados de tableta y de los
   plegables: la hoja se lee igual, en una sola columna. */
body.estrecho .atajos-rejilla { grid-template-columns: 1fr; gap: 14px; }
