/* ============================================================
   Value — estilos locales del módulo. Prefijo .va-
   Cero overrides de .r-, cero valores crudos de color: todo sale de tokens.

   VALUE ES EL REGISTRO; WORKSPACE ES EL TRABAJO. Este módulo existe para que
   una tarea delegada a un agente sepa CONTRA QUÉ REPOSITORIO trabajar sin que
   nadie lo teclee, así que la vista tiene un solo trabajo y se juzga con una
   sola pregunta: ¿se ve de un golpe qué sistemas hay, cuáles están activos y
   qué se está moviendo en cada uno? Todo lo que no conteste eso, sobra.

   ------------------------------------------------------------
   LAS TRES DECISIONES DE CAJA, y las tres son de panel y no de página
   ------------------------------------------------------------

   1 · LA HOJA DE UN SISTEMA ES LA SEGUNDA PÁGINA DEL PANEL, no una losa que
       flota encima. Cero `position`, cero `z-index`, cero ancho, cero sombra:
       los pone el panel, que ya es la caja que flota. Se enseña escondiendo la
       raíz con `:has` —una sola fuente de verdad, el `hidden` de la hoja— igual
       que `.rel-side` y `.wk-side`. Copiar uno de esos tres es la forma
       correcta de agregar el cuarto, y esto es el cuarto.

   2 · LOS CORTES MIRAN LA COLUMNA, no la ventana. Un `@media (max-width:…)`
       no se cumple nunca dentro del panel: la ventana es ancha y la columna
       mide 400–700. Los cortes de abajo son `@container` sobre `#viewValue`,
       y el contenedor va en LA VISTA y no en la raíz del módulo porque la hoja
       es hermana de la raíz: con el contenedor una rama más abajo, los cortes
       de la hoja no se consultarían nunca (es el bug que `relations.css` ya
       documenta y pagó).

   3 · NADA CEDE POR OMISIÓN. En una columna flex todo se estruja sin avisar
       —medido en Relaciones: una barra de 56px pasó a 18 con la lista larga
       empujando—. Aquí se declara al revés: `flex: 0 0 auto` para todos y
       quien crece lo pide por su nombre. `:where` deja la especificidad en
       cero para que la regla de cada pieza le gane sin pelear.
   ============================================================ */

/* ---------- El módulo, dentro del panel ----------
   La cadena de flex existe para que la lista sepa cuánto alto le sobra y para
   que la hoja del sistema pueda llenar el panel sin posicionarse. `.os-view`
   ya es un item flex con `min-height: 0`, así que su alto es el del panel; de
   ahí para abajo cada eslabón lo pasa. */
#viewValue {
  display: flex;
  flex-direction: column;
  min-height: 0;
  height: 100%;
  container-type: inline-size;
  container-name: val;
}
#vaRoot { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
:where(#vaRoot) > * { flex: 0 0 auto; }
/* Con la hoja abierta la lista no está debajo: no está. */
#viewValue:has(> .va-side:not([hidden])) > #vaRoot { display: none; }

/* ---------- La cabecera: la cifra que manda y sus dos acompañantes ----------
   El nombre del módulo NO vive aquí. Lo dice su orbe y lo dice la cabecera del
   panel, una vez; repetirlo como título gasta el alto que es del contenido.
   Lo que queda es la métrica en numeral de matriz de puntos —`--lg`, la misma
   escala que los otros siete, porque el no-negociable es que la cifra que manda
   se vea IGUAL en todo el OS— y dos cifras de apoyo en texto tabular. */
.va-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s-6);
  margin-bottom: var(--s-5);
}
/* La métrica es un `.r-lcdrow` (flex), no un `<p>`: no trae margen de párrafo
   que corregir. Se declara en cero para que quede dicho y no por omisión. */
.va-metric { margin: 0; }
.va-stats { display: flex; gap: var(--s-4); margin: 0; }

/* ---------- La barra de verticales ----------
   El segmentado se queda A LA VISTA con tres verticales o menos, y es la
   excepción que `CLAUDE.md` nombra por su nombre: ver las alternativas ES el
   punto —«qué tengo en Nexxia contra qué tengo en Seguros» es la pregunta del
   módulo, no un filtro de conveniencia—. Con más de tres se comprime a
   `.r-pick`, y de eso decide el JS; aquí solo se le da caja a los dos.

   El alta y la administración de la vertical viven al final de la barra y se
   REVELAN: dar de alta una vertical se hace una vez al año y renombrarla
   menos, así que dos controles puestos serían dos piezas que nadie estaba
   leyendo. Aparecen al hover o al foco de la barra, con las transiciones del
   sistema, y el ancho ya está reservado para que nada salte.

   El host es `.r-toolbar` del sistema, y eso resuelve gratis lo que sería la
   única trampa de geometría de esta barra: con tres verticales el segmentado
   son CUATRO pastillas, y en el mínimo de la columna eso desborda. La cápsula
   ya trae `overflow-x: auto` sin barra visible, así que se recorre en vez de
   romperse — y es uno de los cinco ancestros que el sistema conoce como
   recortadores, así que el bote y la lista comprimida se voltean solos. */
.va-bar { margin-bottom: var(--s-5); }
.va-bar__seg { min-width: 0; }
.va-bar__pick { min-width: 0; }
.va-bar__a {
  display: flex;
  align-items: center;
  gap: var(--s-1);
  margin-left: auto;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--d-fast) var(--ease);
}
.va-bar:hover .va-bar__a,
.va-bar:focus-within .va-bar__a { opacity: 1; pointer-events: auto; }

/* ---------- La lista ----------
   Agrupada por vertical cuando se ven todas: el rótulo del grupo es lo que
   contesta «qué tengo en cada frente». Con una vertical elegida el rótulo se
   va, porque el segmentado ya lo está diciendo y repetirlo es clutter. */
.va-list {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  scrollbar-width: thin;
}
.va-g { margin-bottom: var(--s-4); }
.va-g:last-child { margin-bottom: 0; }
.va-g__t { margin: 0 0 var(--s-1); }
.va-g__l { border-top: var(--stroke) solid var(--hairline); }

/* ---------- Una fila por sistema, y es UN RENGLÓN ----------
   Nombre · contadores · estado. Los tres puestos, ninguno revelado: son las
   tres partes de la única pregunta que este módulo contesta.

   ESTO ERA DE DOS RENGLONES Y SE MIDIÓ MAL. Con la anatomía de una fila de
   Relaciones —nombre y estado arriba, todo lo demás en un segundo renglón
   reservado— la fila medía 77.5 px y seis sistemas pedían 605 px de lista para
   453 disponibles a 1280×800: el módulo estrenaba con rueda del ratón. Y lo
   grave no era el alto, era QUÉ había quedado en el renglón escondido: los tres
   contadores, o sea «qué se está moviendo», que es un tercio del encargo. En un
   renglón la fila mide 46 px, el portafolio cabe sin scroll en los tres anchos y
   la respuesta está a la vista. El razonamiento completo, con lo que se mudó al
   `title`, vive en `fila()` (value.js).

   `align-items: center` y no `baseline`: el punto de estado es un cuadro de
   7 px sin línea base propia, y con `baseline` cuelga del renglón. */
.va-s {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: var(--s-3);
  align-items: center;
  width: 100%;
  padding: var(--s-2);
  border: 0;
  border-bottom: var(--stroke) solid var(--hairline);
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  transition: background var(--d-fast) var(--ease);
  animation: os-slide-in var(--d-base) var(--ease-out) both;
  animation-delay: calc(var(--i, 0) * var(--stagger));
}
.va-s:hover, .va-s:focus-visible { background: var(--surface-2); }
.va-s[aria-current="true"] { background: var(--surface-2); }
.va-s__n {
  font-family: var(--font-display);
  font-weight: var(--fw-light);
  letter-spacing: var(--tr-tight);
  font-size: var(--t-body);
  color: var(--ink);
  margin: 0;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Los tres contadores. `flex: 0 0 auto` porque quien cede es el nombre: una
   cifra recortada no es una cifra degradada, es una cifra falsa. */
.va-s__m {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  margin: 0;
  flex: 0 0 auto;
}
/* Icono + cifra, sin palabra: el símbolo lo dice y la palabra vive en el
   `title`. Es el mismo `rel-p__c` de Relaciones, con su prefijo. */
.va-s__c { display: inline-flex; align-items: center; gap: var(--s-1); }
/* El estado a la derecha, y NO se revela: es un tercio de la pregunta que el
   módulo contesta («cuáles están activos»). El punto es cuadrado, como todo
   estado del sistema, y lo pone `.r-status`. */
.va-s__e { flex: 0 0 auto; justify-self: end; }

/* ---------- El punto de actividad: quién está trabajando aquí AHORA ----------
   Robbie: «que haya un pequeño indicador de notificación en los sistemas que se
   están usando por gente». Es un punto en el renglón, derivado de `sessions` en
   cada pintado (la cadena completa vive en `actividad()`, value.js) y NUNCA
   guardado en el sistema.

   TRES ESTADOS, Y EL TERCERO NO SE DIBUJA:

   · TRABAJANDO — `--info` y LATE. El latido es lo que dice «vivo» en este OS
     (`.r-status--live`, `.r-caret`) y aquí se reusa su misma `@keyframes` y su
     mismo token de periodo, no una copia: dos definiciones de «vivo» es lo que
     el sistema ya fundió una vez a propósito.
   · TE NECESITA — el ÁCIDO, y QUIETO. Es lo único de esta vista que pide una
     acción de Robbie, así que se lleva el único acento (la cabeza le cede el
     suyo; ver `cabeza()`). Y no late porque la sesión tampoco: una que está
     esperando permiso está DETENIDA, y prestarle el ritmo de «algo avanza»
     diría lo contrario de lo que pasa. Quietud + ácido se lee «se paró y es
     tuyo», que es exactamente el estado.
   · QUIETO — nada. Un punto apagado por renglón son veinte piezas que no dicen
     nada en la vista que más se consulta; la misma regla con la que un contador
     en cero no se pinta.

   POR QUÉ `--info` Y NO `--ok` para trabajando, y es lo único que se midió
   mirando la fila completa: el estado del sistema de la derecha ya pinta `--ok`
   para «Activo», y casi todo sistema con un agente encima está activo — así que
   con `--ok` la fila normal tendría DOS cuadros verdes, uno latiendo, a 300 px
   uno del otro. `--info` es igual de semántico (es el mismo azul con el que la
   hoja dice «PR abierto», o sea trabajo en vuelo) y se distingue de un golpe.

   AQUÍ NO SE DIBUJA NADA DEL PUNTO, Y DESDE EL 2026-08-27 TAMPOCO SU COLOR.
   Los 7 px, el radio de 1 y la geometría siempre fueron de `.r-status`; lo que
   este archivo sí hacía era el color y el ritmo, tocando el `::before` de su
   PROPIA clase porque era la única costura posible sin editar `ron.css`. Y
   quedó anotado que el lugar de verdad era el sistema.
   
   Ya subió: `.r-status--busy` (azul que late) y `.r-status--accent` (ácido
   quieto) viven en `ron.css`, y el criterio que las movió es el declarado — el
   contador de sesiones del chasis necesita exactamente la misma señal, y sube
   lo que más de una superficie necesita. Los dos párrafos de arriba se quedan
   porque el ARGUMENTO sigue siendo el que decide (`--info` y no `--ok` para
   trabajando, el acento sin ritmo), sólo que ahora se aplica desde `ron.css` y
   no desde aquí. `.va-act` se queda con el `flex` y nada más.
   
   Sigue pendiente lo que este comentario nombró de paso y es de otro set:
   `.va-repo__k` y el icono de llave que le falta. */
.va-act { flex: 0 0 auto; }
/* «QUIETO NO SE DIBUJA» APLICA TAMBIÉN AL HUECO. En la hoja el punto vive en un
   contenedor fijo (`[data-sysact]`, que `pintaHoja()` rellena), y un contenedor
   vacío sigue siendo un item de flex: se come un `gap` entero y corre el id del
   sistema 8 px a la derecha en el caso NORMAL, que es el sistema quieto. Con
   `:empty` el renglón de la hoja queda idéntico a como estaba cuando no hay
   nadie trabajando, que es la misma garantía que la lista da por construcción. */
.va-side__top [data-sysact]:empty { display: none; }

/* El vacío se centra en lo que le tocó en vez de colgar del techo: en una
   columna alta, un mensaje corto pegado arriba parece contenido que se quedó a
   medio cargar. */
.va-blank {
  flex: 1 1 auto;
  min-height: 0;
  padding: var(--s-8) var(--s-4);
  text-align: center;
  display: grid;
  gap: var(--s-3);
  justify-items: center;
  align-content: center;
}

/* ---------- La hoja del sistema: la segunda página ----------
   No flota, no tapa nada y no tiene velo: OCUPA el panel en lugar de la lista.
   La entrada es `os-slide-in` —hacia arriba y con opacidad— y no una
   translación horizontal: dentro del panel esos píxeles de ancho no existen, y
   aunque el cuerpo los recorte quedan como desborde scrolleable. Es el mismo
   hallazgo que ya corrigieron `.rel-side` y `.wk-side`; las cuatro entran
   igual. */
.va-side {
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  animation: os-slide-in var(--d-base) var(--ease-out);
}
/* El renglón que devuelve a la lista y ofrece el bote. Sin alto fijo ni
   relleno lateral —el cuerpo del panel ya pone el suyo—. */
.va-side__top {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2);
  padding-bottom: var(--s-3);
  border-bottom: var(--stroke) solid var(--hairline);
}
.va-side__id { opacity: 0; transition: opacity var(--d-fast) var(--ease); }
.va-side__top:hover .va-side__id,
.va-side__top:focus-within .va-side__id { opacity: 1; }
/* Lo único que scrollea de la hoja, y por eso el cuerpo del panel no tiene que
   hacerlo: la hoja mide exactamente el panel. */
.va-side__body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: var(--s-5) 0 var(--s-8);
  scrollbar-width: thin;
}

/* El nombre del sistema: `--t-h3` y no `--t-h2` por lo mismo que la ficha de
   una persona — en una columna de 400 un nombre largo en tamaño de titular se
   parte en dos renglones y empuja todo el expediente hacia abajo. */
.va-name {
  width: 100%;
  border: 0;
  background: transparent;
  font-family: var(--font-display);
  font-weight: var(--fw-light);
  letter-spacing: var(--tr-tight);
  font-size: var(--t-h3);
  line-height: var(--lh-snug);
  color: var(--ink);
  padding: 0;
  margin-bottom: var(--s-3);
}
.va-name:focus { outline: none; }

/* Los tres selectores comprimidos —tipo, vertical y estado— en un renglón.
   Comprimidos y no segmentados: aquí ver las alternativas NO es el punto, se
   quiere saber en qué está puesto. Es la regla general de `CLAUDE.md`, y la
   excepción se la queda el segmentado de verticales de la barra, donde
   comparar sí es el trabajo. */
.va-picks {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-bottom: var(--s-4);
}

/* La descripción: un campo de texto que crece con lo escrito, sin barra. */
.va-desc {
  width: 100%;
  min-height: calc(var(--s-6) * 2);
  resize: vertical;
  margin-bottom: var(--s-5);
}

.va-b { margin-bottom: var(--s-5); }
.va-b__in {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-top: var(--s-2);
  align-items: center;
}

/* ---------- Repositorios ----------
   La coordenada, no el código: el OS nunca clona ni corre nada de un repo
   (contrato § 4). Una fila es el vínculo que abre FUERA del OS, la rama base y
   el bote que quita.

   `.r-label` Y NO `.r-micro` para la rama, y es la trampa que este proyecto ya
   pagó tres veces: `.r-micro` transforma a MAYÚSCULAS, y una rama de git no se
   escribe así — es un dato que se copia. */
.va-repos { display: grid; gap: var(--s-1); width: 100%; margin-top: var(--s-2); }
.va-repo {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  min-width: 0;
  padding-block: var(--s-2);
  border-bottom: var(--stroke) solid var(--hairline);
}
.va-repo:last-child { border-bottom: 0; }
.va-repo__l {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--s-1);
  color: var(--ink);
  font-size: var(--t-body-sm);
  text-decoration: none;
}
/* La elipsis cuelga del hijo y no del vínculo: sin el `<span>`, una URL cruda
   se corta a hachazo y de paso se lleva la flecha de «abre fuera». Es la misma
   corrección que `.wk-repo__l` documenta con su captura. */
.va-repo__l > span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.va-repo__l:hover > span, .va-repo__l:focus-visible > span { text-decoration: underline; }
.va-repo__b { flex: 0 0 auto; }
/* El bote se revela con su fila —lo secundario no vive puesto— y el
   `pointer-events` viaja con la opacidad: un bote invisible no se puede picar,
   que es exactamente lo que se quiere. */
.va-repo__x {
  flex: 0 0 auto;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--d-fast) var(--ease);
}
.va-repo:hover .va-repo__x, .va-repo:focus-within .va-repo__x { opacity: 1; pointer-events: auto; }

/* ---------- El token de un repositorio ----------
   Tres piezas y cada una está donde está por una razón distinta:

   `.va-repo__t` — CUÁL CREDENCIAL USA, y va PUESTA. Es un dato, no una acción:
   de él depende que las tareas de este sistema puedan abrir una rama, así que es
   de la misma clase que los tres contadores de la fila de un sistema, que
   tampoco se revelan. Con token propio el sello es además el disparador para
   reemplazarlo —un botón sin caja, como `.va-pr__t` y `.va-t__t`— y así la fila
   se ahorra un control: tres acciones reveladas no caben en 400 px, que es el
   mínimo declarado del módulo.

   `.va-repo__k` — CONECTAR. Puesta cuando NINGÚN token cubre el repo y revelada
   cuando el global lo cubre, y la frontera no es estética: es si la función está
   muerta. Sin credencial, esto es lo único que enciende la rama y el PR, y
   esconderlo tras el hover repetiría el bug que este trabajo vino a cerrar. El
   porqué completo vive en `conectaRepo()` (value.js).

   `.va-repo__in` — EL CAMPO, expandido en su lugar. La fila no crece ni cambia
   de alto: lo que cambia es qué la ocupa. El vínculo cede su `flex-grow` (deja
   de ser `1 1 auto`) y el campo se lo queda, que es lo único que hace falta para
   que un token quepa en una columna de 400 px sin que el renglón se parta. */
.va-repo__t {
  flex: 0 0 auto;
  padding: 0;
  border: 0;
  background: transparent;
  font-family: inherit;
  color: var(--ink-2);
}
button.va-repo__t { cursor: pointer; }
button.va-repo__t:hover, button.va-repo__t:focus-visible { color: var(--ink); text-decoration: underline; }

.va-repo__k { flex: 0 0 auto; }
.va-repo__k--rev {
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--d-fast) var(--ease);
}
.va-repo:hover .va-repo__k--rev,
.va-repo:focus-within .va-repo__k--rev { opacity: 1; pointer-events: auto; }

.va-repo__in {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--s-1);
}
.va-repo__f { flex: 1 1 auto; min-width: 0; }
/* Con el campo abierto el vínculo se estruja hasta su elipsis y el ancho es del
   campo: el nombre del repo ya se leyó, lo que hace falta ahora es pegar un
   token. `max-width` en `ch` y no en px para que siga el tipo que resolvió. */
.va-repo[data-conecta] > .va-repo__l { flex: 0 1 auto; max-width: 18ch; }

/* ---------- Las tareas que pueden mover el repositorio ----------
   La misma anatomía que `.va-repo` —contenido que se estruja, la rama al canto
   y la acción al final— y eso es la mitad del punto: quien aprendió a leer una
   fila de repositorio ya sabe leer ésta. Lo único que cambia es que la acción
   NO se revela al hover.

   POR QUÉ VA PUESTA, contra la regla general de «lo secundario se revela»:

   · el bloque se dibuja SOLO cuando hay un gesto que ofrecer (sin fase 2, sin
     token con escritura o sin repositorio registrado no existe), así que
     esconder la acción lo deja sin contenido — no es metadata de la fila, es su
     razón de ser;
   · y `pointer-events` viaja con la opacidad, así que un control revelado al
     hover no se puede tocar en una pantalla sin puntero. `@media (hover: none)`
     lo devuelve para el resto del módulo; aquí no haría falta porque nunca se
     fue.

   Lo que sí se revela es lo de siempre: el nombre completo de la rama vive en
   el `title` cuando la elipsis lo recorta. */
.va-ts { display: grid; gap: var(--s-1); width: 100%; margin-top: var(--s-2); }
.va-t {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  min-width: 0;
  padding-block: var(--s-1);
  border-bottom: var(--stroke) solid var(--hairline);
}
.va-t:last-child { border-bottom: 0; }
/* El texto de la tarea. Botón sin caja —el texto es el vínculo— y la elipsis
   cuelga de él, que es lo que impide que una frase larga empuje a la rama y a
   la acción fuera del panel (`overflow-x: hidden` las recortaría en silencio,
   la regla 4 del marcado de app/README.md). */
.va-t__t {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: left;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--ink);
  font-family: inherit;
}
.va-t__t:hover, .va-t__t:focus-visible { text-decoration: underline; }
/* Sin Workspace cargado no hay a dónde ir, y no se finge. Misma regla que
   `.va-pr__t--mudo`. */
.va-t__t--mudo { cursor: default; }
.va-t__t--mudo:hover { text-decoration: none; }
.va-t__b { flex: 0 0 auto; max-width: 38%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.va-t__a { flex: 0 0 auto; display: flex; }

/* ---------- Los PRs del sistema ----------
   Salen de `tasks[].repo`, que ya existe: un PR es de una TAREA, y este bloque
   solo los junta por sistema. De ahí que cada fila diga de qué tarea salió —sin
   eso un PR suelto no se puede rastrear— y que el texto lleve a Workspace, que
   es donde se opera. */
.va-prs { display: grid; gap: var(--s-1); width: 100%; margin-top: var(--s-2); }
.va-pr {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0 var(--s-2);
  align-items: baseline;
  padding-block: var(--s-2);
  border-bottom: var(--stroke) solid var(--hairline);
}
.va-pr:last-child { border-bottom: 0; }
.va-pr__l {
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--s-1);
  color: var(--ink);
  font-size: var(--t-body-sm);
  text-decoration: none;
}
.va-pr__l > span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.va-pr__l:hover > span, .va-pr__l:focus-visible > span { text-decoration: underline; }
.va-pr__e { grid-column: 2; grid-row: 1; justify-self: end; }
/* De qué tarea salió. Botón sin caja: el texto es el vínculo. */
.va-pr__t {
  grid-column: 1 / -1;
  justify-self: start;
  max-width: 100%;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font-family: inherit;
  text-align: left;
}
.va-pr__t:hover, .va-pr__t:focus-visible { color: var(--ink); text-decoration: underline; }
/* Sin Workspace cargado no hay puerta, y no se finge: la fila se lee y no
   invita a picarle. Misma regla que `.rel-note__go--mudo`. */
.va-pr__t--mudo { cursor: default; }
.va-pr__t--mudo:hover { text-decoration: none; }

/* Altas: el `.r-capture` del sistema en un bloque propio. El bloque existe
   para no declarar nada sobre `.r-*` —el componente es `inline-grid` y su línea
   arrastra interlineado— y porque en un flex un item con caja propia se alinea
   sin pedir nada. La caja del flujo es la del disparador, 28×28, y no cambia al
   expandirse: el campo va en la capa superior. */
.va-cap { display: flex; }

@media (prefers-reduced-motion: reduce) {
  .va-s, .va-side { animation: none; }
  .va-s, .va-side__id, .va-repo__x, .va-repo__k--rev, .va-bar__a { transition: none; }
  /* QUIETO, NO BORRADO, y por eso lleva `!important`: la regla global de
     `ron.css` aplasta toda duración a 0.01ms, y para una animación `infinite`
     eso no es quietud —es un ciclo corriendo a ciegas que deja la opacidad
     donde caiga, o sea un punto que puede quedarse casi invisible—. El punto
     tiene que seguir LEYÉNDOSE sin movimiento: es la señal de que hay un agente
     encima de este sistema. Es palabra por palabra la corrección que `ron.css`
     ya hizo para `.r-status--live::before`, `.r-beam` y `.r-caret`. */
  .va-act::before { animation: none !important; opacity: 1; }
}

/* Sin hover no hay revelación: en táctil lo secundario se queda visible.
   `.va-repo__k--rev` entra aquí y NO es opcional: `pointer-events` viaja con la
   opacidad, así que sin este renglón darle a un repositorio su propio token
   sería imposible en una pantalla sin puntero. Es la misma corrección que la
   acción de `.va-t` explica con su propio párrafo. */
@media (hover: none) {
  .va-side__id { opacity: 1; }
  .va-repo__x, .va-repo__k--rev, .va-bar__a { opacity: 1; pointer-events: auto; }
}

/* ---------- Angosto ----------
   El corte mira la COLUMNA. 400 es el mínimo declarado del módulo, así que va
   justo encima —a 440— para que el mínimo caiga completo del lado apretado y el
   cómodo (520) no.

   Lo que cede: la cabecera se apila (la métrica y sus dos cifras de apoyo no
   caben de lado a lado en 400) y los tres selectores de la hoja se reparten en
   los renglones que hagan falta, que es lo que `flex-wrap` ya hace. */
@container val (max-width: 440px) {
  .va-head { flex-direction: column; align-items: flex-start; gap: var(--s-3); }
  .va-grid { grid-template-columns: 1fr; }
}

/* ---------- Portafolio v0: grilla de tarjetas ----------
   AC2–AC3. Misma familia `.r-card` / `.r-chip` / `.r-status` / `r-tnum`.
   El hover abre hijos DEBAJO, en el sitio, no en una página. El cue de
   pila se ve sin hover. Motion del sistema: `--d-base` / `--ease-spring`. */
.va-grid {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(168px, 1fr));
  gap: var(--s-3);
  align-content: start;
  padding-bottom: var(--s-8);
  scrollbar-width: thin;
}
.va-cell {
  display: flex;
  flex-direction: column;
  gap: 0;
  min-width: 0;
}
.va-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-2);
  width: 100%;
  min-height: 108px;
  padding: var(--s-3);
  text-align: left;
  cursor: pointer;
  color: inherit;
  font: inherit;
  transition: transform var(--d-base) var(--ease-spring),
              border-color var(--d-base) var(--ease-spring);
}
.va-card--kid { min-height: 76px; padding: var(--s-2); }
.va-card:hover, .va-card:focus-visible { border-color: var(--hairline-strong); }
.va-card[aria-current="true"] { border-color: var(--hairline-strong); }
.va-card__n {
  font-family: var(--font-display);
  font-weight: var(--fw-light);
  letter-spacing: var(--tr-tight);
  font-size: var(--t-body);
  color: var(--ink);
  margin: 0;
  padding-right: var(--s-4);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}
.va-card--kid .va-card__n { font-size: var(--t-body-sm); }
.va-card__tipo { margin-top: auto; }
.va-card__dot {
  position: absolute;
  top: var(--s-3);
  right: var(--s-3);
}
.va-card__pct {
  position: absolute;
  bottom: var(--s-3);
  right: var(--s-3);
  font-size: var(--t-micro);
  color: var(--ink-3);
}
.va-card__pct .r-metric__unit {
  font-size: 0.7em;
  margin-left: 1px;
}
.va-card .va-act { position: absolute; top: var(--s-3); left: var(--s-3); }
.va-card__stack {
  position: absolute;
  left: var(--s-3);
  bottom: var(--s-3);
  width: 14px;
  height: 10px;
  pointer-events: none;
}
.va-card__stack::before,
.va-card__stack::after {
  content: "";
  position: absolute;
  inset: 0;
  border: var(--stroke) solid var(--hairline-strong);
  border-radius: 2px;
  background: var(--surface);
}
.va-card__stack::before { transform: translate(2px, -2px); opacity: 0.55; }
.va-card__stack::after { transform: none; }

/* Hijos: colapsados, se abren debajo al hover/foco. */
.va-kids {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  pointer-events: none;
  transition: grid-template-rows var(--d-base) var(--ease-spring),
              opacity var(--d-base) var(--ease-spring);
}
.va-kids__in {
  overflow: hidden;
  min-height: 0;
  display: grid;
  gap: var(--s-2);
  padding-top: 0;
}
.va-cell:hover > .va-kids,
.va-cell:focus-within > .va-kids {
  grid-template-rows: 1fr;
  opacity: 1;
  pointer-events: auto;
}
.va-cell:hover > .va-kids .va-kids__in,
.va-cell:focus-within > .va-kids .va-kids__in {
  padding-top: var(--s-2);
}

/* ---------- + : cajitas al lado, no un menú (v0.1) ----------
   Una caja por tipo, a la izquierda del FAB. Motion del sistema.
   No es un popover-lista: son cuatro papeles sueltos. */
.va-cajas {
  position: absolute;
  z-index: 4;
  display: flex;
  flex-direction: row;
  align-items: stretch;
  gap: var(--s-2);
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  pointer-events: auto;
}
.va-cajas[hidden] { display: none; }
.va-caja {
  display: grid;
  place-items: center;
  min-width: 4.6rem;
  padding: var(--s-2) var(--s-3);
  font: inherit;
  font-size: var(--t-micro);
  letter-spacing: var(--tr-micro);
  color: var(--ink);
  cursor: pointer;
  text-align: center;
  line-height: var(--lh-snug);
}
.va-caja:hover, .va-caja:focus-visible { border-color: var(--hairline-strong); }
.va-cajas--in { animation: va-cajas-in var(--d-base) var(--ease-spring); }
.va-cajas--out { animation: va-cajas-out var(--d-base) var(--ease-spring) forwards; }
@keyframes va-cajas-in {
  from { opacity: 0; transform: translateX(8px) scale(0.94); }
  to   { opacity: 1; transform: none; }
}
@keyframes va-cajas-out {
  from { opacity: 1; transform: none; }
  to   { opacity: 0; transform: translateX(8px) scale(0.94); }
}
@media (prefers-reduced-motion: reduce) {
  .va-cajas--in, .va-cajas--out { animation: none; }
}

/* Tags + repos arriba de la tarjeta / de la hoja. */
.va-card__tags {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-1);
  max-width: calc(100% - var(--s-6));
  min-height: 18px;
}
.va-card__tags--hoja {
  max-width: 100%;
  margin-bottom: var(--s-3);
}
/* La perilla del componente conserva el compacto de escritorio. En móvil
   amplía el disparador real, no sólo el wrapper que abre otra acción. */
.va-card__tags .va-cap { display: inline-flex; --ctl-sm: 22px; --ico: 14px; }
.os-shell[data-os-mobile] .va-card__tags .va-cap { --ctl-sm: var(--orb-size); }
.va-tag--repo { max-width: 12ch; }

/* ---------- Detalle: cabecera, salud, Workspace ---------- */
.va-who {
  display: flex;
  align-items: baseline;
  gap: var(--s-3);
  margin-bottom: var(--s-4);
}
.va-who .va-name { margin-bottom: 0; flex: 1 1 auto; min-width: 0; }
.va-who__tipo { flex: 0 0 auto; }

.va-health {
  display: grid;
  gap: var(--s-2);
  margin-bottom: var(--s-5);
}
.va-track {
  display: grid;
  grid-template-columns: auto minmax(0, 7rem) minmax(0, 1fr) auto;
  gap: var(--s-2);
  align-items: center;
  width: 100%;
  margin: 0;
  padding: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  border-radius: var(--r-sm);
}
.va-track:hover .va-track__n,
.va-track:focus-visible .va-track__n { color: var(--ink); }
.va-track__n {
  font-size: var(--t-micro);
  color: var(--ink-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.va-track__bar {
  display: block;
  height: 4px;
  background: var(--hairline);
  border-radius: var(--r-pill);
  overflow: hidden;
}
.va-track__bar > i {
  display: block;
  height: 100%;
  background: var(--ink-2);
  border-radius: inherit;
}
.va-track__f { font-size: var(--t-micro); color: var(--ink-3); }

.va-wk { margin-bottom: var(--s-5); }
.va-wk__bar { margin-bottom: var(--s-3); align-items: center; }
.va-wk__filtro {
  max-width: 16ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: pointer;
}
.va-wk__ini {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.va-wk__board { --wk-col: 140px; }
.va-wk__blank { padding: var(--s-4) 0; }
.va-gantt { display: grid; gap: var(--s-2); }
.va-gantt__row {
  display: grid;
  grid-template-columns: minmax(0, 8rem) minmax(0, 1fr) auto;
  gap: var(--s-2);
  align-items: center;
}
.va-gantt__n {
  text-align: left;
  background: transparent;
  border: 0;
  padding: 0;
  color: inherit;
  font: inherit;
  cursor: pointer;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.va-gantt__kids {
  grid-column: 1 / -1;
  display: grid;
  gap: var(--s-1);
  padding-left: var(--s-3);
}
