:root{
    --navy:#004090; --navy2:#0060B0; --navy-deep:#00336d; --cyan:#20B0F0; --cyan-deep:#0E8FD6;
    --ink:#0E1424; --gray:#5B6478; --gray-soft:#8A93A6; --line:#E4E7EE; --line-soft:#EEF1F6;
    --block:#F4F7FB; --bg:#FFFFFF;
    --amber:#B7791F; --amber-bg:#FBF3E2; --rust:#B4502E; --rust-bg:#FBEEE9; --good:#1E7F5C; --good-bg:#E7F4EE;
    --r:10px; --r-sm:7px;
    --shadow:0 1px 2px rgba(14,20,36,.04), 0 6px 18px rgba(14,20,36,.06);
    /* --tb calza con la altura real de .sb-head: 13+13 de padding + 32 de logo + 1 de borde */
    --sb:252px; --tb:58px;
  }
  *{box-sizing:border-box; margin:0; padding:0;}

  /* ---------- dónde está el cursor del teclado ----------
     Un solo anillo para todo lo que se puede enfocar. Antes había diecinueve
     reglas sueltas —casi todas en Correspondencia y Reuniones— y el resto de
     los controles no señalaban nada: quien navega con el teclado no sabía
     dónde estaba parado.

     :focus-visible y no :focus, que es la diferencia entre marcar cuando hace
     falta y marcar siempre: con :focus, cada clic del ratón deja el anillo
     pegado en el botón pulsado hasta que se pulse en otro sitio.

     Va arriba del todo y sin !important a propósito: es el suelo, no el
     techo. Cualquier regla posterior más específica —las que ya existen— lo
     sustituye sin pelear. */
  :focus-visible{
    outline:2px solid var(--navy2);
    outline-offset:2px;
    border-radius:4px;
  }
  /* El borde del velo y el de la tarjeta del modal se enfocan por programa
     (para atrapar el foco) y no son controles: marcarlos confunde. */
  .modalbg:focus-visible, .modalcard:focus-visible{outline:none;}

  html{overflow-y:scroll;} /* barra siempre presente: sin brincos de ancho al cambiar de tab */
  /* Red de seguridad contra el desbordamiento horizontal de la página entera:
     reportado por el usuario con capturas de móvil donde el contenido
     aparecía desplazado, con solo un borde de texto visible a la izquierda y
     el resto en blanco — un elemento más ancho que la pantalla empujaba el
     scroll horizontal de toda la página en vez de quedarse contenido en su
     propio recuadro (que es lo que .tscroll/.vscroll sí hacen para las
     tablas ya identificadas). Con esto, cualquier desborde que se escape se
     recorta en vez de mover la página entera. */
  /* hidden primero y clip después: los navegadores viejos se quedan con
     hidden y los que entienden clip usan clip, que es el que hace falta.
     `overflow-x:hidden` en el body lo convierte en un contenedor de
     desplazamiento, y eso descoloca los doce position:sticky de esta hoja
     —empezando por la barra superior—, porque un sticky se pega a su
     contenedor de desplazamiento más cercano y ése no rueda. `clip` recorta
     igual pero NO crea contenedor, así que los sticky siguen pegándose a la
     ventana. */
  html,body{overflow-x:hidden; overflow-x:clip;}
  html,body{font-family:'Helvetica Neue',Arial,sans-serif; color:var(--ink); background:var(--block); -webkit-font-smoothing:antialiased;}
  body{font-size:13px; line-height:1.45;}
  .tnum{font-variant-numeric:tabular-nums;}
  a{color:inherit; text-decoration:none;}
  svg{display:block;}

  /* ===================== SIDEBAR ===================== */
  .sidebar{position:fixed; top:0; left:0; bottom:0; width:var(--sb); z-index:30;
    /* var(--navy), no el hex suelto que tenía antes (#003a82, muy cerca del
       --navy por defecto pero fijo): con un color fijo en el primer alto de
       la franja, el interruptor de paleta del topbar cambiaba el resto de
       la pantalla pero la sidebar —lo más grande y lo primero que se ve—
       se quedaba a medias, todavía azul con cualquier paleta elegida. */
    background:linear-gradient(180deg,var(--navy) 0%, var(--navy-deep) 100%); color:#fff;
    display:flex; flex-direction:column; overflow:hidden;}
  /* El logo del CIIP se muestra completo (acrónimo + nomenclatura, sin
     recortar) y "Atlas" queda a su misma altura de caja, ambos centrados
     entre sí por el centro de caja. El sidebar se ensanchó (252→268px)
     para darle a esta pareja espacio real de sobra, en vez de depender del
     recorte: width/max-width fijos en .sb-head y overflow:hidden en ambos
     niveles quedan solo como cinturón de seguridad, no como solución.
     Importante: la altura real de esta cabecera (padding + el más alto de
     sus dos hijos + borde) tiene que calzar con --tb, la altura de .topbar
     (línea ~67) — son dos elementos independientes que se tocan en el
     mismo borde superior; si se desalinean, el contenido blanco "asoma"
     antes de que termine el azul del logo. Si vuelve a cambiar el tamaño
     del logo o de "Atlas", recalcular --tb a la par. */
  /* Logo institucional + "Atlas" en Instrument Serif (la tipografía de la
     marca del producto), a la izquierda y contenidos: 32px de logo, 24px de
     "Atlas" y un separador fino. --tb (59) calza la cuenta 13+32+13+1. */
  .sb-head{width:100%; max-width:100%; padding:13px 16px; border-bottom:1px solid rgba(255,255,255,.10); display:flex; align-items:center; justify-content:flex-start; gap:12px; overflow:hidden;}
  .sb-head img{height:32px; width:auto; display:block; flex-shrink:0;}
  .sb-head .pn{font-family:'Instrument Serif',Georgia,serif; font-size:30px; font-weight:400; letter-spacing:.01em; line-height:1; white-space:nowrap; flex-shrink:0;
    border-left:1px solid rgba(255,255,255,.25); padding-left:12px;}
  /* align-items:baseline (no center): el logo (imagen, 2 líneas — CIIP +
     subtítulo) y "Atlas" (texto, 1 línea) tienen alturas de caja distintas,
     así que centrarlos por caja completa no los deja "a la par" — la
     línea de base es el punto en común real entre una imagen y un texto.
     Reemplaza el ajuste a mano que había antes (translateY fijo, afinado
     para una combinación de tamaños que ya no cuadraba). */
  .sb-head{padding:16px 18px 14px; border-bottom:1px solid rgba(255,255,255,.10); display:flex; align-items:baseline; gap:11px;}
  .sb-head img{height:30px; width:auto;}
  .sb-head .pn{font-family:'Instrument Serif',Georgia,serif; font-size:34px; font-weight:400; letter-spacing:.01em; line-height:1;}
  /* Ya no hay una regla para "Atlas": el logo y la palabra son una sola imagen
     (assets/logo_ciip_atlas.png, generada por scripts/local/generar-logo-atlas.py).
     Como texto, el cuadre con el logo dependía del cuerpo de letra —que solo
     admite enteros— y siempre sobraba o faltaba un píxel abajo; encima obligaba
     a cargar una fuente externa solo para esto. En la imagen el ajuste es
     exacto por construcción y no depende de cómo la dibuje cada equipo. */
  .sb-nav{flex:1 1 auto; overflow-y:auto; padding:10px 10px 24px;}
  .sb-nav::-webkit-scrollbar{width:7px;} .sb-nav::-webkit-scrollbar-thumb{background:rgba(255,255,255,.16); border-radius:8px;}
  /* EL RÓTULO DE UN GRUPO. Iba a 9.5px contra los 12.5 de los módulos: tres
     puntos de diferencia es demasiada caída para dos textos que van uno encima
     del otro, y «Inversión» acababa leyéndose como letra chica al pie del
     bloque anterior en vez de como el encabezado del que viene debajo.
     Sube a 11px, que es el tamaño que Atlas le da a este mismo tipo de rótulo
     en el resto de la casa (.fk-k, .na-sec: 11px y peso de 700 a 800). Queda
     1.5px por debajo del módulo, que es la distancia justa: se lee sin
     esfuerzo y sigue siendo, claramente, el que manda sobre los de abajo.
     La jerarquía no la carga el cuerpo de letra sino el color —.55 contra el
     .80 de un módulo— y la sangría: los módulos entran con su icono, el rótulo
     no. Por eso puede crecer sin ponerse a competir con ellos. */
  .sb-sec-h{display:flex; align-items:center; width:100%; gap:8px; margin-top:14px; padding:7px 10px; background:transparent;
    border:none; color:rgba(255,255,255,.55); font-size:11px; font-weight:700; letter-spacing:.01em;
    cursor:pointer; border-radius:7px; font-family:inherit;}
  .sb-sec-h:first-child{margin-top:2px;}
  .sb-sec-h:hover{background:rgba(255,255,255,.06); color:rgba(255,255,255,.78);}
  .sb-sec-h .chev{width:11px; height:11px; margin-left:auto; flex:0 0 auto; transition:transform .18s ease;}
  .sb-sec-h .chev svg{width:100%; height:100%; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; stroke-linejoin:round; display:block;}
  .sb-sec-h[aria-expanded="true"] .chev{transform:rotate(180deg);}
  .sb-sec-body{overflow:hidden; max-height:0; transition:max-height .22s ease;}
  .sb-sec-body[data-open="1"]{max-height:600px;}
  @media (prefers-reduced-motion:reduce){ .sb-sec-body, .sb-sec-h .chev{transition:none;} }
  .sb-item{display:flex; align-items:center; gap:9px; padding:6.5px 10px; border-radius:7px; color:rgba(255,255,255,.80);
    font-size:12.5px; font-weight:500; cursor:pointer; position:relative;}
  .sb-item:hover{background:rgba(255,255,255,.08); color:#fff;}
  .sb-item .ic{width:15px; height:15px; flex:0 0 auto; opacity:.7;}
  .sb-item .ic svg{width:100%; height:100%; fill:none; stroke:currentColor; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; display:block;}
  .sb-item.active{background:rgba(32,176,240,.16); color:#fff; font-weight:700;}
  .sb-item.active::before{content:""; position:absolute; left:0; top:6px; bottom:6px; width:3px; background:var(--cyan); border-radius:0 3px 3px 0;}
  .sb-item.active .ic{opacity:1; color:var(--cyan);}
  .sb-item .cnt{margin-left:auto; font-size:9.5px; font-weight:700; color:rgba(255,255,255,.55); font-variant-numeric:tabular-nums;}
  .sb-item .cnt.cnt-zero{display:none;}
  .sb-item.soon{color:rgba(255,255,255,.45); cursor:default;}
  .sb-item.soon:hover{background:transparent; color:rgba(255,255,255,.45);}
  .sb-item.soon .ic{opacity:.4;}
  .sb-item .soon-tag{margin-left:auto; font-size:8px; font-weight:700; letter-spacing:.06em; text-transform:capitalize; color:rgba(255,255,255,.4); border:1px solid rgba(255,255,255,.18); border-radius:20px; padding:1px 6px;}

  /* ===================== TOPBAR ===================== */
  .main{margin-left:var(--sb); transition:margin-left .22s ease;}

  /* ---------- la pantalla de una institución ----------
     Quien entra representando a un ente no trabaja en el CIIP: el menú lateral
     no le sirve —son módulos a los que no tiene acceso— y verlo ahí, aunque
     esté deshabilitado, sugiere que hay algo detrás. Se retira entero, y el
     contenido ocupa el ancho completo.
     El botón de hamburguesa del encabezado también sobra: no hay menú que
     abrir. */
  body.modo-ente .sidebar,
  body.modo-ente .nav-btn,
  body.modo-ente .nav-backdrop{display:none;}
  body.modo-ente .main{margin-left:0;}
  .sidebar{transition:transform .22s ease;}
  @media (min-width:861px){
    body.sb-collapsed .sidebar{transform:translateX(-100%);}
    body.sb-collapsed .main{margin-left:0;}
  }
  @media (prefers-reduced-motion:reduce){ .main, .sidebar{transition:none;} }
  .topbar{position:sticky; top:0; z-index:20; height:var(--tb); background:var(--navy);
    display:flex; align-items:center; gap:14px; padding:0 20px; color:#fff;
    box-shadow:0 1px 0 rgba(0,0,0,.08);}
  .tb-spacer{flex:1 1 auto;}
  .user{position:relative; display:flex; align-items:center; gap:10px; padding:5px 8px 5px 6px; border-radius:9px; cursor:pointer; user-select:none;}
  .user:hover{background:rgba(255,255,255,.10);}
  .avatar{width:38px; height:38px; flex:0 0 38px; border-radius:50%; background:linear-gradient(135deg,var(--cyan),var(--navy2)); display:flex; align-items:center; justify-content:center; font-size:13px; font-weight:800; color:#fff; box-shadow:0 0 0 2px rgba(255,255,255,.14);}
  .avatar.sm{width:34px; height:34px; flex:0 0 34px; font-size:12px; box-shadow:none;}
  .user .u-meta{line-height:1.2;}
  /* La campana y el selector de paleta ocupan ~60px más en una barra que
     ya iba justa: el nombre pasa a recortarse con puntos suspensivos. Sin
     esto, un nombre largo se parte en dos líneas dentro de una barra de
     alto fijo y lo que sobra se sale por debajo. */
  .user .u-name{font-size:13px; font-weight:700; color:#fff;
    max-width:38vw; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  .user .u-chev{font-size:11px; color:rgba(255,255,255,.7); transition:transform .16s ease;}
  .user.open .u-chev{transform:rotate(180deg);}
  .usermenu{position:absolute; top:calc(100% + 9px); right:0; width:250px; background:#fff; color:var(--ink);
    border:1px solid var(--line); border-radius:11px; box-shadow:0 8px 30px rgba(14,20,36,.16); padding:6px;
    opacity:0; visibility:hidden; transform:translateY(-6px); transition:opacity .15s ease, transform .15s ease; z-index:60; cursor:default;}
  .user.open .usermenu{opacity:1; visibility:visible; transform:translateY(0);}
  .um-head{display:flex; align-items:center; gap:10px; padding:9px 10px 10px;}
  .um-name{font-size:12.5px; font-weight:700; color:var(--ink);}
  .um-mail{font-size:10.5px; color:var(--gray); margin-top:1px;}
  .um-sep{height:1px; background:var(--line-soft); margin:5px 4px;}
  .um-item{display:flex; align-items:center; gap:10px; padding:8px 10px; border-radius:7px; font-size:12.5px; font-weight:600; color:#2A3346; cursor:pointer;}
  .um-item:hover{background:var(--block);}
  .um-item svg{width:15px; height:15px; flex:0 0 auto; fill:none; stroke:var(--gray); stroke-width:2; stroke-linecap:round; stroke-linejoin:round;}
  .um-item.danger{color:var(--rust);}
  .um-item.danger:hover{background:var(--rust-bg);}
  .um-item.danger svg{stroke:var(--rust);}

  /* ---------- el buzón interno: la campana de la barra ----------
     Mismo desplegable que .usermenu, que tiene justo al lado: blanco, filete,
     sombra y esquinas de 11px. Lo que cambia es el ancho —un aviso es una
     frase, no un renglón de menú— y que la lista se desplaza dentro del panel
     en vez de estirarlo hasta salirse de la pantalla. */
  .notis{position:relative; flex:0 0 auto;}

  /* ===================== CONTENT GRID ===================== */
  .content{padding:20px 22px 40px;}
  .grid{display:grid; grid-template-columns:repeat(12,1fr); gap:16px; align-content:start;}
  .col12{grid-column:span 12;} .col8{grid-column:span 8;} .col7{grid-column:span 7;}
  .col6{grid-column:span 6;} .col5{grid-column:span 5;} .col4{grid-column:span 4;}
  .card{background:var(--bg); border:1px solid var(--line); border-radius:var(--r); padding:16px 18px;}
  .card.flush{padding:0; overflow:hidden;}
  /* marco activo de un panel de gráfico con un filtro en el sitio puesto
     (ver crPanel, 4° parámetro "limpiar") — reemplaza el borde gris sutil
     de .card por uno dorado prominente mientras haya algo seleccionado en
     ESE panel; vuelve al borde normal en cuanto se limpia. */
  .card.cr-panel-on{border:2px solid #B87315;}
  .sec-h{display:flex; align-items:center; gap:10px; margin-bottom:13px; flex-wrap:wrap;}
  .sec-h .t{font-size:14px; font-weight:700; color:var(--ink); letter-spacing:-.01em;}
  .sec-h .sub{font-size:12px; color:var(--gray); font-weight:500;}
  .sec-h .spacer{flex:1 1 auto;}
  .sec-h .link{font-size:11px; font-weight:600; color:var(--navy2); cursor:pointer;}
  .tick{width:7px; height:7px; background:var(--cyan); border-radius:2px; flex:0 0 auto;}

  /* ---- títulos de sección con regla (contratos suscritos) · opción C de maqueta-titulos-seccion.html ----
     El título ocupa lo suyo y una línea que se desvanece llena el resto del ancho: separa las secciones sin
     dibujar un borde duro y da sensación de anchura, que es lo que pide un panel donde cada bloque ocupa la
     caja entera.
     Acotado a los dos contenedores del módulo y no a .sec-h, que lo comparten 33 secciones de Atlas y
     ninguna otra pidió cambiar. No hace falta tocar el marcado: la regla es un ::after.
     Se queda en el cian de marca en vez de un color por sección — el módulo ya usa el color para decir
     sector y estado, y un tercer sistema competiría con esos dos.
     nowrap con el título a min-width:0: si la fila pudiera partirse, la regla caería sola a una segunda
     línea y quedaría una raya suelta bajo el título. Así el texto se parte por dentro si hace falta y la
     regla nunca se despega; el 24px de base es lo que puede encogerse antes de desaparecer.

     El azul es --cyan-deep (#0E8FD6) y no el --cyan (#20B0F0) del cuadrito genérico: es el mismo que
     usan los medidores de las tarjetas de este panel y las barras de monto de sus bloques, así que la
     regla queda del color de los gráficos que encabeza en vez de un tono más pálido que ninguna otra
     cosa de la pantalla usa. El cuadrito se iguala con ella por lo mismo — si no, el mismo título
     llevaría dos azules distintos a diez píxeles de distancia. */
  #proyhead .sec-h, #proystats .sec-h{gap:12px; flex-wrap:nowrap;}
  #proyhead .sec-h .t, #proystats .sec-h .t{font-size:14.5px; font-weight:800; min-width:0;}
  #proyhead .sec-h .tick, #proystats .sec-h .tick{background:var(--cyan-deep);}
  #proyhead .sec-h::after, #proystats .sec-h::after{content:''; flex:1 1 24px; min-width:24px; height:1px;
    background:linear-gradient(90deg, var(--cyan-deep), transparent);}

  /* ---- page header ---- */
  .page-h{display:flex; align-items:flex-start; gap:18px; flex-wrap:wrap;}
  .page-h h1{font-size:22px; font-weight:700; letter-spacing:-.02em;}
  .page-h .p-sub{font-size:12px; color:var(--gray); margin-top:4px; max-width:760px; line-height:1.5;}
  .page-h .p-actions{margin-left:auto; display:flex; align-items:center; gap:9px; flex:0 0 auto;}

  /* ---- summary stat row ----
     --cols (opcional, vía crKpiRow): número de columnas, por defecto 4 —
     compartida por toda la app, así que el resto de los usos (sin la
     variable puesta) se quedan igual que siempre. */
  .stat-row{display:grid; grid-template-columns:repeat(var(--cols,4),1fr); gap:14px;}
  .stat{background:var(--bg); border:1px solid var(--line); border-radius:10px; padding:14px 16px;}
  .stat .sn{font-size:24px; font-weight:800; letter-spacing:-.02em;}
  .stat .sn.accent{color:var(--cyan-deep);}
  .stat .sl{font-size:11px; color:var(--gray); margin-top:3px; line-height:1.35;}
  /* Denominador de un KPI de proporción ("57 de 63"): entra en la misma línea pero
     con peso y tamaño de texto secundario, para que el ojo caiga en la cifra y no
     en el "de 63". Lo pinta chartKpiRow cuando el KPI trae pct. */
  .stat .sn .sd{font-size:12px; font-weight:600; color:var(--gray-soft); margin-left:6px; letter-spacing:0;}
  /* Medidor de la proporción. 3px y en el color de acento: acompaña a la cifra,
     no compite con los gráficos de abajo. La pista se ve completa aunque el
     valor sea 0, que es justo el caso que hay que poder distinguir de "sin dato". */
  .stat .smeter{height:3px; border-radius:3px; background:var(--line); margin-top:9px; overflow:hidden;}
  .stat .smeter span{display:block; height:100%; border-radius:3px; background:var(--cyan-deep);}
  /* KPI clicable (Correspondencia · Próximas acciones): mismo par de colores
     que .enteli.on (selección real, ya viva en Todos los activos → Ente),
     no .fchip.on/.segbtn.on (pensados para píldoras/segmentos con fondo
     sólido, no para tarjetas). .on va después de :hover a propósito: misma
     especificidad, y así un tile ya seleccionado no parpadea al pasar el mouse. */
  .stat.clic{cursor:pointer;}
  .stat.clic:hover{border-color:#CDD5E1;}
  .stat.clic.on{background:#EEF5FC; border-color:#CFE0F0;}

  /* ---- stage funnel ---- */
  .funnel{display:flex; align-items:stretch; gap:0;}
  .fst{flex:1 1 0; border:1px solid var(--line); border-radius:8px; padding:11px 12px; background:var(--bg); min-width:0; cursor:pointer;}
  .fst:hover{border-color:#CDD5E1;}
  .fst.inv{background:#F2FAFE; border-color:#CDEBFA;}
  .fst .fc{font-size:9px; font-weight:800; color:var(--navy2); letter-spacing:.04em;}
  .fst.inv .fc{color:var(--cyan-deep);}
  .fst .fnm{font-size:10.5px; font-weight:600; color:var(--ink); margin-top:3px; line-height:1.25;}
  .fst .fn{font-size:20px; font-weight:800; margin-top:6px; letter-spacing:-.02em;}
  .fst .fcv{font-size:9.5px; color:var(--gray-soft); margin-top:1px;}
  .arr{flex:0 0 22px; display:flex; align-items:center; justify-content:center; color:#C2CAD7; font-size:15px; font-weight:800;}

  /* ---- filter bar ---- */
  .filters{display:flex; align-items:center; gap:8px; flex-wrap:wrap;}
  .fsearch{display:flex; align-items:center; gap:8px; background:var(--block); border:1px solid var(--line); border-radius:8px; padding:8px 12px; flex:1 1 240px; min-width:200px; color:var(--gray-soft);}
  .fsearch input{border:none; background:transparent; outline:none; font-family:inherit; font-size:12.5px; color:var(--ink); width:100%;}
  .fchip{font-size:11px; font-weight:600; color:var(--gray); background:var(--bg); border:1px solid var(--line); border-radius:20px; padding:6px 12px; cursor:pointer; white-space:nowrap;}
  .fchip:hover{border-color:#CDD5E1;}
  .fchip.on{background:var(--navy); color:#fff; border-color:var(--navy);}
  /* El recuento dentro de una pastilla. Existía solo para las pestañas
     (.tabitem .tcount); al pasar las etapas a pastillas, el número quedaba
     pegado al texto — "En estructuración22". Mismo tratamiento de píldora que
     en las pestañas, con su separación, y en la pastilla activa se aclara
     sobre el fondo azul en vez de perderse. */
  .fchip .tcount{margin-left:7px; font-size:10px; font-weight:700; color:var(--gray-soft);
    background:var(--block); border:1px solid var(--line-soft); border-radius:20px; padding:0 6px;}
  .fchip.on .tcount{color:#fff; background:rgba(255,255,255,.20); border-color:transparent;}
  .fdiv{width:1px; height:20px; background:var(--line); margin:0 2px;}
  /* El resumen (recuento) vive en su propia línea siempre: si comparte línea con los
     chips, su ancho variable según el filtro activo empuja a los chips a otro renglón
     y toda la barra "salta" al hacer clic. */
  #catcount, #opohead{flex:1 1 100%; order:99; text-align:right; margin-top:2px;}

  /* ---- tab bar ---- */
  /* Una sola fila, siempre. Con flex-wrap la última pestaña se caía sola a un
     segundo renglón —"Documentos" bajo las demás— y dejaba de leerse como parte
     del mismo grupo. Si no caben, la barra rueda en horizontal en vez de
     partirse; y se aprieta un poco el relleno para que casi nunca haga falta. */
  .tabbar{display:flex; gap:2px; border-bottom:1px solid var(--line);
    flex-wrap:nowrap; overflow-x:auto; overflow-y:hidden;}
  .tabitem{display:flex; align-items:center; gap:6px; padding:9px 11px; font-size:12.5px; font-weight:600; color:var(--gray); cursor:pointer; border-bottom:2px solid transparent; margin-bottom:-1px; white-space:nowrap; flex:0 0 auto;}
  .tabitem:hover{color:var(--ink);}
  .tabitem.on{color:var(--navy); font-weight:700; border-bottom-color:var(--cyan);}
  .tabitem .tcount{font-size:10px; font-weight:700; color:var(--gray-soft); background:var(--block); border:1px solid var(--line-soft); border-radius:20px; padding:0 6px;}
  .tabitem.on .tcount{color:var(--cyan-deep); background:#E8F6FE; border-color:#CDEBFA;}

  /* ---- variante de módulo: el primer nivel de pestañas ----
     La barra que navega un módulo entero y la que divide lo que se ve dentro
     de una de sus pestañas eran la misma cosa dibujada dos veces, una encima
     de otra. Abajo se resolvió con píldoras; aquí, dándole a la de arriba lo
     que la de abajo no tiene: una SUPERFICIE. Fondo propio de borde a borde,
     filete al pie y las esquinas de arriba redondeadas, como si el contenido
     colgara de ella. Así no compiten ni de reojo — una es la banda, la otra
     son objetos sueltos sobre una tira.
     Modificador y no cambio de .tabbar: esa clase la comparten nueve
     pantallas y en cuatro vive dentro de una ficha, donde el subrayado
     discreto es justo lo que corresponde. */
  .tabbar.modulo{background:var(--bg); border-bottom:1px solid var(--line);
                 border-radius:10px 10px 0 0; padding:0 10px; gap:4px;}
  .tabbar.modulo .tabitem{font-size:13.5px; padding:12px 14px;}
  /* Subrayado de 3px y no de 2: sobre una banda blanca el de 2 se perdía
     contra el filete del pie. */
  .tabbar.modulo .tabitem.on{color:var(--navy); border-bottom-width:3px;}

  /* ---- la banda de los dos segundos niveles del módulo ----
     La usan el Directorio (sus tres grupos) y el Panorama (sus dos): es el
     mismo nivel —un grupo dentro de la pestaña— y no había razón para que se
     vieran distintos.

     Superficie blanca a lo ancho de la rejilla. Estuvo un tiempo suelta sobre
     el gris de la página, separada solo con aire, y las píldoras quedaban
     flotando sin nada que dijera hasta dónde mandan. Con fondo propio se lee
     como lo que es —una banda que gobierna lo de abajo— y hace juego con las
     demás superficies del módulo.

     En píldoras y a la izquierda. En píldoras porque la barra del módulo,
     justo encima, es la subrayada: dos filas con la misma forma competían por
     la misma lectura, y cambiar de recurso —no de alineación— es lo que las
     separa de verdad.

     Y más baja que la del módulo, pero solo un poco: 43px contra 47. Ese margen
     de cuatro es todo lo que hace falta —el primer nivel manda y se nota— sin
     que la banda quede como un filete. Se llegó por los dos extremos: con 10px
     de relleno subía a 60 y pesaba más que el módulo; con 3px bajaba a 39 y se
     veía anémica. */
  /* La banda blanca de los grupos de Correspondencia. La comparte la
     pantalla de Avisos (.av-tabs-sec): mismo papel —recortes de una misma
     lista— y por eso se AÑADE el selector en vez de copiar las reglas, que
     es como acaban dos bandas pareciéndose menos cada mes. */
  .cr-grupos-sec, .av-tabs-sec{display:flex; flex-direction:column; align-items:flex-start;
                 background:var(--bg); border:1px solid var(--line); border-radius:var(--r);
                 padding:5px 10px; margin-bottom:4px;}
  /* .cr-grupos.pastillas y no .cr-grupos a secas: la regla base de la variante
     en píldoras vive más abajo en esta misma hoja y, a igual especificidad,
     ganaba ella — el relleno se quedaba en 7px y la banda no bajaba de 45. */
  .tabbar.pastillas.cr-grupos, .tabbar.pastillas.av-tabs{width:max-content; max-width:100%; padding:2px;}
  .tabbar.pastillas.cr-grupos .tabitem, .tabbar.pastillas.av-tabs .tabitem{font-size:12px; padding:5px 12px;}
  /* El aviso de "viendo solo estas" comparte la banda, así que se separa de
     las píldoras con su propia línea. */
  .cr-grupos-sec .cr-remfiltro{width:100%; border-top:1px solid var(--line-soft);
                               margin-top:8px; padding-top:9px;}
  .cr-remfiltro{display:flex; align-items:center; gap:10px; flex-wrap:wrap; margin-top:10px;}

  /* ---- el listado: buscador arriba, filtros debajo ----
     Las dos filas nacieron pegadas: .filters no traía margen inferior y la
     barra de desplegables (.sg-toolbar) arranca justo debajo, así que el
     buscador y los cuatro campos se leían como un solo bloque de controles.
     Son dos preguntas distintas —qué busco, y sobre qué recorto— y necesitan
     el aire que las separa. Catorce píxeles, los mismos que .sg-toolbar deja
     por debajo, para que la barra de filtros respire igual por arriba que por
     abajo. */
  .cr-listado .filters{margin-bottom:14px;}

  /* La columna derecha de la fila de correspondencia: la fecha cuando se
     listan documentos, los días esperando cuando es la bandeja de Próximas
     acciones. Vivía sin regla propia —heredaba el tamaño del cuerpo y se
     leía tan fuerte como el asunto—; es un dato de apoyo y se comporta como
     el responsable de una tarea en .sg-resp: ancho fijo, alineado a la
     derecha, sin partirse en dos renglones. */
  .cr-fila-fecha{flex:0 0 auto; min-width:82px; text-align:right; font-size:11.5px;
                 color:var(--gray); white-space:nowrap; padding-top:2px;}

  /* Aquí vivía .cr-subnav-aire, el intento de separar el segundo nivel solo
     con espacio y escala. Se retiró: lo que de verdad lo separa del primero es
     la FORMA —arriba subrayada, abajo píldoras— y con eso la distancia deja de
     tener que hacer ese trabajo. Los dos niveles del módulo comparten hoy la
     misma banda blanca (.cr-grupos-sec). */
  /* ---- variante en píldoras: el segundo nivel de pestañas ----
     La usa hoy el Panorama de Correspondencia, cuyas sub-pestañas caen justo
     debajo de la barra del módulo: dos filas subrayadas idénticas, una encima
     de otra, no dejaban ver cuál manda sobre cuál. En píldoras el segundo
     nivel se lee como parte del primero sin competir con él.
     Nació para contratos suscritos, y de ahí el resto de este comentario. ----
     Modificador y no cambio de .tabbar: esa clase la comparten siete vistas y la ficha del
     contrato, y ninguna pidió cambiar de aspecto.
     Sin subrayado: cada sector es una píldora sobre una tira gris y la activa se levanta en
     blanco. Cuando la fila se parte, no deja un subrayado huérfano bajo la primera línea.
     Allí iba sin conteo, porque la cifra de cada sector ya la daba el panel de abajo. En
     Correspondencia sí lo lleva: es el único sitio donde se dice cuántas cartas hay de cada
     grupo, y son dos píldoras, así que la fila no corre riesgo de partirse. */
  .tabbar.pastillas{border-bottom:0; gap:5px; padding:3px; background:var(--block); border-radius:10px;}
  .tabbar.pastillas .tabitem{border-bottom:0; margin-bottom:0; padding:7px 11px; border-radius:7px; gap:6px;}
  .tabbar.pastillas .tabitem:hover{background:#E9EEF6; color:var(--ink);}
  .tabbar.pastillas .tabitem.on{background:var(--bg); font-weight:700;
                                box-shadow:0 1px 3px rgba(14,20,36,.10);}
  /* El cuadrito de color es el mismo que el sector lleva en "Por sector", en el árbol de mayores
     compromisos y en las listas: ata la pestaña a sus barras. A media opacidad en las inactivas
     para que la fila no se lea como un semáforo de siete luces. */
  .tabbar.pastillas .tpt{width:8px; height:8px; border-radius:2px; flex:0 0 auto;
                         opacity:.5; transition:opacity .12s ease;}
  .tabbar.pastillas .tabitem:hover .tpt, .tabbar.pastillas .tabitem.on .tpt{opacity:1;}
  @media (prefers-reduced-motion:reduce){ .tabbar.pastillas .tpt{transition:none;} }

  /* ---- master-detail (por ente) ---- */
  .md{display:flex; gap:20px; align-items:flex-start;}
  .md-rail{width:252px; flex:0 0 252px;}
  .md-list{display:flex; flex-direction:column; gap:3px; margin-top:10px; padding-right:2px;}
  .md-list::-webkit-scrollbar{width:7px;} .md-list::-webkit-scrollbar-thumb{background:var(--line); border-radius:8px;}
  .enteli{display:flex; align-items:center; gap:9px; padding:8px 9px; border-radius:8px; cursor:pointer; border:1px solid transparent;}
  .enteli:hover{background:var(--block);}
  .enteli.on{background:#EEF5FC; border-color:#CFE0F0;}
  .enteli .el-mono{width:30px; height:30px; border-radius:7px; background:var(--navy); color:#fff; display:flex; align-items:center; justify-content:center; font-size:9px; font-weight:800; flex:0 0 auto; letter-spacing:0;}
  .enteli .el-name{font-size:11.5px; font-weight:700; line-height:1.2;}
  .enteli .el-sub{font-size:9.5px; color:var(--gray-soft); margin-top:1px;}
  .enteli .el-badge{margin-left:auto; display:flex; align-items:center; gap:6px; flex:0 0 auto;}
  .enteli .el-cnt{font-size:11px; font-weight:800; color:var(--gray); font-variant-numeric:tabular-nums;}
  .enteli.on .el-cnt{color:var(--navy);}
  .enteli .el-dot{width:7px; height:7px; border-radius:50%; background:var(--amber);}
  .md-main{flex:1 1 auto; min-width:0;}
  .ente-head{display:flex; gap:11px; align-items:flex-start; padding-bottom:13px; border-bottom:1px solid var(--line-soft);}
  .ente-metastrip{display:flex; align-items:center; gap:8px; flex-wrap:wrap; margin-top:12px;}
  .seg{display:flex; background:var(--block); border:1px solid var(--line); border-radius:8px; padding:3px; gap:3px;}
  .segbtn{flex:1 1 0; text-align:center; font-size:11px; font-weight:700; color:var(--gray); padding:6px 8px; border-radius:6px; cursor:pointer;}
  .segbtn:hover{color:var(--ink);}
  .segbtn.on{background:#fff; color:var(--navy); box-shadow:0 1px 2px rgba(14,20,36,.08);}
  .hseg .segbtn{flex:0 0 auto; padding:6px 12px; white-space:nowrap;}
  /* Un desplegable con la misma piel que .seg. Se usa donde hay que elegir de
     una lista larga y con nombres largos —los proyectos de una contraparte—,
     que en botones uno al lado del otro no cabrían. Misma caja, mismo tipo de
     letra y mismo peso que .segbtn, para que lea como parte de la familia. */
  .segsel{position:relative; display:inline-flex; align-items:center; background:var(--block);
    border:1px solid var(--line); border-radius:8px; padding:3px; max-width:280px;}
  .segsel::after{content:'▾'; position:absolute; right:11px; font-size:10px; color:var(--gray); pointer-events:none;}
  .segsel select{appearance:none; -webkit-appearance:none; border:0; background:transparent; cursor:pointer;
    font-family:inherit; font-size:11px; font-weight:700; color:var(--gray); padding:6px 26px 6px 10px;
    border-radius:6px; max-width:100%; text-overflow:ellipsis;}
  .segsel select:hover{color:var(--ink);}
  .segsel.on{background:#fff; box-shadow:0 1px 2px rgba(14,20,36,.08);}
  .segsel.on select{color:var(--navy);}
  /* Buscar dentro de la pestaña de Documentos de una ficha. Mismo alto y misma
     caja que los .segsel que lleva al lado, para que la fila de controles se
     lea como una sola —no como un buscador pegado a dos desplegables—. */
  /* "Ir al módulo →" al final de cada módulo del manual, dentro de la Guía.
     Se lee cómo se hace algo y se entra a hacerlo de un clic. */
  .gm-ir{display:inline-block; margin-top:14px; font-size:12.5px; font-weight:700; color:var(--navy);
    background:var(--block); border:1px solid var(--line); border-radius:8px; padding:8px 14px; cursor:pointer;}
  .gm-ir:hover{background:#fff; border-color:var(--navy); box-shadow:0 1px 2px rgba(14,20,36,.08);}
  .inv-docq{width:150px; min-width:0; flex:0 1 150px; background:var(--block); border:1px solid var(--line); border-radius:8px;
    font-family:inherit; font-size:11px; font-weight:600; color:var(--ink); padding:8px 10px;}
  /* Calcado del .segsel de al lado, para que el buscador y los desplegables se
     lean como una sola fila de controles y no como tres cajas distintas. Las
     medidas no son a ojo: .segsel es un marco con padding:3px que envuelve un
     select con padding:6px 26px 6px 10px, así que el alto sale de 3+6 arriba y
     abajo, y el texto empieza a 3+10 de la izquierda. De ahí 9px 13px, el mismo
     font-size:11px y el mismo peso 700. El ancho iguala su max-width:280px.
     El foco sí se distingue —fondo blanco y borde navy—: en un campo donde se
     escribe hace falta saber si el cursor está dentro, que en un select no. */
  .inv-docq{width:280px; max-width:280px; min-width:120px; flex:0 1 auto;
    background:var(--block); border:1px solid var(--line); border-radius:8px;
    font-family:inherit; font-size:11px; font-weight:700; color:var(--ink); padding:9px 13px;}
  .inv-docq::placeholder{color:var(--gray); font-weight:700;}
  .inv-docq:focus{outline:none; background:#fff; border-color:var(--navy); box-shadow:0 1px 2px rgba(14,20,36,.08);}
  /* El selector de categoría que va EN CADA FILA de documento: más chico que
     el de la barra, y sin robarle sitio al nombre del archivo. */
  /* Lista para vincular representantes que ya existen: casilla, nombre (con
     las empresas donde ya está, para no confundir a dos que se llaman igual) y
     su cargo en ESTA empresa. Alta acotada y con desplazamiento: son ~160
     personas y la ventana no puede crecer sin fin. */
  .cpap-lista{max-height:260px; overflow-y:auto; border:1px solid var(--line); border-radius:8px; padding:4px;}
  .cpap-row{display:flex; align-items:center; gap:10px; padding:7px 9px; border-radius:6px; cursor:pointer;}
  .cpap-row:hover{background:var(--block);}
  .cpap-row + .cpap-row{border-top:1px solid var(--line-soft);}
  .cpap-txt{display:flex; flex-direction:column; min-width:0; flex:1 1 auto;}
  .cpap-n{font-size:12.5px; font-weight:600; color:var(--ink); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  .cpap-e{font-size:11px; color:var(--gray-soft); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  .cpap-cargo{flex:0 0 130px; font-family:inherit; font-size:11px; padding:5px 8px;
    border:1px solid var(--line); border-radius:6px; background:#fff; color:var(--ink);}
  .doc-cat{flex:none; max-width:190px; margin-left:10px;}
  .doc-cat select{font-size:10.5px; padding:5px 24px 5px 9px;}
  @media (max-width:720px){ .doc-cat{max-width:140px;} }
  .chip.navy{background:var(--navy); color:#fff;}
  /* ---- compact page header ---- */
  .page-h2{display:flex; align-items:baseline; gap:12px; flex-wrap:wrap; padding:2px;}
  .page-h2 .p-actions{margin-left:auto; align-self:center; display:flex; align-items:center; gap:10px; flex-wrap:wrap;}
  .ph-title{font-size:16px; font-weight:700; letter-spacing:-.01em;}
  .ph-sub{font-size:11.5px; color:var(--gray); font-weight:500;}
  @media (max-width:900px){
    .md{flex-direction:column;}
    .md-rail{width:100%; flex:1 1 auto;}
    .md-list{flex-direction:row; overflow-x:auto; max-height:none; gap:7px; padding-bottom:6px;}
    .enteli{flex:0 0 auto; min-width:150px;}
  }

  /* ---- project cards ---- */
  .pgrid{display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:14px;}
  /* Las mismas tarjetas dentro de una ficha (los entes adscritos de un
     ministerio): la columna central es más estrecha que la página, y tres
     columnas fijas ahí dejan las tarjetas ilegibles. Se reparten por ancho
     disponible en vez de por número. */
  .pgrid.encaja{grid-template-columns:repeat(auto-fill,minmax(230px,1fr));}
  .pcard{border:1px solid var(--line); border-radius:11px; padding:15px 16px; background:var(--bg); display:flex; flex-direction:column; cursor:pointer; transition:border-color .12s ease, box-shadow .12s ease;}
  .pcard:hover{border-color:#CDD5E1; box-shadow:var(--shadow);}
  .pc-top{display:flex; align-items:center; gap:6px 8px; margin-bottom:9px; flex-wrap:wrap;}
  .pc-stage{font-size:9.5px; font-weight:800; letter-spacing:.03em; border-radius:20px; padding:2px 9px; white-space:nowrap;}
  .pc-stage.a{background:#EEF0F3; color:var(--gray);}
  .pc-stage.b{background:var(--amber-bg); color:var(--amber);}
  .pc-stage.c{background:#E9EFF7; color:var(--navy2);}
  .pc-stage.inv{background:#E8F6FE; color:var(--cyan-deep);}
  .pc-sector{font-size:10px; font-weight:600; color:var(--gray); background:var(--block); border:1px solid var(--line-soft); border-radius:20px; padding:2px 9px; white-space:nowrap; max-width:100%; overflow:hidden; text-overflow:ellipsis;}
  .pc-star{color:var(--amber); font-size:12px;}
  .pc-code{font-family:ui-monospace,'SF Mono',Consolas,monospace; font-size:9.5px; font-weight:600; color:var(--gray-soft); letter-spacing:.01em;}
  .pc-name{font-size:14px; font-weight:700; letter-spacing:-.01em; line-height:1.25;}
  .pc-loc{font-size:10.5px; color:var(--gray-soft); margin-top:3px;}
  .pc-desc{font-size:11.5px; color:#39414F; margin-top:9px; line-height:1.5; flex:1 1 auto;}
  .pc-foot{display:flex; align-items:center; gap:10px; margin-top:13px; padding-top:11px; border-top:1px solid var(--line-soft);}
  .pc-amt{font-size:14px; font-weight:800; letter-spacing:-.01em;}
  .pc-amt small{font-size:9.5px; font-weight:600; color:var(--gray-soft); display:block; letter-spacing:0;}
  .pc-amt.open{font-size:12px; font-weight:700; color:var(--gray);}
  .pc-fig{font-size:10px; font-weight:700; color:var(--gray); background:var(--bg); border:1px solid var(--line); border-radius:20px; padding:2px 9px; margin-left:6px; white-space:nowrap;}
  .fchip.fig{font-size:10.5px; padding:4px 10px;}
  /* ---- etapas del motor de demanda (contrapartes) ---- */
  .pc-stage.contacto{background:#EEF0F3; color:var(--gray);}
  .pc-stage.match{background:#E8F6FE; color:var(--cyan-deep);}
  .pc-stage.nda{background:var(--amber-bg); color:var(--amber);}
  .pc-stage.kyc{background:#E9EFF7; color:var(--navy2);}
  .pc-stage.negociacion{background:var(--navy); color:#fff;}
  .f-lbl{font-size:10px; font-weight:700; letter-spacing:.01em; color:var(--gray-soft); margin-right:2px;}
  .pc-data{margin-left:auto; display:flex; flex-direction:column; align-items:flex-end; gap:4px;}
  .pc-data .pd-l{font-size:9px; font-weight:700; letter-spacing:.01em; color:var(--gray-soft);}
  .pc-bar{width:78px; height:5px; border-radius:5px; background:var(--line); overflow:hidden;}
  .pc-bar i{display:block; height:100%; border-radius:5px; background:linear-gradient(90deg,var(--navy2),var(--cyan));}
  .empty{padding:34px; text-align:center; color:var(--gray-soft); font-size:12px; border:1px dashed var(--line); border-radius:10px;}

  /* ---- grouped sections ---- */
  .grp{margin-bottom:16px;}
  .grp:last-child{margin-bottom:0;}
  .grp-h{display:flex; align-items:center; gap:11px; margin-bottom:11px;}
  .grp-h .g-name{font-size:14px; font-weight:700;}
  .grp-h .g-meta{font-size:11px; color:var(--gray);}
  .grp-h .g-count{background:var(--navy); color:#fff; font-size:11px; font-weight:800; border-radius:20px; min-width:21px; height:21px; padding:0 7px; display:flex; align-items:center; justify-content:center;}
  .grp-h .spacer{flex:1 1 auto;}

  /* ---- kanban ---- */
  /* Se había borrado por "ya no la usa nadie" (ver historial): vuelve a
     hacer falta porque la reversión de Contratos suscritos a su versión
     original (js/views/proyectos.js) envuelve el kanban en .klane otra vez.
     Mismo min-width:0 defensivo de siempre, contra el desborde de grid. */
  .klane{min-width:0;}
  .kanban{display:grid; grid-template-columns:repeat(4,1fr); gap:14px;}
  .kcol{background:var(--block); border:1px solid var(--line); border-radius:10px; padding:11px; min-width:0;}
  .khead{display:flex; align-items:center; gap:9px; padding:2px 4px 11px;}
  .kdot{width:9px; height:9px; border-radius:50%; flex:0 0 auto;}
  .kdot.a{background:var(--gray-soft);} .kdot.b{background:var(--amber);} .kdot.c{background:var(--navy2);} .kdot.inv{background:var(--cyan);}
  .kdot.late{background:var(--rust);} .kdot.warn{background:var(--amber);}
  /* novedades: feed del día */
  .nv-row{display:flex; align-items:flex-start; gap:12px; padding:11px 6px; border-top:1px solid var(--line-soft); cursor:pointer; border-radius:var(--r-sm);}
  .nv-row:hover{background:var(--block);}
  .nv-row .kdot{margin-top:5px;}
  .nv-main{min-width:0; flex:1;}
  .nv-t{font-size:13px; font-weight:700; color:var(--ink); line-height:1.35;}
  .nv-d{font-size:11.5px; color:var(--gray); margin-top:1px;}
  .nv-f{margin-left:auto; flex:none; font-size:10px; color:var(--gray-soft); white-space:nowrap; padding-top:4px;}
  .ktitle{font-size:11.5px; font-weight:800; letter-spacing:.02em;}
  .ksub{font-size:10px; color:var(--gray); margin-top:1px;}
  .kbody{display:flex; flex-direction:column; gap:9px;}
  /* position:relative para que el aviso de la barra de retraso mida sus coordenadas contra la
     tarjeta y no contra el contenedor que rueda. Ojo: eso fija el origen, no evita el recorte
     —a un absolute lo recorta cualquier ancestro con overflow, sea o no su contenedor de
     referencia—, así que el aviso además tiene que quedarse dentro de la tarjeta. Ver
     .kc-ret-tx. */
  .kcard{background:var(--bg); border:1px solid var(--line); border-radius:9px; padding:10px 11px;
         cursor:pointer; position:relative;
         transition:opacity .12s ease, background .12s ease, border-color .12s ease;}
  .kcard:hover{border-color:#CDD5E1; box-shadow:var(--shadow);}
  @media (prefers-reduced-motion:reduce){ .kcard{transition:none;} }
  .kc-name{font-size:12px; font-weight:700; line-height:1.3;}
  .kc-meta{display:flex; align-items:center; gap:7px; margin-top:6px; font-size:10px; color:var(--gray); flex-wrap:wrap;}
  /* Un chip es white-space:nowrap y, como elemento flex, no encoge por debajo
     de su contenido: uno con un vínculo largo —"Tiryaki USA - Negociación
     Operación Carbonífera Zulia-Falcón"— se salía por el borde de la tarjeta.
     Se le pone tope y puntos suspensivos, con el texto completo en el title.
     Mismo tratamiento que ya usan los adjuntos de la línea de tiempo. */
  .kcard .chip{max-width:100%; min-width:0; overflow:hidden; text-overflow:ellipsis; display:inline-block;}
  .kc-amt{font-weight:800; color:var(--ink); white-space:nowrap;}
  .kc-bar{height:4px; border-radius:4px; background:var(--line); overflow:hidden; margin-top:8px;}
  .kc-bar i{display:block; height:100%; background:linear-gradient(90deg,var(--navy2),var(--cyan));}
  .kc-hint{margin-top:8px; font-size:9.5px; font-weight:700; color:var(--cyan-deep);}
  /* flex-wrap como red de seguridad: el pie de una tarjeta de kanban lleva
     pastillas y enlaces cuyo largo depende de los datos —los días, las veces que
     se ha insistido, el rótulo de la acción—, y en una columna de 199px el ancho
     que sobra es de un puñado de píxeles. Sin esto, el día que un oficio llegue
     a "↻12" o una acción cambie de nombre, el pie se sale por la derecha en
     silencio. Envolviendo, en el peor caso baja a una segunda línea. */
  .kc-foot2{display:flex; align-items:center; gap:7px; margin-top:8px; flex-wrap:wrap;}
  .age{display:inline-flex; align-items:center; font-size:9px; font-weight:800; padding:1px 6px; border-radius:20px; background:var(--block); color:var(--gray); border:1px solid var(--line-soft); white-space:nowrap; flex:none;}

  /* avisos de salida del proyecto y caja de notas (restaurados: cayeron por
     error al retirar el CSS del embudo de chevrons) */
  .cp-alert{margin-top:16px; padding:12px 14px; border-radius:8px; font-size:12.5px; line-height:1.55;}
  /* La exclusividad, en el azul oscuro de la casa. Iba en amarillo, y el
     amarillo en Atlas avisa de algo que se está torciendo —una espera larga, un
     dato sin verificar—. Una exclusividad no se está torciendo: es un estado
     del proyecto, y de los buenos. En azul dice lo que es, un dato firme que
     hay que tener presente, y de paso deja de competir con los avisos que sí
     piden que alguien haga algo. Los otros dos siguen donde estaban: el verde
     es un cierre y el rojo un descarte, y ahí el color es el significado. */
  .cp-alert.exclusividad{background:var(--navy); color:#fff;}
  /* El aviso de que la lista está filtrada, con clase propia: tomaba prestada
     la de exclusividad solo por el amarillo. Aquí el amarillo sí es lo suyo
     —«ojo, no estás viendo todo»— y se queda. */
  .cp-alert.filtros{background:var(--amber-bg); color:#7a5414;}
  .cp-alert.comprometida{background:var(--good-bg); color:#155c40;}
  .cp-alert.descartada{background:var(--rust-bg); color:#7a3420;}

  .cp-notabox{margin-bottom:18px;}
  .cp-notabox textarea{width:100%; border:1px solid var(--line); border-radius:8px; padding:9px 11px; font-family:inherit; font-size:12.5px; color:var(--ink); background:var(--bg); resize:vertical; min-height:56px;}
  .cp-notabox textarea:focus{outline:none; border-color:var(--navy2);}
  /* ---------- corregir una actividad en su sitio ----------
     Mismo gesto que la minuta de una reunión (.reu-ver): en reposo no se ve un
     campo de formulario, solo el texto; el fondo al pasar por encima es toda
     la pista de que se puede tocar. Un historial lleno de cajas de texto se
     lee como un formulario, y esto es una lista para leer. */
  .inv-nota-ver{margin:0 -8px; padding:2px 8px; border-radius:7px; cursor:text; transition:background .12s;}
  .inv-nota-ver:hover{background:var(--block);}
  .inv-nota-ver:focus-visible{outline:2px solid var(--navy2); outline-offset:1px;}
  /* Al corregir, el renglón se cambia por el MISMO formulario del alta —fecha,
     tipo y resumen—, así que aquí ya no hay un textarea suelto que vestir. */
  .inv-nota-form{flex:1 1 auto; min-width:0;}
  .inv-nota-form .cp-nota-campos{margin-bottom:11px;}

  /* Las acciones aparecen al pasar por la fila: siempre visibles convertían
     cada renglón del historial en una barra de botones. */
  .inv-nota-acc{display:inline-flex; gap:10px; margin-left:8px; opacity:0; transition:opacity .12s;}
  .tl-item:hover .inv-nota-acc, .inv-nota-acc:focus-within{opacity:1;}
  /* En pantalla táctil no hay «pasar por encima»: un botón que solo existe con
     ratón no existe. */
  @media (hover:none){ .inv-nota-acc{opacity:1;} }

  /* El ámbito, en la cabecera de la tarjeta: al lado del título y con el
     mismo alto que los demás controles de una .a-sec. Se le pone tope de
     ancho porque el nombre de un proyecto que nace de una carta es larguísimo
     y, sin él, empujaba el título fuera de su fila. */
  .cp-nota-proy-sel{border:1px solid var(--line); border-radius:8px; padding:6px 9px;
    font-family:inherit; font-size:12px; color:var(--ink); background:var(--bg);
    max-width:280px; text-overflow:ellipsis;}
  .cp-nota-proy-sel:focus{outline:none; border-color:var(--navy2);}
  /* Fecha y tipo, uno al lado del otro: son dos datos de una línea y apilados
     empujaban el resumen —lo único largo— fuera de la primera pantalla. */
  .cp-nota-campos{display:grid; grid-template-columns:1fr 1fr; gap:12px; margin-bottom:12px;}
  .cp-nota-campos .field{margin-bottom:0;}
  @media (max-width:560px){ .cp-nota-campos{grid-template-columns:1fr;} }
  /* ---- el documento de una actividad ----
     LA MINIATURA ES PEQUEÑA A PROPÓSITO, 48 px. El historial de un
     inversionista es una lista que se lee de arriba abajo; una vista previa a
     tamaño de tarjeta convierte cada registro con adjunto en un bloque que hay
     que saltarse, y hunde los registros que no llevan foto, que son la
     mayoría. Aquí solo hace falta reconocer que hay un documento y cuál es —
     para verlo en grande está el documento, a un clic—.
     El mismo cuadrado sirve para la imagen y para el icono de lo que no lo es,
     así la fila no cambia de alto entre un PDF y una foto. */
  .cp-adj-mini{flex:0 0 auto; width:48px; height:48px; border-radius:8px; border:1px solid var(--line);
    background:var(--block); background-size:cover; background-position:center; display:block;}
  .cp-adj-mini.ico{display:flex; align-items:center; justify-content:center; color:var(--gray-soft);}
  .cp-adj-mini.ico svg{width:20px; height:20px;}

  .cp-adj{margin-top:10px;}
  .cp-adj-add{display:inline-flex; align-items:center; gap:7px; font:inherit; font-size:12px; font-weight:700;
    color:var(--navy2); background:var(--bg); border:1px dashed #C4CEDD; border-radius:9px;
    padding:8px 13px; cursor:pointer;}
  .cp-adj-add:hover{border-color:var(--cyan-deep); background:#F3FAFE;}
  .cp-adj-add svg{width:14px; height:14px;}
  .cp-adj-sel, .cp-adj-doc{display:flex; align-items:center; gap:10px; min-width:0;}
  .cp-adj-sel{background:var(--bg); border:1px solid var(--line); border-radius:9px; padding:8px 10px;}
  /* El nombre se recorta con puntos suspensivos en vez de partir la fila: un
     acta puede llamarse "Acta de la mesa técnica CIIP-MINTUR 28-08-2026.pdf". */
  .cp-adj-sel .n, .cp-adj-doc .n{min-width:0; flex:1 1 auto; font-size:12px; color:var(--ink);
    overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  .cp-adj-x{flex:0 0 auto; font:inherit; font-size:12px; line-height:1; color:var(--gray-soft);
    background:none; border:0; cursor:pointer; padding:4px 6px;}
  .cp-adj-x:hover{color:var(--rust);}
  /* En el historial va sin recuadro: el renglón ya vive dentro de la línea de
     tiempo y una caja dentro de otra caja sube el peso visual de justo lo que
     se quería dejar discreto. */
  .cp-adj-doc{margin:7px 0 2px; max-width:420px;}
  .cp-adj-doc.abrible{cursor:pointer;}
  .cp-adj-doc.abrible:hover .n{color:var(--navy2); text-decoration:underline;}
  .cp-adj-doc.abrible:hover .cp-adj-mini{border-color:#CDD5E1;}

  .cp-notabox-row2{display:flex; align-items:center; justify-content:flex-end; gap:10px; margin-top:9px;}
  /* max-width: aunque las opciones ya van recortadas (nomCorto), el control
     cerrado se dimensiona por la elegida y un nombre de proyecto largo seguía
     empujando la fila entera. */
  .cp-notabox-row2 select{border:1px solid var(--line); border-radius:8px; padding:7px 9px; font-family:inherit; font-size:11.5px; color:var(--ink); background:var(--bg); max-width:280px; text-overflow:ellipsis;}
  /* El historial empieza donde termina el formulario, y se ve. Sin este filete
     el subformulario de la tarea quedaba pegado al primer renglón y parecían
     lo mismo. */
  .inv-hist-h{margin:26px 0 6px; padding-top:20px; border-top:1px solid var(--line);}
  /* .inv-hist-nota se retiró con su párrafo: explicaba que un registro se
     corrige pulsando encima, que es justo lo que enseñan el cursor y las
     acciones de la fila. */

  .tl-item.sys .tl-t{font-size:12px; font-weight:500; color:var(--gray);} .tl-item.sys .tl-dot{border-color:#C7CEDA;} .tl-item.sys{padding-bottom:12px;}
  .tl-item.hecha .tl-dot{background:var(--good); border-color:#BFE3CF;}
  .age.warn{background:var(--amber-bg); color:var(--amber); border-color:transparent;}
  .age.late{background:var(--rust-bg); color:var(--rust); border-color:transparent;}
  .kc-sig{font-size:9.5px; font-weight:700; color:var(--cyan-deep); margin-left:auto; text-align:right; line-height:1.35;}
  .kc-sig.warn{color:var(--amber);} .kc-sig.late{color:var(--rust);} .kc-sig.mute{color:var(--gray-soft);}

  /* ---- barra de retraso de la tarjeta ----
     Era la frase "1801d sin contacto documentado" escrita en la esquina: se leía tarjeta por
     tarjeta y entre veinte no había forma de ver cuál está peor. La barra sí se compara con la
     vista; los días siguen escritos al lado, porque la barra tope a 180 no distingue 200 de
     1801, y la frase entera aparece al pasar el mouse. */
  .kc-ret{margin-left:auto; display:flex; align-items:center; gap:6px; flex:none;}
  .kc-ret-d{font-size:9.5px; font-weight:800; line-height:1;}
  .kc-ret-tr{position:relative; width:56px; height:5px; border-radius:5px;
             background:var(--line-soft); overflow:hidden; flex:none;}
  .kc-ret-tr i{display:block; height:100%; border-radius:5px; width:var(--p);
               animation:kc-ret-crece .7s cubic-bezier(.22,.61,.36,1) both;}
  /* La marca de la cadencia objetivo, a los 90 días. Sin ella la barra diría "cuánto" pero no
     "cuánto de más": va encima del relleno, en el hueco entre lo esperado y lo real. */
  .kc-ret-tr::after{content:''; position:absolute; top:-1px; bottom:-1px; left:var(--meta);
                    width:1px; background:rgba(20,30,50,.35);}
  @keyframes kc-ret-crece{from{width:0}to{width:var(--p)}}
  .kc-ret.late .kc-ret-d{color:var(--rust);}   .kc-ret.late .kc-ret-tr i{background:var(--rust);}
  .kc-ret.warn .kc-ret-d{color:var(--amber);}  .kc-ret.warn .kc-ret-tr i{background:var(--amber);}
  .kc-ret.mute .kc-ret-d{color:var(--gray-soft);} .kc-ret.mute .kc-ret-tr i{background:var(--gray-soft);}
  /* La frase, al pasar por encima. Cubre el cuerpo de la tarjeta en vez de empujarlo: si
     ocupara sitio, la rejilla entera se recolocaría al mover el ratón por ella.
     Va DENTRO de la tarjeta (top), no colgada por encima de su borde. Estuvo en
     bottom:calc(100% - 4px), que la dejaba flotando sobre el borde superior con solo 4px
     dentro, y ahí las tarjetas de la primera fila de la ventana perdían la frase: anclar a
     .kcard fija el origen de las coordenadas, pero NO libra del recorte —a un absolute lo
     recorta cualquier ancestro con overflow, y .kl-body rueda—. Lo único que la salva es no
     salirse de la tarjeta. Se veía como una franja azul de 4px sobre la tarjeta y nada más. */
  .kc-ret-tx{position:absolute; left:9px; right:9px; top:8px;
             padding:6px 9px; border-radius:7px; background:var(--navy-deep, #0A1730); color:#fff;
             font-size:10px; font-weight:700; line-height:1.4; text-align:left;
             opacity:0; visibility:hidden; transform:translateY(3px);
             transition:opacity .14s ease, transform .14s ease, visibility .14s;
             pointer-events:none; box-shadow:0 6px 18px rgba(14,20,36,.22); z-index:3;}
  .kcard:hover .kc-ret-tx{opacity:1; visibility:visible; transform:translateY(0);}
  @media (prefers-reduced-motion:reduce){
    .kc-ret-tr i{animation:none;}
    .kc-ret-tx{transition:none; transform:none;}
  }

  /* ---- oficios: filas escaneables agrupadas por estado ---- */
  .ofi-row{display:flex; align-items:center; gap:14px; padding:12px 6px; border-top:1px solid var(--line-soft); cursor:pointer; border-radius:var(--r-sm);}
  .ofi-row:hover{background:var(--block);}
  .ofi-mono{flex:none; width:38px; height:38px; border-radius:8px; background:var(--block); border:1px solid var(--line-soft); display:flex; align-items:center; justify-content:center; font-size:9px; font-weight:800; color:var(--navy); letter-spacing:.03em;}
  .ofi-main{min-width:0; flex:1;}
  .ofi-act{font-size:13px; font-weight:700; color:var(--ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
  .ofi-act .ente{font-weight:600; color:var(--gray-soft); font-size:11px;}
  .ofi-que{font-size:11.5px; color:var(--gray); margin-top:2px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
  .ofi-right{flex:none; display:flex; align-items:center; gap:16px; text-align:right;}
  .ofi-d{font-size:12.5px; font-weight:700; color:var(--ink); line-height:1.1; white-space:nowrap;}
  .ofi-d small{display:block; font-size:8.5px; font-weight:700; letter-spacing:.01em; color:var(--gray-soft);}
  .ofi-d.warn{color:var(--amber);} .ofi-d.late{color:var(--rust);} .ofi-d.mute{color:var(--gray-soft);}
  .ofi-doc{display:inline-flex; align-items:center; justify-content:center; width:26px; height:26px; border:1px solid var(--line); border-radius:6px; color:var(--gray-soft); vertical-align:middle; cursor:pointer;}
  .ofi-doc:hover{color:var(--navy); border-color:#CDD5E1; background:var(--block);}
  .pick-note{background:#E8F6FE; border:1px solid #CBE9FB; color:var(--cyan-deep); font-size:12.5px; font-weight:600; padding:11px 16px; border-radius:var(--r-sm);}

  /* ---- oficios: vista Gantt ---- */
  .gantt{position:relative;}
  .gantt-axis{display:flex; align-items:center; gap:14px; height:24px; position:relative; border-bottom:1px solid var(--line); margin-bottom:2px;}
  .gantt-axis .g-label-sp{width:190px; flex:none;}
  .gantt-axis .g-track-sp{position:relative; flex:1 1 auto; height:100%;}
  .gantt-axis .g-mo{position:absolute; top:2px; font-size:9.5px; font-weight:800; letter-spacing:.03em; text-transform:capitalize; color:var(--gray-soft); transform:translateX(-1px); white-space:nowrap;}
  .gantt-axis .g-hoy-lbl{position:absolute; top:2px; font-size:9.5px; font-weight:800; color:var(--navy); transform:translateX(-50%); white-space:nowrap;}
  .gantt-rows{display:flex; flex-direction:column;}
  .grow{display:flex; align-items:center; gap:14px; padding:8px 0; border-bottom:1px solid var(--line-soft); cursor:pointer;}
  .grow:hover{background:var(--block);}
  .gr-label{width:190px; flex:none; min-width:0; display:flex; flex-direction:column; justify-content:center;}
  .gr-label b{font-size:11.5px; font-weight:700; color:var(--ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
  .gr-label span{font-size:10px; color:var(--gray-soft); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
  .gr-track{position:relative; flex:1 1 auto; height:16px;}
  .gr-bar{position:absolute; top:3px; height:10px; border-radius:5px;}
  .gr-bar.over{background-image:repeating-linear-gradient(45deg, currentColor 0 3px, transparent 3px 7px); opacity:.9; border-radius:0 5px 5px 0;}
  .g-hoy-line{position:absolute; top:26px; bottom:0; width:0; border-left:1px dashed var(--navy2); z-index:1;}
  .gantt-note{margin-top:12px; padding-top:12px; border-top:1px dashed var(--line); font-size:11px; color:var(--gray); line-height:1.6;}
  @media (max-width:900px){ .gr-label, .gantt-axis .g-label-sp{width:120px;} .gr-label span{display:none;} }
  /* configuración en tabs */
  .conf-2col{display:grid; grid-template-columns:1fr 1fr; gap:32px;}
  @media (max-width:980px){ .conf-2col{grid-template-columns:1fr;} }
  .conf-hint{font-size:11.5px; color:var(--gray); margin:-2px 0 12px; line-height:1.5;}
  .conf-check{display:flex; align-items:center; gap:9px; font-size:12.5px; color:var(--ink); margin-bottom:9px; cursor:pointer;}
  .conf-check input{accent-color:var(--navy);}
  .conf-check-grid{display:grid; grid-template-columns:repeat(auto-fill,minmax(190px,1fr)); gap:2px 12px;}
  .conf-check-grid .conf-check{margin-bottom:0;}
  .pf-photo-row{display:flex; align-items:center; gap:16px; margin-bottom:20px;}
  .pf-photo{width:72px; height:72px; border-radius:50%; background:linear-gradient(135deg,var(--cyan),var(--navy2)) center/cover no-repeat; display:flex; align-items:center; justify-content:center; color:#fff; font-weight:800; font-size:20px; flex:0 0 auto; box-shadow:0 0 0 2px rgba(255,255,255,.14);}
  .pf-photo-acts{display:flex; gap:8px; flex-wrap:wrap;}
  .g-count.late{background:var(--rust-bg); color:var(--rust);}
  .pcard.off .pc-photo{filter:grayscale(1); opacity:.75;}
  .a-off{display:inline-flex; align-items:center; font-size:10px; font-weight:800; padding:3px 10px; border-radius:20px; background:var(--rust-bg); color:var(--rust); white-space:nowrap;}

  /* ---- seguimiento: un oficio por fila, plegado ----
     Con nueve oficios la página ya era larga y con cincuenta sería
     impracticable. Cada uno enseña plegado lo justo para reconocerlo y saber
     si urge —número, asunto, días y estado— y se abre para trabajarlo. */
  .ofi-seg{display:flex; flex-direction:column; gap:8px;}
  .ofi-seg-i{background:var(--bg); border:1px solid var(--line); border-radius:var(--r); box-shadow:var(--shadow);}
  .ofi-seg-i.abierto{border-color:#C9D8EC;}
  .ofi-seg-cab{display:flex; align-items:center; gap:10px; padding:12px 16px; cursor:pointer; flex-wrap:wrap;}
  .ofi-seg-cab:hover{background:var(--block);}
  .ofi-seg-i.abierto .ofi-seg-cab{border-bottom:1px solid var(--line-soft);}
  .ofi-seg-car{color:var(--gray-soft); font-size:15px; transition:transform .15s ease; flex:0 0 auto;}
  .ofi-seg-car.on{transform:rotate(90deg);}
  .ofi-seg-num{font-size:12px; font-weight:700; color:var(--navy); white-space:nowrap;
               font-variant-numeric:tabular-nums; flex:0 0 auto;}
  .ofi-seg-nm{font-size:13.5px; font-weight:600; color:var(--ink); min-width:0;
              overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  .ofi-seg-cuerpo{padding:16px 18px 18px;}
  /* Lo que llega de vuelta: el acuse sellado, la respuesta, el comprobante. */
  .ofi-seg-adj{margin-top:18px; padding-top:15px; border-top:1px solid var(--line-soft);}
  .ofi-adj-list{display:flex; flex-direction:column; gap:8px; margin-top:9px;}
  .ofi-adj{display:flex; align-items:center; gap:10px; flex-wrap:wrap; font-size:12.5px;}
  .ofi-adj-ic{flex:0 0 auto; font-size:9px; font-weight:800; letter-spacing:.03em; color:var(--gray);
              background:var(--block); border:1px solid var(--line); border-radius:4px; padding:3px 6px;}
  /* Enlace de verdad: abre el archivo en una pestaña del navegador, con su
     visor de PDF y sus controles, que es donde se lee y se imprime. */
  .ofi-adj-nm{font-weight:600; color:var(--navy2); text-decoration:none; cursor:pointer; min-width:0;
              overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  .ofi-adj-nm:hover{text-decoration:underline;}
  .ofi-adj-m{color:var(--gray-soft); font-size:11.5px; flex:1 1 auto; min-width:0;}
  @media (prefers-reduced-motion:reduce){ .ofi-seg-car{transition:none;} }

  /* ---- la barra de pasos de un oficio ----
     Un trámite con cuatro momentos —membrete, redacción, despacho,
     seguimiento— que antes había que descubrir pulsando. La barra los enseña
     todos desde el principio y deja ir y volver: mismo lenguaje que las
     pestañas del sistema, pero numerado, porque aquí el orden sí importa. */
  .ofi-pasos{display:flex; gap:6px; flex-wrap:wrap; margin:0 0 18px;
             border-bottom:1px solid var(--line);}
  .ofi-paso{display:flex; align-items:center; gap:8px; padding:10px 13px 12px;
            font-size:12.5px; font-weight:600; color:var(--gray); cursor:pointer;
            border-bottom:2px solid transparent; margin-bottom:-1px; white-space:nowrap;}
  .ofi-paso:hover{color:var(--ink);}
  .ofi-paso.on{color:var(--navy); font-weight:700; border-bottom-color:var(--cyan);}
  .ofi-paso .n{display:inline-flex; align-items:center; justify-content:center;
               width:19px; height:19px; border-radius:50%; background:var(--block);
               border:1px solid var(--line); font-size:10.5px; font-weight:700; color:var(--gray-soft);}
  .ofi-paso.on .n{background:var(--navy); border-color:var(--navy); color:#fff;}
  /* Un paso ya recorrido se marca en ámbar, el mismo con el que Atlas señala
     en todas partes lo que está en curso. Estuvo en verde: el verde de la casa
     quiere decir "cerrado, conforme" —una respuesta recibida, un contrato
     vigente— y un oficio a medio trámite no está cerrado por haber pasado por
     un paso. */
  .ofi-paso.hecho .n{background:var(--amber-bg); border-color:var(--amber); color:var(--amber);}
  .ofi-paso-card{padding:20px 22px;}

  /* ---- redactar un oficio: la hoja y sus campos ----
     Dos columnas: el documento a la izquierda, tan parecido al papel como se
     pueda, y los datos a la derecha. La hoja va sobre blanco puro y con serifa
     aunque el resto de Atlas no lo sea: lo que se está escribiendo es un
     oficio en papel membretado, y verlo con la tipografía de la aplicación
     hacía difícil juzgar cómo va a quedar impreso. */
  .ofi-red{display:grid; grid-template-columns:minmax(0,1fr) 320px; gap:22px; align-items:start;}
  @media (max-width:940px){ .ofi-red{grid-template-columns:1fr;} }
  .ofi-hoja{background:#fff; border:1px solid var(--line); border-radius:var(--r);
            box-shadow:var(--shadow); overflow:hidden;}
  .ofi-hoja-cab img{display:block; width:100%; height:auto;}
  .ofi-hoja-cuerpo{padding:26px 46px 30px; font-family:'Times New Roman',Times,serif;
                   font-size:14.5px; line-height:1.75; color:#111; text-align:justify;}
  .ofi-hoja-cuerpo p{margin:0 0 13px;}
  .ofi-num{text-align:right; font-size:12.5px; color:#555; line-height:1.6; margin-bottom:20px;}
  .ofi-sinnum{color:#999;}
  /* Lo que pone la plantilla: se ve, para juzgar el documento entero, pero no
     se toca desde aquí. En gris apagado para que se distinga de lo redactado
     sin necesidad de un cartel que lo explique. */
  .ofi-fijo{color:#555;}
  .ofi-fijo-nota{font-family:'Helvetica Neue',Arial,sans-serif; font-size:10.5px; color:#A0A0A0;}
  /* Lo editable, en tinta plena y con su superficie: es la única parte de la
     hoja en la que se escribe, y tiene que verse antes de intentarlo. */
  .ofi-editable{color:#111; min-height:120px; padding:10px 12px; margin:0 -12px 13px;
                border-radius:5px; outline:1px dashed #C9D4E3;}
  .ofi-editable:hover{background:#FAFCFF;}
  .ofi-editable:focus{outline:2px solid var(--cyan-deep); outline-offset:0; background:#fff;}
  .ofi-editable ol{margin:0 0 10px 20px; line-height:1.55;}
  /* El pie del membrete: la ola tricolor y el escudo. Va pegado al fondo de la
     hoja, como en el documento impreso. */
  .ofi-hoja-piemem img{display:block; width:100%; height:auto;}
  /* Destinatario y firma: editables sobre la hoja, línea a línea. Se ven como
     texto normal y solo se marcan al pasar por encima o al escribir, para que
     el documento se lea como un documento y no como un formulario. */
  .ofi-dest{margin-bottom:16px;}
  .ofi-inline{display:block; min-height:0; padding:1px 6px; margin:0 -6px;
              outline:1px dashed transparent; border-radius:4px;}
  .ofi-inline:hover{outline-color:#D6DEE9; background:#FAFCFF;}
  .ofi-inline:focus{outline:2px solid var(--cyan-deep); background:#fff;}
  /* Un campo vacío no puede quedar invisible: se dice qué va ahí. */
  .ofi-inline:empty::before{content:attr(data-ph); color:#B8BFCC;}
  #ofiRDestNombre, .ofi-firma-nm{font-weight:700;}
  /* Centrado, como en la plantilla impresa: .firma de los oficios con cintillo
     lleva text-align:center, y al pasar a redactar encima de la plantilla el
     bloque se quedó alineado a la izquierda. El nombre y el cargo dejaban de
     caer bajo la firma escaneada y el oficio en pantalla no se parecía al que
     salía impreso. */
  .ofi-firma{margin-top:34px; text-align:center;}
  /* La firma escaneada, sobre el nombre. Sin marco ni fondo: es tinta. */
  .ofi-firma-img{min-height:0;}
  .ofi-firma-img img{display:block; max-height:74px; max-width:230px; margin:0 auto -6px;}
  /* Las firmas ya usadas, para elegir sin volver a subirlas. */
  .ofi-firmas{display:flex; align-items:center; gap:8px; flex-wrap:wrap;}
  .ofi-firma-op{width:74px; height:42px; border:1px solid var(--line); border-radius:var(--r-sm);
                background:var(--bg); display:flex; align-items:center; justify-content:center;
                cursor:pointer; overflow:hidden; padding:3px;}
  .ofi-firma-op img{max-width:100%; max-height:100%; object-fit:contain;}
  .ofi-firma-op:hover{border-color:var(--navy2);}
  .ofi-firma-op.on{border-color:var(--navy); box-shadow:0 0 0 2px rgba(0,64,144,.14);}
  .ofi-firma-op.nueva{font-size:19px; color:var(--gray-soft); border-style:dashed;}
  .ofi-firma-op.nueva:hover{color:var(--navy2);}
  /* El aviso de que el texto se pasa de la hoja: solo aparece cuando pasa. */
  .ofi-largo{font-size:11.5px; color:var(--amber); line-height:1.45; margin:0 0 13px; display:none;}
  .ofi-largo.on{display:block;}
  /* El saludo que pone la plantilla, dentro del bloque que se escribe: se lee
     seguido con lo redactado, pero en gris, para que se vea dónde empieza lo
     propio sin una línea que lo explique. */
  .ofi-lead{color:#555;}
  .ofi-hoja-pie{padding:11px 46px 14px; border-top:1px solid var(--line-soft);
                font-family:'Helvetica Neue',Arial,sans-serif; font-size:10.5px; color:var(--gray-soft);}
  .ofi-hoja-pie b{color:var(--gray);}
  .ofi-red-rail > .a-card{padding:16px 18px; margin-bottom:14px;}
  .ofi-red-hint{font-size:11.5px; color:var(--gray-soft); line-height:1.5;}
  .ofi-red-hint .op-link{font-size:11.5px;}
  .ofi-aviso-ente{font-size:11.5px; color:var(--amber); line-height:1.45; margin-top:6px;}
  .ofi-aviso-ente:empty{display:none;}
  .ofi-red-acts{display:flex; align-items:center; gap:10px; flex-wrap:wrap;}

  /* ---- chips ---- */
  .chip{display:inline-flex; align-items:center; gap:5px; font-size:10px; font-weight:700; border-radius:20px; padding:2px 8px; white-space:nowrap;}
  .chip.sector{background:var(--block); color:var(--gray); border:1px solid var(--line); font-weight:600;}
  .chip.good{background:var(--good-bg); color:var(--good);}
  .chip.warn{background:var(--amber-bg); color:var(--amber);}
  .chip.info{background:#E8F6FE; color:var(--cyan-deep);}
  .chip.mute{background:#EEF0F3; color:var(--gray);}
  .chip.rust{background:var(--rust-bg); color:var(--rust);}

  /* ---- estado de una correspondencia, en versión mínima ----
     Un punto del color que ya usan las gráficas del módulo
     (CR_ESTADO_COLOR) y el nombre al lado. Sin fondo ni borde a propósito:
     va en el pie de la tarjeta del Directorio y junto al título de la
     ficha, y en los dos sitios acompaña al dato principal en vez de
     competir con él — un .chip lleno ahí pesaba más que el asunto de la
     carta. El .chip sigue existiendo para el historial, donde el estado
     SÍ es el dato. */
  .cr-est{display:inline-flex; align-items:center; gap:6px; font-size:10.5px; font-weight:700;
          color:var(--gray); white-space:nowrap; letter-spacing:.01em;}
  .cr-est i{width:7px; height:7px; border-radius:50%; flex:0 0 auto;}
  /* En la cabecera de la ficha convive con los .chip del título, que son más
     altos; sube medio punto para no quedar hundido entre ellos. */
  .a-h2 .cr-est{font-size:11px;}

  /* La tarjeta desde la que se cambia el estado, arriba de la pestaña
     Historial: el estado actual a la izquierda y el desplegable al lado, en
     la misma línea, para que se lea "está en X, cámbialo a Y" de un vistazo.
     En pantalla estrecha se parten en dos renglones. */
  /* Aquí vivía la tarjeta del editor de estado (.cr-est-card y compañía). Se
     fue con él: los dos ejes de Seguimiento dicen lo mismo con más precisión.
     .cr-est —el punto de color con el nombre del estado— se queda: lo siguen
     usando las listas y las fichas. */

  /* ---- tables ---- */
  table.tbl{width:100%; border-collapse:collapse; font-size:11.5px;}
  table.tbl th{text-align:left; font-size:10.5px; font-weight:800; letter-spacing:.01em; color:var(--gray-soft); padding:0 10px 8px; border-bottom:1px solid var(--line);}
  table.tbl td{padding:10px 10px; border-bottom:1px solid var(--line-soft); vertical-align:middle; font-size:13.5px;}
  table.tbl tr:last-child td{border-bottom:none;}
  table.tbl tr.click{cursor:pointer;}
  table.tbl tr.click:hover td{background:var(--block);}
  /* La corrida que se está mirando abajo, en #/respaldos — mismo criterio
     de fondo que .click:hover pero fijo, para que no se confunda con "el
     mouse está encima" al alejar el cursor. */
  table.tbl tr.rp-on td{background:var(--block);}
  table.tbl td.who{font-weight:700; color:var(--ink);}
  table.tbl td.num{font-variant-numeric:tabular-nums; font-weight:700;}
  .mini{font-size:10.5px; color:var(--gray);}

  /* ---- ficha / plantilla / ente cards ---- */
  .libgrid{display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:14px;}
  .libgrid.two{grid-template-columns:repeat(2,1fr);}
  .fcard{border:1px solid var(--line); border-radius:11px; padding:16px 17px; background:var(--bg); display:flex; flex-direction:column;}
  .fcard .fc-top{display:flex; align-items:center; gap:8px; margin-bottom:9px; flex-wrap:wrap;}
  .fcard .fc-line{overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  .fcard .fc-name{font-size:14px; font-weight:700; letter-spacing:-.01em; line-height:1.25;}
  .fcard .fc-line{font-size:10.5px; color:var(--gray-soft); margin-top:2px;}
  .fcard .fc-body{font-size:11.5px; color:#39414F; margin-top:10px; line-height:1.5; flex:1 1 auto;}
  .fcard .fc-rows{margin-top:11px; display:flex; flex-direction:column; gap:5px;}
  .fcard .fc-row{display:flex; gap:8px; font-size:11px;}
  .fcard .fc-row .k{color:var(--gray-soft); font-weight:700; min-width:76px; flex:0 0 auto;}
  .fcard .fc-row .v{color:var(--ink);}
  .fcard .fc-foot{display:flex; align-items:center; gap:8px; margin-top:13px; padding-top:12px; border-top:1px solid var(--line-soft); flex-wrap:wrap;}
  .taglist{display:flex; flex-wrap:wrap; gap:5px; margin-top:4px;}
  .ente-ic{width:40px; height:40px; border-radius:9px; background:var(--navy); color:#fff; display:flex; align-items:center; justify-content:center; font-size:11px; font-weight:800; flex:0 0 auto; letter-spacing:0;}
  .ente-sub{font-size:10px; color:var(--gray-soft); margin-top:1px;}
  .trmt{display:flex; gap:8px; align-items:flex-start; font-size:11px; color:#39414F; padding:5px 0; line-height:1.4;}
  .trmt .d{color:var(--cyan-deep); font-weight:800; flex:0 0 auto;}

  /* ---- buttons ---- */
  .btn{font-size:11.5px; font-weight:700; border-radius:8px; padding:7px 13px; cursor:pointer; border:1px solid transparent; white-space:nowrap; font-family:inherit;}
  .btn.primary{background:var(--cyan); color:#06283b;}
  .btn.navy{background:var(--navy); color:#fff;}
  .btn.ghost{background:#fff; border-color:var(--line); color:var(--ink);}
  .btn.ghost:hover{border-color:#CDD5E1;}
  .btn.danger{background:var(--rust); color:#fff;}
  .btn.sm{font-size:10.5px; padding:5px 10px;}
  /* Acciones del rail de fichas (Editar / Eliminar): ancho completo y tamaño legible */
  .btn-rail{width:100%; justify-content:center; text-align:center; font-size:13px; padding:11px 14px; min-height:44px; display:inline-flex; align-items:center;}
  /* El bloque que las agrupa. Va en UN solo elemento a propósito: .a-rail separa
     24px a sus hijos directos, así que tres botones sueltos quedaban a un mundo
     de distancia unos de otros —y a distinta distancia en cada módulo, según
     dónde estuvieran puestos—. Dentro del bloque mandan estos 8px, iguales en
     todas las fichas. Lo escribe railAcciones() en js/core.js. */
  .rail-acc{display:flex; flex-direction:column; gap:8px;}
  .rail-pie{font-size:10.5px; color:var(--gray-soft); text-align:center; line-height:1.45;}
  /* El enlace al ente custodio, en su propio renglón bajo el nombre. Pegado
     detrás se partía a mitad de frase —el rail es angosto y el nombre de un
     ministerio se lleva casi todo el ancho—, así que la flecha acababa sola en
     la línea siguiente. Aquí no se parte nunca: es su propia línea. */
  .act-rail-ir{display:inline-block; margin-top:4px; font-size:12px; white-space:nowrap;}
  .btn:disabled{opacity:.5; cursor:default;}

  /* ---- modal genérico ---- */
  .modalbg{position:fixed; inset:0; background:rgba(10,20,40,.5); z-index:110; display:none; align-items:center; justify-content:center; padding:20px;}
  .modalbg.open{display:flex;}
  /* LA TARJETA NO SE DESPLAZA ENTERA: se desplaza solo su cuerpo.
     Antes el overflow vivía aquí, así que en un formulario largo —editar una
     tarea es el caso— la cabecera y el PIE se iban hacia arriba con el resto:
     había que desplazarse hasta el fondo para encontrar "Guardar", y el aspa
     de cerrar desaparecía por el techo. Con la tarjeta como columna flexible,
     cabecera y pie se quedan fijos y el desplazamiento queda donde tiene que
     estar, en el contenido.
     min-height:0 en el cuerpo es lo que permite que un hijo flexible se
     encoja por debajo de su contenido; sin él, el cuerpo se estira y vuelve a
     empujar el pie fuera de la pantalla. */
  .modalcard{background:#fff; border-radius:12px; width:100%; max-width:440px; max-height:88vh;
    display:flex; flex-direction:column; overflow:hidden; box-shadow:0 20px 60px rgba(14,20,36,.28);}
  .modal-h{flex:0 0 auto; display:flex; align-items:center; justify-content:space-between; gap:10px; padding:15px 18px; border-bottom:1px solid var(--line);}
  .modal-t{font-size:14px; font-weight:700; color:var(--ink);}
  /* Es un <button> de verdad (antes un <span>): se le quita la piel que le
     pone el navegador para que siga viéndose igual, pero ahora se alcanza con
     el teclado y se anuncia como "Cerrar". */
  .modal-x{cursor:pointer; color:var(--gray-soft); font-size:15px; line-height:1; padding:4px;
    background:none; border:0; font-family:inherit;}
  .modal-x:hover{color:var(--ink);}
  .modal-b{padding:18px; flex:1 1 auto; min-height:0; overflow:auto;}
  .modal-b .field:last-child{margin-bottom:0;}
  /* flex-wrap: el pie de un diálogo no siempre lleva dos botones. El historial
     de un oficio ofrece hasta cinco acciones más "Cerrar", y en una sola línea
     no caben: se salían por la izquierda de la tarjeta y los dos primeros
     quedaban cortados —el principal entre ellos—. Al permitir que bajen de
     línea caben todos, siguen alineados a la derecha, y de paso queda
     resuelto para cualquier diálogo en una pantalla estrecha. */
  .modal-f{flex:0 0 auto; display:flex; flex-wrap:wrap; justify-content:flex-end; gap:8px; padding:14px 18px; border-top:1px solid var(--line); background:#fff;}
  .field select{width:100%; border:1px solid var(--line); border-radius:8px; padding:9px 11px; font-family:inherit; font-size:12.5px; color:var(--ink); background:var(--bg);}
  .conf-err{color:var(--rust); font-size:11.5px; margin:-4px 0 12px;}
  .modalcard.wide{max-width:680px;}
  /* Un escalón más para las listas de contratos: cuatro columnas —nombre, fecha de firma,
     barra e importe— no caben en 680px sin recortar el nombre, que es lo que se lee primero. */
  .modalcard.xwide{max-width:780px;}

  /* ---- alta de activo ---- */
  .na-steps{display:flex; gap:6px; margin-bottom:18px;}
  .na-step{flex:1; height:3px; border-radius:3px; background:var(--line);}
  .na-step.done{background:var(--navy2);}
  .na-step.cur{background:var(--cyan);}
  .na-drop{border:1.5px dashed #C4CEDD; border-radius:12px; padding:36px 20px; text-align:center; cursor:pointer; transition:border-color .12s, background .12s;}
  .na-drop:hover, .na-drop.over{border-color:var(--cyan-deep); background:#F3FAFE;}
  .na-drop .ic{font-size:24px; margin-bottom:10px;}
  .na-drop .t1{font-size:13.5px; font-weight:700;}
  .na-drop .t2{font-size:11.5px; color:var(--gray); margin-top:4px;}
  .na-or{display:flex; align-items:center; gap:10px; margin:16px 0; color:var(--gray-soft); font-size:11px; font-weight:700; letter-spacing:.01em;}
  .na-or::before, .na-or::after{content:''; flex:1; height:1px; background:var(--line);}
  .na-filelist{display:flex; flex-direction:column; gap:6px; margin-top:14px;}
  .na-filerow{display:flex; align-items:center; gap:9px; font-size:11.5px; padding:8px 10px; border:1px solid var(--line); border-radius:8px; background:var(--block);}
  .na-filerow .sz{color:var(--gray-soft); margin-left:auto;}
  .na-analyzing{text-align:center; padding:26px 10px;}
  .na-spin{width:34px; height:34px; border-radius:50%; border:3px solid var(--line); border-top-color:var(--cyan-deep); margin:0 auto 18px; animation:na-sp .9s linear infinite;}
  @keyframes na-sp{to{transform:rotate(360deg);}}
  .na-log{margin-top:16px; text-align:left; max-width:360px; margin-left:auto; margin-right:auto; display:flex; flex-direction:column; gap:8px;}
  .na-lrow{display:flex; align-items:center; gap:9px; font-size:11.5px; color:var(--gray-soft); opacity:0; transform:translateX(-4px); transition:opacity .3s, transform .3s, color .3s;}
  .na-lrow.on{opacity:1; transform:none; color:var(--ink);}
  .na-lrow .dot{width:6px; height:6px; border-radius:50%; background:var(--line); flex:0 0 auto;}
  .na-lrow.on .dot{background:var(--good);}
  .na-sec{font-size:11px; font-weight:800; letter-spacing:.01em; color:var(--gray); margin:20px 0 12px;}
  .na-sec:first-child{margin-top:0;}
  .na-row2{display:grid; grid-template-columns:1fr 1fr; gap:12px;}
  .na-legend{display:flex; gap:14px; font-size:10.5px; color:var(--gray-soft); margin-bottom:16px; flex-wrap:wrap;}
  .na-legend span{display:inline-flex; align-items:center; gap:5px;}
  .na-legend i{width:7px; height:7px; border-radius:50%; display:inline-block;}
  .field .lb{display:flex; align-items:center; gap:8px; margin-bottom:5px;}
  .field .lb label{margin-bottom:0;}
  .field.falta input, .field.falta select, .field.falta textarea{border-color:var(--rust); background:var(--rust-bg);}
  .field textarea{width:100%; border:1px solid var(--line); border-radius:8px; padding:9px 11px; font-family:inherit; font-size:12.5px; color:var(--ink); background:var(--bg); resize:vertical; min-height:64px;}
  .na-photos{display:flex; flex-wrap:wrap; gap:10px;}
  .na-pthumb{position:relative; width:82px; height:82px; border-radius:9px; background-size:cover; background-position:center; border:1px solid var(--line);}
  .na-pthumb .x{position:absolute; top:-6px; right:-6px; width:20px; height:20px; border-radius:50%; background:var(--ink); color:#fff; font-size:11px; display:flex; align-items:center; justify-content:center; cursor:pointer; border:2px solid #fff;}
  .na-padd{width:82px; height:82px; border-radius:9px; border:1.5px dashed #C4CEDD; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4px; font-size:10px; font-weight:700; color:var(--gray-soft); cursor:pointer; text-align:center;}
  .na-padd:hover{border-color:var(--cyan-deep); color:var(--navy2);}
  .na-padd .ic{font-size:17px;}
  .na-pcredit{width:100%; margin-top:6px;}
  .na-pcredit input{width:100%; border:1px solid var(--line); border-radius:6px; padding:5px 7px; font-size:10.5px; font-family:inherit;}
  .na-cand{display:flex; align-items:flex-start; gap:10px; padding:10px 0; border-bottom:1px solid var(--line-soft);}
  .na-cand:last-child{border-bottom:none;}
  .na-cand input[type=checkbox]{margin-top:10px; accent-color:var(--navy); flex:0 0 auto;}
  .na-cand-fields{flex:1; min-width:0; display:grid; grid-template-columns:1.4fr 1fr 1fr 90px; gap:8px;}
  .na-cand-fields input, .na-cand-fields select{width:100%; border:1px solid var(--line); border-radius:6px; padding:7px 9px; font-family:inherit; font-size:12px; color:var(--ink); background:var(--bg);}

  /* ---- toast ----
     Centrado en TODA la ventana (left:50%) sin descontar el sidebar caía,
     en pantallas anchas, justo encima del contenido de la izquierda —
     tapando en vivo el tooltip de "Otros documentos" en Banco de activos.
     La esquina inferior derecha, lejos del sidebar y de donde suele estar
     el cursor sobre un botón o un tooltip, no tiene ese problema. */
  .toast{position:fixed; right:26px; bottom:26px; transform:translateY(10px); background:var(--navy-deep); color:#fff; font-size:12.5px; font-weight:600; padding:10px 18px; border-radius:30px; box-shadow:0 10px 30px rgba(14,20,36,.25); z-index:120; opacity:0; pointer-events:none; transition:opacity .18s ease, transform .18s ease; max-width:min(360px,86vw); text-align:left;}
  .toast.show{opacity:1; transform:translateY(0);}

  /* ---- detail ---- */
  .back{display:inline-flex; align-items:center; gap:6px; font-size:11.5px; font-weight:700; color:var(--navy2); cursor:pointer; margin-bottom:2px;}
  .d-head{display:flex; align-items:flex-start; gap:18px; flex-wrap:wrap;}
  .d-head h1{font-size:21px; font-weight:700; letter-spacing:-.02em;}
  .d-head .d-chips{display:flex; gap:7px; flex-wrap:wrap; margin-top:8px;}
  .d-head .d-amt{margin-left:auto; text-align:right; flex:0 0 auto;}
  .d-head .d-amt .n{font-size:24px; font-weight:800; letter-spacing:-.02em;}
  .d-head .d-amt .l{font-size:10px; color:var(--gray); font-weight:600;}
  .sprog{display:flex; align-items:center; gap:0; margin-top:4px;}
  .sstep{display:flex; align-items:center; gap:8px; flex:0 0 auto;}
  .sstep .sdot{width:12px; height:12px; border-radius:50%; background:var(--line); border:2px solid var(--line);}
  .sstep .slab{line-height:1.2;} .sstep .slab b{font-size:10px; font-weight:800; display:block;} .sstep .slab span{font-size:9.5px; color:var(--gray);}
  .sstep.done .sdot{background:var(--navy2); border-color:var(--navy2);}
  .sstep.cur .sdot{background:var(--cyan); border-color:#BFE6FA; box-shadow:0 0 0 3px rgba(32,176,240,.2);}
  .sstep.done .slab b, .sstep.cur .slab b{color:var(--ink);}
  .sstep.todo .slab b{color:var(--gray-soft);}
  .sline{flex:1 1 auto; height:2px; background:var(--line); margin:0 10px; min-width:20px;}
  .sline.on{background:var(--navy2);}
  .d-block{margin-bottom:16px;} .d-block:last-child{margin-bottom:0;}
  .d-lab{font-size:9px; font-weight:800; letter-spacing:.01em; color:var(--gray-soft); margin-bottom:6px;}
  .d-txt{font-size:12.5px; color:#2A3346; line-height:1.55;}
  .why{background:var(--block); border:1px solid var(--line-soft); border-radius:9px; padding:11px 13px;}
  .why .why-l{font-size:9px; font-weight:800; letter-spacing:.01em; color:var(--cyan-deep); margin-bottom:4px;}
  .why .why-t{font-size:12px; color:#2A3346; line-height:1.5;}
  .brechas{display:flex; flex-direction:column; gap:7px;}
  .brow{display:flex; gap:9px; align-items:flex-start; font-size:11.5px; color:#39414F; line-height:1.45;}
  .brow .bmk{width:6px; height:6px; border-radius:50%; background:var(--amber); margin-top:6px; flex:0 0 auto;}
  .brow .btag{margin-left:auto; font-size:9px; font-weight:700; color:var(--cyan-deep); white-space:nowrap; flex:0 0 auto;}
  .kv{display:flex; flex-direction:column; gap:9px;}
  .kv .r{display:flex; gap:10px; font-size:13px;}
  .kv .r .k{color:var(--gray-soft); font-weight:700; min-width:80px; flex:0 0 auto;}
  .kv .r .v{color:var(--ink); font-weight:600;}
  .relofi{border:1px solid var(--line); border-radius:9px; padding:10px 12px; margin-top:8px;}
  .relofi .ro-t{font-size:11.5px; font-weight:700;}
  .relofi .ro-d{font-size:10.5px; color:var(--gray); margin-top:3px; line-height:1.4;}

  /* ---- settings ---- */
  .set-row{display:flex; align-items:center; gap:13px; padding:11px 0; border-bottom:1px solid var(--line-soft);}
  .set-row:last-child{border-bottom:none;}
  .set-av{width:38px; height:38px; border-radius:50%; background:linear-gradient(135deg,var(--cyan),var(--navy2)); color:#fff; display:flex; align-items:center; justify-content:center; font-size:12px; font-weight:800; flex:0 0 auto;}
  .set-nm{font-size:12.5px; font-weight:700;}
  .set-ml{font-size:10.5px; color:var(--gray);}
  .roletag{margin-left:auto; font-size:10px; font-weight:700; border-radius:20px; padding:3px 10px; background:var(--block); border:1px solid var(--line); color:var(--gray);}
  .roletag.admin{background:#E8F6FE; color:var(--cyan-deep); border-color:#CDEBFA;}
  .row-acts{display:flex; gap:12px; white-space:nowrap;}
  .row-acts .op-link{font-size:11px;}
  .row-acts .op-link.danger{color:var(--rust);}
  .row-acts .op-link.mute{color:var(--gray-soft); cursor:default;}
  .field{margin-bottom:13px;} .field label{font-size:10px; font-weight:800; letter-spacing:.01em; color:var(--gray-soft); display:block; margin-bottom:5px;}
  .field input{width:100%; border:1px solid var(--line); border-radius:8px; padding:9px 11px; font-family:inherit; font-size:12.5px; color:var(--ink); background:var(--bg);}
  .perm{width:100%; border-collapse:collapse; font-size:11.5px;}
  .perm th{text-align:left; font-size:9.5px; font-weight:800; letter-spacing:.01em; color:var(--gray-soft); padding:0 8px 8px;}
  .perm td{padding:9px 8px; border-top:1px solid var(--line-soft);}
  .perm td.c{text-align:center;} .perm .yes{color:var(--good); font-weight:800;} .perm .no{color:var(--gray-soft);}

  /* ---- Roles y permisos: listado de grupos y matriz ----
     Pensado para escalar: con 3 grupos una tira horizontal bastaba, con 100 no.
     Se pasa a maestro-detalle con buscador y scroll propio. Mismos tokens de
     color y las mismas formas que el resto del panel: cambia la disposicion,
     no el aspecto. */
  .gp-wrap{display:grid; grid-template-columns:264px 1fr; gap:24px; align-items:start;}
  @media (max-width:980px){ .gp-wrap{grid-template-columns:1fr;} }
  .gp-buscar{width:100%; box-sizing:border-box; border:1px solid var(--line); border-radius:8px;
    padding:8px 10px; font-family:inherit; font-size:12px; color:var(--ink); background:#fff; margin-bottom:8px;}
  .gp-buscar:focus{outline:none; border-color:var(--navy2); box-shadow:0 0 0 3px rgba(0,96,176,.10);}
  /* Sin scroll propio: vive en el flujo normal de la página (no en un modal ni
     un panel anclado), así que rodaba dos veces —la página y esta lista— igual
     que los casos ya retirados en "Fuera el doble scroll en todo el sistema". */
  .gp-lista{border:1px solid var(--line); border-radius:8px; background:var(--block); padding:3px;}
  .gp-item{display:flex; align-items:center; gap:8px; padding:7px 9px; border-radius:6px;
    font-size:11.5px; font-weight:700; color:var(--gray); cursor:pointer;}
  .gp-item:hover{color:var(--ink);}
  .gp-item.on{background:#fff; color:var(--navy); box-shadow:0 1px 2px rgba(14,20,36,.08);}
  .gp-item .n{flex:1 1 auto; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  .gp-item .c{font-size:10px; font-weight:800; color:var(--gray-soft);}
  .gp-vacio{padding:14px 10px; font-size:11.5px; color:var(--gray-soft);}
  /* Cabeceras y primera columna pulsables: marcan la columna o la fila entera.
     El subrayado punteado avisa de que son accionables sin meter otro control. */
  .perm th.tog, .perm td.tog{cursor:pointer; user-select:none;}
  .perm th.tog:hover, .perm td.tog:hover{color:var(--navy);}
  .perm th.tog{text-decoration:underline dotted var(--line); text-underline-offset:3px;}
  .perm td.tog{text-decoration:underline dotted var(--line-soft); text-underline-offset:3px;}
  .perm th.esq{cursor:pointer; user-select:none;}
  .perm th.esq:hover{color:var(--navy);}

  /* Roles y permisos: categorías colapsables dentro de un grupo, y la
     descripción editable inline en su cabecera. */
  .perm-cat{margin-bottom:16px;}
  .perm-cat:last-child{margin-bottom:0;}
  .perm-cat-h{display:flex; align-items:center; gap:8px; width:100%; background:none; border:none;
    padding:6px 2px; cursor:pointer; font-family:inherit; text-align:left;}
  .perm-cat-h:hover .t{color:var(--navy);}
  .perm-cat-h .t{font-size:12.5px; font-weight:700; color:var(--ink);}
  .perm-cat-h .chev{font-size:10px; color:var(--gray-soft); transition:transform .15s ease; display:inline-block;}
  .perm-cat-h .chev.cerrado{transform:rotate(-90deg);}
  .conf-desc-input{border:1px solid transparent; border-bottom:1px solid var(--line); background:none;
    font-size:12px; color:var(--gray); padding:1px 0; font-family:inherit; min-width:220px;}
  .conf-desc-input:hover{border-bottom-color:#CDD5E1;}
  .conf-desc-input:focus{outline:none; border-bottom-color:var(--navy2);}
  /* El <select> de alcance, con el mismo lenguaje de color que .chip en vez de
     la caja gris de un <select> corriente — para que se lea de un vistazo qué
     tan amplio es cada permiso sin tener que leer el texto. */
  .perm .alcance-sel{border:1px solid var(--line); border-radius:20px; background:#fff; font-family:inherit;
    font-size:10px; font-weight:700; padding:3px 8px; cursor:pointer; color:var(--gray);}
  .perm .alcance-sel:disabled{opacity:.5; cursor:default;}
  .perm .alcance-sel.v-todo{background:#E8F6FE; color:var(--cyan-deep); border-color:transparent;}
  .perm .alcance-sel.v-grupo{background:var(--amber-bg); color:var(--amber); border-color:transparent;}
  .perm .alcance-sel.v-propio{background:#EEF0F3; color:var(--gray); border-color:transparent;}

  /* ===================== TRAZABILIDAD (shadcn/ui) =====================
     Única pantalla de Atlas con este tratamiento, a pedido explícito del
     presidente: paleta zinc + Geist/Geist Mono, en vez de navy/Instrument
     Serif. Todo prefijado tz- para no pisar ni heredar nada del resto de la
     app — es una isla visual deliberada, no un descuido de consistencia. */
  /* #view (index.html) ya trae class="grid" (12 columnas, línea ~124) — todo
     módulo necesita grid-column:span 12 para ocupar el ancho completo, igual
     que .col12 en el resto de Atlas. Sin esto, .tz-shell caía como un solo
     carril angosto del grid: quedaba un hueco en blanco a la derecha y la
     tabla, comprimida contra su propio contenido mínimo, terminaba fuera de
     lo visible. (El margin/padding negativo que hubo aquí antes intentaba
     escapar del padding de .content, pero el problema real era este.) */
  /* Los tokens van aparte del resto de .tz-shell porque ya no los usa solo
     Trazabilidad: la barra de filtros de Seguimiento y de Alianzas
     (.sg-filter/.sg-toolbar) toma de aquí el borde, el radio y el anillo de
     foco para poder reusar
     .tz-inp y .tz-btn tal cual, en vez de tener su propia versión parecida.
     Lo que sigue siendo exclusivo de Trazabilidad —Geist y el fondo zinc— se
     quedó en el bloque de abajo. */
  .tz-shell, .sg-filter, .sg-toolbar{
    --tz-bg:#fafafa; --tz-fg:#09090b; --tz-card:#ffffff;
    --tz-muted:#f4f4f5; --tz-muted-fg:#71717a;
    --tz-border:#e4e4e7; --tz-input:#e4e4e7; --tz-ring:#a1a1aa;
    --tz-secondary:#f4f4f5; --tz-secondary-fg:#18181b;
    --tz-destructive:#dc2626; --tz-destructive-bg:#fef2f2; --tz-destructive-border:#fecaca;
    --tz-r:0.625rem;
  }
  .tz-shell{
    grid-column:span 12;
    font-family:'Geist',ui-sans-serif,Arial,sans-serif; background:var(--tz-bg); color:var(--tz-fg);
    font-size:14px; line-height:1.5; min-width:0;
  }
  .tz-shell *{box-sizing:border-box;}
  .tz-mono{font-family:'Geist Mono',ui-monospace,monospace; font-variant-numeric:tabular-nums;}

  .tz-pagehead{display:flex; align-items:flex-start; justify-content:space-between; gap:16px; margin-bottom:22px; flex-wrap:wrap;}
  .tz-pagehead h1{font-size:23px; font-weight:600; margin:0 0 6px; letter-spacing:-.01em;}
  .tz-pagehead p{margin:0; color:var(--tz-muted-fg); font-size:13.5px; max-width:64ch;}

  .tz-badge{display:inline-flex; align-items:center; gap:5px; font-size:11.5px; font-weight:500; padding:2px 9px; border-radius:9999px; border:1px solid var(--tz-border); background:var(--tz-secondary); color:var(--tz-secondary-fg); white-space:nowrap;}
  .tz-badge.destructive{background:var(--tz-destructive-bg); color:var(--tz-destructive); border-color:var(--tz-destructive-border);}

  .tz-layout{display:grid; grid-template-columns:252px 1fr; gap:24px; align-items:start;}
  /* Mismo caso que .plm-carril/.a-rail.cp-sticky: con .tz-layout en una sola
     columna, .tz-rail (los filtros) queda antes de .tz-main en el flujo, no al
     lado — pero seguía con position:sticky, así que se quedaba pegado a
     top:20px y la tabla se desplazaba por debajo, encimándose con los
     filtros. Reportado por el usuario con capturas de la tabla ilegible. */
  @media (max-width:980px){ .tz-layout{grid-template-columns:1fr;} .tz-rail{position:static;} }

  .tz-rail{position:sticky; top:20px; display:flex; flex-direction:column; gap:18px;}
  .tz-rail-card{background:var(--tz-card); border:1px solid var(--tz-border); border-radius:var(--tz-r); padding:14px;}
  .tz-rail-card .rt{font-size:11px; font-weight:600; text-transform:uppercase; letter-spacing:.05em; color:var(--tz-muted-fg); margin-bottom:10px; padding:0 4px;}
  .tz-navtab{display:flex; align-items:center; justify-content:space-between; padding:8px 10px; border-radius:calc(var(--tz-r) - 4px); font-size:13.5px; font-weight:500; color:var(--tz-muted-fg); cursor:pointer; margin-bottom:2px;}
  .tz-navtab:hover{background:var(--tz-muted);}
  /* Azul de marca (--navy2, el mismo de las gráficas de Correspondencia) en
     vez del negro/zinc del resto de la "isla": pedido explícito para que la
     pestaña activa, el orden de columna y la página del paginador compartan
     acento con el resto de Atlas sin renunciar a la paleta zinc/Geist del
     resto de la pantalla. */
  .tz-navtab.on{background:var(--navy2); color:#fff;}
  .tz-navtab .n{font-family:'Geist Mono',monospace; font-size:11px; opacity:.6;}
  .tz-navtab.on .n{opacity:.8;}

  .tz-rail-card .field{margin-bottom:12px;}
  .tz-rail-card .field:last-child{margin-bottom:0;}
  .tz-rail-card .field label{display:block; font-size:11.5px; font-weight:500; color:var(--tz-muted-fg); margin-bottom:5px;}
  .tz-inp{font:inherit; font-size:13px; border:1px solid var(--tz-input); border-radius:calc(var(--tz-r) - 4px); padding:7px 10px; background:var(--tz-card); color:var(--tz-fg); outline:none; width:100%; min-width:0;}
  .tz-inp:focus{border-color:var(--tz-ring); box-shadow:0 0 0 3px rgba(161,161,170,.15);}
  /* Apilados, no en fila: el riel mide 252px y un <input type="date"> tiene un
     ancho mínimo propio del navegador (~120px) que no entra dos veces ahí —
     puestos en fila se desbordaban y se pegaban con la tabla de al lado. */
  .tz-datepair{display:flex; flex-direction:column; gap:8px;}
  .tz-datepair .tz-inp{width:100%;}
  .tz-datepair span{font-size:10.5px; color:var(--tz-muted-fg); display:block; margin:0 0 -3px 1px;}
  .tz-btn{font:inherit; font-size:13px; font-weight:500; border-radius:calc(var(--tz-r) - 4px); padding:8px 13px; cursor:pointer; border:1px solid var(--tz-border); background:var(--tz-card); color:var(--tz-fg); display:inline-flex; align-items:center; justify-content:center; gap:6px; width:100%;}
  .tz-btn:hover{background:var(--tz-muted);}
  .tz-btn.ghost{border-color:transparent; color:var(--tz-muted-fg);}
  .tz-btn svg{width:14px; height:14px; flex:0 0 auto;}
  .tz-rail-card .hint{margin:10px 0 0; font-size:11.5px; color:var(--tz-muted-fg); line-height:1.5;}
  .tz-rail-card .hint b{color:var(--tz-fg); font-weight:500;}

  .tz-main{min-width:0;}
  .tz-stats{display:grid; grid-template-columns:repeat(4,1fr); gap:14px; margin-bottom:22px;}
  @media (max-width:1180px){ .tz-stats{grid-template-columns:repeat(2,1fr);} }
  /* Dos columnas de ~170px dejaban las cifras de la bitácora partidas en tres
     renglones. Trazabilidad era el único módulo con peso en esta hoja sin
     ninguna regla por debajo de 900px. */
  @media (max-width:480px){ .tz-stats{grid-template-columns:1fr; gap:10px;} }
  .tz-stat{border:1px solid var(--tz-border); border-radius:var(--tz-r); padding:16px 18px; background:var(--tz-card);}
  .tz-stat .l{font-size:12px; color:var(--tz-muted-fg); font-weight:500;}
  .tz-stat .v{font-family:'Geist Mono',monospace; font-size:27px; font-weight:500; margin-top:6px; letter-spacing:-.01em;}
  .tz-stat .d{font-size:11.5px; color:var(--tz-muted-fg); margin-top:3px;}

  .tz-tblcard{background:var(--tz-card); border:1px solid var(--tz-border); border-radius:var(--tz-r); overflow:hidden;}
  .tz-tbl-h{display:flex; align-items:center; gap:10px; padding:13px 16px; border-bottom:1px solid var(--tz-border);}
  .tz-tbl-h .t{font-size:13.5px; font-weight:600;}
  .tz-tbl-h .spacer{flex:1 1 auto;}
  /* Las 6 columnas (Cuándo/Quién/Qué/Sobre qué/Detalle/IP) no caben en el ancho
     de un teléfono; sin esto, el overflow:hidden de .tz-tblcard (necesario para
     que las esquinas redondeadas del encabezado/pie no se corten) se comía en
     silencio las columnas de la derecha en vez de dejarlas deslizar. */
  #tzTblCont{overflow-x:auto;}

  .tz-shell table{width:100%; border-collapse:collapse; font-size:13px;}
  .tz-shell thead tr{border-bottom:1px solid var(--tz-border);}
  .tz-shell th{text-align:left; padding:9px 16px; font-size:11px; font-weight:500; color:#fff; text-transform:uppercase; letter-spacing:.05em; background:var(--navy2);}
  .tz-shell tbody tr{border-bottom:1px solid var(--tz-border);}
  .tz-shell tbody tr:last-child{border-bottom:none;}
  .tz-shell tbody tr:hover{background:var(--tz-muted);}
  .tz-shell td{padding:13px 16px; vertical-align:middle;}

  .tz-who .nombre{font-weight:500; font-size:13px;}
  .tz-who .correo{color:var(--tz-muted-fg); font-size:11.5px; margin-top:1px;}

  .tz-sobre .tipo{color:var(--tz-muted-fg);}
  .tz-sobre .tz-id{cursor:default; border-bottom:1px dotted var(--tz-border);}
  .tz-nota{color:var(--tz-muted-fg); font-size:12.5px;}

  .tz-foot{padding:11px 16px; border-top:1px solid var(--tz-border); display:flex; align-items:center; gap:8px; color:var(--tz-muted-fg); font-size:12px; background:var(--tz-muted);}
  .tz-foot svg{width:14px; height:14px; flex:0 0 auto;}

  /* ---- DataTables dentro de Trazabilidad ----
     Misma idea que .pv-tabla en Contratos suscritos (arriba, ~línea 2695): la
     tabla en sí ya hereda el aspecto de .tz-shell table/th/td de arriba —lo que
     falta vestir es lo que DataTables agrega alrededor (selector de filas por
     página, contador, paginador), que por defecto trae su propio look y
     desentonaría con el resto de la "isla" zinc/Geist.
     Todo cuelga de #tzTblCont (el contenedor real), no de la clase .tz-tblcard:
     la propia hoja de DataTables (vendor/dataTables-2.1.8.min.css) define el
     paginador con selectores tipo "div.dt-container .dt-paging .dt-paging-
     button.current" —un tipo más que una clase sola—, así que con solo clases
     de este lado esas reglas seguían ganando pese a cargar después. El id
     sube la especificidad por encima de eso sin pelear regla por regla. El
     color del botón sí lo fuerza la propia hoja con !important —ahí no hay
     otra forma de ganarle que repetir el !important de este lado. */
  #tzTblCont .dt-container,
  #papTblCont .dt-container{font-size:12px; color:var(--tz-muted-fg);}
  #tzTblCont .dt-layout-row,
  #papTblCont .dt-layout-row{align-items:center; padding:10px 16px;}
  #tzTblCont .dt-layout-row:has(.dt-length),
  #papTblCont .dt-layout-row:has(.dt-length){border-bottom:1px solid var(--tz-border); background:var(--tz-muted);}
  #tzTblCont .dt-layout-row:has(.dt-paging),
  #papTblCont .dt-layout-row:has(.dt-paging),
  #tzTblCont .dt-layout-row:has(.dt-info),
  #papTblCont .dt-layout-row:has(.dt-info){border-top:1px solid var(--tz-border);}
  #tzTblCont .dt-info,
  #papTblCont .dt-info{font-size:11.5px; color:var(--tz-muted-fg);}
  #tzTblCont .dt-length label,
  #papTblCont .dt-length label{font-size:11.5px; color:var(--tz-muted-fg); display:flex; align-items:center; gap:6px;}
  #tzTblCont .dt-length select,
  #papTblCont .dt-length select{border:1px solid var(--tz-input); border-radius:calc(var(--tz-r) - 5px); padding:3px 6px; background:var(--tz-card); color:var(--tz-fg); font-family:inherit; font-size:11.5px;}
  #tzTblCont .dt-paging .dt-paging-button,
  #papTblCont .dt-paging .dt-paging-button{font-family:inherit; font-size:11.5px; font-weight:500; color:var(--tz-muted-fg) !important; border:1px solid transparent; border-radius:calc(var(--tz-r) - 5px); padding:4px 9px; margin-left:2px; cursor:pointer; background:transparent;}
  #tzTblCont .dt-paging .dt-paging-button:hover,
  #papTblCont .dt-paging .dt-paging-button:hover{background:var(--tz-muted); color:var(--tz-fg) !important; border-color:var(--tz-border);}
  #tzTblCont .dt-paging .dt-paging-button.current,
  #papTblCont .dt-paging .dt-paging-button.current{background:var(--navy2); color:#fff !important; border-color:var(--navy2);}
  #tzTblCont .dt-paging .dt-paging-button.current:hover,
  #papTblCont .dt-paging .dt-paging-button.current:hover{background:var(--navy); color:#fff !important; border-color:var(--navy);}
  #tzTblCont .dt-paging .dt-paging-button.disabled,
  #papTblCont .dt-paging .dt-paging-button.disabled,
  #tzTblCont .dt-paging .dt-paging-button.disabled:hover,
  #papTblCont .dt-paging .dt-paging-button.disabled:hover{color:var(--tz-border) !important; background:transparent; border-color:transparent; cursor:default;}
  #tzTblCont table.dataTable thead th,
  #papTblCont table.dataTable thead th{cursor:pointer;}
  /* Encabezado sólido en azul de marca (arriba, .tz-shell th) — a partir de
     ahí ya no hace falta la flechita de orden para que se note que la fila es
     clicable, y se quita a pedido. padding-right vuelve al valor normal: las
     clases dt-orderable y dt-ordering reservan 30px a la derecha del título
     (vendor/dataTables-2.1.8.min.css) para dibujarla; sin ícono, ese hueco se
     veía como espacio muerto. */
  #tzTblCont table.dataTable thead th .dt-column-order,
  #papTblCont table.dataTable thead th .dt-column-order{display:none;}
  #tzTblCont table.dataTable thead th.dt-orderable-asc,
  #papTblCont table.dataTable thead th.dt-orderable-asc,
  #tzTblCont table.dataTable thead th.dt-orderable-desc,
  #papTblCont table.dataTable thead th.dt-orderable-desc,
  #tzTblCont table.dataTable thead th.dt-ordering-asc,
  #papTblCont table.dataTable thead th.dt-ordering-asc,
  #tzTblCont table.dataTable thead th.dt-ordering-desc,
  #papTblCont table.dataTable thead th.dt-ordering-desc{padding-right:16px;}

  .tz-notaproc{margin-top:20px; padding:15px 18px; border:1px solid var(--tz-border); border-radius:var(--tz-r); background:var(--tz-card); font-size:12.5px; color:var(--tz-muted-fg); line-height:1.6; display:flex; gap:10px; align-items:flex-start;}
  .tz-notaproc svg{width:16px; height:16px; flex:0 0 auto; margin-top:1px; color:var(--tz-muted-fg);}
  .tz-notaproc b{color:var(--tz-fg);}

  /* ===================== PAPELERA =====================
     Toma prestado el armazón entero de Trazabilidad (.tz-shell y sus tokens):
     son la misma clase de pantalla —un registro que se consulta y se filtra—
     y se pidió expresamente que se parecieran. Aquí solo van las tres piezas
     que Trazabilidad no tiene, porque no tiene acciones: la celda de qué se
     eliminó (dos renglones), el plazo y el botón de restaurar. */
  /* La fecha, en una sola línea: "2/9 · 05:26 p. m." partido en dos renglones
     estiraba la fila al alto de dos líneas en TODA la tabla, y de paso le
     quitaba ancho a la columna que de verdad lo necesita (qué se eliminó). */
  .pap-shell .pap-cuando{color:var(--tz-muted-fg); font-size:12.5px; white-space:nowrap;}
  .pap-shell .pap-que{min-width:200px;}
  .pap-shell .pap-que .n{font-weight:500; font-size:13px; color:var(--tz-fg);}
  .pap-shell .pap-que .m{color:var(--tz-muted-fg); font-size:11.5px; margin-top:1px;}
  /* El plazo, en texto y no en pastilla: al lado ya está el tipo, y dos
     pastillas seguidas se leen como dos etiquetas de lo mismo. El color solo
     aparece cuando dice algo —quedan dos días o menos, ya venció, ya se
     restauró—; pintar los diez días dejaría de distinguir el que corre prisa. */
  .pap-shell .pap-plazo{font-size:12.5px; color:var(--tz-muted-fg); white-space:nowrap;}
  .pap-shell .pap-plazo.urge{color:var(--tz-destructive); font-weight:500;}
  .pap-shell .pap-plazo.out{color:var(--tz-muted-fg); font-style:italic;}
  .pap-shell .pap-plazo.ok{color:var(--good);}
  .pap-shell .pap-btn{font:inherit; font-size:12px; font-weight:500; white-space:nowrap;
    border:1px solid var(--tz-border); background:var(--tz-card); color:var(--tz-fg);
    border-radius:calc(var(--tz-r) - 5px); padding:5px 11px; cursor:pointer;}
  .pap-shell .pap-btn:hover{background:var(--navy2); border-color:var(--navy2); color:#fff;}
  /* .op-link viene del resto de Atlas (azul de marca) y aquí, sobre el fondo
     zinc, se veía como un enlace pegado de otra pantalla. */
  .pap-shell .op-link{font-size:12px; color:var(--tz-muted-fg); font-weight:500;}
  .pap-shell .op-link:hover{color:var(--tz-fg);}

  .footnote{text-align:center; font-size:10.5px; color:var(--gray-soft); padding:22px 0 4px; grid-column:span 12;}

  /* ---- activo / oportunidad ---- */
  .pc-photo{height:118px; margin:-15px -16px 11px; border-radius:10px 10px 0 0; background-size:cover; background-position:center;}
  .fc-photo{height:106px; margin:-16px -17px 11px; border-radius:10px 10px 0 0; background-size:cover; background-position:center;}
  .pc-ops{margin-top:9px; font-size:10.5px; font-weight:700; color:var(--navy2);}
  .pc-stage.prom{background:var(--good-bg); color:var(--good);}
  .chip.prom{background:var(--good-bg); color:var(--good);}
  .kdot.d{background:var(--navy);}
  .kdot.prom{background:var(--good);}
  .fst.prom{background:#F0F9F1; border-color:#CFE9D9;} .fst.prom .fc{color:var(--good);}
  .arr.big{flex:0 0 30px; font-size:18px; color:var(--navy2);}
  .kanban.k2{grid-template-columns:repeat(2,1fr);}
  .kanban.k3{grid-template-columns:repeat(3,1fr);}
  .kanban.k5{grid-template-columns:repeat(5,1fr);}

  /* ---------- Línea de producción: las dos pistas, una sola cadena ----------
     Las cinco columnas van en UNA rejilla, no en dos cajas separadas: el
     activo madura su data en las dos primeras y sale estructurado como
     oportunidad en las tres siguientes, y la costura del medio es el punto
     donde eso pasa. Los rótulos van encima de sus columnas (span 2 y span 3)
     y no encima de dos recuadros distintos.

     El salto del medio no es una pieza nueva: es .arr.big, la misma flecha con
     la que la Guía marca el paso de activo a oportunidad en esta cadena. Por
     eso la columna mide sus mismos 30px. */
  .klinea-h, .klinea-cols{display:grid; grid-template-columns:repeat(2,1fr) 30px repeat(3,1fr); gap:14px;}
  .klinea-h{margin-bottom:9px; align-items:end;}
  .klh{font-size:9.5px; font-weight:800; letter-spacing:.01em; color:var(--gray-soft);}
  .klh.act{grid-column:span 2;}
  .klh.opo{grid-column:span 3;}
  .klinea-pie{margin-top:11px; font-size:10px; color:var(--gray-soft);}
  /* Que el título de la columna pueda encogerse en vez de estirarla: sin esto
     un nombre largo ensancha la columna y descuadra la rejilla. */
  .khead > div{min-width:0;}
  /* La cifra de una tarjeta va en una línea (por eso .kc-amt es nowrap), pero
     si no cabe tiene que partirse antes que salirse de la tarjeta: aquí las
     columnas son estrechas y un potencial mal cargado —"US$ 100.000.000 M"—
     se desbordaba por encima de la tarjeta de al lado. */
  .klinea .kc-amt{white-space:normal; overflow-wrap:anywhere;}
  /* Cada columna se desplaza por su cuenta en vez de estirar toda la página
     por la más larga. Acotado a este módulo para no afectar los otros kanban
     que reusan .kbody en proyectos/seguimiento/oficios/contrapartes. */
  .klinea .kbody{max-height:460px; overflow-y:auto; padding-right:6px;}
  .klinea .kbody::-webkit-scrollbar{width:6px;}
  .klinea .kbody::-webkit-scrollbar-thumb{background:var(--line); border-radius:8px;}
  /* Al señalar una tarjeta se enciende su correspondencia en la otra pista y
     se atenúa el resto: es lo que responde "esta oportunidad, ¿de qué activo
     salió?" sin tener que leer tarjeta por tarjeta.
     La encendida usa el par de .enteli.on / .stat.clic.on —el azul de
     selección real de una TARJETA en Atlas— y no un realce propio; el resto se
     apaga con la misma opacidad que .pz-li.off y .col-lg span.off. */
  .klinea.vinculando .kcard{opacity:.4;}
  .klinea.vinculando .kcard.rel{opacity:1; background:#EEF5FC; border-color:#CFE0F0;}
  .d-photo{position:relative; height:200px; border-radius:10px; background-size:cover; background-position:center; margin-bottom:15px;}
  .d-photo .cred{position:absolute; right:10px; bottom:8px; font-size:8.5px; color:rgba(255,255,255,.85); text-shadow:0 1px 3px rgba(0,0,0,.6);}
  .opmini{border:1px solid var(--line); border-radius:10px; padding:13px 14px; margin-top:9px; background:var(--bg);}
  .opmini .fc-rows{display:flex; flex-direction:column; gap:5px;}
  .opmini .fc-row{display:flex; gap:8px; font-size:11px;}
  .opmini .fc-row .k{color:var(--gray-soft); font-weight:700; min-width:76px; flex:0 0 auto;}
  .opmini .fc-row .v{color:var(--ink);}

  /* ---- hoja de activo (rediseño) ---- */
  .a-hero{grid-column:1/-1; background:var(--bg); border-bottom:1px solid var(--line); margin:-20px -22px 0; padding:13px 32px 11px;}
  /* ---- cabecera en dos columnas: quién es a la izquierda, qué apremia a la derecha ----
     La derecha se dimensiona en px y no en fracción: con una fracción, los contratos de nombre
     largo —"Sal de Araya (CORPOSUCRE / Salinas / Puertos)"— cedían ancho al bloque de urgencia
     en vez de al revés. Medido sobre las tres fichas de la maqueta, la cabecera pasa de 101px a
     110–120px y el ancho sin usar cae del 54–65% al 2%. */
  .a-hfila{display:flex; align-items:flex-start; gap:22px;}
  .a-hizq{min-width:0; flex:1 1 auto;}
  .a-hder{flex:0 0 264px; display:flex; flex-direction:column; align-items:flex-end; gap:7px;}
  .a-hck{display:flex; align-items:baseline; gap:8px;}
  .a-hck .d{font-size:26px; font-weight:800; letter-spacing:-.02em; line-height:1; color:var(--ink);
            font-variant-numeric:tabular-nums;}
  .a-hck .d i{font-size:15px; font-style:normal;}
  .a-hck .t{font-size:11px; font-weight:700; color:var(--gray);}
  .a-hck.rust .d{color:var(--rust);}  .a-hck.warn .d{color:var(--amber);}
  .a-hck.good .d{color:#1E7F5C;}
  .a-hck.mute .d{color:var(--gray-soft); font-size:15px; font-weight:700;}
  /* Misma barra y misma escala que .kc-ret-tr (Kanban) y .tck (tabla): llena significa lo mismo
     en las tres vistas. La marca es la cadencia objetivo. */
  .a-hbar{position:relative; width:100%; height:5px; border-radius:5px; background:var(--line-soft);
          overflow:hidden;}
  .a-hbar i{display:block; height:100%; width:var(--p); border-radius:5px;}
  .a-hbar::after{content:''; position:absolute; top:-1px; bottom:-1px; left:var(--meta); width:1px;
                 background:rgba(20,30,50,.35);}
  .a-hsub{font-size:10.5px; color:var(--gray-soft); text-align:right; line-height:1.45;}
  .a-hder .btn{margin-top:2px;}
  /* El bloque de urgencia debajo del título cuando no hay ancho para las dos columnas: apilado
     y alineado a la izquierda, que es como se lee el resto de la cabecera. */
  @media (max-width:900px){
    .a-hfila{flex-direction:column; gap:12px;}
    .a-hder{flex:1 1 auto; align-self:stretch; align-items:flex-start;}
    .a-hsub{text-align:left;}
  }
  .bk{display:inline-block; font-size:12px; font-weight:600; color:var(--navy2); cursor:pointer;}
  /* La variante sólida: el camino de vuelta con el azul de la casa detrás. Un
     enlace azul sobre fondo claro se confunde con los demás enlaces de la
     pantalla —y en Inversionistas hay uno en cada dato—, mientras que volver
     es la única acción de navegación que hay ahí arriba.
     Modificador y no cambio de .bk: esa clase la usan nueve pantallas más y
     ahí el enlace suelto sigue siendo lo que corresponde. */
  .bk-navy{background:var(--navy); color:#fff; border-radius:6px; padding:3px 9px; font-size:10.5px;}
  /* La barra de filtros de Inversionistas, dentro de la misma tarjeta del
     buscador: .sg-toolbar deja 14px por debajo para separarse de lo que sigue,
     y aquí lo que sigue es el borde de la tarjeta —esos 14px eran aire muerto
     que engordaba la barra entera—.
     Con las dos clases y no solo con .inv-barra: .sg-toolbar se declara más
     abajo en la hoja, así que a igual peso ganaba ella. */
  /* ---- el buscador de Inversionistas y su banda de filtros ----
     Son dos niveles y tienen que verse como dos. Antes iban a nueve píxeles
     uno de otro dentro de la misma tarjeta, y como las dos filas son pastillas
     grises sobre blanco, las seis se leían como un solo bloque de controles
     del mismo rango: no se sabía cuál manda sobre cuál.

     Arriba, lo que decide QUÉ lista se mira: buscar, y en qué forma verla.
     Debajo, tras una línea, lo que la recorta. La línea es lo que hace el
     trabajo —una separación de aire no basta cuando las dos filas pesan
     igual— y los filtros van un punto más pequeños para que se lean como lo
     que son: un segundo nivel. */
  .inv-buscador{padding:0;}
  .inv-buscador-fila{align-items:center; margin:0; padding:11px 16px;}
  /* Los filtros, en su propia tarjeta. Estuvieron dentro de la del buscador,
     separados por una línea de --line-soft: correcto sobre el papel e
     invisible en pantalla, así que las seis pastillas seguían leyéndose como
     una fila partida. Dos superficies con el hueco de la rejilla entre ellas
     se distinguen sin que nadie tenga que fijarse.
     Más baja que la de arriba y con fondo apenas frío: es el segundo nivel, y
     tiene que pesar menos que el buscador aunque sea una tarjeta igual. */
  .card.inv-filtros{padding:0; background:#FAFCFF;}
  .sg-toolbar.inv-barra{margin-bottom:0; padding:10px 16px;}
  /* La de Seguimiento, por lo mismo y en la misma tarjeta que su buscador.
     Y align-items:center porque aquí los controles son .segsel —una sola
     pastilla, sin rótulo encima—: el flex-end de .sg-toolbar existe para
     alinear por el pie campos que sí lo llevan, y con pastillas dejaba el
     botón de quitar filtros medio píxel bajo respecto a ellas. */
  .sg-toolbar.sg-barra{margin-bottom:0; align-items:center;}
  .bk-navy:hover{background:var(--navy-deep);}
  /* La cabecera vive con márgenes negativos y un relleno mayor que el de la
     rejilla, así que su contenido cae 10px a la derecha del borde de las dos
     columnas. Con el enlace de vuelta ya pintado como pastilla ese desfase se
     ve —dos bloques azules casi en la misma vertical, uno un dedo corrido—, y
     el enlace se devuelve al borde. El título de debajo se queda donde está:
     él sí encabeza el contenido de la cabecera. */
  .a-hero .bk-navy{margin-left:-10px; margin-bottom:10px;}
  .a-hero .bk{margin-bottom:6px;}
  .a-h2{display:flex; align-items:baseline; gap:11px; flex-wrap:wrap;}
  .a-h2 h1{font-size:20px; font-weight:700; letter-spacing:-.02em; color:#0B1526;}
  .a-etapa{font-size:11px; font-weight:600; color:var(--navy); background:var(--block); border:1px solid var(--line); border-radius:20px; padding:3px 10px; white-space:nowrap;}
  .a-emb{font-size:11px; font-weight:600; color:var(--navy); white-space:nowrap;}
  .a-apex{margin-left:auto; text-align:right;}
  .a-apex .top{display:flex; align-items:baseline; gap:8px; justify-content:flex-end;}
  .a-apex .lbl{font-size:10px; font-weight:700; letter-spacing:.01em; color:#8892A0;}
  .a-apex .val{font-size:19px; font-weight:700; color:var(--navy); letter-spacing:-.02em; line-height:1.15;}
  .a-apex .base{font-size:10.5px; color:#8892A0; margin-top:1px;}
  /* ---- la cabecera del activo, en dos columnas ----
     Con nombre propio (act-) y no .a-hizq/.a-hder: esos ya existen, son de la
     cabecera de un contrato (.a-hfila) y traen flex-direction:column. Reusarlos
     dejaba el potencial encima del recorrido por herencia y, peor, filtraba
     estas medidas a una ficha que no las pidió.
     Solo la del activo: las demás —oportunidad, contrato, institución— siguen
     con su meta bajo el título, y ahí la fila de abajo sí tiene qué llevar.
     Las dos columnas se centran entre sí, que es lo que baja el título: la
     izquierda trae una línea y la derecha una fila, y alineadas por arriba el
     título quedaba pegado al borde con un palmo de blanco debajo. */
  /* El título de un bloque de la hoja técnica: fuera de su tarjeta, pero en la
     misma vertical que el primer campo. Los 28px son el relleno de la tarjeta
     (18) más el de la celda (10); si alguno cambia, se cambia aquí. */
  .act-sec{margin-top:18px; padding-left:28px;}
  /* La ayuda bajo el campo de inversionista: cuántos hay y que se filtra
     escribiendo. Va debajo y no como placeholder, que desaparece al teclear —
     justo cuando la pista sirve. */
  .act-ayuda{font-size:11px; color:var(--gray); margin-top:5px;}
  /* Las secciones de Documentos van más juntas que las de la hoja técnica: allá
     cada bloque es una tabla de campos que se lee de arriba abajo, y aquí es una
     lista corta —a veces de un solo renglón—, así que el aire de 18px entre una
     y otra dejaba la pestaña llena de huecos. */
  .act-doc-sec{margin-top:14px;}
  .act-doc-card{margin-top:6px;}
  .act-doc-vacio{padding:11px 18px; font-size:13px; color:var(--ink);}
  /* ---- mover un documento arrastrándolo ----
     La fila agarrable lo dice con el cursor y, al empezar a arrastrar, se
     desvanece para que se vea que va en camino. */
  .act-doc-mueve{cursor:grab;}
  .act-doc-mueve:active{cursor:grabbing;}
  .act-doc-mueve[draggable="true"]:hover{background:var(--block);}
  /* La zona de destino se marca cuando el documento está encima, no con un
     borde permanente: seis recuadros punteados a la vez serían la pestaña
     entera pidiendo atención. */
  .act-doc-card.sobre{outline:2px dashed var(--navy2); outline-offset:-2px; background:#F2F7FD;}
  /* Las secciones vacías que se esconden reaparecen mientras dura el arrastre:
     si "Otros" no se ve por estar vacío, devolverle un documento sería
     imposible. */
  .act-doc-oculta{display:none;}
  .act-arrastrando .act-doc-oculta{display:block;}
  /* Eliminar: al final de la fila, discreto pero PRESENTE. Estaba en opacity:0
     y solo asomaba al pasar por encima de la fila, así que para quien no lo
     supiera de antes sencillamente no existía: se pedía "que se puedan borrar
     los documentos" de una pestaña que ya sabía borrarlos.
     Apagado en reposo (.38) y encendido al pasar por la fila: sigue sin
     competir con abrir, que es la acción normal, pero se ve que está. */
  .act-doc-x{margin-left:auto; flex:0 0 auto; width:24px; height:24px; display:flex;
    align-items:center; justify-content:center; border-radius:6px; font-size:13px;
    color:var(--gray-soft); opacity:.38; transition:opacity .12s, background .12s, color .12s;}
  .doc44:hover .act-doc-x{opacity:1;}
  .act-doc-x:hover{background:var(--rust-bg); color:var(--rust); opacity:1;}
  @media (hover:none){ .act-doc-x{opacity:1;} }
  /* ---- la ficha del activo: sin grises apagados y sin insignias ----
     Todo bajo .act-ficha / .act-hizq, que solo lleva esta ficha: las demás
     —oportunidad, contrato, institución— comparten .kvp, .a-sec y .mute y no
     pidieron este cambio.

     EL TÍTULO EN EL AZUL DE LA CASA. Era casi negro y se confundía con el resto
     del texto de la cabecera; el navy lo separa como lo que es, el nombre de lo
     que se está mirando. */
  .act-hizq .a-h2 h1{color:var(--navy);}
  /* La disponibilidad, en el rojo de la casa y sin caja: una insignia al lado
     del título competía con él por la mirada. */
  .act-off{font-size:12.5px; font-weight:700; color:var(--rust); white-space:nowrap;}
  /* NADA EN GRIS APAGADO. "Sin registrar", "Sin asignar" y el código del activo
     iban en el gris que Atlas usa para lo deshabilitado, y en una ficha donde
     todo se edita eso se lee como "esto no se toca" — justo al revés de lo que
     son: los huecos que hay que llenar. En negro normal, y lo que los distingue
     de un dato escrito es lo que dicen, no lo pálidos que están. */
  .act-ficha .mute, .act-ficha .kvp .v .mute{color:var(--ink); font-weight:400;}
  .act-ficha .a-cod{color:var(--ink);}
  /* En negro basta: la negrita de más hacía que cada rótulo pesara tanto como su
     dato y la columna se leía a dos voces. */
  .act-ficha .kvp .k{font-weight:600;}
  .act-sec .t, .act-ficha .a-sec .t{font-weight:700;}
  /* La nota al pie de la hoja técnica explica cómo se edita: es instrucción, no
     letra chica. */
  .act-ficha .sg-note{color:var(--gray);}
  /* ---- lo editable se ve editable ----
     El doble clic no se descubre solo: sin nada que lo anuncie, la ficha parece
     de lectura y nadie prueba. Un fondo gris muy leve —el mismo .block del
     resto de los campos de Atlas— dice "aquí se escribe" sin llenar la pantalla
     de bordes ni de lapicitos. Al pasar por encima se afirma, y el cursor de
     texto remata la promesa.
     Sobre las filas de la hoja técnica el fondo se recorta al valor y no a la
     celda entera, para que la columna de la izquierda —el nombre del campo, que
     no se edita— siga leyéndose como rótulo. */
  .act-ed{background:var(--block); border:1px solid transparent; border-radius:7px;
          padding:3px 8px; margin:0 -8px; transition:background .12s, border-color .12s;}
  .act-ed:hover{background:#E9EEF6; border-color:var(--line);}
  .act-ed:focus-visible{outline:2px solid var(--navy2); outline-offset:1px;}
  /* El título de la ficha es texto grande: con el fondo pegado se ve como una
     etiqueta, así que respira un poco más y se atenúa hasta que se le acerca. */
  h1.act-ed{display:inline-block; background:transparent; padding:4px 10px; margin:0 -10px;}
  h1.act-ed:hover{background:var(--block); border-color:var(--line);}
  .act-hcuerpo{display:flex; align-items:center; gap:24px; flex-wrap:wrap; margin-top:2px;}
  .act-hizq{flex:1 1 320px; min-width:0;}
  /* El potencial y el recorrido EN FILA, no apilados: apilados, la derecha mide
     dos bloques de alto y la banda queda tan gruesa como antes, solo que con el
     hueco movido de sitio. Uno al lado del otro, la derecha se alarga a lo
     ancho —espacio que sobra— y la cabecera adelgaza. */
  .act-hder{flex:0 0 auto; display:flex; flex-direction:row; align-items:center; gap:26px;}
  /* Dentro de su columna el apex ya no se empuja solo a la derecha: la columna
     entera está alineada ahí. */
  .act-hcuerpo .a-apex{margin-left:0; flex:0 0 auto;}
  /* En fila con el recorrido, el rótulo y la cifra no se parten en dos
     renglones: es una sola frase —"Potencial estimado US$ 414 M"— y partida
     hace crecer de nuevo el alto que esta fila vino a quitar. */
  .act-hcuerpo .a-apex .top{flex-wrap:nowrap; white-space:nowrap;}
  /* El recorrido, más ancho que los 240px de antes: es lo que se mira para
     saber en qué punto va el activo. */
  .act-hcuerpo .stepper{margin-left:0; width:320px;}
  /* En pantalla angosta se apilan, y la derecha se alinea a la izquierda como
     el resto: en una columna sola, el texto a la derecha se lee como si
     perteneciera a otra cosa. */
  @media (max-width:900px){
    .act-hder{flex:1 1 100%; flex-wrap:wrap; align-items:flex-start; gap:12px;}
    .act-hcuerpo .a-apex{text-align:left;}
    .act-hcuerpo .a-apex .top{justify-content:flex-start;}
    .act-hcuerpo .stepper{width:100%;}
  }
  .a-h3{display:flex; align-items:center; gap:24px; margin-top:5px; flex-wrap:wrap;}
  .a-meta{font-size:12.5px; color:#5A6472; line-height:1.4;}
  .a-meta a{color:var(--navy2); font-weight:600; cursor:pointer;}
  .a-meta a:hover{text-decoration:underline;}
  .stepper{margin-left:auto; width:240px; flex:0 0 auto;}
  .stp-line{display:flex; align-items:center; gap:4px; padding:0 2px;}
  .stp-dot{width:8px; height:8px; border-radius:50%; background:#fff; border:2px solid #D5DAE3; flex:0 0 auto;}
  .stp-dot.done{background:var(--navy); border-color:var(--navy);}
  .stp-dot.cur{background:var(--cyan); border-color:#BFE6FA; box-shadow:0 0 0 3px rgba(32,176,240,.18);}
  .stp-seg{flex:1 1 auto; height:2px; background:#D5DAE3;}
  .stp-seg.done{background:var(--navy);}
  .stp-labs{display:flex; justify-content:space-between; margin-top:6px;}
  .stp-lab{font-size:10px; font-weight:700; letter-spacing:.01em; color:#8892A0; line-height:1.35; flex:1 1 0;}
  .stp-lab.cur{color:var(--ink);}
  .stp-lab small{display:block; font-size:10px; font-weight:600; color:#8892A0; text-transform:none; letter-spacing:0;}
  .a-grid{display:grid; grid-template-columns:300px minmax(0,1fr); gap:26px 32px; align-items:start;}
  .a-main{min-width:0; display:flex; flex-direction:column; gap:20px;}
  /* Cruza las dos columnas. Para un párrafo largo la columna de 300px es la peor caja posible:
     lo parte en líneas de cuarenta caracteres y desequilibra la ficha —en la peor empresa la
     izquierda medía 749px contra 223px la derecha—. Al ancho completo se lee a ~110. */
  .a-grid > .a-wide{grid-column:1 / -1;}
  .a-card{background:var(--bg); border:1px solid var(--line); border-radius:10px;}
  .ph-tile{position:relative; height:180px; margin:-20px -20px 16px; border-radius:10px 10px 0 0; background-color:var(--block); background-size:cover; background-position:center; cursor:pointer; overflow:hidden;}
  .ph-tile .nfotos{position:absolute; right:10px; bottom:10px; background:rgba(10,20,40,.65); color:#fff; font-size:12px; font-weight:600; border-radius:6px; padding:3px 8px;}
  .ph-tile.empty{margin:0; height:160px; border-radius:10px; border:1px dashed #D5DAE3; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:6px; color:var(--gray-soft); font-size:13px; font-weight:600; cursor:default;}
  .ph-add{display:block; text-align:right; font-size:13px; font-weight:600; color:var(--navy2); margin:-8px 0 2px; cursor:pointer;}
  /* ---- el carrusel del rail ----
     Las flechas y los puntos van ENCIMA de la foto, no debajo: el rail es
     angosto y una fila de controles aparte le robaría alto a la imagen, que es
     lo único que aquí se viene a ver. Sobre foto no se puede confiar en el
     color, así que llevan su propia sombra oscura detrás para leerse igual
     sobre un cielo claro que sobre una nave en penumbra.
     En reposo se atenúan y al pasar el ratón por la foto se afirman: presentes
     cuando hacen falta, callados mientras se mira la imagen. En pantallas sin
     hover no hay "pasar por encima", así que ahí van siempre visibles. */
  .ph-nav{position:absolute; top:50%; transform:translateY(-50%); width:28px; height:28px;
          display:flex; align-items:center; justify-content:center; border-radius:50%;
          background:rgba(10,20,40,.55); color:#fff; font-size:18px; line-height:1; cursor:pointer;
          opacity:.55; transition:opacity .12s, background .12s; user-select:none;}
  .ph-nav.prev{left:8px;} .ph-nav.next{right:8px;}
  .ph-tile:hover .ph-nav{opacity:1;}
  .ph-nav:hover{background:rgba(10,20,40,.8);}
  .ph-dots{position:absolute; left:0; right:0; bottom:9px; display:flex; justify-content:center; gap:6px;}
  .ph-dots span{width:7px; height:7px; border-radius:50%; background:rgba(255,255,255,.5);
                box-shadow:0 0 0 1px rgba(10,20,40,.35); cursor:pointer; transition:background .12s;}
  .ph-dots span.on{background:#fff;}
  .ph-dots span:hover{background:#fff;}
  /* El contador sube para no chocar con los puntos, que ocupan el pie. */
  .ph-tile .nfotos{bottom:22px;}
  @media (hover:none){ .ph-nav{opacity:1;} }
  .a-resumen{font-size:15px; line-height:1.6; color:#2A3442;}
  .a-tesis{margin-top:12px; font-size:14px; font-weight:500; line-height:1.6; color:#1F2A3A;}
  .a-tesis .lab{font-size:11px; font-weight:800; letter-spacing:.01em; color:var(--navy); margin-right:8px;}
  .a-next{background:var(--block); border-radius:10px; padding:16px 20px; display:grid; grid-template-columns:minmax(0,1fr) auto; gap:18px; align-items:center; position:sticky; top:74px; z-index:6;}
  .a-next.one{grid-template-columns:1fr;}
  .a-next .lbl{font-size:11px; font-weight:800; letter-spacing:.01em; color:#5A6472; margin-bottom:7px;}
  /* respuesta del ente por revisar: la señal más accionable, se distingue de un pedido en curso */
  .a-next.review{background:#E8F6FE;}
  .a-next.review .lbl{color:var(--cyan-deep);}
  /* cabo suelto menor (esperando o sin pedir aún en un activo ya maduro): no debe competir en peso visual */
  .a-next.quiet{background:transparent; border:1px solid var(--line); padding:12px 18px;}
  .a-next.quiet .lbl{color:var(--gray-soft); font-weight:700;}
  .a-brecha{font-size:14px; color:#2A3442; line-height:1.55; padding:1px 0;}
  .a-brecha .st{font-size:13px; color:#8892A0;}
  .a-brecha-row{display:flex; align-items:flex-start; gap:9px; padding:3px 0; cursor:pointer;}
  .a-brecha-row input[type=checkbox]{margin-top:4px; flex:0 0 auto; width:15px; height:15px; accent-color:var(--navy);}
  .a-brecha-row .txt{font-size:14px; color:#2A3442; line-height:1.55;}
  .a-brecha-row .txt .st{font-size:13px; color:#8892A0;}
  .a-brecha-row.done .txt{color:#8892A0; text-decoration:line-through;}
  .a-brecha-add{display:flex; align-items:center; gap:8px; margin-top:9px;}
  .a-brecha-add input{flex:1 1 auto; min-width:0; font-size:13px; font-family:inherit; color:var(--ink); border:1px solid var(--line); border-radius:7px; padding:7px 10px; background:#fff;}
  .a-brecha-add input:focus{outline:none; border-color:#CDD5E1;}
  .btn.big{padding:9px 16px; font-size:13.5px; border-radius:8px;}
  /* flex-wrap: con cuatro controles —filtro, categorías, búsqueda y el botón de
     subir— la barra de Documentos se salía del ancho y el botón quedaba fuera
     de la pantalla. Envolviendo, baja a la línea siguiente en vez de perderse. */
  .a-sec{display:flex; align-items:center; gap:12px; flex-wrap:wrap;}
  /* En tinta y no en gris. Un título de sección gris claro sobre fondo blanco
     pesa menos que el dato que encabeza, así que la vista se leía como una
     lista de valores sueltos sin nadie que los agrupara. El tamaño se queda:
     lo que jerarquiza aquí es el peso y el color, no el cuerpo. */
  .a-sec .t{font-size:13px; font-weight:800; letter-spacing:.01em; color:var(--ink);}
  .a-sec .spacer{flex:1 1 auto;}
  /* Tres columnas, no cuatro: la cuarta era el enlace "Abrir la oportunidad →"
     y ahora abre la fila entera. Con la cuarta declarada, la fila repartía un
     hueco muerto en el borde derecho. */
  .op-row{display:grid; grid-template-columns:auto minmax(0,1fr) auto; gap:16px; align-items:center; padding:13px 20px;}
  /* Si toda la fila abre, toda la fila tiene que responder al pasar por encima:
     es lo que sustituye al enlace como señal de que ahí se puede pulsar. */
  .op-row[onclick]:hover{background:var(--block);}
  .op-row[onclick]:hover .op-nm{color:var(--navy2);}
  .op-badge{font-size:11.5px; font-weight:600; color:var(--gray); background:var(--block); border:1px solid var(--line); border-radius:20px; padding:4px 11px; white-space:nowrap; display:inline-flex; align-items:center; gap:6px;}
  .op-badge .dot{width:6px; height:6px; border-radius:50%; background:var(--cyan);}
  .op-nm{font-size:15px; font-weight:600; color:var(--ink); line-height:1.3;}
  .op-meta{font-size:13px; color:#8892A0; margin-top:2px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
  .op-amt{font-size:16px; font-weight:700; color:var(--navy); white-space:nowrap;}
  .op-link{font-size:13px; font-weight:600; color:var(--navy2); white-space:nowrap; cursor:pointer;}
  .doc44{display:flex; align-items:center; gap:12px; padding:12px 20px; border-bottom:1px solid var(--line-soft);}
  .doc44[onclick]:hover{background:var(--block);}
  .doc44[onclick]:hover .nm{color:var(--navy2);}
  .doc44:last-child{border-bottom:none;}
  .doc44 svg{width:20px; height:20px; flex:0 0 auto; stroke:#5A6472; fill:none; stroke-width:1.6; stroke-linecap:round; stroke-linejoin:round;}
  .doc44 .nm{font-size:14px; font-weight:500; color:var(--ink);}
  .doc44 .mt{font-size:12px; color:#8892A0;}
  .doc44 .op{margin-left:auto; font-size:13px; font-weight:600; color:var(--navy2); cursor:pointer; white-space:nowrap;}
  .a-rail{min-width:0; display:flex; flex-direction:column; gap:24px;}
  .a-rail.cp-sticky{position:sticky; top:calc(var(--tb) + 16px); align-self:start;}
  /* ---- columna de contenido con desplazamiento propio ----
     Modificador, no cambio de .a-main: esa clase la comparten siete vistas —activos,
     oportunidades, correspondencia, CRM, reuniones, contrapartes— y solo la ficha de contrato
     lo pide. Sin él, sus cinco tarjetas apiladas obligan a recorrer la página entera y el
     encabezado del expediente se pierde por arriba.
     Se acompaña de .cp-sticky en el rail: con la columna derecha quieta y la izquierda
     desplazándose fuera de vista, la mitad de la pantalla quedaría vacía.
     Por debajo de 1000px la rejilla pasa a una sola columna (más abajo en esta hoja), y ahí un
     scroll anidado sobra: el contenido ya va uno detrás de otro. */
  /* Pegajosa como el rail, no solo con tope de alto: acotada a secas, su final quedaba por
     debajo del borde inferior y había que seguir desplazando la página para llegar. Pegada, la
     página rueda hasta que las dos columnas llegan arriba y a partir de ahí solo rueda esta. */
  /* Sin scroll propio: la columna rueda con la página, como todo lo demás.
     Era pegajosa y acotada al alto de la ventana, así que dentro de una página
     que ya rodaba aparecía una segunda barra —la de la captura del contrato—.
     La clase se conserva porque de ella cuelga el pegado de las pestañas. */
  .a-main.a-scroll{padding-right:0;}
  .a-main.a-scroll::-webkit-scrollbar{width:9px;}
  .a-main.a-scroll::-webkit-scrollbar-thumb{background:var(--line); border-radius:9px;}
  /* Las pestañas se quedan arriba mientras el contenido rueda por debajo. Se pegan al
     contenedor que rueda —la propia columna—, no a la ventana, así que basta top:0.
     Fondo opaco y tirón lateral: sin ellos, las tarjetas se verían pasar por detrás de los
     rótulos y por los lados, donde el relleno de la columna deja aire.
     El z-index las pone por encima de las tarjetas, que no lo llevan. */
  /* Las pestañas se siguen quedando arriba, pero ahora respecto de la VENTANA
     y no de la columna: sin scroll propio, top:0 las habría dejado pegadas a un
     contenedor que ya no rueda por su cuenta. */
  .a-main.a-scroll > .tabbar{position:sticky; top:var(--tb); z-index:5; background:var(--block);
                             padding:2px 10px 0; margin-left:-10px; margin-right:-10px;}
  @media (max-width:1000px){
    .a-main.a-scroll{padding-right:0;}
  }
  .kvp{padding:16px 20px; display:flex; flex-direction:column; gap:14px;}
  .tl-item.nota .tl-dot{background:var(--amber); border-color:#F3DDB0; box-shadow:0 0 0 3px rgba(183,121,31,.15);}

  /* ---- proceso del motor de demanda como chevrons (flechas), no como línea de puntos ---- */
  /* Igual el rótulo de cada dato del rail: estaba en el gris más claro de la
     paleta (#8892A0), el mismo que Atlas usa para lo secundario y lo
     deshabilitado, y en una ficha donde ahora todo se edita el nombre del campo
     no es un adorno — es lo que dice qué se está por cambiar. */
  .kvp .k{font-size:11px; font-weight:800; letter-spacing:.01em; color:var(--ink); margin-bottom:2px;}
  .kvp .v{font-size:13.5px; font-weight:500; color:var(--ink); line-height:1.45;}
  .kvp .v a{color:var(--navy2); font-weight:600; cursor:pointer; font-size:12.5px; white-space:nowrap;}
  /* En la columna de la izquierda no hay 300px para un nombre en una sola
     línea: ahí el enlace parte, en vez de desbordarse fuera de la tarjeta.
     Vale igual para .op-link, que es un <span> y no un <a>: así se pinta el
     ente o el inversionista al que está vinculada una reunión, y con el
     nowrap heredado se salía de la tarjeta y se metía en los detalles. */
  .a-rail .kvp .v a,
  .a-rail .kvp .v .op-link{white-space:normal; overflow-wrap:anywhere;}
  .kvp .v .op-link{font-size:12.5px;}
  .lightbox{position:fixed; inset:0; background:rgba(10,20,40,.88); z-index:100; display:none; align-items:center; justify-content:center; flex-direction:column;}
  .lightbox.open{display:flex;}
  .lb-img{max-width:85vw; max-height:82vh; border-radius:6px;}
  /* Una imagen suelta —un logo, la foto de una persona— no es una fotografía a
     sangre: se enseña sobre blanco y con aire. Muchos logos son PNG con fondo
     transparente y sobre el azul oscuro del visor no se veían. */
  .lb-img.lb-suelta{background:#fff; padding:22px; max-width:min(560px,85vw); max-height:70vh;
    width:auto; height:auto; object-fit:contain; border-radius:10px;}
  .lb-cap{color:rgba(255,255,255,.85); font-size:13px; margin-top:12px; text-align:center; max-width:80vw;}
  .lb-x{position:absolute; top:16px; right:22px; color:#fff; font-size:24px; cursor:pointer; line-height:1; padding:6px;}
  .lb-add{position:absolute; top:18px; left:22px; color:rgba(255,255,255,.85); font-size:13px; font-weight:600; border:1px solid rgba(255,255,255,.4); border-radius:8px; padding:6px 12px; cursor:pointer;}
  .lb-nav{position:absolute; top:50%; transform:translateY(-50%); color:#fff; font-size:36px; cursor:pointer; padding:14px 18px; user-select:none;}
  .lb-prev{left:6px;} .lb-next{right:6px;}
  .lb-count{position:absolute; bottom:20px; color:rgba(255,255,255,.7); font-size:13px;}

  /* ---- guía y definiciones ---- */
  .g-intro{font-size:14px; line-height:1.65; color:#2A3442; max-width:860px;}
  .g-chain .fst{cursor:default;}
  .g-chain .fst:hover{border-color:var(--line);}
  .g-chain .fdef{font-size:10.5px; color:var(--gray); margin-top:5px; line-height:1.5;}
  .hw-row{display:flex; gap:14px; padding:13px 2px; border-bottom:1px solid var(--line-soft); align-items:flex-start;}
  .hw-row:last-child{border-bottom:none;}
  .hw-n{width:26px; height:26px; border-radius:50%; background:var(--navy); color:#fff; font-size:12px; font-weight:800; display:flex; align-items:center; justify-content:center; flex:0 0 auto; margin-top:1px;}
  .hw-t{font-size:13.5px; font-weight:700; color:var(--ink);}
  .hw-d{font-size:12.5px; color:#39414F; line-height:1.55; margin-top:2px;}
  .hw-d a{color:var(--navy2); font-weight:600; cursor:pointer;}
  .hw-d a:hover{text-decoration:underline;}
  table.tbl td.term{font-weight:700; color:var(--navy); width:190px; padding-right:14px; vertical-align:top;}

  /* --- Manual de uso, al final de Guía --- */
  .gm-sec{margin-top:18px;}
  .gm-sec:first-of-type{margin-top:6px;}
  .gm-sec-h{font-size:11px; font-weight:700; letter-spacing:.04em; text-transform:uppercase;
    color:var(--gray); padding-bottom:7px; border-bottom:1px solid var(--line); margin-bottom:2px;}
  .gm-sec-d{display:block; font-size:11.5px; font-weight:400; letter-spacing:0; text-transform:none;
    color:var(--gray-soft); margin-top:3px;}
  /* scroll-margin-top deja libre la barra superior cuando el módulo se lleva
     arriba al abrirlo: sin esto el título queda escondido debajo de ella */
  .gm-mod{border-bottom:1px solid var(--line-soft); scroll-margin-top:calc(var(--tb) + 12px);}
  .gm-mod:last-child{border-bottom:none;}
  .gm-t{display:flex; align-items:center; gap:9px; width:100%; padding:11px 2px; background:transparent;
    border:none; font-family:inherit; font-size:13.5px; font-weight:700; color:var(--ink);
    text-align:left; cursor:pointer;}
  .gm-t:hover{color:var(--navy2);}
  .gm-chev svg{width:13px; height:13px; fill:none; stroke:currentColor; stroke-width:2.4;
    stroke-linecap:round; stroke-linejoin:round; color:var(--gray-soft); transition:transform .16s;}
  .gm-mod.abierto .gm-chev svg{transform:rotate(90deg); color:var(--navy2);}
  /* plegado con altura fija en vez de display:none: así el navegador puede
     animar la apertura y el contenido sigue existiendo para buscar en la página */
  /* El "display:none" se acota al acordeón del manual: así esta misma
     tipografía —la de las instrucciones del sistema— se puede usar suelta en
     una pantalla que ya es de instrucciones, sin duplicar sus reglas ni
     inventarle un formato propio a cada una. */
  .gm-c{padding:2px 2px 18px 22px; max-width:900px;}
  .gm-mod .gm-c{display:none;}
  .gm-mod.abierto .gm-c{display:block;}
  .gm-c.suelto{padding:0; max-width:820px;}
  .gm-c img{width:100%; border:1px solid var(--line); border-radius:8px; display:block; margin-bottom:14px;}
  .gm-c p{font-size:13px; line-height:1.65; color:#2A3442; margin:0 0 9px;}
  .gm-c h3{font-size:13px; font-weight:700; color:var(--ink); margin:16px 0 6px;}
  .gm-c ul,.gm-c ol{margin:0 0 9px; padding-left:18px;}
  .gm-c li{font-size:13px; line-height:1.6; color:#2A3442; margin-bottom:4px;}
  .gm-c table{width:100%; border-collapse:collapse; margin:0 0 12px; font-size:12.5px;}
  .gm-c th{background:var(--block); text-align:left; font-weight:700; font-size:11.5px;
    padding:7px 9px; border-bottom:1px solid var(--line);}
  .gm-c td{padding:7px 9px; border-bottom:1px solid var(--line-soft); vertical-align:top; color:#39414F;}
  .gm-c blockquote{margin:0 0 12px; padding:10px 13px; background:var(--block);
    border-left:3px solid var(--navy2); border-radius:0 6px 6px 0;}
  .gm-c blockquote p{margin:0; font-size:12.5px;}
  .gm-c code{font-family:ui-monospace,Consolas,monospace; font-size:11.5px;
    background:var(--block); padding:1px 4px; border-radius:3px;}

  @media (max-width:1000px){
    .a-grid{grid-template-columns:1fr;}
    .a-rail.cp-sticky{position:static;}
    .stepper{margin-left:0;}
    .a-hero{padding:18px 22px 16px;}
    .a-next{position:static;}
  }

  /* ---- expediente (documentos) ---- */
  .doc-row{display:flex; align-items:center; gap:11px; padding:9px 2px; border-bottom:1px solid var(--line-soft);}
  .doc-row:last-child{border-bottom:none;}
  .doc-row:hover{background:var(--block); border-radius:7px;}
  .doc-ic{width:32px; height:32px; border-radius:7px; display:flex; align-items:center; justify-content:center; font-size:8.5px; font-weight:800; letter-spacing:.02em; flex:0 0 auto; background:#E9EFF7; color:var(--navy2);}
  .doc-ic.pdf{background:var(--rust-bg); color:var(--rust);}
  .doc-ic.xls{background:var(--good-bg); color:var(--good);}
  .doc-ic.img{background:var(--amber-bg); color:var(--amber);}
  .doc-n{font-size:12px; font-weight:600; color:var(--ink); line-height:1.3;}
  .doc-m{font-size:10px; color:var(--gray-soft); margin-top:1px;}
  .doc-act{margin-left:auto; font-size:10.5px; font-weight:700; color:var(--cyan-deep); white-space:nowrap; cursor:pointer;}

  /* ---- bitácora del activo ---- */
  .tl{position:relative; padding-left:20px; margin-top:4px;}
  .tl::before{content:""; position:absolute; left:5px; top:6px; bottom:6px; width:2px; background:var(--line);}
  .tl-item{position:relative; padding:0 0 18px;}
  .tl-item:last-child{padding-bottom:0;}
  .tl-dot{position:absolute; left:-20px; top:4px; width:11px; height:11px; border-radius:50%; background:var(--bg); border:2.5px solid var(--navy2);}
  .tl-item.hito .tl-dot{background:var(--cyan); border-color:#BFE6FA; box-shadow:0 0 0 3px rgba(32,176,240,.18);}
  .tl-item.pend .tl-dot{border-color:#C7CEDA;}
  .tl-t{font-size:14px; font-weight:700; color:var(--ink); line-height:1.4;}
  .tl-item.pend .tl-t{color:var(--gray-soft); font-weight:600;}
  .tl-d{font-size:13px; color:var(--gray); margin-top:3px; line-height:1.5;}
  .tl-f{font-size:11px; font-weight:800; color:var(--gray-soft); letter-spacing:.01em; margin-bottom:3px; font-variant-numeric:tabular-nums;}
  .tl-rel{display:inline-flex; align-items:center; gap:5px; margin-top:8px; font-size:12px; font-weight:600; color:var(--navy2); background:var(--block); border:1px solid var(--line); border-radius:6px; padding:4px 9px; cursor:pointer;}
  /* "Eliminar" de una anotación del historial: discreto y en el color de lo
     destructivo, como el de las filas del expediente. Va detrás de la pastilla
     "Nota de sesión" cuando la hay, y en su propia línea cuando no. */
  .tl-del{display:inline-block; margin-top:8px; font-size:12px; color:var(--rust);}
  .tl-rel + .tl-del, .tl-attachs + .tl-del{margin-left:10px;}
  .tl-attachs{display:flex; flex-wrap:wrap; gap:6px; margin-top:8px;}
  .tl-attachs .chip{cursor:pointer; max-width:220px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; display:inline-block;}

  /* La cadena son CINCO columnas, no dos ni tres: necesita más ancho que el
     resto de las rejillas, y por eso corta antes que ellas. Con el corte en
     1180px, entre 1180 y 1400 seguía pintándose la rejilla completa y cada
     columna quedaba en unos 160px — ahí el título se partía en tres líneas,
     el estado vacío caía a una palabra por renglón y una cifra larga se salía
     de la tarjeta. Partirla en dos filas rompería lo único que hace legible el
     tablero, que es el orden; así que se recorre deslizando, con la costura
     viajando en su sitio. Los rótulos de pista se retiran porque ahí ya no
     tienen columnas encima de las que estar: cada columna se nombra sola
     (ACT-A · Identificado, OPO-B · Lista para inversor) y el pie de abajo
     sigue explicando la relación. */
  @media (max-width:1400px){
    .klinea-h{display:none;}
    .klinea-cols{
      display:flex; gap:12px; align-items:flex-start;
      overflow-x:auto; -webkit-overflow-scrolling:touch;
      scroll-snap-type:x mandatory; scroll-padding-left:18px;
      margin-left:-18px; margin-right:-18px; padding:0 18px 8px;
    }
    .klinea-cols .kcol{flex:0 0 min(82%, 300px); scroll-snap-align:start;}
    /* .arr.big ya trae sus 30px; en el carril hay que estirarla, porque el
       align-items:flex-start de arriba la dejaría del alto de su glifo. */
    .klinea-cols .arr{align-self:stretch;}
  }
  @media (max-width:1180px){
    .stat-row{grid-template-columns:repeat(2,1fr);}
    .pgrid, .libgrid, .libgrid.two{grid-template-columns:repeat(2,1fr);}
    .kanban, .kanban.k2, .kanban.k3, .kanban.k5{grid-template-columns:repeat(2,1fr);}
    .klinea-cols .kcol{flex:0 0 min(82%, 300px); scroll-snap-align:start;}
    /* .arr.big ya trae sus 30px; en el carril hay que estirarla, porque el
       align-items:flex-start de arriba la dejaría del alto de su glifo. */
    .klinea-cols .arr{align-self:stretch;}
    .col7,.col6,.col5,.col8,.col4{grid-column:span 12;}
    .funnel{flex-wrap:wrap;} .funnel .fst{flex:1 1 40%;} .funnel .arr{display:none;}
  }
  @media (max-width:720px){
    .pgrid, .libgrid, .libgrid.two, .kanban, .kanban.k2, .kanban.k3, .kanban.k5, .stat-row{grid-template-columns:1fr;}
  }
  /* ---- menú "estructurar oportunidad": el origen es el primer paso del flujo ---- */
  .nuevo-op{position:relative; display:inline-block;}
  .opnew{position:absolute; top:calc(100% + 8px); right:0; width:300px; background:var(--bg); border:1px solid var(--line);
    border-radius:11px; box-shadow:0 8px 30px rgba(14,20,36,.16); padding:8px; z-index:50;
    opacity:0; visibility:hidden; transform:translateY(-6px); transition:opacity .15s ease, transform .15s ease;}
  .opnew.open{opacity:1; visibility:visible; transform:translateY(0);}
  .opnew-t{font-size:10px; font-weight:800; letter-spacing:.01em; color:var(--gray-soft); padding:7px 10px 6px;}
  .opnew-i{padding:9px 10px; border-radius:8px; cursor:pointer;}
  .opnew-i:hover{background:var(--block);}
  .opnew-i .oi-n{font-size:12.5px; font-weight:700; color:var(--ink);}
  .opnew-i .oi-d{font-size:11px; color:var(--gray); line-height:1.45; margin-top:1px;}

  /* ---- cockpit de cooperación por ente (directorio) ---- */
  .coop{margin-top:10px; padding:10px 12px; background:var(--block); border-radius:8px; display:flex; flex-direction:column; gap:6px;}
  .coop-row{display:flex; gap:10px; font-size:11.5px; line-height:1.5; align-items:baseline;}
  .coop-row .ck{flex:0 0 92px; font-size:9.5px; font-weight:800; letter-spacing:.01em; color:var(--gray-soft);}
  .coop-row .cv{color:#2A3442; min-width:0;}
  .coop-row .cv b{color:var(--ink);}
  .cok{color:var(--good); font-weight:600;}
  .cbad{color:var(--rust); font-weight:600;}
  .trm-det{margin-top:10px;}
  .trm-det summary{font-size:10px; font-weight:800; letter-spacing:.01em; color:var(--gray-soft); cursor:pointer; list-style:none;}
  .trm-det summary::before{content:"▸ ";}
  .trm-det[open] summary::before{content:"▾ ";}
  .trm-det .trmt{margin-top:4px;}

  .fcard.clickable{cursor:pointer; transition:border-color .12s ease, box-shadow .12s ease;}
  .fcard.clickable:hover{border-color:#CDD5E1; box-shadow:0 1px 2px rgba(14,20,36,.04), 0 6px 18px rgba(14,20,36,.06);}

  /* ---- hoja de oportunidad: filas de vínculos ---- */
  .vinc-row{display:flex; align-items:center; gap:12px; padding:12px 2px; border-bottom:1px solid var(--line-soft); cursor:pointer;}
  .vinc-row:last-child{border-bottom:none;}
  .vinc-row:hover .vr-n{color:var(--navy2);}
  .vr-n{font-size:13px; font-weight:700; color:var(--ink);}
  .vr-d{font-size:11.5px; color:var(--gray); margin-top:2px; line-height:1.45;}
  .vinc-row .op-link{margin-left:auto; white-space:nowrap;}

/* ================================================================
   MOBILE PATCH (breakpoint 860px) — pegar AL FINAL del <style>
   ================================================================ */

/* ---- Shell: hamburguesa y backdrop (base, fuera de media query) ---- */
.nav-btn{display:inline-flex; width:40px; height:40px; align-items:center; justify-content:center; background:transparent; border:none; color:#fff; border-radius:8px; cursor:pointer; padding:0; margin-left:-6px; flex:0 0 auto;}
.nav-btn:hover{background:rgba(255,255,255,.10);}
.nav-btn svg{display:block;}
.nav-backdrop{position:fixed; inset:0; background:rgba(14,20,36,.45); z-index:25; opacity:0; visibility:hidden; transition:opacity .2s ease, visibility .2s ease;}
body.nav-open .nav-backdrop{opacity:1; visibility:visible;}

/* ---- Tablas: patrón tscroll (única definición) ---- */
.tscroll{overflow-x:auto; -webkit-overflow-scrolling:touch; max-width:100%;}
.tscroll::-webkit-scrollbar{height:8px;}
.tscroll::-webkit-scrollbar-thumb{background:var(--line); border-radius:8px;}
.tscroll table.tbl-ofi{min-width:780px;}
.tscroll table.tbl-marco{min-width:720px;}

/* ---- vscroll: mismo criterio que tscroll (arriba) pero en vertical —
   cualquier módulo lo puede usar en una lista/panel que no debe alargar la
   página; se ajusta al alto de pantalla disponible. ---- */
/* overflow-x:auto además del vertical: Reuniones mete una tabla de min-width:640px
   ahí adentro, y sin esto se salía del .card en un teléfono sin ninguna forma de
   deslizar para verla — .tscroll (el wrapper horizontal del resto de la app) no
   sirve solo, porque .vscroll también necesita el tope de alto (65vh). */
/* Solo horizontal: la tabla mide 640px y en pantalla estrecha hay que correrla
   de lado. El tope vertical se retira — la lista rueda con la página. */
.vscroll{overflow-x:auto;}
.vscroll::-webkit-scrollbar{width:8px;}
.vscroll::-webkit-scrollbar-thumb{background:var(--line); border-radius:8px;}

/* ---- Detalle de activo: sustituye el inline text-align:right (par atómico con cambio #13) ---- */
.a-nextr{text-align:right;}

@media (max-width:860px){
  .modalcard.wide, .modalcard.xwide{max-width:none; width:100%;}
  .na-row2{grid-template-columns:1fr;}
  .na-cand{flex-direction:column;}
  .na-cand-fields{grid-template-columns:1fr; gap:6px;}
  /* ========== SHELL: drawer off-canvas ========== */
  .sidebar{transform:translateX(-100%); transition:transform .22s ease; will-change:transform;}
  body.nav-open .sidebar{transform:translateX(0); box-shadow:0 0 40px rgba(14,20,36,.35);}
  body.nav-open{overflow:hidden;}
  .main{margin-left:0;}
  .nav-btn{display:inline-flex;}
  .topbar{padding:0 12px; gap:10px;}
  .user .u-name{max-width:38vw; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  .content{padding:14px 14px 32px;}
  .grid{gap:12px;}
  .sb-item{padding:11px 12px; min-height:44px; font-size:13.5px;}
  /* En táctil el módulo sube a 13.5px, así que el rótulo sube con él: si se
     quedara en 11 se abriría otra vez el hueco que se acaba de cerrar. */
  .sb-sec-h{padding:11px 12px; min-height:40px; font-size:12px;}
  .sb-nav{padding:10px 12px 30px;}
  .sb-item.active::before{top:8px; bottom:8px;}

  /* ========== Headers de página ========== */
  .page-h .p-actions, .page-h2 .p-actions{margin-left:0; flex:1 1 100%;}
  /* Los botones se dimensionaban por su texto, así que «Cargar desde
     Correspondencia» salía ancho y «+ Nueva tarea» estrecho, en escalera y
     pegados a la izquierda. A lo ancho y uno debajo de otro se leen como lo
     que son —las cosas que se pueden hacer aquí— y se aciertan sin mirar. */
  .page-h .p-actions > .btn, .page-h2 .p-actions > .btn{flex:1 1 100%; justify-content:center;}
  .page-h h1{font-size:19px;}
  .page-h .p-sub{font-size:11.5px;}
  .p-actions .seg.hseg{width:100%; order:-1; overflow-x:auto; -webkit-overflow-scrolling:touch;}
  /* El scroll horizontal de arriba solo se activaba cuando el .seg.hseg vive
     dentro de un encabezado de página (.p-actions) — el de "Mapa" en
     Inteligencia no está ahí, y sus 4 pestañas (una con "Por materializarse",
     texto largo) se desbordaban sin poder deslizarse para verlas todas.
     Mismo tratamiento, sin exigir el ancestro. */
  .seg.hseg{overflow-x:auto; -webkit-overflow-scrolling:touch;}
  .hseg .segbtn{flex:1 1 0; text-align:center; padding:9px 8px; min-height:40px; display:flex; align-items:center; justify-content:center;}

  /* ========== Convención táctil global ========== */
  .btn{min-height:40px; display:inline-flex; align-items:center; padding:10px 14px;}
  .btn.sm{padding:9px 13px;}
  .segbtn{padding:10px 8px;} /* rail Por ente; .hseg .segbtn de arriba lo afina en headers */
  .fchip{display:inline-flex; align-items:center; min-height:40px; padding:8px 13px;}
  .fchip.fig{padding:7px 11px;}
  .ofi-doc{width:34px; height:34px;}
  .tabitem{flex:0 0 auto; padding:11px 13px; margin-bottom:0; min-height:44px;}
  .tabbar{flex-wrap:nowrap; overflow-x:auto; -webkit-overflow-scrolling:touch; scrollbar-width:none;
    padding-right:8px;}
  .tabbar::-webkit-scrollbar{display:none;}
  /* SE VE QUE HAY MÁS PESTAÑAS. La barra ya se deslizaba, pero sin barra de
     desplazamiento visible la última quedaba cortada a ras del borde y parecía
     rota, no continuada: «Esta se…» y nada que invitara a arrastrar.
     Se difumina el canto derecho con una máscara. Se probó antes la sombra de
     desplazamiento clásica —cuatro capas de fondo con background-attachment
     local y scroll, que aparece solo cuando queda algo por deslizar— y se
     descartó: exige que el color de las tapas case con el de la superficie, y
     esta barra vive sobre tres fondos distintos según el módulo (blanco en una
     tarjeta, gris en la ficha del activo, propio en .modulo). Acertar tres
     colores para un adorno es como se acumulan los desajustes.
     La máscara no mira el color: se limita a desvanecer lo que haya. Su pega
     es que también difumina al llegar al final del carril; si detrás no queda
     ninguna pestaña —barra corta— no se nota nada, porque no hay qué
     desvanecer. */
  .tabbar{
    -webkit-mask-image:linear-gradient(to right, #000 calc(100% - 26px), transparent);
            mask-image:linear-gradient(to right, #000 calc(100% - 26px), transparent);}

  /* ========== Filtros y buscadores (compartidos) ========== */
  .filters{row-gap:8px;}
  .fsearch{flex:1 1 100%; min-width:0;}
  /* EL ZOOM DE iOS lo dispara cualquier campo por debajo de 16px, y Safari no
     lo deshace al salir: la página se queda ampliada y hay que pellizcar para
     volver. Esta regla cubría .fsearch input y .field input, pero en el MISMO
     formulario el desplegable del sector y el área del resumen se quedaron en
     12,5 — escribir el nombre iba bien y abrir el desplegable de al lado
     ampliaba la pantalla. Son 26 reglas de campo repartidas por la hoja.
     Por elemento y con !important, en vez de una lista de selectores: casi
     todas esas reglas son más específicas que ésta, y una lista se queda vieja
     el día que alguien añada el campo 27 — que es exactamente como se llegó
     aquí. Casillas y radios quedan fuera: no llevan texto que ampliar.
     Solo dentro de este bloque, así que en escritorio no cambia nada. */
  input:not([type=checkbox]):not([type=radio]), select, textarea{font-size:16px !important;}

  /* EL BLANCO DE TOQUE de .op-link, la acción más repetida de Atlas: 167 usos
     en las vistas, y es un <span> con onclick de 13px sin relleno, así que la
     zona sensible ronda los 14px de alto — un tercio de los 44 que pide iOS.
     Todo lo demás recibió tamaño táctil unas líneas más arriba; ésta se quedó
     fuera justo por ser la más común y no parecer un botón.
     Se agranda con relleno vertical y no con min-height porque casi siempre va
     EN LÍNEA dentro de una frase: en un elemento en línea el relleno vertical
     se pinta y recibe el toque, pero NO separa los renglones, así que la zona
     crece sin recolocar nada de la página. Ninguna otra regla le pone relleno,
     así que no hay a quién ganarle en especificidad. */
  .op-link{padding-block:11px;}
  #catcount{text-align:left; line-height:1.5;}

  /* ========== OPORTUNIDADES / NOVEDADES ========== */
  .fcard .fc-foot{row-gap:10px;}
  .fcard .fc-foot .pc-amt{flex:1 1 auto;}
  .fcard .fc-row{flex-wrap:wrap;}
  .fcard .fc-row .k{min-width:70px;}
  .grp-h{flex-wrap:wrap; row-gap:2px;}
  .grp-h .g-meta{flex:1 1 100%; margin-left:32px;}
  .nv-row{gap:10px;}
  .nv-row .nv-f{padding-top:3px;}

  /* ========== LÍNEA DE PRODUCCIÓN ==========
     El carril deslizante ya lo pone el corte de 1180px; aquí solo se estrecha
     la columna para que en un teléfono se vea una entera y se asome la
     siguiente, que es lo que invita a deslizar. */
  .klinea-cols .kcol{flex:0 0 min(86%, 280px);}

  /* ========== POR ENTE / CONFIGURACIÓN ========== */
  .md{gap:14px;}
  .md-list{-webkit-overflow-scrolling:touch;}
  .md-main{scroll-margin-top:66px;} /* topbar 58px + colchón */
  .ente-metastrip .btn{margin-left:0 !important;}
  .conf-2col{gap:20px;}
  .perm th, .perm td{padding-left:6px; padding-right:6px;}

  /* ========== DETALLE DE ACTIVO ========== */
  .a-hero{margin:-14px -14px 0; padding:12px 16px 10px;} /* compensa el padding 14px del .content mobile; ajustar juntos si cambia */
  .a-h2{gap:8px 12px;}
  .a-h2 h1{font-size:19px;}
  .a-apex{order:10; flex:1 1 100%; margin-left:0; text-align:left;}
  .a-apex .top{justify-content:flex-start;}
  .a-apex .val{font-size:19px;}
  .a-h3{gap:12px;}
  .stepper{width:100%; flex:1 1 100%; margin-left:0;}
  .a-next{grid-template-columns:1fr; gap:12px; padding:14px 16px;}
  .a-nextr{text-align:left;}
  .a-next .btn.big{width:100%; min-height:44px;}
  .op-row{grid-template-columns:minmax(0,1fr) auto; gap:8px 12px; padding:12px 16px;}
  .op-row > div{grid-column:1/-1;}
  .op-row .op-amt{grid-row:1; grid-column:2; justify-self:end;}
  .op-meta{white-space:normal;}
  .doc44{padding:12px 16px;}
  .doc44 .mt{display:block;}
  .a-sec{flex-wrap:wrap; gap:8px 12px;}
  .a-sec .btn.sm{min-height:40px; padding:8px 12px;}
  .lb-img{max-width:94vw; max-height:72vh;}
  .lb-cap{max-width:92vw;}
  .lb-nav{font-size:30px; padding:12px 10px;}
  .lb-prev{left:0;} .lb-next{right:0;}

  /* ========== GUÍA ========== */
  .funnel.g-chain{flex-direction:column; gap:8px;}
  .g-chain .fst{flex:1 1 auto;}
  .g-chain .arr{display:none;}
  table.tbl.deflist tr{display:block; padding:9px 0; border-bottom:1px solid var(--line-soft);}
  table.tbl.deflist tr:last-child{border-bottom:none;}
  table.tbl.deflist td{display:block; border-bottom:none; padding:0;}
  table.tbl.deflist td.term{width:auto; padding:0 0 3px;}
}

  /* ---- detalle de marco legal (ley) ---- */
  .rowlink{cursor:pointer;}
  .rowlink:hover td{background:var(--block);}
  .ley-head{display:flex; align-items:flex-start; gap:14px; margin-top:10px; flex-wrap:wrap;}
  .ley-title{font-size:19px; font-weight:700; letter-spacing:-.01em; line-height:1.3; max-width:760px;}
  .ley-sub{font-size:13px; color:var(--gray); margin-top:4px;}
  .ley-actions{margin-left:auto; display:flex; align-items:center; gap:10px; flex-wrap:wrap;}
  .lb-h{font-size:12px; font-weight:800; letter-spacing:.01em; color:var(--gray-soft); margin-bottom:8px;}
  .ley-stats{display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:10px; margin-top:16px;}
  @media (max-width:900px){ .ley-stats{grid-template-columns:repeat(2,minmax(0,1fr));} }
  @media (max-width:520px){ .ley-stats{grid-template-columns:1fr;} }
  .ley-stat{background:var(--bg); border:1px solid var(--line); border-radius:10px; padding:12px 14px; min-width:0;}
  .ley-stat .sl{font-size:10.5px; font-weight:700; letter-spacing:.01em; color:var(--gray-soft);}
  .ley-stat .sv{font-size:13.5px; font-weight:700; color:var(--ink); margin-top:5px; line-height:1.4;}
  .ley-hero{margin-top:14px; background:linear-gradient(135deg,var(--navy),var(--navy2)); border-radius:12px; padding:20px 22px;}
  .ley-hero .hl{font-size:10.5px; font-weight:800; letter-spacing:.01em; color:var(--cyan);}
  .ley-hero p{font-size:14.5px; line-height:1.7; color:#EAF3FF; margin-top:9px; max-width:800px;}
  .ley-grid{display:grid; grid-template-columns:minmax(0,1fr) 340px; gap:26px; margin-top:22px;}
  @media (max-width:1000px){ .ley-grid{grid-template-columns:1fr;} }
  .ley-acc{border:1px solid var(--line); border-radius:10px; background:var(--bg); overflow:hidden; margin-top:2px;}
  .ley-acc details{border-bottom:1px solid var(--line);}
  .ley-acc details:last-child{border-bottom:none;}
  .ley-acc summary{list-style:none; cursor:pointer; padding:12px 14px; display:flex; align-items:center; gap:10px;}
  .ley-acc summary::-webkit-details-marker{display:none;}
  .ley-acc summary::after{content:"+"; margin-left:auto; font-size:15px; color:var(--gray-soft);}
  .ley-acc details[open] summary::after{content:"–";}
  .acc-num{flex:0 0 auto; width:21px; height:21px; border-radius:6px; background:var(--block); color:var(--navy); font-size:10.5px; font-weight:800; display:flex; align-items:center; justify-content:center;}
  .acc-t{font-size:13px; font-weight:700; color:var(--ink);}
  .acc-r{flex:0 0 auto; font-size:10px; font-weight:700; color:var(--gray-soft); background:var(--block); border:1px solid var(--line); padding:2px 7px; border-radius:20px; white-space:nowrap;}
  .ley-acc-body{padding:0 14px 14px 45px; font-size:12.5px; line-height:1.7; color:var(--gray); max-width:760px;}
  .ley-box{border:1px solid var(--line); border-radius:10px; padding:15px 17px; margin-bottom:14px; background:var(--bg);}
  .ley-box .fc-rows{display:flex; flex-direction:column; gap:9px;}
  .ley-box .fc-row{display:grid; grid-template-columns:130px 1fr; gap:10px; font-size:13.5px; line-height:1.55;}
  .ley-box .fc-row .k{color:var(--gray); font-weight:700;}
  .ley-box .fc-row .v{color:var(--ink); min-width:0;}
  .ley-box.ley-inv{background:var(--good-bg);}
  .ley-inv p{font-size:13.5px; line-height:1.7; color:var(--ink); margin:0;}
  .ley-step{display:flex; gap:10px; padding:8px 0;}
  .ley-step .dot{flex:0 0 auto; width:8px; height:8px; border-radius:50%; background:var(--navy); margin-top:5px; position:relative;}
  .ley-step:not(:last-child) .dot::after{content:""; position:absolute; top:10px; left:2.5px; width:2px; height:calc(100% + 8px); background:var(--line);}
  .ley-step .sr{font-size:10.5px; font-weight:700; color:var(--navy);}
  .ley-step .st{font-size:11.5px; color:var(--gray); margin-top:2px; line-height:1.5;}
  .ley-nota{font-size:12.5px; color:var(--gray); line-height:1.6; padding:0 2px;}
  .ley-cta{display:flex; gap:10px; margin-top:16px;}
  .ley-txt{border:1px solid var(--line); border-radius:10px; background:var(--bg); padding:28px 34px;}
  .ley-txt pre{white-space:pre-wrap; word-wrap:break-word; font-family:inherit; font-size:15px; line-height:1.85; color:var(--ink); margin:0 auto; max-width:70ch;}
  .ley-txt b.art{font-weight:800; color:var(--navy);}
  .ley-txt .rub{font-weight:800; color:var(--navy-deep); display:inline-block; margin-top:14px; letter-spacing:.01em;}
  .ley-txt mark{background:#FFF1B8; color:inherit; border-radius:3px; padding:0 1px;}
  .ley-txt mark.cur{background:#FFD54F; outline:2px solid #F0B429;}
  .ley-txt::-webkit-scrollbar{width:8px;} .ley-txt::-webkit-scrollbar-thumb{background:var(--line); border-radius:8px;}

  /* =====================================================================
     PROYECTOS EN EJECUCIÓN — migrado del prototipo 02.norte/proyectos_ejecucion/.
     Misma paleta y proporciones que el resto del app (variables :root de arriba).
     ===================================================================== */

  /* ---- vista kanban: cada columna se desplaza por su cuenta en vez de
     estirar todo el tablero por la columna más larga. Acotado a #proybody
     (el id propio de esta lista) para no afectar los otros tableros kanban
     que reusan .kbody en seguimiento.js/oficios.js/linea.js/contrapartes.js. ---- */
  #proybody .kbody{max-height:460px; overflow-y:auto; padding-right:6px;}
  #proybody .kbody::-webkit-scrollbar{width:6px;}
  #proybody .kbody::-webkit-scrollbar-thumb{background:var(--line); border-radius:8px;}

  /* ---- tarjeta de checkpoint de contacto (rail de detalle) ---- */
  /* ---- el reparto por estado, en pizza 3D ----
     Va encima de las filas del bloque, no en su lugar: las filas llevan el monto de cada
     estado, el enlace a su lista y la marca de los mayores compromisos. La pizza es el
     vistazo; las filas son la lectura. */
  /* Con el lienzo en 250px, el círculo y su leyenda vuelven a caber en la misma fila dentro de
     media caja: antes la leyenda se iba debajo y el bloque medía 200px más de alto. */
  .pz-caja{position:relative; display:flex; align-items:center; justify-content:center; gap:22px;
           flex-wrap:wrap; padding:2px 0 4px;}
  .pz-lg{display:flex; flex-direction:column; gap:8px; min-width:196px;}
  .pz-li{display:flex; align-items:center; gap:9px; font-size:12.5px; color:var(--ink); cursor:pointer;
         padding:3px 6px; margin:-3px -6px; border-radius:6px; transition:opacity .1s ease, background .1s ease;}
  .pz-li:hover{background:var(--block);}
  .pz-li i{width:10px; height:10px; border-radius:3px; flex:none;}
  .pz-li .nm{flex:1 1 auto;}
  .pz-li b{font-weight:800; font-variant-numeric:tabular-nums;}
  .pz-li .p{color:var(--gray-soft); font-size:11.5px; min-width:46px; text-align:right;}
  .pz-li.off{opacity:.4;}
  .pz-li.on b{color:var(--navy2);}
  .pz-tip{position:absolute; z-index:5; pointer-events:none; opacity:0; transition:opacity .1s ease;
          background:var(--navy-deep, #0A1730); color:#fff; border-radius:8px; padding:7px 10px;
          box-shadow:0 6px 18px rgba(14,20,36,.22); white-space:nowrap;}
  .pz-tip.on{opacity:1;}
  .pz-tip .t{font-size:11px; font-weight:800; display:flex; align-items:center; gap:7px;}
  .pz-tip .t i{width:8px; height:8px; border-radius:2px; flex:none;}
  .pz-tip .v{font-size:16px; font-weight:800; margin-top:3px; font-variant-numeric:tabular-nums;}
  .pz-tip .s{font-size:10.5px; color:#AFC0DA; margin-top:1px;}
  /* El monto, una línea por moneda: no hay tasa con la que fundir US$ y EUR, y una cifra no se
     parte a mitad. Va separado del resto por una regla tenue —es otra medida, no otro renglón
     de la misma. */
  .pz-tip .m{display:flex; flex-direction:column; gap:1px; margin-top:6px; padding-top:6px;
             border-top:1px solid rgba(255,255,255,.16); font-size:12.5px; font-weight:800;
             font-variant-numeric:tabular-nums;}
  .pz-tip .s.clic{margin-top:5px; color:#7E93B8;}

  /* ---- el reparto por sector, en columnas 3D ----
     El lienzo se dibuja a 880px y se deja encoger con la caja: el mapa que dice qué sector hay
     bajo el cursor ya traduce de píxel de pantalla a píxel de lienzo, así que escalar no lo
     rompe. */
  /* min-width:0 y overflow:hidden rompen un círculo vicioso: el panel es una rejilla, y un
     lienzo de 935px le exigía a su columna 935px de ancho mínimo, con lo que la caja medía
     935 y el lienzo volvía a medirse contra ella. Así medía siempre de más y el bloque
     desbordaba 32px. Sin contribuir al ancho mínimo, la caja recibe el ancho que le toca (883)
     y el lienzo se ajusta a él. */
  .col-caja{position:relative; min-width:0; overflow:hidden;}
  /* Sin width en CSS: el ancho se lo pone prColAjusta() en píxeles, medidos sobre esta caja, y
     el lienzo se dibuja a la resolución del dispositivo. Estirarlo con width:100% era lo que lo
     dejaba borroso en pantallas con escalado. */
  .col-caja canvas{display:block;}
  .col-lg{display:flex; gap:16px; flex-wrap:wrap; justify-content:center; margin-top:12px;
          font-size:11.5px; color:var(--ink);}
  .col-lg span{display:inline-flex; align-items:center; gap:7px; cursor:pointer;
               padding:3px 7px; margin:-3px 0; border-radius:6px;
               transition:opacity .1s ease, background .1s ease;}
  .col-lg span:hover{background:var(--block);}
  .col-lg span i{width:10px; height:10px; border-radius:3px; flex:none;}
  .col-lg span.off{opacity:.4;}
  .col-lg span.on{font-weight:800;}

  /* ---- bloque de barras con las dos medidas apiladas ----
     La de contratos arriba y la de monto justo debajo, dentro de la misma fila: cada una
     recupera el ancho entero del bloque en vez de la mitad, y el nombre del sector deja de
     competir por sitio con dos medidas a la vez. Cuesta el doble de alto por fila, así que
     esto vale para los cuatro o cinco sectores de "Mayores compromisos" y no habría valido
     para una lista larga. */
  #proystats .ap-bloque{position:relative;}
  /* 168px y no 206: el nombre más largo de los siete sectores cabe de sobra, y los 38 que
     sobraban dejaban un pasillo vacío entre el nombre y los rótulos de las barras. */
  #proystats .ap-row{display:grid; grid-template-columns:168px 1fr; align-items:center; gap:14px;
                     padding:10px 7px; margin:0 -7px; border-radius:7px; cursor:pointer;
                     transition:opacity .1s ease, background .1s ease;}
  #proystats .ap-row + .ap-row{border-top:1px solid var(--line-soft);}
  #proystats .ap-row:hover{background:var(--block);}
  #proystats .ap-row.off{opacity:.38;}
  #proystats .ap-l{display:flex; align-items:center; gap:8px; min-width:0;
                   font-size:12.5px; font-weight:700; color:var(--ink);}
  #proystats .ap-nm{min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  #proystats .ap-pt{width:9px; height:9px; border-radius:2px; flex:none;}
  /* El caret pegado al nombre, no empujado al fondo de la columna: con margin-left:auto
     flotaba en medio del hueco y no se leía como parte de nada. */
  #proystats .ap-l .ps-caret{flex:0 0 auto;}
  #proystats .ap-row:hover .ps-caret{background:var(--navy2); border-color:var(--navy2); color:#fff;}
  #proystats .ap-med{display:flex; flex-direction:column; gap:7px; min-width:0;}
  /* El rótulo delante de cada barra no es opcional: un conteo y un importe no comparten vara, y
     dos barras del mismo ancho a dos milímetros una de otra se leen como la misma medida. */
  #proystats .ap-linea{display:grid; grid-template-columns:88px 1fr auto; align-items:center; gap:11px;}
  #proystats .ap-linea .k{font-size:9.5px; font-weight:800; letter-spacing:.01em;
                          color:var(--gray-soft);}
  #proystats .ap-tr{height:13px; border-radius:4px; background:var(--line-soft); overflow:hidden;}
  /* En cero hasta que el bloque entra en pantalla: la anchura vive en --w y solo se toma con la
     clase .arriba. Misma cadencia y misma curva que la subida de las columnas y las pizzas, que
     se hacen en lienzo — el efecto tiene que leerse igual en las tres. */
  #proystats .ap-tr i{display:block; height:100%; border-radius:4px; width:0;
                      transition:width .7s cubic-bezier(.22,.61,.36,1);}
  #proystats .ap-bloque.arriba .ap-tr i{width:var(--w);}
  @media (prefers-reduced-motion:reduce){
    #proystats .ap-tr i{width:var(--w); transition:none;}
  }
  /* Las dos medidas terminan en la misma vertical: el ancho fijo es lo que alinea el borde
     derecho de "5" con el de "EUR 333,8 MM" y deja las barras midiendo lo mismo. */
  #proystats .ap-linea b{font-size:12.5px; font-weight:800; color:var(--ink); width:124px; text-align:right;}
  #proystats .ap-v{font-size:12.5px; font-weight:800; color:var(--ink); text-align:right; width:124px;}
  /* Una línea por moneda: no hay tasa con la que fundirlas y una cifra no se parte a mitad. */
  #proystats .ap-v span{display:block; white-space:nowrap;}
  #proystats .ap-v.vacio{color:var(--gray-soft); font-weight:600;}
  /* En media caja hay 453px, y con las medidas de ancho completo la pista de la barra se
     quedaba en 23px — un muñón que no compara nada. Se estrechan el nombre, el rótulo y la
     cifra, y la barra recupera unos 120px. */
  /* Acotado a los bloques que NO ocupan el ancho entero —hoy este vive en col7— y no a .col6:
     el reparto de la pareja es 7 y 5, no mitades. */
  #proystats section:not(.col12) .ap-row{grid-template-columns:150px 1fr; gap:10px;}
  /* 70px y 9px de cuerpo: "CONTRATOS" en versalita con su interletraje pide 66, y a 62 salía
     recortado. */
  #proystats section:not(.col12) .ap-linea{grid-template-columns:70px 1fr auto; gap:9px;}
  #proystats section:not(.col12) .ap-linea .k{font-size:9px;}
  #proystats section:not(.col12) .ap-linea b,
  #proystats section:not(.col12) .ap-v{width:108px; font-size:11.5px;}
  #proystats section:not(.col12) .ap-l{font-size:12px;}
  /* Sin caret fuera del ancho completo: se lleva 30px de la columna del nombre y ahí
     "Agroalimentario" quedaba justo. La fila entera sigue siendo pulsable y se ilumina al pasar
     por encima, que es lo que el caret venía a anunciar. */
  #proystats section:not(.col12) .ap-l .ps-caret{display:none;}
  @media (max-width:820px){
    #proystats .ap-row{grid-template-columns:1fr; gap:9px;}
    #proystats .ap-linea{grid-template-columns:74px 1fr auto; gap:9px;}
  }

  .ckpt{padding:18px 20px;}
  .ckpt .ck-days{font-size:26px; font-weight:800; letter-spacing:-.02em; color:var(--ink); line-height:1.1;}
  .ckpt .ck-days.warn{color:var(--amber);}
  .ckpt .ck-days.rust{color:var(--rust);}
  .ckpt .ck-days.mute{color:var(--gray-soft); font-size:15px; font-weight:700;}
  .ckpt .ck-sub{font-size:11.5px; color:var(--gray); margin-top:4px; line-height:1.5;}
  .ckpt .ck-meta{display:flex; flex-direction:column; gap:7px; margin-top:14px; padding-top:14px; border-top:1px solid var(--line-soft);}
  /* Cuando la tarjeta empieza por estas filas —los días y la frase se fueron a la cabecera— no
     hay nada arriba de lo que separarlas, y la regla quedaba colgando bajo el rótulo. */
  .ckpt .ck-meta.primera{margin-top:0; padding-top:0; border-top:none;}
  /* La misma escala que la ficha de arriba: el rótulo con el peso y el gris de
     .ct-lbl, y el dato con los de .ct-val. Eran 11px con pesos 700/800, dos
     tarjetas pegadas hablando con dos voces. */
  .ckpt .ck-row{display:flex; gap:10px; font-size:13.5px; line-height:1.5; align-items:baseline;}
  .ckpt .ck-row + .ck-row{margin-top:9px;}
  .ckpt .ck-row .k{font-size:11.5px; font-weight:500; color:var(--gray-soft); min-width:104px; flex:0 0 auto;}
  .ckpt .ck-row .v{color:var(--ink); font-weight:500; min-width:0;}
  .ck-nota{font-size:11.5px; color:var(--gray-soft); line-height:1.45; margin-top:10px;}
  /* El formulario de edición del checkpoint. */
  .ck-edit .field{margin-bottom:11px;}
  .ck-edit .field label{display:block; font-size:11.5px; font-weight:500; color:var(--gray-soft); margin-bottom:5px;}
  .ck-edit input{width:100%; font-family:inherit; font-size:13.5px; color:var(--ink); background:var(--bg);
                 border:1px solid var(--line); border-radius:8px; padding:8px 10px;}
  .ck-edit .ck-acts{display:flex; gap:8px; margin-top:13px;}
  /* Los responsables del contrato, uno por línea con su inicial. */
  .ct-resp{display:flex; flex-direction:column; gap:9px;}
  .ct-resp-i{display:flex; align-items:center; gap:9px; font-size:13.5px; font-weight:500; color:var(--ink); min-width:0;}
  .ct-resp-i .sg-av{width:28px; height:28px; font-size:10px; flex:0 0 auto;}
  .ckpt .btn{width:100%; margin-top:14px;}

  /* ---- formulario inline de agregar evento / contacto ---- */
  .ckform{margin-top:14px; padding-top:14px; border-top:1px solid var(--line-soft); display:flex; flex-direction:column; gap:11px;}
  .ckform .field{margin-bottom:0;}
  .ckform .fbtns{display:flex; gap:8px; justify-content:flex-end;}

  /* ---- puntos de atención (detalle) ---- */
  .atn-list{display:flex; flex-direction:column; gap:8px;}
  .atn-row{display:flex; gap:9px; align-items:flex-start; font-size:14px; color:var(--ink); line-height:1.55;}
  .atn-row .amk{width:6px; height:6px; border-radius:50%; background:var(--gray-soft); margin-top:6px; flex:0 0 auto;}
  .atn-note{font-size:14px; color:var(--ink); line-height:1.65; padding-top:10px; margin-top:10px; border-top:1px dashed var(--line);}
  .atn-h2{font-size:10.5px; font-weight:800; letter-spacing:.01em; color:var(--gray-soft); margin-bottom:8px;}

  /* ---- cláusulas principales ---- */
  .claus-list{display:flex; flex-direction:column; gap:9px;}
  .claus-row{display:flex; gap:8px; font-size:14px; line-height:1.6; color:var(--ink);}
  .claus-row .cq{color:var(--gray-soft); flex:0 0 auto;}

  /* ---- descripción del proyecto (arriba de todo en el detalle) ---- */
  /* El rótulo pasa a ser el mando que pliega la descripción: lleva caret delante y el estado
     escrito a la derecha, así que es flex y su tirón lateral hace que el realce respire sin
     mover el texto de sitio. */
  /* "Ocultar" / "Mostrar" sin versalitas ni espaciado: cuelga del rótulo, que sí las lleva. */
  /* Plegada, la tarjeta se queda en su rótulo: sin quitar el margen inferior quedaría un
     escalón de aire bajo el título. */
  /* Tope de alto con desplazamiento propio. Las 63 descripciones van de 880 a 1.593 caracteres
     —de nueve a diecisiete líneas, mediana doce—, así que esta tarjeta siempre era alta y
     empujaba hacia abajo las dos columnas del expediente en todos los contratos, no en algunos.
     Siete líneas: las suficientes para saber de qué va el proyecto antes de decidir si se lee
     entero. El cálculo va en `em` y no en píxeles para que siga cuadrando si cambia el tamaño
     de letra; el interlineado es 1.6, de ahí el 11.2em. */
  /* Sin tope: la tarjeta ya es plegable, así que recortarla además con scroll
     era pedir dos gestos para leer lo mismo. */
  /* Tirador más marcado que el resto del sistema: aquí el fondo de la tarjeta ya es gris
     (var(--block)), y sobre él un tirador en var(--line) se pierde. */

  /* ---- contraparte del proyecto: empresa + personas de contacto (puente a CRM) ---- */
  .cto-list{display:flex; flex-direction:column; gap:12px;}
  .cto-row{padding-top:10px; border-top:1px dashed var(--line);}
  .cto-row:first-child{padding-top:0; border-top:none;}
  .cto-nm{display:block; font-size:13px; font-weight:700; color:var(--ink); cursor:pointer;}
  .cto-nm:hover{color:var(--navy2);}
  /* El cargo, legible. En var(--gray) sobre blanco quedaba tan claro que se
     leía como un dato apagado, y muchas veces es la única pista de con quién
     se está hablando: "Representante de …". Misma tinta que las descripciones
     de la ficha, y un pelo más de aire respecto al nombre. */
  .cto-rol{font-size:12.5px; color:#39414F; margin-top:3px; line-height:1.45;}
  /* Quién es el contacto principal, dentro de esa misma línea. */
  .cto-marca{font-weight:700; color:var(--navy);}
  .cto-meta{display:flex; align-items:center; gap:9px; margin-top:6px;}
  .cto-nota{font-size:11.5px; color:var(--gray-soft); line-height:1.5; margin-top:6px; padding:8px 10px; background:var(--block); border-radius:6px;}

  /* ---- datos de registro de las partes (ficha de empresa) ----
     Un párrafo del expediente ordenado en campos. La rejilla es auto-fit y no un número fijo de
     columnas: una parte puede traer los seis campos y otra solo el nombre, y con columnas fijas
     la que trae poco deja huecos que se leen como datos que faltan. */
  .rg-bloque{padding-top:16px; margin-top:16px; border-top:1px solid var(--line);}
  .rg-bloque:first-of-type{padding-top:0; margin-top:0; border-top:none;}
  .rg-src{font-size:11px; color:var(--gray-soft); margin-bottom:10px;}
  .rg-src b{color:var(--ink);}
  /* Aviso de que el desglose no separó todas las entidades del párrafo. En ámbar de atención y no
     en rojo: no hay nada roto, hay una lectura incompleta que conviene contrastar. */
  .rg-aviso{display:flex; align-items:center; gap:10px; flex-wrap:wrap; font-size:11.5px;
            color:#8A5A1F; background:#FDF6E7; border:1px solid #F0DFB8; border-radius:7px;
            padding:9px 12px; margin-bottom:14px; line-height:1.5;}
  .rg-aviso b{color:#6E4715;}
  .rg-aviso .op-link{font-size:11.5px; margin-left:auto; cursor:pointer; white-space:nowrap;}
  .rg-parte{border-top:1px solid var(--line-soft); padding-top:13px; margin-top:13px;}
  .rg-parte:first-of-type{border-top:none; padding-top:0; margin-top:0;}
  .rg-nm{display:flex; align-items:center; gap:8px; flex-wrap:wrap;
         font-size:13px; font-weight:800; color:var(--ink); margin-bottom:9px;}
  /* Estado o privada, con los colores que el módulo ya usa para eso. Es lo primero que hay que
     saber de una parte: quién contrata a quién. */
  .rg-rol{font-size:9.5px; font-weight:800; letter-spacing:.01em;
          padding:2px 7px; border-radius:4px;}
  .rg-rol.est{background:#E4F0EA; color:#1E7F5C;}
  .rg-rol.priv{background:#E4EDF8; color:var(--navy);}
  .rg-campos{display:grid; grid-template-columns:repeat(auto-fit, minmax(230px, 1fr)); gap:11px 26px;}
  .rg-c{min-width:0;}
  .rg-k{font-size:10px; font-weight:800; letter-spacing:.01em;
        color:var(--gray-soft); margin-bottom:2px;}
  .rg-v{font-size:12.5px; line-height:1.5; color:var(--ink); overflow-wrap:anywhere;}
  .rg-v.mono{font-variant-numeric:tabular-nums; font-weight:800;}
  .rg-v.falta{color:var(--gray-soft); font-style:italic;}
  /* Lo que ningún campo reconoció, entero. Con borde punteado para que se lea como "esto está
     sin ordenar", no como un campo más. */
  .rg-otros{margin-top:12px; padding-top:10px; border-top:1px dashed var(--line);}
  .rg-otros .rg-v{color:var(--gray); font-size:12px;}
  /* ---- respaldo documental de cada parte ----
     Los campos salen de leer un párrafo; el documento es lo que los sostiene. Una parte sin él
     lleva una barra ámbar a la izquierda: se ve cuál falta recorriendo el bloque con la vista,
     sin leer cada recuadro. Ámbar y no rojo — falta el respaldo, no hay nada roto. */
  .rg-parte.sin-doc{border-left:3px solid #E6C687; padding-left:12px; margin-left:-15px;}
  .rg-sindoc{display:flex; align-items:center; gap:10px; flex-wrap:wrap;
             margin-top:12px; padding:9px 12px; border-radius:7px;
             background:#FDF6E7; border:1px solid #F0DFB8;}
  .rg-sindoc-t{font-size:11.5px; font-weight:800; color:#6E4715;}
  .rg-sindoc-d{font-size:11.5px; color:#8A5A1F; line-height:1.45; min-width:0; flex:1 1 240px;}
  .rg-sindoc .op-link{font-size:11.5px; cursor:pointer; white-space:nowrap;}
  .rg-docs{margin-top:12px;}
  .rg-docs-h{display:flex; align-items:center; gap:12px; margin-bottom:6px;}
  .rg-docs-h .op-link{margin-left:auto; font-size:11.5px; cursor:pointer;}
  /* Cuatro columnas: ícono, nombre, quién y cuándo lo subió, y la acción. Quién lo subió no es
     adorno — es lo que distingue un documento del expediente de uno que agregó alguien ayer. */
  .rg-doc{display:grid; grid-template-columns:16px minmax(0,1fr) auto auto; align-items:center;
          gap:10px; padding:7px 8px; margin:0 -8px; border-radius:7px; cursor:pointer;}
  .rg-doc:hover{background:var(--block);}
  .rg-doc:hover .rg-doc-n{color:var(--navy2);}
  .rg-doc svg{width:16px; height:16px; color:var(--gray-soft);}
  .rg-doc-n{font-size:12.5px; font-weight:700; color:var(--ink);
            overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  .rg-doc-m{font-size:11px; color:var(--gray-soft); white-space:nowrap;}
  .rg-doc-a{font-size:11.5px; font-weight:700; color:var(--navy2); white-space:nowrap;}
  /* Cuenta de partes sin respaldo, en la cabecera del bloque: con cinco o seis repartidas en
     dos contratos, saberlo obligaba a bajar y mirarlas una a una. */
  .rg-cuenta{font-size:11px; font-weight:800; padding:3px 9px; border-radius:20px; white-space:nowrap;}
  .rg-cuenta.falta{background:#FDF6E7; color:#8A5A1F;}
  .rg-cuenta.ok{background:#E4F0EA; color:#1E7F5C;}
  @media (max-width:700px){
    .rg-doc{grid-template-columns:16px minmax(0,1fr) auto;}
    .rg-doc-m{display:none;}
  }
  .rg-pie{display:flex; align-items:center; gap:12px; flex-wrap:wrap;
          margin-top:14px; padding-top:11px; border-top:1px solid var(--line);}
  .rg-pie .op-link{margin-left:auto; cursor:pointer; font-size:12px;}
  .rg-fuente{font-size:11px; color:var(--gray-soft);}
  /* El párrafo íntegro en la ventana: ancho de lectura y sin tope de alto — el más largo son 1.281
     caracteres y la tarjeta ya rueda si hiciera falta. */
  .rg-full{font-size:13px; line-height:1.65; color:var(--ink); white-space:pre-wrap;}

  /* ---- términos del contrato: objeto/obligaciones/reparto/vigencia/rescisión/garantías/jurisdicción,
     extraídos de la lectura completa del contrato ---- */
  .tc-block{padding-top:12px; margin-top:12px; border-top:1px dashed var(--line);}
  .tc-block:first-of-type{padding-top:0; margin-top:0; border-top:none;}
  .tc-h{font-size:10.5px; font-weight:800; letter-spacing:.01em; color:var(--gray-soft); margin-bottom:6px;}
  .tc-txt{font-size:14px; line-height:1.65; color:var(--ink);}
  .tc-sub{font-size:11px; font-weight:700; color:var(--gray); margin-bottom:7px;}
  .tc-oblgrid{display:grid; grid-template-columns:1fr 1fr; gap:18px;}
  @media(max-width:860px){.tc-oblgrid{grid-template-columns:1fr;}}
  .tc-foot{font-size:10.5px; color:var(--gray-soft); margin-top:14px; padding-top:10px; border-top:1px dashed var(--line);}

  /* ===================== FICHA DEL CONTRATO (.ct-f) =====================
     Todo lo de aquí vestía antes con estilos inline repartidos por
     contrato.js y con rótulos en versalitas de peso 800 que competían con su
     propio dato: el nombre de la empresa se leía igual de fuerte que la
     palabra "Empresa", y el título de la tarjeta —gris, 13px— más flojo que
     ambos. La jerarquía queda al derecho: título de tarjeta oscuro, rótulo
     callado, dato legible.

     Va bajo .ct-f y no sobre .a-card/.a-sec a secas porque esas clases las
     comparten siete pantallas; cuando esta se dé por buena, se sube. Los
     tokens de shadcn/ui (--tz-*) están declarados arriba, en el bloque de
     Trazabilidad; aquí solo se usa su gris de rótulo. */
  /* El relleno de las tarjetas, por columna: las del carril más apretadas que
     las del cuerpo, porque el carril mide 340px.

     Basta con .a-rail y .a-main desde que la rejilla volvió a dos filas. Hubo
     una época con celdas propias para la primera tarjeta de cada columna
     (.ct-par-i / .ct-par-d) y esas dos se quedaron fuera del alcance de estas
     reglas, o sea SIN relleno: el rótulo pegado al borde y el texto tocando
     el marco. Si alguna vez vuelve a haber una celda intermedia, hay que
     nombrarla aquí. */
  .ct-f .a-main > .a-card{padding:22px 26px;}
  /* ---- la rejilla de la ficha, en huecos con sitio fijo ----
     Tres filas, dos columnas, y cada pieza puesta a mano en su celda:

       fila 1   ·   (vacía)   ·   pestañas
       fila 2   ·   1ª ficha  ·   1ª del cuerpo     ← misma fila = mismo alto
       fila 3   ·   resto     ·   resto

     Las pestañas van solas en la fila 1 y SOLO en la columna derecha: quedan
     justo encima de "Personas de contacto", del ancho exacto de esa tarjeta,
     que es el contenido que gobiernan —la ficha de la izquierda es la misma
     en Resumen, en Actividad y en Tareas—.

     Fila propia y no dentro de la columna derecha, que no es lo mismo: metidas
     dentro, empujaban esa columna sesenta píxeles hacia abajo y las dos
     empezaban a distinta altura. Con una fila para ellas, la izquierda no pone
     nada en esa fila y las dos arrancan iguales en la fila 2.

     La colocación es explícita (grid-area) y no automática: con una fila a
     medio llenar, el reparto automático mete la tarjeta siguiente en el hueco
     libre de arriba —"Responsable" acabaría al lado de las pestañas—. */
  .ct-grid{display:grid; grid-template-columns:340px minmax(0,1fr);
           gap:20px 32px; align-items:stretch;}
  .ct-grid > .ct-tabs {grid-area:1 / 2;}
  .ct-grid > .a-rail  {grid-area:2 / 1;}
  .ct-grid > .a-main  {grid-area:2 / 2;}
  /* La fila del par (.ct-par-i / .ct-par-d) desapareció. Existía para que
     "Responsables" y "Personas de contacto" se emparejaran a la misma altura;
     desde que las personas viven dentro de la ficha, enfrente de Responsables
     quedaba "Términos del contrato", que es largo, y la celda de la izquierda
     se estiraba a SU altura dejando un palmo de blanco entre Responsables y
     la ficha. Ahora Responsables es la primera tarjeta del carril, sin más:
     dos columnas y una fila, que es lo que la pantalla necesitaba. */
  /* Mismo aire entre tarjetas dentro de una columna que entre las filas de la
     rejilla: si no, el salto de la fila 2 a la 3 se ve distinto al de la 3 a
     la 4 dentro de la misma columna. */
  .ct-grid > .a-rail, .ct-grid > .a-main{gap:20px;}
  /* La barra estándar, la misma que la ficha del inversionista (#cpEmpTabs):
     pestañas a la izquierda, cada una con su relleno —incluida la primera— y
     el número en pastilla; la línea de abajo cruza el ancho de la ficha.
     .ct-tabs no cambia nada de eso: solo quita el margen, porque aquí la
     separación la pone la rejilla.

     Aquí hubo dos intentos de alinearlas de otra forma —al ras del borde
     izquierdo y luego al derecho— y ninguno se sostuvo al lado del resto de
     Atlas. Este patrón ya está probado en Inversionistas; no conviene que
     esta pantalla invente el suyo. */
  .ct-tabs{margin:0;}
  /* En una sola columna se acaban las filas: cada pieza cae en su orden. */
  @media (max-width:1000px){
    .ct-grid{grid-template-columns:1fr;}
    .ct-grid > *{grid-area:auto;}
  }
  .ct-f .a-card > .a-sec{margin-bottom:18px;}
  .ct-f .a-sec .t{font-size:14.5px; font-weight:600; letter-spacing:-.01em; color:var(--ink);}

  /* El rótulo, en todas partes el mismo: minúsculas, peso normal y gris. Un
     rótulo no es un titular; solo dice de qué es el dato que viene debajo. */
  /* ---- la escala de la ficha, en tres tamaños y nada más ----
     Antes convivían siete: 10, 11, 11.5, 12, 12.5, 13.5 y 17 px, con pesos de
     500 a 800, y la tarjeta se leía como un collage. Se reduce al mismo juego
     que usa el resto de Atlas con los tokens de shadcn (--tz-*, arriba, en el
     bloque de Trazabilidad):

       rótulo   11.5px / 500 / gris      qué dato viene ahora
       dato     13.5px / 500 / tinta     el dato
       nombre     17px / 600 / tinta     el titular de la tarjeta

     Los pesos de 800 se van: en textos de 10 y 11px no se leen como énfasis,
     se leen como manchas. */
  .ct-lbl{font-size:11.5px; font-weight:500; color:var(--gray-soft); margin-bottom:7px;}
  /* En la ficha del contrato los rótulos van en negrita y en tinta, no en
     gris: son los títulos de cada bloque —Contraparte, Estado, Ente estatal—
     y en gris claro se leían como una nota al pie de lo de arriba en vez de
     como el encabezado de lo de abajo. El tamaño no cambia; la jerarquía la
     hace el peso, no un cuerpo mayor.
     Acotado a .ct-f: .ct-lbl la comparte Correspondencia, y allí sigue siendo
     un rótulo de campo dentro de un formulario, que es otra cosa. */
  /* Y también donde se reusa la ficha fuera de esa página: la del proyecto, en
     Inversionistas, es el mismo patrón —rótulo, dato, filete— y sus rótulos
     tienen que sonar igual. Por eso el segundo selector cuelga de .ct-ficha,
     que es la ficha, y no de la página. */
  .ct-f .ct-lbl, .ct-ficha .ct-lbl{font-weight:700; color:var(--ink);}
  /* La coletilla de un dato: los días que lleva en el paso, de dónde salió la
     institución. Va debajo del dato, más pequeña y en gris, para que se lea
     como nota al pie de ese dato y no como otro dato. Solo se colorea cuando
     de verdad avisa —dos semanas, un mes en el mismo paso—; el resto del
     tiempo una nota en color sería una alarma que no hay. */
  /* El rótulo de la ficha del proyecto, a 13px. A 11.5 el título se leía más
     pequeño que su propio dato y la ficha parecía escrita al revés. 13 sobre
     13.5 es la proporción de la casa —la misma de .a-sec .t sobre lo que
     encabeza—: el título manda por peso y por tinta, no por tamaño.
     Acotado a las fichas del carril: la de una alianza tiene sus bloques mucho
     más largos y allí el rótulo pequeño sí separa. */
  .rail-ficha .ct-lbl{font-size:13px; margin-bottom:3px;}
  /* La columna del inversionista iba muy holgada: 18px de aire a cada lado
     del filete y 6 bajo el rótulo hacían que nueve campos ocuparan pantalla y
     media. Se aprieta a la mitad —sigue habiendo filete y aire, pero el ojo ya
     no tiene que bajar para pasar de un dato al siguiente—. Acotado al carril
     de Inversionistas; el resto de fichas conserva su medida. */
  .rail-ficha .ct-sep{margin:9px 0;}
  .rail-ficha .ct-val{line-height:1.4;}
  .rail-ficha .inv-ed{padding:2px 8px;}
  .rail-ficha .ct-edit-acts{margin-top:8px;}
  /* El logo encabeza la ficha, dentro de la misma tarjeta. Tenía la suya y eso
     rompía la alineación con la columna de la derecha a partir de la segunda
     tarjeta. El filete de abajo lo pone el primer bloque de la ficha. */
  .rail-logo{text-align:center; padding-bottom:2px;}
  /* Guardar y cancelar de un campo que se edita sin salir de su sitio: la ficha
     del proyecto, la del inversionista y el renglón del historial. */
  .ct-edit-acts{display:flex; gap:8px; margin-top:11px;}
  /* El enlace que abre ese campo, debajo del dato y no al lado: al lado
     competía con el propio dato por la primera línea. */
  .kvp .op-link{display:inline-block; margin-top:5px; font-size:12px;}
  .ct-nota{font-size:11.5px; color:var(--gray-soft); line-height:1.45; margin-top:5px;}
  /* Lo que falta por registrar, en gris. Se escribía ya como <span class="mute">
     en las fichas del rail —"Sin asignar", "Sin institución"— pero no había
     ninguna regla detrás y salía con la misma tinta que un dato de verdad. */
  .ct-ficha .mute, .kvp .v .mute{color:var(--gray-soft); font-weight:500;}
  .ct-nota.warn{color:var(--amber);}
  .ct-nota.late{color:var(--rust); font-weight:600;}
  .ct-f .ckpt .ck-row .k{font-weight:700; color:var(--ink);}
  .ct-f .ck-edit .field label{font-weight:700; color:var(--ink);}
  .ct-vacio{font-size:12.5px; color:var(--gray-soft); line-height:1.55;}

  /* ---- una sola línea de texto por columna ----
     Las tres tarjetas del carril traían tres rellenos distintos —20, 22 y 20—
     heredados de tres sitios distintos, así que "Responsable del seguimiento",
     "Contraparte" y "Checkpoint de contacto" empezaban con dos píxeles de
     diferencia entre sí. Se ve poco y se ve: son rótulos uno debajo de otro.
     Aquí manda una sola regla, y por eso respContratoHtml y descripcionHtml
     dejaron de traer su padding en línea (el inline le gana a cualquier
     selector, así que mientras estuviera no había forma de cuadrarlos). */
  .ct-f .a-rail > .a-card{padding:18px 20px;}
  /* La descripción cruza las dos columnas: su texto arranca donde el del
     carril (20px) y termina donde el de las tarjetas del cuerpo (26px). */
  /* Va con la misma especificidad que la regla de la pila (.ct-f .a-main >
     .a-card): desde que la descripción bajó al detalle es una tarjeta más de
     esa columna, y con dos clases perdía y se le aplicaba el relleno grande. */
  /* Cerrada, la tarjeta es solo su propio título: con el relleno de abierta
     dejaba un hueco largo por nada. (El recorte del salto a la sección
     siguiente se retiró al bajar la descripción al detalle: allí ya no abre
     la pantalla, es una tarjeta más de la pila y la separación la pone la
     rejilla como a las demás.) */
  /* El nombre de la contraparte es el dato del panel, no el valor de una
     fila: se lee primero y su enlace va debajo, en voz baja. */
  /* overflow-wrap: la columna mide 340px y hay operadores con razones sociales
     de una sola palabra larga, que si no se parten sobresalen de la tarjeta. */
  /* 15px y no 17: a 17 el nombre del operador competía con el <h1> de la
     cabecera y la tarjeta se leía como si el titular fuese ese. Con 15/600
     sigue destacando sobre el dato (13.5/500) sin gritar — un escalón, que es
     lo que recomienda la escala; dos son un salto. */
  .ct-emp-nm{font-size:15px; font-weight:600; letter-spacing:-.01em; color:var(--ink);
             line-height:1.35; overflow-wrap:anywhere;}
  .ct-ficha .op-link{display:inline-block; margin-top:6px;}
  /* El inversionista al que está atada la alianza, debajo del enlace: primero
     a dónde lleva, y luego con quién se ató y por qué. Una línea callada, en
     letra pequeña, porque es una precisión sobre el dato de arriba y no un
     dato nuevo. */
  .ct-vinculo{display:flex; flex-wrap:wrap; align-items:baseline; gap:4px 10px;
    margin-top:5px; font-size:11.5px; line-height:1.45;}
  .ct-vinculo-n{color:var(--gray); overflow-wrap:anywhere;}
  /* «Sin vincular» se dice más flojo que un vínculo puesto: es la ausencia del
     dato, no el dato. */
  .ct-vinculo-n.mute{color:var(--gray-soft);}
  .ct-vinculo .op-link{margin-top:0; font-size:11.5px;}
  .ct-val{font-size:13.5px; font-weight:500; color:var(--ink); line-height:1.5;}
  /* Una línea, no una tarjeta más: dentro del panel los bloques se separan
     con aire y un filete, que es más callado que meter cada uno en su caja. */
  .ct-sep{height:1px; background:var(--line-soft); margin:18px 0;}
  /* El estado: UNA pieza, el desplegable. Llevaba además una pastilla al
     lado, y las dos decían lo mismo — dos elementos para un dato hacen dudar
     de cuál manda. El color no se pierde con la pastilla: lo lleva el propio
     campo, con los mismos cuatro colores que usa el resto del módulo. */
  /* Sombreado azul, el de la casa, y no un color por estado. Llevaba verde
     para "vigente", teja para "disputa" y ámbar para "renuncia", y el control
     cambiaba de color solo: parecía una alerta cuando es un campo que se
     elige. El azul dice "esto se puede tocar", que es lo que hace falta
     saber; lo que dice el estado lo dice su texto.
     (Efecto conocido: se pierde el aviso de color cuando un contrato está en
     disputa. Si conviene recuperarlo, el sitio es la pastilla de la lista de
     Alianzas, no este campo.) */
  .ct-estado-campo{margin:0;}
  .ct-estado-campo select{font-size:13px; padding:7px 10px; font-weight:600;
    color:var(--navy); background:#EAF0F8; border-color:#C6D8EC;}
  .ct-estado-campo select:hover{background:#E1EAF6;}
  /* Las personas, ya dentro de la ficha: caben en 340px sin apretarse. */
  .ct-ficha .cto-list{margin-top:10px;}
  .ct-ficha .cto-row + .cto-row{margin-top:12px; padding-top:12px; border-top:1px solid var(--line-soft);}
  .ct-ficha .cto-nm{font-size:13.5px; font-weight:600;}
  .ct-ficha .cto-rol{font-size:11.5px; color:var(--gray); margin-top:1px;}
  .ct-ficha .cto-meta{display:flex; gap:7px; flex-wrap:wrap; align-items:center; margin-top:5px;}
  /* Un campo por renglón. Con dos columnas en 340px, "Urbanización Alto
     Barinas Sur, Calle Fe, Sector Virtudes" caía en cinco líneas cortas. */
  .ct-ficha .rg-campos{grid-template-columns:1fr; gap:13px;}
  .ct-ficha .ct-parte-nm{font-size:12.5px;}

  /* Monto, plazo y fecha: tres datos en fila, cada uno con su rótulo encima.
     Antes eran tres filas de rótulo-a-la-izquierda con los dos lados en
     negrita, y para leer el monto había que pasar por la palabra "Monto". */
  .ct-dl{display:grid; grid-template-columns:repeat(auto-fit,minmax(160px,1fr)); gap:18px 30px;}
  .ct-dl-i{min-width:0;}
  .ct-dl-v{font-size:15px; font-weight:600; color:var(--ink); line-height:1.4;}
  .ct-dl-v .chip{margin-left:6px;}

  .ct-registro{margin-top:22px; padding-top:20px; border-top:1px solid var(--line-soft);}
  .ct-parte{margin-bottom:16px;}
  .ct-parte:last-of-type{margin-bottom:0;}
  .ct-parte-nm{display:flex; align-items:center; gap:9px; flex-wrap:wrap;
               font-size:13px; font-weight:600; color:var(--ink); margin-bottom:10px;}
  .ct-fuente{font-size:11px; color:var(--gray-soft); margin-top:14px;}
  .ct-fuente .op-link{font-size:11.5px; margin-left:6px;}

  .ct-lote{margin-top:22px; padding-top:18px; border-top:1px solid var(--line-soft);}

  /* ---- la sugerencia del asistente de remisión ----
     Un filete a la izquierda y nada más: ni fondo, ni recuadro, ni color de
     aviso. Es una sugerencia, no una alarma ni un resultado — si pesara como
     una tarjeta competiría con las opciones que hay debajo, que son las que
     se pulsan. Tres renglones y ninguno de sobra: qué confianza, a quién
     apunta, y por qué. */
  .cr-sug{border-left:2px solid var(--navy2); padding:2px 0 2px 13px; margin:0 0 20px;}
  .cr-sug-l{font-size:11px; font-weight:500; color:var(--gray-soft); margin-bottom:3px;}
  .cr-sug-n{font-size:15px; font-weight:600; color:var(--ink); line-height:1.3;}
  .cr-sug-d{font-size:12.5px; color:var(--gray); margin-top:3px; line-height:1.5;}

  /* Los textos largos del contrato: un punto menos de cuerpo y una línea más
     de interlínea. Son párrafos de expediente, no titulares. */
  .ct-f .tc-block{padding-top:20px; margin-top:20px; border-top:1px solid var(--line-soft);}
  .ct-f .tc-h{font-size:11.5px; font-weight:500; letter-spacing:0; color:var(--gray-soft); margin-bottom:8px;}
  .ct-f .tc-sub{font-size:12px; font-weight:600; color:var(--ink); margin-bottom:9px;}
  .ct-f .tc-txt{font-size:13.5px; line-height:1.7; color:#2A3442;}
  .ct-f .tc-oblgrid{gap:26px;}
  .ct-f .claus-row{font-size:13px; line-height:1.65; color:#2A3442;}
  .ct-f .claus-list{gap:8px;}
  .ct-f .atn-row{font-size:13.5px;}
  .ct-f .atn-note{border-top-style:solid; border-top-color:var(--line-soft); padding-top:16px; margin-top:16px; font-size:13.5px;}
  .ct-f .a-card > .atn-list + .atn-note{margin-top:18px;}

  /* El carril: mismo criterio de rótulo callado y algo más de aire entre
     campos, que iban a 14px y se leían como un bloque. */
  .ct-f .kvp{gap:17px; padding:18px 20px;}
  .ct-f .kvp .k{font-size:11.5px; font-weight:500; color:var(--gray-soft);}
  .ct-f .kvp .v{font-size:13.5px; font-weight:500;}
  @media (max-width:860px){
    .ct-f .a-main > .a-card{padding:18px 18px;}
  }

  /* ---------- seguimiento (tareas del equipo) ---------- */
  .sg-strip{display:flex; align-items:center; justify-content:space-between; gap:12px; flex-wrap:wrap; background:var(--block); border:1px solid var(--line); border-radius:10px; padding:12px 16px; margin-bottom:16px;}
  .sg-strip .t{font-size:14px; font-weight:800; color:var(--ink);}
  .sg-strip .s{font-size:11.5px; color:var(--gray); margin-left:10px;}
  .sg-nums{display:flex; gap:8px; flex-wrap:wrap;}
  /* El buscador y el responsable son la primera fila de la misma barra que
     .sg-toolbar, así que llevan .tz-inp y se ven igual. */
  .sg-filter{display:flex; gap:10px; margin-bottom:10px; flex-wrap:wrap;}
  .sg-filter input{flex:1 1 260px;}
  /* Ancho fijo por flex-basis, no por width: .tz-inp trae width:100% —vive en
     un carril de 252px— y aquí eso lo mandaba solo a una segunda línea. */
  .sg-filter select{flex:0 0 240px;}
  .sg-group{margin-bottom:18px;}
  .sg-gh{display:flex; align-items:baseline; gap:8px; margin-bottom:8px;}
  .sg-gh .t{font-size:12.5px; font-weight:800; color:var(--ink);}
  .sg-gh .n{font-size:11px; color:var(--gray);}
  .sg-row{display:flex; align-items:flex-start; gap:12px; padding:12px 14px; background:var(--bg); border:1px solid var(--line); border-radius:10px; margin-bottom:8px; cursor:pointer;}
  .sg-row:hover{border-color:#CDD5E1; box-shadow:var(--shadow);}
  .sg-check{flex:0 0 auto; width:20px; height:20px; margin-top:1px; border:2px solid #C7CEDA; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:11px; color:#fff; background:transparent;}
  .sg-check:hover{border-color:var(--navy);}
  .sg-check.on{background:var(--good); border-color:var(--good);}
  .sg-main{flex:1 1 auto; min-width:0;}
  .sg-title{font-size:13.5px; font-weight:700; color:var(--ink); line-height:1.4;}
  /* ---- reuniones: selector de participantes del equipo ----
     Reemplaza al <select multiple>, que exigía Ctrl+clic y desplegaba la
     lista completa. Rejilla de casillas con alto máximo: se marca de un clic
     y, con un equipo grande, se desplaza en vez de estirar el formulario. */
  /* El formulario de reunión, en dos columnas. Son quince campos y la mayoría
     son cortos —fecha, hora, modalidad, país, tipo—: apilados obligaban a
     desplazarse mucho por algo que cabe de sobra a lo ancho, y dejaban la
     minuta con tres líneas de alto al final del todo. Lo que se escribe largo
     lleva la clase "ancho" y ocupa las dos columnas. */
  /* El "Guardado" que aparece al salir de la minuta en la ficha */
  .reu-eco{font-size:10.5px; font-weight:700; color:var(--good, #1E7F5C); margin-left:10px;}

  /* Minuta y acuerdos en la ficha: se leen igual que siempre y se editan
     pulsando encima. En reposo no se ve un campo de formulario —solo el texto—;
     el fondo al pasar por encima es toda la pista de que se puede tocar, que es
     suficiente en un bloque cuyo título ya dice "Minuta". */
  .reu-ver{margin-top:4px; padding:6px 8px; margin-left:-8px; margin-right:-8px;
    border-radius:7px; cursor:text; transition:background .12s;}
  .reu-ver:hover{background:var(--block);}
  .reu-ver:focus-visible{outline:2px solid var(--navy2); outline-offset:1px;}
  .reu-ver.editando{background:transparent; cursor:auto;}
  .reu-ver textarea{width:100%; border:1px solid var(--line); border-radius:8px;
    padding:9px 11px; font-family:inherit; font-size:12.5px; line-height:1.6;
    color:var(--ink); background:var(--bg); resize:vertical;}
  .reu-ver textarea:focus{outline:none; border-color:var(--navy2); box-shadow:0 0 0 3px rgba(0,96,176,.12);}
  .reu-ver-vacio{font-size:12.5px; color:var(--gray-soft);}
  .reu-ver-vacio span{color:var(--navy2); font-weight:600; margin-left:6px;}

  .reu-form{display:grid; grid-template-columns:1fr 1fr; gap:0 18px;}
  .reu-form .ancho{grid-column:1 / -1;}
  @media (max-width:760px){ .reu-form{grid-template-columns:1fr;} }

  /* Los acuerdos, dentro del formulario, son un bloque aparte: se ve que no es
     un campo suelto sino la tarea que va a nacer de la reunión. */
  .reu-bloque{border:1px solid var(--line); border-left:3px solid var(--navy); border-radius:8px;
    padding:13px 14px 14px; margin-bottom:13px; background:var(--block);}
  .reu-bloque-h{font-size:10px; font-weight:800; letter-spacing:.01em;
    color:var(--navy); margin-bottom:11px; display:flex; align-items:center; gap:8px;}
  .reu-bloque .field:last-child{margin-bottom:0;}
  /* Quitar una tarea de la reunión. Discreto pero a la vista —el mismo criterio
     que el ✕ de los documentos del activo—: la acción normal es escribir, no
     borrar, pero quien añadió un bloque de más tiene que poder deshacerlo sin
     adivinar dónde se pulsa. */
  .reu-tarea-x{margin-left:auto; width:22px; height:22px; flex:0 0 auto;
    display:flex; align-items:center; justify-content:center; border:0; padding:0;
    background:transparent; color:var(--gray-soft); font-size:12px; cursor:pointer;
    border-radius:5px; opacity:.55; transition:opacity .12s, background .12s, color .12s;}
  .reu-bloque:hover .reu-tarea-x{opacity:1;}
  .reu-tarea-x:hover{background:var(--rust-bg); color:var(--rust); opacity:1;}
  /* Agregar va DEBAJO de la lista y en el ancho completo: es lo que sigue
     después de la última tarea, no una acción de la cabecera. */
  .reu-tarea-add{width:100%; margin-bottom:13px;}

  /* El campo cerrado resume a quién hay elegido; se abre de un clic. <details>
     nativo, sin JS de apertura ni manejador de "clic fuera". */
  .reu-drop{border:1px solid var(--line); border-radius:8px; background:var(--bg);}
  .reu-drop > summary{list-style:none; cursor:pointer; padding:9px 11px; font-size:12.5px;
    color:var(--ink); display:flex; align-items:center; gap:8px;
    text-transform:none; letter-spacing:0; font-weight:400;}
  .reu-drop > summary::-webkit-details-marker{display:none;}
  .reu-drop > summary::after{content:''; margin-left:auto; flex:0 0 auto; width:7px; height:7px;
    border-right:1.5px solid var(--gray-soft); border-bottom:1.5px solid var(--gray-soft);
    transform:rotate(45deg) translateY(-2px);}
  .reu-drop[open] > summary{border-bottom:1px solid var(--line-soft);}
  .reu-drop[open] > summary::after{transform:rotate(-135deg) translateY(1px);}
  .reu-chks{display:grid; grid-template-columns:repeat(auto-fill,minmax(148px,1fr)); gap:1px 10px;
    border:0; border-radius:0 0 8px 8px;
    padding:7px 9px; background:var(--bg);}
  /* El tope de alto y el scroll propio solo cuando .reu-chks vive dentro de un
     modal (editar reunión): ahí sí corresponde, mismo criterio que #modal
     .kl-body/.ps-hijos. En "Nueva reunión" (página completa, no modal) esto
     mismo rodaba dos veces —la página y esta lista— y se retira, igual que
     los casos ya resueltos en "Fuera el doble scroll en todo el sistema". */
  #modal .reu-chks{max-height:168px; overflow-y:auto;}
  /* .reu-chks .reu-chk y no .reu-chk a secas: son <label> dentro de un .field,
     y `.field label` los pondría en mayúsculas, en negrita y en bloque. */
  .reu-chks .reu-chk{display:flex; align-items:center; gap:7px; font-size:12.5px; color:var(--ink);
    margin:0; padding:4px; border-radius:5px; cursor:pointer;
    text-transform:none; letter-spacing:0; font-weight:400;}
  .reu-chks .reu-chk:hover{background:var(--block);}
  .reu-chks .reu-chk input{margin:0; cursor:pointer; flex:0 0 auto; width:auto;}
  .reu-chks .reu-chk span{min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}

  .sg-detalle{font-size:12px; color:var(--gray); margin-top:3px; line-height:1.5;}
  /* "+N" cuando la tarea tiene más de un responsable */
  .sg-rmas{font-size:9.5px; font-weight:800; color:var(--gray-soft); background:var(--block);
    border:1px solid var(--line-soft); border-radius:20px; padding:1px 5px; margin-left:5px;}
  /* detalle de varias líneas (los acuerdos de una reunión): una viñeta por línea */
  .sg-detalle-lista{margin:4px 0 0; padding-left:16px;}
  .sg-detalle-lista li{margin:1px 0;}
  .sg-chips{display:flex; gap:6px; flex-wrap:wrap; margin-top:7px; align-items:center;}
  /* Las etiquetas son nowrap; sin este tope, una sola larga —el checkpoint de
     una alianza dice el estado y los días— se sale de la fila en vez de
     recortarse. Mismo caso que .kcard .chip. */
  .sg-chips .chip{max-width:100%; min-width:0; overflow:hidden; text-overflow:ellipsis; display:inline-block;}
  .sg-chips .op-link{font-size:11px;}
  .sg-link{cursor:pointer;}
  .sg-link:hover{color:var(--navy); border-color:#CDD5E1;}
  .sg-resp{flex:0 0 auto; display:flex; align-items:center; gap:7px; max-width:190px;}
  /* overflow:hidden como red: el círculo es de 24px y cualquier valor más
     largo que dos iniciales se salía por los lados en vez de recortarse. Así
     un dato inesperado se ve feo dentro del círculo, no derramado sobre la
     tarjeta. */
  .sg-av{width:24px; height:24px; border-radius:50%; background:var(--navy); color:#fff; font-size:9px; font-weight:800; display:flex; align-items:center; justify-content:center; flex:0 0 auto; overflow:hidden;}
  .sg-rn{font-size:11px; color:var(--gray); white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
  /* Lo que lleva uno mismo, marcado en la propia fila. Solo cambia el color
     —el círculo en el azul de la casa y «Tú» en vez del nombre—: con veinte
     filas, un recuadro o un fondo por cada tarea propia convertiría la lista
     en un tablero de colores donde otra vez no destaca nada. */
  .sg-resp.mia .sg-av{background:var(--cyan-deep);}
  .sg-resp.mia .sg-rn{color:var(--navy); font-weight:700;}
  /* ---- la fila de una alianza ----
     Sector, estatus, plazo y días sin contacto en una línea de texto, no en
     pastillas: son cuatro datos por fila y con sesenta y tres alianzas eran
     un mosaico de color donde nada resaltaba. Solo se pinta lo que pide una
     acción —contrato en disputa o en renuncia, checkpoint vencido— y se pinta
     el texto, no un recuadro detrás. */
  .proy-meta{font-size:11.5px; color:var(--gray); margin-top:5px; line-height:1.5;}
  /* Solo el color cambia. En negrita además, y con la mitad de las alianzas
     sin contacto desde hace más de 180 días, la línea volvía a gritar. */
  .proy-meta .alerta{color:var(--rust);}
  /* El monto ocupa en .sg-row el sitio del responsable de una tarea: a la
     derecha, alineado, porque es lo único que se lee comparando una fila con
     otra. Cifras tabulares para que las comas caigan en la misma columna
     aunque las cantidades tengan distinto largo. */
  .proy-monto{flex:0 0 auto; text-align:right; max-width:190px; font-size:13px; font-weight:700;
              color:var(--ink); font-variant-numeric:tabular-nums; white-space:nowrap; padding-top:1px;}
  .proy-monto.vacio{font-weight:500; color:var(--gray-soft);}
  @media (max-width:640px){ .proy-monto{display:none;} }

  .sg-row.done{opacity:.75; background:var(--block);}
  .sg-row.done .sg-title{font-weight:600; color:var(--gray);}
  .sg-trail{margin-top:26px; padding-top:16px; border-top:1px dashed var(--line);}
  .sg-quick{display:flex; gap:8px; flex-wrap:wrap; align-items:center; background:var(--block); border:1px solid var(--line); border-radius:10px; padding:10px 12px; margin-bottom:16px;}
  .sg-quick input[type=text], .sg-quick select{border:1px solid var(--line); border-radius:8px; padding:9px 11px; font-family:inherit; font-size:12.5px; color:var(--ink); background:var(--bg);}
  .sg-quick input[type=text]:focus{outline:none; border-color:var(--navy2);}
  .sg-quick .qa-t{flex:2 1 240px;}
  .sg-quick .qa-tema{flex:1 1 150px;}
  .sg-quick label{display:flex; align-items:center; gap:6px; font-size:11.5px; color:var(--gray); white-space:nowrap; cursor:pointer;}
  @media (max-width:640px){ .sg-rn{display:none;} .sg-row{padding:11px 12px;} .sg-strip .s{display:block; margin-left:0; margin-top:2px;} }

  /* ---- seguimiento: tablero ---- */
  .sg-kdone{opacity:.72; background:var(--block);}
  .sg-kdone .kc-name{color:var(--gray); font-weight:600;}
  .sg-kvacio{font-size:11px; color:var(--gray-soft); text-align:center; padding:18px 6px; border:1px dashed #C7CEDA; border-radius:8px;}
  .sg-note{font-size:11px; color:var(--gray-soft); margin-top:12px; line-height:1.55;}
  .kcard[draggable=true]{cursor:grab;}

  /* ---- seguimiento: calendario ---- */
  .sg-tray{display:flex; align-items:stretch; gap:10px; background:var(--block); border:1px dashed #C7CEDA; border-radius:10px; padding:10px 12px; margin-bottom:12px; flex-wrap:wrap;}
  .sg-tray .lbl{font-size:10px; font-weight:800; letter-spacing:.01em; color:var(--gray-soft); padding:8px 2px; white-space:nowrap;}
  .sg-tray .kcard{flex:0 1 230px; margin:0;}
  .sg-tray-ok{font-size:11.5px; color:var(--gray); padding:8px 0;}
  .sg-cal{display:grid; grid-template-columns:repeat(5,minmax(0,1fr)); gap:10px;}
  .sg-day{background:var(--block); border:1px solid var(--line); border-radius:10px; padding:9px; min-height:170px; min-width:0;}
  .sg-day.today{background:#EFF6FF; border-color:#BDD7F2;}
  .sg-day .kcard{margin-bottom:8px;}
  .sg-day-h{display:flex; align-items:baseline; gap:6px; margin-bottom:9px; padding:0 2px;}
  .sg-day-h .d{font-size:12px; font-weight:800;}
  .sg-day.today .sg-day-h .d{color:var(--navy);}
  .sg-day-h .n{font-size:10px; color:var(--gray-soft);}
  .sg-day-h .hoy{margin-left:auto; font-size:8.5px; font-weight:800; letter-spacing:.08em; text-transform:capitalize; color:var(--navy); background:rgba(0,64,144,.10); border-radius:10px; padding:2px 7px;}
  .sg-waitlane{margin-top:12px; background:var(--amber-bg); border:1px solid #F0DFB8; border-radius:10px; padding:10px 12px;}
  .sg-waitlane .lbl{font-size:10px; font-weight:800; letter-spacing:.01em; color:var(--amber); margin-bottom:8px;}
  .sg-waitrow{display:flex; align-items:center; gap:10px; background:var(--bg); border:1px solid var(--line); border-radius:8px; padding:8px 11px; margin-bottom:6px; flex-wrap:wrap; cursor:pointer;}
  .sg-waitrow:last-child{margin-bottom:0;}
  .sg-waitrow:hover{border-color:#CDD5E1;}
  .sg-waitrow .t{font-size:12px; font-weight:700; flex:1 1 240px;}
  .sg-waitrow .k{font-size:10.5px; color:var(--gray); white-space:nowrap;}

  /* ---- seguimiento: plan (cronograma) ---- */
  .sg-gt{overflow-x:auto;}
  .sg-ghead{display:flex; margin-left:240px; border-bottom:1px solid var(--line); min-width:700px;}
  .sg-gw{font-size:10px; font-weight:700; color:var(--gray-soft); padding:6px 8px; border-left:1px solid var(--line-soft);}
  .sg-gw.cur{color:var(--navy); background:#F4F9FF; font-weight:800;}
  .sg-gbody{position:relative; min-width:940px;}
  .sg-gtoday{position:absolute; top:0; bottom:0; width:2px; background:var(--cyan); z-index:3;}
  .sg-gtoday::after{content:"hoy"; position:absolute; top:0; left:5px; font-size:8.5px; font-weight:800; letter-spacing:.06em; text-transform:capitalize; color:var(--cyan-deep);}
  .sg-ggroup{font-size:11px; font-weight:800; letter-spacing:.01em; color:var(--gray); padding:14px 0 6px 2px;}
  .sg-grow{display:flex; align-items:center; min-height:34px; border-bottom:1px solid var(--line-soft); cursor:pointer;}
  .sg-grow.hitos{cursor:default;}
  .sg-grow:hover:not(.hitos){background:var(--block);}
  .sg-glabel{flex:0 0 240px; font-size:12px; font-weight:600; padding-right:14px; display:flex; align-items:center; gap:7px; min-width:0;}
  .sg-glabel .tx{overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  .sg-grow.hitos .sg-glabel{color:var(--gray-soft); font-weight:600; font-size:11px;}
  .sg-gtrack{flex:1; position:relative; height:34px; background:repeating-linear-gradient(90deg, var(--line-soft) 0 1px, transparent 1px calc(100%/26*7));}
  .sg-gbar{position:absolute; top:8px; height:18px; border-radius:5px; background:var(--navy2); color:#fff; font-size:9.5px; font-weight:700; display:flex; align-items:center; padding:0 8px; white-space:nowrap; overflow:hidden;}
  .sg-gbar.prio{background:var(--navy);}
  .sg-gbar.wait{background:repeating-linear-gradient(45deg, #D9A94E 0 6px, #C99838 6px 12px); color:#5d420f;}
  .sg-gmile{position:absolute; top:11px; width:11px; height:11px; background:var(--ink); transform:rotate(45deg); border-radius:2px;}
  .sg-gmile-lbl{position:absolute; top:1px; font-size:9px; font-weight:700; color:var(--gray); white-space:nowrap;}
  .sg-gleg{display:flex; gap:16px; margin-top:14px; font-size:10.5px; color:var(--gray); flex-wrap:wrap; align-items:center; min-width:700px;}
  .sg-gleg .sw{display:inline-block; width:14px; height:10px; border-radius:3px; margin-right:5px; vertical-align:-1px;}
  .sg-gleg .sw-wait{background:repeating-linear-gradient(45deg,#D9A94E 0 4px,#C99838 4px 8px);}

  /* ---- seguimiento: centro de control ---- */
  .sg-stats{display:grid; grid-template-columns:repeat(4,1fr); gap:12px; margin-bottom:14px;}
  .sg-stat{background:var(--bg); border:1px solid var(--line); border-radius:10px; padding:12px 14px;}
  .sg-stat .n{font-size:22px; font-weight:800; letter-spacing:-.02em;}
  .sg-stat .l{font-size:10.5px; color:var(--gray); margin-top:2px; line-height:1.4;}
  .sg-stat.bad .n{color:var(--rust);}
  .sg-stat.warnn .n{color:var(--amber);}
  .sg-cc{display:grid; grid-template-columns:1.35fr 1fr; gap:14px; align-items:start;}
  .sg-ccard{background:var(--bg); border:1px solid var(--line); border-radius:10px; padding:14px 16px; margin-bottom:14px;}
  .sg-ccard:last-child{margin-bottom:0;}
  .sg-ccard .h{display:flex; align-items:baseline; gap:8px; margin-bottom:10px; flex-wrap:wrap;}
  .sg-ccard .h .t{font-size:12px; font-weight:800; letter-spacing:.01em; color:var(--gray);}
  .sg-ccard .h .s{font-size:10.5px; color:var(--gray-soft);}
  .sg-urow{display:flex; align-items:center; gap:9px; padding:8px 0; border-bottom:1px solid var(--line-soft); flex-wrap:wrap; cursor:pointer;}
  .sg-urow:last-child{border-bottom:none;}
  .sg-urow:hover .t{color:var(--navy);}
  .sg-urow .t{font-size:12.5px; font-weight:700; flex:1 1 220px;}
  .sg-brow{display:flex; align-items:center; gap:9px; margin-bottom:8px;}
  .sg-brow .who{flex:0 0 170px; font-size:11px; color:var(--gray); display:flex; align-items:center; gap:7px; min-width:0;}
  .sg-brow .bar{flex:1; height:9px; background:var(--block); border-radius:6px; overflow:hidden;}
  .sg-brow .bar i{display:block; height:100%; background:var(--navy2); border-radius:6px;}
  .sg-brow .n{font-size:10.5px; font-weight:700; color:var(--gray); width:16px; text-align:right;}
  .sg-rit{display:flex; gap:9px; padding:7px 0; border-bottom:1px solid var(--line-soft); font-size:12px; color:var(--gray); line-height:1.5;}
  .sg-rit:last-child{border-bottom:none;}
  .sg-rit .d{flex:0 0 56px; font-size:10px; font-weight:800; letter-spacing:.01em; color:var(--navy); padding-top:2px;}
  @media (max-width:960px){ .sg-cc{grid-template-columns:1fr;} .sg-stats{grid-template-columns:1fr 1fr;} }
  @media (max-width:860px){ .sg-cal{grid-template-columns:repeat(2,minmax(0,1fr));} }
  @media (max-width:560px){ .sg-cal{grid-template-columns:1fr;} .sg-day{min-height:0;} }

  /* ---------- inteligencia: el panel de la Presidencia ----------
     Casi todo se dibuja con primitivas que ya existían y que este panel
     comparte con la reportería de Correspondencia: barras horizontales
     (.in-rrow, aquí abajo), segmentos apilados (.in-sbar) y columnas por mes
     (.cr-cols). Lo propio es poco —la cifra grande, la fila de cifras
     chicas, el tooltip y la hoja carta— y está al final de este bloque.

     Lo que había antes aquí (embudo, franja de alertas, cola priorizada,
     mapa de calor, relato, mapa de burbujas y el selector de forma por
     sección) se retiró con las cuatro vistas que lo usaban. Sigue en el
     historial de Git, hasta 15507af. */
  /* Barras horizontales: la primitiva de gráfico más reusada de Atlas —este
     panel, Correspondencia y Contrapartes dibujan con ella. Geometría fija a
     propósito: rótulo de ancho fijo, pista que ocupa TODO el hueco que queda
     y columna de valor de ancho fijo. Así dos barras de dos tarjetas
     distintas empiezan y terminan en la misma vertical y se pueden comparar
     con la vista, que es justo lo que se le pide a un panel. */
  .in-rrow{display:flex; align-items:center; gap:10px; padding:7px 0;}
  .in-rrow .rl{width:140px; flex:0 0 auto; font-size:12.5px; font-weight:700; color:var(--ink); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  .in-rrow .rl small{display:block; font-weight:500; color:var(--gray); font-size:11px;}
  .in-rrow .rtrack{flex:1 1 auto; height:14px; border-radius:4px; background:var(--block); overflow:hidden;}
  .in-rrow .rfill{height:100%; border-radius:4px; background:linear-gradient(90deg, var(--navy), var(--cyan-deep));}
  .in-rrow .rv{width:84px; flex:0 0 auto; font-size:12.5px; font-weight:800; color:var(--ink); text-align:right;}
  .in-rrow .rv small{display:block; font-weight:600; color:var(--gray); font-size:11px;}
  /* Correspondencia (crBarras, siempre dentro de .cr-scroll-y): 84px se
     quedaba corto para "$9.290 M (73%)" en negrita, así que esa fila
     envolvía a 2 líneas mientras las demás ("$150 M (1%)") cabían en 1 —
     se veía dispareja. Ancho automático + sin salto de línea: cada fila
     usa solo lo que su propio valor necesita, y como el resto de la fila
     (.rl fijo + .rtrack flexible) sigue ocupando el mismo ancho total, el
     borde derecho de los valores queda alineado entre filas igual.
     Acotado a .cr-scroll-y (exclusivo de ese archivo) para no tocar a
     Contrapartes, que usa .in-rrow con el ancho fijo de siempre. El panel de
     inteligencia hace lo propio con .in-panel, más abajo. */
  .cr-scroll-y .rv{width:auto; white-space:nowrap;}
  /* fila de barra clicable (Correspondencia · Próximas acciones) — mismo
     criterio que .stat.clic arriba: fondo #EEF5FC de .enteli.on, hover con
     el mismo var(--block) que ya usa .cr-top-row en este archivo. */
  .in-rrow.clic{cursor:pointer; border-radius:7px; transition:background-color .12s ease;}
  .in-rrow.clic:hover{background:var(--block);}
  .in-rrow.clic.on{background:#EEF5FC;}
  .in-rrow.clic.on .rl{color:#B87315; font-weight:700;}
  /* con una fila seleccionada, las demás de ESE panel quedan en azul claro
     (#A0C4E2, ver crBarras) en vez del color propio del panel — más claro
     de un vistazo que una simple atenuación por opacidad. */
  .in-rrow.clic.dim .rl{color:var(--gray);}

  /* ---- cards de datos (Diligencia) ---- */
  .in-cardgrid{display:grid; grid-template-columns:repeat(auto-fill,minmax(160px,1fr)); gap:10px;}
  .in-minicard{border:1px solid var(--line); border-radius:8px; padding:12px 14px; background:var(--block);}
  .in-minicard.clic{cursor:pointer;} .in-minicard.clic:hover{border-color:var(--navy2);}
  .in-minicard .mc-t{font-size:12.5px; font-weight:700; color:var(--ink);}
  .in-minicard .mc-sub{display:block; font-weight:500; color:var(--gray); font-size:11px; margin-top:1px;}
  .in-minicard .mc-n{font-size:19px; font-weight:800; color:var(--navy); margin:6px 0 2px;}
  .in-minicard .mc-s{font-size:11px; color:var(--gray);}
  .in-minicard .mc-stats{display:flex; flex-wrap:wrap; gap:8px 14px; margin:8px 0 2px; font-size:11px; color:var(--gray);}
  .in-minicard .mc-stats b{display:block; font-size:13.5px; font-weight:800; color:var(--ink);}
  .in-minicard .mc-txt{font-size:12.5px; color:var(--ink); line-height:1.45;}
  .in-minicard .mc-txt b{font-weight:700;}
  .in-minicard.sev-crit{border-left:3px solid var(--rust);}
  .in-minicard.sev-warn{border-left:3px solid var(--amber);}
  .in-minicard.sev-info{border-left:3px solid var(--cyan-deep);}

  /* 2px de aire entre tramos: sin él dos sectores contiguos se leen como uno */
  .in-sbar{display:flex; gap:2px; height:20px; border-radius:5px; overflow:hidden; margin:14px 0 10px;}
  .in-sbar span{height:100%;}
  .in-sbar-legend{display:flex; flex-wrap:wrap; gap:10px 16px; font-size:11px; color:var(--gray); margin-bottom:24px;}
  .in-sbar-legend i{width:8px; height:8px; border-radius:2px; display:inline-block; margin-right:5px; vertical-align:middle;}

  /* ---- lo propio del panel de la Presidencia ---- */
  /* Una sola columna de valor para todo el panel, y más ancha que los 84px
     de partida: con "US$ 12.480 M" en negrita el ancho de siempre partía el
     monto en dos líneas y las filas quedaban dispares. Acotado a .in-panel
     —que llevan la pantalla y la hoja carta— para no tocar a nadie más. */
  .in-panel .in-rrow .rv{width:112px; white-space:nowrap;}
  /* El conteo va bajo el NOMBRE y no bajo el valor: así la columna de la
     derecha se queda en una sola línea de monto y el borde de los montos
     cae a plomo en todas las tarjetas. */
  .in-panel .in-rrow .rl small{margin-top:1px;}
  /* La tabla de Inversionistas. Cuatro columnas —quién, de dónde, cuántos
     proyectos y cuánto—, que es lo que hay que saber de un inversionista sin
     abrir su expediente. Va en tabla y no en barras porque los nombres reales
     son largos y los montos van de US$ 10.000 M a US$ 800 M: las barras de
     abajo quedaban en un muñón y el país salía cortado. Ver inTablaEmpresas. */
  .in-tinv td{cursor:pointer;}
  .in-tinv tbody tr:hover{background:var(--block);}
  .in-tinv .in-td-monto{font-weight:800; white-space:nowrap; text-align:right;}
  .in-tinv th:last-child{text-align:right;}
  .in-tinv .in-tr-otros{color:var(--gray);}
  .in-tinv .in-tr-otros b{font-weight:700;}
  /* lo desplegado dentro de «Otros»: sangrado y sobre el mismo gris que usa
     la variante de barras, para que se lea como el interior de esa fila */
  .in-tinv .in-tr-dentro{background:var(--block);}
  .in-tinv .in-tr-dentro td:first-child{padding-left:26px;}
  .in-tinv .in-tr-dentro b{font-weight:600;}
  /* «Otros» se abre: el signo dice en qué estado está, y lo desplegado va
     sangrado y sobre un fondo apenas distinto para que se lea como lo que es
     —el interior de esa fila— y no como cinco categorías más del ranking.
     Rueda por dentro: en «Países de origen» la cola puede traer veinte. */
  /* sin acotar a .in-rrow: el mismo signo lo lleva la fila «Otros» de la
     tabla de Inversionistas */
  .caret{display:inline-block; width:14px; color:var(--gray-soft); font-size:9px;
    vertical-align:middle; margin-right:2px;}
  .in-rrow.resto.clic:hover .caret{color:var(--ink);}
  .in-desplegado{background:var(--block); border-radius:8px; padding:2px 10px; margin:2px 0 6px;
    max-height:270px; overflow-y:auto;}
  .in-desplegado .in-rrow{padding:5px 0;}
  .in-desplegado .in-rrow .rl{font-size:12px;}
  .in-desplegado .in-rrow + .in-rrow{border-top:1px solid var(--line-soft);}
  /* La fila del "Resto": una línea de total, no una barra. Sin pista de fondo
     —que ahí no hay nada que medir— y con un filete arriba que la separa de
     las categorías de verdad. */
  .in-panel .in-rrow.resto{margin-top:4px; padding-top:11px; border-top:1px solid var(--line);}
  .in-panel .in-rrow.resto .rl, .in-panel .in-rrow.resto .rv{color:var(--gray);}
  .in-panel .in-rrow.resto .rtrack{background:none;}
  /* la cifra grande: una sola en toda la pantalla, y con cifras
     proporcionales, no tabulares — a este tamaño el ancho fijo de dígito
     deja el número suelto */
  .in-cifra{display:flex; flex-wrap:wrap; align-items:center; gap:18px 40px;}
  .in-cifra-n{flex:0 0 auto;}
  .in-cifra-n .n{font-size:48px; font-weight:800; letter-spacing:-.025em; line-height:1; color:var(--navy);}
  .in-cifra-n .m{font-size:12.5px; color:var(--gray); margin-top:8px;}
  .in-cifra-b{flex:1 1 280px; min-width:240px;}
  .in-cifra-b .in-sbar{margin:0 0 9px;}
  .in-cifra-b .in-sbar-legend{margin:0;}
  /* La tira de tres cifras con la que abren las tarjetas que resumen otro
     módulo (inversionistas, solicitudes, banco de activos, oportunidades).
     Rejilla de tres columnas iguales y no flex: así las cuatro tarjetas miden
     exactamente lo mismo de alto, que es lo que alinea las parejas de la
     rejilla. Alto fijo por la misma razón — un valor largo que envolviera a
     dos líneas descuadraría solo esa tarjeta. */
  .in-cifras3{display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:10px;
    padding-bottom:12px; margin-bottom:8px; border-bottom:1px solid var(--line-soft);}
  .in-cifras3 > div{min-width:0;}
  .in-cifras3 b{display:block; font-size:17px; font-weight:800; color:var(--ink); line-height:1.2;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
  .in-cifras3 span{display:block; font-size:11px; color:var(--gray); line-height:1.3;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
  /* la fila de filtros reusa .sg-toolbar, que es quien trae las variables
     --tz-* de las que viven .tz-inp y .sg-sel */
  .in-fl .sg-fld .seg{margin:0;}
  .in-fl .btn{height:35px;}
  /* El mapa de oportunidades: el dibujo a la izquierda, el detalle de lo
     señalado a la derecha. Por debajo de 900px se apilan. */
  .in-mapa{display:flex; gap:18px; align-items:stretch;}
  .in-mapa .in-geo{flex:1 1 460px; min-width:0;}
  .in-mapa-det{flex:1 1 300px; min-width:0; max-width:400px; display:flex; flex-direction:column;}
  .in-mapa-h{display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; padding-bottom:9px;
    margin-bottom:4px; border-bottom:1px solid var(--line);}
  .in-mapa-h b{font-size:14px; font-weight:800; color:var(--ink);}
  .in-mapa-h span{font-size:11.5px; color:var(--gray);}
  .in-mapa-h .op-link{margin-left:auto;}
  /* Alto atado al del mapa (400px) menos su cabecera: la lista rueda por
     dentro en vez de estirar la tarjeta cuando un estado trae quince
     oportunidades. */
  .in-mapa-list{flex:1 1 auto; overflow-y:auto; max-height:352px;}
  /* Fila y columna EXPLÍCITAS en las tres celdas: con solo `grid-row` en el
     monto, la colocación automática le daba la primera columna y mandaba el
     nombre del estado a la derecha. */
  .in-mapa-it{display:grid; grid-template-columns:1fr auto; gap:1px 10px;
    padding:8px 6px; border-bottom:1px solid var(--line-soft); cursor:pointer; border-radius:6px;}
  .in-mapa-it:last-child{border-bottom:none;}
  .in-mapa-it:hover{background:var(--block);}
  .in-mapa-it .mi-t{grid-column:1; grid-row:1; font-size:12.5px; font-weight:700; color:var(--ink); line-height:1.3;}
  .in-mapa-it .mi-m{grid-column:1; grid-row:2; font-size:11px; color:var(--gray-soft);}
  .in-mapa-it .mi-v{grid-column:2; grid-row:1 / span 2; font-size:12.5px; font-weight:800; color:var(--ink);
    white-space:nowrap; align-self:center;}
  .in-mapa-pie{font-size:11px; color:var(--gray-soft); padding-top:9px; margin-top:4px;
    border-top:1px solid var(--line-soft);}
  /* el dibujo: burbuja por estado sobre el contorno del país.
     Dos cajas y no una: .in-geo es el mar —ocupa lo que le den y solo pone el
     alto y el color—, y .in-geo-lienzo es el país, que tiene que salir con su
     forma. El <svg> se estira con preserveAspectRatio="none" sobre una ventana
     de 18,5° de longitud por 12,6° de latitud, así que la caja que lo contiene
     manda en la forma: a 1,468 de ancho por 1 de alto Venezuela sale como es, y
     a cualquier otra proporción sale estirada. El lienzo crece con el ancho
     disponible hasta que su alto llega al de la caja (--in-geo-h), y de ahí no
     pasa; lo que sobra a los lados queda de mar. */
  .in-geo{--in-geo-h:400px; position:relative; height:var(--in-geo-h);
    border-radius:10px; overflow:hidden; display:flex; align-items:center; justify-content:center;}
  .in-geo-lienzo{position:relative; width:100%; max-width:calc(var(--in-geo-h) * 1.468); aspect-ratio:1.468;}
  /* Sin aspect-ratio (Safari anterior a 15) el lienzo se quedaría sin alto y
     el mapa desaparecería: allí vuelve a llenar la caja, estirado como antes
     pero visible. */
  @supports not (aspect-ratio:1/1){ .in-geo-lienzo{height:100%; max-width:none;} }
  .in-geo-b{position:absolute; transform:translate(-50%,-50%); border-radius:50%; cursor:pointer;
    display:flex; align-items:center; justify-content:center;
    box-shadow:0 2px 8px rgba(14,20,36,.18), inset 0 0 0 2px rgba(255,255,255,.35);
    transition:transform .12s;}
  .in-geo-b:hover{transform:translate(-50%,-50%) scale(1.06); z-index:4;}
  .in-geo-b.on{outline:3px solid var(--ink); outline-offset:1px; z-index:5;}
  .in-geo-b .v{font-size:10px; font-weight:800; white-space:nowrap;}
  .in-geo-l{position:absolute; transform:translate(-50%,0); font-size:9.5px; font-weight:700;
    color:var(--gray); white-space:nowrap; pointer-events:none; text-shadow:0 1px 0 rgba(255,255,255,.8);}
  /* La hoja del PDF mide 816px SIEMPRE, sea cual sea la ventana desde la que
     se exporte, así que su composición no puede depender del ancho del
     navegador: acotado a #inBody —la pantalla— y no a .in-mapa a secas.
     Sin esto, exportar con la ventana por debajo de 900px apilaba el mapa y
     soltaba el alto de la lista, y la página del mapa pasaba de 470px a
     1.440: se salía de la hoja y se partía por la mitad. */
  @media (max-width:900px){
    #inBody .in-mapa{flex-direction:column;}
    #inBody .in-mapa-det{max-width:none;}
    #inBody .in-mapa-list{max-height:none;}
  }
  /* En papel el mapa va a los 724px completos de la caja de texto, así que el
     alto es el que pide esa misma proporción: 724 / 1,468 = 493. Aquí el
     lienzo llena la caja entera y no queda mar de sobra a los lados. */
  .in-hoja-mapa .in-geo{--in-geo-h:493px; margin-bottom:14px;}
  /* Tooltip de las marcas. El valor va primero y en negrita: quien pasa el
     ratón ya sabe sobre qué está: lo que quiere es el número. Nunca es la
     única forma de leer un valor —todos están escritos en la barra o en la
     columna, y la vista Tabla los da todos— así que no hace falta llevarlo
     también al teclado. */
  .in-tip{position:fixed; z-index:60; pointer-events:none; opacity:0; transition:opacity .1s ease;
    background:var(--ink); color:#fff; border-radius:7px; padding:7px 10px; max-width:260px;
    box-shadow:0 6px 20px rgba(14,20,36,.28);}
  .in-tip.on{opacity:1;}
  .in-tip b{display:block; font-size:13px; font-weight:800; line-height:1.2;}
  /* pre-line: el rótulo de una fase trae debajo, en su propia línea, los
     pasos que la componen (ver inEtapaHtml). El resto de los rótulos no
     llevan salto y se ven igual que antes. */
  .in-tip span{display:block; font-size:11px; color:#C7D0DD; margin-top:2px; white-space:pre-line;}
  /* La hoja carta que exporta inExportarPDF. 816px son las 8,5 pulgadas a 96
     ppp: el mismo papel que la ficha para inversionista. Se arma dentro del
     documento de la aplicación, así que hereda estas reglas y las de las
     barras sin tener que copiarle ninguna. */
  .in-hoja{width:816px; background:#fff; padding:0 0 46px; color:var(--ink);}
  /* la banda azul con el logo en blanco de los documentos de la casa
     (plantillas/plantilla_ficha_inversor.html) */
  .in-hoja-banda{background:var(--navy-deep); display:flex; align-items:center; gap:12px; padding:13px 46px;}
  .in-hoja-banda img{height:30px; width:auto; display:block;}
  .in-hoja-banda span{color:#fff; font-size:9px; font-weight:600; letter-spacing:.4px; line-height:1.4;}
  .in-hoja-head{position:relative; border-bottom:2px solid var(--navy); margin:26px 46px 22px; padding-bottom:14px;}
  .in-hoja-sec, .in-hoja-2col{margin-left:46px; margin-right:46px;}
  .in-hoja-2col .in-hoja-sec{margin-left:0; margin-right:0;}
  .in-hoja-h1{font-size:23px; font-weight:800; letter-spacing:-.01em; color:var(--navy);}
  .in-hoja-h2{font-size:12.5px; color:var(--gray); margin-top:3px;}
  .in-hoja-f{position:absolute; right:0; bottom:14px; font-size:11px; color:var(--gray-soft);}
  .in-hoja-sec{margin-bottom:22px;}
  .in-hoja-t{font-size:11px; font-weight:800; letter-spacing:.02em; text-transform:uppercase; color:var(--navy);
    border-bottom:1px solid var(--line); padding-bottom:5px; margin-bottom:10px;}
  .in-hoja-corte{page-break-before:always; break-before:page; padding-top:14px;}
  .in-hoja-2col{display:flex; gap:26px;}
  .in-hoja-2col .in-hoja-sec{flex:1 1 0; min-width:0;}
  /* A media hoja hay que repartir distinto: 140px de rótulo se comerían la
     pista, pero por debajo de 132 se corta el rótulo pequeño más largo de
     todos ("se traba en Formalización", en Tiempo por etapa) y deja la frase
     a medias. El ancho está medido contra ese caso, no elegido a ojo. */
  .in-hoja-2col .in-rrow .rl{width:132px;}
  .in-hoja-2col .in-rrow .rv{width:84px;}
  .in-hoja-vacio{font-size:12px; color:var(--gray-soft); padding:6px 0;}
  .in-hoja .in-cifra-n .n{font-size:40px;}
  .in-hoja-tbl{width:100%;}
  .in-hoja-tbl td div{color:var(--gray); font-size:11px;}
  @media (max-width:700px){ .in-cifra-n .n{font-size:38px;} }

  /* ---- documentos: icono de archivo con símbolo + formato ---- */
  .dc-ic{flex-direction:column; gap:2px; width:34px; height:40px; border-radius:8px;}
  .dc-ic svg{width:14px; height:14px; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; stroke-linejoin:round; display:block;}
  .dc-ic span{font-size:6.5px; font-weight:800; letter-spacing:.05em; line-height:1;}

  /* ---- seguimiento: checkboxes del formulario, en línea y alineados ---- */
  /* Una casilla que hace de ETIQUETA de su campo: mismo hueco de 5px que una
     etiqueta normal, y en su propio tamaño —no el de 10px en mayúsculas de
     .field label, que a una frase con casilla la vuelve ilegible—. align-items
     center para que el cuadrito quede a la altura del texto y no colgando. */
  .reu-check{display:flex !important; align-items:center; gap:8px; margin:0 0 5px !important;
    font-size:12px !important; font-weight:600 !important; letter-spacing:0 !important;
    text-transform:none; color:var(--ink) !important; cursor:pointer;}
  .reu-check input{width:15px; height:15px; margin:0; accent-color:var(--navy); cursor:pointer;}
  .reu-form select:disabled{background:var(--block); color:var(--gray-soft); cursor:default;}

  /* ===================== FORMULARIO LEGIBLE (.form-amable) =====================
     El vestido base de un formulario de Atlas (.field label) es de 10 px, en
     gris apagado y en mayúsculas: se lee como el pie de una tabla, no como la
     pregunta que hay que contestar. En una ventana de 440 px con diez campos
     seguidos —editar una tarea— eso da justo lo que se reportó: "se ve súper
     chiquito y poco amigable".

     Esto NO cambia los 227 campos del sistema: es una clase que se pone en el
     formulario que la quiera, y hoy la lleva el de tareas. El día que se
     decida para todos, se cambia el bloque base y esta se retira.

     Lo que hace, y por qué:
       · El rótulo es un TÍTULO: 12,5 px, negrita, en el negro del texto y sin
         mayúsculas forzadas. Se lee antes que el campo, que es el orden en que
         se rellena un formulario.
       · Nada de párrafos explicativos bajo el rótulo. Lo que era explicación
         se fue al placeholder (que solo estorba cuando el campo está vacío) y
         lo que era un dato del expediente —quién repartió la tarea— se fue a
         la derecha del rótulo, donde se lee como dato y no como instrucción.
       · "opcional" deja de ser un paréntesis dentro del título y pasa a ser
         una marca a la derecha: el título queda limpio y la información no se
         pierde.
       · Los controles crecen (13,5 px, más aire): en una ventana ya no se está
         rellenando una celda de tabla. */
  .form-amable .field{margin-bottom:16px;}
  .form-amable .field > label,
  .form-amable .fa-lbl > label{font-size:12.5px; font-weight:700; color:var(--ink);
    text-transform:none; letter-spacing:0; margin-bottom:6px; display:block;}
  .form-amable .fa-lbl{display:flex; align-items:baseline; justify-content:space-between; gap:12px;}
  .form-amable .fa-lbl > label{margin-bottom:6px;}
  .form-amable .fa-opt{font-size:11px; font-weight:600; color:var(--gray-soft); white-space:nowrap;}
  /* Un dato del expediente, no una explicación: "La asignó Carmen el 12/08". */
  .form-amable .fa-dato{font-size:11.5px; color:var(--gray); text-align:right; line-height:1.35;}
  .form-amable .field input,
  .form-amable .field select,
  .form-amable .field textarea{font-size:13.5px; padding:11px 13px; border-radius:9px;}
  .form-amable .field input:focus,
  .form-amable .field select:focus,
  .form-amable .field textarea:focus{outline:none; border-color:var(--navy2); box-shadow:0 0 0 3px rgba(0,64,144,.10);}
  /* EL DETALLE, CON SITIO. Era una caja de 64 px con desplazamiento propio, y
     ahí es donde vive lo que se escribe por puntos —los compromisos de una
     reunión, lo que hay que revisar—: se veían tres renglones sueltos a media
     lista, sin principio ni final. Arranca en seis renglones y crece sola con
     lo que tenga dentro (sgAutoAlto), hasta que el cuerpo de la ventana se
     encargue de desplazar. */
  .form-amable .field textarea{min-height:132px; line-height:1.6; resize:vertical;}
  /* Dos campos cortos por fila: una fecha o un estado no necesitan el ancho
     entero, y en columna dejaban el formulario el doble de largo de lo que da
     su contenido. */
  .form-amable .fa-fila2{display:grid; grid-template-columns:1fr 1fr; gap:0 16px;}
  @media (max-width:560px){ .form-amable .fa-fila2{grid-template-columns:1fr;} }
  /* El apartado: dice de qué va el bloque que viene, en vez de separar con una
     raya muda. */
  .form-amable .fa-sec{font-size:11px; font-weight:800; letter-spacing:.05em; text-transform:uppercase;
    color:var(--gray-soft); margin:6px 0 14px; padding-top:18px; border-top:1px solid var(--line);}

  .sg-fchecks{display:flex; gap:20px; flex-wrap:wrap; align-items:center;}
  .sg-fchecks label{display:flex; align-items:center; gap:7px; font-size:12.5px; color:var(--ink); cursor:pointer; margin:0; text-transform:none; letter-spacing:0; font-weight:600;}
  .sg-fchecks input{width:15px; height:15px; accent-color:var(--navy);}

  /* Es un botón de verdad, con su piel de botón: como <span> con color de
     enlace no se distinguía de un rótulo más y había que descubrirlo probando. */
  .sg-masdet{display:inline-flex; align-items:center; gap:6px; font:inherit; font-size:12.5px; font-weight:700;
    color:var(--navy2); cursor:pointer; margin:2px 0 16px; padding:8px 14px;
    background:var(--block); border:1px solid var(--line); border-radius:9px;}
  .sg-masdet:hover{border-color:#CDD5E1; color:var(--navy);}
  .sg-fdetalles{display:none;}
  .sg-fdetalles.open{display:block;}

  /* ---- contrapartes: espacio de logo/foto ---- */
  /* Un logo NO es una foto: se recorta mal. Los logotipos vienen apaisados y
     con aire alrededor, así que 'cover' les cortaba los lados y dejaba fuera
     justo el nombre de la empresa. Con 'contain' cabe entero.
     Y con contain hace falta no-repeat: si no, un logo pequeño se embaldosa.
     Fondo blanco porque muchos vienen en PNG transparente pensados para
     blanco; sobre el gris del bloque se ensucian. */
  .cp-logo{border-radius:10px; background-color:#fff; background-size:contain; background-repeat:no-repeat;
    background-position:center; background-origin:content-box; padding:3px;
    border:1px solid var(--line); flex:0 0 auto; display:inline-flex; align-items:center; justify-content:center;
    cursor:pointer;}
  .cp-logo.mono{background-color:var(--block); font-weight:800; color:var(--navy2); letter-spacing:.02em; padding:0;}
  /* La foto de una persona sí es una foto: encuadrarla llenando el círculo es
     lo correcto, y ahí 'cover' es lo que se quiere. */
  .cp-logo.redonda{border-radius:50%; background-size:cover; background-origin:padding-box; padding:0;}
  .cp-card-id{display:flex; align-items:center; gap:11px; margin:2px 0 6px;}

  /* ---- documentos: a qué expediente pertenece ----
     Categoría arriba (etiqueta sobria, en versalitas) y nombre del expediente
     debajo: se lee "esto es una Contraparte, y es Well Tech Fluids". El nombre
     es pulsable y va al expediente. */
  .dc-pert{display:flex; flex-direction:column; gap:3px; min-width:0;}
  .dc-tag{align-self:flex-start; font-size:9px; font-weight:700; text-transform:uppercase; letter-spacing:.06em; color:var(--gray); background:var(--block); border:1px solid var(--line); border-radius:5px; padding:1px 6px;}
  .dc-pert-n{font-size:12.5px; font-weight:600; color:var(--ink); line-height:1.35;}
  .dc-pert-n.liga{cursor:pointer;}
  .dc-pert-n.liga:hover{color:var(--navy2); text-decoration:underline;}

  /* ---- documentos: vista previa en la ficha ---- */
  .dc-prev{border-radius:10px; overflow:hidden; border:1px solid var(--line); max-height:300px; display:flex; align-items:center; justify-content:center; background:var(--block);}
  .dc-prev img{width:100%; height:auto; display:block; object-fit:cover; max-height:300px;}
  .dc-prev.vacia{padding:34px 24px; font-size:12.5px; color:var(--gray); text-align:center; line-height:1.6; border-style:dashed; flex-direction:column;}

  /* ---- paginado al pie de una lista o tabla (paginar(), core.js) ----
     Propio, no DataTables: estas listas se repintan enteras en cada tecla del
     buscador, y montar/destruir la librería en cada repintado (lo que hace
     Trazabilidad) no compensa donde solo hacen falta tamaño de página y salto.
     Sin prefijo de módulo a propósito: lo usan Documentos e Inversionistas, y
     cualquier tabla que venga después. Selector a la izquierda, rango al
     centro, botones a la derecha; en móvil se apilan centrados. */
  .pager{display:flex; align-items:center; gap:12px; flex-wrap:wrap; margin-top:12px; padding-top:12px; border-top:1px solid var(--line); font-size:11.5px; color:var(--gray);}
  .pag-len select{border:1px solid var(--line); border-radius:7px; padding:4px 6px; margin:0 3px; font-family:inherit; font-size:11.5px; color:var(--ink); background:var(--bg);}
  .pag-len select:focus{outline:none; border-color:var(--navy2);}
  .pag-info{color:var(--gray-soft);}
  .pag-nums{margin-left:auto; display:flex; gap:4px;}
  .pag-b{min-width:26px; height:26px; padding:0 7px; border:1px solid var(--line); border-radius:7px; background:var(--bg); color:var(--ink); font-family:inherit; font-size:11.5px; cursor:pointer;}
  .pag-b:hover:not(:disabled){border-color:var(--navy2); color:var(--navy2);}
  .pag-b.on{background:var(--navy2); border-color:var(--navy2); color:#fff; font-weight:600;}
  .pag-b:disabled{opacity:.4; cursor:default;}
  @media (max-width:640px){
    .pager{justify-content:center;}
    .pag-nums{margin-left:0;}
  }

  /* tarjeta de oportunidad: la tesis en máximo 3 líneas */
  .fc-clamp{display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical; overflow:hidden;}

  /* hoja técnica en edición */
  .te-in{width:100%; border:1px solid var(--line); border-radius:7px; padding:7px 10px; font-family:inherit; font-size:13px; color:var(--ink); background:var(--bg);}
  .te-in:focus{outline:none; border-color:var(--navy2);}
  .doc44 .dc-ic{width:30px; height:34px;}
  .doc44 .dc-ic svg{width:12px; height:12px;}

  /* ===================== entrada universal de archivos =====================
     Velo al arrastrar un archivo sobre la ventana + acciones del triaje. */
  #dropOverlay{position:fixed; inset:0; z-index:400; display:none; align-items:center; justify-content:center;
    background:rgba(0,51,109,.42); backdrop-filter:blur(2px); pointer-events:none;}
  #dropOverlay.on{display:flex;}
  #dropOverlay .do-card{background:var(--bg); border:2px dashed var(--cyan-deep); border-radius:16px;
    padding:40px 56px; text-align:center; box-shadow:var(--shadow);}
  #dropOverlay .do-card .ic{font-size:30px; margin-bottom:10px; color:var(--cyan-deep);}
  #dropOverlay .do-card .t1{font-size:17px; font-weight:800; letter-spacing:-.01em;}
  #dropOverlay .do-card .t2{font-size:12px; color:var(--gray); margin-top:4px;}
  .ia-acciones{display:flex; flex-direction:column; gap:9px;}
  .ia-accion{display:block; width:100%; text-align:left; border:1px solid var(--line); border-radius:10px;
    background:var(--bg); padding:12px 15px; cursor:pointer; font-family:inherit; transition:border-color .12s, background .12s;}
  .ia-accion:hover{border-color:var(--cyan-deep); background:#F3FAFE;}
  .ia-accion.prim{border-color:var(--navy); background:var(--block);}
  .ia-accion .t{display:block; font-size:13px; font-weight:700; color:var(--ink);}
  .ia-accion .s{display:block; font-size:11px; color:var(--gray); margin-top:2px;}

  /* ===================== entrada · la bandeja =====================
     Panel lateral que recibe los archivos soltados: no interrumpe el trabajo.
     Debajo del modal (110) para que el formulario de corrección mande. */
  #iaTray{position:fixed; top:0; right:-380px; bottom:0; width:360px; z-index:90; background:var(--bg);
    border-left:1px solid var(--line); box-shadow:-10px 0 30px rgba(14,20,36,.10);
    display:flex; flex-direction:column; transition:right .45s cubic-bezier(.2,.8,.2,1);}
  #iaTray.in{right:0;}
  /* Mismo arreglo que .cr-prev (su hermano, más abajo): en un teléfono angosto
     (~320-359px) los 360px fijos no caben completos en pantalla. */
  @media (max-width:480px){ #iaTray{width:100%; right:-100%;} }
  .iat-h{display:flex; align-items:flex-start; justify-content:space-between; gap:10px; padding:16px 18px 12px; border-bottom:1px solid var(--line-soft);}
  .iat-h .t{font-weight:800; font-size:14px;}
  .iat-h .s{font-size:11px; color:var(--gray); margin-top:2px;}
  .iat-x{border:none; background:none; cursor:pointer; font-size:13px; color:var(--gray-soft); padding:2px 4px; font-family:inherit;}
  .iat-x:hover{color:var(--ink);}
  .iat-b{flex:1; overflow:auto; padding:10px 12px;}
  .iat-row{border:1px solid var(--line); border-radius:10px; padding:10px 12px; margin-bottom:9px; background:var(--bg);
    opacity:0; transform:translateY(8px); transition:opacity .3s, transform .3s, border-color .2s, background .2s;}
  .iat-row.vis{opacity:1; transform:none;}
  .iat-row.ok{border-color:var(--good); background:var(--good-bg);}
  .iat-row.fuera{opacity:0; transform:translateX(24px);}
  .iat-row .fn{font-size:11.5px; font-weight:700; display:flex; gap:7px; align-items:center; word-break:break-all;}
  .iat-row .ld{margin-top:7px; font-size:11px; color:var(--gray);}
  .iat-row .bar{height:4px; border-radius:3px; background:var(--line-soft); overflow:hidden; margin-top:7px;}
  .iat-row .bar i{display:block; height:100%; width:30%; border-radius:3px; background:linear-gradient(90deg,var(--cyan),var(--cyan-deep)); animation:iaSlide 1.1s infinite;}
  @keyframes iaSlide{0%{margin-left:-30%}100%{margin-left:100%}}
  .iat-row .dest{font-size:11.5px; margin-top:7px;}
  .iat-row .preg{font-size:11.5px; margin-top:7px;}
  .iat-row .acts{display:flex; gap:6px; margin-top:9px;}
  .iat-row .acts button{font-family:inherit; font-size:10.5px; font-weight:800; border-radius:7px; padding:5px 10px; cursor:pointer; border:1px solid var(--line); background:var(--bg); transition:border-color .12s;}
  .iat-row .acts button:hover{border-color:var(--cyan-deep);}
  .iat-row .acts .ok{background:var(--navy); border-color:var(--navy); color:#fff;}
  .iat-chips{display:flex; gap:6px; flex-wrap:wrap; margin-top:9px;}
  .iat-chips button{font-family:inherit; font-size:10.5px; font-weight:700; border:1.5px solid var(--navy2); color:var(--navy2); background:var(--bg); border-radius:999px; padding:5px 11px; cursor:pointer;}
  .iat-chips button:hover{background:#F3FAFE;}
  .iat-f{padding:12px 14px; border-top:1px solid var(--line-soft);}
  .iat-f button{width:100%; font-family:inherit; font-size:12.5px; font-weight:800; border-radius:9px; padding:10px; border:none; background:var(--navy); color:#fff; cursor:pointer;}

  /* ===================== el mostrador sereno (filtros tras "Afinar") =====================
     La vista recibe con pestañas y búsqueda; lo demás espera aquí. */
  .afinar{position:relative; display:inline-flex; align-items:center; gap:8px;}
  .af-btn{font-family:inherit; font-size:12px; font-weight:800; border:1.5px solid var(--line); background:var(--bg); border-radius:10px; padding:8px 14px; cursor:pointer; display:inline-flex; gap:7px; align-items:center; color:var(--ink); transition:border-color .12s;}
  .af-btn:hover{border-color:var(--navy2);}
  .af-n{background:var(--navy); color:#fff; border-radius:20px; font-size:10px; padding:1px 7px; font-weight:800;}
  .af-ar{color:var(--gray-soft); font-size:10px;}
  .af-pop{position:absolute; z-index:70; left:0; top:calc(100% + 8px); width:max-content; min-width:340px; max-width:min(560px, 86vw); background:var(--bg); border:1px solid var(--line); border-radius:13px; box-shadow:0 12px 40px rgba(14,20,36,.16); padding:14px 16px; display:none; cursor:default;}
  .af-pop.open{display:block;}
  .af-gl{font-size:9.5px; font-weight:800; letter-spacing:.01em; color:var(--gray-soft); margin:11px 0 6px;}
  .af-gl:first-child{margin-top:0;}
  .af-ops{display:flex; gap:6px; flex-wrap:wrap;}

  /* ---------- barra de filtros (shadcn/ui) ----------
     Nació en Seguimiento y hoy la comparte Alianzas; el prefijo sg- se queda
     por lo mismo que .sg-row, que ya vestía filas fuera de su módulo.
     Desplegables, no pastillas: la lista de temas crece con los datos y cada
     opción pedía su sitio en pantalla aunque nadie la mirara. Un <select>
     ocupa lo mismo con tres opciones que con veinte y dice lo elegido sin
     abrirse.

     El aspecto es el de la barra de herramientas de shadcn/ui, que en Atlas ya
     estaba implementada en Trazabilidad: se reusan sus clases .tz-inp y
     .tz-btn y sus tokens (borde zinc, radio de 6px, anillo de foco), no una
     copia parecida. Lo único que no se hereda es la tipografía: Geist se queda
     en Trazabilidad, porque estos campos van dentro de una pantalla escrita
     con la de Atlas y dos fuentes en la misma vista se leen como un error, no
     como un estilo. Es el mismo criterio con el que Trazabilidad conserva el
     navy de Atlas en su pestaña activa. */
  .sg-toolbar{display:flex; align-items:flex-end; gap:10px; flex-wrap:wrap; margin-bottom:14px;}
  /* .sg-fld y no .field —el nombre que usa Trazabilidad— porque .field select
     (los formularios de Atlas, más arriba) tiene más especificidad que .tz-inp
     y le pisaba el borde, el radio y hasta la flecha. */
  .sg-toolbar .sg-fld{display:flex; flex-direction:column; gap:5px; min-width:0; max-width:260px;}
  .sg-toolbar .sg-fld label{font-size:11.5px; font-weight:500; color:var(--tz-muted-fg);}
  /* .tz-btn nace a lo ancho de su carril (vive en una tarjeta de 252px); aquí
     va en línea con los campos y mide lo que dice. */
  .sg-toolbar .tz-btn{width:auto; height:35px;}
  /* Flecha propia: con appearance:none el navegador deja de dibujar la suya y
     el campo queda idéntico al de shadcn. El relleno derecho le reserva sitio
     para que ninguna opción larga se meta debajo. */
  .sg-sel{appearance:none; -webkit-appearance:none; padding-right:30px; cursor:pointer;
          background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2371717a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
          background-repeat:no-repeat; background-position:right 9px center; background-size:14px;}
  .af-toks{display:inline-flex; gap:6px; flex-wrap:wrap; align-items:center;}
  .af-tok{display:inline-flex; align-items:center; gap:6px; background:var(--block); border:1px solid var(--line); border-radius:20px; padding:5px 11px; font-size:11px; font-weight:700; cursor:pointer; white-space:nowrap;}
  .af-tok .x{color:var(--gray-soft);}
  .af-tok:hover .x{color:var(--ink);}

  /* ===================== responsable (quién lleva el expediente) ===================== */
  .resp-chip{display:inline-flex; align-items:center; gap:7px; font-size:11.5px; font-weight:700; color:var(--ink);}
  .resp-chip .resp-av{width:22px; height:22px; border-radius:50%; background:var(--navy); color:#fff; font-size:9.5px; font-weight:800; display:inline-flex; align-items:center; justify-content:center; flex:none;}
  .resp-chip.vacio{color:var(--gray-soft); font-weight:600;}
  /* "+N" cuando el inversionista lo llevan varios. Mismo tratamiento que el de
     una tarea con varios responsables (.sg-rmas): la rejilla de tarjetas no da
     para más de una inicial, y los nombres completos van en el title. */
  .resp-chip .resp-mas{font-size:9.5px; font-weight:800; color:var(--gray-soft); background:var(--block);
    border:1px solid var(--line-soft); border-radius:20px; padding:1px 5px; margin-left:-3px;}

  /* ===================== reportería de correspondencia: columnas mensuales =====================
     Atlas ya tiene barras horizontales (.in-rrow) y segmentos apilados (.in-sbar) reusables desde
     Inteligencia; falta un tercer tipo (columnas verticales de una sola serie) para "ritmo de
     llegada por mes", así que es lo único nuevo aquí. */
  .cr-cols{display:flex; align-items:flex-end; gap:5px; height:130px; padding:4px 2px 0;}
  .cr-col{flex:1 1 0; display:flex; flex-direction:column; align-items:center; min-width:0; height:100%; justify-content:flex-end;}
  .cr-col-n{font-size:10px; font-weight:800; color:var(--ink); margin-bottom:3px;}
  .cr-col-bar{width:100%; max-width:26px; border-radius:4px 4px 0 0; background:var(--navy2); min-height:2px; transition:background-color .12s ease;}
  .cr-col-l{font-size:9px; color:var(--gray-soft); margin-top:6px; white-space:nowrap;}
  /* monto declarado del mes (panel de mes de Panorama, ver crColumnas) — sin
     white-space:nowrap a propósito: a diferencia del mes (siempre corto),
     "$X (Y%)" puede no caber en una columna angosta y se prefiere que baje a
     una 2ª línea dentro de su propia columna, no que se salga hacia la de al
     lado. */
  .cr-col-monto{font-size:8.5px; color:var(--gray); margin-top:2px; line-height:1.25; text-align:center;}
  /* porcentaje secundario junto a un monto — más claro que el monto que
     acompaña (ver "Monto declarado por sector" y el panel de mes) */
  .cr-pct{color:var(--gray-soft); font-weight:500;}

  /* ===================== reportería: filas expandibles (Próximas acciones) =====================
     <details>/<summary> nativo en vez de un componente de acordeón a mano:
     el <summary> toma el look de .vinc-row (ya existe) y el cuerpo abierto
     reusa .a-card + .kvp, el mismo patrón que ya usa la ficha de detalle. */
  .cr-acc-item{border-bottom:1px solid var(--line-soft);}
  .cr-acc-item:last-child{border-bottom:none;}
  .cr-acc-item summary{list-style:none;}
  .cr-acc-item summary::-webkit-details-marker{display:none;}
  .cr-acc-item summary.vinc-row{border-bottom:none; position:relative; padding-left:20px;}
  .cr-acc-item summary.vinc-row::before{content:'›'; position:absolute; left:0; font-size:16px; font-weight:800; color:var(--gray-soft); transition:transform .15s;}
  .cr-acc-item[open] summary.vinc-row::before{transform:rotate(90deg);}
  .cr-acc-item[open] summary.vinc-row{padding-bottom:6px;}

  /* ===================== Panorama: "Mayores montos declarados" =====================
     Ranking, no gráfica de barras — los montos entre el #1 y el #5 pueden
     ser muy distintos, comparar sus barras entre sí no diría nada útil. */
  .cr-top-row{display:flex; align-items:flex-start; gap:12px; padding:10px 4px; border-bottom:1px solid var(--line-soft); cursor:pointer; border-radius:8px;}
  .cr-top-row:last-child{border-bottom:none;}
  .cr-top-row:hover{background:var(--block);}
  .cr-top-rank{width:22px; height:22px; border-radius:50%; background:var(--block); color:var(--gray); font-size:11px; font-weight:800; display:flex; align-items:center; justify-content:center; flex:0 0 auto; margin-top:1px;}
  .cr-top-info{flex:1 1 auto; min-width:0;}
  .cr-top-name{font-size:13px; font-weight:700; color:var(--ink); line-height:1.35;}
  .cr-top-meta{font-size:11px; color:var(--gray-soft); margin-top:3px;}
  .cr-top-meta .chip{margin-left:4px; vertical-align:middle;}
  .cr-top-monto{font-size:14.5px; font-weight:800; color:var(--ink); flex:0 0 auto; font-variant-numeric:tabular-nums; white-space:nowrap;}

  /* ---- Próximas acciones: los dos embudos ----
     Se dibujan con .sec-h y .in-rrow, las mismas de los paneles de Panorama.
     Lo único propio es esto: los rótulos de fase, el pie de los cerrados, el
     desglose por unidad y la fila de alarma. Nada de eso existía porque
     Panorama no agrupa sus barras ni tiene alarma. */
  /* Las tres columnas fijas para que TODAS las barras empiecen y terminen en la
     misma vertical. El valor iba a ancho automático, así que "139 (96%)" y
     "1 (1%)" empujaban distinto y cada pista acababa en un sitio: comparar dos
     barras exigía descontar de cuánto era el número de al lado. */
  .cr-acc-embudo .in-rrow .rl{width:auto; flex:0 0 210px;}
  .cr-acc-embudo .in-rrow .rv{width:96px; flex:0 0 96px; white-space:nowrap;}
  /* Y con techo: a lo ancho de la rejilla entera la barra de 139 medía casi
     mil píxeles y el ojo perdía el otro extremo antes de llegar. Ochocientos
     bastan para distinguir cualquier proporción de esta pantalla. */
  .cr-acc-embudo .in-rrow{max-width:800px;}
  .cr-acc-unidades{max-width:800px;}

  /* El rótulo de cada bloque de gráficos: dice de qué son los paneles que
     vienen debajo. Sin él, cuatro tarjetas seguidas parecían cuatro cosas
     sueltas en vez de dos gestiones, una con tres partes y otra con una. */
  /* ---- la ficha de una carta ----
     Los tres bloques con hueco propio: eran hermanos sueltos dentro del cuerpo
     y se tocaban, así que la carta, sus documentos y sus tareas se leían como
     un solo bloque largo. */
  .cr-ficha-cuerpo{display:flex; flex-direction:column; gap:18px; margin-top:18px;}
  /* El textarea de las observaciones: el ancho de la tarjeta y alto para
     cuatro renglones, que es lo que suele escribirse. */
  .cr-obs-txt{width:100%; border:1px solid var(--line); border-radius:8px; padding:10px 12px;
              font-family:inherit; font-size:13.5px; line-height:1.6; color:var(--ink);
              background:var(--bg); resize:vertical;}
  .cr-obs-txt:focus{outline:none; border-color:var(--navy2);}
  .cr-obs-pie{font-size:11px; color:var(--gray-soft); margin-top:7px;}
  /* La descripción, a lo ancho y antes que nada: es la única tarjeta de la
     columna que no lleva datos sino prosa, y por eso se lee como un párrafo y
     no como una ficha. */
  .cr-desc .fk-intro{font-size:13.5px; color:var(--ink); line-height:1.6;}
  .cr-desc .a-sec .t{font-size:13px; font-weight:700; color:var(--ink);}
  /* El rótulo del rail con su enlace de corregir a la derecha, en la misma
     línea: debajo del dato quedaba tan cerca del siguiente rótulo que parecía
     pertenecerle al de abajo. */
  .cr-rail-lbl{display:flex; align-items:baseline; justify-content:space-between; gap:10px;}
  .cr-rail-lbl .op-link{font-size:11.5px; font-weight:600;}
  /* Los sectores, como pastillas que se encienden: son doce y una lista de
     casillas ocuparía el rail entero. */
  .cr-sec-chips{display:flex; flex-wrap:wrap; gap:6px; margin-top:2px;}
  .cr-sec-chips .fchip{font-size:11px; padding:5px 10px;}
  .cr-cto-form{display:flex; flex-direction:column; gap:7px; margin-top:2px;}
  .cr-cto-inp{width:100%; border:1px solid var(--line); border-radius:8px; padding:8px 10px;
              font-family:inherit; font-size:12.5px; color:var(--ink); background:var(--bg);}
  .cr-cto-inp:focus{outline:none; border-color:var(--navy2);}
  /* Los rótulos, en negrita y en el color del texto: .fk-k y .a-sec .t vienen
     en gris claro y versalitas, que en una ficha de doce filas hace que el
     dato y su nombre pesen lo mismo y no se sepa cuál se está leyendo. */
  .cr-ficha-cuerpo .fk-k{font-size:12px; font-weight:700; letter-spacing:0;
                         text-transform:none; color:var(--ink);}
  .cr-ficha-cuerpo .a-sec .t{font-size:14px; font-weight:700; color:var(--ink);}
  .cr-ficha-cuerpo .fk-intro{font-size:13.5px; color:var(--ink); line-height:1.6;}
  .cr-ficha-cuerpo .fk-intro.mute, .cr-ficha-cuerpo .mute{color:var(--gray-soft);}
  /* El rótulo del rail ya viene en negrita por .ct-ficha; la coletilla del
     contacto no, y son tres seguidas: se separan un punto para que no se lean
     como un párrafo. */
  .rail-ficha .ct-nota + .ct-nota{margin-top:2px;}

  .cr-acc-titulo{font-size:13.5px; font-weight:700; color:var(--navy); margin:6px 0 -4px;}
  .cr-acc-titulo + .cr-acc-embudo{margin-top:0;}
  .cr-acc-cero{opacity:.4;}
  /* La barra elegida conserva el dorado que .in-rrow hereda de Panorama —el
     mismo que marca ahí la fila sobre la que se está filtrando—. Llegó a
     estar en azul; se devolvió al dorado para que seleccionar se vea igual en
     todo el módulo: si en Panorama el filtro puesto es dorado, aquí también,
     o hay que aprenderse dos códigos. */
  /* Aquí vivió .cr-acc-fase, el rótulo de fase dentro del panel. Se retiró al
     partir el trámite en un panel por fase: el rótulo pasó a ser el título del
     propio panel, que es donde no compite con nada. */
  .cr-acc-embudo + .cr-acc-embudo{margin-top:-2px;}
  /* Lo ya cerrado se dice en una línea, no en barras: completa la cuenta —para
     que nadie sume lo de arriba y crea que faltan documentos— sin invitar a
     trabajarlo, que es justo lo que no toca en esta pestaña. */
  .cr-acc-cerrados{margin-top:13px; padding-top:11px; border-top:1px solid var(--line-soft); font-size:11.5px; color:var(--gray);}
  .cr-acc-cerrados b{color:var(--navy); font-weight:700;}
  /* El desglose por unidad, anidado bajo su paso y solo cuando está elegido. */
  .cr-acc-unidades{margin:2px 0 4px 12px; padding-left:12px; border-left:2px solid var(--line-soft);}
  .cr-acc-unidades .in-rrow{padding:4px 0;}
  .cr-acc-unidades .in-rrow .rl{flex:0 0 198px; font-size:11.5px; font-weight:600; color:var(--gray);}
  .cr-acc-unidades .in-rrow.on .rl{color:var(--navy); font-weight:700;}
  .cr-acc-unidades .in-rrow .rtrack{height:9px;}
  .cr-acc-unidades .in-rrow .rv{font-size:11.5px; font-weight:700;}
  /* Aquí vivió la fila de alarma del embudo de atención, en óxido y bajo su
     propia línea. Se retiró con ella: no era un paso sino un corte por tiempo
     colado entre los cinco, y su barra competía con las que sí dicen dónde
     está cada carta. */

  /* ---- Próximas acciones: la lista ----
     .cr-top-row, la fila que este mismo módulo usa en "Mayores montos
     declarados": título, contexto debajo y el dato duro a la derecha, dentro
     de un panel. No .sg-row: esta pestaña vive entre paneles de barras y una
     fila con caja propia rompía el bloque. */
  .cr-acc-row{padding:10px 8px;}
  .cr-acc-row .cr-top-name{white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
  /* Sin regla propia para .cr-top-meta: hereda la de Panorama (11px sobre
     gray-soft), que es lo que pedía «la misma tipografía y color». Lo único que
     se sale de ese gris son los dos pasos, porque son el dato, no el contexto:
     el del trámite en el azul del módulo, el de la atención en el óxido con
     que Atlas marca lo que se le debe a alguien. */
  /* Todo el texto de la fila en negro; lo que separa un dato de otro es el
     peso, no el color. Con el tipo en azul, los dos pasos en azul y óxido y la
     antigüedad en rojo, cada renglón tenía cuatro colores compitiendo y ya no
     se sabía cuál era el importante. El único azul que queda es el de las
     acciones, porque son enlaces y tienen que verse pulsables. */
  .cr-acc-row .cr-top-meta{color:var(--gray);}
  .cr-acc-acciones{display:flex; gap:14px; flex-wrap:wrap; margin-top:7px;}
  .cr-acc-acciones .op-link{font-size:11.5px;}
  .cr-acc-acciones .op-link.mute{color:var(--gray);}
  /* ---- las dos gestiones, arriba de la pestaña Seguimiento ---- */
  .cr-gest{padding:16px 20px;}
  .cr-gest-par{display:grid; grid-template-columns:1fr 1fr; gap:18px;}
  @media (max-width:700px){ .cr-gest-par{grid-template-columns:1fr;} }
  .cr-gest-k{font-size:11.5px; font-weight:700; color:var(--navy); margin-bottom:6px;}
  .cr-gest-campo select{width:100%;}
  .cr-gest-fijo{font-size:13px; font-weight:700; color:var(--ink); padding:2px 0;}
  .cr-gest-nota{font-size:11.5px; color:var(--gray); margin-top:6px;}

  .cr-acc-dias{font-size:11.5px; font-weight:600; color:var(--gray); padding-top:2px; min-width:74px; text-align:right;}
  .cr-acc-dias.viejo{color:var(--ink); font-weight:800;}
  /* El carril de las cartas: todas dentro, con scroll propio. Sin él la
     pestaña crecía con el filtro —ciento cuarenta filas empujaban los cuatro
     gráficos fuera de la pantalla— y había que subir para volver a filtrar. */
  .cr-acc-lista{max-height:420px; overflow-y:auto; padding-right:6px;}
  .cr-acc-fichas{display:flex; align-items:baseline; gap:8px; flex-wrap:wrap; margin-bottom:10px; font-size:11.5px; color:var(--gray);}
  .cr-acc-fichas b{color:var(--ink); font-weight:700;}
  .cr-acc-fichas .op-link{font-size:11.5px; margin-left:4px;}
  @media (max-width:760px){ .cr-acc-embudo .in-rrow .rl{flex:0 0 140px;} .cr-acc-unidades .in-rrow .rl{flex:0 0 128px;} .cr-acc-embudo .in-rrow .rv{width:78px; flex:0 0 78px;} }

  /* ===================== reportería: paneles de barras con muchas filas =====================
     Cuando una gráfica de barras (.in-rrow) puede crecer más allá de una
     pantalla (ej. país, con más registros entrando) se limita su alto y se
     deja desplazable en vez de recortar datos a "Otros" — mismo estilo de
     scrollbar fino que ya usan .tscroll/.ley-txt/.md-list. */
  .cr-scroll-y{max-height:280px; overflow-y:auto; padding-right:8px;}
  .cr-scroll-y::-webkit-scrollbar{width:8px;}
  .cr-scroll-y::-webkit-scrollbar-thumb{background:var(--line); border-radius:8px;}
  /* Directorio (tabla/catálogo) es la vista principal de trabajo — se ajusta
     al alto de pantalla disponible en vez de un pixelaje fijo, para aprovechar
     pantallas grandes y no verse enorme en una chica. #tscroll (horizontal,
     para la tabla ancha) queda anidado adentro sin conflicto: uno es vertical
     y el otro horizontal. */
  /* Sin tope de alto: el listado rueda con la página. Con 65vh, las 346
     tarjetas quedaban dentro de su propia barra —la de la captura—. */
  .cr-scroll-y-xl{padding-right:0;}
  .cr-scroll-y-xl::-webkit-scrollbar{width:8px;}
  .cr-scroll-y-xl::-webkit-scrollbar-thumb{background:var(--line); border-radius:8px;}
  /* mismo criterio, en horizontal, para las columnas mensuales */
  .cr-scroll-x{overflow-x:auto; padding-bottom:6px;}
  .cr-scroll-x::-webkit-scrollbar{height:8px;}
  .cr-scroll-x::-webkit-scrollbar-thumb{background:var(--line); border-radius:8px;}
  /* .in-rrow .rl trunca con "…" por defecto (regla compartida con Inteligencia
     → Torre de control, que sigue truncando la suya); adentro de .cr-scroll-y
     se sobreescribe (selector más específico, sin !important) para que el
     nombre se vea completo envolviendo en varias líneas en vez de cortarse. */
  /* ===================== gráficos interactivos (correspondencia) =====================
     Cada marca (barra, columna, segmento y su entrada de leyenda) responde a
     hover y a foco de teclado. El realce es discreto a propósito: la marca
     debe acusar recibo del puntero sin que el color del dato cambie de peso,
     que es lo que se compara entre barras. */
  .cr-mark{transition:background-color .12s ease, opacity .12s ease;}
  .cr-mark.accionable{cursor:pointer;}
  .cr-mark.accionable:hover, .cr-mark.accionable:focus-visible{background:var(--wash, rgba(0,64,144,.06));}
  .cr-mark.accionable:focus-visible{outline:2px solid var(--navy); outline-offset:1px;}
  /* el <details> y la fila de barra ya traen padding lateral 0; se le da algo
     de aire al realce para que no quede pegado al borde del panel */
  .cr-scroll-y .in-rrow.cr-mark{padding-left:6px; padding-right:6px; margin-left:-6px; margin-right:-6px; border-radius:6px;}
  /* columnas: la marca es toda la columna (número + barra + etiqueta), no
     solo la barra pintada — blanco de clic mucho mayor que los 26px de ancho */
  .cr-col.cr-mark.accionable{border-radius:6px; padding:2px;}
  .cr-col.cr-mark.accionable:hover .cr-col-bar{filter:brightness(1.08);}
  /* variante con clic-para-alternar en el sitio (Panorama · mes), en vez del
     salto a Directorio de arriba. Base en el azul institucional de siempre
     (hereda de .cr-col-bar) — igual que el resto de las gráficas del
     módulo; dorado (#B87315, pedido explícito) solo para la(s) mes(es)
     seleccionado(s), que ahora pueden ser varios a la vez (selección
     múltiple: cada mes se alterna aparte, ver crSetPanFiltro/
     crSetFiltroGraf). Con algo elegido, las no seleccionadas pasan a azul
     claro (#A0C4E2, pedido explícito) para quedar "atrás" — mismo criterio
     que .in-rrow.clic.dim (filas de barra), un color distinto en vez de
     solo atenuar la opacidad. */
  .cr-col.clic{cursor:pointer; border-radius:6px; padding:2px;}
  .cr-col.clic:hover .cr-col-bar{filter:brightness(1.08);}
  .cr-col.clic.on .cr-col-bar{background:#B87315;}
  .cr-col.clic.on .cr-col-n{color:#B87315; font-weight:700;}
  .cr-col.clic.dim .cr-col-bar{background:#A0C4E2;}
  .cr-col.clic.dim .cr-col-n{color:var(--gray);}
  /* variante fusionada (mes de Panorama, crColumnasFusion): dos franjas
     apiladas por columna en vez de una sola barra — cartas de intención
     (navy2) abajo, otra correspondencia (cyan) arriba. Seleccionada o
     atenuada, las dos franjas se ven de un solo color (mismo criterio que
     .cr-col-bar de arriba), la distinción de color por categoría solo
     importa en el estado normal. */
  .cr-col-bar-fusion{width:100%; max-width:26px; min-height:2px; display:flex; flex-direction:column-reverse; border-radius:4px 4px 0 0; overflow:hidden;}
  .cr-col.clic:hover .cr-col-bar-fusion{filter:brightness(1.08);}
  .cr-col-seg{width:100%;}
  .cr-col-seg-intencion{background:var(--navy2);}
  .cr-col-seg-otras{background:var(--cyan);}
  .cr-col.clic.on .cr-col-seg{background:#B87315;}
  .cr-col.clic.dim .cr-col-seg{background:#A0C4E2;}
  .cr-fusion-legend{display:flex; gap:16px; margin-bottom:10px; font-size:11px; color:var(--gray); font-weight:600;}
  .cr-fusion-legend i{width:9px; height:9px; border-radius:3px; display:inline-block; margin-right:6px; vertical-align:middle;}
  .cr-fusion-h{display:flex; align-items:center; gap:9px; font-size:12px; font-weight:800; color:var(--gray); letter-spacing:.01em; margin:8px 2px -2px;}
  .cr-fusion-h .tick{width:3px; height:12px; border-radius:2px; background:var(--navy); display:inline-block;}
  /* segmentos: la franja pintada suele ser estrecha, así que el realce es un
     aclarado sutil y la leyenda hace de blanco grande */
  .in-sbar span.cr-mark.accionable:hover, .in-sbar span.cr-mark.accionable:focus-visible{opacity:.82;}
  .in-sbar-legend span.cr-mark.accionable{padding:2px 6px; margin:-2px -2px; border-radius:5px;}
  /* variante onClick de segmentos (crSegmentos con 4° parámetro) — mismo
     criterio clic/on/dim que .cr-col/.in-rrow: seleccionado se realza, el
     resto de ESE panel se atenúa. Usado por Cartas de intención dentro de
     Directorio (Gráfica), ver crRenderGraficaIntencion. */
  .in-sbar span.clic{cursor:pointer; transition:opacity .12s ease, filter .12s ease;}
  .in-sbar span.clic:hover{filter:brightness(1.1);}
  .in-sbar span.clic.on{box-shadow:inset 0 0 0 2px rgba(0,0,0,.28);}
  .in-sbar span.clic.dim{opacity:.35;}
  .in-sbar-legend span.clic{cursor:pointer; padding:2px 6px; margin:-2px -2px; border-radius:5px; transition:opacity .12s ease, background-color .12s ease;}
  .in-sbar-legend span.clic:hover{background:var(--block);}
  .in-sbar-legend span.clic.on{background:#EEF5FC; font-weight:700;}
  .in-sbar-legend span.clic.dim{opacity:.5;}

  /* Tooltip de gráfico. Único en el documento, se mueve con el puntero.
     El valor manda tipográficamente; la etiqueta y el porcentaje acompañan. */
  .cr-tip{position:fixed; z-index:9000; pointer-events:none; opacity:0; visibility:hidden;
    transition:opacity .12s ease; background:var(--ink, #16202E); color:#fff;
    border-radius:7px; padding:8px 11px; max-width:280px; box-shadow:0 6px 22px rgba(0,0,0,.22);
    font-size:12px; line-height:1.45; display:flex; flex-direction:column; gap:1px;}
  .cr-tip.on{opacity:1; visibility:visible;}
  .cr-tip b{font-size:15px; font-weight:700; letter-spacing:.01em;}
  .cr-tip span{opacity:.88;}
  .cr-tip i{font-style:normal; opacity:.62; font-size:11px;}
  .cr-tip u{text-decoration:none; opacity:.55; font-size:10.5px;
    letter-spacing:.01em; margin-top:3px;}

  /* Filtros activos: la única forma de ver y quitar los que llegan desde un
     gráfico, que no tienen ficha propia en la fila de "Afinar". */
  .cr-factivos{display:flex; align-items:center; gap:8px; flex-wrap:wrap;}
  .cr-flabel{font-size:11px; letter-spacing:.01em; color:var(--gray); font-weight:600;}
  .cr-ftok{display:inline-flex; align-items:center; gap:6px; background:var(--wash, rgba(0,64,144,.07));
    border:1px solid rgba(0,64,144,.18); border-radius:14px; padding:3px 6px 3px 11px; font-size:12px;}
  .cr-ftok b{font-weight:650;}
  .cr-ftok .x{cursor:pointer; opacity:.5; padding:0 4px; border-radius:9px; line-height:1.6;}
  .cr-ftok .x:hover, .cr-ftok .x:focus-visible{opacity:1; background:rgba(0,0,0,.08);}
  .cr-fclear{margin-left:auto; font-size:12px;}

  /* Panel de mes de Panorama: el .card de siempre + una sombra suave
     (mismo var(--shadow) que ya usan .pcard/.kcard/.sg-row al pasar el
     mouse) para enmarcarlo como pieza central de la pestaña — a diferencia
     de esos, aquí es fija, no de hover, porque el panel no es un enlace a
     otra pantalla, ya vive en el sitio. */
  .cr-mespanel{box-shadow:var(--shadow);}

  /* ---- tarjetas-resumen de 3 partes (crTileRow) ----
     rótulo / valor / subtítulo, a diferencia de .stat (2 partes: valor
     arriba, rótulo abajo) que sigue usando crKpiRow en el resto del módulo
     (Gráfica de Directorio, Otra correspondencia) — no se toca .stat/
     .stat-row (compartida por toda la app). Usada por Panorama (5,
     informativas) y Próximas acciones (6, clicables — mismo criterio que
     .stat.clic/.in-rrow.clic: fondo #EEF5FC de .enteli.on para la
     seleccionada). El número de columnas lo fija crTileRow con la variable
     --tiles (nunca grid-template-columns directo), para que los saltos a
     3/2/1 columnas de abajo lo puedan pisar en pantallas angostas sin
     necesitar !important. */
  .cr-tiles{display:grid; grid-template-columns:repeat(var(--tiles,5),1fr); gap:14px; align-items:stretch;}
  .cr-tile{background:var(--bg); border:1px solid var(--line); border-radius:10px; padding:16px; min-width:0; text-align:center;}
  /* line-height + min-height fijos (2 líneas, en em de la propia fuente) en
     rótulo Y subtítulo — no solo el rótulo — para que el valor grande de en
     medio arranque siempre a la misma altura Y las tarjetas terminen a la
     misma altura visual, sin importar que un rótulo o subtítulo ocupe 1
     línea ("Monto declarado", "en seguimiento") o 2 ("Se sugiere revisar
     documentación", "expedientes con soportes incompletos"). Texto
     centrado (pedido explícito) en las 3 partes — hereda de .cr-tile, sin
     tocar el resto de usos de .card en la app. align-items:stretch arriba
     ya iguala el alto exterior de la tarjeta; esto iguala además dónde cae
     cada línea por dentro. */
  /* El rótulo en tinta y no en gris: con la descripción de abajo retirada, es
     lo único que dice QUÉ es la cifra, y en gris claro se leía como una nota
     al pie de algo que ya no está. */
  .cr-tile-l{font-size:11px; font-weight:700; letter-spacing:.01em; color:var(--ink); line-height:1.3; min-height:2.6em; display:flex; align-items:center; justify-content:center;}
  /* Todas las cifras del mismo azul. Antes cada una llevaba el suyo —ámbar el
     monto, verde las completas, óxido las incompletas— y ese color no
     significaba nada: no eran bueno, malo ni regular, eran cinco cifras del
     mismo tipo pintadas de cinco maneras. Una fila de cifras se lee
     comparando, y para comparar tienen que estar dichas igual. El color en
     Atlas queda para lo que sí lo necesita: un estado. */
  .cr-tile-v{font-size:26px; font-weight:800; letter-spacing:-.02em; margin-top:6px; color:var(--navy2); font-variant-numeric:tabular-nums;}
  .cr-tile.clic{cursor:pointer; transition:background-color .12s ease, border-color .12s ease;}
  .cr-tile.clic:hover{border-color:#CDD5E1;}
  .cr-tile.clic.on{background:#EEF5FC; border-color:#CFE0F0;}
  @media (max-width:1180px){ .cr-tiles{grid-template-columns:repeat(3,1fr);} }
  @media (max-width:720px){ .cr-tiles{grid-template-columns:repeat(2,1fr);} }
  @media (max-width:480px){ .cr-tiles{grid-template-columns:1fr;} }

  /* ===================== "Otra correspondencia": pipeline de estado =====================
     Variante de AGREGADO del .stepper que ya existe (activo.js/oportunidad.js):
     ahí un solo nodo "cur" marca la posición de UN registro; aquí los 5 nodos
     muestran el conteo de TODOS los registros de cada etapa a la vez — no hay
     estados done/cur/todo, cada nodo va siempre "lleno" con su color real
     (CR_ESTADO_COLOR, vía style inline). */
  .cr-pipe{padding:4px 2px 0;}
  .cr-pipe-line{display:flex; align-items:center; gap:4px;}
  .cr-pipe-node{width:16px; height:16px; border-radius:50%; flex:0 0 auto; transition:transform .12s ease, filter .12s ease, opacity .12s ease;}
  .cr-pipe-node.cr-mark.accionable:hover, .cr-pipe-node.cr-mark.accionable:focus-visible{filter:brightness(1.15); transform:scale(1.15);}
  /* variante onClick (crPipelineEstadoHtml con 3° parámetro) — filtra en el
     sitio contra crFiltro.estado, ver crRenderOtras modo 'completo'. */
  .cr-pipe-node.clic{cursor:pointer;}
  .cr-pipe-node.clic:hover{filter:brightness(1.15); transform:scale(1.15);}
  .cr-pipe-node.clic.on{transform:scale(1.25); box-shadow:0 0 0 3px rgba(0,0,0,.18);}
  .cr-pipe-node.clic.dim{opacity:.35;}
  .cr-pipe-seg{flex:1 1 auto; height:2px; background:var(--line);}
  .cr-pipe-labs{display:flex; justify-content:space-between; margin-top:8px;}
  .cr-pipe-lab{flex:1 1 0; text-align:center; font-size:11.5px; font-weight:700; color:var(--ink); line-height:1.4;}
  .cr-pipe-lab:first-child{text-align:left;}
  .cr-pipe-lab:last-child{text-align:right;}
  .cr-pipe-lab small{display:block; font-size:10.5px; font-weight:600; color:var(--gray-soft);}
  @media (max-width:720px){ .cr-pipe-lab{font-size:10px;} .cr-pipe-lab small{font-size:9.5px;} }

  /* ===================== "Otra correspondencia": vista previa rápida =====================
     Panel lateral nuevo y propio — no #iaTray (singleton de la bandeja de
     archivos entrantes, con contenido específico de esa función), pero sí
     su mecánica real de deslizamiento: right:-380px → .in → right:0. Por
     encima en z-index (95 > 90 de #iaTray): no deberían coexistir en la
     práctica, pero si alguna vez lo hicieran, la vista previa recién abierta
     es la acción más reciente del usuario. */
  .cr-prev{position:fixed; top:0; right:-380px; bottom:0; width:360px; z-index:95; background:var(--bg);
    border-left:1px solid var(--line); box-shadow:-10px 0 30px rgba(14,20,36,.10);
    display:flex; flex-direction:column; transition:right .45s cubic-bezier(.2,.8,.2,1);}
  .cr-prev.in{right:0;}
  .cr-prev-h{display:flex; align-items:center; justify-content:space-between; gap:10px; padding:16px 18px 12px; border-bottom:1px solid var(--line-soft);}
  .cr-prev-t{font-weight:800; font-size:14px;}
  .cr-prev-x{border:none; background:none; cursor:pointer; font-size:13px; color:var(--gray-soft); padding:2px 4px; font-family:inherit;}
  .cr-prev-x:hover{color:var(--ink);}
  .cr-prev-b{flex:1; overflow:auto; padding:16px 18px;}
  .cr-prev-asunto{font-size:15px; font-weight:800; color:var(--ink); line-height:1.4;}
  .cr-prev-row{display:flex; gap:6px; flex-wrap:wrap; margin-top:8px;}
  .cr-prev-extracto{margin-top:16px; padding-top:14px; border-top:1px solid var(--line-soft); font-size:12.5px; color:var(--gray); line-height:1.5;}
  @media (max-width:480px){ .cr-prev{width:100%; right:-100%;} }

  .cr-scroll-y .in-rrow{align-items:flex-start;}
  .cr-scroll-y .in-rrow .rl{width:auto; flex:0 0 220px; max-width:220px; white-space:normal; overflow:visible; text-overflow:clip; line-height:1.35; padding-top:1px;}

  /* ===================== contratos suscritos · tarjetas de Panorama que abren su lista =====================
     Las tarjetas de "Panorama del expediente" dejaron de ser solo una cifra: las tres que
     representan un subconjunto se pulsan y despliegan sus contratos debajo. La primera
     ("63 contratos en ejecución") no, porque es la lista entera — y por eso no lleva ni el
     cursor de mano ni el pie de "Ver los N". El estado abierto se marca con un anillo, no con
     un relleno: la tarjeta sigue teniendo que leerse como cifra. */
  .stat.pulsable{cursor:pointer; transition:border-color .12s ease, box-shadow .12s ease;}
  .stat.pulsable:hover{border-color:#CDD5E1; box-shadow:var(--shadow);}
  .stat.pulsable.activa{border-color:var(--navy); box-shadow:0 0 0 1px var(--navy);}
  .stat .sver{display:block; margin-top:8px; font-size:10.5px; font-weight:700; color:var(--navy2);}
  .stat.pulsable:hover .sver{text-decoration:underline;}

  /* ---- las tarjetas de KPI del expediente ----
     Estuvieron un rato enseñando en reposo solo la cifra y su rótulo, con el medidor y el
     "Ver los N →" apareciendo al pasar el mouse. Se volvió: lo que la tarjeta tiene que decir
     lo dice siempre, y esconder el medidor dejaba fuera la única lectura que compara —qué parte
     del total es esa cifra— hasta que alguien pasara por encima.
     Lo que sí se queda es el realce: al señalarla se pinta del azul de Atlas.
     Acotado a los dos bloques de este módulo: chartKpiRow lo comparten otras vistas y allí las
     tarjetas no se pulsan. */
  #proyhead .stat.pulsable, #proystats .stat.pulsable{
    transition:border-color .14s ease, box-shadow .14s ease, transform .14s ease, background .14s ease;}
  /* Al señalar, la tarjeta se pinta del azul de Atlas: el mismo degradado de la barra lateral
     —#003a82 a --navy-deep— con el cuadrito de --cyan que la marca usa de acento. Todo lo que
     lleva dentro tiene que invertirse con ella, o se queda escrito en azul sobre azul: la cifra
     y el rótulo pasan a blanco, el sufijo "de 63" a un azul claro legible, la pista del medidor
     a blanco translúcido con el relleno en --cyan, y el "Ver los N →" en --cyan.
     La sombra también se tiñe: una sombra gris bajo una caja azul se ve sucia. */
  #proyhead .stat.pulsable:hover, #proystats .stat.pulsable:hover{
    background:linear-gradient(180deg, #003a82 0%, var(--navy-deep) 100%);
    border-color:var(--navy-deep); box-shadow:0 8px 20px rgba(0,51,109,.28);
    transform:translateY(-2px);}
  #proyhead .stat.pulsable:hover .sn, #proystats .stat.pulsable:hover .sn,
  #proyhead .stat.pulsable:hover .sl, #proystats .stat.pulsable:hover .sl{color:#fff;}
  #proyhead .stat.pulsable:hover .sn.accent, #proystats .stat.pulsable:hover .sn.accent{color:var(--cyan);}
  #proyhead .stat.pulsable:hover .sn .sd, #proystats .stat.pulsable:hover .sn .sd,
  #proyhead .stat.pulsable:hover .sl b, #proystats .stat.pulsable:hover .sl b{color:#AFC9EA;}
  #proyhead .stat.pulsable:hover .smeter, #proystats .stat.pulsable:hover .smeter{
    background:rgba(255,255,255,.22);}
  #proyhead .stat.pulsable:hover .smeter span, #proystats .stat.pulsable:hover .smeter span{
    background:var(--cyan);}
  #proyhead .stat.pulsable:hover .sver, #proystats .stat.pulsable:hover .sver{color:var(--cyan);}
  @media (prefers-reduced-motion:reduce){
    #proyhead .stat.pulsable:hover, #proystats .stat.pulsable:hover{transform:none;}
  }

  /* Vive DENTRO de la sección de Panorama, pegado a las tarjetas: a 12px, no separado
     por el hueco de la rejilla. Lo que se abre pertenece a la tarjeta que lo abrió, y
     con el hueco de por medio se leía como un bloque suelto de la página. */
  .pv-panel{border:1px solid var(--line); border-radius:var(--r); background:var(--bg);
            overflow:hidden; margin-top:12px;}
  .pv-h{display:flex; align-items:center; gap:10px; padding:11px 14px; background:var(--block);
        border-bottom:1px solid var(--line);}
  .pv-t{font-size:12.5px; font-weight:800; color:var(--ink);}
  .pv-c{font-size:11px; font-weight:700; color:var(--gray-soft);}
  .pv-sp{flex:1 1 auto;}
  /* Cierre propio y no .op-link: el enlace del sistema es de 13px y aquí pesa más que
     el título del panel, que es lo que hay que leer primero. */
  .pv-x{font-size:11.5px; font-weight:700; color:var(--navy2); cursor:pointer;}
  .pv-x:hover{text-decoration:underline;}
  /* Tope de alto y scroll propio: la lista más larga son 31 contratos y no debe empujar la
     tabla fuera de la pantalla — lo que se abre aquí es una consulta, no la vista principal. */
  .pv-body{}
  .pv-body::-webkit-scrollbar{width:8px;}
  .pv-body::-webkit-scrollbar-thumb{background:var(--line); border-radius:8px;}
  /* En ventana la lista manda sobre toda la caja, así que puede ser más alta que dentro del
     panel —allí competía con la tabla— y su relleno se ajusta al de la ventana: el tirón
     horizontal deja que el realce del hover respire sin desalinear el texto con el título.
     El relleno lateral de 7px y overflow-x:hidden no son estéticos: sin ellos el margen
     negativo de las filas desborda la caja y, como overflow-y:auto obliga a que overflow-x se
     calcule también como auto, aparece una barra de scroll horizontal que no mide nada y roba
     alto. Es el mismo fallo que ya apareció en la lista de los gráficos. */
  #modal .pv-body{max-height:min(560px, 58vh); overflow-x:hidden; padding:0 7px;}
  #modal .pv-row{padding:8px 7px; margin:0 -7px; border-radius:7px;}
  .pv-row{display:flex; align-items:center; gap:11px; padding:8px 14px; cursor:pointer;
          border-bottom:1px solid var(--line-soft);}
  .pv-row:last-child{border-bottom:none;}
  .pv-row:hover{background:var(--block);}
  .pv-row:hover .pv-n{color:var(--navy2);}
  .pv-pt{width:8px; height:8px; border-radius:2px; flex:0 0 auto;}
  .pv-n{font-size:12.5px; font-weight:700; color:var(--ink); flex:1 1 auto; min-width:0;
        overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  .pv-m{font-size:12px; font-weight:800; color:var(--navy); white-space:nowrap;}
  .pv-m.vacio{color:var(--gray-soft); font-weight:600;}
  /* Banda de interruptores sobre la tabla. Van sobre el gris de la cabecera para
     que se lean como mandos del panel y no como una fila más de datos. */
  .pv-tabla{padding:4px 14px 12px;}
  /* Aviso en el sitio donde antes estaba la tabla. Sin él, cerrar el panel deja
     la pantalla sin contratos y sin explicación. */
  .pv-pista{padding:16px 2px; font-size:12.5px; color:var(--gray-soft);}
  .pv-pista b{color:var(--ink);}
  @media (max-width:620px){ .pv-row .chip.sector{display:none;} }
  @media (prefers-reduced-motion:reduce){ .stat.pulsable{transition:none;} }

  /* ===================== contratos suscritos · Kanban como lista plegable =====================
     El tablero de cuatro columnas pasó a ser una lista de grupos plegables. Cada cabecera es el
     interruptor y lleva la estadística del grupo: cuántos son, qué porcentaje del total, cuánto
     comprometido y cuántos de ellos declaran monto.
     Las tarjetas (.kcard) no cambian: se reparten en rejilla dentro del grupo en vez de apilarse
     en una columna estrecha. El scroll lo sigue poniendo #proybody (.vscroll), como antes — nada
     de una segunda barra dentro de cada grupo. */
  /* Gráfico de columnas sobre el tablero. El área de trazado reserva un canal a la izquierda
     (--kg-eje) para los rótulos de la escala, y las guías se posicionan por su valor: así la
     altura de una columna y la línea que la corta hablan de la misma unidad. La cifra va
     absoluta sobre la barra, no como hermana dentro de la columna, para que el alto en % sea
     exactamente el valor y no el valor menos lo que ocupe el número. */
  .kg{--kg-eje:38px; margin:2px 0 16px; padding-bottom:14px; border-bottom:1px solid var(--line);}
  /* El hueco bajo el rótulo del eje es sitio reservado para la cifra de la columna más alta:
     va posicionada sobre su barra, así que cuando el máximo coincide con el tope de la escala
     —pasa siempre que el máximo ya es un número redondo: 4, 6, 20…— la barra mide el 100% y su
     cifra cae por encima del área de trazado. Con los 6px de antes se montaba sobre el rótulo. */
  .kg-ejeY{font-size:9.5px; font-weight:800; letter-spacing:.01em;
           color:var(--gray-soft); margin-bottom:20px;}
  .kg-plot{position:relative; height:180px; margin-left:var(--kg-eje); border-bottom:1px solid var(--line);}
  .kg-gl{position:absolute; left:0; right:0; height:0; border-top:1px solid var(--line-soft);}
  /* La del cero coincide con el borde inferior del trazado: dibujarla encima daría una línea
     doble más gruesa que las demás justo donde se apoyan las columnas. */
  .kg-gl.cero{border-top-color:transparent;}
  .kg-gl b{position:absolute; right:100%; margin-right:9px; top:-7px;
           font-size:10px; font-weight:700; color:var(--gray-soft);}
  .kg-cols{position:absolute; inset:0; display:flex; align-items:flex-end; gap:14px; padding:0 8px;}
  /* La columna es el mando de su grupo, así que se comporta como tal: cursor de mano, realce al
     pasar por encima y toda su altura como área pulsable —no solo la barra, que en un grupo de
     cuatro contratos es una franja de pocos píxeles y un blanco imposible. */
  .kg-col{flex:1 1 0; display:flex; flex-direction:column; justify-content:flex-end;
          align-items:center; height:100%; min-width:0;
          cursor:pointer; border-radius:6px 6px 0 0; transition:background .12s ease;}
  .kg-col:hover{background:var(--line-soft);}
  /* El color lo pone cada columna en línea, con el mismo CK_COLOR que llevan el cuadrito de la
     cabecera y las barras de los medidores: así el gráfico y el tablero hablan el mismo idioma
     y la columna roja se reconoce sin leer el rótulo. */
  .kg-bar{position:relative; width:100%; max-width:52px; min-height:2px;
          border-radius:4px 4px 0 0;
          transition:filter .12s ease, opacity .12s ease;}
  .kg-col:hover .kg-bar{filter:brightness(1.08);}
  .kg-n{position:absolute; bottom:100%; left:0; right:0; margin-bottom:4px; text-align:center;
        font-size:11px; font-weight:800; color:var(--ink);}
  /* Ya no hay columna "abierta" que marcar: la ranura y la cifra en azul se encienden solo al
     pasar por encima. Mientras el grupo se desplegaba bajo el gráfico había que señalar cuál
     estaba abierto; ahora lo que se abre es una ventana y al cerrarla no queda nada que señalar.
     La regla anterior era :not(.cerrada), y sin esa clase habría dejado las cuatro columnas
     encendidas a la vez — descolorido el gráfico entero, que es justo lo contrario de lo que la
     vista tiene que decir al entrar. */
  .kg-col:hover .kg-n{color:var(--navy);}
  /* Mismo gap y mismo padding que .kg-cols: es lo que mantiene cada rótulo bajo su columna. */
  .kg-labs{display:flex; gap:14px; padding:8px 8px 0; margin-left:var(--kg-eje);}
  .kg-lab{flex:1 1 0; min-width:0; text-align:center; font-size:10px; color:var(--gray-soft); line-height:1.35;}
  /* El cuadrito y el nombre, en fila. El recorte con puntos suspensivos va en el <span> del
     nombre y no en el <b>: sobre un contenedor flex no se aplica, y el nombre es lo único que
     puede desbordar —el cuadrito no debe encogerse con él, de ahí el flex:0 0 auto. */
  .kg-lab b{display:flex; align-items:center; justify-content:center; gap:5px;
            color:var(--gray); font-weight:700;}
  .kg-pt{width:8px; height:8px; border-radius:2px; flex:0 0 auto;}
  .kg-nm{min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  /* El rótulo también abre la lista: es tan objetivo de clic como su columna, y con cuatro
     columnas estrechas el nombre escrito es lo más fácil de acertar. */
  .kg-lab{cursor:pointer; border-radius:6px; padding:2px 4px; margin:0 -4px;}
  .kg-lab:hover{background:var(--line-soft);}
  .kg-lab:hover b{color:var(--navy);}
  /* Bajo el gráfico hubo cuatro filas con el nombre de cada grupo y dos medidores. Se fueron
     enteras: con el gráfico nombrando los grupos y abriendo su lista, eran el mismo índice
     escrito dos veces. Lo que decían y el gráfico no —el monto comprometido— pasó al rótulo
     emergente de la columna y a la cabecera de su ventana; el dato no se perdió con el
     apartado. Sobreviven aquí solo las clases que la ventana sigue usando. */
  .kl-pt{width:9px; height:9px; border-radius:2px; flex:0 0 auto;}
  .kl-sp{flex:1 1 auto;}
  .kl-m{font-size:12px; font-weight:800; color:var(--navy); white-space:nowrap;}
  /* Con un solo grupo no hay gráfico —una columna sola no compara nada— y esta línea es lo
     único que queda: sin ella la vista saldría en blanco. */
  .kl-solo{display:flex; align-items:center; gap:10px; flex-wrap:wrap;
           padding:14px 16px; border:1px solid var(--line); border-radius:var(--r);
           background:var(--bg); font-size:12.5px; color:var(--gray);}
  .kl-solo b{color:var(--ink);}
  .kl-solo.mando{cursor:pointer;}
  .kl-solo.mando:hover{background:var(--block);}
  /* Monto de la tarjeta. En azul y con cifras tabulares para que se compare de un vistazo entre
     tarjetas; en gris y peso normal cuando no consta, porque ahí no hay cifra que comparar. */
  .kc-monto{font-size:12px; font-weight:800; color:var(--navy); margin-top:6px;}
  .kc-monto.vacio{color:var(--gray-soft); font-weight:600;}
  /* Las tarjetas viven ahora en la ventana. Tope de alto con scroll propio dentro de ella, no
     dejando rodar la tarjeta entera: con 31 contratos el título del grupo y el botón de cerrar
     se irían de la vista al bajar por la lista. */
  .kl-body{display:grid; grid-template-columns:repeat(auto-fill, minmax(268px,1fr)); gap:9px;}
  #modal .kl-body{max-height:min(520px, 56vh); overflow-y:auto; overflow-x:hidden; padding:2px;}
  #modal .kl-body::-webkit-scrollbar{width:8px;}
  #modal .kl-body::-webkit-scrollbar-thumb{background:var(--line); border-radius:8px;}
  /* Cuántos son y qué parte del filtro actual representan, sobre las tarjetas: el título de la
     ventana dice el grupo y la cifra, pero no contra qué total se está leyendo. */
  #modal .kl-aviso{display:flex; align-items:center; gap:8px; flex-wrap:wrap;
                   padding:8px 11px; margin-bottom:12px; border-radius:6px;
                   background:var(--block); font-size:11.5px; color:var(--gray);}
  #modal .kl-avm{color:var(--navy); font-weight:800;}
  @media (max-width:620px){
    /* El gráfico se achica en vez de desaparecer: es la lectura de conjunto y en móvil,
       donde recorrer las tarjetas exige más desplazamiento, es cuando más se agradece. */
    .kg{--kg-eje:26px;} .kg-plot{height:130px;} .kg-cols, .kg-labs{gap:8px;} }
  @media (prefers-reduced-motion:reduce){ .kg-bar{transition:none;} }

  /* ===================== contratos suscritos · tabla de datos =====================
     La tabla del módulo en formato data table: encabezado fijo y pulsable para ordenar,
     filas alternas y algo más densas. Todo acotado a #proybody — las demás tablas del
     sistema (.tbl es compartida) siguen exactamente igual.
     El scroll vive en .tscroll, no en #proybody (applyLista le quita .vscroll cuando hay
     tabla): position:sticky se ancla al contenedor que rueda más cercano, y con los dos
     rodando el encabezado se iba de todos modos.
     El borde inferior del encabezado va como box-shadow inset: un border-bottom sobre un
     th sticky se despega de la celda al desplazar, y queda una hendidura de 1px. */
  /* ---- la tabla, en formato consola ----
     Escrita de cero cuando la tabla dejó DataTables y las siete columnas conmutables. Cuatro
     columnas fijas, encabezado que ordena, y un pie propio con la cuenta, el tamaño de página y
     los números. Nada de esto hereda ya de la tabla densa que hubo antes, que es lo que hacía
     que cada retoque chocara con una regla de otra época. */
  .pv-tabla .tscroll{max-height:60vh; overflow:auto;}
  .pv-tabla .tscroll::-webkit-scrollbar{width:8px; height:8px;}
  .pv-tabla .tscroll::-webkit-scrollbar-thumb{background:var(--line); border-radius:8px;}

  /* table-layout:fixed para que los anchos declarados manden: en auto el navegador se los salta
     en cuanto una celda pide más, y la columna del ente se quedaba en 110px con el texto
     desbordando la fila. */
  .pv-tabla table.tb-consola{width:100%; border-collapse:collapse; table-layout:fixed;}
  .pv-tabla .tb-consola th{position:sticky; top:0; z-index:2; background:var(--bg);
    text-align:left; padding:11px 14px; font-size:10.5px; font-weight:800; letter-spacing:.06em;
    text-transform:uppercase; color:var(--gray); white-space:nowrap; cursor:pointer;
    box-shadow:inset 0 -1px 0 var(--line); user-select:none;}
  .pv-tabla .tb-consola th:hover{color:var(--navy2);}
  .pv-tabla .tb-consola th.orden{color:var(--navy);}
  .pv-tabla .tb-consola th .fl{margin-left:6px; font-size:9px; color:var(--gray-soft);
    letter-spacing:0; font-weight:700;}
  .pv-tabla .tb-consola th.orden .fl{color:var(--navy);}
  .pv-tabla .tb-consola th.nombre{width:32%;} .pv-tabla .tb-consola th.ente{width:34%;}
  .pv-tabla .tb-consola th.estado{width:17%;} .pv-tabla .tb-consola th.ck{width:17%;}

  .pv-tabla .tb-consola td{padding:11px 14px; font-size:12.5px; color:var(--ink);
    vertical-align:middle; border-bottom:1px solid var(--line-soft); overflow:hidden;}
  /* Sin franjas alternas: la fila se separa por su regla y por el aire, y la franja competía
     con el color del estado, que es lo que hay que ver. */
  .pv-tabla .tb-consola tr.click{cursor:pointer;}
  .pv-tabla .tb-consola tr.click:hover td{background:#F7FAFD;}

  /* El nombre en negrita con el sector debajo: la primera celda identifica el contrato entero,
     así que el sector no necesita columna propia.
     El recorte a dos líneas va en el elemento de dentro y nunca en el <td>: sobre la celda,
     display:-webkit-box la saca de la tabla y la columna se encoge hasta el mínimo. */
  .pv-tabla .tb-consola td.who b{display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical;
    font-weight:700; overflow:hidden; line-height:1.35;}
  .pv-tabla .tb-consola td.who .sub{display:block; margin-top:2px; font-size:11px;
    color:var(--gray); overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  .pv-tabla .tb-consola td.mini{color:var(--gray); font-size:11.5px;}
  .pv-tabla .tb-consola td.mini .dos{display:-webkit-box; -webkit-line-clamp:2;
    -webkit-box-orient:vertical; overflow:hidden; line-height:1.4;}
  .pv-tabla .tb-consola td.mini b{color:var(--ink); font-weight:700;}

  /* El estado con su icono al lado de la palabra, y los días con su punto: un punto verde y otro
     ámbar a dos milímetros son el mismo punto para quien no distingue esos dos, y aquí el estado
     es lo que decide si hay que hacer algo. */
  .pv-tabla .cs-est{display:inline-flex; align-items:center; gap:8px; white-space:nowrap;}
  .pv-tabla .cs-est svg{width:15px; height:15px; flex:none;}
  .pv-tabla .cs-est.good{color:#1E7F5C;} .pv-tabla .cs-est.rust{color:var(--rust);}
  .pv-tabla .cs-est.warn{color:var(--amber);} .pv-tabla .cs-est.mute{color:var(--gray-soft);}
  .pv-tabla .cs-ck{display:inline-flex; align-items:center; gap:8px; white-space:nowrap;}
  .pv-tabla .cs-ck i{width:8px; height:8px; border-radius:50%; flex:none;}
  .pv-tabla .cs-ck b{font-size:12px; font-weight:700; font-variant-numeric:tabular-nums;}
  .pv-tabla .cs-ck.vencido b{color:var(--rust);}  .pv-tabla .cs-ck.atencion b{color:var(--amber);}
  .pv-tabla .cs-ck.ok b{color:#1E7F5C;}
  .pv-tabla .cs-ck.sindato b{color:var(--gray-soft); font-weight:600;}

  /* ---- el pie: cuenta, tamaño de página y números ---- */
  .pv-tabla .tb-pie{display:flex; align-items:center; gap:16px; flex-wrap:wrap;
    padding:11px 2px 2px; font-size:11.5px; color:var(--gray-soft);}
  .pv-tabla .tb-pie b{color:var(--ink); font-variant-numeric:tabular-nums;}
  .pv-tabla .tb-ver select{border:1px solid var(--line); border-radius:7px; padding:3px 6px;
    background:var(--bg); color:var(--ink); font-family:inherit; font-size:11.5px; font-weight:700;
    margin:0 4px;}
  .pv-tabla .tb-pags{margin-left:auto; display:flex; gap:2px;}
  .pv-tabla .tb-p{font-size:11.5px; font-weight:700; color:var(--gray); border:1px solid transparent;
    border-radius:7px; padding:4px 9px; cursor:pointer;}
  .pv-tabla .tb-p:hover{background:var(--block); color:var(--navy2); border-color:var(--line);}
  .pv-tabla .tb-p.on, .pv-tabla .tb-p.on:hover{background:var(--navy); color:#fff; border-color:var(--navy);}
  .pv-tabla .tb-p.hueco{cursor:default; color:var(--line); padding:4px 2px;}
  .pv-tabla .tb-p.hueco:hover{background:transparent; border-color:transparent; color:var(--line);}

  /* ===================== contratos suscritos · afinado del panel de estadísticas =====================
     Correcciones de forma sobre los gráficos compartidos, acotadas a #proystats para no mover
     Correspondencia ni Inteligencia, que usan las mismas clases con otra composición.
       · Separador de 2px del color del fondo entre segmentos apilados: pegados, dos tramos
         contiguos se leen como uno solo cuando sus colores son parecidos.
       · La barra horizontal se redondea solo en su extremo de dato (derecha). Redondeada
         también a la izquierda parecía flotar en vez de arrancar del eje, y una barra muy
         corta se deformaba en una pastilla.
       · Pista de la barra un tono más suave: el gráfico gana peso frente al fondo. */
  /* ---- el panel entero, corriendo con la página ----
     Estuvo acotado a 640px con desplazamiento propio, para que sus seis secciones —cerca de
     2.900px desplegadas— no estiraran la página. Se retira por decisión de uso: dos barras en la
     misma pantalla obligan a adivinar cuál mueve qué, y la de dentro esconde secciones enteras
     sin dar señal de que están ahí. Se prefiere una página larga a una caja que oculta. */

  #proystats .in-sbar span + span{border-left:2px solid var(--bg);}
  #proystats .in-rrow .rtrack{background:var(--line-soft);}
  #proystats .in-rrow .rfill{border-radius:0 4px 4px 0;}
  #proystats .in-rrow:hover .rl{color:var(--navy2);}

  /* ---- por sector: contratos y monto en la misma fila ----
     Rejilla de tres columnas —nombre, medida, medida— repetida en el encabezado y en cada
     fila, con los mismos anchos: es lo que hace que las dos barras de un sector arranquen
     donde arrancan las del sector de arriba y se puedan comparar en vertical.
     La columna del monto es la más ancha porque su valor es la cadena más larga del panel
     ("US$ 64,5 MM + EUR 341,1 MM"). El panel anterior le daba 84px fijos y el texto se
     partía en tres líneas; aquí cabe entera.
     La del nombre subió de 148px a 206px al entrar el bloque de seguimiento. 206 es lo que
     mide la etiqueta más larga de los tres bloques —"En disputa o incumplimiento"— con su
     cuadrito y su sangría; a 148px se cortaba, y "Checkpoint vencido" perdía justo la palabra
     que lo distingue de los otros tres grupos. Los 58px salen de las columnas de barras, que
     solo pierden pista: ninguna cifra se parte por ello.
     Por debajo de 1100px la pista se quedaría en nada, así que ahí vuelve al ancho corto y se
     acepta el recorte: una barra que no se puede comparar es peor que un nombre a medias. */
  #proystats .ps-head, #proystats .ps-row{display:grid; grid-template-columns:206px 1fr 1.5fr;
                                          align-items:center; gap:16px;}
  @media (max-width:1100px){
    #proystats .ps-head, #proystats .ps-row{grid-template-columns:148px 1fr 1.5fr;}
  }
  #proystats .ps-head{padding:0 0 8px; border-bottom:1px solid var(--line); margin-bottom:4px;}
  #proystats .ps-head span{font-size:10px; font-weight:800; letter-spacing:.01em;
                           color:var(--gray-soft);}
  /* El tirón horizontal deja que el realce del hover respire fuera del texto sin mover las
     columnas: el padding lo compensa el margen negativo. */
  #proystats .ps-row{padding:8px 7px; margin:0 -7px; border-radius:7px;}
  #proystats .ps-pista{font-size:11px; color:var(--gray); margin:0 0 11px;}
  /* Solo llevan mano y realce las filas que de verdad abren algo. Una fila que se ilumina al
     pasar por encima y luego no responde al clic se lee como rota. */
  /* El mando es la celda de contratos —la gráfica—, no la fila. La mano y el realce viven ahí,
     y el nombre de la categoría queda como rótulo: sin cursor y sin responder al clic. */
  #proystats .ps-m.mando{grid-template-columns:auto 1fr auto; cursor:pointer;
                         padding:5px 7px; margin:0 -7px; border-radius:7px;
                         transition:background-color .12s ease, transform .12s ease,
                                    box-shadow .12s ease;}
  /* Al señalarla, la fila se levanta y se pone por encima de las demás: crece un 3% y
     saca sombra, así que su sombra cae sobre las vecinas y se ve cuál está delante. Con
     un fondo tenue y nada más, siete filas de barras parecidas se leían todas al mismo
     nivel. Sube a fondo blanco porque una cosa levantada recibe más luz que el suelo, y
     con el gris de antes la sombra no tenía a qué contrastar.
     El z-index de .ps-grupo:hover es lo que deja que se sobreponga de verdad: sin él la
     fila siguiente, que se pinta después, le pasaría por encima igual que le pasaba al
     aviso de los mayores. */
  #proystats .ps-m.mando:hover{background:var(--bg); transform:scale(1.03);
                               box-shadow:0 2px 6px rgba(14,20,36,.10), 0 10px 24px rgba(14,20,36,.10);}
  @media (prefers-reduced-motion:reduce){
    #proystats .ps-m.mando{transition:none;}
    #proystats .ps-m.mando:hover{transform:none;}
  }
  #proystats .ps-m.mando:hover .ps-n{color:var(--navy2);}
  /* Cuadrito y nombre en fila, así que es flex y el recorte con puntos suspensivos baja al
     <span> del nombre: sobre un contenedor flex no se aplica. Ya no lleva caret —se mudó a la
     celda de contratos, que es donde ahora se pulsa—, pero sí sangría a su izquierda para que
     el nombre no arranque pegado al borde ni se desplace respecto a como estaba. */
  #proystats .ps-l{display:flex; align-items:center; gap:7px; min-width:0; padding-left:18px;
                   font-size:12.5px; font-weight:700; color:var(--ink);}
  #proystats .ps-nm{min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  /* El cuadrito de la categoría: el mismo color que llevan sus contratos al desplegarse, y en
     el bloque de sector el mismo de su rama en "Mayores compromisos". Es lo que identifica la
     fila cuando el nombre se recorta. */
  #proystats .ps-pt{width:9px; height:9px; border-radius:2px; flex:0 0 auto;}
  /* El caret suelto de 11px en gris claro no se veía: era la única señal de que la celda de
     contratos abre algo, y en una fila ancha pasaba por adorno. Va dentro de un botón redondo
     con borde y en azul de marca — a esa escala sí se lee como "esto se pulsa".
     Apunta a la derecha y se queda ahí: la lista ya no se despliega hacia abajo, se abre en
     ventana. Un caret que baja anunciaría que la fila va a crecer, que es justo lo que no pasa;
     hacia la derecha dice "esto lleva a otro sitio". Como el círculo es simétrico, girarlo no
     lo deforma. */
  #proystats .ps-caret{width:22px; height:22px; padding:5px; box-sizing:border-box; flex:0 0 auto;
                       border:1px solid var(--line); border-radius:50%; background:var(--bg);
                       color:var(--navy2); overflow:visible; transform:rotate(-90deg);
                       transition:background .12s ease, border-color .12s ease, color .12s ease;}
  #proystats .ps-m.mando:hover .ps-caret{background:var(--navy2); border-color:var(--navy2); color:#fff;}

  /* ---- lista de contratos de una categoría, en su ventana ----
     Mismo lenguaje que las hojas del árbol de "Mayores compromisos" (nombre, barra, importe),
     porque son la misma clase de dato leído desde otro sitio.
     Va acotada a #modal y no a #proystats: es ahí donde se pinta desde que dejó de desplegarse
     bajo su fila. Sin cambiar el ámbito las reglas no la alcanzarían y saldría sin formato.
     Tope de alto con scroll propio dentro de la ventana, en vez de dejar rodar la tarjeta
     entera: Agroalimentario tiene 23 contratos y con la tarjeta rodando el título de la
     categoría y el botón de cerrar se irían de la vista al bajar por la lista. */
  /* El relleno derecho no es estético: .ps-hoja lleva margin:0 -7px para que su realce respire,
     y sin 7px que lo absorban ese margen desborda la caja. Como overflow-y:auto obliga a que
     overflow-x se calcule también como auto, aparecía una barra de scroll horizontal que no
     medía nada y que además robaba alto — con ella cabían dos contratos menos en el mismo tope. */
  /* Sin relleno arriba: el rótulo de columnas va pegado al borde y cualquier hueco por encima
     dejaría asomar una tira de fila al desplazarse por debajo de él. */
  #modal .ps-hijos{max-height:min(560px, 58vh); overflow-y:auto; overflow-x:hidden;
                   padding:0 8px 2px 8px;}
  #modal .ps-hijos::-webkit-scrollbar{width:8px;}
  #modal .ps-hijos::-webkit-scrollbar-thumb{background:var(--line); border-radius:8px;}
  /* Sin la columna de la guía en L: colgaba del nombre del sector, que en la ventana ya no está
     encima —lo dice el título— y una L que no arranca de ninguna parte solo desalinea.
     La segunda columna es la fecha de firma. Mide 104px porque la cadena más larga que trae el
     expediente es "1 y 3-oct-2025"; con menos se recortaría justo la que avisa de que hay dos
     fechas de firma. */
  #modal .ps-hoja, #modal .ps-lhead{display:grid; grid-template-columns:1fr 104px 120px 104px;
                                    align-items:center; gap:10px;}
  #modal .ps-hoja{padding:6px 7px; margin:0 -7px; border-radius:7px; cursor:pointer;}
  #modal .ps-hoja:hover{background:var(--block);}
  #modal .ps-hoja:hover .ps-hnm{color:var(--navy2);}
  /* Rótulos de columna, en el mismo tono que los del panel. Pegados arriba: la lista rueda por
     debajo y sin esto los rótulos se irían al primer desplazamiento, que es justo cuando hacen
     falta —con 23 filas ya no se ve de dónde salía cada columna. */
  /* El mismo tirón horizontal que las filas (padding 7px con margen -7px): sin él la caja del
     rótulo mide 14px menos que la de una fila y sus columnas fijas quedan desplazadas — el
     rótulo "Monto" no caería sobre la cifra que rotula. */
  #modal .ps-lhead{position:sticky; top:0; z-index:1; background:#fff;
                   padding:0 7px 6px; margin:0 -7px 2px; border-bottom:1px solid var(--line);}
  #modal .ps-lhead span{font-size:9.5px; font-weight:800; letter-spacing:.01em;
                        color:var(--gray-soft);}
  #modal .ps-lhead span:last-child{text-align:right;}
  #modal .ps-hnm{min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;
                 font-size:12px; font-weight:600; color:var(--ink);}
  /* La fecha del expediente, tal cual. Atenuada cuando no da el día ("~2021", "no consta"):
     a simple vista una fila sin fecha y una con fecha aproximada no deben leerse igual. */
  #modal .ps-hfec{font-size:11px; color:var(--gray); font-variant-numeric:tabular-nums;
                  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;}
  #modal .ps-hfec.vacio{color:var(--gray-soft); font-style:italic;}
  /* Marca de "mayor compromiso", con el puesto dentro. En azul de marca sobre fondo claro y no
     en uno de los colores semánticos del módulo (ámbar de atención, rojo de disputa): el puesto
     en el ranking no dice nada sobre el estado del contrato, y tomar prestado uno de esos
     colores lo haría parecer una alerta. */
  #modal .ps-top{display:inline-block; margin-right:7px; padding:1px 5px; border-radius:4px;
                 background:#E4EDF8; color:var(--navy); font-size:9.5px; font-weight:800;
                 font-variant-numeric:tabular-nums; vertical-align:1px;}
  #modal .ps-hoja.top .ps-hnm{font-weight:800;}
  /* Cuántos mayores guarda la categoría, bajo su importe. Es lo que dice cuál merece abrirse
     sin tener que abrirlas todas, así que va en azul y no en el gris del resto de pies.
     El selector repite `.ps-v small` para ganarle por especificidad a la regla de los pies
     grises, que si no le impone su color por ir después con el mismo peso. */
  #proystats .ps-v small.ps-topn{color:var(--navy2); font-weight:700;}
  #modal .ps-hbar{height:9px; border-radius:3px; background:var(--line-soft); overflow:hidden;}
  #modal .ps-hfill{display:block; height:100%; border-radius:0 3px 3px 0;}
  #modal .ps-hval{text-align:right; font-size:11.5px; font-weight:800; color:var(--ink);}
  #modal .ps-hval.vacio{font-weight:600; color:var(--gray-soft);}
  /* Estrecho: cae la barra, que es la única columna cuyo dato ya está escrito al lado —el
     importe—. La fecha se queda: no se repite en ningún otro sitio de la fila. */
  @media (max-width:820px){
    #modal .ps-hoja, #modal .ps-lhead{grid-template-columns:1fr auto auto;}
    #modal .ps-hbar, #modal .ps-lhead span:nth-child(3){display:none;}
  }
  /* Cada medida es barra + valor. El valor con ancho fijo para que las barras terminen
     todas en la misma vertical, que es de donde sale la comparación. */
  #proystats .ps-m{display:grid; grid-template-columns:1fr auto; align-items:center; gap:10px;
                   min-width:0;}
  #proystats .ps-track{height:14px; border-radius:4px; background:var(--line-soft); overflow:hidden;}
  /* La barra de contratos va del color de su categoría —en sector, la paleta categórica que ya
     usa el árbol de "Mayores compromisos"; en estado, el verde/gris/rojo/ámbar de siempre—, así
     que la fila se identifica por color además de por el nombre, y coincide con el color de los
     contratos que despliega. La de monto se queda de un solo azul: el color pasa a decir de qué
     categoría es la fila, y el azul, cuál de las dos medidas se está mirando.
     La paleta de sector está validada para pares adyacentes y aquí se cumplen sus condiciones:
     cada fila lleva su nombre escrito al lado y dos categorías nunca comparten barra. */
  #proystats .ps-fill{height:100%; border-radius:0 4px 4px 0; transition:filter .12s ease;}
  /* El realce de la barra sigue al mando, no a la fila: pasar por el nombre ya no ilumina nada
     porque ahí no hay nada que pulsar. */
  #proystats .ps-m.mando:hover .ps-fill{filter:saturate(1.4) brightness(.94);}
  /* Sin monto declarado no hay barra que pintar: el ancho es cero y el relleno no debe
     dejar ni la esquina redondeada asomando, que se leería como un importe minúsculo. */
  #proystats .ps-fill.vacio{display:none;}
  /* Barra de contratos partida por estado. Los segmentos son hermanos en fila dentro del mismo
     ancho que ocuparía la barra entera, así que el largo total sigue midiendo lo mismo que
     antes —contratos frente al mayor— y lo que se añade es su reparto interno. El redondeo va
     en el contenedor y no en cada segmento: redondeados uno a uno se leerían como cuatro barras
     sueltas en vez de una repartida. */
  #proystats .ps-seg{height:100%; display:flex; border-radius:0 4px 4px 0; overflow:hidden;}
  /* Cada tramo abre la ventana acotada a su estado, así que se comporta como un mando. Ya no
     hay tramo "activo" que resaltar: lo que se abre es una ventana, no una lista que quede
     desplegada marcando de dónde salió. */
  #proystats .ps-seg span{display:block; height:100%; cursor:pointer; transition:filter .12s ease;}
  #proystats .ps-seg span:hover{filter:saturate(1.5) brightness(.9);}
  /* Aviso de qué acota la lista. Va dentro de la ventana, sobre las filas, porque describe lo
     que se está viendo debajo — no la categoría entera, que ya la dice el título. */
  #modal .ps-filtro{display:flex; align-items:center; gap:7px; flex-wrap:wrap;
                    padding:7px 9px; margin:0 0 8px; border-radius:6px;
                    background:var(--block); font-size:11.5px; color:var(--gray);}
  #modal .ps-filtro i{width:9px; height:9px; border-radius:2px; flex:0 0 auto;}
  #modal .ps-filtro b{color:var(--ink); font-weight:800;}
  #modal .ps-filtro .op-link{margin-left:auto; font-size:11.5px;}
  /* ---- leyenda de los estados, escrita en su propia fila ----
     Entre los rótulos de columna y las barras. Estuvo así, pasó a una píldora emergente colgada
     del rótulo —para no gastar una línea en algo que se consulta una vez— y vuelve a estarlo: la
     emergente obliga a saber que hay algo que señalar, y quien no lo sabe no descubre nunca qué
     significan los colores. Con ella se fueron .ps-info y .ps-mini, que eran su disparador.
     Cuesta 25px y queda a 20px de la primera barra, la más cerca de las seis ubicaciones
     probadas en maqueta-leyenda-estados.html.
     El borde inferior la ata a las barras que explica en vez de dejarla flotando bajo los
     rótulos; el <b> va en versalitas como los rótulos de columna, y los nombres de los estados
     NO — son datos, no encabezados. */
  #proystats .ps-leyfila{display:flex; align-items:center; gap:14px; flex-wrap:wrap;
                         padding:7px 0 9px; margin-bottom:2px; border-bottom:1px solid var(--line);}
  #proystats .ps-leyfila > b{font-size:10px; font-weight:800; letter-spacing:.01em;
                             color:var(--gray-soft);}
  #proystats .ps-leyfila > span{display:inline-flex; align-items:center; gap:6px;
                                font-size:10.5px; font-weight:700; color:var(--gray);
                                text-transform:none; letter-spacing:0;}
  #proystats .ps-leyfila i{width:9px; height:9px; border-radius:2px; flex:0 0 auto;}
  /* z-index alto y posición absoluta: el aviso tiene que poder salirse de la fila del
     encabezado sin empujar nada ni quedar por debajo de las barras de las filas siguientes. */
  #proystats .ps-tip{display:none; position:absolute; top:22px; left:-8px; z-index:40;
                     min-width:210px; padding:10px 12px; border-radius:var(--r-sm);
                     background:var(--bg); border:1px solid var(--line); box-shadow:var(--shadow);
                     font-size:11.5px; font-weight:600; font-style:normal; color:var(--gray);
                     text-align:left; letter-spacing:0;}
  /* Cualquier elemento con .ps-hint enseña su aviso al señalarlo o al recibir el foco. Lo usa el
     pie del monto ("N de los 12 mayores"), que dice cuántos y al señalarlo dice cuáles; la
     píldora de la leyenda también lo usaba, hasta que la leyenda pasó a fila escrita. Necesitan
     position:relative para que el aviso, que es absoluto, se cuelgue de ellos y no de la fila. */
  #proystats .ps-hint{position:relative; cursor:help;}
  /* El que además lleva a otro sitio va con mano, no con el interrogante: el cursor tiene que
     decir que ahí hay un destino y no solo una explicación. */
  #proystats .ps-hint.clic{cursor:pointer;}
  #proystats .ps-hint.clic:hover{color:var(--navy);}
  /* Pie del aviso, separado por una línea: anuncia el salto sin mezclarse con la lista de
     contratos que hay encima. */
  #proystats .ps-tip-pie{display:block; margin-top:8px; padding-top:8px;
                         border-top:1px solid var(--line-soft); font-size:10.5px;
                         font-weight:600; color:var(--gray-soft); text-transform:none;
                         letter-spacing:0;}
  /* El selector repite `.ps-tip` para ganarle a la regla del título del aviso, que va después
     en la hoja con la misma especificidad y pone versalitas a todo <b> de dentro. */
  #proystats .ps-tip .ps-tip-pie b{display:inline; margin:0; font-size:10.5px; text-transform:none;
                           letter-spacing:0; color:var(--navy2); font-weight:800;}
  /* :focus-visible y no :focus. Con :focus, un clic dejaba el aviso abierto hasta pulsar en
     otro sitio — el elemento recibe el foco al pulsarlo y ya no lo suelta. :focus-visible solo
     responde al foco que llega por teclado, así que el ratón lo abre y lo cierra al salir, y
     quien navega con el tabulador lo sigue teniendo.
     El disparador lleva además onmousedown="event.preventDefault()", que impide que el ratón
     llegue a dar el foco. Es cinturón y tirantes a propósito: :focus-visible depende de una
     heurística del navegador sobre de dónde vino el foco, y el aviso pegajoso al hacer clic
     tiene que quedar descartado sin depender de ella. El tabulador no pasa por mousedown, así
     que el acceso por teclado no se toca. */
  #proystats .ps-hint:hover > .ps-tip, #proystats .ps-hint:focus-visible > .ps-tip{display:block;}
  #proystats .ps-hint:focus{outline:none;}
  #proystats .ps-hint:focus-visible{outline:2px solid var(--navy2); outline-offset:2px; border-radius:3px;}
  /* El subrayado punteado avisa de que ahí hay algo que leer. Llevaba un :not(.ps-info) para
     excluir la píldora de la leyenda, que tenía borde propio; sin píldora, la excepción sobra. */
  #proystats .ps-hint:hover,
  #proystats .ps-hint:focus-visible{text-decoration:underline dotted; text-underline-offset:3px;}
  #proystats .ps-tip b{display:block; margin-bottom:7px; font-size:10.5px; font-weight:800;
                       letter-spacing:.01em; color:var(--gray-soft);}
  /* El aviso cuelga del rótulo de columna, que va en versalitas y espaciado; sin devolver aquí
     text-transform y letter-spacing a su valor normal, los nombres de los estados salen en
     mayúsculas y separados, como si fueran otro encabezado. */
  #proystats .ps-tip span{display:flex; align-items:center; gap:7px; padding:2px 0; color:var(--ink);
                          text-transform:none; letter-spacing:0; font-size:11.5px; font-weight:600;}
  /* Colgado a la derecha: los pies del monto viven en la última columna, y un aviso anclado a
     la izquierda se saldría de la pantalla.
     Más ancho que el de la leyenda porque aquí cada línea lleva nombre de contrato e importe:
     con los 210px de aquella, "Centrales azucareras (Paciscor)" se partía en tres renglones. */
  /* Sube: colgando hacia abajo tapaba las filas siguientes, que es donde está lo que se
     compara con lo que el aviso cuenta. Arriba se apoya en lo ya leído. Y se corre 8px a
     la derecha, hasta el borde del panel, que es todo el margen que hay: el padding-right
     de #proystats son 10px y más allá empieza a recortar, porque un contenedor con
     overflow-y:auto también recorta en horizontal. */
  #proystats .ps-tip.der{left:auto; right:-8px; top:auto; bottom:calc(100% + 7px);
                         min-width:330px;}
  /* El nombre empuja y el dato de la derecha no se parte: así los avisos de contratos se leen
     como una lista de dos columnas y no como texto corrido. */
  #proystats .ps-tip.der span{text-align:left;}
  #proystats .ps-tip em{margin-left:auto; padding-left:12px; font-style:normal; font-weight:800;
                        color:var(--navy); white-space:nowrap;}
  /* margin-right propio y no solo el gap del flex: el nombre del contrato es un nodo de texto
     suelto, y contra él el hueco no separa — el chip quedaba pegado a la primera letra.
     Eran 2px y no bastaban: con dos cifras ("#10VENTEKNO", "#12Veneminsk") el puesto y el
     nombre se leían como una sola palabra. Suben a los 7 del resto de la lista. */
  #proystats .ps-rank{flex:0 0 auto; width:auto; height:auto; border-radius:4px; padding:1px 5px;
                      margin-right:7px; background:#E4EDF8; color:var(--navy); font-size:9.5px;
                      font-weight:800; font-style:normal; font-variant-numeric:tabular-nums;}
  #proystats .ps-tip i{width:10px; height:10px; border-radius:2px; flex:0 0 auto;}
  /* La cifra y su porcentaje se marcan juntos al señalar la fila: son la misma lectura, y
     entre siete filas de barras parecidas hay que poder ver de un vistazo sobre cuál está
     el puntero. El realce de la celda entera ya existía, pero es un fondo muy tenue a lo
     ancho de media fila; una pastilla sobre las dos cifras cae justo donde está mirando
     quien compara números.
     Los 50px con border-box dejan los mismos 38 de texto y el resto es el aire de la
     pastilla. Sin margen negativo a la derecha a propósito: devolvería las cifras a su
     columna de antes, pero dejaría la pastilla pegada al borde del cuadro —a 1px—, y ahí
     el realce se lee como un defecto del marco. Las cifras se corren 6px a la izquierda,
     igual en las siete filas, y la pastilla respira. */
  #proystats .ps-n{width:50px; padding:3px 6px; border-radius:7px;
                   text-align:right; font-size:12.5px; font-weight:800; color:var(--ink);
                   line-height:1.2; transition:background-color .12s ease, color .12s ease;}
  #proystats .ps-m.mando:hover .ps-n{background:#E4EDF8;}
  #proystats .ps-m.mando:hover .ps-n small{color:var(--navy2);}
  /* Una cifra a la vez, la que pida el interruptor de la cabecera. Las dos van siempre
     escritas y aquí se decide cuál se ve: cambiar de una a otra es quitar y poner una
     clase, sin repintar el panel. Los 38px de texto salen de "100%", lo más ancho que
     puede escribir cualquiera de las dos. */
  #proystats .ps-n b{font-weight:800;}
  #proystats .ps-n .cp,
  #proystats.pct .ps-n .cn{display:none;}
  #proystats.pct .ps-n .cp{display:inline;}
  /* El interruptor, pegado al rótulo de la columna que manda. Dos pastillas dentro de una
     ranura, como el de Tabla/Kanban de arriba: es el mismo gesto y conviene que se vea que
     lo es. La que está activa sale en blanco sobre el gris de la ranura —el mismo recurso
     que ahí— y no en color, que competiría con las barras. */
  /* La cabecera deja de ser rejilla para poder llevar el interruptor pegado a su rótulo:
     con las columnas "1fr auto" de las filas, el interruptor se iba al extremo derecho de
     la columna y quedaba huérfano, lejos de la palabra que califica. */
  #proystats .ps-head .ps-m{display:flex; align-items:center;}
  #proystats .cifsw{display:inline-flex; gap:2px; margin-left:8px; padding:2px;
                    background:var(--block); border:1px solid var(--line); border-radius:7px;
                    vertical-align:middle;}
  #proystats .cifsw button{border:0; background:transparent; cursor:pointer; padding:1px 6px;
                           border-radius:5px; font:inherit; font-size:9.5px; font-weight:800;
                           letter-spacing:.03em; color:var(--gray-soft); line-height:1.5;
                           transition:background-color .12s ease, color .12s ease;}
  #proystats .cifsw button:hover{color:var(--navy2);}
  #proystats:not(.pct) .cifsw .cn,
  #proystats.pct .cifsw .cp{background:var(--bg); color:var(--navy); box-shadow:0 1px 2px rgba(14,20,36,.10);}
  #proystats .cifsw button:focus-visible{outline:2px solid var(--navy2); outline-offset:1px;}
  @media (prefers-reduced-motion:reduce){ #proystats .cifsw button{transition:none;} }
  /* En estrecho no hay cabecera, así que tampoco hay interruptor: la fila apilada le da
     una línea entera a la medida y caben las dos cifras juntas, que es mejor que dejar
     una escondida sin manera de sacarla. */
  @media (max-width:980px){
    #proystats .ps-n .cp,
    #proystats.pct .ps-n .cn{display:inline;}
    #proystats .ps-n .cp::before{content:' · '; font-weight:600; color:var(--gray-soft);}
    /* Ancho por contenido: los 50px están medidos para una cifra sola y con las dos
       juntas "23 · 37%" se partía en dos renglones. */
    #proystats .ps-n{width:auto; white-space:nowrap;}
  }
  #proystats .ps-v{width:132px; text-align:right; font-size:12.5px; font-weight:800; color:var(--ink);
                   line-height:1.35;}
  /* Cada moneda ocupa su línea entera y no se parte nunca: con las dos unidas por " + " el
     navegador cortaba donde le cabía y dejaba un "MM" huérfano en la línea siguiente. */
  #proystats .ps-cur{display:block; white-space:nowrap;}
  #proystats .ps-v.vacio{font-size:11.5px; font-weight:600; color:var(--gray-soft);}
  #proystats .ps-v small{display:block; font-weight:600; color:var(--gray); font-size:10.5px;}
  /* En estrecho la fila se parte en líneas apiladas: con tres columnas fijas las dos barras
     se quedaban en muñones y dejaban de medir nada. El encabezado se oculta —ya no hay
     columnas que encabezar—, así que cada medida recupera su rótulo de data-rot: sin él las
     dos barras quedarían sin decir cuál es cuál, que es justo lo que este panel vino a
     arreglar. Rótulo · barra · valor es además la misma forma que los medidores del Kanban.
     El corte estaba en 820px y llegaba tarde: por debajo de unos 970 las tres columnas ya no
     caben —las cifras de monto y "N de los 12 mayores" tienen un ancho mínimo que no cede— y
     la fila se salía del bloque (medido: 23px a 900px de ventana, que se comían el final de
     las barras). Sube a 980 para que apile antes de que empiece a apretar. */
  @media (max-width:980px){
    #proystats .ps-head{display:none;}
    #proystats .ps-row{grid-template-columns:1fr; gap:7px; padding:11px 0;
                       border-bottom:1px solid var(--line-soft);}
    #proystats .ps-m{grid-template-columns:74px 1fr auto; gap:10px;}
    /* La celda de contratos lleva un cuarto hijo —la mano— y se quedaba con la plantilla
       de tres de arriba: el rótulo se comía la columna de la barra, la barra se encogía a
       nada y la cifra caía a una segunda línea. Se le da su propia columna a la mano. */
    #proystats .ps-m.mando{grid-template-columns:74px auto 1fr auto;}
    #proystats .ps-m::before{content:attr(data-rot); font-size:10px; font-weight:800;
                             letter-spacing:.01em; color:var(--gray-soft);}
    #proystats .ps-v{width:auto;}
  }

  /* Dentro de una caja hay que reservarle sitio al tirón horizontal del realce: .ps-row y
     .ps-m.mando se salen 7px a cada lado con su margen negativo —es lo que deja respirar el
     resaltado sin mover las columnas—, y contra el borde de la caja eso desborda. Los 7px de
     padding lo compensan; van también en el encabezado y la leyenda para que las columnas
     sigan cuadrando. En plano no hacía falta: el panel no tenía borde contra el que chocar. */
  #proystats section.card .ps-bloque,
  #proystats section.card .ps-pista,
  #proystats section.card .ps-leyfila{padding-left:7px; padding-right:7px;}
  /* El encabezado ya vive dentro del bloque: hereda su padding y no lleva el suyo, o las
     columnas se le irían 7px respecto a las filas, que recuperan el borde con su margen
     negativo. Medido: rótulo y columna arrancan ambos en el mismo píxel. */
  #proystats section.card .ps-head{padding:0 0 9px;}

  /* ---- los dos cuadros de cada bloque ----
     Cada bloque enmarca sus dos medidas por separado: uno para los contratos —con el
     nombre del grupo dentro, que es lo que la barra cuenta— y otro para el monto
     comprometido. Son dos preguntas distintas: cuántos y cuánto. Un solo cuadro las
     daba por una sola lectura, y una caja por fila partía la comparación entre grupos
     en siete lecturas sueltas; dos columnas enmarcadas dejan comparar de arriba abajo
     dentro de cada medida y separan lo que no se compara entre sí.
     Los marcos no envuelven las filas: son una capa aparte con la MISMA rejilla de la
     fila (206px 1fr 1.5fr, gap 16px), así que caen sobre las columnas sin que haya que
     repetir la medida en dos sitios ni tocar el HTML de cada fila. Cambiar la rejilla
     cambia los dos a la vez.
     Cada marco se sale 7px a los lados de su columna. Sin eso el contenido nace pegado
     al borde —la barra azul arrancaba justo encima de la línea y las cifras terminaban
     encima de la de la derecha— y además la celda del mando se sale esos mismos 7px al
     realzarse, con lo que el resaltado asomaba fuera del marco. Por lo mismo el gap del
     bloque sube de 16 a 30px dentro de la caja: 14 se los comen los dos marcos al
     estirarse y quedan los 16 de aire de siempre entre uno y otro. El gap va también en
     el encabezado y en la fila, o los rótulos dejarían de caer sobre sus columnas.
     Las filas van por encima con z-index: el realce tiene que verse sobre el marco. */
  #proystats section.card .ps-bloque{position:relative; padding-top:10px; padding-bottom:6px;}
  #proystats section.card .ps-grupo,
  #proystats section.card .ps-head{position:relative; z-index:1;}
  /* El z-index de la fila la vuelve un contexto de apilado, y dentro de él el aviso de
     "N de los 12 mayores" deja de valer 40 hacia fuera: las filas de debajo se pintan
     después, con el mismo 1, y le pasaban por encima —se leía el aviso y los importes de
     las otras filas a la vez—. Al señalarla, la fila sube por encima de sus hermanas. */
  #proystats section.card .ps-grupo:hover,
  #proystats section.card .ps-grupo:focus-within{z-index:30;}
  #proystats section.card .ps-head,
  #proystats section.card .ps-row,
  #proystats section.card .ps-marcos{gap:30px;}
  #proystats section.card .ps-marcos{position:absolute; top:0; bottom:0; left:7px; right:7px;
    display:grid; grid-template-columns:206px 1fr 1.5fr; pointer-events:none;}
  @media (max-width:1100px){
    #proystats section.card .ps-marcos{grid-template-columns:148px 1fr 1.5fr;}
  }
  #proystats section.card .ps-marcos i{border:1px solid var(--line); border-radius:9px;
    background:var(--bg); margin:0 -7px;}
  #proystats section.card .ps-marcos i:first-child{grid-column:1 / 3;}
  #proystats section.card .ps-marcos i:last-child{grid-column:3 / 4;}
  /* El encabezado pierde su línea inferior: dentro del cuadro la raya lo partiría en dos,
     y quien separa las medidas ya es el borde de cada marco. */
  #proystats section.card .ps-head{border-bottom:0; margin-bottom:0;}
  #proystats section.card .ps-leyfila{margin-bottom:9px;}
  /* Por debajo de 980px la fila apila sus medidas una encima de otra: ya no hay dos
     columnas que enmarcar, y el separador de la fila hace el trabajo. */
  @media (max-width:980px){
    #proystats section.card .ps-marcos{display:none;}
  }

  /* ---- realce al pasar el puntero ----
     El color se intensifica en vez de cambiar: cada marca conserva su identidad
     (el sector, el estado) y solo sube de intensidad, que es lo que hay que hacer
     para señalar sin repintar. Va con filter y no con un color alternativo porque
     el color de cada marca llega inline desde el JS —del sector o del estado— y no
     hay forma de escribir de antemano una versión "más fuerte" de cada uno.
     saturate sube la viveza y brightness compensa el aclarado que trae saturar;
     juntos dan un tono más denso, no otro tono.
     El realce se dispara desde la FILA o la columna entera, no desde la barra: una
     barra de 14px de alto (o un segmento angosto) es un objetivo muy fino para el
     puntero, y con el área grande el realce responde donde el ojo ya está. */
  #proystats .in-rrow .rfill,
  #proystats .in-sbar span,
  #proystats .cr-col-bar{transition:filter .12s ease;}
  #proystats .in-rrow:hover .rfill,
  #proystats .in-sbar span:hover,
  #proystats .cr-col:hover .cr-col-bar{filter:saturate(1.45) brightness(.92);}
  /* La columna sin datos no tiene barra que realzar: se marca la ranura para que
     pasar por encima no parezca que el gráfico dejó de responder. */
  #proystats .cr-col{border-radius:5px; transition:background .12s ease;}
  #proystats .cr-col:hover{background:var(--line-soft);}
  /* Pie del gráfico de años. Los contratos sin fecha de firma precisa quedan fuera de las
     columnas —son 23 de 63: con columna propia serían la segunda más alta y darían a entender
     un "año" que no existe—, pero siguen siendo contratos del expediente. El título de la
     sección los contaba y ahí se acababa; desde aquí se abren y se ve cuáles son. */
  #proystats .pr-anio-pie{margin-top:12px; font-size:11.5px; color:var(--gray);}
  #proystats .pr-anio-pie .op-link{font-size:11.5px;}
  @media (prefers-reduced-motion:reduce){
    #proystats .in-rrow .rfill, #proystats .in-sbar span, #proystats .cr-col-bar,
    #proystats .cr-col{transition:none;}
  }

  /* ===================== contratos suscritos · interruptores de columna =====================
     Lista de encendido/apagado, una fila por columna de la tabla, dentro de la ventana de
     "Columnas" (el mismo componente .af-pop de Afinar). Dos columnas mientras quepan: siete
     filas en una sola tira obligaban a una ventana muy alta.
     El interruptor es puro CSS —.pc-sw con el botón en ::after—, no un <input type=checkbox>:
     la fila entera ya es el área de clic y un checkbox real solo agregaría un segundo objetivo
     con su propio foco. La columna fija (Proyecto) se apaga visualmente y no responde. */
  .pc-lista{display:grid; grid-template-columns:repeat(auto-fill, minmax(158px,1fr)); gap:0 18px;}
  .pc-row{display:flex; align-items:center; gap:10px; padding:7px 2px; cursor:pointer; user-select:none;}
  .pc-row.fija{cursor:default; opacity:.55;}
  .pc-row:not(.fija):hover .pc-l{color:var(--navy2);}
  .pc-sw{width:32px; height:18px; border-radius:20px; background:#D9DEE7; position:relative; flex:0 0 auto;
         transition:background .15s ease;}
  .pc-sw::after{content:''; position:absolute; top:2px; left:2px; width:14px; height:14px; border-radius:50%;
                background:#fff; box-shadow:0 1px 2px rgba(14,20,36,.25); transition:transform .15s ease;}
  .pc-sw.on{background:var(--navy);}
  .pc-sw.on::after{transform:translateX(14px);}
  .pc-l{font-size:12.5px; font-weight:600; color:var(--ink); white-space:nowrap;}
  .pc-row.off .pc-l{color:var(--gray-soft); font-weight:500;}
  @media (prefers-reduced-motion:reduce){ .pc-sw, .pc-sw::after{transition:none;} }

  /* ===================== contratos suscritos · mayores compromisos =====================
     Aquí vivía el árbol plegable sector → contrato: .pr-rama, .pr-sec, .pr-hoja, las guías en L
     de .pr-gui y su barra de peso. Se fue entero con el marcado — el bloque pasó al componente
     común (.ps-*), que ya dibuja categoría, cuenta y monto y abre su lista en ventana.
     No queda nada que acotar aquí: lo único .pr- que sobrevive es .pr-anio-pie, el pie del
     gráfico de firmas por año, que está con el resto del panel más arriba. */

  /* ===================== impresión (Reportería de correspondencia) =====================
     Primera hoja de impresión de Atlas: sin librería, calcado del @page + print-color-adjust
     que ya usaba el sistema original de correspondencia. .no-print oculta cromo de navegación;
     #view a bloque simple evita que el grid de 12 columnas corte paneles entre páginas. */
  @page{ size:A4; margin:12mm; }
  /* ===================== IMPRESIÓN DESHABILITADA =====================
     Política de privacidad: Atlas maneja expedientes delicados y no debe poder
     llevarse a papel. Todo intento de imprimir sale en blanco, con una sola línea
     que deja claro que es intencional y no una falla de maquetado.

     Cubre TODAS las vías, porque todas usan el mismo motor del navegador:
     Ctrl+P, el menú del navegador, y "Guardar como PDF" (que es imprimir a un
     archivo, no una exportación aparte).

     ALCANCE REAL: esto es disuasión, no seguridad. No impide captura de pantalla,
     copiar y pegar, guardar el HTML ni las herramientas de desarrollo. El control
     efectivo sobre quién ve qué vive en las políticas RLS de Postgres.

     Historia: hasta el commit c8fb939 existía una hoja de impresión para la
     reportería de Correspondencia (A4, márgenes de 12 mm, .no-print para ocultar
     el cromo). Ese commit quitó los botones pero dejó el CSS; aquí se sustituye
     por el bloqueo. Las clases .no-print que quedan en el marcado son inertes. */
  @page{ size:A4; margin:0; }
  @media print{
    html, body{ background:#fff !important; }
    /* nada del documento llega al papel */
    body > *{ display:none !important; }
    body::before{
      display:block !important;
      content:"Impresión deshabilitada por política de privacidad · Atlas — CIIP";
      font:600 11px/1.6 system-ui, -apple-system, sans-serif;
      color:#111; padding:16mm;
    }
    *{ -webkit-print-color-adjust:exact; print-color-adjust:exact; }
    .sidebar, .topbar, .no-print{ display:none !important; }
    #view{ display:block; }
    #view .col12, #view .col8, #view .col7, #view .col6, #view .col5, #view .col4{ break-inside:avoid; margin-bottom:14px; }
    body{ background:#fff; }
    .cr-scroll-y, .cr-scroll-y-xl{ max-height:none; overflow:visible; } /* impreso: todo el panel visible, sin recorte de scroll */
    .cr-scroll-x{ overflow:visible; }
  }

  /* ---------- CMS de plantillas ---------- */
  /* Dos columnas: la lista y la zona de trabajo. En modo Diseño la zona de trabajo es
     el documento entero, a toda su anchura; en modo HTML se parte en código y
     previsualización. La hoja mide 816px fijos, así que se le deja el ancho. */
  .plm{display:grid; grid-template-columns:210px minmax(0,1fr); gap:14px; align-items:stretch;}
  .plm-lista{border:1px solid var(--line); border-radius:var(--r-sm); background:var(--block);}
  .plm-lista-top{display:flex; gap:6px; padding:8px; border-bottom:1px solid var(--line); position:sticky; top:0; background:var(--block); z-index:1;}
  .plm-grupo{font-size:9.5px; font-weight:700; letter-spacing:.01em; color:var(--gray); padding:11px 10px 5px;}
  .plm-item{display:flex; align-items:center; gap:7px; padding:7px 10px; cursor:pointer; font-size:12px; line-height:1.35; border-left:2px solid transparent;}
  .plm-item:hover{background:var(--bg);}
  .plm-item.on{background:var(--bg); border-left-color:var(--navy); font-weight:600;}
  .plm-item-n{flex:1 1 auto; overflow:hidden; text-overflow:ellipsis;}
  /* punto de origen: relleno = el contenido ya vive en la base; hueco = sale del repo */
  .plm-item-o{flex:0 0 auto; width:7px; height:7px; border-radius:50%; border:1px solid var(--gray);}
  .plm-item-o.base{background:var(--good); border-color:var(--good);}

  .plm-obra{display:flex; flex-direction:column; gap:8px; min-width:0;}
  .plm-barra{display:flex; flex-wrap:wrap; gap:8px; align-items:center;}
  .plm-frags{display:flex; flex-wrap:wrap; gap:5px; align-items:center;}
  /* Selector de modo: Diseño primero porque es el que sirve a quien no programa. */
  .plm-modos{display:inline-flex; border:1px solid var(--line); border-radius:8px; overflow:hidden;}
  .plm-modo{border:0; background:var(--bg); color:var(--gray); cursor:pointer;
    font-family:inherit; font-size:11.5px; font-weight:600; padding:6px 14px;}
  .plm-modo + .plm-modo{border-left:1px solid var(--line);}
  .plm-modo:hover{background:var(--block);}
  .plm-modo.on{background:var(--navy); color:#fff;}
  .plm-pista{font-size:11.5px; color:var(--gray); line-height:1.5; margin:0;}

  .plm-paneles{display:grid; gap:10px; grid-template-columns:minmax(0,1fr);}
  .plm-paneles textarea{width:100%; height:calc(100vh - 360px); min-height:0;
    font-family:ui-monospace,SFMono-Regular,Consolas,'Liberation Mono',monospace; font-size:11.5px; line-height:1.55;
    border:1px solid var(--line); border-radius:var(--r-sm); padding:11px 12px; color:var(--ink); background:var(--bg);
    resize:none; white-space:pre; overflow:auto; tab-size:2;}
  .plm-paneles textarea:focus{outline:none; border-color:var(--navy);}
  .plm-paneles textarea:disabled{background:var(--block); color:var(--gray);}
  .plm-paneles iframe{width:100%; height:calc(100vh - 360px);
    border:1px solid var(--line); border-radius:var(--r-sm); background:var(--block);}
  /* En Diseño el código no estorba; en HTML se ve al lado de lo que produce. */
  .modo-diseno .plm-paneles textarea{display:none;}
  .modo-html .plm-paneles{grid-template-columns:minmax(280px,1fr) minmax(340px,1fr);}

  /* Menú de "añadir bloque": cada opción con su nombre y para qué sirve, porque
     "Nota" o "Indicadores" no dicen nada por sí solos. */
  .plm-menu{display:grid; gap:6px;}
  .plm-menu .btn{display:flex; flex-direction:column; align-items:flex-start; gap:2px;
    text-align:left; height:auto; padding:9px 12px;}
  .plm-menu .btn span{font-weight:400; font-size:11px; color:var(--gray); line-height:1.4;}

  .plm-meta{display:flex; flex-wrap:wrap; gap:6px; align-items:center; margin-top:12px; padding-top:12px; border-top:1px solid var(--line);}

  /* Por debajo de un portátil ancho las columnas no caben: se apilan y cada panel
     recupera una altura propia en vez de repartirse la del viewport. */
  @media (max-width:1200px){
    .plm{grid-template-columns:minmax(0,1fr);}
    .plm-lista{max-height:220px;}
    .modo-html .plm-paneles{grid-template-columns:minmax(0,1fr);}
    .plm-paneles textarea, .plm-paneles iframe{height:460px;}
  }
  /* ===================== exportación a PDF (compartida) =====================
     html2pdf captura el DOM tal como está en pantalla, no imprime, así que las
     reglas de @media print no le aplican: hacen falta las mismas aquí, activas
     solo durante la captura. La clase la pone y la quita quien exporta; fuera
     de ese instante no afecta a nada. Vale para cualquier módulo. */
  body.pdf-exportando #view{ display:block; }
  body.pdf-exportando .cr-scroll-y, body.pdf-exportando .cr-scroll-y-lg,
  body.pdf-exportando .cr-scroll-y-xl{ max-height:none; overflow:visible; }
  body.pdf-exportando .cr-scroll-x{ overflow:visible; }
  body.pdf-exportando .col12, body.pdf-exportando .col8, body.pdf-exportando .col7,
  body.pdf-exportando .col6, body.pdf-exportando .col5,
  body.pdf-exportando .col4{ break-inside:avoid; margin-bottom:14px; }
  /* EL MANUAL, ABIERTO AL EXPORTAR. Los módulos van plegados en pantalla —son
     dieciséis y desplegados no se navegan—, pero el botón promete "la guía
     completa" y el PDF salía con dieciséis títulos y ningún contenido. En papel
     no hay nada que plegar: lo que no se ve, no existe. */
  body.pdf-exportando .gm-mod .gm-c{ display:block; }
  body.pdf-exportando .gm-chev{ display:none; }
  body.pdf-exportando .gm-mod{ break-inside:avoid; }
  /* "Ir al módulo" no sirve en un papel */
  body.pdf-exportando .gm-ir{ display:none; }

  /* ---------- Guía: embudo vivo ----------
     Las 5 etapas del diagrama pasan a llevar datos reales y a ser accionables.
     El realce es discreto: la etapa acusa recibo del puntero sin que el color
     del bloque cambie de peso frente a las demás. */
  .g-chain .fst.viva{cursor:pointer; transition:transform .12s ease, box-shadow .12s ease;}
  .g-chain .fst.viva:hover, .g-chain .fst.viva:focus-visible{transform:translateY(-2px); box-shadow:0 4px 14px rgba(0,0,0,.10);}
  .g-chain .fst.viva:focus-visible{outline:2px solid var(--navy); outline-offset:2px;}
  .g-chain .fst .fnum{display:block; font-size:21px; font-weight:700; line-height:1.15; margin:6px 0 2px;}
  .g-chain .fst .fnum .u{font-size:11px; font-weight:600; opacity:.6; margin-left:3px;}
  .g-chain .fst .fnum.cero{opacity:.38; font-weight:600;}
  /* el cursor y el realce sobran cuando no hay nada que abrir */
  .g-chain .fst.viva.vacia{cursor:default;}
  .g-chain .fst.viva.vacia:hover{transform:none; box-shadow:none;}

  /* Tooltip compartido de gráficos (mismo componente que usa Correspondencia). */
  .g-tip{position:fixed; z-index:9000; pointer-events:none; opacity:0; visibility:hidden;
    transition:opacity .12s ease; background:var(--ink, #16202E); color:#fff;
    border-radius:7px; padding:8px 11px; max-width:280px; box-shadow:0 6px 22px rgba(0,0,0,.22);
    font-size:12px; line-height:1.45; display:flex; flex-direction:column; gap:1px;}
  .g-tip.on{opacity:1; visibility:visible;}
  .g-tip b{font-size:15px; font-weight:700;}
  .g-tip span{opacity:.88;}
  .g-tip u{text-decoration:none; opacity:.55; font-size:10.5px;
    letter-spacing:.01em; margin-top:3px;}
  body.pdf-exportando .g-tip{display:none;}
  /* ---- capitalización normal en Contrapartes e inversionistas ----
     Los rótulos del sistema van en mayúsculas sostenidas por diseño, pero en
     este módulo se piden con solo la inicial en mayúscula. Se acota con la
     marca data-mod="inv" que ponen invRenderShell() y las dos fichas, y que
     router.js limpia en cada navegación: el resto de los módulos no cambia. */
  #view[data-mod="inv"] .a-sec .t,   #view[data-mod="ente"] .a-sec .t,
  #view[data-mod="inv"] .kvp .k,     #view[data-mod="ente"] .kvp .k,
  #view[data-mod="inv"] .tl-f,       #view[data-mod="ente"] .tl-f,
  #view[data-mod="inv"] .field label,#view[data-mod="ente"] .field label{text-transform:none; letter-spacing:.01em;}
  #view[data-mod="inv"] .a-sec .t,
  #view[data-mod="ente"] .a-sec .t{font-size:13.5px; color:#3F4854;}
  /* los modales cuelgan de <body>, fuera de #view: se alcanzan mirando si el
     módulo es el que está pintado */
  body:has(#view[data-mod="inv"]) #modal .field label{text-transform:none; letter-spacing:.01em;}
  /* LOS DESPLEGABLES DE LA FICHA DEL PROYECTO, EN EL MISMO GRIS QUE LO DEMÁS.
     Iban en azul porque nacieron como el campo de «estado» de Correspondencia y
     de Alianzas, donde el azul dice que ese dato manda. Aquí no mandan: el tier,
     el paso y el sector son tres campos más de la ficha, y en azul al lado de
     los campos grises parecían de otra especie. En el gris del resto se leen
     como lo que son —campos que se pueden cambiar—, y el módulo entero queda en
     una sola paleta. El azul se queda donde significa algo: en los estados.
     Y más finos: 5px arriba y abajo en vez de 7, y el peso normal. Con el borde
     grueso y la negrita, tres desplegables seguidos pesaban más que la ficha que
     encabezan. */
  /* LO QUE FALTA POR PONER, EN UN GRIS QUE SE LEA. «Sin registrar» iba en el
     gris más claro de Atlas, el de lo deshabilitado, y en una ficha donde todo
     se edita eso dice justo lo contrario de lo que es: no son campos apagados,
     son los huecos que hay que llenar. Un punto más oscuro basta para que se
     lean sin llegar a pesar como un dato escrito —lo que los distingue de uno
     de verdad es lo que dicen, no lo pálidos que estén—, y de paso dejan de
     desentonar con el fondo del recuadro que los rodea. */
  #view[data-mod="inv"] .ct-val .mute,
  #view[data-mod="inv"] .fk-v .mute{color:var(--gray);}
  #view[data-mod="inv"] .ct-estado-campo select{font-size:12.5px; padding:5px 10px;
    font-weight:500; color:var(--ink); background:var(--block); border-color:var(--line);}
  #view[data-mod="inv"] .ct-estado-campo select:hover{background:#E9EEF6; border-color:#D7DDE7;}
  .inv-kan{display:flex;gap:14px;overflow-x:auto;padding-bottom:6px;}
  .inv-kan .kcol{flex:0 0 210px;}
  .inv-kan .kbody{max-height:440px;overflow-y:auto;padding-right:8px;}
  /* --- arrastrar tarjetas entre pasos --- */
  .inv-kan .kcard{cursor:grab;}
  .inv-kan .kcard:active{cursor:grabbing;}
  /* la tarjeta que viaja se atenúa, para no confundirla con la que se queda */
  .inv-kan .kcard.arrastrando{opacity:.4;}
  /* la columna que va a recibir se marca entera: el destino es la columna, no
     una posición dentro de ella — aquí no hay orden que respetar */
  .inv-kan .kcol.recibe{outline:2px dashed var(--navy2); outline-offset:3px; border-radius:10px; background:rgba(0,96,176,.045);}
  .inv-kan .kmas{font-size:11px; color:var(--gray-soft); text-align:center; padding:8px 0 2px;}
  .inv-scroll{}
  /* Caja de tarjetas con desplazamiento propio. Los listados de Inversionistas
     y de Entes YA NO la usan: se pidió que la primera vista del módulo corra
     con la página, sin scroll interno. La conserva Debida diligencia, que la
     necesita para sus 221 expedientes (ver js/views/diligencia.js).
     padding-right: deja sitio a la barra de desplazamiento para que no se
     monte sobre las tarjetas; padding en los otros lados, para que el borde
     resaltado del hover no se recorte contra la caja. */
  .inv-cards{padding:2px 12px 4px 2px;}
  /* padding-right: la barra de scroll se montaba sobre las cifras de la
     derecha (.rv) y las volvía ilegibles */
  .inv-graf{max-height:300px;overflow-y:auto;padding-right:14px;}
  .inv-graf.mini{max-height:120px;}      /* los dos apilados suman el alto del principal */
  .inv-graf.corta{max-height:192px;}     /* asoma ~3 filas; el resto se baja */
  /* la ficha del paso puede tener diez campos: se desplaza sola para que
     Documentos y Tareas queden siempre a la vista, sin bajar la página */
  /* La ficha del paso completa, sin jaula de 250 px con su propio
     desplazamiento: los campos en rejilla de dos columnas caben a la vista,
     y los largos (textarea) toman el ancho entero. */
  /* Lo que se puede hacer con un paso —cerrarlo, salir al expediente, editar su
     ficha— en una barra a lo ancho y arriba del todo, con un filete que la
     separa de lo que se lee. Estuvo apilada en la esquina derecha y ahí le
     robaba un tercio del ancho al párrafo de qué pide.
     (Se probó como banda de píldoras, la de los grupos de Correspondencia, y
     se descartó: aquí no son grupos entre los que se elige uno, son tres
     acciones distintas, y envueltas en una sola caja gris se leían como si
     fueran lo mismo.) */
  /* LA CABECERA DEL PASO: el nombre a la izquierda y las acciones a la derecha,
     con el filete debajo cerrando las dos. El filete lo lleva la cabecera y no
     los botones, que es lo que deja al título dentro del encabezado en vez de
     caer al cuerpo con el párrafo.
     Envuelve y no estira: si el nombre del paso es largo, los botones no caben
     al lado y bajan enteros a su renglón —siguen a la derecha, porque el filete
     y la esquina de la tarjeta les dan el borde contra el que alinearse—. */
  .inv-paso-cab{display:flex; align-items:center; gap:10px 16px; flex-wrap:wrap;
                padding-bottom:12px; margin-bottom:12px;
                border-bottom:1px solid var(--line-soft);}
  .inv-paso-cab .a-sec{flex:0 1 auto; min-width:0;}
  /* Las acciones, a la derecha: el ojo entra por la izquierda a leer de qué va
     el paso, y lo que se puede HACER con él se recoge al final del renglón, que
     es donde se busca un botón. A la izquierda competían con el título.
     safe flex-end y no flex-end a secas: si algún día no caben, `safe` las
     devuelve al principio en vez de empujar la primera fuera de la pantalla. */
  .inv-paso-acc{display:flex; align-items:center; gap:8px; flex-wrap:wrap;
                flex:1 1 auto;
                justify-content:flex-end; justify-content:safe flex-end;}
  /* El párrafo de qué pide el inversionista, más cerca del filete: con el título
     ya fuera del cuerpo, el hueco que le separaba de él sobra y lo único que
     hacía era descolgar el texto del encabezado que lo anuncia. Lo que ahora
     lo diferencia del título es la línea, no el aire. */
  .inv-paso-cab + .fk-intro{margin-top:2px;}
  /* ---- lo editable se ve editable ----
     El mismo gesto que ya tiene la ficha de un activo (.act-ed), traído a las
     fichas de Inversionistas: un fondo gris muy leve —el .block del resto de
     los campos de Atlas— dice "aquí se escribe" sin llenar la columna de
     bordes. Al pasar por encima se afirma y el cursor de texto lo remata.
     Va SOLO sobre lo que se edita. Los desplegables (tier, paso, sector) ya se
     anuncian solos con su azul y se quedan como están, y lo que es de lectura
     —los sectores, el monto sumado, el número de proyectos— se queda limpio:
     si todo llevara el mismo gris, el gris dejaría de significar algo. */
  .inv-ed{background:var(--block); border:1px solid transparent; border-radius:7px;
          padding:3px 8px; margin:0 -8px; cursor:text;
          transition:background .12s, border-color .12s;}
  .inv-ed:hover{background:#E9EEF6; border-color:var(--line);}
  .inv-ed:focus-visible{outline:2px solid var(--navy2); outline-offset:1px;}
  /* En la ficha de un paso el rótulo va a la izquierda y el valor a la derecha,
     en una celda ancha: ahí el fondo se ciñe al texto en vez de estirarse por
     toda la celda, que dejaría una columna de gris de arriba abajo. En el
     carril, en cambio, la columna es estrecha y el fondo la ocupa entera.
     El margen negativo cancela justo el relleno (8) y el borde (1): el texto se
     queda donde estaba, así que las filas con fondo y las que no lo llevan —el
     activo, que se elige en la ventana— siguen alineadas en la misma columna, y
     ninguna fila crece de alto. El fondo se mete en el hueco de 16px que hay
     hasta el rótulo, donde no estorba a nada. */
  .fk-v .inv-ed{display:inline-block; max-width:100%; margin:-4px -9px;
                min-width:min(330px, 100%);}
  /* El nombre del proyecto es texto grande: con el fondo pegado se lee como una
     etiqueta, así que respira más y espera a que se le acerque el ratón. */
  .a-h2 .inv-ed{background:transparent; padding:4px 10px; margin:0 -10px;}
  .a-h2 .inv-ed:hover{background:var(--block); border-color:var(--line);}
  @media (prefers-reduced-motion:reduce){ .inv-ed{transition:none;} }

  /* ---------- la ficha de un paso ----------
     Era .inv-ficha .kvp: una rejilla de dos columnas con el rótulo encima de
     cada dato. Once campos así median 626 px en la carta —medido a 900 px de
     ancho, que es lo que mide la columna— y empujaban Documentos y Tareas
     fuera de la pantalla; cinco de esos campos estaban vacíos y ocupaban lo
     mismo que los llenos.

     Ahora la ficha tiene tres piezas: una línea de contexto con lo corto,
     filas de rótulo a la izquierda para lo que necesita espacio, y una línea
     al pie con las observaciones y lo que falta por registrar. Lo vacío no se
     pinta. La misma ficha mide 508 px con dos recaudos pendientes de más.

     Arriba, el párrafo de qué pide el inversionista: es lo primero que se
     pregunta quien abre el paso. Va recortado —entero repite el título— y en
     tinta plena, porque es texto para leer, no un dato para consultar.
     (Aquí vivió una «línea de contexto» que ponía fecha y modalidad seguidas,
     en un formato distinto al de las filas. Dos formatos en la misma ficha se
     leían como dos secciones sin serlo: ahora todo va en filas.) */
  .fk-intro{font-size:13.5px; color:var(--ink); line-height:1.6; margin-top:11px;}
  /* Las filas. El rótulo a la izquierda y no encima: encima gasta un renglón
     entero por dato, y con ocho datos son ocho renglones de puro rótulo. */
  /* 8px y no 11: con los enlaces «Editar» fuera de cada fila, lo que quedaba
     entre un dato y el siguiente era hueco por el hueco, y la ficha entera se
     leía más larga de lo que tiene. El filete ya separa; el aire de más solo
     obligaba a bajar la vista. */
  .fk-fila{display:grid; grid-template-columns:112px minmax(0,1fr); gap:16px;
           padding:8px 0; border-bottom:1px solid var(--line-soft);}
  .fk .fk-fila:last-child{border-bottom:none;}
  .fk-k{font-size:11px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
        color:var(--gray-soft); padding-top:2px;}
  .fk-k-n{font-size:10.5px; font-weight:600; letter-spacing:0; text-transform:none;
          color:var(--rust); margin-top:3px;}
  .fk-v{font-size:13.5px; color:var(--ink); line-height:1.5; min-width:0; overflow-wrap:anywhere;}
  .fk-v a{color:var(--navy2); font-weight:600; cursor:pointer;}
  /* Lo que acompaña a un dato sin ser otro dato: el contacto bajo el firmante. */
  .fk-sub{font-size:12.5px; color:#39414F; margin-top:3px; line-height:1.45;}
  .fk-pie{margin-top:12px; font-size:12px; color:var(--gray-soft); line-height:1.6;}
  .fk-pie b{color:var(--gray); font-weight:600;}
  @media (max-width:640px){
    .fk-fila{grid-template-columns:1fr; gap:4px;}
  }

  /* ---------- los recaudos, como lista de comprobación ----------
     Lo que llegó y lo que falta. El pendiente se dibuja con el círculo vacío y
     de trazo discontinuo: se distingue del recibido a un metro de la pantalla,
     que es como se mira una lista de estas. */
  .fk-rec{display:flex; align-items:center; gap:9px; font-size:13px; padding:3px 0;}
  .fk-rec .mrk{width:15px; height:15px; border-radius:50%; flex:0 0 auto; cursor:pointer;
               display:flex; align-items:center; justify-content:center;
               font-size:9px; font-weight:800; color:#fff; background:var(--good);}
  .fk-rec.falta .mrk{background:transparent; border:1.5px dashed #C4CEDD; color:transparent;}
  .fk-rec.falta{color:var(--gray);}
  .fk-rec-q{min-width:0; overflow-wrap:anywhere;}
  /* Las acciones de un recaudo aparecen al pasar por encima; en pantalla táctil
     no hay «pasar por encima», así que ahí se quedan puestas. */
  .fk-rec-acc{display:inline-flex; gap:10px; margin-left:auto; padding-left:10px;
              opacity:0; transition:opacity .12s;}
  .fk-rec:hover .fk-rec-acc, .fk-rec-acc:focus-within{opacity:1;}
  @media (hover:none){ .fk-rec-acc{opacity:1;} }
  .fk-rec-vacio{font-size:12.5px; color:var(--gray-soft);}
  .fk-add{display:inline-block; margin-top:8px;}
  .fk-rec-alta{display:flex; gap:8px; align-items:center; flex-wrap:wrap; margin-top:9px;}
  .fk-rec-alta input{flex:1 1 220px; min-width:0; border:1px solid var(--line); border-radius:8px;
    padding:8px 10px; font-family:inherit; font-size:12.5px; color:var(--ink); background:var(--bg);}
  .fk-rec-alta input:focus{outline:none; border-color:var(--navy2);}
  /* barra activa del filtro cruzado: ámbar, para distinguir de un vistazo cuál
     dimensión se está filtrando */
  .in-rrow.inv-on{background:var(--amber-bg); border-radius:8px;}
  .in-rrow.inv-on .rfill{background:var(--amber);}
  .in-rrow.inv-on .rl, .in-rrow.inv-on .rv{color:var(--amber);}
  .stat.inv-on{border-color:var(--amber); background:var(--amber-bg);}
  .stat.inv-on .sn{color:var(--amber);}
  /* los nombres de los entes son largos: a lo ancho caben con holgura */
  .inv-entes .in-rrow .rl{width:300px;}
  @media (max-width:900px){ .inv-entes .in-rrow .rl{width:150px;} }
  .inv-col{display:flex;flex-direction:column;gap:14px;}
  .inv-list-row{display:flex;align-items:center;gap:12px;padding:12px 4px;border-top:1px solid var(--line-soft);cursor:pointer;}
  .inv-list-row:first-child{border-top:0;} .inv-list-row:hover{background:#fbfdff;}
  /* Vista Lista de inversionistas: cuadrícula compartida por cabecera y filas.
     El hueco entre columnas sube de 12 a 20: sin los puntos ni las pastillas,
     lo único que separa una columna de la siguiente es el aire, y con 12px dos
     textos largos —«Estados Unidos» y «Salud / Farmacéutico»— llegaban a
     tocarse y se leían como una sola frase. Es la división de la tabla, así que
     no hacen falta rayas verticales: nueve filetes de arriba abajo pesarían más
     que los datos. */
  .inv-tabla-cab,.inv-tabla-fila{display:grid;grid-template-columns:minmax(180px,2fr) 1.4fr 1fr 1.5fr .7fr 1.3fr 1.2fr 1.1fr .95fr;gap:20px;align-items:center;}
  /* POR QUÉ SE DESCUADRABAN LAS COLUMNAS. La cabecera y cada fila son rejillas
     SEPARADAS: comparten la lista de columnas, pero cada una reparte el ancho
     con su propio contenido. Y una columna en «fr» no mide solo su proporción
     —su mínimo es «auto»—, así que se ensancha si lo que lleva dentro no cabe.
     La cabecera va en mayúsculas y con letra espaciada: «MONTO DECLARADO» o
     «RESPONSABLES» ocupan más que el dato que encabezan, empujaban su columna y,
     de ahí en adelante, todas las siguientes quedaban corridas respecto a las
     filas. Por eso el desajuste no se veía en Empresa y sí crecía hacia la
     derecha, en País, Sector y Etapa.
     min-width:0 le quita ese mínimo automático: las dos rejillas reparten el
     ancho por la pura proporción y salen idénticas. Lo que ya no cabe se
     recorta en las filas y se parte en dos renglones en la cabecera, en vez de
     robarle sitio a la columna de al lado. */
  .inv-tabla-cab>span,.inv-tabla-fila>span{min-width:0;}
  .inv-tabla-cab>span,.inv-tabla-cab .ord{white-space:normal;line-height:1.25;}
  /* Personas: nombre, cargo, empresa, contacto y el atajo de editar. */
  .inv-per-cab,.inv-per-fila{display:grid;grid-template-columns:minmax(180px,1.6fr) 1.2fr 1.6fr 1.4fr 52px;gap:12px;align-items:center;}
  /* cabeceras que ordenan: la flecha hueca en reposo, rellena en la activa */
  .inv-tabla-cab .ord{cursor:pointer;user-select:none;white-space:nowrap;}
  .inv-tabla-cab .ord i{font-style:normal;opacity:.45;font-size:10px;}
  .inv-tabla-cab .ord:hover{color:var(--ink);} .inv-tabla-cab .ord:hover i{opacity:.8;}
  .inv-tabla-cab .ord.on{color:var(--ink);} .inv-tabla-cab .ord.on i{opacity:1;}
  /* pie de la lista que se alarga sola: cuántos van, y el botón por si acaso */
  .inv-mas{display:flex;align-items:center;justify-content:center;gap:14px;padding:16px 4px 6px;font-size:12px;color:var(--gray);border-top:1px solid var(--line-soft);}
  .inv-mas.fin{padding:12px 4px 2px;}

  /* ---------- Panel de Inversionistas: embudo + mapa + empresas ---------- */
  .inv-pan-cab{display:flex;flex-direction:column;gap:10px;}
  .inv-pan-cab .seg{align-self:flex-start;}
  .inv-pan-banda{margin:0;display:flex;align-items:center;gap:12px;flex-wrap:wrap;}
  .inv-pan-banda b{color:var(--ink);} .inv-pan-banda .sub{margin:0 0 0 auto;}
  .inv-pan-ejes{margin-left:4px;}
  /* los doce pasos */
  .inv-emb{display:grid;grid-template-columns:repeat(12,1fr);gap:6px;align-items:end;margin-top:6px;}
  .inv-emb .col{display:flex;flex-direction:column;align-items:center;gap:5px;cursor:pointer;padding:4px 2px;border-radius:6px;}
  .inv-emb .col:hover{background:var(--block);}
  .inv-emb .col.off{opacity:.32;} .inv-emb .col.on{background:var(--block);box-shadow:inset 0 0 0 2px var(--cyan-deep);}
  .inv-emb .bar{width:100%;background:var(--navy);border-radius:4px 4px 0 0;min-height:3px;}
  .inv-emb .bar.soft{background:#BFD3EC;}
  .inv-emb .cnt{font-size:15px;font-weight:800;letter-spacing:-.01em;}
  .inv-emb .usd{font-size:9.5px;color:var(--gray-soft);white-space:nowrap;}
  .inv-emb .lbl{font-size:10px;font-weight:700;color:var(--gray);text-align:center;line-height:1.2;height:24px;}
  .inv-emb .age{font-size:9px;}
  .inv-emb-base{height:1px;background:var(--line);margin:0 0 8px;}
  .inv-fases{display:grid;grid-template-columns:3fr 4fr 2fr 3fr;gap:6px;margin-top:4px;}
  .inv-fases div{font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--gray-soft);border-top:2px solid var(--line);padding-top:5px;text-align:center;cursor:pointer;border-radius:4px;}
  .inv-fases div:hover{color:var(--ink);} .inv-fases div.on{color:var(--navy);border-top-color:var(--navy);} .inv-fases div.off{opacity:.4;}
  /* el mapa */
  .inv-mapa-wrap{overflow-x:auto;}
  .inv-mapa{width:100%;border-collapse:separate;border-spacing:2px;font-size:12.5px;}
  .inv-mapa th{font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--gray-soft);padding:4px 8px;text-align:right;white-space:nowrap;cursor:pointer;}
  .inv-mapa th:first-child{text-align:left;cursor:default;} .inv-mapa th.on{color:var(--navy);} .inv-mapa th:not(:first-child):hover{color:var(--ink);}
  .inv-mapa td{padding:7px 8px;text-align:right;font-variant-numeric:tabular-nums;border-radius:5px;cursor:pointer;}
  .inv-mapa td:first-child{text-align:left;font-weight:600;white-space:nowrap;max-width:320px;overflow:hidden;text-overflow:ellipsis;}
  .inv-mapa td:first-child:hover{color:var(--navy2);}
  .inv-mapa td.tot{font-weight:800;background:transparent;cursor:default;}
  .inv-mapa td.usd{color:var(--gray);font-size:11.5px;background:transparent;cursor:default;white-space:nowrap;}
  .inv-mapa td.c0,.inv-escala i.c0{background:#F6F8FB;color:var(--gray-soft);} .inv-mapa td.c1,.inv-escala i.c1{background:#E3ECF8;} .inv-mapa td.c2,.inv-escala i.c2{background:#C4D6EF;}
  .inv-mapa td.c3,.inv-escala i.c3{background:#8FB0DF;color:#fff;} .inv-mapa td.c4,.inv-escala i.c4{background:#4A7FC4;color:#fff;} .inv-mapa td.c5,.inv-escala i.c5{background:var(--navy);color:#fff;}
  .inv-mapa td.sel{outline:2px solid var(--cyan-deep);outline-offset:-2px;}
  .inv-mapa td.dim{opacity:.35;} .inv-mapa tr.off td{opacity:.35;}
  .inv-mapa tr.sel td:first-child{color:var(--navy);text-decoration:underline;text-decoration-color:var(--cyan-deep);}
  .inv-mapa tr.total td{border-top:1px solid var(--line);background:transparent;font-weight:800;cursor:default;}
  .inv-mapa tbody tr:hover td:not(:first-child):not(.tot):not(.usd){filter:brightness(.95);}
  .inv-escala{display:flex;align-items:center;gap:5px;font-size:10.5px;color:var(--gray-soft);}
  .inv-escala i{width:16px;height:10px;border-radius:2px;display:inline-block;} .inv-escala i.c0{border:1px solid var(--line);}
  /* empresas en la selección: misma fila que la lista, con otras columnas */
  .inv-pan-fila{display:grid;grid-template-columns:minmax(160px,1.9fr) .9fr 1.2fr 1.4fr .7fr 1fr 1.2fr .9fr;gap:10px;align-items:center;}
  .inv-pan-fila>span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
  .inv-pan-fila.inv-tabla-cab{padding:6px 4px 10px;} .inv-pan-fila.inv-tabla-cab>span{white-space:normal;line-height:1.25;overflow:visible;}
  @media (max-width:900px){
    .inv-emb{grid-template-columns:repeat(6,1fr);} .inv-fases{display:none;}
    .inv-pan-fila{grid-template-columns:minmax(160px,2fr) 1fr 1fr 1fr;} .inv-pan-fila>span:nth-child(n+5){display:none;}
  }
  .inv-tabla-cab{padding:6px 4px 10px;font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--gray);border-bottom:1px solid var(--line-soft);}
  /* Todo alineado a la izquierda, cifras incluidas. Proyectos y Monto iban a la
     derecha —la convención de una tabla de cálculo, donde las cifras se comparan
     unidades contra unidades—, pero aquí no se suman ni se comparan: son un dato
     más de cada inversionista. Y un «1» solo, pegado al borde derecho de su
     columna y lejísimos de su rótulo, se lee como si perteneciera a la columna
     siguiente. Se conservan las cifras tabulares, que es lo que mantiene los
     dígitos en su sitio de una fila a otra. */
  .inv-tabla-cab .num,.inv-tabla-fila .num{text-align:left;font-variant-numeric:tabular-nums;}
  /* En tinta todo lo que consta, y en gris solo lo que falta: el gris marca un
     hueco, y usarlo para un dato de verdad —la fecha de alta iba así— hace
     dudar de si ese dato está a medias. */
  .inv-tabla-fila{font-size:13px; color:var(--ink);}
  .inv-tabla-fila .mute{color:var(--gray-soft);}
  .inv-tabla-cab+.inv-tabla-fila{border-top:0;}
  @media (max-width:900px){ .inv-tabla-cab,.inv-tabla-fila{grid-template-columns:minmax(160px,2fr) 1fr 1fr 1fr;} .inv-tabla-cab span:nth-child(n+5),.inv-tabla-fila>span:nth-child(n+5){display:none;} }
  /* ---------- la ficha flotante de la lista de inversionistas ----------
     Una sola tarjeta, colgada de <body> y fija a la ventana, que se rellena
     al señalar el nombre de una empresa (invTipMostrar). Misma piel que
     .usermenu y el aviso de #proystats: blanco, filete, sombra, esquinas de
     tarjeta. Fija y no absoluta porque la tabla recorta lo que sobresale. */
  .inv-tip{position:fixed; z-index:60; width:340px; max-width:calc(100vw - 16px);
    background:var(--bg); border:1px solid var(--line); border-radius:var(--r);
    box-shadow:0 8px 30px rgba(14,20,36,.16); padding:14px 16px 10px;
    font-size:12px; line-height:1.45; color:var(--ink); pointer-events:auto;}
  .inv-tip-h{display:flex; align-items:center; gap:12px; margin-bottom:8px;}
  .inv-tip-h .cp-logo{flex:0 0 auto; border:1px solid var(--line-soft);}
  .inv-tip-n{font-size:13.5px; font-weight:800; letter-spacing:-.01em; line-height:1.25;}
  .inv-tip-s{font-size:11px; color:var(--gray); margin-top:2px;}
  /* la descripción, recortada a tres líneas: es para reconocer, no para leer */
  .inv-tip-d{color:var(--gray); font-size:11.5px; margin-bottom:8px;
    display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical; overflow:hidden;}
  .inv-tip-r{display:flex; gap:10px; padding:6px 0; border-top:1px solid var(--line-soft);}
  .inv-tip-r .l{flex:0 0 104px; font-size:10.5px; font-weight:700; letter-spacing:.04em;
    text-transform:uppercase; color:var(--gray-soft); padding-top:1px;}
  .inv-tip-r .v{flex:1 1 auto; min-width:0; overflow-wrap:anywhere;}
  .inv-tip-r.col{flex-direction:column; gap:4px;}
  .inv-tip-r.col .l{flex:none;}
  .inv-tip .mute{color:var(--gray-soft);}
  .inv-tip-p{padding:2px 0;}
  .inv-tip-p .n{font-weight:700;}
  .inv-tip-p .m{display:flex; align-items:center; gap:6px; font-size:11px; color:var(--gray); flex-wrap:wrap;}
  .inv-tip-p .m .sep{color:var(--gray-soft);}
  .inv-tip-p.mas{font-size:11px; color:var(--gray-soft);}
  .inv-tip-f{display:flex; gap:6px; flex-wrap:wrap; padding:8px 0 2px; border-top:1px solid var(--line-soft);}
  .inv-tip-pie{margin-top:6px; padding-top:6px; border-top:1px solid var(--line-soft);
    font-size:10.5px; color:var(--gray-soft);}
  /* el nombre dice que hay algo que señalar: subrayado punteado suave al pasar */
  .inv-tabla-fila [data-tip-emp]{cursor:pointer;}
  .inv-tabla-fila:hover [data-tip-emp]{text-decoration:underline dotted var(--gray-soft); text-underline-offset:3px;}
  @media (max-width:900px){ .inv-per-cab,.inv-per-fila{grid-template-columns:minmax(160px,2fr) 1fr 52px;} .inv-per-cab span:nth-child(3),.inv-per-cab span:nth-child(4),.inv-per-fila>span:nth-child(3),.inv-per-fila>span:nth-child(4){display:none;} }
  .inv-frow-sel{background:#E8F6FE;border-radius:8px;}

  /* ---------- Reuniones · dashboard sobre las pestañas (barras · mapa ·
     culminación) ---------- */
  /* una sola fila en escritorio (nunca envuelve: con flex-wrap, 20+60+20=100%
     más el gap entre paneles se pasaba por poco del ancho disponible y
     mandaba "Culminación" a una segunda fila) — en angosto pasa a columna. */
  .reu-dash{display:flex; gap:14px; margin-bottom:16px;}
  /* proporción pedida: 20% / 60% / 20% del ancho de la franja */
  .reu-dash-panel{flex:1 1 0; min-width:0; box-sizing:border-box; background:var(--bg); border:1px solid var(--line); border-radius:var(--r); padding:10px 12px;}
  .reu-dash-mapa{flex:3 1 0;}
  .rd-t{font-size:10.5px; font-weight:700; color:var(--gray); letter-spacing:.01em; margin-bottom:8px;}
  /* barras: cada fila es su propio "legend" (nombre + color), sin caja aparte */
  .rdb{height:4cm; display:flex; flex-direction:column; justify-content:space-around;}
  .rdb-row{display:flex; align-items:center; gap:8px; outline:none;}
  .rdb-row:focus-visible .rdb-track{box-shadow:0 0 0 2px var(--navy2);}
  .rdb-lbl{width:76px; flex:0 0 auto; font-size:10.5px; color:var(--gray); line-height:1.25;}
  .rdb-track{flex:1 1 auto; height:10px; background:var(--block); border-radius:6px; overflow:hidden;}
  .rdb-fill{height:100%; border-radius:0 6px 6px 0; transition:width .2s;}
  .rdb-fill.warn{background:var(--amber);}
  .rdb-fill.good{background:var(--good);}
  .rdb-fill.rust{background:var(--rust);}
  .rdb-val{width:20px; flex:0 0 auto; text-align:right; font-size:11.5px; font-weight:700; color:var(--ink);}
  /* mapa: proyección equirectangular simple, recortada en óvalo (al estilo
     de un globo en Robinson) sobre una grilla de apoyo — no hay librería de
     mapas ni contorno de costas real, así que cada país es un punto ubicado
     por coordenada aproximada, no una forma geográfica trazada. */
  .rdm-wrap{position:relative; width:100%; height:4cm;}
  .rdm-svg{width:100%; height:100%; display:block;}
  .rdm-grid{stroke:#437099; stroke-width:.35; opacity:.35;}
  .rdm-eq{stroke:#437099; stroke-width:.5; opacity:.5;}
  .rdm-land{fill:url(#rdmTierra); stroke:#B99A55; stroke-width:.5;}  /* tierra con degradado sutil (tono "mapa de pared"), borde para que cada masa se distinga */
  .rdm-ocean{fill:#EAF3FC; font-size:2.6px; font-weight:700; letter-spacing:.02em; opacity:.85; pointer-events:none;}
  .rdm-borde{fill:none; stroke:var(--line); stroke-width:1.5;}
  .rdm-dot{fill:var(--rust); stroke:#fff; stroke-width:.5; cursor:pointer; outline:none; transform-box:fill-box; transform-origin:center; transition:transform .15s, fill .15s;}
  .rdm-dot:hover, .rdm-dot:focus-visible{fill:var(--navy); transform:scale(1.5);}
  .rdm-dot:focus-visible{stroke:#fff; stroke-width:.8;}
  .reu-dash-tip{position:absolute; z-index:5; pointer-events:none; background:var(--ink); color:#fff; font-size:10.5px; font-weight:600; padding:4px 8px; border-radius:6px; white-space:nowrap; box-shadow:var(--shadow);}
  .rdm-empty{position:absolute; inset:0; display:flex; align-items:center; justify-content:center; text-align:center; padding:0 14px; font-size:10.5px; color:var(--gray-soft); background:rgba(244,247,251,.85);}
  /* culminación: meter — la pista es un paso más claro de la misma rampa que el relleno */
  .reu-dash-meter{display:flex; flex-direction:column; align-items:center; justify-content:center; height:calc(4cm + 26px); text-align:center;}
  .rdmt-pct{font-size:30px; font-weight:700; color:var(--good); line-height:1;}
  .rdmt-pct span{font-size:16px; font-weight:600; margin-left:1px;}
  .rdmt-track{width:100%; height:10px; background:var(--good-bg); border-radius:6px; margin:12px 0 8px; overflow:hidden;}
  .rdmt-fill{height:100%; background:var(--good); border-radius:6px; transition:width .2s;}
  .rdmt-sub{font-size:10.5px; color:var(--gray-soft);}
  @media (max-width:900px){
    .reu-dash{flex-direction:column;}
  }
  /* ---------- Plantillas · copia propia y publicación ---------- */
  /* La barra va arriba del todo del editor porque "quién ve esto" hay que saberlo
     antes de escribir, no al pulsar un botón. */
  .plm-pub{display:flex; align-items:center; gap:11px; padding:10px 12px; margin-bottom:12px;
    border:1px solid var(--line); border-radius:var(--r-sm); background:var(--block);}
  .plm-pub-p{flex:0 0 auto; width:9px; height:9px; border-radius:50%; background:var(--gray-soft);}
  .plm-pub.mia .plm-pub-p{background:var(--amber); box-shadow:0 0 0 3px var(--amber-bg);}
  .plm-pub.pub .plm-pub-p{background:var(--good); box-shadow:0 0 0 3px var(--good-bg);}
  .plm-pub.choque .plm-pub-p{background:var(--rust); box-shadow:0 0 0 3px var(--rust-bg);}
  .plm-pub-t{font-size:12px; font-weight:700; line-height:1.25;}
  .plm-pub-s{font-size:10.5px; color:var(--gray); line-height:1.4; margin-top:1px;}
  .plm-pub-acc{margin-left:auto; display:flex; gap:6px; flex-wrap:wrap;}
  /* "Descartar mi copia" solo tiene sentido cuando hay una */
  .plm-pub:not(.mia):not(.choque) .plm-solo-mia{display:none;}

  /* Original / Mi copia. Original es de solo lectura: no es tuyo. */
  .plm-vistas{display:inline-flex; border:1px solid var(--line); border-radius:7px; overflow:hidden;}
  .plm-vista{border:0; background:var(--bg); color:var(--gray); cursor:pointer;
    font-family:inherit; font-size:10.5px; font-weight:700; padding:6px 11px;}
  .plm-vista + .plm-vista{border-left:1px solid var(--line);}
  .plm-vista:hover{background:var(--block);}
  .plm-vista.on{background:var(--navy); color:#fff;}
  .plm.plm-leer .plm-frags{opacity:.4; pointer-events:none;}
  .plm.plm-leer .plm-paneles iframe{box-shadow:inset 0 0 0 2px var(--gray-soft);}

  /* marca de copia propia en la lista */
  .plm-item-m{flex:0 0 auto; font-size:8px; font-weight:800; letter-spacing:.01em;
    color:var(--amber); background:var(--amber-bg); border-radius:4px; padding:1px 4px;}

  /* navegador de huecos: el análisis de brechas tiene 38 y se buscaban a ojo */
  .plm-huecos{display:inline-flex; align-items:center; gap:3px;}
  .plm-huecos .sub{min-width:56px; text-align:center;}

  /* ---------- Plantillas · panel de Formato ---------- */
  /* El panel entra como tercera columna: la hoja mide 816px fijos, así que se le
     quita ancho a la zona de trabajo y no al documento. */
  .plm.con-formato{grid-template-columns:210px minmax(0,1fr) 288px;}
  .plm-formato{border:1px solid var(--line); border-radius:var(--r-sm); background:var(--bg); overflow:hidden;}
  .plm-formato-h{display:flex; align-items:center; gap:8px; padding:9px 11px; border-bottom:1px solid var(--line);}
  .plm-formato-h .t{font-size:12px; font-weight:700; flex:1 1 auto;}
  .plm-formato-x{border:0; background:transparent; cursor:pointer; color:var(--gray); font-size:13px; line-height:1; padding:2px 4px;}
  /* Alto: con "100vh - 400" solo cabían dos tarjetas y había que desplazarse mucho
     para llegar a las de texto. El mínimo evita que en una pantalla baja se quede
     en una rendija. */
  .plm-formato-b{min-height:340px; padding:4px 11px 12px;}
  .plm-fmt-sec{font-size:9px; font-weight:800; letter-spacing:.01em; color:var(--gray);
    padding:12px 0 6px; border-bottom:1px solid var(--line-soft); margin-bottom:7px;}
  .plm-fmt-r{display:flex; align-items:center; gap:8px; padding:5px 0;}
  .plm-fmt-r label{flex:1 1 auto; font-size:11px;}
  .plm-fmt-r select, .plm-fmt-r input[type=file]{flex:0 0 124px; font-family:inherit; font-size:10.5px;
    border:1px solid var(--line); border-radius:6px; padding:4px 6px; background:var(--bg);}

  /* tarjeta de color: se nombra por dónde se ve y se enseña lo que va a cambiar */
  .plm-ct{border:1px solid var(--line); border-radius:9px; padding:8px 9px; margin-bottom:6px;}
  .plm-ct-h{display:flex; align-items:center; gap:9px;}
  .plm-ct-n{font-size:11.5px; font-weight:700; line-height:1.25;}
  .plm-ct-d{font-size:9.5px; color:var(--gray); line-height:1.3; margin-top:1px;}
  .plm-ct-m{flex:0 0 auto; width:36px; height:25px; border-radius:5px; border:1px solid var(--line);
    overflow:hidden; display:flex; align-items:center; justify-content:center; background:var(--bg);}
  .plm-ct-sw{display:flex; flex-wrap:wrap; gap:4px; margin-top:7px;}
  .plm-sw{width:22px; height:22px; border-radius:6px; border:1px solid rgba(14,20,36,.16);
    cursor:pointer; padding:0; position:relative;}
  .plm-sw:hover{transform:scale(1.12);}
  .plm-sw.sel::after{content:"✓"; position:absolute; inset:0; display:flex; align-items:center;
    justify-content:center; font-size:11px; font-weight:900; color:var(--plm-tick);}
  /* el cuadrito de pareja enseña la etiqueta tal cual quedará, no dos colores sueltos */
  .plm-sw-par{width:auto; min-width:42px; padding:0 6px; height:22px; border-radius:6px;
    border:1px solid rgba(14,20,36,.16); cursor:pointer; font-family:inherit;
    font-size:8px; font-weight:800; letter-spacing:.3px;}
  .plm-sw-par.sel{box-shadow:0 0 0 2px var(--ink);} .plm-sw-par.sel::after{display:none;}
  /* salida de emergencia: el selector completo del sistema */
  .plm-sw-mas{width:auto; padding:0 7px; height:22px; border-radius:6px; border:1px dashed var(--line);
    background:var(--bg); color:var(--gray); font-size:9.5px; font-family:inherit; cursor:pointer; position:relative;}
  .plm-sw-mas input{position:absolute; inset:0; opacity:0; cursor:pointer;}
  /* el aviso de legibilidad: el error que de verdad comete quien no sabe diseño */
  .plm-ct-ojo{display:none; margin-top:6px; font-size:10px; line-height:1.35; border-radius:6px; padding:5px 7px;}
  .plm-ct-ojo.mal{display:block; background:var(--rust-bg); color:var(--rust);}
  .plm-ct-ojo.flojo{display:block; background:var(--amber-bg); color:var(--amber);}

  @media (max-width:1200px){ .plm.con-formato{grid-template-columns:minmax(0,1fr);} }

  /* menú de bloques anclado al + del hueco */
  .plm-men{max-height:280px; overflow-y:auto; margin:0 -4px;}
  .plm-men-i{display:flex; align-items:center; gap:10px; padding:8px 10px; border-radius:8px; cursor:pointer;}
  .plm-men-i.on{background:#EAF4FD;}
  .plm-men-i svg{flex:0 0 auto;}
  .plm-men-i .n{font-size:12.5px; font-weight:600; line-height:1.2;}
  .plm-men-i .d{font-size:10.5px; color:var(--gray); line-height:1.35; margin-top:1px;}

  /* Menú de bloques: nace apartado a la derecha y NO se mueve mientras se usa. El
     fondo se queda transparente para ver la hoja y la previa que va apareciendo,
     pero sigue capturando: se está eligiendo, no editando. */
  #modal.plm-men-lado{align-items:flex-end; justify-content:flex-end; background:rgba(14,20,36,.10);}
  #modal.plm-men-lado .modalcard{width:312px; max-width:calc(100vw - 32px);
    margin:0 22px 22px 0; box-shadow:0 10px 34px rgba(14,20,36,.3);}
  #modal.plm-men-lado .plm-men{max-height:300px;}

  /* ===================== catálogo de plantillas: uso ==============
     El dato de uso vive en la tarjeta, no en un panel aparte: la decisión que se
     toma con él —cuál de las plantillas abro— se toma mirando el catálogo. */
  .plm-tira{display:flex; background:var(--bg); border:1px solid var(--line); border-radius:var(--r);
    box-shadow:var(--shadow); overflow:hidden; margin:0 0 12px;}
  .plm-tira .c{flex:1; padding:11px 15px; border-right:1px solid var(--line-soft); cursor:pointer;}
  .plm-tira .c:last-child{border-right:0;}
  .plm-tira .c:hover{background:var(--block);}
  .plm-tira .c.sinmedir{cursor:default;} .plm-tira .c.sinmedir:hover{background:transparent;}
  .plm-tira .r{display:flex; align-items:baseline; gap:5px;}
  .plm-tira .v{font-size:21px; font-weight:700; line-height:1.05; letter-spacing:-.02em;
    font-variant-numeric:tabular-nums;}
  .plm-tira .de{font-size:11px; color:var(--gray-soft);}
  .plm-tira .l{font-size:10.5px; color:var(--gray); margin-top:2px;}
  .plm-tira .mini{height:4px; border-radius:3px; background:var(--line-soft); overflow:hidden; margin-top:6px;}
  .plm-tira .mini i{display:block; height:100%; border-radius:3px; background:var(--navy2);}
  .plm-tira .usadas .v{color:var(--good);}    .plm-tira .usadas .mini i{background:var(--good);}
  .plm-tira .muertas .v{color:var(--rust);}   .plm-tira .muertas .mini i{background:var(--rust);}
  .plm-tira .huerfanas .v{color:var(--amber);}.plm-tira .huerfanas .mini i{background:var(--amber);}
  .plm-tira .sinmedir .v{color:var(--gray-soft);}
  .plm-tira .c.sel{background:#EAF4FD; box-shadow:inset 0 -2px 0 var(--navy2);}

  .plm-mandos{align-items:center;}
  .plm-chips{display:flex; gap:6px; align-items:center; flex-wrap:wrap;}
  .plm-chipf{font-size:10.5px; font-weight:600; padding:3px 9px; border-radius:20px; cursor:pointer;
    border:1px solid var(--line); background:var(--bg); color:var(--gray); font-family:inherit;}
  .plm-chipf:hover{border-color:var(--navy2); color:var(--navy2);}
  .plm-chipf.on{background:var(--navy2); border-color:var(--navy2); color:#fff;}
  .plm-orden{margin-left:auto; display:flex; align-items:center; gap:6px; font-size:11px; color:var(--gray);}
  .plm-orden select{font-family:inherit; font-size:11.5px; padding:4px 7px; border:1px solid var(--line);
    border-radius:var(--r-sm); background:var(--bg); color:var(--ink);}
  .plm-orden select:disabled{color:var(--gray-soft); background:var(--block);}
  .plm-plegar{background:none; border:0; font-family:inherit; font-size:11px; color:var(--navy2); cursor:pointer; padding:0;}

  /* con carril caben dos columnas de tarjetas; plegado vuelven las tres de siempre */
  .plm-conjunto{display:grid; grid-template-columns:1fr 292px; gap:12px; align-items:start;}
  .plm-conjunto.solo{grid-template-columns:1fr;}
  .plm-conjunto .libgrid{grid-template-columns:repeat(2,minmax(0,1fr));}
  .plm-conjunto.solo .libgrid{grid-template-columns:repeat(3,minmax(0,1fr));}
  @media (max-width:1150px){
    .plm-conjunto{grid-template-columns:1fr;}
    .plm-conjunto .libgrid{grid-template-columns:repeat(2,minmax(0,1fr));}
    /* Con .plm-conjunto en una sola columna el carril queda debajo de la grilla
       principal, no al lado — mismo caso que .a-rail.cp-sticky (arriba, ~línea
       1076): un sticky ahí se queda pegado a 14px del borde y flota sobre el
       resto de la página en vez de desplazarse con el scroll normal. */
    .plm-carril{position:static;}
  }

  .plm-uso{display:flex; align-items:center; gap:9px; margin-top:11px; padding-top:10px;
    border-top:1px solid var(--line-soft);}
  .plm-uso .n{font-size:17px; font-weight:700; line-height:1; font-variant-numeric:tabular-nums;}
  .plm-uso .t{font-size:10.5px; color:var(--gray); line-height:1.3;}
  .plm-spark{display:flex; align-items:flex-end; gap:2px; height:22px; margin-left:auto;}
  .plm-spark i{width:5px; background:#A8CDEA; border-radius:1.5px; min-height:2px; display:block;}
  .plm-spark i.ult{background:var(--navy2);}
  /* una plantilla sin uso no compite por la atención, pero se sigue pudiendo leer */
  .fcard.plm-apagada{background:#FBFCFD; border-style:dashed;}
  .fcard.plm-apagada .fc-name{color:var(--gray);}

  .plm-carril{display:flex; flex-direction:column; gap:12px; position:sticky; top:14px;}
  .plm-caja{background:var(--bg); border:1px solid var(--line); border-radius:var(--r); box-shadow:var(--shadow);}
  .plm-caja-h{display:flex; align-items:baseline; gap:8px; padding:10px 13px; border-bottom:1px solid var(--line-soft);}
  .plm-caja-h h3{font-size:12px; font-weight:700;}
  .plm-caja-h .s{font-size:10.5px; color:var(--gray);}
  .plm-caja-b{padding:11px 13px;}
  .plm-nota{font-size:10.5px; color:var(--gray); line-height:1.55;}
  .plm-nota b{color:var(--ink);}

  .plm-rk{cursor:pointer; padding:4px 6px; margin:0 -6px; border-radius:var(--r-sm);}
  .plm-rk:hover{background:var(--block);} .plm-rk:hover .n{color:var(--navy2);}
  .plm-rk .r1{display:flex; justify-content:space-between; align-items:baseline; gap:8px;}
  .plm-rk .n{font-size:11.5px; font-weight:600; line-height:1.25;}
  .plm-rk .v{font-size:11px; color:var(--gray); font-variant-numeric:tabular-nums; flex:0 0 auto;}
  .plm-bar{height:5px; border-radius:3px; background:var(--line-soft); overflow:hidden; margin-top:3px;}
  .plm-bar i{display:block; height:100%; background:var(--navy2); border-radius:3px;}

  .plm-meses{display:flex; align-items:flex-end; gap:5px; height:66px;}
  .plm-meses .m{flex:1; display:flex; flex-direction:column; justify-content:flex-end; align-items:center; gap:4px; height:100%;}
  .plm-meses .c{width:100%; background:var(--navy2); border-radius:3px 3px 0 0; min-height:2px;}
  .plm-meses .c.pal{background:#A8CDEA;}
  .plm-meses .e{font-size:9px; color:var(--gray-soft);}

  .plm-pers{display:flex; align-items:center; gap:8px; padding:4px 0; font-size:11.5px;}
  .plm-pers .ini{flex:0 0 auto; width:22px; height:22px; border-radius:50%; background:var(--block);
    color:var(--navy2); font-size:9.5px; font-weight:700; text-align:center; line-height:22px;}
  .plm-pers .nb{font-weight:600; overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}
  .plm-pers .v{margin-left:auto; font-variant-numeric:tabular-nums; color:var(--gray);}

  .plm-huerf{padding:7px 8px; margin:0 -8px; border-radius:var(--r-sm); cursor:pointer;}
  .plm-huerf:hover{background:var(--block);}
  .plm-huerf + .plm-huerf{border-top:1px solid var(--line-soft);}
  .plm-huerf .h1{display:flex; align-items:center; gap:6px;}
  .plm-huerf .hn{font-size:11px; font-weight:600; line-height:1.25;}
  .plm-huerf .h2{font-size:10px; color:var(--gray); line-height:1.45; margin-top:3px;}
  .plm-huerf .h2 b{color:var(--ink); font-weight:600;}
  /* ===================== VISTAS DEL PROCESO (rama rediseno-proyectos) =====================
     Tres alternativas al embudo de chevrons, con conmutador temporal para compararlas. */
  /* C — Pastillas numeradas que se acomodan en varias filas */
  .pvc{display:flex; flex-wrap:wrap; gap:7px;}
  .pvc-pill{display:inline-flex; align-items:center; gap:7px; padding:5px 12px 5px 6px; border-radius:999px;
    font-size:11.5px; font-weight:600; cursor:pointer; background:#fff; border:1px solid var(--line); color:var(--gray-soft);}
  .pvc-pill:hover{border-color:var(--gray-soft);}
  .pvc-pill .pvc-n{width:19px; height:19px; border-radius:50%; display:flex; align-items:center; justify-content:center;
    font-size:10px; font-weight:700; background:var(--line-soft); color:var(--gray-soft);}
  .pvc-pill.done{background:var(--navy); border-color:var(--navy); color:#fff;}
  .pvc-pill.done .pvc-n{background:rgba(255,255,255,.22); color:#fff;}
  /* EL PASO EN CURSO, COMO LOS HECHOS: azul oscuro y letras blancas. Iba en
     cian, y en una fila de doce pastillas el cian se leía como un cuarto estado
     —ni hecho, ni pendiente, ni descartado— cuando lo que dice es lo mismo que
     el azul: hasta aquí se ha llegado. Distinguirlo del hecho no le toca al
     fondo: el hecho lleva ✓ y el que está en curso lleva su número. */
  .pvc-pill.cur{background:var(--navy); border-color:var(--navy); color:#fff;}
  .pvc-pill.cur .pvc-n{background:rgba(255,255,255,.22); color:#fff;}
  .pvc-pill.off{background:var(--rust); border-color:var(--rust); color:#fff;}
  .pvc-pill.off .pvc-n{background:rgba(255,255,255,.25); color:#fff;}
  /* Cuál está DESPLEGADO es otra cosa que en qué paso se va: el recuadro iba en
     navy2 y sobre un fondo ya azul se perdía. En cian se ve en las cuatro
     variantes, y el cian queda haciendo un trabajo que sí es suyo: señalar
     dónde está puesta la vista, no en qué estado está el paso. */
  .pvc-pill.abierto{outline:2px solid var(--cyan); outline-offset:1px;}

  /* ===================== lista de proyectos del inversionista =====================
     Monto a la derecha en tabulares, etapa como pastilla, microbarra de avance;
     la fila elegida se marca con banda azul al borde izquierdo. */
  /* El tope de la columna izquierda. El alto no es decorativo: es lo que pone
     la primera tarjeta del carril a la altura de la primera de la derecha —la
     ficha con el nombre del proyecto, o la tarjeta de tareas pendientes—.
     En la columna de la derecha, entre el borde de arriba y la tarjeta del
     proyecto hay la barra de pestañas (38) + el hueco de la columna (20) + el
     margen del cuerpo (16) = 74; el rail ya separa sus bloques 24, así que a
     este le tocan los 50 restantes. El padding de arriba deja el enlace en la
     misma línea que los rótulos de las pestañas.
     En la ficha de un proyecto lleva dentro el enlace de volver; en la del
     inversionista va vacío, solo separando. Apilado en una columna (móvil) no
     hay nada que alinear y desaparece. */
  .rail-tope{display:flex; align-items:flex-start; height:50px; padding-top:9px;}
  /* Apilado en una columna no hay nada que alinear, pero el tope NO se oculta:
     lleva dentro el enlace de volver al listado de proyectos, y esconderlo
     dejaba la ficha de un proyecto sin camino de vuelta en el teléfono. Pierde
     el alto, que es lo único que sobra ahí. */
  @media (max-width:1000px){ .rail-tope{height:auto; padding-top:0;} }

  /* .iproy-cab, .iproy-estado, .iproy-acc y .iproy-ente vivían aquí: eran el
     encabezado del proyecto con el estado a la izquierda y los botones a la
     derecha. Todo eso pasó a la ficha del proyecto, en el rail (kvp + .rail-acc),
     y el encabezado quedó con el nombre y los doce pasos. */
  .iproy-row{display:flex; align-items:center; gap:16px; margin:0 -20px; padding:13px 20px; cursor:pointer;}
  .iproy-row + .iproy-row{border-top:1px solid var(--line-soft);}
  .iproy-row:hover{background:var(--block);}
  .iproy-row.sel{background:#EEF7FE; box-shadow:inset 3px 0 0 var(--navy2);}
  .iproy-main{min-width:0; flex:1 1 auto;}
  .iproy-n{font-size:12.5px; font-weight:700; line-height:1.35;}
  .iproy-meta{display:flex; align-items:center; gap:10px; margin-top:6px; flex-wrap:wrap;}
  .iproy-sec{font-size:11.5px; color:var(--gray);}
  .iproy-side{flex:0 0 auto; text-align:right;}
  .iproy-monto{font-size:13px; font-weight:700;}
  .iproy-mini{display:inline-flex; gap:3px; margin-top:7px;}
  .iproy-mini span{width:9px; height:4px; border-radius:2px; background:var(--line-soft);}
  .iproy-mini span.done{background:var(--navy);}
  .iproy-mini span.cur{background:var(--cyan);}
  .iproy-mini span.off{background:var(--rust);}
  @media (max-width:640px){ .iproy-side{display:none;} }

  /* ===================== conmutador de vistas (comparación temporal) ===================== */
  .pv-toggle{display:flex; align-items:center; gap:10px;}
  .pv-lbl{font-size:11px; font-weight:700; letter-spacing:.04em; text-transform:uppercase; color:var(--gray-soft);}
  .pv-tabs{display:flex; border:1px solid var(--line); border-radius:999px; overflow:hidden; background:var(--bg);}
  .pv-tab{padding:4px 12px; font-size:11.5px; font-weight:600; color:var(--gray); cursor:pointer; user-select:none; white-space:nowrap;}
  .pv-tab:not(:first-child){border-left:1px solid var(--line);}
  .pv-tab:hover{background:var(--block);}
  .pv-tab.on{background:var(--navy); color:#fff;}

  /* ===================== panorama compacto: tarjetas plegables (vista B) ===================== */
  .cr-folds{display:grid; grid-template-columns:1fr 1fr; gap:12px; align-items:start;}
  @media (max-width:900px){ .cr-folds{grid-template-columns:1fr;} }
  .cr-fold{background:var(--bg); border:1px solid var(--line); border-radius:var(--r); box-shadow:var(--shadow); overflow:hidden; min-width:0;}
  .cr-fold.wide{grid-column:1 / -1;}
  .cr-fold summary{list-style:none; display:flex; align-items:center; gap:10px; padding:14px 18px; cursor:pointer; user-select:none;}
  .cr-fold summary::-webkit-details-marker{display:none;}
  .cr-fold summary:hover{background:var(--block);}
  .cr-fold .cf-t{font-size:12.5px; font-weight:700; white-space:nowrap;}
  .cr-fold .cf-r{margin-left:auto; font-size:11.5px; color:var(--gray); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; min-width:0;}
  .cr-fold .cf-ch{flex:none; color:var(--gray-soft); font-size:11px; transition:transform .12s;}
  .cr-fold[open] .cf-ch{transform:rotate(180deg);}
  .cr-fold[open] summary{border-bottom:1px solid var(--line-soft);}
  .cr-fold .cf-b{padding:12px 18px 16px;}

  /* Instrucciones de Reuniones: pantalla de solo texto, justificado. Va
     acotado a esta pestaña y no a .g-intro, que la comparte con la Guía —
     ahí los párrafos alternan con diagramas y tablas anchas, y justificarlos
     abriría huecos entre palabras. */
  .reu-instr p{text-align:justify; text-wrap:pretty;}

  /* Lista larga dentro de un panel del Panorama (hoy, las empresas que
     proponen). Con 30 y subiendo, la ventana estiraba la página entera y
     empujaba abajo los paneles que van después. Asoma unas seis filas —lo
     suficiente para ver el reparto y comparar los primeros— y el resto se
     baja. Mismo criterio que .inv-graf en el panel de Inversionistas, con su
     propio nombre para no atar dos módulos por una regla de tamaño. */
  .cr-lista-scroll{max-height:320px; overflow-y:auto; padding-right:10px;}
  /* Con una empresa desplegada hace falta sitio para su detalle; sigue
     acotada para no estirar la página, pero deja leerlo sin agobio. */
  .cr-lista-scroll.abierta{max-height:620px;}
  /* El pie de "no dicen qué empresa" queda FUERA del scroll: es un total, y
     un total que hay que ir a buscar deslizando no se lee. */

  /* ---- aviso de cambios en segundo plano (js/sync.js) ----
     Abajo a la derecha y flotante: no empuja la página, así que aparecer no
     mueve nada de lo que se estaba leyendo. Entra deslizándose desde abajo —un
     elemento que aparece de golpe se lee como un fallo de pintado— y sale del
     flujo del teclado cuando está cerrada (visibility), para que Tab no caiga
     en un botón invisible. */
  .sync-aviso{position:fixed; right:22px; bottom:22px; z-index:60;
    display:flex; align-items:center; gap:10px;
    padding:10px 12px 10px 15px; border-radius:11px;
    background:var(--navy); color:#fff; box-shadow:0 8px 26px rgba(12,26,48,.28);
    font-size:12.5px; opacity:0; visibility:hidden; transform:translateY(10px);
    transition:opacity .16s ease, transform .16s ease, visibility .16s;}
  .sync-aviso.open{opacity:1; visibility:visible; transform:none;}
  .sync-aviso .sync-t{font-weight:600; white-space:nowrap;}
  .sync-aviso .sync-btn{border:none; border-radius:7px; cursor:pointer;
    background:var(--cyan); color:#06283b; font-family:inherit;
    font-size:11.5px; font-weight:800; letter-spacing:.02em; padding:6px 11px;}
  .sync-aviso .sync-btn:hover{filter:brightness(1.07);}
  .sync-aviso .sync-x{border:none; background:none; cursor:pointer;
    color:rgba(255,255,255,.55); font-size:12px; line-height:1; padding:4px;}
  .sync-aviso .sync-x:hover{color:#fff;}
  /* La de versión nueva (js/version-check.js) usa la misma pastilla pero a la
     izquierda: puede coincidir en pantalla con la de sync.js —datos nuevos Y
     versión nueva a la vez— y no deben taparse. */
  .sync-aviso.version{right:auto; left:22px;}
  @media (max-width:640px){
    .sync-aviso{right:12px; left:12px; bottom:12px; justify-content:space-between;}
    .sync-aviso.version{bottom:68px;}
  }

/* Clases dinámicas del buzón que la primera pasada no vio: el marcado las
   escribe como class="nt-tab ${...}

/* ---------- buzón de avisos ----------
   Bloque COMPLETO de ciip-app-rediseno, no una selección. La primera vez se
   trajeron solo las clases que "faltaban" y quedaron fuera los ESTADOS de las
   que ya existían: .nt-badge[hidden] (sin él, el círculo rojo se queda puesto
   con cero avisos) y .nt-bell.tiene / .notis.open .nt-bell (la campana no se
   encendía ni al haber avisos ni al abrir el panel). La paleta es la misma en
   los dos proyectos, así que traer el bloque entero es lo correcto. */
/* ---------- el buzón interno: la campana de la barra ----------
     Mismo desplegable que .usermenu y .tema-menu, que tiene justo al lado:
     blanco, filete, sombra y esquinas de 11px. Lo que cambia es el ancho —un
     aviso es una frase, no un renglón de menú— y que la lista se desplaza
     dentro del panel en vez de estirarlo hasta salirse de la pantalla. */
  .notis{position:relative; flex:0 0 auto;}
  .nt-bell{position:relative; display:flex; align-items:center; justify-content:center;
    width:34px; height:34px; border-radius:9px; background:transparent; border:0; padding:0;
    color:rgba(255,255,255,.85); cursor:pointer; transition:background .12s ease, color .12s ease;}
  .nt-bell svg{width:19px; height:19px; fill:none; stroke:currentColor; stroke-width:1.9; stroke-linecap:round; stroke-linejoin:round;}
  /* Pasar el ratón por encima solo cambia el fondo: es un roce, no un
     estado. */
  .nt-bell:hover{background:rgba(255,255,255,.10);}
  /* La campana se rellena en los dos momentos en que está "encendida": con
     avisos sin leer, y mientras el panel está abierto. El relleno lo pone la
     hoja y no el atributo fill del <svg> justamente para poder encenderlo y
     apagarlo desde aquí; el .tiene lo pone pintar() (js/notificaciones.js).
     Lo que distingue una cosa de la otra es la insignia roja, que solo
     aparece cuando hay algo sin leer — por eso importa tanto que de verdad
     desaparezca en cero, ver .nt-badge[hidden] aquí abajo. Abierto además
     lleva fondo, así que tampoco se confunden estando las dos a la vez. */
  .nt-bell.tiene, .notis.open .nt-bell{color:#fff;}
  .nt-bell.tiene svg, .notis.open .nt-bell svg{fill:currentColor;}
  .notis.open .nt-bell{background:rgba(255,255,255,.18);}
  /* El anillo del color de la barra separa la insignia de la campana que
     tiene debajo: sin él, el número se lee pegado al dibujo. */
  .nt-badge{position:absolute; top:1px; right:1px; min-width:16px; height:16px; padding:0 4px;
    border-radius:20px; background:var(--rust); color:#fff; font-size:9.5px; font-weight:800;
    display:flex; align-items:center; justify-content:center; box-shadow:0 0 0 2px var(--navy);}
  /* SIN ESTO la insignia no se va nunca. El código la apaga con el atributo
     `hidden`, que el navegador implementa con [hidden]{display:none} en SU
     hoja — y cualquier regla de la hoja del sitio le gana a la del
     navegador, por poca especificidad que tenga. Como .nt-badge trae
     display:flex, el círculo rojo se quedaba puesto con cero avisos, y una
     señal que está siempre no señala nada. */
  .nt-badge[hidden]{display:none;}
  .nt-panel{position:absolute; top:calc(100% + 9px); right:0; width:min(348px, calc(100vw - 24px));
    background:#fff; color:var(--ink); border:1px solid var(--line); border-radius:11px;
    box-shadow:0 8px 30px rgba(14,20,36,.16); padding:6px;
    opacity:0; visibility:hidden; transform:translateY(-6px);
    transition:opacity .15s ease, transform .15s ease; z-index:60; cursor:default;}
  .notis.open .nt-panel{opacity:1; visibility:visible; transform:translateY(0);}
  .nt-head{display:flex; align-items:center; gap:8px; padding:8px 10px 9px; flex-wrap:wrap;}
  .nt-h-t{font-size:12.5px; font-weight:700; color:var(--ink);}
  .nt-h-n{font-size:10.5px; color:var(--gray);}
  .nt-head .op-link{margin-left:auto; font-size:11px;}
  /* Ocho avisos caben sin desplazar; a partir de ahí la lista rueda dentro
     del panel y la cabecera con «marcar todo» se queda fija arriba. */
  .nt-list{max-height:min(58vh, 420px); overflow-y:auto; border-top:1px solid var(--line-soft); padding-top:4px;}
  .nt-item{display:flex; align-items:flex-start; gap:9px; padding:9px 10px; border-radius:8px; cursor:pointer;}
  .nt-item:hover{background:var(--block);}
  .nt-item + .nt-item{border-top:1px solid var(--line-soft);}
  /* Lo no leído se distingue por el icono y el peso del titular, no por un
     fondo de color en la fila: con cinco avisos seguidos sin leer, cinco
     bloques tintados se leen como una alerta y esto no es una alerta. El
     círculo del icono se rellena con el azul de la casa —var(--navy), no un
     hex fijo— para que siga a la paleta que esté puesta. */
  .nt-ico{width:26px; height:26px; flex:0 0 auto; border-radius:50%; background:var(--block);
    display:flex; align-items:center; justify-content:center; margin-top:1px;}
  .nt-ico svg{width:14px; height:14px; fill:none; stroke:var(--gray-soft); stroke-width:2; stroke-linecap:round; stroke-linejoin:round;}
  .nt-item.nuevo .nt-ico{background:var(--navy);}
  .nt-item.nuevo .nt-ico svg{stroke:#fff;}
  .nt-cuerpo{min-width:0; flex:1;}
  .nt-t{font-size:12px; font-weight:600; color:var(--gray); line-height:1.4;}
  .nt-item.nuevo .nt-t{font-weight:700; color:var(--ink);}
  /* De qué va el aviso, en dos líneas como tope: es el asunto de la cosa, y
     uno largo empujaría la fecha fuera de la fila. */
  .nt-d{font-size:11.5px; color:var(--gray); line-height:1.45; margin-top:2px;
    display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;}
  .nt-when{font-size:10.5px; color:var(--gray-soft); margin-top:3px;}

  /* Todo / Sin leer. Una franja propia debajo del título y no dos pestañas
     metidas en él: la cabecera ya lleva «Marcar todo como leído» a la
     derecha y los tres apretados no se leían. El número va solo en «Sin
     leer», que es la razón de mirar esa pestaña. */
  .nt-tabs{display:flex; gap:4px; padding:0 10px 8px;}
  .nt-tab{font:inherit; font-size:11px; font-weight:600; color:var(--gray); cursor:pointer;
    background:transparent; border:0; padding:4px 9px; border-radius:7px; line-height:1.4;}
  .nt-tab:hover{background:var(--block); color:var(--ink);}
  .nt-tab.on{background:var(--block); color:var(--ink); font-weight:700;}

  /* Las dos acciones de la fila: dar por leído (el punto) y archivar (la
     equis). Apagadas en reposo pero PRESENTES —nunca opacity:0—, porque un
     control que solo aparece al pasar el ratón no existe para quien no sabe
     de antes que está ahí. Se encienden al entrar en la fila y del todo al
     apuntarlas. */
  .nt-acc{display:flex; align-items:center; gap:2px; flex:0 0 auto; margin-top:1px;}
  .nt-b{width:22px; height:22px; flex:0 0 auto; display:flex; align-items:center; justify-content:center;
    background:transparent; border:0; padding:0; border-radius:6px; cursor:pointer;
    opacity:.35; transition:opacity .12s ease, background .12s ease;}
  .nt-item:hover .nt-b{opacity:.8;}
  .nt-b:hover{opacity:1; background:var(--line-soft);}
  /* El punto dice el estado y lo cambia: relleno del azul de la casa mientras
     está sin leer, hueco en cuanto se marca. Volver a pulsarlo la devuelve a
     sin leer — es el deshacer del clic accidental. */
  .nt-punto::after{content:''; width:9px; height:9px; border-radius:50%;
    border:1.5px solid var(--gray-soft); background:transparent;}
  .nt-punto.on::after{background:var(--navy); border-color:var(--navy);}
  .nt-x svg{width:13px; height:13px; fill:none; stroke:var(--gray-soft); stroke-width:2.2; stroke-linecap:round;}
  .nt-x:hover svg{stroke:var(--rust);}
  /* El pie del panel: la puerta a la pantalla entera. Separado con un filete
     porque no es un aviso más — si va pegado a la última fila, se pulsa por
     error creyendo que se abre ese. */
  .nt-pie{padding:8px 10px 4px; margin-top:4px; border-top:1px solid var(--line-soft); text-align:center;}
  .nt-pie .op-link{font-size:11px;}
  .nt-pie-sep{font-size:11px; color:var(--gray-soft); margin:0 6px;}

  /* El acuse de lectura al pie de la ficha de una tarea. Filete arriba porque
     no es un campo del formulario: no se edita, se consulta. */
  .sg-acuse:not(:empty){margin-top:14px; padding-top:12px; border-top:1px solid var(--line-soft);}
  .sg-acuse-fila{display:flex; align-items:center; gap:10px; flex-wrap:wrap; padding:3px 0;}
  .sg-acuse-fila .k{font-size:11.5px; color:var(--gray);}

  /* ---------- la pantalla de Avisos (js/views/avisos.js) ----------
     Misma gramática de fila que el panel de la campana —el mismo círculo de
     icono, el mismo punto, la misma equis—, en una rejilla más ancha: aquí sí
     hay sitio para el cuerpo del aviso y para la fecha en su propia columna.
     Una fila no puede leerse de dos maneras distintas según por dónde se
     entre. */
  .av-lista{display:flex; flex-direction:column;}
  .av-fila{display:grid; grid-template-columns:auto minmax(0,1fr) auto auto; align-items:start;
    gap:12px; padding:12px 4px; border-bottom:1px solid var(--line-soft);}
  .av-fila:last-child{border-bottom:none;}
  .av-fila:hover{background:var(--block);}
  .av-cuerpo{min-width:0;}
  .av-cuerpo[role="button"]{cursor:pointer;}
  .av-fila .nt-t{font-size:13px;}
  /* El asunto pesa menos que el titular: son dos renglones seguidos y con el
     mismo grosor se leían como dos títulos peleándose, no como una frase y su
     detalle. */
  .av-d{font-size:12.5px; color:var(--ink); font-weight:500; line-height:1.45; margin-top:2px;}
  .av-c{font-size:12px; color:var(--gray); line-height:1.5; margin-top:3px;}
  .av-cuando{font-size:11px; color:var(--gray-soft); white-space:nowrap; padding-top:2px; text-align:right;}
  /* Cuándo se leyó, debajo de cuándo llegó: distingue "esto lo despaché el
     martes y se me olvidó" de "esto lo acabo de mirar". Solo sale si hay
     fecha — las filas leídas de antes de que existiera la columna no la
     tienen, y una inventada sería peor que ninguna. */
  .av-leido{display:block; font-size:10.5px; color:var(--gray-soft); margin-top:3px;}
  /* Lo archivado no se esconde aquí —esta pantalla existe para poder verlo—
     pero se apaga: sigue siendo lo que uno decidió quitarse de encima. */
  .av-fila.archivada{opacity:.55;}
  .av-fila.archivada:hover{opacity:1;}
  /* En esta pantalla los controles no se esconden: no hay una acción
     principal con la que compitan (la fila entera ya abre el expediente) y
     una lista larga se recorre decidiendo, no mirando. */
  .av-fila .nt-b{opacity:.6;}
  .av-fila:hover .nt-b{opacity:.85;}
  .av-fila .nt-b:hover{opacity:1;}
  .av-volver svg{width:13px; height:13px; fill:none; stroke:var(--gray-soft); stroke-width:2.2; stroke-linecap:round; stroke-linejoin:round;}
  .av-volver:hover svg{stroke:var(--navy2);}
  /* Encabezado de día. Pequeño y en mayúsculas, como los rótulos de sección
     del resto de Atlas: tiene que ordenar la lista sin competir con ella. */
  .av-dia{font-size:10.5px; font-weight:700; letter-spacing:.08em; text-transform:uppercase;
    color:var(--gray-soft); padding:16px 4px 6px; border-bottom:1px solid var(--line);}
  .av-dia:first-child{padding-top:2px;}
  @media (max-width:640px){
    /* La fecha se va debajo del cuerpo: en un teléfono, cuatro columnas dejan
       el titular en una tira de dos palabras por línea. */
    .av-fila{grid-template-columns:auto minmax(0,1fr) auto;}
    .av-cuando{grid-column:2; grid-row:2; padding-top:4px;}
  }
  .nt-vacio{font-size:12px; color:var(--gray); text-align:center; padding:26px 14px; line-height:1.6;}
  .nt-vacio span{font-size:11px; color:var(--gray-soft);}
  @media (max-width:640px){
    /* Anclado a la derecha de la campana, un panel de 348px se sale por el
       borde en un teléfono: se ancla al borde de la pantalla en su lugar. */
    .nt-panel{right:-8px;}
  }


/* ===========================================================================
   EL TELÉFONO DE VERDAD (≤640px)
   ===========================================================================
   El bloque de 860 es el de «cabe sin barra lateral», y vale igual para una
   tableta en vertical: encoge lo mismo que hay. Éste es el del teléfono, donde
   no se trata de encoger sino de PRESENTARLO DE OTRA MANERA.

   Lo que lo motivó: una tabla de nueve columnas encogida a cuatro sigue siendo
   una tabla de cuatro columnas de 82px, y a ese ancho todos los datos salen
   cortados con puntos suspensivos —«Ale…», «Sin…», «Hi…»— mientras los
   títulos, que van sin partir, se montan unos sobre otros
   («RESPONSABPAÍSES SECTOR»). Se lee peor que si no estuvieran.

   VA AL FINAL DEL ARCHIVO, Y NO ES CASUALIDAD. Estuvo un rato detrás del
   bloque de 860 —que es donde se leería mejor— y ahí NO FUNCIONABA: las reglas
   de .inv-* y de .sg-toolbar viven en las líneas 3600-5400, o sea después, y
   una media query no suma especificidad, así que ganaban ellas y la tabla
   seguía apretada. Un bloque de anulaciones tiene que ir después de todo lo
   que anula. Si alguien lo mueve «a su sitio» por orden, esto se cae en
   silencio: el escritorio se verá igual y el teléfono volverá a verse mal.
   ======================================================================== */
@media (max-width:640px){

  /* ---------- las listas dejan de ser tablas y pasan a ser tarjetas ----------
     Sin cabecera de columnas —una lista de tarjetas no la necesita— y con cada
     dato en su renglón, precedido de su rótulo, que sale del data-col del
     marcado (ver invListRow en js/views/contrapartes.js). Nada se recorta: lo
     que no cabe de ancho, baja de línea. */
  .inv-tabla-cab, .inv-per-cab{display:none;}
  .inv-tabla-fila, .inv-per-fila, .inv-list-row.inv-pan-fila{
    display:block; padding:13px 14px; margin-bottom:9px;
    background:var(--bg); border:1px solid var(--line); border-radius:12px;
    box-shadow:0 1px 2px rgba(14,20,36,.05);}
  .inv-tabla-fila:active, .inv-per-fila:active, .inv-list-row.inv-pan-fila:active{background:var(--block);}
  /* El recorte con puntos suspensivos va en un style= del propio marcado, así
     que hay que pisarlo desde aquí: en una tarjeta sobra ancho y lo que falta
     es alto, justo al revés que en una fila. */
  .inv-tabla-fila > span, .inv-per-fila > span, .inv-pan-fila > span{
    display:flex; gap:10px; align-items:baseline; padding:3px 0;
    font-size:13px; min-width:0;
    white-space:normal !important; overflow:visible !important; text-overflow:clip !important;}
  /* Solo lo que TIENE rótulo lo lleva. Sin el [data-col] del selector, una
     celda que es una acción y no un dato —el «Editar» de la lista de personas—
     se ganaba igual un ::before vacío de 88px que la empujaba media tarjeta a
     la derecha, sin nada escrito delante. */
  .inv-tabla-fila > span[data-col]::before, .inv-per-fila > span[data-col]::before,
  .inv-pan-fila > span[data-col]::before{
    content:attr(data-col); flex:0 0 88px;
    font-size:11px; font-weight:600; color:var(--gray-soft);}
  /* El nombre encabeza la tarjeta: sin rótulo (ya se sabe de qué es), a cuerpo
     mayor, en el azul de la casa y con un filete debajo que lo separa de sus
     datos. Es lo que se busca al recorrer la lista. */
  .inv-tabla-fila > span:first-child, .inv-per-fila > span:first-child,
  .inv-pan-fila > span:first-child{
    display:block; font-size:15px; line-height:1.3; color:var(--navy);
    padding:0 0 8px; margin-bottom:6px; border-bottom:1px solid var(--line-soft);}
  .inv-tabla-fila > span:first-child::before, .inv-per-fila > span:first-child::before,
  .inv-pan-fila > span:first-child::before{display:none;}
  /* Las cifras dejan de alinearse como columna: en una tarjeta no hay columna
     con la que alinearlas. */
  .inv-tabla-fila > span.num, .inv-pan-fila > span.num{text-align:left;}
  /* «Editar» vuelve con los demás y con su blanco de toque, en vez de quedar
     suelto y diminuto contra el borde derecho. */
  .inv-per-fila > span.op-link{text-align:left !important; font-size:13px !important;}

  /* ---------- las barras de filtros, parejas ----------
     Cada desplegable se dimensionaba por su contenido, así que «Sector» salía
     ancho, «País de origen» medio y «Tier» estrecho: tres cajas desiguales en
     escalera, que es lo que hace que una pantalla parezca a medio terminar. En
     rejilla de dos van todas del mismo ancho y la barra se lee como un bloque.
     .sg-toolbar la comparten Correspondencia, Inteligencia, Proyectos,
     Seguimiento y Contrapartes: se arreglan las cinco a la vez. */
  .sg-toolbar{display:grid; grid-template-columns:1fr 1fr; gap:8px; align-items:stretch;}
  .sg-toolbar > *{min-width:0;}
  .sg-toolbar .segsel{width:100%;}
  .sg-toolbar .segsel select{width:100%; min-width:0;}
  /* Lo que no es un desplegable —buscadores, el botón de quitar filtros— toma
     la fila entera: partirlo por la mitad no ayuda a nadie. */
  .sg-toolbar > .tz-btn, .sg-toolbar > input, .sg-toolbar > label{grid-column:1 / -1;}
  .sg-toolbar > .tz-btn{justify-content:center;}
  /* Misma idea en la barra rápida de Seguimiento, que es de flex: cada control
     ocupa media fila como mínimo en vez de encogerse hasta su contenido. */
  .sg-quick input[type=text], .sg-quick select{flex:1 1 calc(50% - 8px); min-width:0;}
  .sg-quick .qa-t{flex:1 1 100%;}
}
