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

   Dos medidas propias del módulo, declaradas aquí porque son
   geometría de layout y tienen un solo consumidor cada una (misma
   razón que --rel-halo en relations.css):
     --wk-lab   ancho de la columna de nombres del Gantt. La línea de
                "hoy" la vuelve a leer para caer en plomada con las
                pistas, así que un valor fijo repetido se desincroniza
                en cuanto cambia el breakpoint.
     --wk-col   ancho de una columna del tablero cuando las tres dejan
                de caber y el tablero pasa a scroll horizontal.

   ------------------------------------------------------------
   EL ANCHO QUE MANDA ES EL DEL PANEL, NO EL DE LA VENTANA

   Este módulo vivía en una página de 1240 y sus tres cortes eran
   `@media (max-width: …)`. Dentro del panel flotante eso quedó no
   solo inútil sino AL REVÉS: a 1280 de ventana ninguno dispara, así
   que las columnas del tablero se repartían los 578 px del panel
   cómodo y salían de 106 — una tarjeta de dos letras por renglón. El
   módulo se veía peor en el panel ancho que en un teléfono, porque
   en el teléfono los cortes sí disparaban.

   Los cortes son `@container` sobre `.wk`, que mide exactamente la
   caja que el panel le da (ancho del panel − 42 px de relleno). Con
   eso el mismo módulo se acomoda al arrastrar el canto del panel sin
   que la ventana cambie, que es el gesto nuevo del OS.

   Los dos cortes, medidos contra los anchos que declara el módulo:

     ≤ 620   CÓMODO (620 de panel → 578 de caja). La columna de
             nombres del Gantt baja de 200 a 168.
     ≤ 430   APRETADO. Es el modo que pide el encargo cuando el piso
             de la conversación gana y el panel queda por debajo de su
             mínimo. El mínimo declarado (480 → 438 de caja) cae del
             lado bueno del corte a propósito: un módulo no abre en su
             modo degradado. Aquí, y SOLO aquí, el tablero pasa a
             scroll horizontal.

   El tercer corte se fue con las cinco columnas: en ≤ 880 el tablero
   dejaba de caber y pasaba a scroll. Tres columnas caben en 552 de
   caja, o sea en todo el rango del panel, y por debajo de eso apretar
   las tres le gana a esconder una (el porqué está junto al corte).

   `container-type: inline-size` trae `contain: layout`, así que `.wk`
   se vuelve bloque contenedor de sus descendientes absolutos. Nada de
   lo que este módulo posiciona absoluto vive fuera de `.wk-tl__in` o
   de su propia caja, y la hoja de la tarea NO es descendiente de
   `.wk` (es su HERMANA dentro de la vista, ver más abajo), así que la
   contención no le llega.
   ============================================================ */

/* ------------------------------------------------------------
   LO QUE TIENE QUE CABER ES EL TABLERO, NO LA COLUMNA

   Medido con volumen realista (59 tareas, siete por columna más las de
   la semilla) el cuerpo del panel se pasaba **2,053 px a 1280×800,
   1,953 a 1440×900 y 1,845 a 2560×1000 con el panel en su techo de
   970**. O sea que no era una ventana chica: el tablero no cabía en
   ninguna pantalla, y el número casi no se movía con el ancho —2,474
   px de tablero a 626 de panel contra 2,466 a 970—. Eso dice qué NO
   era la causa: no es el envolvimiento del texto, es la CUENTA de
   tarjetas, que la pone Robbie y no tiene techo.

   De ahí sale la única unidad que se puede prometer: **el tablero
   cabe; cada columna se recorre por dentro.** Las tres cabeceras con
   su nombre y su cuenta están siempre a la vista, y ninguna columna
   puede quedar "abajo del pliegue" — que es lo que pasaba antes, con
   la última columna existiendo solo si scrolleabas.

   Pasar de cinco columnas a tres NO derogó esta regla, y es la parte
   que hay que tener escrita: el número de tarjetas no bajó, se
   REPARTIÓ en menos columnas, así que las dos que reciben señal
   («Por hacer» con lo bloqueado, «Listo» con lo que espera veredicto)
   piden MÁS alto que antes, no menos. Lo único que cambió a favor es
   el ancho.

   Las dos alternativas se descartaron con la regla en la mano:

     · Segmentar el tablero en secciones (dos columnas por sección)
       cambia scroll por clics —lo que el límite de `CLAUDE.md`
       prohíbe— y además rompe la función: un Kanban existe para
       comparar columnas de un golpe.
     · Topar la cantidad de tarjetas por columna esconde trabajo. Ya
       existe un tope y es el de "Listo" (`TOPE_LISTO`), que es una
       decisión de producto —Listo no es un archivo—, no una forma de
       hacer caber la vista.

   La cadena de flex es la misma de Relaciones y Growth: `.os-view` ya
   es item flex con `min-height: 0`, así que su alto es el del panel, y
   de ahí para abajo cada eslabón lo pasa. `container-type:
   inline-size` no contiene el alto, así que no estorba.
   ------------------------------------------------------------ */

.wk {
  --wk-lab: 200px;
  --wk-col: 176px;
  container-type: inline-size;
  container-name: wk;
  display: flex;
  flex-direction: column;
  min-height: 0;
}

/* En una columna flex TODO cede por omisión, y lo que cede se estruja sin
   avisar: un contenedor con `overflow` tiene mínimo automático 0 y se aplasta
   hasta desaparecer cuando el tablero empuja. Se declara al revés —nada cede,
   y quien crece lo pide por su nombre— igual que en `#relRoot` y `#gwRoot`.
   `:where` deja la especificidad en cero para que la regla de cada pieza le
   gane sin pelear. */
:where(.wk) > * { flex: 0 0 auto; }

/* ---------- Encabezado ---------- */

.wk-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s-6);
  margin-bottom: var(--s-6);
}
/* La métrica es un .r-lcdrow (flex), no un <p>: sin margen de párrafo que
   corregir, y el --s-2 que la separaba de su rótulo se fue con el rótulo. */
.wk-metric { margin: 0; }
.wk-stats {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  margin: 0;
}

/* ---------- Barra y lente ---------- */

/* ---------- La tira de revertir ----------
   Aparece donde acaba de quedar el hueco, entre la barra y el tablero, y se va
   sola cuando la cuenta llega a cero. Aquí el texto completo NO es clutter: es
   una acción irreversible y su única salida, que es justo la excepción que el
   sistema reserva para las palabras. Un solo renglón, el punto de estado en
   `warn` (señal, no acento) y la cuenta en cifra tabular para que el número no
   baile al bajar de 10 a 9. */
.wk-undo {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-height: 40px;
  padding: var(--s-2) var(--s-3);
  margin-bottom: var(--s-3);
  background: var(--surface-sunk);
  border: var(--stroke) solid var(--hairline);
  border-radius: var(--r-md);
  animation: os-in var(--d-base) var(--ease);
}
/* El texto de la tarea se recorta antes de empujar el botón: el rescate tiene
   que seguir alcanzable con una tarea de dos renglones. */
.wk-undo__t {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--ink-2);
}
.wk-undo > :last-child { flex: 0 0 auto; }

/* La barra, en dos renglones fijos y no en uno que envuelve.

   En un panel de 438–578 los siete controles de la barra vieja no caben en
   una línea, y dejarlos envolver reparte distinto en cada ancho: el botón de
   "tarea nueva" —la acción principal— caía unas veces al final del primer
   renglón y otras al principio del segundo. Dos renglones DECLARADOS se ven
   igual a todos los anchos, y el reparto dice qué es cada cosa:

     · arriba   qué estás mirando (Kanban/Gantt).
     · abajo    con qué lente, y las acciones DE la iniciativa puesta.

   Arriba llevaba también la acción principal —"tarea nueva"— y hoy no: se fue
   a la esquina del panel (`.r-fab`). Los dos renglones se quedan igual, porque
   el que envolvía era el de abajo. */
/* Ya no es una `.r-toolbar`: es el segmentado a secas. Ver la lápida en
   `tools()` (workspace.js) — una cápsula cuyo único hijo era otra cápsula.

   `align-self: start` es lo que hace verdad ese comentario. `.r-seg` es
   `inline-flex`, o sea que mide su contenido — pero desde que `.wk` es una
   columna flex (el arreglo del alto), sus hijos se estiran a lo ancho por
   omisión y el segmentado salía como una cápsula de 746 px con «Kanban» y
   «Gantt» apretados en la esquina izquierda: exactamente el control a medio
   pintar que la lápida decía haber quitado. Medido: 746 estirado contra 160
   midiendo su contenido. */
.wk-tools { margin-bottom: var(--s-2); align-self: start; }
/* LÁPIDAS de `.wk-tools__grow` y `.wk-tools__div`. El elástico empujaba el alta
   de una tarea al canto derecho del renglón; el alta se mudó a la esquina del
   panel (`.r-fab`) y un elástico sin nada detrás no separa nada. El divisor ya
   no tenía consumidores desde que la barra se partió en dos renglones. */

/* El renglón del lente. Envuelve, porque lo que trae depende de si hay
   iniciativa puesta: sin ella son dos controles y con ella cinco. */
.wk-lens {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  flex-wrap: wrap;
  margin-bottom: var(--s-5);
}
/* El selector se lleva el ancho sobrante del renglón. `min-width: 0` no es
   restilar nada: es la condición para que un elemento de flex ceda — sin él un
   nombre de iniciativa largo se niega a encoger y empuja el bote de borrar
   fuera del panel. El techo de 34ch existe para que con el panel arrastrado
   ancho el selector no se estire a lo tonto por todo el renglón. */
.wk-lens__sel { flex: 1 1 14ch; min-width: 0; max-width: 34ch; }
.wk-port {
  max-width: 18ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* La semilla de la próxima iniciativa: cuatro opciones, así que no es
   un `.r-seg`. Mide menos que el lente — no es lo que se consulta. */
.wk-lens__tpl { flex: 0 1 14ch; min-width: 0; max-width: 22ch; }

/* El árbol de la iniciativa puesta: épica, luego HU. Cada renglón es
   el mismo `.wk-lens` comprimido; el hueco entre ellos es el de la
   barra, no un segundo tablero. */
.wk-rama {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  margin-bottom: var(--s-5);
}
.wk-lens--rama { margin-bottom: 0; }

/* El anidado dentro de una columna: cabecera diminuta y las cartas
   de esa épica o HU. El hueco es el mismo que entre tarjetas sueltas,
   para que el nido no se lea como otro tablero. */
.wk-nido {
  display: grid;
  gap: var(--s-2);
  min-width: 0;
}
.wk-nido__h { margin: 0; }

/* Altas y renombrado: 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 para ser un flex item con caja propia dentro de
   la barra. La caja del flujo es la del disparador, 28×28, y no cambia al
   expandirse: por eso abrir un campo no reacomoda la barra ni el panel. */
.wk-cap { display: flex; flex: 0 0 auto; }

/* El + de Workspace: Iniciativa · Tarea. Misma trampa de popover que
   Intel — `display` solo en `:popover-open`, reset de UA. */
.wk-alta {
  position: fixed;
  inset: auto;
  margin: 0;
  padding: var(--s-1);
  width: max-content;
  max-width: min(260px, calc(100vw - var(--s-6)));
  min-width: 0;
  background: var(--theme-surface);
  color: var(--theme-ink);
  border: var(--stroke) solid var(--theme-hairline);
  border-radius: var(--r-md);
  box-shadow: var(--e-3);
}
.wk-alta:not(:popover-open) { display: none; }
.wk-alta:popover-open { display: grid; gap: var(--s-1); }
.wk-alta button[data-alta] {
  display: block;
  width: 100%;
  text-align: left;
  padding: var(--s-1) var(--s-3);
  background: transparent;
  border: 0;
  color: var(--ink);
  font: inherit;
  font-size: var(--t-body-sm);
  line-height: var(--lh-snug);
  cursor: pointer;
  border-radius: var(--r-sm);
}
.wk-alta button[data-alta]:hover { background: var(--surface-2); }
.wk-alta [data-wk-paso="ini"] {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  gap: var(--s-1);
  align-items: center;
}
.wk-alta [data-wk-paso="ini"][hidden] { display: none; }
.wk-alta [data-wk-paso="ini"] .r-input { min-width: 8rem; height: 30px; }
.wk-alta [data-wk-paso="ini"] .wk-selwrap { min-width: 0; }

/* ---------- LÁPIDA: el lente como pastillas ----------
   El lente era un `.r-tabs`: una pastilla por iniciativa más "Todas". Con la
   página de 1240 cabían; en el panel no, y no es cuestión de afinar un ancho
   —el número de pastillas lo pone el usuario, así que no hay ancho que
   alcance—. Medido en el panel cómodo (578): con las tres iniciativas de la
   semilla la cuarta pastilla salía cortada por el canto y no había manera de
   llegar a ella.

   `CLAUDE.md` ya tenía la respuesta y la frontera escrita: el segmentado a la
   vista se queda "cuando son dos o tres opciones y ver las alternativas es el
   punto". Un lente de N iniciativas no es ninguna de las dos cosas, así que es
   `.r-pick` — comprimido de entrada, expande al tocar. El Kanban/Gantt sí se
   queda segmentado, y por esa misma frontera: son dos y ver la alternativa es
   el punto.

   Lo que se perdió con las pastillas fue la ATENUACIÓN de una iniciativa
   cerrada (`.wk-lens__i[data-cerrada]`, opacidad 0.5). No se pierde el dato:
   `workspace.js` lo dice en la etiqueta de la opción, con palabras.

   LÁPIDA: `.wk-hint`. Era el renglón "⌥← ⌥→ mueve · ↩ abre" que se revelaba
   al enfocar el tablero. Robbie lo quitó, y el criterio se sostiene solo: los
   atajos ya viven en el `title` y en la etiqueta accesible de cada tarjeta,
   así que el renglón repetía lo que la pieza ya dice. */

/* ---------- Tablero ---------- */

/* El tablero se queda con el alto que le sobra al panel y no crece más: es la
   pieza que "pide crecer por su nombre". `align-items: stretch` en vez de
   `start` es la otra mitad —la columna tiene que medir el tablero para poder
   recorrerse por dentro— y de paso vuelve el destino de arrastre la columna
   entera y no solo el pedazo con tarjetas. */
.wk-board {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-3);
  align-items: stretch;
  flex: 1 1 auto;
  min-height: 0;
}

.wk-col {
  min-width: 0;
  display: flex;
  flex-direction: column;
  min-height: 0;
  border-radius: var(--r-md);
  border: var(--stroke) dashed transparent;
  transition: background var(--d-fast) var(--ease), border-color var(--d-fast) var(--ease);
}
/* Soltar aquí. El resalte lo pone el JS contra el puntero, no con
   dragenter/dragleave, para que no parpadee al pasar sobre las tarjetas. */
.wk-col--over {
  background: var(--idle-bg);
  border-color: var(--hairline-strong);
}

/* Las tres cabeceras miden lo mismo, y hacía falta decirlo: la de "Listo"
   reserva el alto del bote de limpiar (28 px, `.r-confirm--sm`) y las otras
   dos no tenían nada que reservar, así que quedaba 6 px más baja que sus
   vecinas y sus tarjetas arrancaban 6 px más abajo. Se veía poco cuando cada
   columna medía distinto; con el tablero estirado las tres cabeceras son un
   renglón y el ojo las compara. `--s-8` es el escalón que cubre el bote. */
.wk-col__h {
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-2);
  /* Las tres cabeceras miden lo mismo, y la reserva es el alto del bote de
     limpiar que solo tiene «Listo» (`.r-confirm--sm` = `--ctl-sm`) MÁS lo que
     la cabecera le suma por fuera. Eso último faltaba y por eso la reserva no
     servía: `min-height` mide la caja del borde, así que 28 px de mínimo con
     8 px de relleno abajo y un hairline dan una cabecera de 28 para las dos
     columnas sin bote y de 37 para la que lo tiene. Medido: 28 · 28 · 37, con
     las tarjetas de «Listo» arrancando 9 px más abajo que sus vecinas.

     Se veía poco cuando el tablero tenía cinco columnas angostas; con tres
     anchas las cabeceras son un renglón y el ojo compara los tres rótulos de
     un golpe. El bote sigue reservando su espacio aunque esté invisible —se
     revela al hover— así que la reserva tiene que estar puesta siempre. */
  min-height: calc(var(--ctl-sm) + var(--s-2) + var(--stroke));
  padding: 0 var(--s-2) var(--s-2);
  border-bottom: var(--stroke) solid var(--hairline);
}
.wk-col__n { font-size: var(--t-label); color: var(--ink-3); }

/* Limpiar las cerradas. Se revela al hover o al foco de la columna, como toda
   acción secundaria del OS: la cabecera arranca con el nombre y la cuenta, que
   es lo que se consulta. La caja del flujo es la del bote (28×28) y no cambia
   al expandirse —el panel de la pregunta va fuera de flujo— así que revelar no
   mueve la cuenta ni la columna. Sin `pointer-events` explícito no se podría
   tocar en táctil, donde no hay hover que lo devuelva; el bloque de
   `@media (hover: none)` de más abajo lo deja puesto. */
.wk-col__x {
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--d-fast) var(--ease);
}
.wk-col:hover .wk-col__x,
.wk-col:focus-within .wk-col__x { opacity: 1; pointer-events: auto; }

/* LA PILA DE TARJETAS ES LO QUE SE RECORRE, y por eso la cabecera de arriba
   —nombre, cuenta, bote de limpiar— se queda puesta: es lo que se consulta
   para saber qué hay en la columna, incluido lo que no cabe.

   `overscroll-behavior-y: contain` corta el encadenamiento: llegar al final de
   una columna no arrastra al panel ni a la página. Y no lleva `tabindex` como
   `.wk-tl__sc`, porque aquí no hace falta: las tarjetas ya son enfocables, así
   que recorrer con el teclado es tabular, y el navegador trae la enfocada a la
   vista solo.

   LÁPIDA de `min-height: var(--s-16)`. Estaba para que una columna vacía
   siguiera siendo un destino de arrastre: si midiera cero no habría dónde
   soltar. Ya no hace falta y no es un descuido — con el tablero estirado la
   pila mide el alto del tablero completo, o sea mucho más que 64 px, así que
   una columna vacía es hoy el destino MÁS grande, no el más chico. */
.wk-col__l {
  flex: 1 1 auto;
  min-height: 0;
  display: grid;
  gap: var(--s-2);
  align-content: start;
  padding: var(--s-2);
  overflow-y: auto;
  overscroll-behavior-y: contain;
  scrollbar-width: thin;
  /* El relleno del cuerpo del panel queda FUERA de esta pista, así que el
     último renglón se metería debajo del `.r-fab` y el clic se lo comería
     el alta. Encontrado por `pruebas/ui/test_traslape.py` el 2026-08-27.
     Ver `ron.css § 33d bis`. */
  padding-bottom: var(--fab-reserve);
}

/* ---------- Tarjeta ----------
   TRES BANDAS DECLARADAS, y el reparto viene de la maqueta de referencia:
   título (con el bote que se revela) · etiquetas · estado y fechas, más un pie
   que existe solo si hay algo que poner en él.

   LO QUE CAMBIÓ, Y NO COSTÓ ALTO. Las etiquetas —prioridad, iniciativa, tags—
   se revelaban al hover dentro de `.wk-card__m`, con su espacio YA reservado en
   `opacity: 0` para que la columna no saltara. Sacarlas a su propia banda es
   mover ese espacio, no pedir más: la altura que gana la banda la pierde el
   renglón de abajo, que deja de envolver.

   La regla de «la tarjeta arranca callada» no se derogó: sigue valiendo para las
   ACCIONES —el bote, el ✓, la ✗ siguen apareciendo al hover y al foco— y dejó
   de valer para el DATO, porque una etiqueta que hay que descubrir con el ratón
   no clasifica nada mientras se lee la columna.

   La prioridad se dice DOS veces y a propósito: con una regla en el canto
   (monocromo, sin gastar el ácido ni un semántico que aquí significa estado)
   para poder barrer la columna sin leer, y con su palabra en la banda de
   etiquetas para saber cuál es sin aprenderse el grosor. */

.wk-card {
  display: grid;
  gap: var(--s-2);
  padding: var(--s-3);
  background: var(--surface);
  border: var(--stroke) solid var(--hairline);
  border-left: var(--stroke-2) solid transparent;
  border-radius: var(--r-md);
  animation: os-slide-in var(--d-base) var(--ease-out) both;
  animation-delay: calc(var(--i, 0) * var(--stagger));
  transition: border-color var(--d-fast) var(--ease),
              background var(--d-fast) var(--ease),
              transform var(--d-fast) var(--ease);
}
.wk-card:hover { background: var(--surface-2); }
.wk-card:hover, .wk-card:focus-visible { border-color: var(--hairline-strong); }
.wk-card:active { transform: scale(0.99); }

.wk-card[data-p="alta"]  { border-left-color: var(--ink); }
.wk-card[data-p="media"] { border-left-color: var(--ink-4); }

/* ---------- La señal: un contorno, y de los semánticos ----------
   Bloqueada en `crit`, en revisión en `warn`. No es el ácido y no puede
   serlo: el acento es UNO por vista y ya está en la métrica de la cabeza. Un
   contorno de estado es exactamente el caso de uso de un semántico —señal,
   no acento— y de paso es la misma pareja de colores que estas dos tarjetas
   ya tenían cuando eran columnas propias, así que nadie tiene que reaprender
   nada.

   Va DESPUÉS de `[data-p]` y de `:hover` a propósito, con la misma
   especificidad: así la señal gana el canto izquierdo (la prioridad conserva
   el grosor y pierde el color, ver `tarjeta()` en el JS) y NO se apaga al
   pasar el ratón, que es cuando más falta hace saber qué se está tocando. */
.wk-card[data-senal="blocked"],
.wk-card[data-senal="blocked"]:hover,
.wk-card[data-senal="blocked"]:focus-visible { border-color: var(--crit); }
.wk-card[data-senal="review"],
.wk-card[data-senal="review"]:hover,
.wk-card[data-senal="review"]:focus-visible { border-color: var(--warn); }

/* ---------- La tercera señal: BORRADOR, y es la que NO es un semántico ----------
   Lo pidió Robbie «con un look más gris», y gris es exactamente lo contrario de
   una alarma: un borrador no urge, está esperando su ✓.

   Tres piezas, y ninguna inventa un color:

     · CONTORNO PUNTEADO en `--hairline-strong`. El punteado es el que hace el
       trabajo: dice «provisional» —la misma palabra que ya dicen el canto de
       `.r-stream` y la pastilla de `.wk-more`— y de paso vuelve las tres señales
       distinguibles por CLASE DE LÍNEA y no solo por color, que es lo que
       necesita quien no separa el rojo del ámbar.
     · PAPEL HUNDIDO (`--surface-sunk`). Es el mismo escalón que ya usan la
       ficha del agente y el bloque de revisión para «esto no es un campo, es
       algo que le pasa a la tarea». Aquí dice «esto todavía no es trabajo».
     · TÍTULO EN `--ink-2`, la tinta de lo que se lee de corrido, no la de lo que
       manda. Baja un escalón y NO más: `--ink-3` es la tinta de los rótulos y
       ahí el título de la tarjeta dejaría de leerse (el propio design system
       tiene anotado que `--ink-3` no llega a 3:1 en tema claro). Lo que se
       atenúa es la jerarquía, no la legibilidad.

   El punto de la palabra «Borrador» no se declara aquí: es `.r-status` SIN
   modificador, que el sistema pinta en `--idle` —el token que literalmente se
   llama «en reposo»—. Un color nuevo habría sido un token nuevo, y no hacía
   falta ninguno. */
.wk-card[data-senal="draft"],
.wk-card[data-senal="draft"]:hover,
.wk-card[data-senal="draft"]:focus-visible {
  border-style: dashed;
  border-color: var(--hairline-strong);
  background: var(--surface-sunk);
}
.wk-card[data-senal="draft"] .wk-card__t { color: var(--ink-2); }

/* ---------- Banda 1: el título y su bote ----------
   El bote no empuja el título: su caja es 28×28 y el panel de la pregunta vive
   fuera de flujo, así que armarlo no mueve un pixel de la tarjeta ni de la
   columna. Se revela al hover y al foco, como toda acción secundaria — y en la
   maqueta se veía en una sola de las cuatro tarjetas, que es este mismo patrón
   visto en una captura. */
.wk-card__h {
  display: flex;
  align-items: flex-start;
  gap: var(--s-2);
  min-width: 0;
}
/* Las dos acciones reveladas de la tarjeta: el bote, en el renglón del título,
   y el ✓/✗ al final de la banda de estado. Comparten regla porque comparten
   mecánica —y una sola definición de «se revela» es lo que evita que una de las
   dos se quede con la mitad, que es el error que ya se cometió una vez con el
   bote de limpiar las cerradas.

   `pointer-events` viaja con la opacidad, siempre: un control invisible que
   recibe clics es una trampa. El foco no se pierde —`pointer-events` no estorba
   al tabulador— y enfocarlo lo revela por `:focus-within`. */
.wk-card__x,
.wk-card__v {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--d-fast) var(--ease);
}
.wk-card:hover .wk-card__x, .wk-card:hover .wk-card__v,
.wk-card:focus-visible .wk-card__x, .wk-card:focus-visible .wk-card__v,
.wk-card:focus-within .wk-card__x, .wk-card:focus-within .wk-card__v {
  opacity: 1;
  pointer-events: auto;
}
/* El ✓ es el gesto que cierra o que acepta, así que se tiñe al tocarlo. `--ok`
   es señal y no acento, igual que el contorno de al lado. */
.wk-card__ok:hover, .wk-card__ok:focus-visible { color: var(--ok); }

/* ---------- Banda 2: las etiquetas, a la vista ----------
   Un renglón que envuelve. `--s-1` de hueco vertical para que dos renglones de
   etiquetas no se lean como dos bandas distintas. */
.wk-card__tags {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s-1) var(--s-2);
  margin: 0;
  min-width: 0;
}

/* La pastilla de etiqueta. NO es `.r-chip` (26 px de alto, pensada para un
   renglón de controles): en una tarjeta de tablero eso son tres renglones de
   pastillas donde caben dos de contenido. Misma familia —radio de píldora,
   papel hundido, `--t-micro`— a la escala de la tarjeta.

   MONOCROMA, Y ES LA DECISIÓN QUE MÁS PESA. La maqueta las pinta de color: rojo
   sobre rosa para el tipo, azul sobre azul pálido para una mejora, rojo para la
   prioridad alta. Aquí no, por dos reglas que dicen lo mismo desde dos lados:
   «un solo acento por vista» —y el de esta vista ya lo gastó la métrica de la
   cabeza— y «los semánticos son señal, no acento». Un tag de tipo o de prioridad
   NO es una señal: no urge, no pide nada, no cambia. Pintarlo de rojo
   permanente le enseña al ojo a ignorar el rojo, y entonces la tarjeta bloqueada
   —que sí urge— deja de gritar. Los tres semánticos que este tablero gasta
   (`crit` bloqueada, `warn` en revisión, `ok` cerrada) se quedan donde están. */
.wk-tag {
  /* `inline-block` y NO `inline-flex`, y es la diferencia entre recortar bien y
     recortar a media letra: `text-overflow: ellipsis` no aplica al texto suelto
     dentro de un contenedor flex —se vuelve un item anónimo— así que la
     iniciativa larga se cortaba a la mitad de un glifo, sin puntos, y parecía un
     error de datos. Medido en la columna angosta: «PILOTO ILUSTF». El alto sale
     de la interlínea más el hairline, no de una altura fija. */
  display: inline-block;
  line-height: 16px;
  padding: 0 var(--s-2);
  border-radius: var(--r-pill);
  background: var(--surface-sunk);
  border: var(--stroke) solid var(--hairline);
  color: var(--ink-2);
  font-size: var(--t-micro);
  letter-spacing: var(--tr-micro);
  white-space: nowrap;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* La prioridad, monocroma y por PESO: alta en tinta plena, media y baja
   atenuadas. Es la misma jerarquía que ya dice la regla del canto, dicha con la
   herramienta que el sistema sí permite gastar dos veces —tinta y espacio— en
   vez de con un color. */
.wk-tag[data-p="alta"]  { color: var(--ink); border-color: var(--hairline-strong); }
.wk-tag[data-p="media"] { color: var(--ink-2); }
.wk-tag[data-p="baja"]  { color: var(--ink-3); }
/* La iniciativa es el agrupador («sprint» en la maqueta): versalitas, como el
   rótulo de una sección, porque es de qué trabajo es esto y no un adjetivo. */
.wk-tag--ini {
  text-transform: uppercase;
  font-weight: var(--fw-medium);
  background: transparent;
  /* Es la pastilla más larga de la banda —la escribe Robbie y no tiene tope— y
     sin techo se lleva un renglón entero para ella sola. 14ch recorta con
     elipsis y el nombre completo se queda en el `title` de la tarjeta. */
  max-width: 14ch;
}
/* Un tag lleva su gato pegado y no como carácter aparte: así no se puede
   separar del nombre al envolver. */
.wk-tag--t::before { content: "#"; color: var(--ink-3); }

.wk-card__t {
  margin: 0;
  font-size: var(--t-body-sm);
  line-height: var(--lh-body);
  letter-spacing: var(--tr-tight);
  color: var(--ink);
  /* Un texto larguísimo se recorta a tres renglones: la columna no se
     estira y el completo sigue disponible en el title. */
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
}
/* ---------- Banda 3: el estado y las fechas ----------
   Reserva su alto aquí para que la tarjeta mida igual con y sin urgencia, y la
   columna no salte al revelar el ✓. El ✓/✗ se empuja al final con `margin-left:
   auto` en vez de un elástico: así el hueco existe siempre y no aparece al
   revelarse.

   `min-width: 0` es el eslabón que faltaba de la cadena de truncado. Como es a
   la vez contenedor flex y elemento de la retícula de la tarjeta, arrastra
   `min-width: auto` y propaga hacia arriba el ancho mínimo de sus nietos con
   `white-space: nowrap`. El nombre de una iniciativa larga estiraba la columna
   hasta sacar el documento 30 px del viewport, y la elipsis que ya estaba
   escrita nunca llegaba a activarse. */
.wk-card__b {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s-2);
  min-height: var(--ctl-sm);
}
/* La celda del contenido: aquí sí envuelve, y envolver aquí no cuesta un
   renglón vacío porque no hay ningún control de 28 px en la fila. */
.wk-card__bi {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s-1) var(--s-3);
  min-width: 0;
}
.wk-card__u { flex: 0 0 auto; white-space: nowrap; }
.wk-card__s { flex: 0 0 auto; white-space: nowrap; }

/* El rango de fechas. En cifra tabular para que dos tarjetas seguidas alineen
   los días, y en tinta terciaria: es contexto, no la señal. */
.wk-card__r {
  flex: 0 1 auto;
  min-width: 0;
  font-size: var(--t-micro);
  color: var(--ink-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---------- Banda 4: el pie ----------
   Existe solo si hay algo que poner: a qué agente está delegada, cuántas veces
   volvió de revisión, cuántos adjuntos y cuántos comentarios. Es la cuarta banda
   de la maqueta —el avatar de quien la trabaja, el clip y el globo— y ahora sí
   está completa: los dos contadores llegaron con los campos que los sostienen.

   LÁPIDA de «el vínculo al merge request y los adjuntos no existen». Los
   adjuntos existen; el vínculo del PR existe y NO va aquí, por decisión: una URL
   es un renglón que nadie barre de un vistazo, así que vive en la hoja.

   El hairline lo separa de las fechas. Es lo mismo que hace la maqueta con una
   línea, y la regla del sistema es «hairline antes que sombra». */
.wk-card__f {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s-2) var(--s-3);
  min-width: 0;
  padding-top: var(--s-2);
  border-top: var(--stroke) solid var(--hairline);
  font-size: var(--t-micro);
  color: var(--ink-3);
}

/* Delegada a un agente. La palabra "delegada" está en el `title` de la tarjeta,
   así que aquí basta el icono y el nombre.

   El tamaño del icono se declara AQUÍ, sobre el contenedor: `--ico` es la
   variable del sistema y se hereda, así que este módulo consigue un icono de
   13px sin escribir una sola regla con prefijo `.r-`. */
/* El punto que late sustituye al rayo cuando hay una sesión corriendo: no se
   suman, se reemplazan. Dos marcas para el mismo dato en un pie de 176 px son
   dos pixeles peleándose, y de los dos el que dice algo que cambia es el punto.
   `gap: 0` en la pastilla porque `.r-status` ya trae el suyo entre punto y
   texto, y aquí el texto es el hermano de al lado. */
.wk-card__vivo { gap: 0; }

.wk-card__d {
  --ico: 13px;
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Cuántas veces volvió de revisión. Es lo más cerca que este OS está del globo
   de comentarios de la maqueta, y no es una traducción floja: `reviews` es
   literalmente el hilo de lo que se dijo al regresar la tarea. El número no
   compite —tinta terciaria, cifra tabular— pero está, porque es el dato que
   dice «esto ya se intentó» sin abrir la hoja. */
.wk-card__no {
  --ico: 13px;
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  flex: 0 0 auto;
}
/* Los otros dos contadores del pie: adjuntos y comentarios. Mismo dibujo que el
   de regresadas —icono de 13px, cifra tabular, tinta terciaria— porque son la
   misma clase de dato: cuántos hay de algo que se lee en la hoja. Que sean tres
   reglas y no una es lo que dejaría distinguirlos si algún día uno tiene que
   gritar; hoy ninguno grita, y eso es correcto: un contador no urge.
   SOLO SE DIBUJAN SI HAY (lo decide el JS): un cero es decoración. */
.wk-card__c {
  --ico: 13px;
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  flex: 0 0 auto;
}

/* Mientras viaja, la tarjeta se atenúa en su lugar de origen. */
.wk-card--drag { opacity: 0.4; }

/* Y al aterrizar se ve dónde cayó: sin esto, mover con el teclado no
   deja rastro y se siente como que no pasó nada. */
@keyframes wk-land {
  from { transform: scale(0.96); border-color: var(--ink-3); }
}
.wk-card[data-movido] {
  animation: wk-land var(--d-slow) var(--ease-spring) both;
}

/* Repintado sin novedad (mover, cambiar una fecha): nada entra, porque
   nada es nuevo. Solo se anima lo que aterrizó. La marca la pone
   workspace.js comparando qué tareas hay contra el repintado anterior. */
.wk--quieto .wk-card:not([data-movido]),
.wk--quieto .wk-grow,
.wk--quieto .wk-trow { animation: none; }

/* Listo no es un archivo: más allá del tope se pide. */
.wk-more {
  justify-self: start;
  height: 26px;
  padding-inline: var(--s-3);
  border: var(--stroke) dashed var(--hairline-strong);
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--ink-3);
  font-family: inherit;
  font-size: var(--t-label);
  transition: color var(--d-fast) var(--ease), border-color var(--d-fast) var(--ease);
}
.wk-more:hover, .wk-more:focus-visible { color: var(--ink); border-color: var(--ink-4); }

.wk-blank {
  padding: var(--s-16) var(--s-4);
  text-align: center;
  display: grid;
  gap: var(--s-3);
  justify-items: center;
}

/* ============================================================
   Gantt — la línea de tiempo con lupa

   Cada renglón es la misma retícula de dos columnas (nombre + pista),
   así que todo cae en plomada sin medir nada.

   Lo que cambió respecto del eje viejo: las posiciones YA NO son
   porcentajes. El eje es un ojo de pez y su mapeo no es lineal, así
   que no hay una fracción que el navegador pueda resolver solo — las
   calcula `workspace.js` contra el ancho medido y las escribe como
   `--x` / `--w` en píxeles. De ahí sale la regla de este bloque:

     · La GEOMETRÍA (dónde y cuánto mide) la escribe el JS.
     · El LENGUAJE (color, grosor, hueco o lleno, hover) vive aquí.

   Nada de esto se dibuja sin caja: el JS observa con ResizeObserver y
   no pinta hasta que la hay.
   ============================================================ */

/* El Gantt es la otra pieza que "pide crecer": se queda con el alto que le
   sobra al panel y la bandeja de abajo cede lo suyo. */
.wk-tl {
  position: relative;
  flex: 1 1 auto;
  min-height: 0;
  display: flex;
  flex-direction: column;
  border-top: var(--stroke) solid var(--hairline);
}

/* La región que se recorre. El vertical es de la lista y el horizontal
   del eje: `contain` corta el encadenamiento para que llegar al final
   de los renglones no arrastre la página.

   EL TECHO ERA `52vh` Y ESO MEDÍA LA VENTANA, que es exactamente el error que
   la cabecera de este archivo documenta para el eje horizontal: dentro del
   panel la ventana miente. En el eje vertical mentía distinto pero igual de
   feo —52 % de 800 px son 416, y el panel le dejaba 247— así que el cuerpo del
   panel se pasaba 169 px a 1280×800, 87 a 1440×900 y 39 a 2560×1000. Hoy el
   alto sale de la caja: `flex` toma lo que sobra y `--s-16` es el piso por
   debajo del cual la línea deja de ser una línea. */
.wk-tl__sc {
  flex: 1 1 auto;
  min-height: var(--s-16);
  overflow-y: auto;
  overscroll-behavior-y: contain;
  scrollbar-width: thin;
}
.wk-tl__sc:focus-visible {
  outline: var(--stroke-2) solid var(--accent-ink);
  outline-offset: var(--s-1);
  border-radius: var(--r-sm);
}

/* El encabezado de fechas se queda: un Gantt donde las fechas se van con
   el scroll deja de decir dónde está cada barra. Papel translúcido y no
   opaco, que es la postura del sistema — recoge el color de atrás en vez
   de taparlo. El estrato es interno de la pieza, no de la escala. */
.wk-tl__head {
  position: sticky;
  top: 0;
  z-index: 1;
  display: grid;
  grid-template-columns: var(--wk-lab) minmax(0, 1fr);
  gap: var(--s-4);
  align-items: end;
  padding-bottom: var(--s-1);
  background: var(--surface-frost);
  backdrop-filter: blur(var(--frost-blur));
  border-bottom: var(--stroke) solid var(--hairline);
}
.wk-tl__gut { display: flex; justify-content: flex-end; padding-bottom: var(--s-1); }
.wk-tl__dates { min-width: 0; }
.wk-tl__fechas { display: block; width: 100%; }

/* Las fechas. Cifras tabulares para que el renglón no baile al recorrer,
   y el día de la semana en la misma tinta secundaria que el resto de lo
   que se lee de corrido. */
.wk-tl__d, .wk-tl__w {
  font-family: var(--font-sans);
  font-size: var(--t-micro);
  font-variant-numeric: tabular-nums;
}
.wk-tl__d { fill: var(--ink-2); }
.wk-tl__w { fill: var(--ink-3); }

/* HOY: el cuadro que remata su regla. Es la marca que sobrevive a la
   compresión —no depende de la escala— y la única tinta llena del
   encabezado. Cuadrada, como todo punto de estado del sistema. */
.wk-tl__hoy { fill: var(--ink); }

.wk-tl__in { position: relative; padding-top: var(--s-2); }

/* La retícula, un solo <path>. Se estira en vertical a propósito: sus
   líneas son verticales, así que deformar el eje Y no deforma nada, y
   `non-scaling-stroke` deja el grosor donde el sistema lo declaró. */
/* Ancho y alto EXPLÍCITOS, y las dos veces por la misma razón: un `<svg>` sin
   atributos trae `width: 100%; height: 100%` de fábrica, así que los `inset`
   no lo gobiernan. Costó dos síntomas distintos y feos: con `height` de fábrica
   la retícula medía 100px sobre un cuerpo de 368 y las líneas se cortaban a la
   altura del primer grupo; con `width` de fábrica medía el ancho ENTERO —columna
   de nombres incluida— mientras su viewBox era el de la pista, y el eje salía
   estirado un 23%: la regla de hoy caía dos días a la derecha de su fecha. */
.wk-tl__grid {
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(var(--wk-lab) + var(--s-4));
  width: calc(100% - var(--wk-lab) - var(--s-4));
  height: 100%;
  pointer-events: none;
}
.wk-tl__g { fill: none; stroke: var(--trace); stroke-width: var(--stroke); }
/* La regla de hoy: la ÚNICA línea del campo que no es trama. */
.wk-tl__n { fill: none; stroke: var(--ink); stroke-width: var(--stroke-2); }

/* El botón de volver a hoy vive comprimido: solo aparece cuando hoy se
   salió de la zona expandida, que es cuando sirve. */
.wk-hoy {
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--d-fast) var(--ease);
}
.wk-tl--lejos .wk-hoy { opacity: 1; pointer-events: auto; }

.wk-grow, .wk-trow {
  position: relative;
  display: grid;
  grid-template-columns: var(--wk-lab) minmax(0, 1fr);
  gap: var(--s-4);
  align-items: center;
  animation: os-slide-in var(--d-base) var(--ease-out) both;
  animation-delay: calc(var(--i, 0) * var(--stagger));
}
.wk-grow { margin-top: var(--s-4); }

/* Los dos nombres del Gantt —el de la iniciativa y el de la tarea— dejan de
   recortarse a UN renglón con elipsis y se parten en DOS. En una columna de
   200 px un nombre de iniciativa cabía; en la de 116 del modo apretado
   cualquier nombre se volvía tres palabras y puntos suspensivos, o sea una
   fila que no se puede leer. Dos renglones y elipsis al final del segundo es
   el mismo trato que ya hace `.r-radar` con sus etiquetas: primero partir,
   recortar solo si ni así cabe. El nombre completo sigue en el `title`. */
.wk-glab, .wk-tlab {
  min-width: 0;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  overflow-wrap: anywhere;
}

.wk-glab { color: var(--ink); }

.wk-plot {
  position: relative;
  min-width: 0;
  height: var(--s-6);
}

/* Barra de la iniciativa: del hito más temprano al más tardío. Sin color de
   estado a propósito — una iniciativa no tiene uno, y teñirla competiría con
   las tareas que sí lo dicen. */
.wk-span {
  position: absolute;
  top: 50%;
  left: 0;
  width: var(--w, 0);
  height: var(--s-2);
  translate: var(--x, 0) -50%;
  border-radius: var(--r-pill);
  background: var(--surface-sunk);
  border: var(--stroke) solid var(--hairline-strong);
}

.wk-tlab {
  padding-left: var(--s-3);
  font-size: var(--t-body-sm);
  line-height: var(--lh-snug);
  color: var(--ink-2);
}

/* ---------- La barra y el hito ----------
   Mismo dibujo, misma escala de color, y la geometría en `--x` / `--w`.

   EL MÍNIMO ES EL HITO, y lo pone el JS: comprimido, un día mide medio
   píxel, y media raya no significa nada mientras que el cuadro sí — es
   el glifo que en esta línea ya quiere decir "un día". */
.wk-bar, .wk-mile {
  position: absolute;
  top: 50%;
  left: 0;
  width: var(--w, 9px);
  height: 9px;
  padding: 0;
  translate: var(--x, 0) -50%;
  border: var(--stroke-2) solid var(--ink-3);
  border-radius: 1px;
  background: transparent;
  transition: scale var(--d-fast) var(--ease), background var(--d-fast) var(--ease);
}
.wk-mile { width: 9px; }
/* Solo en el eje corto: escalar el largo movería los extremos, que son el dato.
   El hito no tiene largo que perder, así que crece parejo. */
.wk-bar:hover, .wk-bar:focus-visible { scale: 1 1.6; }
.wk-mile:hover, .wk-mile:focus-visible { scale: 1.35; }

/* ---------- El color de estado, y la jerarquía que lo salva del confeti ----------

   La regla que ordena el campo NO es el color, es RELLENO vs. CONTORNO:

     contorno neutro  →  todo      no ha empezado
     relleno de color →  doing / review / blocked   está en vuelo
     contorno `ok`    →  done      cerrada

   `todo` va hueca y en `--ink-3` a propósito, y esto se corrigió MIDIENDO: con
   relleno de tinta era la pieza más fuerte del campo —en cockpit, una barra
   blanca llena le gana a cualquier color— así que el estado por DEFECTO, que
   además es el más numeroso, era el que más gritaba. Ahora lo que grita es lo
   que ya empezó, que es justo la tesis del módulo y el dato que carga la
   métrica de arriba.

   Con eso el relleno de color queda reservado a tres estados que son minoría
   por definición, y `ok` —el que se acumula con el tiempo— vive en contorno,
   que es lo que evita que el tablero se vuelva verde solo. */
.wk-bar--doing,   .wk-mile--doing   { background: var(--info); border-color: var(--info); }
.wk-bar--review,  .wk-mile--review  { background: var(--warn); border-color: var(--warn); }
.wk-bar--blocked, .wk-mile--blocked { background: var(--crit); border-color: var(--crit); }
.wk-bar--done, .wk-mile--done { background: transparent; border-color: var(--ok); }

/* La cola del retraso: de donde la tarea acabó hasta hoy. Punteada y del mismo
   tono que la tarea — el retraso ya no gasta un color, porque en un Gantt la
   posición ES la fecha y el color de `crit` queda para decir una sola cosa,
   bloqueada. `--dash-sm` y no `--map-dash`: el trazo es corto y el punteado
   largo dejaría de leerse como punteado. */
.wk-over {
  position: absolute;
  top: 50%;
  left: 0;
  width: var(--w, 0);
  height: 0;
  translate: var(--x, 0) -50%;
  border-top: var(--stroke-2) dashed var(--ink-3);
  opacity: 0.55;
  pointer-events: none;
}
.wk-over--doing   { border-top-color: var(--info); }
.wk-over--review  { border-top-color: var(--warn); }
.wk-over--blocked { border-top-color: var(--crit); }

/* El galón del canto: la tarea quedó fuera de la ventana y esto dice para qué
   lado. Un renglón con nombre y con la pista vacía se lee como un error del
   programa; con el galón se lee como "está más allá", y al tocarlo lleva la
   vista hasta ella. */
.wk-off {
  position: absolute;
  top: 50%;
  translate: 0 -50%;
  display: grid;
  place-items: center;
  width: var(--s-5);
  height: var(--s-5);
  padding: 0;
  border: 0;
  background: none;
  color: var(--ink-3);
  transition: color var(--d-fast) var(--ease);
}
.wk-off:hover, .wk-off:focus-visible { color: var(--ink); }
.wk-off[data-dir="a"] { left: 0; }
.wk-off[data-dir="a"] .r-ico { scale: -1 1; }
.wk-off[data-dir="b"] { right: 0; }
.wk-off .r-ico { width: 14px; height: 14px; }

/* Bandeja de lo que no tiene fecha. No se dibuja en la línea: una fecha
   inventada se lee como compromiso. */
/* NO CEDE, Y SE TOPA. Las dos mitades salieron de medir el intento anterior:
   con `shrink: 1` el reparto del flex es proporcional a lo que mide cada uno,
   así que la línea (1,899 px) se llevaba el 93 % del estrujón y la bandeja
   pasaba de 141 px a 40 — o sea el rótulo con la cuenta y las pastillas
   aplastadas a nada. Una bandeja que dice "12 sin fecha" y no deja tocar
   ninguna es peor que no tenerla.

   Así que la bandeja se queda entera y quien cede es la línea, que ya tiene su
   piso (`--s-16`). Lo que la bandeja no puede es crecer sin freno: veinte
   pastillas envueltas en una columna angosta son media pantalla, así que las
   pastillas se topan en tres renglones y se recorren. El rótulo con la cuenta
   nunca se va: es lo que se consulta. */
.wk-tray {
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  min-height: 0;
  margin-top: var(--s-8);
  padding-top: var(--s-4);
  border-top: var(--stroke) solid var(--hairline);
}
.wk-tray__l {
  max-height: calc(var(--s-12) * 2);
  display: flex;
  align-items: center;
  align-content: flex-start;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-top: var(--s-3);
  overflow-y: auto;
  overscroll-behavior-y: contain;
  scrollbar-width: thin;
}
.wk-pill {
  max-width: 32ch;
  overflow: hidden;
  text-overflow: ellipsis;
  font-family: inherit;
  transition: border-color var(--d-fast) var(--ease);
}
.wk-pill:hover, .wk-pill:focus-visible { border-color: var(--ink-4); }

/* ============================================================
   La hoja de la tarea — la SEGUNDA PÁGINA del panel
   ============================================================ */

/* ---------- LÁPIDA: el velo ----------
   `.wk-scrim` cubría la ventana entera y atenuaba el OS de atrás mientras se
   editaba una tarea. Existía para una hoja que entraba desde el canto DERECHO
   DE LA VENTANA por encima de la página del módulo.

   Hoy la hoja es la segunda página de su panel, así que detrás de ella no
   queda nada del módulo que atenuar — y lo único que el velo alcanzaría a
   cubrir es la CONVERSACIÓN, que es justo lo que no se puede tocar: el centro
   es el piso del OS, sigue vivo con el panel abierto, y el gesto que el
   rediseño viene a habilitar es tener una tarea enfrente y preguntarle al
   agente sobre ella. Un velo encima de la conversación apagaría eso.

   No se pierde "tocar fuera cierra": eso nunca lo hizo el velo, lo hace el
   `pointerdown` en captura de `workspace.js`, que sigue igual. */

/* ---------- La hoja de la tarea, DENTRO de la VISTA ----------
   Se monta como hermana del tablero dentro de `#viewWork`, y es un item de
   flujo: cero `position`, cero `z-index`, cero geometría copiada. Es el
   patrón de la ficha de persona de Relaciones y de la nota de Intelligence
   — las tres segundas páginas del OS son la misma pieza.

   Pasó por dos casas antes de esta y las dos se pagaron:

     · `<body>`, hoja `fixed` de 460 px pegada al canto derecho de la VENTANA,
       corrida por `--os-rail-r`. Ahí tapaba la conversación.
     · `.r-flyout` con `absolute; inset: 0` y `--z-panel`: medía el panel sin
       leer `--flyout-w`, que era el punto, pero se ponía ENCIMA de su
       cabecera y de su manija. Medido: con una tarea abierta,
       `elementFromPoint` sobre el centro de la manija contestaba
       `.wk-side__body` —la manija está en `z-index: 2` y la hoja estaba en
       60— así que el panel no se podía redimensionar, y mientras durara la
       tarea desaparecían el nombre del módulo y su ×. `--z-panel` es un
       estrato GLOBAL: dentro del contexto de apilamiento que crea otro
       componente no dice nada, solo gana.

   Como item de flujo lo gana todo sin declararlo: mide el panel porque su
   padre lo mide, sigue el arrastre porque el ancho lo da el padre, y se
   esconde con la vista sin código. */

/* ---------- Entrar Y SALIR ----------
   El panel entraba animado y se iba de golpe: `hidden` lo saca del layout en el
   mismo cuadro y no queda nada que transicionar. El modelo para arreglarlo ya
   existía en el sistema —`.r-pick__list` y `.r-capture__panel`—: transicionar
   `display` con `allow-discrete` mantiene la caja viva mientras la opacidad y
   el desplazamiento corren, y `@starting-style` da el estado DESDE el que se
   entra. Con eso la entrada deja de ser `@keyframes` y pasa a ser la misma
   transición al revés: ida y vuelta se declaran una sola vez y no se pueden
   desincronizar.

   Dos diferencias con el modelo de `ron.css`, y las dos a propósito:

   · SIN `overlay`. Esa propiedad solo existe para lo que vive en la CAPA
     SUPERIOR (`popover`, `dialog`), que es el caso de las dos piezas del
     sistema. El panel es un elemento normal con `z-index`: no hay capa
     superior que retener, así que `overlay` no tendría nada que hacer.
   · EL ESTADO CERRADO ES `[hidden]`, no `:popover-open` al revés. Quien apaga
     el panel es `display: none !important` de `os.css`, y la transición lo
     sostiene mientras dura porque en el orden de la cascada las transiciones
     van por encima de las declaraciones `!important` de autor.

   Y la trampa que documenta `ron.css` no aplica aquí, pero conviene decir por
   qué: prohíbe declarar `display` en la regla base de un elemento con
   `popover`, porque le ganaría al `[popover]:not(:popover-open){display:none}`
   del navegador y el panel se quedaría con caja real. Estos dos no son
   `popover` y su apagador lleva `!important`, así que `display` en la base es
   justo lo que hace falta: es el valor al que se vuelve al abrir. */

/* La vista, con sus dos páginas. Con la tarea abierta el tablero no está
   debajo: no está. Es `:has` y no una bandera en el JS a propósito — una sola
   fuente de verdad, el `hidden` de la hoja, y nada que se pueda
   desincronizar. La cadena de flex es lo que le deja a la hoja llenar el panel
   sin posicionarse. */
/* ---------- EL ALTO SE DICE, NO SE HEREDA ----------
   `height: 100%` es el eslabón que hacía falta y hay que saber POR QUÉ, porque
   no es decoración y quitarlo devuelve el bug entero.

   El cuerpo del panel declara `.r-flyout[data-flyout-fab] .r-flyout__body > * {
   flex-shrink: 0 }` (ron.css § 33d) y tiene razón: un hijo que cede saca su
   contenido del flujo del scroll y el relleno del `.r-fab` deja de ser lo
   último. Workspace SÍ declara alta, así que esa regla le aplica: la vista mide
   su contenido y no cede un píxel. Con eso, `flex: 1 1 auto` en `.wk` no
   reparte nada —el alto que reparte es el del contenido, o sea el mismo que
   sobra— y el tablero seguía midiendo 2,474 px con la caja adentro sin recortar.
   MEDIDO tras poner la cadena de flex y ANTES de esta línea: el cuerpo se pasaba
   los mismos 2,053 px y el Gantt EMPEORÓ a 1,651, porque `.wk-tl` pasó de
   toparse en `52vh` a crecer con su contenido.

   La salida no es pelearle a `flex-shrink` desde el consumidor —un `#id` le
   gana por especificidad y es justo lo que este proyecto no hace—: es decirle a
   la vista cuánto mide. `flex-basis: auto` lee la propiedad `height`, así que
   con `100%` el tamaño hipotético ES el del cuerpo y ya no hay nada que
   estrujar. `flex-shrink: 0` se queda intacto y el relleno del alta sigue
   siendo lo último. */
#viewWork {
  display: flex;
  flex-direction: column;
  min-height: 0;
  height: 100%;
}
#viewWork > .wk { flex: 1 1 auto; min-height: 0; }
#viewWork:has(> .wk-side:not([hidden])) > .wk { display: none; }

.wk-side {
  /* La tercera medida propia del módulo, y va AQUÍ y no en `.wk`: la hoja es
     HERMANA del tablero, no su hija, así que una variable declarada en `.wk` no
     le llega. Es el ancho de la columna de rótulos de la ficha — plomada, no
     ancho de contenido (ver `.wk-f--row`). */
  --wk-lbl: 88px;
  flex: 1 1 auto;
  min-height: 0;
  container-type: inline-size;
  container-name: wkside;
  display: flex;
  flex-direction: column;
  opacity: 1;
  translate: 0 0;
  /* Sale más rápido de lo que entra, y con la curva sin rebote: el resorte es
     bienvenido cuando algo llega, no cuando se va. */
  transition: opacity var(--d-base) var(--ease),
              translate var(--d-slow) var(--ease-spring),
              display var(--d-slow) var(--ease-spring) allow-discrete;
}
.wk-side[hidden] {
  opacity: 0;
  translate: 0 var(--s-2);
  transition: opacity var(--d-base) var(--ease),
              translate var(--d-base) var(--ease-out),
              display var(--d-base) var(--ease-out) allow-discrete;
}
@starting-style {
  .wk-side:not([hidden]) { opacity: 0; translate: 0 var(--s-2); }
}
/* EL RECORRIDO ES VERTICAL, y es una corrección medida. Fue horizontal
   —primero --s-16, luego --s-8— de cuando la hoja entraba desde el canto de
   una ventana. Como segunda página del panel eso son píxeles de ancho que no
   existen: el cuerpo del panel es `overflow-x: hidden`, así que no se ven,
   pero quedan como DESBORDE SCROLLEABLE mientras dura la animación (medido a
   1440: 12 px de `scrollWidth` de más en `.r-flyout__body`, con la hoja
   sobresaliendo 11 px del canto derecho del panel) en un OS que no tiene
   scroll horizontal en ningún lado. Es el mismo hallazgo que ya había
   corregido `.rel-side`, y ahora las tres entran igual: hacia arriba y con
   opacidad, la forma de "algo entra" del sistema (`os-slide-in`, os.css). */

/* LÁPIDA DEL PAPEL OPACO. `.wk-side` traía `background: var(--surface)` con el
   argumento de que una segunda capa translúcida sobre el mismo color recogería
   lo mismo dos veces. Era correcto cuando la hoja TAPABA el panel; como
   segunda página del panel no hay nada que despegar: el papel es el del
   flotante, el mismo sobre el que leen los otros seis módulos, y un rectángulo
   opaco adentro de un panel de vidrio se lee como un parche, no como papel. */

/* Ya no es la cabecera de una caja aparte: es el renglón que devuelve al
   tablero y ofrece el bote. Sin alto fijo ni relleno lateral —el cuerpo del
   panel ya pone el suyo—, exactamente como `.rel-side__top` y `.os-side__top`.
   El hairline se queda porque separa la tarea de sus campos. */
.wk-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);
}
.wk-side__id { opacity: 0; transition: opacity var(--d-fast) var(--ease); }
.wk-side__top:hover .wk-side__id,
.wk-side__top:focus-within .wk-side__id { opacity: 1; }

/* Lo único que scrollea de la hoja, y por eso el cuerpo del panel no tiene que
   hacerlo. El relleno lateral se fue con el de la cabecera —lo pone el cuerpo
   del panel— y la cola de abajo baja de --s-16 a --s-8: era espacio para que
   el último campo no quedara pegado al canto de la VENTANA, y en una columna
   de 438 px eso son media pantalla vacía. */
.wk-side__body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: var(--s-4) 0 var(--s-8);
  scrollbar-width: thin;
}
.wk-side__foot { margin-top: var(--s-6); }

/* El texto de la tarea es el título del panel: se edita en su lugar. */
.wk-text {
  width: 100%;
  border: 0;
  background: transparent;
  resize: none;
  font-family: var(--font-display);
  font-weight: var(--fw-light);
  letter-spacing: var(--tr-display);
  font-size: var(--t-h2);
  line-height: var(--lh-snug);
  color: var(--ink);
  padding: 0;
  margin-bottom: var(--s-5);
  overflow-wrap: anywhere;
}
.wk-text:focus { outline: none; }

/* La descripción. NO es un segundo título: tipo de cuerpo, no de display, y sin
   recorte de ninguna clase —crece con lo que se escriba (el alto lo mide
   `crece()` en JS) y respeta los saltos de línea—. Vive sin rótulo, como el campo
   de notas de Relaciones: el placeholder etiqueta mientras está vacía. */
.wk-desc {
  width: 100%;
  border: 0;
  background: transparent;
  resize: none;
  overflow: hidden;
  font-family: inherit;
  font-size: var(--t-body-sm);
  line-height: var(--lh-body);
  color: var(--ink-2);
  padding: 0;
  margin-bottom: var(--s-5);
  overflow-wrap: anywhere;
}
.wk-desc::placeholder { color: var(--ink-3); }
.wk-desc:focus { outline: none; color: var(--ink); }

/* ---------- LAS ETIQUETAS, HASTA ARRIBA ----------
   Encima del título, con la mecánica del `.r-eyebrow` del sistema: lo que
   clasifica se lee antes de lo clasificado. Aquí sí es `.r-chip` de tamaño
   completo y no la pastilla chica de la tarjeta — en la hoja hay ancho, y estos
   chips son lo primero que se ve.

   Sin etiquetas el bloque no existe (lo decide el JS), así que no hay nada que
   esconder ni un hueco que reservar. */
.wk-side__tags {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin: 0 0 var(--s-3);
}
/* El gato pegado al nombre, para que no se separe al envolver. `gap` a cero
   porque `.r-chip` es flex con `--s-2` de hueco: sin esto el gato queda a ocho
   píxeles de su etiqueta y se lee como un símbolo aparte. */
.wk-side__tag { gap: 2px; }
.wk-side__tag::before { content: "#"; color: var(--ink-3); }

.wk-f { display: grid; gap: var(--s-2); align-content: start; margin-bottom: var(--s-5); }

/* ---------- El renglón: rótulo a la izquierda, valor a la derecha ----------
   Es el reparto de la maqueta de referencia, y la parte que lo hace funcionar es
   que la columna del rótulo mide LO MISMO en todos los renglones: con `auto` cada
   rótulo medía su palabra y los valores quedaban en seis sangrías distintas, que
   es exactamente lo que hace que una ficha se lea recorriéndola en vez de
   barriéndola.

   `--wk-lbl` son 88px, medidos contra el rótulo más largo que hay («Completada»
   en `--t-label` con `--tr-label`). No es un ancho de contenido: es plomada.

   `align-items: start` y no `center`: el valor de «Fechas» son dos renglones
   (los campos y la nota de abajo) y con el rótulo centrado contra los dos queda
   a media altura de nada. */
.wk-f--row {
  grid-template-columns: var(--wk-lbl) minmax(0, 1fr);
  align-items: start;
  gap: var(--s-3);
  margin-bottom: var(--s-3);
}
/* El rótulo se alinea con la PRIMERA línea del valor, no con la caja: un
   control de 30px y un rótulo de 11px no comparten línea base sin esto. */
.wk-f--row > .r-label { padding-top: var(--s-2); }
/* Un control que MIDE SU CONTENIDO no se estira a la celda. El segmentado de
   prioridad y el desplegable comprimido dicen tres palabras; estirados a los
   1,200 px de un panel ancho se leen como un control a medio pintar — el mismo
   hallazgo que ya tiene anotado `.wk-tools`. Los que sí se estiran (los dos
   campos de fecha, el selector de iniciativa) lo piden por su nombre más
   abajo. */
.wk-f--row > .r-seg,
.wk-f--row > .r-pick { justify-self: start; }

/* La celda del valor, cuando lleva más de una cosa: el control y su nota
   debajo. Existe porque una retícula de dos columnas manda el tercer hijo a la
   columna del rótulo, y ahí la nota quedaría bajo la palabra «Fechas». */
.wk-val {
  display: grid;
  gap: var(--s-2);
  justify-items: start;
  min-width: 0;
}
.wk-val > .wk-fechas { justify-self: stretch; }

/* LÁPIDAS de `.wk-grid`, `.wk-chips` y `.wk-f--wide`. `.wk-f--wide` era el
   campo que se estiraba a las dos columnas de `.wk-grid` y se fue con ella. `.wk-grid` ponía Fechas e Iniciativa en
   dos columnas; con cada campo vuelto renglón de rótulo + valor no hay nada que
   repartir, y en el panel angosto se desarmaba de todas formas. `.wk-chips` era
   el renglón de etiquetas del final de la hoja, que se fue arriba del título. */
.wk-quick { justify-self: start; }

/* El punto de color del estado ACTUAL, al lado del desplegable. Es el único que
   sobrevive a comprimir, y es el que hace falta: dice dónde está esta tarea sin
   abrir nada. Los otros cuatro solo servían al elegir, y ahí la lista los dice
   por nombre y en el orden del tablero. */
.wk-st { display: flex; align-items: center; gap: var(--s-3); }

/* Las dos fechas son UN control: comparten rótulo y renglón, y el guion largo
   entre ellas dice que son un rango y no dos datos parecidos. Los campos se
   reparten el ancho por igual para que ninguno parezca el principal. */
.wk-fechas {
  display: flex;
  align-items: center;
  gap: var(--s-2);
}
.wk-fechas .r-input { flex: 1 1 0; min-width: 0; }
.wk-fechas__d { color: var(--ink-3); flex: 0 0 auto; }

/* `.wk-states` / `.wk-state` se fueron con los cinco botones apilados: el estado
   es el `.r-pick` del sistema, así que la lista y su selección las viste `ron.css`
   y este módulo no declara nada de eso. El único resto propio es `.wk-st`, que
   solo coloca el punto de color junto al desplegable. */

/* ---------- Revisión ----------
   El bloque no existe sin veredictos y sin estar en revisión (lo decide el JS),
   así que aquí no hay nada que esconder: cuando aparece, aparece con algo que
   decir. Ficha hundida, la misma que el bloque del agente — son las dos cosas
   que le PASAN a la tarea en vez de ser campos suyos, y se leen como pareja.

   Cero acento otra vez: `ok` para lo aceptado, `warn` para lo que volvió. El
   ácido de esta vista es la métrica de la cabeza y no se toca. */
.wk-rev {
  display: grid;
  gap: var(--s-3);
  padding: var(--s-3);
  background: var(--surface-sunk);
  border: var(--stroke) solid var(--hairline);
  border-radius: var(--r-md);
}
/* El par de veredicto. Sin hover de por medio: en la hoja son la acción
   principal del bloque y en táctil son la única. */
.wk-rev__act { display: flex; align-items: center; gap: var(--s-2); }

.wk-rev__log {
  display: grid;
  gap: var(--s-3);
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Un veredicto: el sello y su hora en un renglón, el comentario debajo. El
   comentario NO se recorta —es lo único que este dato existe para guardar— y
   parte palabras si hace falta antes de desbordar una hoja de 438. */
.wk-rev__i {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: baseline;
  gap: var(--s-1) var(--s-3);
}
.wk-rev__at { justify-self: start; }
.wk-rev__n {
  grid-column: 1 / -1;
  margin: 0;
  color: var(--ink-2);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
/* Un renglón más de separación entre veredictos, para que dos comentarios
   seguidos no se lean como uno de dos párrafos. */
.wk-rev__i + .wk-rev__i {
  padding-top: var(--s-3);
  border-top: var(--stroke) solid var(--hairline);
}

/* Elegir una iniciativa y crear una son dos controles, no un menú con una
   opción que abre un diálogo. El select se estira y el disparador de alta se
   queda en su caja de 28: al expandirse el campo va a la capa superior, así que
   el renglón no cambia de alto ni el select de ancho. */
.wk-inirow { display: flex; align-items: center; gap: var(--s-2); }
.wk-inirow .wk-selwrap { flex: 1 1 auto; min-width: 0; }

/* ---------- Agente ----------
   Sin delegar el bloque es un disparador comprimido y nada más. Delegada, es
   una ficha hundida: quién la tiene, desde cuándo, y lo que devolvió. Las
   acciones —ejecutar y quitar— son lo secundario del renglón y se revelan al
   hover y al foco, con la caja ya reservada para que nada salte.

   Cero acento: el ácido de esta vista es la métrica de "en curso". Lo que este
   bloque usa son los semánticos, que son señal —`info` mientras corre, `crit`
   cuando el agente no pudo— y la tinta secundaria para todo lo demás. */
.wk-ag {
  display: grid;
  gap: var(--s-2);
  padding: var(--s-3);
  background: var(--surface-sunk);
  border: var(--stroke) solid var(--hairline);
  border-radius: var(--r-md);
}
.wk-ag__h {
  --ico: 15px;
  display: flex;
  align-items: center;
  gap: var(--s-2);
  min-width: 0;
}
.wk-ag__n {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--t-body-sm);
  color: var(--ink);
}
.wk-ag__at { flex: 0 0 auto; }
.wk-ag__a {
  display: flex;
  align-items: center;
  gap: var(--s-1);
  flex: 0 0 auto;
  opacity: 0;
  transition: opacity var(--d-fast) var(--ease);
}
.wk-ag:hover .wk-ag__a,
.wk-ag:focus-within .wk-ag__a { opacity: 1; }
/* Mientras corre no se vuelve a disparar: dos corridas escribiendo la misma
   nota se pisan. Se apaga en su lugar en vez de desaparecer — un botón que se
   va deja el renglón moviéndose justo cuando hay que mirarlo. */
.wk-ag__run[disabled] { opacity: 0.32; pointer-events: none; }

/* La frase que aparece cuando no hay motor que ejecute nada. Es la excepción
   de la claridad, no clutter: prometer una ejecución que no va a pasar es peor
   que decirlo con palabras completas. Va en tipo de CUERPO y no en `.r-micro`:
   micro es versalita, y una oración entera en mayúsculas se grita en vez de
   leerse — justo lo contrario de lo que esta frase viene a hacer. */
.wk-ag__s, .wk-ag__say { margin: 0; }
.wk-ag__alta { display: flex; align-items: center; gap: var(--s-3); }
.wk-ag__alta .wk-cap { flex: 0 0 auto; }
.wk-ag__alta .wk-ag__say { flex: 1 1 auto; min-width: 0; }

/* El "en qué quedó". Mismo trato que la descripción —sin rótulo, sin marco,
   crece con lo que tenga (el alto lo mide `crece()` en JS)— porque es el mismo
   trabajo: texto largo que se lee de corrido. `pre-wrap` porque lo que devuelve
   un agente suele venir con saltos de línea que son parte del dato. */
.wk-ag__note {
  width: 100%;
  border: 0;
  background: transparent;
  resize: none;
  overflow: hidden;
  font-family: inherit;
  font-size: var(--t-body-sm);
  line-height: var(--lh-body);
  color: var(--ink-2);
  padding: 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.wk-ag__note::placeholder { color: var(--ink-3); }
.wk-ag__note:focus { outline: none; color: var(--ink); }

/* ============================================================
   GITHUB · ARCHIVOS · COMENTARIOS — los tres bloques del final

   Los tres son renglones de la ficha (`.wk-f--row`), así que su rótulo cae en la
   misma plomada que los demás y no declaran nada del reparto: lo pone
   `--wk-lbl`. Lo que declaran es lo de adentro.

   CERO ACENTO, otra vez: el ácido de esta vista es la métrica de "en curso". Lo
   que usan estos tres son los semánticos —`ok`/`info`/`crit` en el estado del
   PR, `crit` en un error— y la tinta secundaria para todo lo demás.
   ============================================================ */

/* ---------- El disparador de un bloque colapsado ----------
   No es `.r-seg` ni `.r-pick`: no hay opciones que elegir, hay una cosa que se
   enseña o se esconde. Es la misma tinta y el mismo hover que `.wk-more` —el
   «+N antes» de la columna Listo y del historial de revisión— sin su pastilla:
   aquí el control vive dentro de un renglón de ficha y una pastilla de más
   competiría con el valor de al lado.

   La flecha gira, no se cambia: dos glifos para un solo estado binario son dos
   cosas que pueden contradecirse. */
.wk-fold {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  min-height: var(--ctl-sm);
  padding: 0;
  border: 0;
  background: transparent;
  font-family: inherit;
  font-size: var(--t-body-sm);
  color: var(--ink-2);
  cursor: pointer;
  transition: color var(--d-fast) var(--ease);
}
.wk-fold:hover, .wk-fold:focus-visible { color: var(--ink); }
.wk-fold .r-ico {
  color: var(--ink-3);
  transition: rotate var(--d-fast) var(--ease);
}
.wk-fold[aria-expanded="true"] .r-ico { rotate: 180deg; }

/* ---------- El ancho de los tres: la CUARTA medida propia del módulo ----------
   Los tres son contenido de renglón, no controles que llenen el panel, y sin un
   tope se estiran a la celda del valor — que en un panel de 970 son ~730 px. Se
   midió en captura y el problema es de LECTURA, no de estética: el nombre de un
   adjunto a la izquierda y su peso pegado al canto derecho quedan a ~350 px uno
   del otro y el ojo no puede emparejarlos; y las acciones del PR se van a vivir
   solas al otro extremo del renglón.

   Es el mismo hallazgo que ya tiene anotado `.wk-f--row > .r-pick` («un control
   que mide su contenido no se estira a la celda»), aplicado a una lista. 44ch se
   eligió contra el contenido más largo que hay —`cifras-ilustrativas.csv` más su
   peso— con holgura para un nombre de archivo normal, y de paso deja la caja de
   escribir un comentario en un ancho de lectura en vez de un renglón de 730 px.
   Va como variable y no como número suelto por lo mismo que `--wk-lbl`: es una
   medida del módulo y se afina en un lugar. */
.wk-side { --wk-list: 44ch; }
.wk-repo, .wk-files, .wk-com, .wk-av { max-width: var(--wk-list); }

/* ============================================================
   EL LOG DE AVANCE

   Una lista de sesiones dentro de la ficha, así que toma el reparto de
   `.wk-com__i` y de `.wk-rev__i` en vez de inventar un tercero: los tres son
   renglones fechados dentro del mismo panel, y tres repartos distintos para lo
   mismo se leen como tres piezas.

   CERO ACENTO, como los otros tres bloques del final. Lo que se usa son los
   semánticos: `ok` mientras trabaja, `warn` cuando te espera —que es el único
   estado que pide algo de una persona— y `crit` cuando falló. El ácido de esta
   vista sigue siendo la métrica de «en curso».
   ============================================================ */
.wk-av { display: grid; gap: var(--s-3); min-width: 0; }
.wk-av__h {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  min-width: 0;
}
.wk-av__l {
  display: grid;
  gap: var(--s-3);
  margin: 0;
  padding: 0;
  list-style: none;
}
.wk-av__i {
  display: grid;
  /* estado · rama · cuándo · el salto. La rama es la que cede: es la única de
     las cuatro que puede ser larga, y su nombre completo vive en el `title`. */
  grid-template-columns: auto minmax(0, 1fr) auto auto;
  align-items: baseline;
  gap: var(--s-1) var(--s-2);
  min-width: 0;
}
.wk-av__i + .wk-av__i {
  padding-top: var(--s-3);
  border-top: var(--stroke) solid var(--hairline);
}
.wk-av__st { flex: 0 0 auto; }
/* La rama en monoespacio porque se COPIA a un `git checkout`: es lo único que
   queda del trabajo cuando el worktree se limpia, y un nombre de rama en
   tipografía de texto se lee mal justo cuando hay que transcribirlo. */
.wk-av__r {
  font-family: var(--font-mono);
  font-size: var(--t-micro);
  color: var(--ink-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.wk-av__at { justify-self: end; }
/* El salto al panel de sesiones se revela, como toda acción de fila en el OS. */
.wk-av__go {
  opacity: 0;
  transition: opacity var(--d-fast) var(--ease);
}
.wk-av__i:hover .wk-av__go,
.wk-av__i:focus-within .wk-av__go { opacity: 1; }
/* La última línea de lo que dijo el agente. UNA línea recortada, y es la
   decisión: el transcript completo está a un clic (`.wk-av__go`), y tres
   renglones por sesión × cuatro sesiones convertirían la ficha de una tarea
   delegada en un transcript con la tarea perdida adentro. En monoespacio y en
   tinta terciaria porque no es texto del OS: es una cita. */
.wk-av__t {
  grid-column: 1 / -1;
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--t-micro);
  color: var(--ink-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.wk-av__say { margin: 0; }

/* ---------- GitHub ---------- */
.wk-repo { display: grid; gap: var(--s-2); min-width: 0; }
.wk-repo__h {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  min-width: 0;
}
/* El vínculo. Subrayado solo al tocarlo: un renglón de ficha con un subrayado
   permanente se lee como texto marcado, y el `--ink` contra el `--ink-2` de los
   valores de al lado ya dice que esto se pica. La flecha del set dice que se va
   fuera del OS. */
.wk-repo__l {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  min-width: 0;
  font-size: var(--t-body-sm);
  color: var(--ink);
  /* El nombre cede antes que el estado: `owner/nombre #123` recortado sigue
     diciendo de qué PR se trata, y un estado a medias no dice nada. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.wk-repo__l > span { overflow: hidden; text-overflow: ellipsis; }
.wk-repo__l .r-ico { flex: 0 0 auto; color: var(--ink-3); }
.wk-repo__l:hover { text-decoration: underline; text-underline-offset: 0.22em; }
.wk-repo__l:hover .r-ico { color: var(--ink); }
.wk-repo__e { flex: 0 0 auto; }
/* Recargar y quitar son lo secundario del renglón: se revelan al hover y al
   foco, con la caja reservada para que nada salte. Mismo trato que `.wk-ag__a`. */
.wk-repo__a {
  display: flex;
  align-items: center;
  gap: var(--s-1);
  flex: 0 0 auto;
  margin-left: auto;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--d-fast) var(--ease);
}
.wk-repo:hover .wk-repo__a,
.wk-repo:focus-within .wk-repo__a { opacity: 1; pointer-events: auto; }
.wk-repo__m {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s-1) var(--s-3);
  margin: 0;
}
.wk-repo__err, .wk-files__err { margin: 0; overflow-wrap: anywhere; }

/* ---------- Las tres escrituras: la rama, el PR y la compuerta ----------

   EL BOTÓN DEL GESTO VA PUESTO, no en `.wk-repo__a`, y es la misma decisión que
   `.va-t__a` documenta del otro lado: abrir la rama es el gesto PRINCIPAL de una
   tarea sin PR, no metadata de la fila. Además `.wk-repo__a` se revela al hover
   y `pointer-events` viaja con la opacidad, así que ahí el gesto no existiría en
   una pantalla sin puntero.

   Pegado a su disparador y no al canto: es la misma razón que el tope de ancho
   de arriba —una acción que vive a 350 px de lo que actúa se lee como si fuera
   de otra cosa— y aquí el vecino es el campo donde se pega la URL, que es la
   otra forma de hacer lo mismo. */
.wk-repo__git { flex: 0 0 auto; }

/* El renglón del pase, y el de fusionar, comparten caja: nunca conviven —
   mientras la compuerta corre lo que se ve es en qué va, no la invitación a
   arrancarla otra vez— así que una sola regla los alinea igual y el bloque no
   salta de alto al cambiar de uno al otro. */
.wk-repo__gate {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s-1) var(--s-2);
  min-width: 0;
}
/* EN QUÉ VA, CON PALABRAS. El aura dice que algo trabaja; esto dice QUÉ, que es
   la mitad que un brillo no puede dar —«corriendo el nivel 12 de 13» contra «se
   atoró en el mapa» son dos cosas y el aura es la misma—. Cede antes que el
   botón de detener: un paso recortado sigue ubicando, y un freno recortado no
   se puede picar. */
.wk-repo__paso {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------- Archivos ---------- */
.wk-files { display: grid; gap: var(--s-2); min-width: 0; }
/* El disparador y el icono de subir, PEGADOS: el icono no se va al canto. Es la
   misma razón que el tope de ancho de arriba —una acción que vive a 350 px de lo
   que actúa se lee como si fuera de otra cosa— y aquí además el icono es lo
   único que hay cuando no hay ningún archivo, así que tiene que caer donde el
   ojo ya está. */
.wk-files__h {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: var(--s-3);
  min-width: 0;
}
.wk-files__h > :first-child { flex: 0 1 auto; min-width: 0; }
.wk-files__s { margin: 0; }

/* SUBIR ES UN ICONO, y el `<input type="file">` no se ve NUNCA: los navegadores
   lo dibujan con su propio botón del sistema —su tipografía, su color, su radio—
   y no hay forma de estilarlo. No se esconde con `display: none` a propósito: un
   input así no siempre acepta `.click()` programático en todos los motores, y la
   caja de 1px recortada es la forma que sí lo mantiene vivo.

   Esa caja YA EXISTE en el sistema y es `.r-sr` (ron.css), así que el marcado la
   usa en vez de que este módulo redeclare las mismas seis propiedades. El nombre
   dice «para lectores de pantalla» y aquí el input además va `aria-hidden` —el
   botón de al lado es el que tiene el nombre accesible— pero el contrato VISUAL
   es exactamente el mismo, y una segunda definición de «esto no se ve» es una
   que algún día va a divergir. Lo único propio es que no reciba clics. */
.wk-up { position: relative; display: inline-flex; flex: 0 0 auto; }
.wk-up__i { pointer-events: none; }

.wk-files__l {
  display: grid;
  gap: var(--s-2);
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Una fila: el nombre se lleva el ancho, el peso y el bote miden lo suyo. El
   bote reserva su caja siempre (`opacity: 0` sigue midiendo), así que el nombre
   no cambia de ancho al pasar el ratón — el mismo hallazgo que el bote de la
   tarjeta. */
.wk-file {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: var(--s-2);
  min-width: 0;
}
.wk-file__n {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  min-width: 0;
  font-size: var(--t-body-sm);
  color: var(--ink-2);
  transition: color var(--d-fast) var(--ease);
}
.wk-file__n > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wk-file__n .r-ico { flex: 0 0 auto; color: var(--ink-3); }
.wk-file__n:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 0.22em; }
.wk-file__m { flex: 0 0 auto; }
/* `pointer-events` viaja con la opacidad, SIEMPRE: un bote invisible que recibe
   clics es una trampa, y aquí lo que recibiría es la confirmación de quitar algo.
   Es la misma regla —y la misma razón— que `.wk-card__x`. */
.wk-file__x, .wk-com__x {
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--d-fast) var(--ease);
}
.wk-file:hover .wk-file__x,
.wk-file:focus-within .wk-file__x,
.wk-com__i:hover .wk-com__x,
.wk-com__i:focus-within .wk-com__x { opacity: 1; pointer-events: auto; }

/* ---------- Comentarios ---------- */
.wk-com { display: grid; gap: var(--s-3); min-width: 0; }
.wk-com__h { display: flex; align-items: center; min-width: 0; }
.wk-com__l {
  display: grid;
  gap: var(--s-3);
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Quién y cuándo en el primer renglón, el bote al final de ése, el texto abajo
   a todo el ancho. Es el reparto de `.wk-rev__i`, y no por ahorro: los dos son
   una lista de renglones fechados dentro de la misma ficha, y dos repartos
   distintos para lo mismo se leen como dos piezas. */
.wk-com__i {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: baseline;
  gap: var(--s-1) var(--s-2);
  min-width: 0;
}
.wk-com__who {
  font-size: var(--t-label);
  font-weight: var(--fw-medium);
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.wk-com__at { justify-self: start; }
.wk-com__t {
  grid-column: 1 / -1;
  margin: 0;
  color: var(--ink-2);
  /* El comentario NO se recorta: es lo único que este dato existe para
     guardar. Parte palabras antes que desbordar una hoja de 438. */
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
.wk-com__i + .wk-com__i {
  padding-top: var(--s-3);
  border-top: var(--stroke) solid var(--hairline);
}
/* La caja de escribir. Sí lleva marco, y es la diferencia con la descripción y
   el «en qué quedó», que viven sin él: aquéllos son campos de la tarea que ya
   están escritos y se editan en su lugar; ésta es una caja VACÍA esperando algo
   nuevo, y sin canto no se lee como caja. */
.wk-com__new {
  display: flex;
  align-items: flex-end;
  gap: var(--s-2);
  min-width: 0;
}
.wk-com__in {
  flex: 1 1 auto;
  min-width: 0;
  resize: none;
  overflow: hidden;
  padding: var(--s-2) var(--s-3);
  border: var(--stroke) solid var(--hairline-strong);
  border-radius: var(--r-sm);
  background: var(--surface-sunk);
  font-family: inherit;
  font-size: var(--t-body-sm);
  line-height: var(--lh-body);
  color: var(--ink);
}
.wk-com__in::placeholder { color: var(--ink-3); }
.wk-com__in:focus {
  outline: none;
  border-color: var(--ink-4);
}
.wk-com__new .r-icon-btn[disabled] { opacity: 0.32; pointer-events: none; }

/* El select nativo pierde su flecha y le pone la del set: un glifo del
   sistema no respeta el peso del trazo. */
.wk-selwrap { position: relative; display: block; }
.wk-sel {
  appearance: none;
  -webkit-appearance: none;
  padding-right: var(--s-8);
  font-family: inherit;
}
.wk-selwrap__i {
  position: absolute;
  right: var(--s-3);
  top: 50%;
  translate: 0 -50%;
  color: var(--ink-3);
  pointer-events: none;
}

/* ============================================================
   Movimiento reducido y táctil
   ============================================================ */

/* La regla global de ron.css aplasta la DURACIÓN, no el retardo: sin
   apagar la animación completa, las tarjetas de la cascada se quedan
   invisibles su turno. */
@media (prefers-reduced-motion: reduce) {
  .wk-card, .wk-card[data-movido], .wk-grow, .wk-trow, .wk-undo { animation: none; }
  .wk-card, .wk-card__x, .wk-card__v, .wk-card__ok, .wk-col, .wk-more, .wk-mile,
  .wk-bar, .wk-pill, .wk-side__id, .wk-ag__a, .wk-off, .wk-hoy,
  .wk-col__x, .wk-fold, .wk-fold .r-ico, .wk-repo__a, .wk-repo__l, .wk-file__n,
  .wk-file__x, .wk-com__x, .wk-com__in { transition: none; }
  /* El RECORRIDO no se apaga: es cómo se opera la vista, no un adorno. Lo que
     se apaga es el viaje animado hasta un destino —el galón del canto, volver
     a hoy—, que `tlVa()` resuelve saltando en `workspace.js`. Recorrer con dos
     dedos, con las flechas y con Inicio sigue funcionando igual. */
  /* El panel y su velo aparecen y se van puestos. `transition: none` apaga
     también la de `display`, así que `hidden` vuelve a esconder en el mismo
     cuadro —que es justo lo que se pide aquí— y no queda una caja viva sin
     nada que la retire. El desplazamiento se anula porque sin transición el
     estado de salida se quedaría aplicado tal cual. */
  .wk-side, .wk-side[hidden] { transition: none; }
  .wk-side[hidden] { translate: none; }
}

/* Sin hover no hay revelación: en táctil lo secundario se queda visible. */
@media (hover: none) {
  /* `pointer-events` viaja con la opacidad, siempre: sin la segunda mitad el
     bote de limpiar las cerradas se vería puesto y no respondería a un toque
     —la revelación por hover está apagada aquí y nadie devolvería el `auto`—. */
  .wk-side__id, .wk-ag__a { opacity: 1; }
  /* Las acciones de la tarjeta —el bote, el ✓, la ✗— no se pueden quedar detrás
     de un hover que no existe. La hoja de la tarea tiene el mismo par sin hover,
     así que en táctil hay dos caminos y ninguno es el único. */
  .wk-card__x, .wk-card__v { opacity: 1; pointer-events: auto; }
  .wk-col__x { opacity: 1; pointer-events: auto; }
  /* Y las tres del final de la hoja, por lo mismo: quitar un adjunto, borrar un
     comentario y recargar el estado del PR no pueden quedarse detrás de un hover
     que en una pantalla táctil no existe. La `pointer-events` viaja con la
     opacidad SIEMPRE — sin la segunda mitad se verían puestas y no responderían
     a un toque, que es el bug que ya se documentó con el bote de la columna. */
  .wk-repo__a, .wk-file__x, .wk-com__x { opacity: 1; pointer-events: auto; }
}

/* ============================================================
   Anchos — contra la caja del PANEL, no contra la ventana
   (el porqué está arriba, en la cabecera del archivo)
   ============================================================ */

/* Las TRES columnas dejan de caber: el tablero pasa a scroll horizontal con
   anclaje y cada columna se queda con ancho de lectura en vez de encogerse a
   una palabra. `--wk-col` es un ancho FIJO aquí y no un `minmax(…, 78%)`: el
   porcentaje se medía contra una ventana y adentro del panel daba columnas de
   dos letras.

   EL CORTE BAJÓ DE 880 A 430, y no es solo aritmética. La aritmética dice que
   con cinco columnas el tablero pedía 5 × 176 + 4 × 12 = 928 y con tres pide
   552, así que dejarlo en 880 pondría a scrollear un tablero que cabe de sobra
   —el panel cómodo son 578 de caja—. Lo que decide el número, sin embargo, es
   otra cosa: **con tres columnas conviene apretarlas antes que esconderlas.**

   Medido en el mínimo declarado del módulo (480 de panel → 438 de caja):
   fluidas, las tres miden 138 px y se ven las tres; en scroll con `--wk-col`
   se ven dos y media y la tercera hay que ir a buscarla. Un Kanban existe para
   comparar columnas de un golpe, y con cinco esa comparación ya estaba perdida
   a ese ancho —de ahí el corte alto—; con tres no lo está. Así que el scroll
   horizontal se queda solo por DEBAJO del mínimo, donde el módulo ya está en su
   modo degradado por decisión del chasis. */
@container wk (max-width: 430px) {
  .wk-board {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: var(--wk-col);
    overflow-x: auto;
    /* Y el vertical se apaga a mano. `overflow-x: auto` con `overflow-y:
       visible` computa el vertical a `auto` también, así que el tablero
       estrenaría una segunda barra de scroll por encima de la de cada
       columna — dos pistas para el mismo gesto. El alto ya lo gobierna cada
       `.wk-col__l`, así que aquí no hay nada que recortar. */
    overflow-y: hidden;
    overscroll-behavior-x: contain;
    scroll-snap-type: x;
    padding-bottom: var(--s-2);
    scrollbar-width: thin;
  }
  .wk-col { scroll-snap-align: start; }
}

/* Un elemento NUNCA es su propio contenedor de consulta: `@container wk` busca
   un ANCESTRO llamado `wk`, y el que declara el nombre es `.wk`, que no
   existe. O sea que `.wk { --wk-lab }` dentro de un `@container wk` no aplica
   —el ancho de la columna del Gantt se quedaba en 200 a todos los anchos—.
   Por eso el que recibe la medida es `.wk-tl`, que sí es descendiente. */
@container wk (max-width: 620px) {
  .wk-tl { --wk-lab: 168px; }
}

/* APRETADO: el piso de la conversación ganó y el panel quedó por debajo de su
   mínimo. Se recorta con elipsis y el nombre completo se queda en el `title`,
   que es la degradación que el encargo pide — no el estado normal. */
@container wk (max-width: 430px) {
  .wk-tl { --wk-lab: 116px; }
  .wk-board { --wk-col: 156px; }
  /* La métrica y su contexto dejan de compartir renglón: el numeral de puntos
     no encoge —es un SVG con ancho intrínseco— así que el que cede es el
     renglón de contexto, y aquí ya no le queda de dónde. */
  .wk-head { flex-direction: column; align-items: flex-start; gap: var(--s-2); }
  /* La iniciativa se calla en la tarjeta. A este ancho la columna mide 156 px y
     su pastilla, aun recortada, se lleva media banda de etiquetas — que es
     donde tienen que caber la prioridad y los tags, que son de LA tarea. De qué
     iniciativa es se sigue leyendo en el `title` y se filtra con el lente, que
     está a dos renglones de aquí. */
  .wk-tag--ini { display: none; }
}

/* ---------- La hoja de la tarea mide su propio ancho ----------
   Es hermana de `.wk`, no hija, así que el contenedor de arriba no la alcanza.
   Se declara el suyo: mide lo mismo que el panel, y sus campos son lo único
   que hay adentro. */
@container wkside (max-width: 430px) {
  /* Rótulo arriba del control: en 388 px el rótulo y el desplegable en el
     mismo renglón dejaban al desplegable sin ancho para su propio valor. Aquí el
     renglón se desarma y vuelve a ser un campo apilado, que es el modo degradado
     que el chasis ya declara para este ancho. El `padding-top` que alineaba el
     rótulo con la primera línea del valor se quita: apilado no hay nada a qué
     alinearse y sobraría el hueco. */
  .wk-f--row { grid-template-columns: minmax(0, 1fr); gap: var(--s-2); }
  .wk-f--row > .r-label { padding-top: 0; }
  /* El renglón de una sesión pierde la columna de la rama: cuatro columnas en
     388 px dejan el nombre de la rama en tres caracteres, que es peor que no
     enseñarlo. Baja a su propio renglón, completa, arriba de la cita. */
  .wk-av__i { grid-template-columns: auto minmax(0, 1fr) auto; }
  .wk-av__r { grid-column: 1 / -1; grid-row: 2; }
  .wk-av__t { grid-row: 3; }
}
