/* MERITUS — componentes. Doce piezas que cubren las 56 plantillas. */

/* ---------- marca ---------- */
/* Mención puntual de "MERITVS" fuera de la barra lateral (portales públicos,
   home.html). Mismo trazo que .app-nav-marca: version viva de meritus.css,
   que estas plantillas ya no cargan. */
.wordmark { font-family: var(--font-display); letter-spacing: .08em; }

/* ---------- shell ---------- */
.app { display: flex; min-height: 100vh; }

.app-nav { width: var(--w-nav); flex-shrink: 0; background: var(--nav);
           padding: var(--sp-4) 0; display: flex; flex-direction: column; gap: var(--sp-1); }
.app-nav-marca { font-family: var(--font-display); font-weight: 700;
                 letter-spacing: .13em; font-size: var(--fs-100);
                 color: var(--accent-pale); padding: 0 var(--sp-4) var(--sp-4);
                 text-decoration: none; display: block; }
.app-nav-item { color: color-mix(in srgb, var(--on-primary) 72%, transparent);
                padding: var(--sp-2) var(--sp-4); font-size: var(--fs-200);
                text-decoration: none; border-left: 2px solid transparent;
                min-height: var(--tap); display: flex; align-items: center; }
.app-nav-item:hover { color: var(--on-primary);
                      background: color-mix(in srgb, var(--accent-pale) 10%, transparent); }
.app-nav-item.activo { color: var(--on-primary); font-weight: 500;
                       border-left-color: var(--accent-pale);
                       background: color-mix(in srgb, var(--accent-pale) 16%, transparent); }
.app-nav-pie { margin-top: auto; padding: var(--sp-4); font-size: var(--fs-100);
               color: color-mix(in srgb, var(--on-primary) 60%, transparent); }

/* R5 sobre --nav: el foco de base.css usa --primary, que sobre el burdeos
   de la barra lateral (--nav: #4E0E19) da 1,28:1 — muy por debajo del 3:1
   de WCAG 2.2 SC 1.4.11. --accent-pale sí cumple (9,08:1) sobre esa
   superficie oscura, así que aquí se sustituye solo dentro de .app-nav. */
.app-nav :focus-visible { outline-color: var(--accent-pale); }

.app-main { flex: 1; min-width: 0; max-width: var(--w-content);
            padding: 0 var(--sp-5) var(--sp-7); }

.app-head { display: flex; align-items: baseline; gap: var(--sp-3);
            flex-wrap: wrap; padding: var(--sp-4) 0 var(--sp-3);
            border-bottom: 1px solid var(--bd); position: relative; }
.app-head-titulo { font-family: var(--font-editorial); font-size: var(--fs-500);
                   font-weight: 600; color: var(--primary); }
.app-head-acciones { margin-left: auto; display: flex; gap: var(--sp-2);
                     align-items: center; }
/* El gesto único: el filete de oro se traza al cargar. */
.app-head::after { content: ""; position: absolute; left: 0; bottom: -1px;
                   height: 2px; width: 100%; background: var(--accent);
                   transform-origin: left; animation: filete var(--dur-filete) var(--ease) both; }
@keyframes filete { from { transform: scaleX(0); } to { transform: scaleX(1); } }

.migas { font-size: var(--fs-100); color: var(--text-muted); padding: var(--sp-3) 0 0; }
.migas a { color: var(--text-muted); text-decoration: none; }

/* ---------- barra global (_barra.html) ---------- */
/* Cinta superior de contexto: institución, «ver como», volver a superadmin.
   Sus controles van EN LÍNEA; sin esto los <form> se apilan (son de bloque). */
.barra-global { display: flex; flex-wrap: wrap; align-items: center;
                gap: var(--sp-2) var(--sp-4); padding: var(--sp-2) var(--sp-5);
                border-bottom: 1px solid var(--bd); font-size: var(--fs-100);
                color: var(--text-muted); }
.barra-global-grupo { display: flex; align-items: center; gap: var(--sp-2); margin: 0; }
.barra-global a { color: var(--text-muted); text-decoration: none; }
.barra-global select { font: inherit; padding: var(--sp-1) var(--sp-2);
                       border: 1px solid var(--bd); border-radius: var(--r-sm);
                       background: var(--surface); color: var(--text); }

/* ---------- tabla ---------- */
.tabla th { font-size: var(--fs-100); font-weight: 600;
            text-transform: uppercase; letter-spacing: var(--tracking-label);
            color: var(--text-muted); padding: var(--sp-2) var(--sp-3);
            border-bottom: 1px solid var(--bd); }
.tabla td { padding: var(--sp-2) var(--sp-3); border-bottom: 1px solid var(--bd-soft);
            height: var(--row-h); }
.tabla tr:last-child td { border-bottom: 0; }
.tabla--densa td { padding: var(--sp-1) var(--sp-3); }
/* Celda de acciones: varios <form> pueden compartir fila (validar/rechazar,
   sellar/editar). Sin esto cada <form>, de bloque por defecto, se apila y
   rompe --row-h. */
.tabla td form { display: inline-block; margin: 0 var(--sp-2) 0 0; }
.tabla-vacia { padding: var(--sp-6); text-align: center; color: var(--text-muted);
               font-size: var(--fs-200); }
/* Restricción G-responsive: la tabla hace scroll, nunca la página. */
.tabla-scroll { overflow-x: auto; }

/* ---------- tarjeta ---------- */
.card { background: var(--surface); border: 1px solid var(--bd);
        border-radius: var(--r-lg); box-shadow: var(--sh-1);
        margin: var(--sp-4) 0; overflow: hidden; }
.card-cabecera { padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--bd-soft);
                 font-weight: 600; font-size: var(--fs-200); }
.card-cuerpo { padding: var(--sp-4); }

/* Rejilla de tarjetas (hubs de acceso: home.html, inicio.html). Cada tarjeta
   clicable envuelve un .card en un .kpi-link (ver mas abajo) para heredar
   display:block + sin subrayado; .card en si no lo necesita en su uso normal
   (apilado), asi que la regla vive aqui, no en .card. */
.rejilla-tarjetas { display: grid; gap: var(--sp-4); margin: var(--sp-4) 0;
                    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
.rejilla-tarjetas .card { margin: 0; height: 100%; }
.rejilla-tarjetas .card:hover { border-color: var(--primary); }

/* ---------- cifras ---------- */
/* R4 — superficie cálida SIEMPRE con filete de oro. */
.cifras { display: flex; flex-wrap: wrap; background: var(--surface-warm);
          border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent);
          border-radius: var(--r-md); margin: var(--sp-4) 0; }
/* El reparto, el filete separador y el escalonado se aplican al HIJO DIRECTO de
   .cifras, sea `.cifra` o el `<a class="kpi-link">` que la envuelve cuando es
   clicable. Con selectores atados a `.cifra` el envoltorio los rompía en silencio. */
.cifras > * { flex: 1; min-width: var(--w-cifra-min);
              animation: entra var(--dur-filete) var(--ease) both; }
.cifras > * + * { border-left: 1px solid color-mix(in srgb, var(--accent) 30%, transparent); }
.cifras > *:nth-child(2) { animation-delay: var(--dur-fila); }
.cifras > *:nth-child(3) { animation-delay: calc(var(--dur-fila) * 2); }
.cifras > *:nth-child(4) { animation-delay: calc(var(--dur-fila) * 3); }
.cifra { padding: var(--sp-3) var(--sp-4); }
.cifra-valor { font-size: var(--fs-700); font-weight: 600; line-height: 1;
               color: var(--text-data); font-variant-numeric: tabular-nums; }
.cifra-valor--marca { color: var(--primary); }
.cifra-etiqueta { font-size: var(--fs-100); font-weight: 600; margin-top: var(--sp-1);
                  text-transform: uppercase; letter-spacing: var(--tracking-label);
                  color: var(--accent-text); }
@keyframes entra { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; } }

/* Cifra clicable. El nombre .kpi-link lo impone G1 (tests/test_panel_dashboard.py
   está acoplado a él); se reutiliza aquí en vez de inventar un segundo nombre. */
.kpi-link { text-decoration: none; color: inherit; display: block; }
.kpi-link:hover .cifra-valor,
.kpi-link:hover .cifra-etiqueta { color: var(--primary); }

/* ---------- botones ---------- */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
       min-height: var(--tap); padding: var(--sp-2) var(--sp-4);
       font-size: var(--fs-200); font-weight: 600; text-decoration: none;
       border: 1px solid transparent; border-radius: var(--r-pill);
       background: var(--primary); color: var(--on-primary); }
.btn:hover { background: var(--primary-hover); color: var(--on-primary); }
.btn--sec { background: transparent; color: var(--primary); border-color: var(--primary); }
.btn--sec:hover { background: color-mix(in srgb, var(--primary) 8%, transparent); }
.btn--fantasma { background: transparent; color: var(--text-muted); border-color: var(--bd); }
.btn--sm { min-height: var(--tap-denso); padding: var(--sp-1) var(--sp-3); font-size: var(--fs-100); }

/* ---------- estados (R1: icono + palabra, nunca color solo) ---------- */
.pill { display: inline-flex; align-items: center; gap: var(--sp-1);
        padding: 2px var(--sp-3); border-radius: var(--r-pill);
        font-size: var(--fs-100); font-weight: 600; white-space: nowrap;
        background: var(--neutral-bg); color: var(--neutral);
        box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 30%, transparent); }
.pill::before { font-weight: 700; }
.pill.validado  { background: var(--ok-bg);     color: var(--ok); }
.pill.validado::before  { content: "\2713"; }   /* ✓ */
.pill.pendiente { background: var(--warn-bg);   color: var(--warn); }
.pill.pendiente::before { content: "\25F7"; }   /* ◷ */
.pill.rechazado { background: var(--danger-bg); color: var(--danger); }
.pill.rechazado::before { content: "\2715"; }   /* ✕ */
.pill.borrador::before  { content: "\25CB"; }   /* ○ */

/* ---------- campos ---------- */
.campo { margin: var(--sp-3) 0; max-width: var(--w-prose); }
.campo-etiqueta { font-size: var(--fs-100); font-weight: 600; margin-bottom: var(--sp-1); }
.campo input, .campo select, .campo textarea {
  width: 100%; min-height: var(--tap); padding: var(--sp-2) var(--sp-3);
  font-size: var(--fs-300); background: var(--surface); color: var(--text);
  border: 1px solid var(--bd); border-radius: var(--r-md); }
.campo input[type="checkbox"], .campo input[type="radio"] {
  width: auto; min-height: 0; accent-color: var(--primary); margin-right: var(--sp-2); }
.campo-ayuda { font-size: var(--fs-100); color: var(--text-muted); margin-top: var(--sp-1); }
.campo-error { font-size: var(--fs-100); color: var(--danger); margin-top: var(--sp-1); }
/* Rejilla de casillas (poderes por perfil, filtros múltiples). */
.rejilla-campos { display: grid; gap: var(--sp-2);
                  grid-template-columns: repeat(auto-fit, minmax(var(--w-campo-min), 1fr)); }
.rejilla-campos .campo { margin: 0; display: flex; align-items: center;
                         min-height: var(--tap); }

/* ---------- avisos ---------- */
.aviso { padding: var(--sp-3) var(--sp-4); margin: var(--sp-3) 0;
         border-left: 3px solid var(--text-muted); border-radius: 0 var(--r-md) var(--r-md) 0;
         background: var(--neutral-bg); font-size: var(--fs-200); max-width: var(--w-prose); }
.aviso--success { background: var(--ok-bg);     border-left-color: var(--ok);     color: var(--ok); }
.aviso--warning { background: var(--warn-bg);   border-left-color: var(--warn);   color: var(--warn); }
.aviso--error   { background: var(--danger-bg); border-left-color: var(--danger); color: var(--danger); }
.aviso--info    { background: var(--neutral-bg); border-left-color: var(--text-muted); color: var(--text); }

/* ---------- paginación ---------- */
.paginacion { display: flex; gap: var(--sp-1); align-items: center;
              margin: var(--sp-4) 0; font-size: var(--fs-200); }
.paginacion-item { min-width: var(--tap); min-height: var(--tap);
                   display: inline-flex; align-items: center; justify-content: center;
                   border: 1px solid var(--bd); border-radius: var(--r-md);
                   text-decoration: none; }
.paginacion-item[aria-current="page"] { background: var(--primary);
                                        color: var(--on-primary); border-color: var(--primary); }

/* ---------- barra de proporción (informes) ---------- */
/* El ancho del relleno lo calcula la vista: `style="width:{{ pct|unlocalize }}%"`.
   Ese atributo es DATO, no estilo suelto, y se conserva — igual que en el Gantt.
   Ojo al `|unlocalize`: sin él, «83,5%» es CSS inválido y la barra sale vacía. */
.fila-dato { display: flex; align-items: center; gap: var(--sp-3); }
.pista { flex: 1; height: 16px; overflow: hidden; border-radius: var(--r-pill);
         background: color-mix(in srgb, var(--primary) 8%, transparent); }
.pista > div { height: 100%; border-radius: var(--r-pill); background: var(--primary); }

/* ---------- impresión ---------- */
/* Los informes de dirección se imprimen: hay un botón «Imprimir / PDF». Sin esto
   saldrían la barra lateral y la cinta de contexto en el papel.
   Se añade `.migas` a la lista de ocultos, fuera del bloque literal que dio el
   controlador: es la cinta "⌂ Inicio …" de `_barra.html`, que vive FUERA de
   `.barra-global` (esa solo envuelve los selectores "ver como"/"ver rol") y por
   tanto no la tapaba `.barra-global{display:none}` sola. Sigue siendo solo CSS,
   dentro del fichero que esta ronda autoriza tocar. */
.no-print { display: revert; }
@media print {
  .app-nav, .barra-global, .migas, .app-head-acciones, .no-print, .paginacion { display: none; }
  .app { display: block; }
  .app-main { max-width: none; padding: 0; }
  .app-head::after { animation: none; }
  .card { break-inside: avoid; }
  a { text-decoration: none; color: var(--text); }
}

/* ---------- ficha (pares dato–valor) ---------- */
.ficha { display: grid; grid-template-columns: max-content 1fr;
         gap: var(--sp-2) var(--sp-5); align-items: baseline; margin: var(--sp-4) 0; }
.ficha-dato { font-size: var(--fs-100); font-weight: 600; text-transform: uppercase;
              letter-spacing: var(--tracking-label); color: var(--text-muted); }
.ficha-valor { font-size: var(--fs-200); }

/* ---------- superficie editorial (portales públicos e informes) ---------- */
.editorial { max-width: var(--w-prose); margin: 0 auto; padding: var(--sp-7) var(--sp-5); }
.editorial h1 { font-size: var(--fs-600); }
.editorial p { font-size: var(--fs-300); line-height: var(--lh-prose); margin: var(--sp-4) 0; }

/* ---------- responsive ---------- */
/* El colapso a "iconos" por debajo de 1100px prometido en la spec no es
   viable sin un juego de iconos que no existe: el contenido íntegro de cada
   .app-nav-item es un <span> de texto (T5, seis bases de app), así que
   ocultar el span dejaba enlaces de 44px clicables y vacíos, sin wordmark
   (el enlace a /) ni pie (cierre de sesión inalcanzable). En vez de un corte
   intermedio sin contenido, la barra lateral completa (vertical) se mantiene
   hasta 1100px y por debajo pasa directamente a la cinta horizontal
   desplazable, que sí conserva texto, wordmark y pie. */
@media (max-width: 1100px) {
  .app { flex-direction: column; }
  .app-nav { width: 100%; flex-direction: row; overflow-x: auto; padding: var(--sp-2); }
  .app-nav-marca { padding: 0 var(--sp-3); }
  .app-nav-item { border-left: 0; border-bottom: 2px solid transparent; }
  .app-nav-item.activo { border-left: 0; border-bottom-color: var(--accent-pale); }
  .app-nav-pie { margin-top: 0; margin-left: auto; }
  .app-main { padding: 0 var(--sp-4) var(--sp-6); }
  .cifras > * + * { border-left: 0; border-top: 1px solid color-mix(in srgb, var(--accent) 30%, transparent); }
  .cifras { flex-direction: column; }
}

/* ---------- gantt ---------- */
/* Cronograma de membresías de grupo (registro/grupo.html) y trayectoria de
   persona (registro/trayectoria.html). Las posiciones y anchos de las
   barras (`style="left:…%;width:…%"`) los calcula la vista: son DATOS, no
   estilo suelto, y viven en la plantilla — no se tocan aquí. Esta hoja solo
   dibuja el carril fijo. Las dimensiones internas que mantienen la barra
   centrada en su carril (alto de fila, ancho de la columna de nombre,
   alto/línea de la barra) van literales, no a un token: son geometría
   interna acoplada de una sola pieza, igual que un filete de 1px (G4) —
   snap-earlas a la escala de espaciado rompería la alineación vertical. */
.gantt { display: flex; flex-direction: column; gap: var(--sp-1); }
.gantt-eje { position: relative; height: 1.1rem; margin-left: 170px;
             border-bottom: 1px solid var(--bd); }
.gantt-eje .yl { position: absolute; top: 0; font-size: var(--fs-100);
                 color: var(--text-muted); transform: translateX(-50%); }
.gantt-fila { display: flex; align-items: center; gap: var(--sp-2); }
.gantt-fila .nombre { width: 170px; flex: 0 0 170px; font-size: var(--fs-200);
                       white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.track { position: relative; flex: 1; height: 1.5rem; border-radius: var(--r-sm);
         background: linear-gradient(var(--bd), var(--bd)) no-repeat center / 100% 1px; }
.track .gl { position: absolute; top: 0; bottom: 0; width: 1px;
             background: var(--bd); opacity: .6; }
.barra { position: absolute; top: .18rem; height: 1.15rem; border-radius: var(--r-sm);
         color: var(--on-primary); font-size: var(--fs-100); line-height: 1.15rem;
         text-align: center; min-width: 3px; overflow: hidden; box-shadow: var(--sh-1); }
/* `.prog` queda del original (sin uso hoy en la plantilla); se conserva por
   fidelidad al bloque que se traslada, no es un añadido nuevo. */
.barra.prog { opacity: .55; }
/* Contorno del grupo PRINCIPAL de la persona (no confundir con el ★ del IP). */
.barra.princ { box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--on-primary) 90%, transparent),
                            var(--sh-1); }
/* Banda de contrato/afiliación con la universidad (solo trayectoria.html). */
.barra.afil { background: repeating-linear-gradient(45deg,
              var(--ok), var(--ok) 6px,
              color-mix(in srgb, var(--ok) 75%, black) 6px,
              color-mix(in srgb, var(--ok) 75%, black) 12px); }
.gantt-leyenda { display: flex; flex-wrap: wrap; gap: var(--sp-1) var(--sp-4);
                 align-items: center; margin-top: var(--sp-4); padding-top: var(--sp-2);
                 border-top: 1px solid var(--bd); font-size: var(--fs-100);
                 color: var(--text-muted); }
.gantt-leyenda .tit { font-weight: 700; }
.gantt-leyenda .item { display: inline-flex; align-items: center; gap: var(--sp-1); }
.gantt-leyenda .muestra { width: .85rem; height: .85rem; border-radius: var(--r-sm);
                          display: inline-block; background: var(--bd); }
.gantt-leyenda .muestra.princ { box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--on-primary) 90%, transparent);
                                 border: 1px solid var(--bd); }
.gantt-leyenda .muestra.afil { background: repeating-linear-gradient(45deg,
                                var(--ok), var(--ok) 4px,
                                color-mix(in srgb, var(--ok) 75%, black) 4px,
                                color-mix(in srgb, var(--ok) 75%, black) 8px); }
.gantt-leyenda .sub { flex-basis: 100%; }

/* Asiento anulado en el libro de registro (grupo.html/trayectoria.html): una
   enmienda lo anula pero el asiento original sigue visible, tachado, para
   no perder el rastro notarial. No es del Gantt, pero solo lo usan estas
   dos plantillas y esta es la única hoja que esta tarea autoriza tocar. */
.anulado { text-decoration: line-through; color: var(--text-muted); }

/* ---------- panorama del ecosistema (panel.html) ---------- */
/* Dashboard /panel/<slug>/. Marcado SIN CAMBIOS respecto al original salvo
   quitar el <style> propio: aqui viven los ganchos de G1 (`.kpi-link` en las
   ocho cifras, `<a href="/faq/.../"><g class="node">` del SVG) y la Tarea 11
   los conserva literales — hay pruebas acopladas
   (tests/test_panel_dashboard.py). */
.kpis { display: grid; gap: var(--sp-3);
        grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.kpi { border: 1px solid var(--bd); border-radius: var(--r-lg);
       padding: var(--sp-3) var(--sp-4); background: var(--surface);
       border-left: 5px solid var(--c, var(--primary)); }
.kpi .num { font-size: var(--fs-700); font-weight: 700; line-height: 1; }
.kpi .lbl { color: var(--text-muted); font-size: var(--fs-100); margin-top: var(--sp-1); }
/* El .kpi-link de la cifra (mas arriba) ya pone text-decoration:none/color:inherit/
   display:block; esta regla solo anade el resalte de foco/hover propio de .kpi. */
.kpi-link:hover .kpi { border-color: var(--c, var(--primary)); }

/* Los ocho `--c` de arriba y los `fill` que hacen juego en los <rect> del SVG
   de abajo son la MISMA paleta por dato (personas=azul, grupos=verde…): la
   Tarea 14 los sustituyo por la rampa --serie-1..8, en el mismo orden que las
   ocho tarjetas KPI. El noveno nodo (Categorias) no tiene tarjeta KPI propia
   y usa var(--primary); el color de las flechas (antes literal) usa
   var(--text-muted), igual que `.elbl` y `.edge`. Cero color literal. */
.card-cuerpo svg { width: 100%; height: auto; min-width: 760px; }
svg a { cursor: pointer; text-decoration: none; }
.node .t { fill: var(--on-primary); font-weight: 600; font-size: 14px; }
.node .n { fill: var(--on-primary); font-weight: 700; font-size: 22px; }
.edge { stroke: var(--text-muted); stroke-width: 1.6; fill: none; }
.elbl { fill: var(--text-muted); font-size: 11px; }

/* Estados de la tabla de indicadores de cumplimiento (RD 640 y similares).
   No son `.pill`: no llevan icono, pero R1 se cumple igual porque el texto
   siempre lleva la palabra del estado ({{ it.estado }}), nunca solo el color. */
.chip { display: inline-block; padding: 2px var(--sp-3); border-radius: var(--r-pill);
        font-size: var(--fs-100); font-weight: 600; color: var(--on-primary); }
.chip-cumple { background: var(--ok); }
.chip-no_cumple { background: var(--danger); }
.chip-sin_datos { background: var(--neutral); }
.chip-informativo { background: var(--primary); }
