/* CiberLex — base, efectos firma */
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; height: 100%; }
body {
  background: var(--bg-void);
  color: var(--text-mid);
  font-family: var(--font-body);
  font-size: 14.5px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}
h1, h2, h3, h4 { font-family: var(--font-display); color: var(--text-hi); margin: 0; font-weight: 600; letter-spacing: -0.01em; text-wrap: balance; }
p { margin: 0; text-wrap: pretty; }
button { font-family: inherit; cursor: pointer; border: none; background: none; color: inherit; }
input, textarea, select { font-family: inherit; color: var(--text-hi); }
::selection { background: rgba(91,140,255,.35); }

/* ---------- scrollbars ---------- */
*::-webkit-scrollbar { width: 8px; height: 8px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb { background: var(--line-2); border-radius: 99px; }
*::-webkit-scrollbar-thumb:hover { background: var(--line-3); }

/* ---------- kicker ---------- */
.kicker {
  font-family: var(--font-mono);
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--text-mute);
}

.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.tnum { font-variant-numeric: tabular-nums; }

/* ---------- glass ---------- */
.glass {
  position: relative;
  background: linear-gradient(160deg, var(--glass-a), var(--glass-b));
  backdrop-filter: blur(18px) saturate(1.3);
  -webkit-backdrop-filter: blur(18px) saturate(1.3);
  border: 1px solid var(--line-2);
  border-radius: var(--r-lg);
}
.glass::before {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: linear-gradient(165deg, var(--glass-sheen), transparent 32%);
}

/* borde gradiente luminoso */
.grad-border {
  position: relative;
  border: 1px solid transparent;
  background-clip: padding-box;
}
.grad-border::after {
  content: "";
  position: absolute; inset: -1px;
  border-radius: inherit;
  padding: 1px;
  background: var(--grad-ia);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
  opacity: calc(.85 * var(--glow, 1));
}

/* ---------- CTA con sheen ---------- */
.cta {
  position: relative;
  overflow: hidden;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 14px;
  color: var(--ink-cta);
  background: var(--grad-ia);
  border-radius: var(--r-md);
  padding: 11px 22px;
  letter-spacing: .01em;
  white-space: nowrap;
  box-shadow: var(--glow-ia);
  transition: transform .25s var(--ease-fluid), box-shadow .25s var(--ease-fluid), filter .25s;
}
.cta::after {
  content: "";
  position: absolute;
  top: -40%; bottom: -40%;
  width: 38%;
  left: -60%;
  transform: skewX(-22deg);
  background: linear-gradient(90deg, transparent, rgba(255,255,255,.55), transparent);
  transition: left .7s var(--ease-fluid);
  pointer-events: none;
}
.cta:hover { transform: translateY(-1px); filter: brightness(1.06); }
.cta:hover::after { left: 130%; }
.cta:active { transform: translateY(0); }
.cta:disabled { filter: saturate(.2) brightness(.7); cursor: not-allowed; }

/* botón fantasma */
.btn-ghost {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 10px 18px;
  border-radius: var(--r-md);
  border: 1px solid var(--line-3);
  color: var(--text-mid);
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 14px;
  background: rgba(20,29,57,.4);
  transition: all .2s var(--ease-fluid);
}
.btn-ghost:hover { border-color: var(--acc-blue); color: var(--text-hi); background: var(--bg-hover); box-shadow: var(--glow-blue); }

/* ---------- chips HUD ---------- */
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: .04em;
  padding: 4px 10px;
  border-radius: 99px;
  border: 1px solid var(--line-3);
  background: var(--chip-bg);
  color: var(--text-mid);
  white-space: nowrap;
}
.chip .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--acc-cyan); box-shadow: 0 0 8px var(--acc-cyan); }
.chip.mint { border-color: rgba(52,211,166,.4); color: var(--acc-mint); background: rgba(52,211,166,.08); }
.chip.mint .dot { background: var(--acc-mint); box-shadow: 0 0 8px var(--acc-mint); }
.chip.red { border-color: rgba(248,113,113,.4); color: var(--acc-red); background: rgba(248,113,113,.08); }
.chip.red .dot { background: var(--acc-red); box-shadow: 0 0 8px var(--acc-red); }
.chip.amber { border-color: rgba(245,165,36,.4); color: var(--acc-amber); background: rgba(245,165,36,.08); }
.chip.cyan { border-color: rgba(34,211,238,.4); color: var(--acc-cyan); background: rgba(34,211,238,.07); }
.chip.purple { border-color: rgba(167,139,250,.4); color: var(--acc-purple); background: rgba(167,139,250,.08); }

/* ---------- PÍLDORAS DE SUGERENCIA DEL CHAT ----------
   CLASE PROPIA Y NO UNA VARIANTE DE `.chip`, y esa es la decisión importante de este bloque.
   `.chip` queda con 195 usos en el producto -estados de vigencia, contadores, etiquetas de plan,
   distintivos de un caso- y casi ninguno es pulsable. Añadirle elevación al pasar el ratón y
   un borde que brilla habría hecho que docenas de etiquetas que NO se pueden pulsar
   parecieran botones. Aquí lo que se estiliza es lo único que sí lo es: las tres sugerencias
   de la pantalla de bienvenida.

   Hereda la forma de `.chip` (redondeo total, tipografía) pero no su regla, así que las dos
   pueden evolucionar por separado. */
.sug-pill {
  display: inline-flex; align-items: center; gap: 6px;
  border-radius: 99px;
  padding: 8px 14px;
  font-family: var(--font-body);
  font-size: 12px;
  cursor: pointer;
  color: var(--text-mid);
  border: 1px solid rgba(34,211,238,.20);
  background: rgba(34,211,238,.04);
  transition: transform .18s var(--ease-fluid), border-color .18s, background .18s,
              box-shadow .18s, color .18s;
}
/* AL PASAR EL RATÓN el borde pasa a rose gold, que es el color con el que este producto
   marca lo cálido y humano, y el texto sube a contraste alto. El fondo apenas cambia: lo que
   invita al clic es el borde y la elevación, no un relleno que taparía el fondo. */
.sug-pill:hover {
  border-color: rgba(231,161,149,.55);
  background: rgba(231,161,149,.07);
  color: var(--text-hi);
  box-shadow: 0 6px 18px -8px rgba(0,0,0,.7),
              0 0 18px -6px rgba(231,161,149,calc(.45 * var(--glow, 1)));
}
/* EL FOCO POR TECLADO SE VE IGUAL QUE EL HOVER, y además con un anillo. Son botones: quien
   navega con el tabulador tiene que saber dónde está, y `:hover` no le sirve de nada. */
.sug-pill:focus-visible {
  outline: none;
  border-color: rgba(34,211,238,.7);
  color: var(--text-hi);
  box-shadow: 0 0 0 2px rgba(34,211,238,.35);
}
/* La elevación va aparte: es lo único de aquí que es movimiento. */
@media (prefers-reduced-motion: no-preference) {
  .sug-pill:hover { transform: translateY(-2px); }
}
/* EN CLARO, LOS MISMOS COLORES PERO EN TINTA. El cian #22d3ee y el rose gold #e7a195 son
   acentos pensados para brillar sobre negro: al 20% sobre `#e9edf8` la píldora se queda sin
   contorno y no se lee como un botón. Van los tonos profundos de la misma familia -teal y
   terracota-, que es el mismo criterio que ya usa la malla (`--mesh-*`) en este tema. El
   resplandor se retira: sobre fondo claro una sombra de color se ve como una mancha. */
html[data-theme="light"] .sug-pill {
  border-color: rgba(14,116,144,.38);
  background: rgba(14,116,144,.05);
}
html[data-theme="light"] .sug-pill:hover {
  border-color: rgba(166,88,74,.6);
  background: rgba(166,88,74,.07);
  box-shadow: 0 6px 16px -10px rgba(30,42,90,.5);
}
html[data-theme="light"] .sug-pill:focus-visible {
  border-color: rgba(14,116,144,.85);
  box-shadow: 0 0 0 2px rgba(14,116,144,.3);
}

/* ---------- ATMÓSFERA DEL ESCRITORIO ----------
   Sustituye a `<Aurora dim />` en el workspace. La aurora son TRES manchas de
   `rgba(91,140,255,.5)`, `rgba(183,148,255,.42)` y `rgba(56,224,245,.36)` con `blur(90px)`:
   incluso atenuada al 50% teñía de azul toda la pantalla, y eso es el «fondo azul plano».

   Aquí hay DOS destellos y nada más: cian arriba-izquierda, rose gold abajo-derecha, con los
   tokens `--atm-*` -que el tema claro redefine-. Al no llevar `filter: blur()` no crea una
   capa de composición del tamaño de la pantalla, así que además cuesta menos que la aurora.

   `pointer-events: none` porque encima van los paneles, los botones y los campos: sin esto
   una capa a pantalla completa se comería todos los clics. No necesita `z-index`: el
   contenido del workspace ya vive en un hermano con `zIndex: 2`. */
.cl-atmosfera {
  position: absolute;
  inset: 0;
  pointer-events: none;
  /* LAS COORDENADAS SON LO QUE HACE VISIBLE ESTO, y la primera versión las tenía mal.
     El cian estaba en `at 6% 4%`: en 1440x900 eso es el píxel (86, 36), o sea DENTRO de la
     barra lateral (272 px) y DENTRO del topbar (58 px) a la vez. La barra usa `--panel-bg`
     -rgba(10,16,32,.6), pasa el 40 %- y el topbar `--topbar-bg` -rgba(6,9,18,.55), pasa el
     45 %-, así que el alfa que llegaba a la pantalla era .10 x .40 x .45 = .018. Se declaraba
     un 10 % y se veía un 1,8 %: el destello principal estaba enterrado bajo los menús.

     Ahora el cian cae en `22% 12%`, que en 1440x900 es (317, 108): a la derecha de la barra
     y por debajo del topbar, ya en el área de trabajo, donde llega entero. El rose gold sube
     de `96% 98%` a `88% 88%` por lo mismo -esa esquina es el rincón más muerto de la
     pantalla- y entra en el lienzo del expediente.

     Los radios NO se tocan: 58vw/58vh es lo que hace que el degradado se lea como luz de
     ambiente y no como un foco con borde. Lo que cambia es dónde está el centro. */
  background:
    radial-gradient(58vw 58vh at 22% 12%, var(--atm-cian), transparent 68%),
    radial-gradient(52vw 52vh at 88% 88%, var(--atm-rose), transparent 68%);
}

/* cita legal como chip mono */
.cite-chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  padding: 2px 8px;
  margin: 0 2px;
  border-radius: 6px;
  border: 1px solid rgba(34,211,238,.35);
  background: rgba(34,211,238,.08);
  color: var(--acc-cyan);
  cursor: pointer;
  transition: all .15s;
  vertical-align: baseline;
  white-space: nowrap;
}
.cite-chip:hover { background: rgba(34,211,238,.16); box-shadow: var(--glow-cyan); }

/* ---------- tarjetas lift ---------- */
/* ---------- resplandor sutil de los modulos interactivos ----------
   Marca lo que se puede pulsar -los iconos de la barra del mensaje, las tarjetas de
   Mis casos- con un halo tenue EN REPOSO que se acentua al pasar el raton.

   EL ORDEN IMPORTA Y NO ES CASUAL: va ANTES de `.lift`. Las tarjetas de caso llevan las
   dos clases, y `.lift:hover` ya define su propia sombra al pasar por encima
   (--shadow-lift + --glow-blue, que le da la profundidad del levantamiento). Las dos
   reglas :hover tienen la MISMA especificidad, asi que gana la que este mas abajo: con
   `.cl-glow` arriba, la tarjeta se queda con el halo tenue en reposo y conserva su
   hover de siempre, y los iconos de la barra -que no llevan `.lift`- usan los dos
   estados de aqui. Si alguien mueve este bloque debajo de `.lift`, las tarjetas pierden
   la profundidad al pasar el raton y no da ningun error: solo se ve peor. */
/* SON DOS CAPAS Y LA PRIMERA ES LA QUE SE VE. La version anterior llevaba un solo halo
   exterior y en produccion NO SE VEIA NADA: con .10 de opacidad, blur 12 y spread -2px
   sobre un boton de 38 px transparente metido en un panel de cristal, el halo queda por
   debajo del umbral de percepcion. Y lo que de verdad dice "esto se pulsa" en un boton
   oscuro y pequeno es el BORDE, que aqui NO se puede aclarar desde una clase: `iconBtn()`
   de chat.jsx lo escribe en el style INLINE y el inline gana a cualquier hoja de estilos.
   De ahi la primera capa `0 0 0 1px`: un anillo pegado al borde que hace de borde
   luminoso sin pelearse con el inline, y que ademas se dibuja igual en las tarjetas. */
.cl-glow {
  box-shadow: var(--glow-soft);
  transition: box-shadow .22s var(--ease-fluid), border-color .22s;
}
.cl-glow:hover { box-shadow: var(--glow-soft-hi); }
/* Con el teclado tiene que verse igual que con el raton: quien navega con Tab tambien
   necesita saber que eso se pulsa. */
.cl-glow:focus-visible { box-shadow: var(--glow-soft-hi); }
/* Un modulo desactivado no invita a nada, asi que no se ilumina. */
.cl-glow:disabled, .cl-glow[aria-disabled="true"] { box-shadow: none; }
/* EN ALTO CONTRASTE EL RESPLANDOR NO SIRVE COMO INDICADOR DE FOCO. `--glow-soft-hi` es un
   halo azul al 42 % de opacidad, y sobre negro o blanco PUROS eso da 1,92:1 y 1,43:1: por
   debajo del 3:1 que la norma pide para un indicador que no es texto. O sea que quien navega
   con el teclado en el modo de accesibilidad era justo quien peor veia donde estaba.
   Se arregla con un `outline`, no tocando `--glow-soft-hi`: ese token esta atado a
   `tests/test_ui_ajustes.js`, que exige DOS declaraciones -una por tema base- y una tercera
   romperia la prueba. El outline va aparte, se dibuja fuera de la caja y no compite con el
   `box-shadow` que la clase ya usa. */
html[data-contrast="alto"] .cl-glow:focus-visible {
  outline: 2px solid var(--line-3);
  outline-offset: 2px;
}

/* ---------- Filas del selector de tema (Ajustes) ----------
   El foco de teclado NO se delega al navegador: el resto del producto dibuja su propio aro
   (`.mic-cta`, `.send-cta`, `.voice-sec` usan todos `2px solid var(--acc-cyan)`), y en una
   lista de opcion unica el foco y la SELECCION son dos cosas distintas que se mueven juntas
   con las flechas: si el foco no se ve, no hay forma de saber sobre que fila estas.
   Va con `:focus-visible` y no con `:focus` a proposito: al pulsar con el raton la fila ya se
   marca -cambia fondo, borde y radio-, asi que un aro ademas seria ruido; con el teclado es
   la unica senal. */
.cl-tema-fila:focus-visible {
  outline: 2px solid var(--tema-sel-borde);
  outline-offset: -3px;
}

.lift {
  transition: transform .3s var(--ease-fluid), box-shadow .3s var(--ease-fluid), border-color .3s;
}
.lift:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lift), var(--glow-blue);
  border-color: var(--line-3);
}

/* ---------- esquinas HUD ---------- */
.hud-corners { position: relative; }
.hud-corners .hudc {
  position: absolute; width: 14px; height: 14px;
  border-color: rgba(34,211,238, calc(.55 * var(--glow,1)));
  border-style: solid;
  pointer-events: none;
  transition: border-color .3s;
}
.hud-corners .hudc.tl { top: -1px; left: -1px; border-width: 1.5px 0 0 1.5px; border-radius: 10px 0 0 0; }
.hud-corners .hudc.tr { top: -1px; right: -1px; border-width: 1.5px 1.5px 0 0; border-radius: 0 10px 0 0; }
.hud-corners .hudc.bl { bottom: -1px; left: -1px; border-width: 0 0 1.5px 1.5px; border-radius: 0 0 0 10px; }
.hud-corners .hudc.br { bottom: -1px; right: -1px; border-width: 0 1.5px 1.5px 0; border-radius: 0 0 10px 0; }

/* ---------- skeleton shimmer ---------- */
.skeleton {
  position: relative;
  overflow: hidden;
  background: var(--bg-card);
  border-radius: var(--r-sm);
}
.skeleton::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(100deg, transparent 20%, rgba(91,140,255,.10) 50%, transparent 80%);
  animation: shimmer calc(1.6s / var(--motion, 1)) infinite;
  transform: translateX(-100%);
}
@keyframes shimmer { to { transform: translateX(100%); } }

/* ---------- texto degradado IA ---------- */
.ia-text {
  background: var(--grad-ia);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

/* ---------- aurora mesh ---------- */
.aurora {
  position: absolute; inset: 0; overflow: hidden; pointer-events: none;
}
.aurora .blob {
  position: absolute;
  border-radius: 50%;
  filter: blur(90px);
  opacity: calc(.5 * var(--glow, 1));
  mix-blend-mode: screen;
}
@media (prefers-reduced-motion: no-preference) {
  .aurora .blob { animation: drift calc(26s / var(--motion,1)) infinite alternate var(--ease-fluid); }
  .aurora .blob:nth-child(2) { animation-duration: calc(34s / var(--motion,1)); animation-delay: -8s; }
  .aurora .blob:nth-child(3) { animation-duration: calc(42s / var(--motion,1)); animation-delay: -16s; }
}
@keyframes drift {
  from { transform: translate(0,0) scale(1); }
  50%  { transform: translate(8vw, -6vh) scale(1.15); }
  to   { transform: translate(-6vw, 5vh) scale(.95); }
}

/* ---------- ojos del búho que laten ---------- */
@media (prefers-reduced-motion: no-preference) {
  .owl-thinking { animation: owlpulse calc(1.4s / var(--motion,1)) ease-in-out infinite; }
}
@keyframes owlpulse {
  0%, 100% { filter: drop-shadow(0 0 6px rgba(183,148,255,.5)) brightness(1); }
  50% { filter: drop-shadow(0 0 22px rgba(56,224,245,.9)) brightness(1.25); }
}

/* ---------- onda del micrófono ---------- */
.wavebar { width: 3px; border-radius: 2px; background: var(--grad-ia); }
@media (prefers-reduced-motion: no-preference) {
  .wavebar { animation: wave calc(.9s / var(--motion,1)) ease-in-out infinite; }
}
@keyframes wave {
  0%, 100% { transform: scaleY(.35); }
  50% { transform: scaleY(1); }
}

/* ---------- efecto latido de corazón (heartbeat) ---------- */
@media (prefers-reduced-motion: no-preference) {
  .heartbeat { animation: heartbeat 1.4s ease-in-out infinite; }
}
@keyframes heartbeat {
  0%, 100% { transform: scale(1); box-shadow: 0 0 0 0 currentColor; }
  14% { transform: scale(1.06); }
  28% { transform: scale(1); }
  42% { transform: scale(1.04); }
  56% { transform: scale(1); box-shadow: 0 0 20px -4px currentColor; }
}

/* ---------- entradas ---------- */
.field {
  width: 100%;
  background: var(--field-bg);
  border: 1px solid var(--line-2);
  border-radius: var(--r-md);
  padding: 11px 14px;
  font-size: 14px;
  color: var(--text-hi);
  outline: none;
  transition: border-color .2s, box-shadow .2s;
}
/* `--text-mute` Y NO `--text-dim`, y está medido. Un placeholder es TEXTO: dice qué formato se
   exige en el campo, y en varios formularios de Contratación Pública es la única pista de cómo
   escribir una cifra. Con `--text-dim` daba 2,56:1 sobre las tarjetas y 1,71:1 sobre la fila
   seleccionada -la norma pide 4,5:1-, o sea que había que acercarse a la pantalla para leerlo.
   `--text-mute` da 7,11 / 4,75 en oscuro y 5,76 / 4,76 en claro, y SIGUE a 2,39:1 de `--text-hi`,
   que es lo que importa aquí y no se puede perder: un placeholder tiene que leerse, pero también
   tiene que distinguirse de un valor ya escrito. Con `--text-mid` (11,80:1) se leería mejor pero
   quedaría a 1,44:1 del texto real y el campo parecería relleno cuando está vacío. */
.field::placeholder { color: var(--text-mute); }
.field:focus { border-color: var(--acc-blue); box-shadow: 0 0 0 3px rgba(91,140,255,.15), var(--glow-blue); }

/* ---------- score meter ---------- */
.score-track { height: 4px; border-radius: 99px; background: var(--bg-hover); overflow: hidden; position: relative; }
.score-fill { height: 100%; border-radius: 99px; background: var(--grad-ia); position: relative; overflow: hidden; transition: width 1s var(--ease-fluid); }
@media (prefers-reduced-motion: no-preference) {
  .score-fill::after {
    content: ""; position: absolute; inset: 0;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,.6), transparent);
    animation: shimmer calc(2.2s / var(--motion,1)) infinite;
    transform: translateX(-100%);
  }
}

/* fade-in genérico */
@media (prefers-reduced-motion: no-preference) {
  .fade-up { animation: fadeup calc(.5s / var(--motion,1)) var(--ease-fluid) backwards; }
}
@keyframes fadeup {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

/* tema claro: ajustes finos */
html[data-theme="light"] .aurora .blob { opacity: calc(.22 * var(--glow, 1)); mix-blend-mode: multiply; }
/* EL BÚHO EN TEMA CLARO. `screen` sobre una página clara lo blanquea, así que aquí se compone
   en `normal`. Lo que hace que eso ya NO saque un cuadro oscuro detrás del ave es que el tema
   claro pinta otro archivo -el emblema en tinta, sin medallón- vía `--owl-emblema`; antes esta
   misma regla era la que dejaba el medallón a la vista. El `!important` sigue haciendo falta
   porque el `mix-blend-mode: screen` se escribe en el `style` inline de los componentes.
   Los OJOS (`.owl-eye`) quedan fuera a propósito: conservan su `screen` y siguen iluminando,
   porque caen sobre la cabeza del ave, que en tinta es oscura. */
html[data-theme="light"] .owl-shatter,
html[data-theme="light"] .owl-piece,
html[data-theme="light"] .owl-emblema { mix-blend-mode: normal !important; }

/* ---------- PLATOS OSCUROS QUE NO SIGUEN EL TEMA ----------
   Hay paneles que pintan su propio fondo casi negro ESCRITO A MANO y se ven igual con el tema
   claro puesto: la portada y la cabecera del Centro de Mando de la Secretaría Jurídica. Para el
   emblema eso es un caso aparte, y hay que decirlo porque los dos archivos NO son
   intercambiables:

     · `owl-emblem-blue.png` se sostiene solo -medallón oscuro con la tinta del ave CLARA
       encima-, así que lee sobre cualquier fondo;
     · `owl-emblem-tinta.png` es tinta de marca sobre transparencia, así que lee SOLO sobre
       fondos claros. Medido sobre esos dos platos: entre 1,0 y 2,7:1. Tinta oscura sobre un
       fondo oscuro, o sea un borrón.

   Quien pinta oscuro a mano se lleva el emblema oscuro y su `screen`, con el mismo criterio con
   el que `.aud-escena-oscura` se lleva la paleta oscura entera: la regla no es «qué tema está
   activo» sino «de qué color es la superficie que tengo debajo». */
.cl-plato-oscuro { --owl-emblema: url('../assets/owl-emblem-blue.png'); }
html[data-theme="light"] .cl-plato-oscuro .owl-shatter,
html[data-theme="light"] .cl-plato-oscuro .owl-piece,
html[data-theme="light"] .cl-plato-oscuro .owl-emblema { mix-blend-mode: screen !important; }
html[data-theme="light"] .btn-ghost { background: rgba(255,255,255,.55); }
/* EL VELO DEL MODAL, que era la queja explícita: «los modales se pierden contra el fondo».
   Estaba en `rgba(176,188,220,.62)`, o sea un gris azulado CLARO al 62 %: sobre una página que
   ya era casi blanca daba 1,34:1 contra el fondo y 1,56:1 contra el modal blanco. Un velo que
   no oscurece no es un velo: es una neblina, y el modal se quedaba flotando sin separarse de
   lo que había debajo. Ahora es una tinta oscura de la misma familia y sube a 1,96:1 contra la
   página y 2,47:1 contra el modal, que es lo que hace que el diálogo se lea como una capa
   encima y no como un trozo más de la pantalla. */
html[data-theme="light"] .modal-overlay { background: rgba(96,112,152,.55); }
/* Y el modal deja de ser un degradado casi plano sin canto: blanco puro arriba, un canto
   marcado (`--line-3`, no `--line-2`) y la sombra de dos capas. El borde es lo que remata la
   separación cuando el diálogo cae sobre una zona clara de la pantalla. */
html[data-theme="light"] .modal-overlay > .glass {
  background: linear-gradient(160deg, #ffffff, #f4f7fd);
  border-color: var(--line-3);
  box-shadow: var(--shadow-lift);
}
html[data-theme="light"] ::selection { background: rgba(53,101,217,.22); }
html[data-theme="light"] .chip .dot,
html[data-theme="light"] .chip.mint .dot,
html[data-theme="light"] .chip.red .dot,
html[data-theme="light"] .chip.amber .dot { box-shadow: none; }
html[data-theme="light"] .cite-chip { border-color: rgba(8,146,176,.4); background: rgba(8,146,176,.08); }
html[data-theme="light"] .cite-chip:hover { background: rgba(8,146,176,.16); }
html[data-theme="light"] .owl-ring-spin { filter: drop-shadow(0 0 5px rgba(53,101,217,.6)); }
html[data-theme="light"] .owl-bit { text-shadow: none; }
html[data-theme="light"] .skeleton::after { background: linear-gradient(100deg, transparent 20%, rgba(53,101,217,.12) 50%, transparent 80%); }
html[data-theme="light"] .cta::after { background: linear-gradient(90deg, transparent, rgba(255,255,255,.4), transparent); }
html[data-theme="light"] .toggle-track.on { background: rgba(53,101,217,.25); }

/* ---------- modo de voz ---------- */
.voice-halo { position: absolute; inset: 6%; border-radius: 50%; pointer-events: none; }
@media (prefers-reduced-motion: no-preference) {
  .voice-halo.listen { animation: vhpulse calc(1.7s / var(--motion,1)) ease-out infinite; }
  .voice-halo.speak { animation: vhspeak calc(1.1s / var(--motion,1)) ease-in-out infinite; }
}
@keyframes vhpulse {
  from { box-shadow: 0 0 0 0 rgba(34,211,238,.38); }
  to { box-shadow: 0 0 0 44px rgba(34,211,238,0); }
}
@keyframes vhspeak {
  0%, 100% { box-shadow: 0 0 24px 4px rgba(91,140,255,.3); }
  50% { box-shadow: 0 0 44px 14px rgba(183,148,255,.45); }
}
.voice-btn {
  width: 56px; height: 56px; border-radius: 50%;
  display: grid; place-items: center;
  border: 1px solid var(--line-3);
  background: var(--chip-bg);
  color: var(--text-mid);
  transition: all .2s var(--ease-fluid);
}
.voice-btn:hover { color: var(--text-hi); border-color: var(--acc-blue); box-shadow: var(--glow-blue); }
.voice-btn.active { color: var(--acc-amber); border-color: rgba(245,165,36,.5); background: rgba(245,165,36,.1); }
.voice-btn.end { width: 64px; height: 64px; color: var(--acc-red); border-color: rgba(248,113,113,.5); background: rgba(248,113,113,.12); }
.voice-btn.end:hover { background: rgba(248,113,113,.22); box-shadow: 0 0 20px rgba(248,113,113,.3); }

/* ==========================================================================
   EL MICROFONO ES EL PROTAGONISTA
   ==========================================================================
   La pantalla de voz tenia cuatro botones circulares DEL MISMO TAMAÑO -adjuntar,
   micrófono, responder y terminar-, asi que nada indicaba cual era la accion
   principal: se leia como una barra de herramientas, no como una conversacion. Y
   la accion de adjuntar ocupaba una caja enorme en la pantalla de inicio, lo que
   hacia parecer el modulo un formulario de subida de archivos en vez de un colega
   al que se le habla.

   La jerarquia ahora es explicita y se ve en el TAMAÑO: el micrófono grande, el
   boton de cerrar turno mediano y con texto, y adjuntar/terminar reducidos a
   secundarios discretos.

   TODO SALE DE tokens.css. Ni un color en hex: el tema claro redefine las
   variables, y un hex fijo rompe el componente en claro. Los `rgba()` que si
   aparecen son los mismos acentos de marca que ya usan `.voice-halo` y
   `.voice-aura` para sus resplandores, donde hace falta transparencia.

   Y TODA ANIMACION RESPETA LAS DOS PALANCAS DEL PROYECTO: vive dentro de
   `prefers-reduced-motion: no-preference` y su duracion se divide por
   `--motion`. Cada estado tiene ADEMAS una señal estatica -borde y resplandor-
   para que con el movimiento desactivado la pantalla siga diciendo en que estado
   esta: una animacion no puede ser el unico portador de informacion. */
.mic-cta {
  position: relative;
  width: 104px; height: 104px;
  border-radius: 50%;
  display: grid; place-items: center;
  border: 1px solid var(--line-3);
  background: var(--chip-bg);
  color: var(--text-hi);
  cursor: pointer;
  transition: transform .2s var(--ease-fluid), border-color .3s var(--ease-fluid), background .3s var(--ease-fluid);
  z-index: 1;
}
.mic-cta:hover { transform: scale(1.035); }
.mic-cta:active { transform: scale(.98); }
.mic-cta:disabled { filter: saturate(.2) brightness(.7); cursor: not-allowed; transform: none; }
.mic-cta:focus-visible { outline: 2px solid var(--acc-cyan); outline-offset: 5px; }
.mic-cta.sm { width: 84px; height: 84px; }

/* Las señales ESTATICAS de cada estado. Sin movimiento, esto es lo que queda. */
.mic-cta.listen { border-color: rgba(56,224,245,.75); background: rgba(56,224,245,.10); }
.mic-cta.busy   { border-color: rgba(183,148,255,.7); background: rgba(183,148,255,.10); color: var(--acc-purple); }
.mic-cta.speak  { border-color: rgba(91,140,255,.75); background: rgba(91,140,255,.12); color: var(--acc-blue); }
/* El ambar va MAS FLOJO que los demas acentos a la misma alfa. Se vio en pantalla: a .10 el
   circulo de «en pausa» era lo mas llamativo de la interfaz, por encima del estado de
   escucha —el ambar tiene mucha mas luminancia que el cian o el violeta—. Pausado es un
   estado pasivo: tiene que NOTARSE (el abogado necesita saber que no se le oye) sin gritar
   mas que el estado activo. */
.mic-cta.muted  { border-color: rgba(245,165,36,.55); background: rgba(245,165,36,.06); color: var(--acc-amber); }

/* REPOSO: latido suave. Es el estado de «aqui estoy, no te estoy grabando». */
@media (prefers-reduced-motion: no-preference) {
  .mic-cta.idle { animation: miclatido calc(3.6s / var(--motion,1)) ease-in-out infinite; }
}
@keyframes miclatido {
  0%, 100% { box-shadow: 0 0 16px 1px rgba(56,224,245,.12); }
  50%      { box-shadow: 0 0 34px 8px rgba(56,224,245,.26); }
}

/* ESCUCHANDO: anillos que se expanden. Tres, desfasados, para que se lea como un
   pulso continuo y no como un parpadeo. Son hermanos del boton y no
   pseudo-elementos porque hacen falta TRES con retardos distintos. */
.mic-ring {
  position: absolute; inset: 0; border-radius: 50%;
  border: 1px solid rgba(56,224,245,.55);
  pointer-events: none;
  opacity: 0;
}
@media (prefers-reduced-motion: no-preference) {
  .mic-cta.listen .mic-ring { animation: micanillo calc(2.4s / var(--motion,1)) cubic-bezier(.22,.61,.36,1) infinite; }
  .mic-cta.listen .mic-ring:nth-child(2) { animation-delay: calc(.8s / var(--motion,1)); }
  .mic-cta.listen .mic-ring:nth-child(3) { animation-delay: calc(1.6s / var(--motion,1)); }
}
/* El anillo llega a 1,85 y no a 2,2 a proposito: `.mic-cta` crea contexto de
   apilado (`z-index: 1`), asi que los anillos se pintan POR ENCIMA del boton de
   cerrar turno que va debajo. A 2,2 el anillo le cruzaba el texto por la mitad. */
@keyframes micanillo {
  0%   { transform: scale(1);    opacity: .5; }
  70%  { opacity: .1; }
  100% { transform: scale(1.85); opacity: 0; }
}

/* PENSANDO y HABLANDO: cambio de color -ya esta arriba, estatico- mas un pulso de
   brillo. Se anima `filter` a proposito y no `box-shadow`: asi el resplandor
   estatico del estado no se pisa, y el navegador lo compone sin repintar. */
@media (prefers-reduced-motion: no-preference) {
  .mic-cta.busy  { animation: micbrillo calc(1.9s / var(--motion,1)) ease-in-out infinite; }
  .mic-cta.speak { animation: micbrillo calc(1.15s / var(--motion,1)) ease-in-out infinite; }
}
@keyframes micbrillo {
  0%, 100% { filter: brightness(1); }
  50%      { filter: brightness(1.28); }
}

/* CERRAR EL TURNO: la accion que le ahorra la espera al abogado, asi que se ve y
   se lee. Existia como un icono de 56 px con tooltip -o sea, invisible para quien
   no pase el raton por encima, y en el telefono no hay raton-. */
.send-cta {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  padding: 12px 24px; border-radius: 999px;
  border: 1px solid rgba(56,224,245,.5);
  background: rgba(56,224,245,.13);
  color: var(--text-hi);
  font-size: 13.5px; font-weight: 600; letter-spacing: .01em;
  cursor: pointer;
  transition: all .2s var(--ease-fluid);
}
.send-cta:hover:not(:disabled) { background: rgba(56,224,245,.22); border-color: rgba(56,224,245,.8); box-shadow: 0 0 22px rgba(56,224,245,.24); }
.send-cta:active:not(:disabled) { transform: translateY(1px); }
.send-cta:disabled { opacity: .38; cursor: not-allowed; box-shadow: none; }
.send-cta:focus-visible { outline: 2px solid var(--acc-cyan); outline-offset: 3px; }

/* Los SECUNDARIOS: adjuntar y terminar. Discretos a proposito -son salidas, no la
   accion principal- pero con area de toque suficiente en el telefono. */
.voice-sec {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 8px 14px; border-radius: 999px;
  border: 1px solid var(--line-3);
  background: transparent;
  /* `--text-mute` Y NO `--text-dim`, y esto se midio en pantalla. `--text-dim` da 2,72:1
     sobre el fondo en oscuro y 2,19:1 en claro, o sea la mitad del 4,5:1 que pide WCAG AA
     para texto normal. Para un `.kicker` decorativo pasa -es la convencion del producto-,
     pero esto es la ETIQUETA DE UN BOTON: si no se lee, no se puede usar. `--text-mute`
     da 7,56:1 y 5,41:1, y sigue leyendose como secundario. */
  color: var(--text-mute);
  font-size: 12px;
  cursor: pointer;
  transition: all .2s var(--ease-fluid);
}
.voice-sec:hover:not(:disabled) { color: var(--text-hi); border-color: var(--acc-blue); background: var(--chip-bg); }
.voice-sec:disabled { opacity: .45; cursor: not-allowed; }
.voice-sec:focus-visible { outline: 2px solid var(--acc-cyan); outline-offset: 3px; }
.voice-sec.danger:hover:not(:disabled) { color: var(--acc-red); border-color: rgba(248,113,113,.45); background: rgba(248,113,113,.08); }

/* candado de función premium sobre botón */
.lock-badge {
  position: absolute; top: -5px; right: -5px;
  width: 16px; height: 16px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--grad-ia);
  color: var(--ink-cta);
  pointer-events: none;
}

/* ---------- mirror glass: cajón del chat (efecto espejo transparente) ---------- */
.mirror-glass {
  position: relative;
  /* EL CRISTAL PIERDE EL TINTE AZUL. El segundo degradado iba de `rgba(20,29,57,.46)` a
     `rgba(10,16,32,.60)`, y el primero de esos dos es azul marino: sobre un escritorio que
     ahora es casi negro, la caja de escritura se leía como un recuadro azulado pegado encima
     en vez de como cristal. Los mismos alfas con la base neutra del producto
     (`--bg-void` = #060912) dan cristal de verdad: se ve lo que hay detrás, no un color.
     El borde pasa a blanco al 10% por el mismo motivo: `--line-2` es una línea azulada. */
  background:
    linear-gradient(180deg, rgba(255,255,255,.06), rgba(255,255,255,0) 16%),
    linear-gradient(158deg, rgba(14,17,26,.46), rgba(8,10,18,.60));
  backdrop-filter: blur(30px) saturate(1.6) brightness(1.04);
  -webkit-backdrop-filter: blur(30px) saturate(1.6) brightness(1.04);
  border: 1px solid rgba(255,255,255,.10);
  box-shadow:
    inset 0 1px 0 rgba(240,244,255,.16),
    inset 0 -1px 0 rgba(0,0,0,.30),
    0 22px 60px -26px rgba(0,0,0,.85);
  transition: border-color .35s var(--ease-fluid), box-shadow .4s var(--ease-fluid), transform .4s var(--ease-fluid);
}
/* reflejo / lámina de espejo en la parte superior */
.mirror-glass::after {
  content: "";
  position: absolute; inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background:
    linear-gradient(180deg, rgba(240,244,255,.13), rgba(240,244,255,0) 30%),
    radial-gradient(120% 60% at 50% -10%, rgba(91,140,255,.10), transparent 60%);
  mix-blend-mode: screen;
  z-index: 0;
}
.mirror-glass > * { position: relative; z-index: 1; }
/* borde-gradiente luminoso que respira al enfocar el cajón */
.mirror-glass::before {
  content: "";
  position: absolute; inset: -1px;
  border-radius: inherit;
  padding: 1px;
  background: var(--grad-ia);
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  pointer-events: none;
  opacity: 0;
  transition: opacity .45s var(--ease-fluid);
  z-index: 0;
}
.mirror-glass:focus-within {
  border-color: transparent;
  transform: translateY(-1px);
  box-shadow:
    inset 0 1px 0 rgba(240,244,255,.22),
    inset 0 -1px 0 rgba(0,0,0,.30),
    0 0 0 1px rgba(91,140,255,.18),
    0 18px 50px -20px rgba(56,224,245,.30),
    0 22px 60px -26px rgba(0,0,0,.85);
}
.mirror-glass:focus-within::before { opacity: .85; }
html[data-theme="light"] .mirror-glass {
  background:
    linear-gradient(180deg, rgba(255,255,255,.7), rgba(255,255,255,.25) 18%),
    linear-gradient(158deg, rgba(255,255,255,.55), rgba(244,248,255,.62));
  /* EL BORDE VUELVE A SER TINTA. Arriba pasó a blanco al 10% para quitarle el azulado al
     cristal sobre fondo negro; aquí ese mismo blanco cae sobre un fondo casi blanco y la
     caja de escritura se queda SIN contorno. `--line-2` es la línea del tema claro
     (#c7d0e9) y es la que dibuja el borde que ya tenía antes de este cambio. */
  border-color: var(--line-2);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.9),
    inset 0 -1px 0 rgba(120,140,190,.18),
    0 22px 55px -28px rgba(30,42,90,.4);
}
html[data-theme="light"] .mirror-glass::after { mix-blend-mode: normal; opacity: .7; }

/* ---------- aura conversacional estilo Gemini Live ---------- */
.voice-aura {
  position: absolute; left: 50%; top: 50%;
  /* 320 px fijos se salian en un telefono estrecho (el aura esta centrada y difuminada,
     asi que asomaba por los bordes). Con `min()` ocupa lo que haya. */
  width: min(320px, 78vw); height: min(320px, 78vw);
  transform: translate(-50%, -50%);
  border-radius: 50%;
  pointer-events: none;
  background: conic-gradient(from 0deg,
    rgba(56,224,245,.55), rgba(91,140,255,.5) 28%,
    rgba(183,148,255,.55) 55%, rgba(240,166,255,.5) 78%, rgba(56,224,245,.55));
  filter: blur(34px);
  opacity: .42;
  z-index: 0;
}
@media (prefers-reduced-motion: no-preference) {
  .voice-aura { animation: auraspin calc(11s / var(--motion,1)) linear infinite; }
  .voice-aura.speak { animation-duration: calc(5s / var(--motion,1)); }
  .voice-aura.think { animation-duration: calc(3.4s / var(--motion,1)); }
}
.voice-aura.listen { opacity: .5; }
.voice-aura.speak  { opacity: .72; }
.voice-aura.think  { opacity: .6; }
.voice-aura.idle   { opacity: .3; }
@keyframes auraspin { to { transform: translate(-50%, -50%) rotate(360deg); } }

/* Copiar conversación. Va en el FLUJO del layout (no flotando): antes era absolute
   sobre el área de mensajes y tapaba las letras del primer mensaje. */
.copy-thread {
  display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--font-mono);
  font-size: 10.5px; letter-spacing: .04em;
  padding: 6px 12px; border-radius: 99px;
  border: 1px solid var(--line-2);
  background: linear-gradient(160deg, rgba(20,29,57,.7), rgba(10,16,32,.82));
  backdrop-filter: blur(16px) saturate(1.3);
  -webkit-backdrop-filter: blur(16px) saturate(1.3);
  color: var(--text-mute);
  box-shadow: 0 8px 24px -12px rgba(0,0,0,.7);
  transition: all .18s var(--ease-fluid);
}
.copy-thread:hover { color: var(--text-hi); border-color: var(--acc-cyan); box-shadow: var(--glow-cyan); }
.copy-thread.done { color: var(--acc-mint); border-color: rgba(52,211,166,.45); }

/* copiar mensaje del usuario (aparece al pasar el cursor) */
.user-msg-copy {
  opacity: 0;
  display: grid; place-items: center;
  width: 28px; height: 28px; border-radius: 8px;
  color: var(--text-dim);
  border: 1px solid transparent;
  transition: all .16s var(--ease-fluid);
  flex-shrink: 0;
}
.user-row:hover .user-msg-copy { opacity: 1; }
.user-msg-copy:hover { color: var(--acc-cyan); background: var(--bg-hover); border-color: var(--line-2); }
.user-msg-copy.done { opacity: 1; color: var(--acc-mint); }

/* ============================================================================
   LA ISLA DE CRISTAL (modulo Analizar caso)
   ============================================================================
   Un solo contenedor centrado en vez de dos columnas. El objetivo es de carga
   cognitiva: el abogado entra, ve UNA caja, elige como alimentarla y dispara.

   POR QUE EL RESPLANDOR VA EN `box-shadow` Y NO EN UN PSEUDOELEMENTO. `.glass::before` ya
   esta ocupado por el brillo del cristal, y `::after` lo usan `grad-border` y el borde vivo:
   un tercer inquilino habria apagado a uno de los dos SIN dar error -es el fallo que costo el
   hotfix del #694-. `box-shadow` no gasta pseudoelemento y admite varias capas.

   Y el resplandor se multiplica por `--glow`, el ajuste de intensidad del abogado: quien lo
   baje a cero tiene que ver la isla sin halo, o el ajuste no significa lo que dice. */
.cl-isla {
  position: relative;
  border-radius: var(--r-lg);
  /* Dos capas: un halo amplio y difuso que despega la isla del fondo, y un filo interior de
     1 px que le da el canto de cristal. */
  box-shadow:
    0 30px 80px -30px rgba(0, 0, 0, .8),
    0 0 70px -20px rgba(34, 211, 238, calc(.22 * var(--glow, 1))),
    inset 0 1px 0 rgba(255, 255, 255, calc(.05 * var(--glow, 1)));
}

/* ---------- El interruptor ovalado (subir documento / pegar texto) ----------
   El riel es el elemento con el fondo, y el INDICADOR es un hijo absoluto que se desliza:
   asi la transicion es un `transform`, que el navegador compone en la GPU. Animar el color de
   fondo de cada boton daria el mismo aspecto y costaria un repintado por fotograma. */
/* ES UNA REJILLA Y NO UN FLEX, y esto se corrigio MIDIENDO, no razonando.
   El indicador se desplaza con `translateX(i * 100%)`, o sea por SU PROPIO ancho, asi que su
   ancho tiene que ser EXACTAMENTE el de un boton. Con `display: inline-flex` y `flex: 1` eso
   parecia garantizado -crecimiento igual reparte el espacio a partes iguales- y es falso cuando
   el contenedor mide lo que pide su contenido: no hay espacio libre que repartir, `min-width:
   auto` impide que un boton baje de su texto, y cada uno acaba con el ancho de SU rotulo.
   Medido en el navegador con «Comparar versiones» / «Auditar contrato»: riel 305,9 px, botones
   158,5 y 137,4, indicador 148. Ni uno ni el otro, y el error se ACUMULA opcion a opcion: bajo la
   segunda pestaña el indicador quedaba 10 px corrido. Con tres opciones es peor.
   `grid-auto-columns: 1fr` reparte en pistas IGUALES y, al medir el contenido, las iguala todas al
   rotulo mas largo. Es la unica forma de que la cuenta del indicador sea exacta por construccion
   en vez de por casualidad. */
.cl-pill {
  position: relative;
  display: inline-grid;
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  padding: 4px;
  border-radius: 999px;
  background: var(--well-bg);
  border: 1px solid var(--line-1);
}
.cl-pill-ind {
  position: absolute;
  top: 4px;
  bottom: 4px;
  left: 4px;
  border-radius: 999px;
  background: var(--grad-ia);
  box-shadow: 0 2px 14px -4px rgba(34, 211, 238, calc(.55 * var(--glow, 1)));
  pointer-events: none;
}
.cl-pill-btn {
  position: relative;               /* por encima del indicador */
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 8px 18px;
  border-radius: 999px;
  font-family: var(--font-display);
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-mute);
  white-space: nowrap;
  cursor: pointer;
  background: transparent;
  border: none;
}
.cl-pill-btn[aria-selected="true"] { color: var(--ink-cta); }
.cl-pill-btn:not([aria-selected="true"]):hover { color: var(--text-hi); }

/* ---------- El area de soltar ----------
   SIN BORDE PUNTEADO, que es lo que se pidio y ademas coincide con la decision que este
   modulo ya habia tomado: un punteado, unas esquinas HUD y un arco de luz sobre el mismo
   contorno se estorban y la caja se lee como un error de maquetacion. Aqui el contorno es un
   borde de 1 px casi invisible que SOLO se enciende cuando hay algo que soltar. */
.cl-dz {
  position: relative;
  border-radius: var(--r-md);
  border: 1px solid var(--line-1);
  background: var(--well-bg);
  transition: border-color .22s var(--ease-fluid), background .22s var(--ease-fluid),
              box-shadow .22s var(--ease-fluid);
}
.cl-dz:hover { border-color: var(--line-2); }
/* ARRASTRANDO: el cian de la marca. Es la unica señal de que el archivo se puede soltar ahi,
   asi que se ilumina el borde Y el fondo -un borde solo se pierde en una pantalla grande-. */
.cl-dz.dz-on {
  border-color: var(--acc-cyan);
  background: color-mix(in oklab, var(--acc-cyan) 7%, var(--well-bg));
  box-shadow:
    0 0 0 1px var(--acc-cyan),
    0 0 34px -6px rgba(34, 211, 238, calc(.45 * var(--glow, 1))),
    inset 0 0 40px -12px rgba(34, 211, 238, calc(.35 * var(--glow, 1)));
}

/* ============================================================================
   EL SISTEMA DE LA ISLA: lo que comparten los tres modulos de documentos
   ============================================================================
   Las clases de arriba nacieron en «Analizar caso» (#695). Lo que sigue es lo que hizo falta
   para que la MISMA isla sirviera tambien en «Revision de contratos» y en el «Comparador de
   sentencias», sin duplicar ni una regla: ver `frontend/app/isla.jsx`.

   LAS MEDIDAS VAN EN VARIABLES Y NO EN LOS .jsx. Los tres modulos escriben sus medidas en
   estilos EN LINEA, y un estilo en linea NO puede consultar un @media -pero SI puede leer una
   variable que un @media cambia-. Es el mismo truco de `--cl-2col`, y evita repetir el
   breakpoint en tres componentes. El breakpoint sigue viviendo en UN solo sitio (860 px, mas
   abajo, emparejado con `CL_MOVIL_PX` de shared.jsx). */
:root {
  --cl-isla-pad: 22px 24px 24px;   /* relleno de la isla */
  --cl-dz-pad: 38px 24px;          /* relleno del area de soltar */
  --cl-pad-pantalla: 34px 36px;    /* relleno de la pantalla del modulo */
  /* ANCHO MAXIMO DE LA ISLA. Sus contenedores miden 920 px (Analizar, Revisar), 1040 (Comparador)
     y 880 (Jurisprudencia), y a esos anchos el omnibox se estira: un interruptor de tres opciones
     flotando en medio de un rectangulo enorme y el rotulo del boton maestro perdido en su centro.
     820 px es la medida en la que la caja se sigue leyendo como UN objeto -y deja el resultado del
     Comparador a sus 1040, que ahi enfrentar dos o tres providencias en paralelo si necesita el
     ancho-.
     NO hace falta bajarlo en el telefono: `max-width` es un techo, no una anchura, asi que a 360 px
     no ata nada.

     SEGUNDA REVISION: DE 820 A 660. El 820 seguia leyendose estirado en un monitor grande. 660 es
     el ancho al que la caja se lee como UN bloque compacto y no como una superficie que hay que
     rellenar, y sigue dando de sobra para lo mas ancho que tiene que caber dentro: el interruptor
     de tres vias de la optica (unos 300 px), el rotulo «Construir linea jurisprudencial» (unos 230)
     y el parrafo de ayuda del area de soltar (que ya se autolimita a 420). Medido: a 660 nada
     ajusta linea de mas ni se aprieta. */
  --cl-isla-max: 660px;
}

/* ---------- Variante TENUE del interruptor ----------
   Para un segmented control SECUNDARIO dentro de la isla: la optica de la revision de
   contratos (equilibrado / contratante / contratista) va debajo del interruptor principal, y
   con el degradado de marca en los dos, los dos gritan lo mismo y ninguno manda. El indicador
   tenue es un relleno translucido con el cian de la marca: se ve cual esta activo, sin
   competir con el interruptor que decide el modo.
   Se mantiene la MISMA geometria (mismo riel, mismo indicador absoluto, misma aritmetica), asi
   que no hay una segunda implementacion que se pueda desincronizar. */
.cl-pill-tenue { background: transparent; border-color: var(--line-2); }
.cl-pill-tenue .cl-pill-ind {
  background: color-mix(in oklab, var(--acc-cyan) 16%, transparent);
  border: 1px solid color-mix(in oklab, var(--acc-cyan) 45%, transparent);
  box-shadow: 0 0 14px -6px rgba(34, 211, 238, calc(.5 * var(--glow, 1)));
}
.cl-pill-tenue .cl-pill-btn { font-size: 11.5px; padding: 6px 14px; }
/* Sobre el degradado el texto va en `--ink-cta`; sobre un relleno translucido, ese color no
   contrasta. Aqui el activo se marca con el cian de la marca. */
.cl-pill-tenue .cl-pill-btn[aria-selected="true"] { color: var(--acc-cyan); }

/* ---------- LAS FICHAS: el selector de MUCHAS opciones ----------
   Para dos o tres opciones el control correcto es el interruptor de arriba. Para siete -las
   calculadoras del liquidador- no: el interruptor reparte su ancho en pistas iguales, asi que
   siete en un telefono son 43 px cada una y en escritorio mas de 900 px de riel.
   Estas fichas ENVUELVEN, asi que caben en cualquier ancho. Y son OVALADAS como el interruptor:
   lo que habia antes eran rectangulos de esquina blanda con borde de 1 px, siete en fila, que se
   leian como una rejilla de botones rigidos en vez de como una lista de herramientas. */
.cl-ficha {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 15px;
  border-radius: 999px;
  border: 1px solid var(--line-2);
  background: transparent;
  color: var(--text-mute);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 12.5px;
  cursor: pointer;
  transition: color .18s var(--ease-fluid), border-color .18s var(--ease-fluid),
              background .18s var(--ease-fluid);
}
.cl-ficha:hover { color: var(--text-hi); border-color: var(--acc-blue); }
.cl-ficha[aria-selected="true"] {
  color: var(--ink-cta);
  background: var(--grad-ia);
  border-color: transparent;
  box-shadow: var(--glow-ia);
}

/* ---------- EL BUSCADOR «SPOTLIGHT» ----------
   Una sola barra, ancha y central, que invita a escribir. Va DENTRO de una isla, asi que el
   resplandor de fondo y el arco de luz ya los pone `.cl-isla`; lo que aporta esta clase es el
   campo grande y su reaccion al foco.

   SE ILUMINA CON `:focus-within` Y NO CON `:hover`, y eso es a proposito por dos razones. La
   primera es de significado: lo que importa aqui no es que el raton pase por encima, es que el
   cursor este DENTRO y el abogado pueda escribir -es la misma señal que `dz-on` da en el area de
   soltar-. La segunda es que en una pantalla tactil no hay `hover` fiable: el foco, en cambio,
   ocurre igual al tocar el campo, asi que el efecto funciona en el telefono sin un caso especial.
   `:focus-within` en el contenedor y no `:focus` en el input, porque lo que se ilumina es la
   barra entera, con su icono y su boton. */
.cl-spotlight {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 6px 6px 6px 20px;
  border-radius: 999px;
  border: 1px solid var(--line-1);
  background: var(--well-bg);
  transition: border-color .22s var(--ease-fluid), box-shadow .22s var(--ease-fluid),
              background .22s var(--ease-fluid);
}
.cl-spotlight:focus-within {
  border-color: var(--acc-cyan);
  background: color-mix(in oklab, var(--acc-cyan) 5%, var(--well-bg));
  box-shadow:
    0 0 0 1px var(--acc-cyan),
    0 0 34px -8px rgba(34, 211, 238, calc(.45 * var(--glow, 1)));
}
.cl-spotlight-campo {
  flex: 1;
  /* `min-width: 0` NO es opcional: un `<input>` trae un ancho minimo propio, asi que con solo
     `flex: 1` no se encoge y empuja el boton fuera de la pantalla del telefono. */
  min-width: 0;
  background: transparent;
  border: none;
  outline: none;
  color: var(--text-hi);
  font-family: var(--font-display);
  font-size: 21px;
  padding: 12px 0;
}
.cl-spotlight-campo::placeholder { color: var(--text-dim); font-weight: 400; }

/* ---------- El area de soltar: los dos rotulos ----------
   En una pantalla TACTIL no hay arrastre, asi que «arrastra tu documento» describe un gesto
   que no existe. Los dos rotulos se pintan siempre y el @media elige: no se decide con el
   ancho porque `hover: none` no es lo mismo que «pantalla estrecha» -una portatil tactil y un
   iPad apaisado son anchos Y tactiles-. */
.cl-dz-toque { display: none; }
.cl-dz-puntero { display: inline; }

/* ---------- La bandeja de documentos (Comparador) ----------
   Una fila por providencia. Sin cristal propio: van DENTRO de la isla, que ya lo pone. */
.cl-bandeja-fila { transition: border-color .18s var(--ease-fluid), background .18s var(--ease-fluid); }
.cl-bandeja-fila:hover { border-color: var(--line-2); background: var(--bg-hover); }

/* ---------- PANTALLAS TACTILES: la isla sin puntero ----------
   Dos problemas distintos, y el segundo es el que rompe el modulo en un telefono.

   (1) EL `:hover` SE QUEDA PEGADO. En tactil muchos navegadores mantienen el estado `:hover`
   despues de un toque, asi que un borde que «se ilumina al pasar el dedo» se queda iluminado
   para siempre y deja de significar nada. Se neutraliza, igual que ya se hace con los tooltips
   y con las flechas del carrusel.

   (2) NO HAY ARRASTRE. En un telefono no se puede arrastrar un PDF a la pantalla, asi que
   «arrastra tu documento» describe un gesto imposible y el area de subida se queda sin camino
   visible. El rotulo cambia y el boton pasa a ser un area de toque de ancho completo y 48 px
   de alto: es el UNICO acceso al selector de archivos del sistema, no puede ser un boton de
   texto de 12 px. (48 px es el minimo recomendado para un objetivo tactil.) */
@media (hover: none) {
  .cl-dz:hover { border-color: var(--line-1); }
  .cl-bandeja-fila:hover { border-color: var(--line-1); background: var(--well-bg); }
  .cl-pill-btn:not([aria-selected="true"]):hover { color: var(--text-mute); }
  .cl-dz-puntero { display: none; }
  .cl-dz-toque { display: inline; }
  .cl-dz-btn { width: 100%; min-height: 48px; font-size: 14px; }
  /* Las fichas: mismo motivo que el interruptor. Un `:hover` que se queda pegado tras un toque
     deja DOS fichas con aspecto de activa, y entonces ninguna lo parece. */
  .cl-ficha:hover { color: var(--text-mute); border-color: var(--line-2); }
  .cl-ficha[aria-selected="true"]:hover { color: var(--ink-cta); border-color: transparent; }
  /* Y SON OBJETIVOS DE DEDO. Con los 9 px de relleno de escritorio salen unos 36 px de alto, por
     debajo del minimo recomendado de 44.
     EL `min-height` NO ES REDUNDANTE con el relleno, y esto lo corrigio una medicion: con solo
     `padding: 12px 16px` el boton media 42 px -12+12 de relleno, 2 de borde y 15,6 de linea-, o
     sea que seguia dos pixeles corto. El relleno depende de las metricas de la fuente y el
     `min-height` no, asi que el suelo se declara y se deja de calcular a mano. */
  .cl-ficha { padding: 12px 16px; min-height: 44px; }
}

/* tooltips simples */
[data-tip] { position: relative; }
[data-tip]:hover::before {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  background: var(--bg-hover);
  border: 1px solid var(--line-3);
  color: var(--text-mid);
  font-size: 11px;
  font-family: var(--font-body);
  padding: 4px 9px;
  border-radius: 7px;
  white-space: nowrap;
  z-index: 50;
  pointer-events: none;
  /* LOS DOS LADOS QUE NO SE USAN SE ANULAN EXPRESAMENTE, y no es redundante: es una red.
     El tooltip vive en `::before`, y si se pone `data-tip` en un elemento cuyo `::before` ya
     estaba ocupado -`.glass`, por ejemplo, que lo usa para el brillo del cristal- las dos
     reglas se pisan PROPIEDAD POR PROPIEDAD, y las que la regla del tooltip no declara
     sobreviven de la otra. Con `.glass::before` la que sobrevivia era `inset: 0`: el globo
     quedaba con `top: 0` y `bottom: calc(100% + 8px)` a la vez, sobre-restringido, su altura
     colapsaba a cero, el fondo desaparecia y el texto salia crudo encima del contenido.
     Declarandolos aqui, ese choque ya no puede descolocar el globo. Aun asi hay una prueba
     que persigue la combinacion, porque el brillo del cristal SI se pierde al pasar el raton
     y eso no lo arregla ninguna linea de CSS: hay que no ponerlos en el mismo elemento. */
  top: auto;
  right: auto;
}
/* Variante para chips pegados al borde superior/derecho (p. ej. el saldo de
   analisis en la cabecera): el tooltip baja y se ancla a la derecha para NO
   salirse de la pantalla, y ajusta el texto largo en varias lineas. */
/* `width: max-content` HACE FALTA, y su ausencia produjo una columna de una palabra por
   linea. Un elemento posicionado en absoluto con `width: auto` se calcula «shrink to fit»,
   y el ancho disponible se mide contra su BLOQUE CONTENEDOR, que aqui es el propio control
   -`[data-tip]` lleva `position: relative`-. En un boton de 85 px eso da un tooltip de 85 px:
   con un texto largo, el resultado es un tubo vertical. El `max-width` no lo arregla, porque
   solo pone un techo. `tip-esquina` (mas abajo) ya lo declaraba por esta misma razon. */
[data-tip].tip-left:hover::before {
  left: auto; right: 0; transform: none;
  top: calc(100% + 8px); bottom: auto;
  white-space: normal; width: max-content; max-width: min(240px, 76vw);
  text-align: left; line-height: 1.4;
}
/* Variante para botones pegados al borde IZQUIERDO (p. ej. adjuntar/microfono en
   la barra de escritura): el tooltip se ancla a la izquierda para NO cortarse. */
[data-tip].tip-right:hover::before {
  left: 0; right: auto; transform: none;
  white-space: normal; width: max-content; max-width: min(220px, 76vw);
  text-align: left; line-height: 1.4;
}
/* Variante para la burbuja flotante de la esquina INFERIOR DERECHA. Ninguna de las dos
   de arriba sirve ahi: la de por defecto se centra y se saldria por la derecha, y
   `tip-left` baja el tooltip, que en un elemento pegado al borde de abajo es fuera de
   la pantalla. Esta se ancla a la derecha y sale por ARRIBA, el unico lado con sitio.
   `width: max-content` con tope: el texto corto no se parte y el largo si. */
[data-tip].tip-esquina:hover::before {
  left: auto; right: 0; transform: none;
  bottom: calc(100% + 10px); top: auto;
  white-space: normal; width: max-content; max-width: 230px;
  text-align: left; line-height: 1.4;
}
/* Variante para elementos ANCHOS y centrados con un texto de ayuda LARGO: las tarjetas de
   dinero del tablero de Finanzas, cuyo texto es una frase entera («Honorarios pactados menos
   abonos recibidos. Los gastos del proceso no entran: son reembolsables por el cliente.»).

   POR QUE HACIA FALTA UNA CUARTA. El tooltip por defecto lleva `white-space: nowrap`, que es
   lo correcto para lo que hay en toda la aplicacion -etiquetas de tres palabras sobre botones
   de 24 px-, pero con una frase de 118 caracteres produce UNA SOLA LINEA de unos 700 px que
   se sale de la pantalla por un lado: el sintoma que se reporto como «el texto se corta».
   Las otras tres variantes si ajustan el texto, pero las tres MUEVEN el ancla a un borde
   -estan pensadas para elementos pegados a una esquina- y en una tarjeta centrada dentro de
   una rejilla eso descoloca el globo respecto a lo que describe.

   Asi que esta conserva el ancla por defecto (centrada y por arriba) y solo cambia el ajuste
   del texto. `width: max-content` con tope: una frase corta no se parte en dos lineas por
   gusto y una larga si. El tope va en `min(...)` con `vw` porque un maximo fijo de 280 px se
   sale igual en un telefono estrecho -y ahi el tooltip ya no se muestra, pero la regla no
   deberia depender de eso para ser correcta-. */
[data-tip].tip-ancho:hover::before {
  white-space: normal;
  width: max-content;
  max-width: min(280px, 72vw);
  text-align: left;
  line-height: 1.45;
}

/* Bandeja de soporte (admin): el bote de basura para borrar TODO el hilo de un
   abogado aparece al pasar el mouse por la fila (para no recargar la lista). */
.sop-conv .sop-del { opacity: 0; transition: opacity .15s; }
.sop-conv:hover .sop-del, .sop-conv .sop-del:focus-visible { opacity: .85; }

/* Grabacion de audio en soporte: efecto visual de que esta grabando. */
@keyframes clRecPulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: .3; transform: scale(.6); } }
.sop-rec-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--acc-red); box-shadow: 0 0 9px var(--acc-red); animation: clRecPulse 1s ease-in-out infinite; flex-shrink: 0; }
@keyframes clRecWave { 0%, 100% { transform: scaleY(.3); } 50% { transform: scaleY(1); } }
.sop-rec-wave { display: inline-flex; align-items: center; gap: 3px; height: 20px; }
.sop-rec-wave i { display: block; width: 3px; height: 20px; border-radius: 2px; background: var(--acc-red); transform-origin: center; animation: clRecWave .9s ease-in-out infinite; }
@keyframes clMicRing { 0% { box-shadow: 0 0 0 0 rgba(248,113,113,.55); } 70% { box-shadow: 0 0 0 9px rgba(248,113,113,0); } 100% { box-shadow: 0 0 0 0 rgba(248,113,113,0); } }
.sop-mic-rec { animation: clMicRing 1.3s ease-out infinite; }

/* Rebote sutil para el boton "rayo" que baja a las recargas de analisis. */
@keyframes clBoltBounce { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(3px); } }
.cl-bolt-jump { animation: clBoltBounce 1.7s ease-in-out infinite; }
.cl-bolt-jump:hover { animation-play-state: paused; filter: brightness(1.08); }


/* ==================== Simulador de audiencias (sala real) ==================== */
.aud-sala { position: absolute; inset: 0; overflow: hidden; background: #0a0806; }

/* ETIQUETAS DE LOS ROLES DENTRO DE LA SALA 3D (Fase 2).
   `pointer-events: none` CON `!important`, Y HACE FALTA ASI. Las etiquetas las proyecta el
   componente `Html` de drei, que escribe `pointer-events: auto` EN LINEA en su propio
   envoltorio: un estilo en linea gana a cualquier regla de hoja, asi que pasarle
   `style={{pointerEvents:'none'}}` al componente no sirve -se comprobo en un navegador real: las
   siete etiquetas seguian capturando el raton-.
   Y lo que esto evita es concreto: son siete divs flotando sobre el lienzo y, sin la regla, cada
   uno es una ZONA MUERTA donde el arrastre de la camara no llega. El abogado intenta girar la
   sala, engancha sin saberlo el rotulo de «Contraparte», y la camara no se mueve. Se aplica al
   subarbol entero (`*`) porque el texto va en un hijo. */
.aud-np3d-wrap, .aud-np3d-wrap * { pointer-events: none !important; }
/* techo con luminarias */
.aud-ceiling { position: absolute; top: 0; left: 0; right: 0; height: 13%;
  background: linear-gradient(180deg, #15100a, #0c0805);
  box-shadow: inset 0 -14px 26px rgba(0,0,0,.6); }
.aud-ceiling::before { content: ''; position: absolute; left: 12%; right: 12%; top: 34%; height: 26%;
  background: repeating-linear-gradient(90deg, rgba(255,238,200,.5) 0 44px, transparent 44px 150px);
  filter: blur(1px); opacity: .5; border-radius: 4px; }
/* paredes laterales en perspectiva (dan profundidad de sala) */
.aud-sidewall { position: absolute; top: 12%; bottom: 34%; width: 18%;
  background: linear-gradient(90deg, #2c2013, #17100a); }
.aud-sidewall.left { left: 0; clip-path: polygon(0 0, 100% 11%, 100% 89%, 0 100%); box-shadow: inset -18px 0 30px rgba(0,0,0,.5); }
.aud-sidewall.right { right: 0; clip-path: polygon(0 11%, 100% 0, 100% 100%, 0 89%); box-shadow: inset 18px 0 30px rgba(0,0,0,.5); }
/* pared de madera al fondo (paneles + friso) */
.aud-wall { position: absolute; top: 12%; left: 0; right: 0; bottom: 34%;
  background:
    repeating-linear-gradient(90deg, rgba(0,0,0,.16) 0 2px, transparent 2px 96px),
    linear-gradient(180deg, #4c3826 0%, #3a2917 62%, #2c1f13 100%);
  box-shadow: inset 0 -30px 50px rgba(0,0,0,.55), inset 0 8px 20px rgba(0,0,0,.4); }
.aud-wall::before { content: ''; position: absolute; left: 0; right: 0; bottom: 20%; height: 3px;
  background: linear-gradient(180deg, #c9a24b, #6f5526); opacity: .5; }
.aud-wall::after { content: ''; position: absolute; left: 0; right: 0; top: 0; height: 7px;
  background: linear-gradient(180deg, #d8b45f, #7a5f2a); opacity: .5; }
/* banderas de Colombia flanqueando el emblema */
.aud-flag { position: absolute; top: 16%; width: 34px; height: 92px; border-radius: 2px;
  background: linear-gradient(180deg, #fcd116 0 50%, #003893 50% 75%, #ce1126 75% 100%);
  box-shadow: 0 6px 16px rgba(0,0,0,.5), inset 0 0 0 1px rgba(0,0,0,.25); opacity: .92; }
.aud-flag.left { left: calc(50% - 118px); transform: rotate(-3deg); }
.aud-flag.right { left: calc(50% + 84px); transform: rotate(3deg); }
/* piso de madera con tapete central */
.aud-floor { position: absolute; left: 0; right: 0; bottom: 0; top: 66%;
  background:
    repeating-linear-gradient(90deg, rgba(0,0,0,.22) 0 1px, transparent 1px 74px),
    linear-gradient(180deg, #2a1d12, #120c07);
  box-shadow: inset 0 30px 50px rgba(0,0,0,.72); }
.aud-floor::before { content: ''; position: absolute; left: 50%; top: 0; width: 46%; height: 100%; transform: translateX(-50%);
  background: linear-gradient(180deg, rgba(122,26,26,.4), rgba(80,16,16,.18)); }
/* baranda / barra de madera al frente */
.aud-rail { position: absolute; left: 8%; right: 8%; bottom: 33%; height: 12px; border-radius: 3px;
  background: linear-gradient(180deg, #6a4c2c, #3a2817); box-shadow: 0 8px 18px rgba(0,0,0,.5); z-index: 2; }
.aud-rail::before { content: ''; position: absolute; left: 0; right: 0; top: 12px; height: 26px;
  background: repeating-linear-gradient(90deg, #4a3420 0 4px, transparent 4px 26px); opacity: .8; }
/* emblema Rama Judicial */
.aud-emblem { position: absolute; top: 15%; left: 50%; transform: translateX(-50%); display: flex; flex-direction: column; align-items: center; gap: 5px; text-align: center; z-index: 3; }
.aud-emblem .ring { width: 82px; height: 82px; border-radius: 50%; display: grid; place-items: center;
  background: radial-gradient(circle at 50% 32%, #221a11, #0b0805); border: 3px solid #c9a24b;
  box-shadow: 0 0 26px rgba(201,162,75,.5), inset 0 0 18px rgba(0,0,0,.72); color: #e7c877; }
.aud-emblem .t1 { font-family: var(--font-display); font-size: 10.5px; letter-spacing: .22em; color: #e7c877; text-transform: uppercase; }
.aud-emblem .t2 { font-size: 8px; letter-spacing: .28em; color: rgba(231,200,119,.65); text-transform: uppercase; }
/* estrado del juez (elevado, con respaldo) */
.aud-bench { position: absolute; top: 40%; left: 50%; transform: translateX(-50%); width: min(320px, 50%); height: 92px;
  background-color: #43301c;
  background-image: repeating-linear-gradient(90deg, rgba(0,0,0,.14) 0 1px, transparent 1px 40px), linear-gradient(180deg, #5a4229, #33230f);
  border-radius: 8px 8px 4px 4px; border: 1px solid rgba(201,162,75,.4);
  box-shadow: 0 26px 44px rgba(0,0,0,.62), inset 0 2px 0 rgba(255,255,255,.06); z-index: 2; }
.aud-bench::before { content: ''; position: absolute; inset: 14px 18px auto 18px; height: 46%; border-radius: 5px;
  background: linear-gradient(180deg, #4a3320, #29190d); box-shadow: inset 0 0 18px rgba(0,0,0,.6); }
/* mesas de las partes y estrado del testigo */
.aud-desk { position: absolute; bottom: 12%; width: min(196px, 28%); height: 58px;
  background-image: repeating-linear-gradient(90deg, rgba(0,0,0,.12) 0 1px, transparent 1px 34px), linear-gradient(180deg, #4a3626, #281a10);
  border-radius: 7px; border: 1px solid rgba(201,162,75,.28); box-shadow: 0 16px 26px rgba(0,0,0,.55); z-index: 3; }
.aud-desk.left { left: 7%; } .aud-desk.right { right: 7%; }
.aud-witness { position: absolute; top: 46%; right: 15%; width: 62px; height: 60px;
  background: linear-gradient(180deg, #4a3626, #281a10); border-radius: 7px 7px 4px 4px; border: 1px solid rgba(201,162,75,.25); box-shadow: 0 12px 22px rgba(0,0,0,.5); z-index: 2; }
/* silueta de persona (cabeza + hombros) que sobresale del mueble */
.aud-figure { position: absolute; left: 50%; bottom: 100%; transform: translateX(-50%); width: 48px; height: 40px; margin-bottom: -5px;
  background: linear-gradient(180deg, #202632, #0e131a); border-radius: 40px 40px 9px 9px;
  box-shadow: inset 0 2px 0 rgba(255,255,255,.05); transition: box-shadow .3s, filter .3s; }
.aud-figure::before { content: ''; position: absolute; left: 50%; bottom: 66%; transform: translateX(-50%); width: 25px; height: 25px; border-radius: 50%;
  background: radial-gradient(circle at 42% 34%, #2c343f, #10151c); box-shadow: inset 0 1px 0 rgba(255,255,255,.06); transition: box-shadow .3s; }
.aud-figure.sm { width: 40px; height: 34px; }
.aud-figure.sm::before { width: 21px; height: 21px; }
/* placa dorada */
.aud-plate { position: absolute; left: 50%; transform: translateX(-50%); bottom: 6px; padding: 2px 9px; font-size: 8.5px; letter-spacing: .14em;
  text-transform: uppercase; color: #20160c; background: linear-gradient(180deg, #ecd293, #c39c44); border-radius: 3px; box-shadow: 0 2px 6px rgba(0,0,0,.5); white-space: nowrap; font-weight: 700; z-index: 2; }
/* posición activa (quien habla) */
.aud-pos { transition: box-shadow .3s ease, filter .3s ease; }
@keyframes audSpeak { 0%,100% { box-shadow: 0 0 0 2px rgba(90,200,245,.7), 0 0 26px rgba(90,200,245,.4); } 50% { box-shadow: 0 0 0 2px rgba(90,200,245,.95), 0 0 46px rgba(90,200,245,.78); } }
.aud-pos.speaking { animation: audSpeak 1.3s ease-in-out infinite; filter: brightness(1.16); }
.aud-pos.speaking .aud-figure, .aud-pos.speaking .aud-figure::before { box-shadow: 0 0 20px rgba(90,200,245,.75); filter: brightness(1.3); }
/* luz cálida + viñeta */
.aud-light { position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(120% 74% at 50% -8%, rgba(226,184,112,.22), transparent 54%),
              radial-gradient(90% 90% at 50% 120%, rgba(0,0,0,.5), transparent 60%); }
.aud-vignette { position: absolute; inset: 0; pointer-events: none; box-shadow: inset 0 0 240px rgba(0,0,0,.8); }
/* tarjeta de modo (config) */
.aud-modo { text-align: left; padding: 16px 16px; border-radius: 14px; border: 1px solid var(--line-2); background: var(--bg-hover); cursor: pointer; transition: border-color .15s, box-shadow .15s, transform .12s; }
.aud-modo:hover { transform: translateY(-1px); border-color: var(--acc-cyan); }
.aud-modo.sel { border-color: var(--acc-mint); box-shadow: 0 0 0 1px var(--acc-mint), 0 0 22px -6px var(--acc-mint); }
/* dropdown al estilo de la página (tipo de audiencia / rol) */
.aud-dd { position: relative; }
.aud-dd-btn { display: flex; align-items: center; gap: 8px; width: 100%; text-align: left; padding: 10px 12px; font-size: 13; cursor: pointer; }
.aud-dd-pop { position: absolute; z-index: 40; left: 0; right: 0; top: calc(100% + 6px); max-height: 320px; overflow-y: auto;
  border-radius: 12px; border: 1px solid var(--line-3); background: var(--bg-elev, #12151d); box-shadow: 0 20px 50px rgba(0,0,0,.55); padding: 6px; }
.aud-dd-group { font-size: 9.5px; letter-spacing: .14em; text-transform: uppercase; color: var(--acc-cyan); padding: 9px 10px 4px; }
.aud-dd-opt { display: block; width: 100%; text-align: left; padding: 8px 10px; border-radius: 8px; font-size: 12.5px; color: var(--text-mid); cursor: pointer; }
.aud-dd-opt:hover { background: var(--bg-hover); color: var(--text-hi); }
.aud-dd-opt.sel { background: rgba(52,211,166,.12); color: var(--acc-mint); }


/* Fondo FOTOGRÁFICO real de la sala (se ve como foto, no como dibujo)

   AJUSTADO PARA UNA SALA CLARA. Los valores anteriores estaban calibrados para una foto
   OSCURA: `brightness(.66)` le quitaba un tercio de luz y el velo de abajo llegaba a
   alpha .90. Sobre la sala institucional colombiana -paredes crema, piso claro, madera
   miel- eso no la oscurecía: la ENSUCIABA, y el escudo nacional y las banderas, que son
   justo lo que da la sensación de sala real, quedaban apagados y grises.
   Ahora la foto se respeta casi tal cual y el velo solo trabaja en los bordes. */
.aud-foto { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  /* `object-position` alto a propósito: con `cover`, en una pantalla ancha y baja se
     recorta arriba y abajo, y arriba está el escudo. Se sacrifica banca del público
     -que no aporta nada- antes que el escudo y las banderas. */
  object-position: 50% 42%;
  filter: saturate(1.04) contrast(1.02); }
.aud-foto-shade { position: absolute; inset: 0; pointer-events: none;
  /* La FRANJA CENTRAL (24%-56%) va casi limpia: ahí viven el escudo, las banderas y el
     estrado, o sea la credibilidad de la escena. Se oscurece solo arriba -donde va la
     placa «República de Colombia · Rama Judicial»- y abajo -donde van los indicadores de
     estado-, más una viñeta suave para que la foto no compita con la interfaz. */
  background:
    linear-gradient(180deg, rgba(10,14,22,.38) 0%, rgba(10,14,22,.05) 24%, rgba(10,14,22,.05) 56%, rgba(8,11,18,.58) 100%),
    radial-gradient(115% 72% at 50% 42%, transparent 42%, rgba(8,11,18,.30) 100%); }
.aud-topbar { position: absolute; top: 16px; left: 50%; transform: translateX(-50%); display: flex; align-items: center; gap: 12px; z-index: 2;
  padding: 6px 16px; border-radius: 999px; background: rgba(8,10,16,.5); border: 1px solid rgba(201,162,75,.35); backdrop-filter: blur(4px); }
.aud-topring { display: inline-grid; place-items: center; width: 30px; height: 30px; border-radius: 50%;
  background: radial-gradient(circle at 50% 34%, #221a11, #0b0805); border: 2px solid #c9a24b; color: #e7c877; box-shadow: 0 0 14px rgba(201,162,75,.4); }
.aud-toptxt { font-family: var(--font-display); font-size: 10.5px; letter-spacing: .2em; color: #e7c877; text-transform: uppercase; white-space: nowrap; }
.aud-topflag { width: 22px; height: 15px; border-radius: 2px; background: linear-gradient(180deg, #fcd116 0 50%, #003893 50% 75%, #ce1126 75% 100%); box-shadow: 0 1px 4px rgba(0,0,0,.5); }


/* Foco de luz sobre la posición de quien tiene la palabra (sobre la foto real) */
.aud-spot { position: absolute; transform: translate(-50%, -50%); width: 220px; height: 160px; pointer-events: none; display: flex; align-items: flex-end; justify-content: center; z-index: 2; }
/* El HALO sube de alpha .50 a .58 y nada más. Es el mismo celeste y el mismo tamaño: no
   se cambia el efecto, se compensa la física. Un halo es luz que se SUMA, y sumar luz
   sobre una pared crema se nota mucho menos que sobre una sala en penumbra; con el valor
   viejo, el foco casi desaparecía sobre el fondo nuevo. Si lo quieres más o menos
   marcado, esta alpha es la única palanca que hay que tocar. */
.aud-spot::before { content: ''; position: absolute; inset: 0; border-radius: 50%; opacity: 0; transition: opacity .35s ease;
  background: radial-gradient(ellipse at 50% 45%, rgba(130,215,255,.58), rgba(90,180,245,.18) 42%, transparent 72%); }
/* La ILUMINACIÓN (opacity) va fuera de la puerta de movimiento y el PULSO dentro: quien
   pida movimiento reducido tiene que seguir viendo A QUIÉN le toca hablar -eso es
   información, no decoración-, solo que sin latido. Antes el pulso corría siempre. */
.aud-spot.on::before { opacity: 1; }
@keyframes audSpotPulse { 0%, 100% { filter: brightness(1); transform: scale(1); } 50% { filter: brightness(1.3); transform: scale(1.06); } }
@media (prefers-reduced-motion: no-preference) {
  .aud-spot.on::before { animation: audSpotPulse calc(1.7s / var(--motion, 1)) ease-in-out infinite; }
}
/* ETIQUETAS DE LOS INTERVINIENTES (Juez, Fiscal, Usted...).

   SE HACEN AUTOSUFICIENTES, y eso es a propósito. Antes la pastilla era casi
   transparente (fondo alpha .50) y el texto también (alpha .55): se leía porque el velo
   de la foto era oscuro, o sea que la legibilidad dependía de CÓMO FUERA LA FOTO. Con una
   sala clara -madera miel y paredes crema- ese texto al 55% se disuelve.
   Subir el velo para compensar seria arreglarlo por el lado equivocado: apagaria la foto
   que acabamos de poner, y la proxima foto volveria a romperlo.
   Con fondo alpha .82 la pastilla garantiza el contraste POR SI MISMA: sobre madera clara
   da 13,2:1 y sobre blanco puro 10,3:1, muy por encima del 4,5:1 de la norma. Deja de
   importar qué haya detrás, y la foto puede cambiar sin que nadie recalcule nada. */
.aud-np { position: relative; z-index: 1; padding: 4px 12px; border-radius: 999px; font-size: 9.5px; letter-spacing: .14em; text-transform: uppercase; font-weight: 700;
  color: #f2f7ff; background: rgba(9,13,22,.82); border: 1px solid rgba(255,255,255,.58);
  /* DOBLE TRAZO, y esto es lo que resuelve «las etiquetas se pierden sobre la madera del
     estrado». Ojo con el diagnostico: el TEXTO nunca fue el problema -sobre madera oscura
     da 17:1-, lo que se perdia era la PASTILLA, que es oscura sobre un fondo oscuro. Subir
     su opacidad no arregla nada (mas oscuro sobre oscuro) y aclararla rompe el contraste
     del texto sobre la pared crema. Lo que define un objeto contra CUALQUIER fondo es el
     borde: un filo claro por dentro (.58) y un aro oscuro justo por fuera. Sobre madera
     oscura se ve el filo claro; sobre pared crema, el aro oscuro. Es el mismo recurso de
     los subtitulos de cine, y funciona sin tocar los colores medidos.
     La tercera capa es la sombra de contacto: sin ella la pastilla parece pegada con
     pegamento en vez de flotar sobre la escena. */
  box-shadow: 0 0 0 1px rgba(0,0,0,.55), 0 2px 12px rgba(0,0,0,.5);
  backdrop-filter: blur(3px); transition: all .3s ease; white-space: nowrap; }
/* TURNO DE PALABRA: se conserva la inversión celeste, que es la señal que ya funciona
   (texto #061018 sobre el degradado = 9,4:1 en su punto más flojo). Solo se refuerza el
   aro y se le añade sombra: contra una pared crema, un borde celeste claro sobre fondo
   celeste claro se perdía, y el aro es lo que dice «este es el que tiene la palabra». */
/* El mismo encendido sirve para los rotulos posicionados de escritorio y para la tira
   compacta de pantalla angosta: una sola definicion, asi que los dos modos no pueden
   divergir en el aspecto de «quien tiene la palabra». */
.aud-spot.on .aud-np, .aud-np.encendida { color: #061018; background: linear-gradient(180deg, #bfe6ff, #6cc3f5);
  border-color: rgba(255,255,255,.92);
  box-shadow: 0 0 18px rgba(120,210,255,.75), 0 2px 10px rgba(0,0,0,.35); }

/* TIRA DE INTERVINIENTES (pantalla angosta). Una sola linea, centrada, que se puede
   arrastrar si no cabe: en 320 px siete pastillas no entran, y envolver a dos lineas
   robaria alto a una pantalla que ya va justa. */
.aud-tira { display: flex; gap: 5px; align-items: center; margin-top: 8px;
  overflow-x: auto; scrollbar-width: none; -ms-overflow-style: none;
  padding-bottom: 2px; }
.aud-tira::-webkit-scrollbar { display: none; }
.aud-tira .aud-np { flex: 0 0 auto; font-size: 8.5px; letter-spacing: .1em; padding: 3px 8px; }


/* Lo que el abogado debe DECIR (resaltado dentro de la guía del modo principiante).
   El recuadro de la guía tiene fondo NEUTRO oscuro, así este realce menta contrasta y se lee bien. */
.aud-decir { color: #eafff6; font-weight: 700; text-decoration: underline; text-decoration-color: var(--acc-mint); text-decoration-thickness: 2px; text-underline-offset: 3px; background: rgba(52,211,166,.22); border: 1px solid rgba(52,211,166,.5); border-radius: 5px; padding: 1px 5px; box-decoration-break: clone; -webkit-box-decoration-break: clone; }


/* Roadmap de etapas de la audiencia (sobre la foto) */
.aud-road { display: flex; align-items: center; gap: 4px; flex-wrap: wrap; margin-top: 10px; padding: 7px 10px; border-radius: 10px; background: rgba(8,10,16,.5); border: 1px solid rgba(255,255,255,.08); backdrop-filter: blur(3px); }
.aud-road-step { display: inline-flex; align-items: center; gap: 5px; padding: 2px 8px 2px 4px; border-radius: 999px; opacity: .55; }
.aud-road-step .aud-road-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--text-dim); box-shadow: none; flex-shrink: 0; transition: all .3s; }
.aud-road-step .aud-road-lbl { font-size: 9.5px; letter-spacing: .04em; color: var(--text-mute); white-space: nowrap; }
.aud-road-step.done { opacity: .8; }
.aud-road-step.done .aud-road-dot { background: var(--acc-mint); }
.aud-road-step.on { opacity: 1; background: rgba(90,200,245,.14); }
.aud-road-step.on .aud-road-dot { background: var(--acc-cyan); box-shadow: 0 0 10px var(--acc-cyan); }
.aud-road-step.on .aud-road-lbl { color: var(--text-hi); font-weight: 700; }
/* Fila del historial de simulaciones */
.aud-hist-row { transition: border-color .15s, transform .12s; }
.aud-hist-row:hover { border-color: var(--acc-cyan); transform: translateY(-1px); }

/* ---------- Extreme Makeover del Simulador — layout de tarjetas ----------

   ANTES: una sola columna de 720 px (efecto pergamino, carga cognitiva alta).
   AHORA: los campos se agrupan en tres tarjetas temáticas con cabecera, y en pantallas
   anchas las dos primeras se colocan lado a lado con CSS Grid, reduciendo el scroll y
   dando la sensación de formulario profesional.

   El CARRUSEL de casos de ejemplo pasa de `flex-wrap` (muchos renglones) a scroll
   horizontal en una línea, ahorrando toda la cabecera sin perder ningún ejemplo. La barra
   de desplazamiento se oculta reutilizando `.cl-fila-scroll`, que ya existía para esto.

   Y OJO CON ESCONDER ESA BARRA, que es el fallo que se corrigió después: en un teléfono
   se arrastra con el dedo, pero en escritorio la barra era el ÚNICO mando de un ratón, así
   que al ocultarla los últimos casos quedaban recortados y sin forma de alcanzarlos. De
   ahí las flechas y el desvanecido del borde de más abajo: no son adorno, son el mando
   que se quitó. */

/* ---- Carrusel horizontal de casos de ejemplo ----
   El ocultado de la barra, el `-webkit-overflow-scrolling` y el «los hijos no se
   encogen» NO se repiten aqui: los pone `.cl-fila-scroll`, que ya existia para esto y
   se aplica junto con esta clase. Aqui va solo lo propio del carrusel. */
.aud-carousel-wrap { position: relative; }
.aud-carousel {
  display: flex; gap: 8px; overflow-x: auto; padding: 4px 0;
  scroll-snap-type: x proximity;
  /* `min-width: 0` es lo que permite que un contenedor desplazable metido en un flex
     column se ENCOJA en vez de estirar a su padre. Sin esto, el minimo automatico es el
     del contenido y la fila empuja el ancho de la tarjeta. */
  min-width: 0;
}
.aud-carousel-item { scroll-snap-align: start; white-space: nowrap; }

/* EL DESVANECIDO AVISA DE QUE LA FILA SIGUE. Con la barra oculta, una fila cortada a
   escuadra parece una fila que se termina; con el borde difuminado se lee como que hay
   mas. Va con mascara y no con un degradado superpuesto porque detras esta la aurora
   animada: un color plano no la puede imitar y se veria un parche. */
.aud-carousel.tiene-der {
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 44px), transparent 100%);
  mask-image: linear-gradient(to right, #000 calc(100% - 44px), transparent 100%);
}
.aud-carousel.tiene-izq {
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 44px);
  mask-image: linear-gradient(to right, transparent 0, #000 44px);
}
.aud-carousel.tiene-izq.tiene-der {
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 44px, #000 calc(100% - 44px), transparent 100%);
  mask-image: linear-gradient(to right, transparent 0, #000 44px, #000 calc(100% - 44px), transparent 100%);
}

/* Flechas del carrusel: el mando que un raton no tiene cuando la barra esta oculta.
   Solo se dibujan si queda algo hacia ese lado (lo decide el .jsx midiendo). */
.aud-carousel-arrow {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 3;
  display: grid; place-items: center; width: 30px; height: 30px;
  border-radius: 50%; border: 1px solid var(--line-3);
  /* `--bg-elev` y no `--bg-card`: es el token declarado OPACO a proposito, para lo que
     flota y tiene que TAPAR lo que pasa por debajo. Una flecha se dibuja encima de los
     casos, asi que si transparenta se lee el titulo del boton a traves del icono. De
     paso ya esta cubierto por `.aud-escena-oscura`, que es la regla que obliga a que la
     escena no herede colores del tema claro (lo comprueba test_contraste_accesible.js). */
  background: var(--bg-elev); color: var(--text-mid);
  box-shadow: 0 4px 14px rgba(0,0,0,.35);
  transition: color .15s, border-color .15s, background .15s;
}
.aud-carousel-arrow:hover { color: var(--text-hi); border-color: var(--acc-cyan); background: var(--bg-hover); }
.aud-carousel-arrow.izq { left: -6px; }
.aud-carousel-arrow.der { right: -6px; }
/* En pantallas tactiles se arrastra con el dedo, asi que las flechas solo estorban:
   tapan el primer y el ultimo caso de la fila. */
@media (hover: none) {
  .aud-carousel-arrow { display: none; }
}

/* PISTA DE ARRASTRE (solo pantallas tactiles).
   En el telefono no hay flechas -se esconden justo arriba- y el borde difuminado, que en
   escritorio basta como aviso, no le dice a nadie QUE HACER. Esta pista es el gesto
   dibujado: una flecha pequeña pegada al borde derecho que se mueve un poco hacia el lado,
   que es lo que un dedo lee como «arrastra por aqui».
   Va OCULTA por defecto y solo se enciende bajo `hover: none`, o sea el complemento exacto
   del @media de las flechas: nunca se ven las dos cosas a la vez. */
.aud-carousel-pista {
  display: none;
  position: absolute; right: 2px; top: 50%; z-index: 2;
  /* El `translateY` va TAMBIEN aqui y no solo en la animacion: quien pide movimiento
     reducido no ejecuta los fotogramas, y sin esto su flecha quedaria descentrada. */
  transform: translateY(-50%);
  pointer-events: none;                      /* no puede robarle el toque al ultimo caso */
  color: var(--acc-cyan);
  opacity: .85;
}
@media (hover: none) {
  .aud-carousel-pista { display: inline-flex; }
}
/* El movimiento va detras de la puerta de siempre: quien pide menos movimiento sigue
   viendo la flecha -eso es informacion-, solo que quieta. */
@media (hover: none) and (prefers-reduced-motion: no-preference) {
  .aud-carousel-pista { animation: audPista calc(1.6s / var(--motion, 1)) ease-in-out infinite; }
}
@keyframes audPista {
  0%, 100% { transform: translate(0, -50%); opacity: .5; }
  50%      { transform: translate(-5px, -50%); opacity: 1; }
}

/* ---------- Secciones plegables del expediente (Mis casos) ----------
   La columna izquierda del expediente eran trece tarjetas abiertas en fila («efecto
   pergamino»). Ahora cada una es un acordeon con el MISMO encabezado, definido aqui una vez
   en vez de copiado trece veces en el .jsx. Ver `CasoSeccion` en cases.jsx para el criterio
   de que se deja abierto. */
.caso-sec-cab { display: flex; align-items: center; gap: 8px; }
/* El titulo es el area de toque grande: ocupa todo el ancho que sobra. */
.caso-sec-btn {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: 8px;
  background: transparent; border: none; padding: 0;
  cursor: pointer; text-align: left;
}
.caso-sec-btn .kicker { transition: color .15s; }
.caso-sec-btn:hover .kicker { color: var(--text-hi); }
/* El rotulo de la seccion CERRADA (¿3 pendientes? ¿cuanto por cobrar?). Se recorta con
   puntos suspensivos: es un resumen, y si no cabe vale mas verlo a medias que romper la
   fila del encabezado. */
.caso-sec-res {
  margin-left: auto; flex-shrink: 1; min-width: 0;
  font-family: var(--font-mono); font-size: 9.5px;
  color: var(--text-dim);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.caso-sec-extra { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.caso-sec-tog {
  flex-shrink: 0; display: grid; place-items: center;
  width: 24px; height: 24px; border-radius: 7px;
  border: 1px solid var(--line-2); background: transparent;
  color: var(--text-mute); cursor: pointer;
  transition: color .15s, border-color .15s, background .15s;
}
.caso-sec-tog:hover { color: var(--text-hi); border-color: var(--acc-cyan); background: var(--bg-hover); }

/* ---- Tarjeta temática (Card) ---- */
.aud-card {
  background: var(--glass-a);
  border: 1px solid var(--line-2);
  border-radius: var(--r-lg);
  padding: 20px 20px;
  display: flex; flex-direction: column; gap: 16px;
  /* Una tarjeta es una columna de un grid: sin esto, un campo ancho la estira por
     encima de su reparto y las dos columnas dejan de medir lo mismo. */
  min-width: 0;
}
.aud-card-header {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--font-display); font-weight: 600; font-size: 13px;
  color: var(--acc-cyan); letter-spacing: .03em; text-transform: uppercase;
  padding-bottom: 8px; border-bottom: 1px solid var(--line-1);
}

/* ---- Grid de dos columnas ----
   USA `--cl-2col` EN VEZ DE SU PROPIO @media, Y ESO ARREGLA UN FALLO DEL #684.
   Alli se escribio `@media (min-width: 768px)`, pero el limite de «esto es un telefono»
   de este proyecto son 860 px, y esta escrito en DOS sitios que tienen que coincidir:
   `CL_MOVIL_PX` en shared.jsx y el @media de mas abajo. Con 768 px habia una franja
   entre 768 y 860 en la que el CSS ya ponia dos columnas mientras el JavaScript seguia
   creyendo que era un telefono y dibujaba las variantes estrechas: dos columnas con el
   contenido apilado dentro. Justo el desajuste del que avisa el comentario del @media.
   Leyendo la variable, el limite vive en UN sitio y no puede volver a separarse. */
.aud-form-grid {
  display: grid; gap: 14px;
  grid-template-columns: var(--cl-2col);
}


/* ---------- Cuadriculas de dos columnas ----------
   Hay 25 cuadriculas de dos columnas repartidas por los modulos (el liquidador solo
   tiene 12), escritas en estilos EN LINEA como `1fr 1fr`. Y `1fr` NO es
   `minmax(0, 1fr)`: su minimo automatico es el del contenido, asi que un campo o una
   palabra larga impide que la columna se encoja y la cuadricula se sale de la
   pantalla. En un telefono de 360 px se salian los formularios enteros.

   En vez de repetir el breakpoint en doce componentes, los estilos en linea leen esta
   variable y el breakpoint vive AQUI, en un solo sitio: en el telefono las dos
   columnas se apilan. Un estilo en linea no puede consultar un @media, pero si puede
   leer una variable que un @media cambia. */
:root { --cl-2col: 1fr 1fr; --cl-2col-ancha: 1fr 1.6fr; --cl-3col: 1fr 1fr 1fr; }

/* ============================================================================
   TELEFONOS
   ============================================================================
   Esta aplicacion se escribio para escritorio y no tenia NADA de responsivo: el
   unico @media de ancho de todo el proyecto ocultaba el buho del login. En un
   telefono la barra lateral de 272 px se llevaba la pantalla, la cabecera y la
   barra de escritura pedian mas ancho del que hay, y como `body` lleva
   `overflow: hidden` lo que sobraba no se podia desplazar: se RECORTABA. El
   boton de Ejecutar quedaba literalmente fuera de la vista.

   El grueso del arreglo esta en los .jsx (ver clUsarEsMovil en shared.jsx),
   porque las medidas viven en estilos EN LINEA y un estilo en linea le gana a
   cualquier regla de aqui. Lo que queda en esta hoja es lo que SI se puede
   resolver con CSS: lo que ya estaba en clases.                             */

/* Fila que se puede desplazar de lado sin que se vea la barra de desplazamiento
   (los chips de la cabecera). Los hijos NO se encogen: un chip a medias es peor
   que un chip que hay que arrastrar para ver. */
.cl-fila-scroll { scrollbar-width: none; -ms-overflow-style: none; -webkit-overflow-scrolling: touch; }
.cl-fila-scroll::-webkit-scrollbar { display: none; }
.cl-fila-scroll > * { flex-shrink: 0; }

/* OJO: estos 860 px son los mismos de CL_MOVIL_PX en shared.jsx. Si se cambia uno
   hay que cambiar el otro, o habra un tramo de anchos en el que el CSS crea que es
   un telefono y el JavaScript crea que no (o al contrario). */
@media (max-width: 860px) {
  /* Las cuadriculas de dos columnas se apilan (ver arriba). Es `minmax(0, 1fr)` y no
     `1fr` a proposito: el minimo automatico de `1fr` es el del contenido, asi que una
     tabla o un campo ancho volvia a estirar la columna por encima de la pantalla.
     Con minimo 0 la columna se ajusta y el contenido se reparte dentro. */
  :root { --cl-2col: minmax(0, 1fr); --cl-2col-ancha: minmax(0, 1fr); --cl-3col: minmax(0, 1fr); }

  /* ---------- LA ISLA EN UN TELEFONO ----------
     LA CUENTA QUE OBLIGA A ESTO, con numeros: un telefono de 360 px con el relleno de
     escritorio se queda en 360 - 72 (la pantalla del modulo, 36 por lado) - 48 (la isla, 24
     por lado) = 240 px utiles. Ahi el rotulo del boton maestro del comparador («Construir
     linea jurisprudencial») ya no cabe, y el interruptor de tres vias de la optica tampoco.
     Con estos rellenos quedan 304 px, que es donde todo entra.

     Van en las variables de arriba y no en cada .jsx a proposito: los tres modulos escriben
     sus medidas en estilos EN LINEA, y un estilo en linea le gana a cualquier regla de esta
     hoja -pero puede LEER una variable que este @media cambia-. */
  :root {
    --cl-isla-pad: 16px 14px 18px;
    --cl-dz-pad: 26px 14px;
    --cl-pad-pantalla: 18px 14px 28px;
  }

  /* El interruptor pasa de «lo ancho que pidan sus rotulos» a ocupar la linea entera: en
     vertical el ancho es el recurso escaso y un control centrado de 240 px con 60 px de aire a
     cada lado se lee como un elemento suelto, no como el mando de la caja.
     La aritmetica del indicador NO cambia -sigue siendo un porcentaje de la caja de relleno-,
     asi que pasar de `inline-flex` a `flex` no lo descoloca. */
  .cl-pill-caja { width: 100%; }
  /* `grid` y no `inline-grid`: las pistas siguen siendo `1fr` iguales, pero ahora se reparten el
     ancho completo de la linea en vez del que pida el rotulo mas largo. */
  .cl-pill { display: grid; width: 100%; }
  /* Y los rotulos pueden partir linea. Es mas robusto que recortarlos: `.cl-pill-btn` lleva
     `white-space: nowrap` para que en escritorio no se parta «Subir documento», pero en 100 px
     de telefono lo que hace falta es que quepa, y dos lineas caben siempre. Recortar con
     puntos suspensivos no es opcion aqui: el texto de un boton flex no se puede elipsar. */
  .cl-pill-btn { padding: 9px 8px; font-size: 11.5px; min-width: 0; white-space: normal; line-height: 1.25; }
  .cl-pill-tenue .cl-pill-btn { font-size: 10.5px; padding: 8px 4px; }

  /* El boton maestro tambien parte linea. `.cta` lleva `white-space: nowrap` -correcto para un
     boton que se ajusta a su texto-, pero este ocupa el 100 % del ancho y con un rotulo largo
     se salia de la pantalla. Un boton ancho puede permitirse dos lineas. */
  .cl-boton-maestro { white-space: normal; }

  /* Los botones de quitar/editar de la bandeja no se encogen: son objetivos de dedo. */
  .cl-bandeja-actos { flex-shrink: 0; }

  /* EL BUSCADOR SPOTLIGHT EN UN TELEFONO. Los 21 px de escritorio no caben con el icono y el
     boton al lado, asi que baja a 17. NUNCA por debajo de 16: Safari en iOS AMPLIA la pagina al
     enfocar un campo mas pequeño, y el abogado se queda con la interfaz descuadrada y el teclado
     encima.
     Y hay que declararlo AQUI aunque mas abajo esta `input { font-size: 16px }`: esa regla es un
     selector de ELEMENTO (0,0,1) y `.cl-spotlight-campo` es una CLASE (0,1,0), asi que la clase
     gana y el campo se habria quedado en 21 px disparando el zoom. */
  .cl-spotlight { padding: 5px 5px 5px 14px; gap: 9px; }
  .cl-spotlight-campo { font-size: 17px; padding: 10px 0; }
  /* Las fichas del liquidador pueden partir linea: «Despido sin justa causa (art. 64)» no cabe
     en una sola en 304 px, y una ficha es una etiqueta, no un boton de accion. */
  .cl-ficha { white-space: normal; text-align: left; line-height: 1.25; }

  /* EL AVISO DE CUOTA AGOTADA. Son tres piezas en fila -icono, texto y «Mejorar plan»- y en un
     telefono el boton no cabe al lado de dos renglones de texto: el `flexWrap` del JSX lo baja a su
     propia linea. Lo que hay que declarar aqui es que ABAJO ocupe el ancho completo, porque un
     boton de 110 px suelto y pegado a la izquierda debajo de un parrafo se lee como si perteneciera
     a otra cosa. Y con 44 px de alto, que es objetivo de dedo. */
  .cl-aviso-cuota-btn { width: 100%; min-height: 44px; margin-top: 4px; }

  /* LAS TARJETAS DEL SIMULADOR AFLOJAN EL RELLENO EN EL TELEFONO.
     20 px por lado dentro de una pagina que ya lleva 14 px son 34 px comidos a cada
     lado: en una pantalla de 360 px, a un campo de texto le quedan 292, y ahi es donde
     se veia que los inputs iban «ahogados». Con 14 px el campo gana 12 px de ancho por
     lado sin que la tarjeta pierda su forma. El hueco ENTRE campos tambien baja: en
     vertical se leen como grupo por la cercania, no hace falta separarlos tanto. */
  .aud-card { padding: 14px 14px; gap: 13px; }

  /* Los botones heredados dejan de exigir un ancho que no existe. No se toca el
     de la barra de escritura ni el de la barra lateral: esos llevan su medida en
     linea, decidida en el .jsx segun el ancho real. */
  .cta, .btn-ghost { padding: 10px 16px; }

  /* 16 px es el minimo que NO dispara el zoom automatico de Safari en iOS al
     enfocar un campo. Con 14 px el telefono ampliaba la pagina y el abogado se
     quedaba con la interfaz descuadrada y el teclado encima. */
  .field, input, textarea, select { font-size: 16px; }

  /* Los chips de sugerencia pueden partir linea; los de la cabecera no (esos van
     en una fila que se desplaza, arriba). */
  .chip { max-width: 100%; }

  /* Las burbujas de lo que escribe el abogado aprovechan el ancho: con 86% se
     quedaban muy estrechas y una consulta larga salia en columna. Lleva
     !important porque ese 86% esta en un estilo EN LINEA, que de otro modo gana. */
  .user-row { max-width: 94% !important; }

  /* ---------- PANEL DE ADMINISTRACION ----------
     El panel admin se escribio entero para escritorio: no tenia ni un @media, ni un
     clUsarEsMovil, ni una tabla que se pudiera encoger. El grueso del arreglo esta en
     los .jsx (fichas en vez de tabla, modales a todo el ancho, las 17 secciones
     plegadas); aqui queda lo que SI se puede resolver desde la hoja de estilos.

     TABLAS. Las nueve tablas de los modales pedian entre 545 y 966 px. La razon no era
     el numero de columnas: era que un correo de 40 caracteres en `mono` NO TIENE NI UN
     ESPACIO donde partir linea, asi que la celda exigia su ancho completo y estiraba la
     tabla por encima de la pantalla. Con `anywhere` el correo parte en dos lineas y la
     tabla cabe: se lee de un tiron, sin arrastrar nada. El `overflow-x: auto` de
     TablaAdm queda como red de seguridad para lo que aun asi no quepa -y ahi se arrastra
     la tabla, no el modal entero-. */
  .adm-tabla table { font-size: 11.5px; }
  .adm-tabla th, .adm-tabla td { padding: 7px 7px !important; }
  .adm-tabla { -webkit-overflow-scrolling: touch; }
  /* OJO CON EL ALCANCE DE `anywhere`, que es donde se aprende algo.

     La primera version lo puso en TODAS las celdas. La tabla cabia... y partia
     «$159.900» en «$159.9 / 00», «approved» en «approve / d» y «2026-12-31» en
     «2026-12-3 / 1». Una cifra cortada en dos lineas no se lee mal: SE LEE OTRA, y estas
     son pesos que el administrador va a cuadrar contra un extracto bancario.

     Asi que se parte solo lo que de verdad lo necesita y no puede confundirse: los
     correos y los codigos de cupon, que son tokens largos SIN un solo espacio donde
     partir -y por eso estiraban la tabla-. Lo demas ya parte por sus espacios o es
     bastante corto para caber. Se marca a mano, con `adm-partir`, para que nadie lo
     herede por accidente. */
  .adm-tabla .adm-partir { overflow-wrap: anywhere; word-break: break-word; }
  /* Y se levanta el `white-space: nowrap` de las celdas. Estaba puesto en cuatro sitios
     -la fecha con hora de Pagos y Actividad, y la celda de botones de Cupones- y son
     justo las columnas que no podian encogerse: una sola de ellas estiraba la tabla 100
     px de mas. «1 de ago,» y «02:32 p. m.» en dos lineas se leen igual de bien. */
  .adm-tabla td, .adm-tabla th { white-space: normal !important; }

  /* Los dos modales que usan la clase .modal-overlay (Notificaciones y Ajustes) llevan
     su ancho en un estilo EN LINEA, asi que hace falta !important. Van a todo el ancho y
     pegados abajo, igual que los que si pasan por AdminModal. */
  .modal-overlay { padding: 0 !important; place-items: end center !important; }
  .modal-overlay > .glass {
    width: 100% !important;
    max-width: 100% !important;
    max-height: 93vh !important;
    padding: 18px 14px 24px !important;
    border-radius: var(--r-lg) var(--r-lg) 0 0 !important;
    overflow-x: hidden !important;
  }

  /* El titulo de cada notificacion enviada: dos lineas en vez de una cortada a los 152
     px que quedan en el telefono. Lleva !important porque el `nowrap` viene en linea. */
  .adm-notif-titulo {
    white-space: normal !important;
    overflow-wrap: anywhere;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    line-height: 1.35;
  }

  /* El aviso flotante esta centrado abajo y no tenia tope de ancho, y los del panel son
     frases largas («Usuario creado, pero el correo NO salio...»): se salia por los dos
     lados a la vez. */
  .toast { max-width: calc(100vw - 28px); }
}

/* Un segundo escalon, SOLO para las tablas del panel admin y SOLO de CSS: aqui no hay
   nada que decidir en JavaScript, asi que este 400 no tiene pareja en shared.jsx y no
   hace falta mantenerlo sincronizado con nada (a diferencia del 860 de arriba).

   Por que existe: a 390 px las tablas ya caben enteras. A 360 -que es un iPhone SE o un
   Android de gama de entrada, y los hay- tres de ellas se pasaban por entre 3 y 21 px.
   Veinte pixeles. Con 4 px de relleno por lado en vez de 7 se recuperan unos 30 y caben
   todas, sin tocar ni una medida del contenido. */
@media (max-width: 400px) {
  .adm-tabla table { font-size: 11px; }
  .adm-tabla th, .adm-tabla td { padding: 6px 4px !important; }
}

/* En pantallas TACTILES los tooltips no sirven -no hay puntero que se pose- y
   ademas estorban: `white-space: nowrap` los hace mas anchos que la pantalla y
   algunos navegadores mantienen el estado :hover pegado despues de un toque, asi
   que se quedaba un rectangulo de texto tapando la interfaz. La informacion no se
   pierde: todos estos controles llevan aria-label. */
@media (hover: none) {
  [data-tip]:hover::before { display: none; }
}


/* ============================================================================
   LA PORTADA PUBLICA (landing.jsx)
   ============================================================================
   POR QUE ESTA GEOMETRIA VIVE AQUI Y NO EN LINEA. Es la misma razon que ya dejo escrita
   `LoginFondoVideo` en auth.jsx: un estilo en linea GANA a cualquier regla de una @media
   -sin `!important`-, asi que todo lo que tenga que cambiar en el movil tiene que estar en
   esta hoja o el corte de abajo no sirve para nada. En landing.jsx solo se queda lo que mide
   igual en todos los tamanos.

   Y LA PORTADA SE DESPLAZA, que es lo que no hacia. `body` lleva `overflow: hidden` y
   `height: 100%` (arriba, lineas 3 y 11) porque la aplicacion es un escritorio de viewport
   fijo: ahi el scroll lo hacen los paneles de dentro, no la pagina. La portada es lo
   contrario -una pagina larga que termina en un pie- y heredaba ese bloqueo: el contenido
   por debajo del primer pantallazo se RECORTABA y no habia forma de llegar ni con la rueda
   ni con el dedo. El pie con los enlaces a terminos y privacidad quedaba inalcanzable, que
   es justo lo que Google tiene que poder ver.

   SE ARREGLA CON UN CONTENEDOR PROPIO Y NO TOCANDO `body`. Quitarle el `overflow: hidden` al
   `body` mientras la portada esta montada habria sido menos codigo y mas fragil: es estado
   global que hay que acordarse de devolver, y si se escapa deja la aplicacion entera con dos
   barras de desplazamiento. Asi el bloqueo del escritorio se queda como esta y la portada
   trae su propio scroll.

   `100dvh` DESPUES DE `100vh`, en ese orden y a proposito: en iOS `100vh` cuenta la barra de
   direcciones que el navegador esconde al bajar, asi que la primera pantalla sale mas alta
   que el hueco visible y el pie se queda siempre 60-80 px por debajo del borde. `dvh` mide
   el hueco DE VERDAD. El navegador que no entienda `dvh` se queda con la linea anterior. */
.cl-portada {
  height: 100vh;
  height: 100dvh;
  overflow-y: auto;
  /* En horizontal NO se desplaza: si algo se pasa de ancho es un defecto que hay que
     arreglar, y una barra horizontal solo lo disimularia. */
  overflow-x: hidden;
  /* Inercia en iOS. Sin esto el desplazamiento dentro de un contenedor se siente rigido,
     como si la pagina se arrastrara en vez de deslizarse. Ya se usa en `.cl-fila-scroll`. */
  -webkit-overflow-scrolling: touch;
  /* Que el rebote del final no arrastre a la pagina de detras. */
  overscroll-behavior-y: contain;
}

.cl-portada-nav {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 10px 20px;
  /* Barra de lado a lado: solo se le deja el canto de abajo. */
  border-radius: 0;
  border-left: none;
  border-right: none;
  border-top: none;
}

.cl-portada-main {
  max-width: 1100px;
  margin: 0 auto;
  padding: 0 20px 48px;
}

.cl-portada-hero { text-align: center; padding: 56px 0 34px; }
/* `clamp` en vez de tres cortes: el titular es lo unico que de verdad tiene que escalar con
   el ancho, y asi lo hace de forma continua entre 30 y 58 px. */
.cl-portada-titular { font-size: clamp(30px, 6vw, 58px); line-height: 1.06; letter-spacing: -.02em; margin-bottom: 18px; }
.cl-portada-bajada { max-width: 640px; margin: 0 auto 26px; font-size: 16px; line-height: 1.6; }
.cl-portada-video { margin-bottom: 44px; }
/* El marco del video: el relleno es el grosor del cristal que se ve alrededor. */
.cl-portada-marco { padding: 8px; }

/* ---- La caja 16:9 del reproductor ----------------------------------------------------
   UN IFRAME NO TIENE PROPORCION PROPIA, y esa es toda la razon de que esta clase exista. Un
   `<video>` conoce las dimensiones de su archivo y se adapta con `height: auto`; un `<iframe>`
   no sabe lo que hay dentro, asi que sin decirle nada se queda en los 300x150 px que trae por
   omision: el reproductor saldria como una franja diminuta en medio del cristal.

   `aspect-ratio` Y NO EL TRUCO DEL `padding-bottom: 56.25%`. Los dos funcionan, pero el del
   relleno necesita que el hijo vaya en `position: absolute` y que el padre no tenga relleno
   propio, y este padre SI lo tiene -es el cristal del marco-. `aspect-ratio` no pelea con nada
   y se lee. La compatibilidad esta cubierta: esta hoja ya depende de `100dvh` en `.cl-portada`,
   que es mas reciente.

   NO SE PONE NINGUNA @media: la proporcion es la misma a 320 px y a 1100, que es justamente lo
   que hace que el video no se deforme en ningun dispositivo. Lo unico que cambia con el ancho es
   el tamano, y de eso se encarga el `width` del contenedor. */
.cl-portada-video-16x9 {
  aspect-ratio: 16 / 9;
  /* Mientras YouTube carga -o si no cargara- el hueco es el vacio de la marca y no un blanco
     que parece un error de maquetacion. */
  background: var(--bg-void);
}
/* EL IFRAME LLENA LA CAJA, y las tres declaraciones hacen falta: sin `width`/`height` al 100 %
   se queda en su tamano por omision dentro de una caja que si tiene la proporcion correcta -o
   sea, el reproductor pequeno y centrado en un hueco grande-, y sin `border: 0` el navegador le
   dibuja el marco gris de los iframes por dentro de las esquinas redondeadas.
   `display: block` quita la linea base que dejaria una franja de 4 px bajo el video. */
.cl-portada-video-16x9 > iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
}

/* CUATRO COLUMNAS FIJAS, Y ANTES ERA `auto-fit` CON `minmax`: el cambio es a proposito y
   conviene saber que se pierde. `auto-fit` decidia el numero de columnas por el ancho
   disponible, sin una @media por salto, y con CUATRO tarjetas eso daba 4 / 2 / 1 casi solo.
   Con OCHO ya no: entre 860 y 1100 px `auto-fit` mete TRES columnas, y ocho tarjetas en tres
   columnas dejan la ultima fila con dos huecos -una cuadricula descuadrada justo en el ancho de
   un portatil-. Ocho pide 4+4 o 2+2+2+2, nunca 3+3+2, asi que el numero de columnas se declara
   y deja de ser una consecuencia del ancho.

   Con esto `--cl-portada-min` deja de usarse y se retira del corte de 400 px: era el minimo que
   `minmax` necesitaba, y sin `minmax` no significa nada. Una variable que ya no se lee es una
   trampa para quien la encuentre luego. */
.cl-portada-grid {
  display: grid;
  gap: 16px;
  /* 4 columnas => 2 filas de 4 con las ocho tarjetas. */
  grid-template-columns: repeat(4, minmax(0, 1fr));
}
.cl-portada-tarjeta { padding: 20px; }
.cl-portada-pie {
  margin-top: 8px;
  padding-top: 20px;
  border-top: 1px solid var(--line-2);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

/* ---- Tableta y movil ------------------------------------------------------------------
   MISMO UMBRAL QUE EL LOGIN (860 px), para que las dos pantallas publicas cambien de forma
   a la vez y no una antes que otra. Lo que se aprieta es el RELLENO, no el contenido: a 360
   px los 20 px por lado se comen 40 de los 360, y con el marco del video y el de la tarjeta
   encima el texto se queda en una columna de 260. */
@media (max-width: 860px) {
  .cl-portada-main { padding: 0 16px 40px; }
  .cl-portada-hero { padding: 40px 0 26px; }
  .cl-portada-bajada { font-size: 15px; }
  .cl-portada-video { margin-bottom: 32px; }
  /* DOS COLUMNAS EN TABLETA Y MOVIL ANCHO. Cuatro tarjetas a 860 px darian columnas de ~200 px
     y los titulos de dos palabras -«Analisis Juridico Integral»- se partirian en tres lineas. */
  .cl-portada-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* ---- Telefono estrecho (iPhone SE, Android de entrada) --------------------------------
   EL LIMITE SON 400 px Y NO UNO NUEVO, y esto lo caza una prueba: `base.css` solo puede usar
   los 860 de `CL_MOVIL_PX` -el limite de «esto es un telefono», escrito en shared.jsx y aqui,
   que tienen que coincidir- y los 400 que ya existian para pantallas muy angostas. Un tercer
   valor crearia una franja de anchos en la que el CSS y el JavaScript no opinan lo mismo sobre
   si es un telefono, que es el desajuste que dejo el #684 entre 768 y 860. Se escribio 480 y
   `test_el_simulador_responde_a_la_pantalla.js` lo rechazo, con razon.

   Lo que hace ademas del relleno: pone la cuadricula de modulos en UNA columna. Antes bajaba
   `--cl-portada-min` a 200 px, que era el minimo que `minmax` necesitaba para no forzar una
   columna mas ancha que el hueco; al declararse el numero de columnas esa variable dejo de
   leerse y se retiro, porque una variable que ya nadie lee es una trampa para quien la
   encuentre luego. */
@media (max-width: 400px) {
  .cl-portada-nav { padding: 9px 14px; gap: 10px; }
  .cl-portada-main { padding: 0 14px 34px; }
  .cl-portada-hero { padding: 30px 0 22px; }
  .cl-portada-bajada { font-size: 14.5px; margin-bottom: 22px; }
  .cl-portada-marco { padding: 5px; }
  .cl-portada-tarjeta { padding: 16px; }
  /* UNA SOLA COLUMNA EN TELEFONO ESTRECHO. A 320 px, con los 14 px de relleno por lado, dos
     columnas dejan 146 px por tarjeta: ahi no cabe ni el titulo ni el icono con su texto. */
  .cl-portada-grid { grid-template-columns: 1fr; gap: 12px; }
  /* El pie en una sola columna: a 320 px «Términos de Servicio» y «Política de Privacidad»
     no caben en la misma linea que el aviso de copyright, y `space-between` los separaba
     hasta partirlos por la mitad. Los dos enlaces tienen que quedar ENTEROS y visibles: son
     el requisito de la verificacion de Google. */
  .cl-portada-pie { flex-direction: column; align-items: flex-start; gap: 10px; }
}
