/* ═══════════════════════════════════════════════════════════════════════════
   VanyCorp · los componentes de contenido
   ═══════════════════════════════════════════════════════════════════════════
   Necesita `tokens.css` y `marca.css` cargados antes. El comportamiento, donde
   lo hay, vive en `componentes.js` (elementos propios `<vc-…>`, sin shadow DOM).
   La guía está en `docs/componentes.md`.

   Cuatro reglas que no son de estilo:

   1. **Solo tokens.** Ningún color literal: un color escrito aquí sería un
      color que el tema oscuro no sabe cambiar. Los tonos intermedios salen de
      `color-mix()` sobre los tokens.
   2. **Sin capa aquí; la capa la pone el puente.** Una regla sin capa le gana
      a TODA regla con capa, sea cual sea su especificidad. Si este archivo se
      declarara en `@layer vc` y `marca.css` no, `.vc-boton { width: 100% }`
      le ganaría a `.vc-boton--corto` en las pantallas sin framework (pasó en
      la prueba: el botón medía 335 px en vez de 155). Así que los archivos de
      la marca van sin capa, como siempre, y es `tailwind.css` quien los mete
      en `vc` con `@import … layer(vc)`: en React una utilidad (`w-auto`) le
      gana a la marca, y la marca al reseteo de Tailwind.
   3. **Las formas dicen lo mismo que el color.** Cada tono de estado lleva su
      marca (círculo vacío, medio, lleno, rombo, cuadrado…): el color solo no
      es accesible, y en un teléfono al sol tampoco se distingue.
   4. **El tamaño lo decide el contenedor, no la pantalla.** La tabla se vuelve
      tarjetas por `@container`, no por `@media`: la misma tabla dentro de un
      panel lateral de 400 px tiene que comportarse como en un teléfono.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── Lo que todos comparten ───────────────────────────────────────────────── */
vc-lista, vc-recorrido { display: block; }
vc-estado { display: inline-flex; }

/* El botón de peligro: anular, borrar, dar de baja. Va en la marca porque
   VanyPago, VanyCartera y VanyTesorería ya lo escribían cada una por su lado. */
.vc-boton--peligro {
  color: var(--vc-primario-fg);
  background: var(--vc-error);
}
.vc-boton--peligro:hover:not(:disabled) {
  background: color-mix(in oklab, var(--vc-error) 82%, var(--vc-tinta));
}
/* `.vc-boton` es `width: 100%` sin `box-sizing`: con el relleno se sale de su
   caja. En React no se ve porque el reseteo de Tailwind pone `border-box` a
   todo; sin framework, sí (la bandeja a 360 px desplazaba 1 px a lo ancho).
   Los componentes lo ponen; un enlace con aspecto de botón, también. */
:is(vc-lista, vc-ficha, vc-bandeja, vc-asistente, .vc-vacio, dialog.vc-dialogo) .vc-boton { box-sizing: border-box; }
/* Y en ninguna parte se sale de su caja (sprint 9, M06): «Guardar los papeles de
   VanyTesorería» a 360 px parte en dos líneas en vez de empujar el recuadro.
   `break-word` y no `anywhere` (posplan-4, marca-t1): una palabra se parte solo cuando no
   cabe sola, y en una fila `flex` el botón ya no se encoge hasta las letras («Reemplazar
   certificado» letra a letra a 360 px) ni aplasta al vecino. El ancho no cambia (plan §4.1). */
.vc-boton { max-width: 100%; overflow-wrap: break-word; }
a.vc-boton { display: inline-block; box-sizing: border-box; text-align: center; text-decoration: none; }

/* Un botón que no ocupa todo el ancho: el de la tarjeta de acceso sí lo hace. */
.vc-boton--corto { width: auto; }

/* La fila de botones (posplan-4, marca-t1; guía §5.24): los de dentro miden lo que su
   texto, como con `--corto` sin escribirlo en cada uno, y bajan de línea si no caben.
   `--derecha` los arrima al final. `vc-boton--corto` sigue valiendo. */
.vc-botones { display: flex; flex-wrap: wrap; gap: var(--vc-e-2) var(--vc-e-3); align-items: center; }
.vc-botones--derecha { justify-content: flex-end; }
.vc-botones > .vc-boton, .vc-botones > a.vc-boton { width: auto; }

/* ══ 1. Estado ════════════════════════════════════════════════════════════════
   <vc-estado codigo="EN_DIAGNOSTICO"></vc-estado>       ← el nombre lo pone el diccionario
   <span class="vc-estado" data-tono="bien">Pagada</span> ← lo mismo, escrito a mano

   El texto se pinta con el color del tono MEZCLADO con la tinta. Con el color
   puro no llega a AA en claro: el latón sobre su fondo suave da 2,8:1 y el
   verdigrís 3,4:1 (medido en el ensayo de esta prueba). La mezcla con
   `--vc-tinta` acerca el texto a la tinta en los dos temas, que es justo lo
   que hace falta: en claro lo oscurece, en oscuro lo aclara. */
.vc-estado,
vc-estado {
  --vc-estado-color: var(--vc-tinta-suave);
  --vc-estado-fondo: var(--vc-superficie-2);
  --vc-estado-borde: transparent;
  align-items: center;
  gap: 0.4em;
  max-width: 100%;
  padding: 0.15em 0.65em 0.15em 0.55em;
  border: 1px solid var(--vc-estado-borde);
  border-radius: 999px;
  background: var(--vc-estado-fondo);
  color: color-mix(in oklab, var(--vc-estado-color) 62%, var(--vc-tinta));
  font-family: var(--vc-font-sans);
  font-size: var(--vc-t-nota);
  font-weight: var(--vc-peso-medio);
  line-height: 1.5;
  white-space: nowrap;
  vertical-align: middle;
}
.vc-estado::before,
vc-estado::before {
  content: '';
  flex: none;
  width: 0.6em;
  height: 0.6em;
  border: 1.5px solid var(--vc-estado-color);
  border-radius: 50%;
  box-sizing: border-box;
}
/* Mientras el diccionario no ha corrido, no hay texto que leer: no se pinta
   una pastilla vacía. */
vc-estado:empty { display: none; }

/* neutro · no ha empezado, o es un borrador: círculo vacío */
:is(.vc-estado, vc-estado)[data-tono='neutro'] { --vc-estado-color: var(--vc-tinta-tenue); }

/* en curso · alguien de dentro trabaja en ello: círculo a medias */
:is(.vc-estado, vc-estado)[data-tono='curso'] {
  --vc-estado-color: var(--vc-primario);
  --vc-estado-fondo: var(--vc-superficie);
  --vc-estado-borde: var(--vc-primario);
}
:is(.vc-estado, vc-estado)[data-tono='curso']::before {
  background: linear-gradient(90deg, var(--vc-estado-color) 50%, transparent 50%);
}

/* espera · la pelota está en otro tejado (el cliente, el proveedor, el SRI):
   anillo discontinuo */
:is(.vc-estado, vc-estado)[data-tono='espera'] {
  --vc-estado-color: var(--vc-laton);
  --vc-estado-fondo: var(--vc-superficie);
  --vc-estado-borde: color-mix(in oklab, var(--vc-laton) 70%, transparent);
}
:is(.vc-estado, vc-estado)[data-tono='espera']::before { border-style: dotted; border-width: 2px; }

/* aviso · pide atención ya (vence, observado, por revisar): rombo lleno */
:is(.vc-estado, vc-estado)[data-tono='aviso'] {
  --vc-estado-color: var(--vc-laton);
  --vc-estado-fondo: var(--vc-laton-suave);
  --vc-estado-borde: var(--vc-laton);
}
:is(.vc-estado, vc-estado)[data-tono='aviso']::before {
  border-radius: 1px;
  background: var(--vc-estado-color);
  transform: rotate(45deg) scale(0.85);
}

/* bien · terminó bien (aprobado, pagado, entregado): círculo lleno */
:is(.vc-estado, vc-estado)[data-tono='bien'] {
  --vc-estado-color: var(--vc-ok);
  --vc-estado-fondo: var(--vc-primario-suave);
}
:is(.vc-estado, vc-estado)[data-tono='bien']::before { background: var(--vc-estado-color); }

/* mal · terminó mal o se cayó (rechazado, anulado, fallido, vencido): cuadrado */
:is(.vc-estado, vc-estado)[data-tono='mal'] {
  --vc-estado-color: var(--vc-error);
  --vc-estado-fondo: var(--vc-error-suave);
}
:is(.vc-estado, vc-estado)[data-tono='mal']::before { border-radius: 1px; background: var(--vc-estado-color); }

/* cerrado · terminó sin bien ni mal (archivado, cancelado por quien podía):
   sin fondo, con raya */
:is(.vc-estado, vc-estado)[data-tono='cerrado'] {
  --vc-estado-color: var(--vc-tinta-tenue);
  --vc-estado-fondo: transparent;
  --vc-estado-borde: var(--vc-borde);
}
:is(.vc-estado, vc-estado)[data-tono='cerrado']::before { border-radius: 0; height: 0; border-width: 1px 0 1px 0; width: 0.7em; }

/* ══ 2. Vacío ═════════════════════════════════════════════════════════════════
   Qué es este sitio, qué hacer para llenarlo y el botón que lo hace. Un
   «No hay datos» a secas deja a la persona sin saber si es un fallo. */
.vc-vacio {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--vc-e-3);
  padding: var(--vc-e-7) var(--vc-e-5);
  text-align: center;
  border: 1px dashed var(--vc-borde);
  border-radius: var(--vc-radio-lg);
  background: var(--vc-superficie);
  color: var(--vc-tinta-suave);
}
.vc-vacio > :first-child { margin-top: 0; }
.vc-vacio h2, .vc-vacio h3, .vc-vacio__titulo {
  margin: 0;
  font-size: var(--vc-t-subtitulo);
  font-weight: var(--vc-peso-fuerte);
  color: var(--vc-tinta);
}
.vc-vacio p { margin: 0; max-width: 46ch; text-wrap: pretty; }
.vc-vacio .vc-boton { width: auto; margin-top: var(--vc-e-2); }

/* ══ 3. Tabla ═════════════════════════════════════════════════════════════════
   <vc-lista buscar="Buscar…"> <table>…</table> <div class="vc-vacio" data-vacio>…</div> </vc-lista>

   El elemento NO crea la tabla: la mejora. Las filas son de quien las pinta
   (React o el JS de la pantalla) y el elemento solo les pone atributos
   (`hidden`, `data-etiqueta`) y, si nadie se lo impide, las ordena dentro de su
   mismo `<tbody>`. Lo que crea él —la barra con el buscador y el «nada
   coincide»— lleva `data-vc-propio`. */
vc-lista {
  container-type: inline-size;
  container-name: vc-lista;
  font-variant-numeric: tabular-nums;
}

.vc-lista__barra {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: var(--vc-e-2) var(--vc-e-4);
  margin-bottom: var(--vc-e-3);
}
.vc-lista__buscar {
  display: flex;
  flex-direction: column;
  gap: var(--vc-e-1);
  flex: 1 1 16rem;
  min-width: 0;
}
.vc-lista__buscar label,
.vc-lista__ordenar label {
  font-size: var(--vc-t-nota);
  font-weight: var(--vc-peso-medio);
  color: var(--vc-tinta-suave);
}
.vc-lista__buscar input,
.vc-lista__ordenar select {
  width: 100%;
  box-sizing: border-box;
  min-height: 2.5rem;
  padding: var(--vc-e-2) var(--vc-e-3);
  font: inherit;
  color: var(--vc-tinta);
  background: var(--vc-superficie);
  border: 1px solid var(--vc-borde);
  border-radius: var(--vc-radio-md);
}
.vc-lista__ordenar {
  display: none;               /* solo en tarjetas: en la tabla se ordena por la cabecera */
  flex-direction: column;
  gap: var(--vc-e-1);
  flex: 1 1 10rem;
}
.vc-lista__cuenta {
  margin: 0 0 0 auto;
  font-size: var(--vc-t-nota);
  color: var(--vc-tinta-tenue);
}

/* La tabla de `vc-lista` y `.vc-tabla` (posplan-4, marca-t1; guía §5.25) son UNA definición
   con dos selectores: la tabla de datos que ni pagina ni busca se escribe con la clase y se
   ve igual que la del elemento. */
vc-lista table, .vc-tabla {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  background: var(--vc-superficie);
  border: 1px solid var(--vc-borde);
  border-radius: var(--vc-radio-lg);
  font-size: var(--vc-t-cuerpo);
  color: var(--vc-tinta);
}
vc-lista th,
vc-lista td,
.vc-tabla th,
.vc-tabla td {
  padding: var(--vc-e-3) var(--vc-e-4);
  text-align: left;
  vertical-align: middle;
  border-bottom: 1px solid var(--vc-borde);
}
vc-lista tbody tr:last-child td, .vc-tabla tbody tr:last-child td { border-bottom: 0; }
vc-lista th, .vc-tabla th {
  font-size: var(--vc-t-nota);
  font-weight: var(--vc-peso-fuerte);
  color: var(--vc-tinta-suave);
  background: var(--vc-superficie-2);
  white-space: nowrap;
}
vc-lista thead th:first-child, .vc-tabla thead th:first-child { border-top-left-radius: calc(var(--vc-radio-lg) - 1px); }
vc-lista thead th:last-child, .vc-tabla thead th:last-child { border-top-right-radius: calc(var(--vc-radio-lg) - 1px); }
vc-lista tbody tr:hover td, .vc-tabla tbody tr:hover td { background: color-mix(in oklab, var(--vc-superficie-2) 55%, var(--vc-superficie)); }
vc-lista td.vc-num, vc-lista td[data-tipo='numero'], .vc-tabla td.vc-tabla__num { text-align: right; font-family: var(--vc-font-mono); }
vc-lista th.vc-num, vc-lista th[data-tipo='numero'], .vc-tabla th.vc-tabla__num { text-align: right; }
.vc-tabla td.vc-tabla__num { font-variant-numeric: tabular-nums; white-space: nowrap; }
.vc-tabla caption { caption-side: top; text-align: left; padding: 0 0 var(--vc-e-2); font-size: var(--vc-t-nota); color: var(--vc-tinta-suave); }
/* A 360 px la tabla no empuja la página: se desplaza dentro de su envoltura. */
.vc-tabla__envoltura { max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; }
.vc-tabla__envoltura > .vc-tabla { min-width: max-content; }
.vc-tabla__fila--enlace { cursor: pointer; }
.vc-tabla__fila--enlace:focus-visible { outline: 2px solid var(--vc-primario); outline-offset: -2px; }
vc-lista .vc-mono { font-family: var(--vc-font-mono); font-size: 0.92em; }

/* La cabecera que ordena es un <button> que pone quien escribe la tabla; el
   elemento le cambia `aria-sort` al <th>. La flecha la pinta el CSS. */
vc-lista th[data-ordenar] button {
  display: inline-flex;
  align-items: center;
  gap: var(--vc-e-1);
  /* 24 px de alto para el dedo (WCAG 2.5.8): relleno arriba y abajo, y el
     margen negativo lo devuelve para que la cabecera no crezca. */
  box-sizing: border-box;
  min-height: 24px;
  padding: 5px 0;
  margin-block: -5px;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  cursor: pointer;
}
vc-lista th[data-ordenar] button::after {
  content: '';
  width: 0.5em;
  height: 0.5em;
  border: solid currentColor;
  border-width: 0 1.5px 1.5px 0;
  transform: rotate(45deg) translate(-0.1em, -0.1em);
  opacity: 0.25;
}
vc-lista th[aria-sort='ascending'] button::after { transform: rotate(-135deg) translate(-0.1em, -0.1em); opacity: 1; }
vc-lista th[aria-sort='descending'] button::after { opacity: 1; }
vc-lista th[data-ordenar].vc-num button { flex-direction: row-reverse; }

/* Las acciones de la fila: botones cortos, juntos, a la derecha. */
/* Las acciones de la fila parten en filas ordenadas (alineadas a la derecha)
   en vez de empujar la tabla fuera de la pantalla: con cinco, `nowrap` se salía. */
.vc-lista__acciones { text-align: right; white-space: normal; width: 13rem; }
.vc-lista__acciones > * { margin: 2px 0 2px var(--vc-e-2); vertical-align: middle; }
.vc-accion {
  display: inline-flex;
  align-items: center;
  min-height: 2rem;
  padding: var(--vc-e-1) var(--vc-e-3);
  font: inherit;
  font-size: var(--vc-t-nota);
  font-weight: var(--vc-peso-medio);
  color: var(--vc-primario-2);
  background: none;
  border: 1px solid var(--vc-borde);
  border-radius: var(--vc-radio-sm);
  cursor: pointer;
  text-decoration: none;
}
.vc-accion:hover:not(:disabled) { background: var(--vc-primario-suave); }
.vc-accion--peligro { color: var(--vc-error); }
.vc-accion--peligro:hover:not(:disabled) { background: var(--vc-error-suave); }
.vc-accion:disabled { opacity: 0.55; cursor: not-allowed; }

/* Los tres estados del elemento: con filas, sin ninguna, y con filas que la
   búsqueda dejó fuera. Los decide `componentes.js` en `data-vc-estado`. */
vc-lista > .vc-vacio,
vc-lista [data-vacio] { display: none; }
vc-lista[data-vc-estado='vacia'] > .vc-vacio,
vc-lista[data-vc-estado='vacia'] [data-vacio] { display: flex; }
vc-lista[data-vc-estado='vacia'] > table,
vc-lista[data-vc-estado='vacia'] > .vc-lista__barra { display: none; }

.vc-lista__nada {
  display: none;
  margin: 0;
  padding: var(--vc-e-5) var(--vc-e-4);
  text-align: center;
  color: var(--vc-tinta-suave);
  border: 1px dashed var(--vc-borde);
  border-radius: var(--vc-radio-lg);
}
.vc-lista__nada .vc-enlace { margin-left: var(--vc-e-2); font-size: inherit; }
vc-lista[data-vc-estado='nada'] > .vc-lista__nada { display: block; }
vc-lista[data-vc-estado='nada'] > table { display: none; }

/* ── En 360 px, cada fila es una tarjeta ─────────────────────────────────────
   Sin desplazamiento lateral: un `overflow-x: auto` esconde columnas que en un
   teléfono nadie descubre. Cada celda lleva delante el nombre de su columna,
   que el elemento copia de la cabecera a `data-etiqueta`. */
@container vc-lista (max-width: 40rem) {
  .vc-lista__ordenar { display: flex; }
  .vc-lista__cuenta { flex-basis: 100%; margin: 0; }

  vc-lista table,
  vc-lista tbody,
  vc-lista tr,
  vc-lista td { display: block; }
  vc-lista table { border: 0; background: none; }
  vc-lista thead {
    position: absolute; width: 1px; height: 1px; overflow: hidden;
    clip-path: inset(50%); white-space: nowrap;
  }
  vc-lista tbody { display: flex; flex-direction: column; gap: var(--vc-e-3); }
  vc-lista tbody tr {
    display: block;
    padding: var(--vc-e-3) var(--vc-e-4);
    background: var(--vc-superficie);
    border: 1px solid var(--vc-borde);
    border-radius: var(--vc-radio-lg);
  }
  vc-lista tbody tr[hidden] { display: none; }
  vc-lista tbody tr:hover td { background: none; }
  /* La etiqueta va en su propia columna a la izquierda: así el contenido de la
     celda —texto, una pastilla, un enlace— se queda como está, por muchos hijos
     que tenga. Es un FLOTANTE metido en el relleno (margen negativo) y no una
     posición absoluta: con `display: flow-root` la celda crece hasta contenerla,
     y una etiqueta de dos líneas («Cédula, RUC o pasaporte») ya no se monta
     sobre la fila de abajo (lo vio VanyCuenta en sus terceros, sprint 8). */
  vc-lista td {
    display: flow-root;
    min-height: 1.5em;
    padding: var(--vc-e-1) 0 var(--vc-e-1) 7.5rem;
    border: 0;
    text-align: left;
    overflow-wrap: anywhere;
  }
  vc-lista td::before {
    content: attr(data-etiqueta);
    float: left;
    margin-left: -7.5rem;
    width: 7rem;
    font-size: var(--vc-t-nota);
    line-height: 1.6;
    font-family: var(--vc-font-sans);
    color: var(--vc-tinta-tenue);
    overflow-wrap: anywhere;
  }
  vc-lista td.vc-num, vc-lista td[data-tipo='numero'] { text-align: left; }
  /* La primera celda es el título de la tarjeta, sin etiqueta delante. */
  vc-lista tbody td:first-child {
    padding-left: 0;
    padding-bottom: var(--vc-e-2);
    font-weight: var(--vc-peso-fuerte);
  }
  vc-lista tbody td:first-child::before { display: none; }
  /* Las acciones, abajo, a lo ancho y fáciles de pulsar con el dedo. */
  vc-lista td.vc-lista__acciones {
    /* En la tarjeta, en rejilla: columnas iguales, las que quepan. */
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, 6.5rem), 1fr));
    gap: var(--vc-e-2);
    width: auto;
    padding: var(--vc-e-3) 0 0;
    margin-top: var(--vc-e-2);
    border-top: 1px solid var(--vc-borde);
    white-space: normal;
  }
  vc-lista td.vc-lista__acciones::before { display: none; }
  /* Una fila sin nada que hacer no deja una franja vacía abajo. */
  vc-lista td.vc-lista__acciones:empty { display: none; }
  vc-lista td.vc-lista__acciones > * { margin: 0; }
  vc-lista td.vc-lista__acciones .vc-accion { justify-content: center; min-height: 2.75rem; }
}

/* ══ 4. Recorrido ═════════════════════════════════════════════════════════════
   <vc-recorrido>
     <ol>
       <li>Recibida</li>
       <li aria-current="step" data-quien="el técnico">Diagnóstico</li>
       <li>Presupuesto</li> …
     </ol>
   </vc-recorrido>

   Lo único que dice el marcado es CUÁL es el paso actual. Hecho y pendiente los
   deduce el elemento (`data-vc-paso`), y el «Paso 2 de 5» también: contar a
   mano es lo primero que se queda mal cuando el catálogo gana un paso. */
vc-recorrido {
  container-type: inline-size;
  container-name: vc-recorrido;
  padding: var(--vc-e-3) var(--vc-e-4);
  background: var(--vc-superficie);
  border: 1px solid var(--vc-borde);
  border-radius: var(--vc-radio-lg);
}
vc-recorrido > ol {
  display: flex;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: vc-paso;
}
vc-recorrido li {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--vc-e-1);
  padding: 0 var(--vc-e-1);
  text-align: center;
  font-size: var(--vc-t-nota);
  color: var(--vc-tinta-tenue);
  counter-increment: vc-paso;
}
/* El número o la marca de hecho. */
vc-recorrido li::before {
  content: counter(vc-paso);
  position: relative;
  z-index: 1;
  display: grid;
  place-items: center;
  width: 1.75rem;
  height: 1.75rem;
  box-sizing: border-box;
  border: 1.5px solid var(--vc-borde);
  border-radius: 50%;
  background: var(--vc-superficie);
  font-family: var(--vc-font-mono);
  font-size: var(--vc-t-nota);
  font-weight: var(--vc-peso-medio);
  color: var(--vc-tinta-tenue);
}
/* La línea que une un paso con el siguiente. */
vc-recorrido li + li::after {
  content: '';
  position: absolute;
  top: calc(0.875rem - 1px);
  right: calc(50% + 0.875rem + 2px);
  left: calc(-50% + 0.875rem + 2px);
  height: 2px;
  background: var(--vc-borde);
}
vc-recorrido li[data-vc-paso='hecho'] { color: var(--vc-tinta-suave); }
vc-recorrido li[data-vc-paso='hecho']::before {
  content: '✓' / 'hecho';
  border-color: var(--vc-ok);
  background: var(--vc-primario-suave);
  color: color-mix(in oklab, var(--vc-ok) 62%, var(--vc-tinta));
  font-family: var(--vc-font-sans);
}
vc-recorrido li[data-vc-paso='hecho'] + li::after,
vc-recorrido li[data-vc-paso='actual']::after { background: var(--vc-ok); }
vc-recorrido li[data-vc-paso='actual'] {
  color: var(--vc-tinta);
  font-weight: var(--vc-peso-fuerte);
}
vc-recorrido li[data-vc-paso='actual']::before {
  border-color: var(--vc-primario);
  background: var(--vc-primario);
  color: var(--vc-primario-fg);
  box-shadow: 0 0 0 4px var(--vc-primario-suave);
}
/* Un proceso parado (cancelado, rechazado): el actual no se celebra. */
vc-recorrido[parado] li[data-vc-paso='actual']::before {
  border-color: var(--vc-error);
  background: var(--vc-error-suave);
  color: var(--vc-error);
  box-shadow: none;
}
vc-recorrido li > * { overflow-wrap: anywhere; }

.vc-recorrido__resumen {
  margin: var(--vc-e-3) 0 0;
  padding-top: var(--vc-e-3);
  border-top: 1px solid var(--vc-borde);
  font-size: var(--vc-t-nota);
  color: var(--vc-tinta-suave);
  text-wrap: pretty;
}
.vc-recorrido__resumen strong { color: var(--vc-tinta); font-weight: var(--vc-peso-fuerte); }

/* En un teléfono no caben cinco nombres: quedan los números y el nombre del
   actual va en el resumen, que ya lo dice. */
@container vc-recorrido (max-width: 34rem) {
  vc-recorrido li { font-size: 0; gap: 0; }
  vc-recorrido li::before { font-size: var(--vc-t-nota); }
}

/* ══ 5. Diálogo ═══════════════════════════════════════════════════════════════
   Lo abre `VanyDialogo.confirmar()` / `.motivo()` / `.avisar()` sobre un
   <dialog> nativo con `showModal()`: el resto de la página queda inerte —ni
   el ratón ni el lector salen de él— sin escribir ese trabajo a mano. */
dialog.vc-dialogo {
  width: min(28rem, calc(100vw - 2 * var(--vc-e-4)));
  max-height: calc(100dvh - 2 * var(--vc-e-4));
  box-sizing: border-box;
  margin: auto;
  padding: var(--vc-e-6);
  overflow-y: auto;
  color: var(--vc-tinta);
  background: var(--vc-superficie);
  border: 1px solid var(--vc-borde);
  border-radius: var(--vc-radio-tarjeta);
  box-shadow: var(--vc-sombra-elevada);
  font-family: var(--vc-font-sans);
  font-size: var(--vc-t-cuerpo);
}
dialog.vc-dialogo::backdrop {
  background: color-mix(in oklab, var(--vc-tinta) 42%, transparent);
}
:root[data-theme='dark'] dialog.vc-dialogo::backdrop,
:root.dark dialog.vc-dialogo::backdrop {
  background: color-mix(in oklab, var(--vc-bg) 70%, transparent);
}
@media (prefers-color-scheme: dark) {
  :root:not(.claro):not([data-theme='light']) dialog.vc-dialogo::backdrop {
    background: color-mix(in oklab, var(--vc-bg) 70%, transparent);
  }
}
.vc-dialogo__forma { display: flex; flex-direction: column; gap: var(--vc-e-4); margin: 0; }
.vc-dialogo__titulo {
  margin: 0;
  font-size: var(--vc-t-titulo);
  font-weight: var(--vc-peso-fuerte);
  letter-spacing: -0.01em;
  text-wrap: balance;
}
.vc-dialogo__texto { margin: 0; color: var(--vc-tinta-suave); text-wrap: pretty; }
/* Lo que quien llama pone después del texto (`contenido`, posplan-4): una lista, una negrita. */
.vc-dialogo__contenido { color: var(--vc-tinta-suave); min-width: 0; overflow-wrap: break-word; }
.vc-dialogo__contenido > :first-child { margin-top: 0; }
.vc-dialogo__contenido > :last-child { margin-bottom: 0; }
.vc-dialogo__contenido :is(ul, ol) { padding-left: var(--vc-e-5); }
.vc-dialogo__acciones {
  display: flex;
  flex-direction: row-reverse;
  flex-wrap: wrap;
  gap: var(--vc-e-2);
  margin-top: var(--vc-e-1);
}
.vc-dialogo__acciones .vc-boton { width: auto; flex: 1 1 8rem; }
.vc-dialogo textarea {
  width: 100%;
  box-sizing: border-box;
  min-height: 5.5rem;
  padding: var(--vc-e-3);
  font: inherit;
  color: var(--vc-tinta);
  background: var(--vc-superficie);
  border: 1px solid var(--vc-borde);
  border-radius: var(--vc-radio-md);
  resize: vertical;
}
.vc-dialogo textarea[aria-invalid='true'] { border-color: var(--vc-error); }
.vc-campo__ayuda { margin: 0; font-size: var(--vc-t-nota); color: var(--vc-tinta-tenue); }
.vc-dialogo .vc-campo__error { margin: 0; }
.vc-dialogo [role='alert']:empty { display: none; }


/* ══ 6. Campos de una ficha ═══════════════════════════════════════════════════
   `.vc-campo` (etiqueta, control, ayuda, error) ya existía para la tarjeta de
   acceso. Aquí gana el aspecto de una ficha: el control nativo tal cual, sin
   envoltorio de ícono. Los campos con tipo (M03) se meten en el mismo hueco:
   un `.vc-campo` con su <label> y su control. */
:is(vc-ficha, vc-asistente, .vc-ficha) .vc-campo :is(input:not([type='checkbox']):not([type='radio']), select, textarea) {
  width: 100%;
  box-sizing: border-box;
  min-height: 2.5rem;
  padding: var(--vc-e-2) var(--vc-e-3);
  font: inherit;
  color: var(--vc-tinta);
  background: var(--vc-superficie);
  border: 1px solid var(--vc-borde);
  border-radius: var(--vc-radio-md);
}
:is(vc-ficha, vc-asistente, .vc-ficha) .vc-campo textarea { min-height: 5rem; resize: vertical; }
:is(vc-campo, .vc-campo, vc-lista, dialog.vc-dialogo) ::placeholder { color: var(--vc-tinta-ejemplo); opacity: 1; }
:is(vc-ficha, vc-asistente, .vc-ficha) .vc-campo [aria-invalid='true'] { border-color: var(--vc-error); }
:is(vc-ficha, vc-asistente, .vc-ficha) .vc-campo [aria-invalid='true']:focus-visible { outline-color: var(--vc-error); }
/* Obligatorio se DICE, no solo se pinta con un asterisco. Lo pone el CSS a
   partir del `required` del control: no hay que escribirlo dos veces. */
.vc-campo:has(:required) > label::after {
  content: ' · obligatorio';
  font-weight: var(--vc-peso-normal);
  color: var(--vc-tinta-tenue);
}
.vc-campo--ancho { grid-column: 1 / -1; }
.vc-campo__error:empty { display: none; }

/* ══ 7. Ficha ═════════════════════════════════════════════════════════════════
   <vc-ficha [lectura]> <form novalidate> <fieldset class="vc-ficha__seccion">
     <legend>…</legend> <div class="vc-ficha__campos"> .vc-campo … </div>
   </fieldset> … <div class="vc-ficha__acciones">…</div> </form> </vc-ficha> */
vc-ficha { display: block; container-type: inline-size; container-name: vc-ficha; }
vc-ficha > form, .vc-ficha { display: flex; flex-direction: column; gap: var(--vc-e-5); margin: 0; }
.vc-ficha__seccion {
  margin: 0;
  padding: var(--vc-e-5);
  border: 1px solid var(--vc-borde);
  border-radius: var(--vc-radio-lg);
  background: var(--vc-superficie);
  min-width: 0;
}
.vc-ficha__seccion > legend {
  padding: 0 var(--vc-e-2);
  margin-left: calc(-1 * var(--vc-e-2));
  font-size: var(--vc-t-subtitulo);
  font-weight: var(--vc-peso-fuerte);
  color: var(--vc-tinta);
}
.vc-ficha__nota { margin: 0 0 var(--vc-e-4); font-size: var(--vc-t-nota); color: var(--vc-tinta-tenue); }
.vc-ficha__campos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
  gap: var(--vc-e-4) var(--vc-e-5);
}
.vc-ficha__acciones {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: var(--vc-e-2);
}
.vc-ficha__acciones .vc-boton { width: auto; }
/* Un BLOQUE: una ficha de una sola sección que vive entre otras (los papeles de cada
   producto en VanyCuenta → Personas, sprint 8). El recuadro es el del formulario
   entero, así que «Guardar» queda DENTRO de su caja y se sabe qué guarda. */
vc-ficha[bloque] > form {
  gap: var(--vc-e-4);
  padding: var(--vc-e-5);
  border: 1px solid var(--vc-borde);
  border-radius: var(--vc-radio-lg);
  background: var(--vc-superficie);
}
vc-ficha[bloque] .vc-ficha__seccion { padding: 0; border: 0; background: none; }
@container vc-ficha (max-width: 30rem) {
  .vc-ficha__seccion { padding: var(--vc-e-4); }
  vc-ficha[bloque] > form { padding: var(--vc-e-4); }
  vc-ficha[bloque] .vc-ficha__seccion { padding: 0; }
  .vc-ficha__acciones { flex-direction: column-reverse; }
  .vc-ficha__acciones .vc-boton { width: 100%; }
}
/* El resumen de errores: arriba, enlaza a cada campo. Lo pone el elemento. */
.vc-ficha__errores {
  padding: var(--vc-e-3) var(--vc-e-4);
  border: 1px solid var(--vc-error);
  border-radius: var(--vc-radio-md);
  background: var(--vc-error-suave);
  color: var(--vc-tinta);
  font-size: var(--vc-t-nota);
}
.vc-ficha__errores p { margin: 0 0 var(--vc-e-1); font-weight: var(--vc-peso-fuerte); }
.vc-ficha__errores ul { margin: 0; padding-left: var(--vc-e-5); }
.vc-ficha__errores a { color: var(--vc-tinta); }
vc-ficha > .vc-ficha__errores { margin-bottom: var(--vc-e-4); }
/* Solo lectura: la MISMA ficha, con los controles como texto. */
vc-ficha[lectura] .vc-ficha__acciones,
vc-ficha[lectura] .vc-campo:has(:required) > label::after { display: none; }
/* Mismo selector que el del campo editable, para ganarle en especificidad. */
vc-ficha[lectura] .vc-campo :is(input:not([type='checkbox']):not([type='radio']), select, textarea) {
  padding-left: 0;
  border-color: transparent;
  background: transparent;
  color: var(--vc-tinta);
  opacity: 1;
  appearance: none;
  resize: none;
}
vc-ficha[lectura] .vc-campo :is(input, textarea)::placeholder { color: transparent; }

/* ══ 8. Avisos ════════════════════════════════════════════════════════════════
   En línea: `.vc-aviso` con tono (los tres de antes siguen valiendo). */
.vc-aviso--info  { background: var(--vc-superficie); border-color: var(--vc-borde); color: var(--vc-tinta); }
.vc-aviso--bien  { background: var(--vc-primario-suave); border-color: var(--vc-ok); color: var(--vc-tinta); }
.vc-aviso--aviso { background: var(--vc-laton-suave); border-color: var(--vc-laton); color: var(--vc-tinta); }
.vc-aviso--mal   { background: var(--vc-error-suave); border-color: var(--vc-error); color: var(--vc-tinta); }
.vc-aviso__titulo { display: block; margin-bottom: var(--vc-e-1); font-weight: var(--vc-peso-fuerte); }
.vc-aviso:is(.vc-aviso--info, .vc-aviso--bien, .vc-aviso--aviso, .vc-aviso--mal) { border-left-width: 4px; }

/* El pasajero: abajo a la derecha, uno encima de otro; en el teléfono, a lo
   ancho. Lo crea `VanyAviso.pasajero()`. */
.vc-pasajeros {
  position: fixed;
  right: var(--vc-e-4);
  bottom: var(--vc-e-4);
  z-index: 70;
  display: flex;
  flex-direction: column;
  gap: var(--vc-e-2);
  width: min(24rem, calc(100vw - 2 * var(--vc-e-4)));
  pointer-events: none;
}
.vc-pasajeros > div { display: contents; }
.vc-pasajero {
  pointer-events: auto;
  display: flex;
  align-items: start;
  gap: var(--vc-e-3);
  padding: var(--vc-e-3) var(--vc-e-3) var(--vc-e-3) var(--vc-e-4);
  border: 1px solid var(--vc-borde);
  border-left: 4px solid var(--vc-ok);
  border-radius: var(--vc-radio-md);
  background: var(--vc-superficie);
  box-shadow: var(--vc-sombra-elevada);
  color: var(--vc-tinta);
  font-family: var(--vc-font-sans);
  font-size: var(--vc-t-cuerpo);
  animation: vc-entra 0.18s ease-out;
}
.vc-pasajero[data-tono='aviso'] { border-left-color: var(--vc-laton); }
.vc-pasajero[data-tono='mal'] { border-left-color: var(--vc-error); }
.vc-pasajero[data-tono='info'] { border-left-color: var(--vc-tinta-tenue); }
.vc-pasajero__texto { flex: 1; margin: 0; padding-top: 2px; }
.vc-pasajero__cerrar {
  flex: none;
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  padding: 0;
  border: 0;
  border-radius: var(--vc-radio-sm);
  background: none;
  color: var(--vc-tinta-tenue);
  font: inherit;
  font-size: 1.1rem;
  cursor: pointer;
}
.vc-pasajero__cerrar:hover { background: var(--vc-superficie-2); color: var(--vc-tinta); }
@keyframes vc-entra { from { opacity: 0; transform: translateY(0.5rem); } }
@media (prefers-reduced-motion: reduce) {
  .vc-pasajero { animation: none; }
}

/* ══ 9. Cargando ══════════════════════════════════════════════════════════════
   El esqueleto tiene la forma de lo que viene: no salta la página cuando llega.
   <div class="vc-cargando" role="status" aria-busy="true">
     <span class="vc-solo-lectores">Cargando las órdenes…</span>
     <span class="vc-esqueleto vc-esqueleto--fila"></span> … </div> */
.vc-cargando { display: flex; flex-direction: column; gap: var(--vc-e-3); }
.vc-cargando--ficha {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
  gap: var(--vc-e-4) var(--vc-e-5);
  padding: var(--vc-e-5);
  border: 1px solid var(--vc-borde);
  border-radius: var(--vc-radio-lg);
  background: var(--vc-superficie);
}
.vc-esqueleto {
  display: block;
  height: 1rem;
  border-radius: var(--vc-radio-sm);
  background:
    linear-gradient(90deg, transparent, color-mix(in oklab, var(--vc-superficie) 60%, transparent), transparent) 0 0 / 40% 100% no-repeat,
    var(--vc-superficie-2);
  animation: vc-brillo 1.4s linear infinite;
}
.vc-esqueleto--titulo { width: 40%; height: 1.4rem; }
.vc-esqueleto--fila { height: 3rem; border-radius: var(--vc-radio-md); }
.vc-esqueleto--etiqueta { width: 35%; height: 0.8rem; margin-bottom: var(--vc-e-2); }
.vc-esqueleto--campo { height: 2.5rem; border-radius: var(--vc-radio-md); }
@keyframes vc-brillo { from { background-position: -40% 0, 0 0; } to { background-position: 140% 0, 0 0; } }
@media (prefers-reduced-motion: reduce) { .vc-esqueleto { animation: none; } }

/* El botón ocupado: `aria-busy="true"` y `disabled`. La rueda la pone el CSS. */
.vc-boton[aria-busy='true'] { cursor: progress; }
.vc-boton[aria-busy='true']::before {
  content: '';
  display: inline-block;
  width: 0.9em;
  height: 0.9em;
  margin-right: var(--vc-e-2);
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  vertical-align: -0.12em;
  animation: vc-giro 0.7s linear infinite;
}

/* ══ 10. Pestañas ═════════════════════════════════════════════════════════════
   <vc-pestanas etiqueta="…" [fragmento]>
     <div class="vc-pestanas__lista"> <button type="button" data-panel="p1">…</button> … </div>
     <section id="p1">…</section> …
   </vc-pestanas>
   Partes de UNA cosa. Para ir a otra pantalla está el rail, con su URL. */
vc-pestanas { display: block; }
.vc-pestanas__lista {
  display: flex;
  gap: var(--vc-e-1);
  overflow-x: auto;              /* el único desplazamiento lateral permitido: dentro de su tira */
  scrollbar-width: thin;
  border-bottom: 1px solid var(--vc-borde);
  margin-bottom: var(--vc-e-5);
}
.vc-pestanas__lista > button {
  flex: none;
  position: relative;
  padding: var(--vc-e-3) var(--vc-e-4);
  border: 0;
  background: none;
  font: inherit;
  font-weight: var(--vc-peso-medio);
  color: var(--vc-tinta-suave);
  cursor: pointer;
  white-space: nowrap;
}
.vc-pestanas__lista > button:hover { color: var(--vc-tinta); background: var(--vc-superficie-2); }
.vc-pestanas__lista > button[aria-selected='true'] { color: var(--vc-tinta); font-weight: var(--vc-peso-fuerte); }
.vc-pestanas__lista > button[aria-selected='true']::after {
  content: '';
  position: absolute;
  left: var(--vc-e-2);
  right: var(--vc-e-2);
  bottom: -1px;
  height: 3px;
  border-radius: 3px 3px 0 0;
  background: var(--vc-primario);
}
.vc-pestanas__lista > button:focus-visible { outline-offset: -2px; }

/* ══ 11. Migas ════════════════════════════════════════════════════════════════
   <nav class="vc-migas" aria-label="Estás en"><ol><li><a href>…</a></li> … <li aria-current="page">…</li></ol></nav> */
.vc-migas { container-type: inline-size; font-size: var(--vc-t-nota); }
.vc-migas ol { display: flex; flex-wrap: wrap; align-items: center; margin: 0; padding: 0; list-style: none; }
.vc-migas li { display: inline-flex; align-items: center; color: var(--vc-tinta-tenue); }
.vc-migas li + li::before { content: '/'; margin: 0 var(--vc-e-2); color: var(--vc-borde); }
.vc-migas a { color: var(--vc-primario); text-decoration: underline; text-underline-offset: 2px;
  box-sizing: border-box; min-height: 24px; padding-block: 5px; margin-block: -5px; }   /* el dedo: 24 px, sin mover la línea */
.vc-migas a:hover { color: var(--vc-primario-2); }
.vc-migas [aria-current='page'] { color: var(--vc-tinta); font-weight: var(--vc-peso-medio); }
/* En el teléfono queda solo «‹ el anterior», que es a donde se vuelve. */
@container (max-width: 30rem) {
  .vc-migas li { display: none; }
  .vc-migas li:nth-last-child(2) { display: inline-flex; }
  .vc-migas li:nth-last-child(2)::before { content: '‹'; margin: 0 var(--vc-e-1) 0 0; color: var(--vc-primario); }
}

/* ══ 12. Bandeja ══════════════════════════════════════════════════════════════
   <vc-bandeja [dias-aviso="3"]> <ul class="vc-bandeja__lista"> <li class="vc-bandeja__item">
     <div class="vc-bandeja__que"><a href>…</a><span class="vc-bandeja__detalle">…</span></div>
     <span class="vc-bandeja__quien">…</span> <time class="vc-bandeja__desde" datetime="…"></time>
     <a class="vc-boton" href>el paso</a> </li> … </ul> <div class="vc-vacio" data-vacio>…</div> </vc-bandeja> */
vc-bandeja { display: block; container-type: inline-size; container-name: vc-bandeja; }
/* Las columnas las fija la LISTA y cada ítem las hereda (subgrid): si cada ítem fuera su
   propia rejilla, un botón más ancho que otro movería «quién» y «desde cuándo» de fila en
   fila (se vio en la portada de VanyCuenta, sprint 6). */
.vc-bandeja__lista { display: grid; grid-template-columns: minmax(0, 1fr) 10rem 8rem auto; column-gap: var(--vc-e-4);
  margin: 0; padding: 0; list-style: none;
  border: 1px solid var(--vc-borde); border-radius: var(--vc-radio-lg); background: var(--vc-superficie); }
.vc-bandeja__item {
  display: grid;
  grid-column: 1 / -1;
  grid-template-columns: subgrid;
  align-items: center;
  row-gap: var(--vc-e-2);
  padding: var(--vc-e-3) var(--vc-e-4);
  border-bottom: 1px solid var(--vc-borde);
}
.vc-bandeja__item:last-child { border-bottom: 0; }
.vc-bandeja__que { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.vc-bandeja__que a { color: var(--vc-tinta); font-weight: var(--vc-peso-fuerte); text-decoration: none;
  box-sizing: border-box; min-height: 24px; padding-block: 4px; margin-block: -4px; }   /* el dedo: 24 px, sin mover la fila */
.vc-bandeja__que a:hover { text-decoration: underline; }
.vc-bandeja__detalle, .vc-bandeja__quien { font-size: var(--vc-t-nota); color: var(--vc-tinta-suave); overflow-wrap: anywhere; }
.vc-bandeja__desde { font-size: var(--vc-t-nota); color: var(--vc-tinta-suave); }
.vc-bandeja__desde[data-vc-antiguo] { color: color-mix(in oklab, var(--vc-laton) 55%, var(--vc-tinta)); font-weight: var(--vc-peso-fuerte); }
.vc-bandeja__item .vc-boton { width: auto; white-space: nowrap; }
vc-bandeja > .vc-vacio, vc-bandeja [data-vacio] { display: none; }
vc-bandeja[data-vc-estado='vacia'] > .vc-vacio, vc-bandeja[data-vc-estado='vacia'] [data-vacio] { display: flex; }
vc-bandeja[data-vc-estado='vacia'] > .vc-bandeja__lista { display: none; }
@container vc-bandeja (max-width: 40rem) {
  .vc-bandeja__lista { grid-template-columns: minmax(0, 1fr) auto; }
  .vc-bandeja__que { grid-column: 1 / -1; }
  .vc-bandeja__item .vc-boton { grid-column: 1 / -1; width: 100%; }
}

/* ══ 13. Asistente ════════════════════════════════════════════════════════════
   <vc-asistente [confirmar="Recibir el equipo"]> <form novalidate>
     <section class="vc-paso" data-titulo="Cliente"><h3>…</h3> .vc-campo … </section> …
     <section class="vc-paso" data-titulo="Confirmar" data-resumen><h3>…</h3></section>
   </form> </vc-asistente>
   El recorrido, los botones y el resumen los pone el elemento. Un paso a la vez:
   la clase `.vc-paso` es la de VanyID; cuál se ve lo dice `data-vc-activo`. */
vc-asistente { display: flex; flex-direction: column; gap: var(--vc-e-4); container-type: inline-size; container-name: vc-asistente; }
vc-asistente > form { display: flex; flex-direction: column; gap: var(--vc-e-4); margin: 0;
  padding: var(--vc-e-5); border: 1px solid var(--vc-borde); border-radius: var(--vc-radio-lg); background: var(--vc-superficie); }
vc-asistente .vc-paso[data-vc-activo] { display: flex; }
vc-asistente .vc-paso > :is(h2, h3) { margin: 0; font-size: var(--vc-t-subtitulo); font-weight: var(--vc-peso-fuerte); }
.vc-asistente__acciones { display: flex; justify-content: flex-end; gap: var(--vc-e-2); padding-top: var(--vc-e-4); border-top: 1px solid var(--vc-borde); }
.vc-asistente__acciones .vc-boton { width: auto; min-width: 8rem; }
.vc-asistente__acciones > .vc-boton:first-child { margin-right: auto; }
.vc-asistente__acciones > [hidden] { display: none; }
@container vc-asistente (max-width: 30rem) {
  vc-asistente > form { padding: var(--vc-e-4); }
  .vc-asistente__acciones { flex-direction: column-reverse; }
  .vc-asistente__acciones .vc-boton { width: 100%; }
}
.vc-asistente__resumen { display: flex; flex-direction: column; gap: var(--vc-e-4); }
.vc-asistente__grupo { padding: var(--vc-e-3) var(--vc-e-4); border: 1px solid var(--vc-borde); border-radius: var(--vc-radio-md); }
.vc-asistente__grupo > header { display: flex; justify-content: space-between; align-items: baseline; gap: var(--vc-e-2); margin-bottom: var(--vc-e-2); }
.vc-asistente__grupo h4 { margin: 0; font-size: var(--vc-t-cuerpo); font-weight: var(--vc-peso-fuerte); }
.vc-asistente__grupo dl { display: grid; grid-template-columns: minmax(6rem, max-content) 1fr; gap: var(--vc-e-1) var(--vc-e-4); margin: 0; font-size: var(--vc-t-nota); }
.vc-asistente__grupo dt { color: var(--vc-tinta-tenue); }
.vc-asistente__grupo dd { margin: 0; overflow-wrap: anywhere; }

/* Un panel de pestañas o un paso escondido se queda escondido aunque la
   pantalla le ponga `display` (una clase suya, o `flex` de Tailwind, que va en
   una capa por encima de la marca). `!important` en una capa baja le gana a
   cualquier regla normal de las de arriba: es el único sitio donde se usa. */
vc-pestanas > [role='tabpanel'][hidden],
vc-asistente [hidden] { display: none !important; }

/* ══ 14. Campos con tipo — <vc-campo> (M03) ═══════════════════════════════════
   El elemento crea etiqueta, control, ayuda y error; aquí, su aspecto. Mismas
   medidas que el `.vc-campo` escrito a mano, para que convivan en una ficha. */
vc-campo { display: flex; flex-direction: column; gap: var(--vc-e-1); min-width: 0; position: relative; }
vc-campo.vc-campo--ancho { grid-column: 1 / -1; }
vc-campo > label {
  font-size: var(--vc-t-nota);
  font-weight: var(--vc-peso-medio);
  color: var(--vc-tinta-suave);
}
vc-campo:has(:required) > label::after { content: ' · obligatorio'; font-weight: var(--vc-peso-normal); color: var(--vc-tinta-tenue); }
vc-campo :is(input:not([type='checkbox']):not([type='radio']):not([type='file']), select, textarea) {
  width: 100%;
  box-sizing: border-box;
  min-height: 2.5rem;
  padding: var(--vc-e-2) var(--vc-e-3);
  font: inherit;
  color: var(--vc-tinta);
  background: var(--vc-superficie);
  border: 1px solid var(--vc-borde);
  border-radius: var(--vc-radio-md);
}
vc-campo textarea { min-height: 5rem; resize: vertical; }
vc-campo [aria-invalid='true'] { border-color: var(--vc-error); }
vc-campo input:disabled, vc-campo select:disabled, vc-campo textarea:disabled { background: var(--vc-superficie-2); color: var(--vc-tinta-tenue); cursor: not-allowed; }
.vc-campo__cuenta { margin: 0; font-size: var(--vc-t-nota); color: var(--vc-tinta-tenue); text-align: right; }
.vc-campo__cuenta:empty, .vc-campo__nota:empty { display: none; }
.vc-campo__nota { margin: 0; font-size: var(--vc-t-nota); color: color-mix(in oklab, var(--vc-laton) 55%, var(--vc-tinta)); }
.vc-campo__fila { display: flex; align-items: stretch; gap: var(--vc-e-2); min-width: 0; }
.vc-campo__fila > input { flex: 1 1 auto; min-width: 0; }
.vc-campo__fila--identificacion > select { flex: 0 0 auto; width: auto; max-width: 45%; }
/* La moneda, a la vista y pegada al importe. El importe va a la derecha y en
   cifras de ancho fijo, para que las columnas de centavos se lean de un golpe. */
.vc-campo__moneda {
  display: inline-flex; align-items: center;
  padding: 0 var(--vc-e-3);
  border: 1px solid var(--vc-borde); border-radius: var(--vc-radio-md);
  background: var(--vc-superficie-2);
  font-family: var(--vc-font-mono); font-size: var(--vc-t-nota); color: var(--vc-tinta-suave);
}
vc-campo [data-vc-alinear='derecha'] { text-align: right; font-family: var(--vc-font-mono); font-variant-numeric: tabular-nums; }
/* Sí / no: un interruptor de verdad (<input type=checkbox role=switch>) con su texto. */
.vc-interruptor { display: flex; align-items: center; gap: var(--vc-e-3); min-height: 2.5rem; }
.vc-interruptor input {
  appearance: none; margin: 0; flex: none;
  width: 2.75rem; height: 1.5rem; border-radius: 999px;
  background: var(--vc-borde); position: relative; cursor: pointer;
  transition: background 0.15s;
}
.vc-interruptor input::after {
  content: ''; position: absolute; top: 3px; left: 3px;
  width: calc(1.5rem - 6px); height: calc(1.5rem - 6px); border-radius: 50%;
  background: var(--vc-superficie); box-shadow: 0 1px 2px color-mix(in oklab, var(--vc-tinta) 30%, transparent);
  transition: transform 0.15s;
}
.vc-interruptor input:checked { background: var(--vc-primario); }
.vc-interruptor input:checked::after { transform: translateX(1.25rem); }
.vc-interruptor input:disabled { opacity: 0.6; cursor: not-allowed; }
.vc-interruptor__texto { font-size: var(--vc-t-cuerpo); color: var(--vc-tinta); }
/* Archivo: un sitio donde soltar, con el control nativo dentro. */
.vc-archivo {
  display: flex; flex-direction: column; gap: var(--vc-e-2);
  padding: var(--vc-e-4); border: 1px dashed var(--vc-borde); border-radius: var(--vc-radio-md);
  background: var(--vc-superficie);
}
.vc-archivo[data-vc-encima] { border-color: var(--vc-primario); background: var(--vc-primario-suave); }
.vc-archivo__fila { display: flex; flex-wrap: wrap; align-items: center; gap: var(--vc-e-2) var(--vc-e-3); min-width: 0; }
/* El <input type=file> es el control de verdad, escondido a la vista y no al
   teclado: el foco se le ve en el botón, que es su <label>. Tampoco recibe el
   toque (`pointer-events`): el dedo va al botón, que sí tiene tamaño. */
.vc-archivo__entrada {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0; opacity: 0; pointer-events: none;
}
.vc-archivo__entrada:focus-visible + .vc-archivo__boton { outline: 2px solid var(--vc-primario); outline-offset: 2px; }
.vc-archivo__boton { width: auto; box-sizing: border-box; display: inline-flex; align-items: center; cursor: pointer; }
.vc-archivo__nombre { min-width: 0; font-size: var(--vc-t-nota); color: var(--vc-tinta); overflow-wrap: anywhere; }
.vc-archivo__texto { margin: 0; font-size: var(--vc-t-nota); color: var(--vc-tinta-tenue); }
vc-campo[tipo='archivo'] .vc-campo__nota { color: var(--vc-error); }
/* El selector que busca: la lista cuelga del campo. */
.vc-selector { position: relative; }
.vc-selector__lista {
  position: absolute; z-index: 40; left: 0; right: 0; top: calc(100% + 4px);
  max-height: 16rem; overflow-y: auto; margin: 0; padding: var(--vc-e-1);
  list-style: none; background: var(--vc-superficie);
  border: 1px solid var(--vc-borde); border-radius: var(--vc-radio-md); box-shadow: var(--vc-sombra-elevada);
}
.vc-selector__opcion { display: flex; flex-direction: column; gap: 1px; padding: var(--vc-e-2) var(--vc-e-3); border-radius: var(--vc-radio-sm); cursor: pointer; }
.vc-selector__opcion[aria-selected='true'] { background: var(--vc-primario-suave); outline: 1px solid var(--vc-primario); }
.vc-selector__nombre { color: var(--vc-tinta); font-weight: var(--vc-peso-medio); overflow-wrap: anywhere; }
.vc-selector__detalle { font-size: var(--vc-t-nota); color: var(--vc-tinta-suave); overflow-wrap: anywhere; }
.vc-selector__opcion--crear .vc-selector__nombre { color: var(--vc-primario); }
.vc-selector__vacio { padding: var(--vc-e-2) var(--vc-e-3); font-size: var(--vc-t-nota); color: var(--vc-tinta-tenue); }
/* El tercero (sprint 4, P02) y la persona (sprint 5, P01): «Crear uno nuevo» /
   «Crear una nueva» es un diálogo corto, a una columna, con los parecidos encima
   de los botones y su «Usar este» a la derecha. */
dialog.vc-dialogo.vc-tercero, dialog.vc-dialogo.vc-persona { width: min(32rem, calc(100vw - 2 * var(--vc-e-4))); }
.vc-tercero .vc-ficha__campos, .vc-persona .vc-ficha__campos { grid-template-columns: 1fr; }
.vc-tercero__avisos:empty, .vc-persona__avisos:empty { display: none; }
.vc-tercero__avisos .vc-aviso p, .vc-persona__avisos .vc-aviso p { margin: 0; }
.vc-tercero__lista, .vc-persona__lista { display: flex; flex-direction: column; gap: var(--vc-e-2); margin: var(--vc-e-2) 0 0; padding: 0; list-style: none; }
.vc-tercero__parecido, .vc-persona__parecido { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--vc-e-2); }
.vc-tercero__quien, .vc-persona__quien { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 12rem; }
.vc-tercero__usar.vc-boton, .vc-persona__usar.vc-boton { width: auto; box-sizing: border-box; }
/* Teléfono en lectura: a un toque. */
.vc-campo__enlaces { display: flex; flex-wrap: wrap; gap: var(--vc-e-2) var(--vc-e-4); margin: 0; font-size: var(--vc-t-nota); }
.vc-campo__enlaces a { color: var(--vc-primario); text-decoration: underline; text-underline-offset: 2px; }
/* Solo lectura: la misma ficha, sin bordes; el importe, a la derecha. */
vc-campo[data-vc-lectura] :is(input:not([type='checkbox']):not([type='radio']):not([type='file']), select, textarea) {
  padding-left: 0; border-color: transparent; background: transparent; color: var(--vc-tinta); opacity: 1; appearance: none; resize: none;
}
vc-campo[data-vc-lectura] > label::after { display: none; }
vc-campo[data-vc-lectura] .vc-campo__moneda { border-color: transparent; background: transparent; padding-right: 0; }
vc-campo[data-vc-lectura] .vc-campo__fila--identificacion > select { padding-right: var(--vc-e-2); }
/* En lectura: lo que el control nativo pintaría a su manera lo dice un texto
   nuestro, y sobran la ayuda, las notas y el contador —son para quien escribe—. */
.vc-campo__lectura { margin: 0; min-height: 2.5rem; display: flex; align-items: center; color: var(--vc-tinta); overflow-wrap: anywhere; }
/* Sprint 9 (M06): en lectura, todo lo que es texto se lee ENTERO en un párrafo que
   parte líneas (una dirección larga, una razón social): un <input> no parte y lo
   cortaba (el emisor de VanyFactura). El control sigue en el DOM y en el formulario. */
vc-campo[data-vc-lectura]:is([tipo='texto'], [tipo='texto-largo'], [tipo='correo'], [tipo='identificacion'], [tipo='numero'],
  [tipo='dinero'], [tipo='selector'], [tipo='tercero'], [tipo='persona'], [tipo='lista']) :is(input:not([type='hidden']), textarea, select, .vc-campo__fila, .vc-selector) { display: none; }
vc-campo[data-vc-lectura][tipo='dinero'] .vc-campo__lectura { justify-content: flex-end; font-family: var(--vc-font-mono); }
.vc-campo__lectura[hidden] { display: none; }
vc-campo[data-vc-lectura]:is([tipo='fecha'], [tipo='fecha-hora']) input,
vc-campo[data-vc-lectura] .vc-archivo { display: none; }
vc-campo[data-vc-lectura] :is(.vc-campo__ayuda, .vc-campo__nota, .vc-campo__cuenta),
vc-ficha[lectura] :is(.vc-campo__ayuda, .vc-ficha__nota) { display: none; }
vc-campo[data-vc-lectura][tipo='telefono'] input { display: none; }
vc-campo:not([data-vc-lectura]) .vc-campo__enlaces { display: none; }

/* ══ 15. Etiqueta — <vc-etiqueta> · .vc-etiqueta ══════════════════════════════
   Para CATEGORÍAS que no son estados: un papel («Dueño»), «Estándar»,
   «Incluido». Neutra a propósito, sin los tonos ni las formas del diccionario:
   si tuviera color, se leería como un estado y alguien preguntaría qué le pasa.
   Esquinas casi rectas, para que no se confunda con la pastilla redonda. */
.vc-etiqueta,
vc-etiqueta {
  display: inline-flex;
  align-items: center;
  max-width: 100%;
  padding: 0.1em 0.55em;
  border: 1px solid var(--vc-borde);
  border-radius: var(--vc-radio-sm);
  background: var(--vc-superficie-2);
  color: var(--vc-tinta-suave);
  font-family: var(--vc-font-sans);
  font-size: var(--vc-t-nota);
  font-weight: var(--vc-peso-medio);
  line-height: 1.5;
  white-space: nowrap;
  vertical-align: middle;
}

/* El recorrido terminado: todo hecho, y el resumen lo dice. */
vc-recorrido[terminado] .vc-recorrido__resumen strong { color: color-mix(in oklab, var(--vc-ok) 62%, var(--vc-tinta)); }

/* ══ 16. Ciclo — <vc-ciclo> (C03) ══════════════════════════════════════════════
   El recorrido, el estado, los pasos de quien mira y, si no le toca, a quién se
   espera. Los botones son los de la marca; aquí solo su disposición. */
vc-ciclo { display: flex; flex-direction: column; gap: var(--vc-e-3); container-type: inline-size; container-name: vc-ciclo; }
vc-ciclo[aria-busy='true'] { opacity: 0.7; }
.vc-ciclo__estado { display: flex; align-items: center; gap: var(--vc-e-2); margin: 0; }
.vc-ciclo__estado:focus-visible { outline: 2px solid var(--vc-primario); outline-offset: 2px; }
.vc-ciclo__rotulo { font-size: var(--vc-t-nota); color: var(--vc-tinta-suave); }
.vc-ciclo__pasos { display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--vc-e-2) var(--vc-e-3); }
.vc-ciclo__pasos:empty { display: none; }
.vc-ciclo__paso { display: flex; flex-direction: column; gap: var(--vc-e-1); max-width: 22rem; }
.vc-ciclo__paso .vc-boton { width: auto; box-sizing: border-box; }
/* Apagado, pero se alcanza con el tabulador y el lector lee el porqué
   (`aria-disabled` + `aria-describedby`): `disabled` lo sacaría del orden. */
.vc-ciclo__paso .vc-boton[aria-disabled='true'] { opacity: 0.55; cursor: not-allowed; }
.vc-ciclo__paso .vc-boton[aria-disabled='true']:hover { background: var(--vc-primario); }
.vc-ciclo__paso .vc-boton--suave[aria-disabled='true']:hover { background: none; }
.vc-ciclo__paso .vc-boton--peligro[aria-disabled='true']:hover { background: var(--vc-error); }
.vc-ciclo__impedimento { margin: 0; font-size: var(--vc-t-nota); color: var(--vc-tinta-suave); text-wrap: pretty; }
.vc-ciclo__error-paso, .vc-ciclo__error { margin: 0; font-size: var(--vc-t-nota); color: var(--vc-error); }
.vc-ciclo__error:empty { display: none; }
.vc-ciclo__espera { margin: 0; padding: var(--vc-e-2) var(--vc-e-3); border-left: 3px solid var(--vc-laton);
  background: var(--vc-laton-suave); color: var(--vc-tinta); font-size: var(--vc-t-nota); border-radius: var(--vc-radio-sm); }
.vc-ciclo__espera[hidden] { display: none; }
@container vc-ciclo (max-width: 30rem) {
  .vc-ciclo__pasos { flex-direction: column; align-items: stretch; }
  .vc-ciclo__paso { max-width: none; }
  .vc-ciclo__paso .vc-boton { width: 100%; }
}

/* ══ 17. Campana — <vc-campana> (A02, sprint 3) ════════════════════════════════
   En la barra del marco, junto al avatar. En el teléfono, el panel ocupa el
   ancho de la pantalla justo bajo la barra. */
vc-campana { position: relative; display: inline-flex; flex: none; }
.vc-campana__boton {
  position: relative; display: grid; place-items: center;
  width: 2.25rem; height: 2.25rem; padding: 0;
  border: 1px solid var(--vc-borde); border-radius: var(--vc-radio-md);
  background: var(--vc-superficie); color: var(--vc-tinta-suave); cursor: pointer;
}
.vc-campana__boton:hover, .vc-campana__boton[aria-expanded='true'] { color: var(--vc-tinta); border-color: var(--vc-primario); }
.vc-campana__icono { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.vc-campana__numero {
  position: absolute; top: -0.4rem; right: -0.45rem;
  min-width: 1.15rem; height: 1.15rem; padding: 0 0.25rem; box-sizing: border-box;
  display: grid; place-items: center; border-radius: 999px;
  background: var(--vc-primario); color: var(--vc-primario-fg);
  font-size: 0.68rem; font-weight: var(--vc-peso-fuerte); line-height: 1;
  box-shadow: 0 0 0 2px var(--vc-superficie);
}
.vc-campana__numero[hidden] { display: none; }
.vc-campana__panel {
  position: absolute; right: 0; top: calc(100% + var(--vc-e-2)); z-index: 45;
  width: 22rem; max-height: min(70dvh, 32rem); overflow-y: auto;
  background: var(--vc-superficie); color: var(--vc-tinta);
  border: 1px solid var(--vc-borde); border-radius: var(--vc-radio-md); box-shadow: var(--vc-sombra-elevada);
}
.vc-campana__panel[hidden] { display: none; }
.vc-campana__cabeza { display: flex; align-items: center; justify-content: space-between; gap: var(--vc-e-3);
  padding: var(--vc-e-3) var(--vc-e-4); border-bottom: 1px solid var(--vc-borde); position: sticky; top: 0; background: var(--vc-superficie); }
.vc-campana__titulo { margin: 0; font-size: var(--vc-t-cuerpo); font-weight: var(--vc-peso-fuerte); }
.vc-campana__todo[hidden] { display: none; }
.vc-campana__lista { margin: 0; padding: 0; list-style: none; }
.vc-campana__aviso + .vc-campana__aviso { border-top: 1px solid var(--vc-borde); }
.vc-campana__enlace { display: flex; flex-direction: column; gap: 2px; padding: var(--vc-e-3) var(--vc-e-4) var(--vc-e-3) calc(var(--vc-e-4) + 10px);
  position: relative; color: inherit; text-decoration: none; }
a.vc-campana__enlace:hover { background: var(--vc-superficie-2); }
a.vc-campana__enlace:focus-visible { outline-offset: -2px; }
/* Sin leer: un punto (y el lector oye «sin leer»), y el título más fuerte. */
.vc-campana__aviso[data-leido='no'] .vc-campana__enlace::before {
  content: ''; position: absolute; left: var(--vc-e-3); top: calc(var(--vc-e-3) + 0.45em);
  width: 6px; height: 6px; border-radius: 50%; background: var(--vc-primario);
}
.vc-campana__aviso-titulo { font-size: var(--vc-t-cuerpo); font-weight: var(--vc-peso-medio); overflow-wrap: anywhere; }
.vc-campana__aviso[data-leido='no'] .vc-campana__aviso-titulo { font-weight: var(--vc-peso-fuerte); }
.vc-campana__texto { font-size: var(--vc-t-nota); color: var(--vc-tinta-suave); overflow-wrap: anywhere; }
.vc-campana__cuando { font-size: var(--vc-t-nota); color: var(--vc-tinta-tenue); }
.vc-campana__nota { margin: 0; padding: var(--vc-e-5) var(--vc-e-4); text-align: center; color: var(--vc-tinta-suave); font-size: var(--vc-t-nota); }
.vc-campana__nota[hidden] { display: none; }
/* En el teléfono, el panel cuelga de la BARRA (que es `sticky`, y por tanto
   caja de referencia), no de la campana: así ocupa el ancho entero justo
   debajo, sin medir nada —medir fallaba si la barra crecía al cargar la fuente—. */
@media (max-width: 640px) {
  .vc-barra vc-campana { position: static; }
  .vc-campana__panel {
    left: 0; right: 0; width: auto; top: 100%;
    max-height: 75dvh;
    border-radius: 0; border-left: 0; border-right: 0;
  }
}

/* ══ 18. Maestros — <vc-maestro>, VanyLista, «Configurar la ficha» (F03, sprint 4) ══ */
vc-campo[hidden] { display: none !important; }
.vc-campo__ayuda--org { padding-left: var(--vc-e-2); border-left: 2px solid var(--vc-laton); }
.vc-campo__unico { margin: 0; font-size: var(--vc-t-nota); color: color-mix(in oklab, var(--vc-laton) 55%, var(--vc-tinta)); }
.vc-campo__unico:empty { display: none; }
.vc-campo__unico a, .vc-campo__error a { color: inherit; font-weight: var(--vc-peso-medio); }
vc-campo[data-vc-lectura] .vc-campo__unico, vc-campo[data-vc-lectura] .vc-campo__ayuda--org { display: none; }
.vc-ficha__avisos { margin-bottom: var(--vc-e-4); }
.vc-ficha__avisos ul { margin: var(--vc-e-1) 0 0; padding-left: var(--vc-e-5); }

vc-maestro[sin-titulo] .vc-maestro__cabeza { justify-content: flex-end; }   /* sin `h2`: los botones, donde estaban */
vc-maestro { display: flex; flex-direction: column; gap: var(--vc-e-4); container-type: inline-size; container-name: vc-maestro; }
.vc-maestro__cabeza { display: flex; flex-wrap: wrap; align-items: center; gap: var(--vc-e-2) var(--vc-e-4); }
.vc-maestro__volver { flex-basis: 100%; text-align: left; font-size: var(--vc-t-nota); }
.vc-maestro__titulo { margin: 0; flex: 1 1 12rem; font-size: var(--vc-t-titulo); font-weight: var(--vc-peso-fuerte); overflow-wrap: anywhere; }
/* La letra es la del maestro, no la de los `h2` y `label` de la página (posplan-4, marca-t1:
   en VanyFactura, hasta 0018, su `estilos.css` ponía en todo `h2` y todo `label` mayúsculas,
   mono, espaciado y el filete de un `::after`, y el título salía «PRODUCTOS» con raya). */
.vc-maestro__titulo { display: block; font-family: var(--vc-font-sans); letter-spacing: normal; text-transform: none; color: var(--vc-tinta); }
.vc-maestro__titulo::before, .vc-maestro__titulo::after { content: none; display: none; }
:is(.vc-maestro__baja, .vc-maestro__filtro > label) { margin: 0; font-family: var(--vc-font-sans); font-size: var(--vc-t-nota);
  letter-spacing: normal; text-transform: none; }
.vc-maestro__baja { display: flex; }
/* `solo_crear` al editar (posplan-4): el campo sale en lectura y su nota se ve. */
vc-campo[data-vc-solo-crear][data-vc-lectura] .vc-campo__ayuda { display: block; }
.vc-maestro__titulo:focus-visible { outline: 2px solid var(--vc-primario); outline-offset: 2px; }
.vc-maestro__botones { display: flex; flex-wrap: wrap; gap: var(--vc-e-2); }
.vc-maestro__filtros { display: flex; flex-wrap: wrap; align-items: end; gap: var(--vc-e-2) var(--vc-e-4); margin-bottom: var(--vc-e-2); }
.vc-maestro__filtros:empty { display: none; }
.vc-maestro__filtro { display: flex; flex-direction: column; gap: var(--vc-e-1); font-size: var(--vc-t-nota); color: var(--vc-tinta-suave); }
.vc-maestro__filtro select { min-height: 2.5rem; padding: var(--vc-e-2) var(--vc-e-3); font: inherit; color: var(--vc-tinta);
  background: var(--vc-superficie); border: 1px solid var(--vc-borde); border-radius: var(--vc-radio-md); }
.vc-maestro__mas { margin-top: var(--vc-e-3); }
.vc-maestro__mas[hidden] { display: none; }
.vc-maestro__abrir { color: var(--vc-primario); font-weight: var(--vc-peso-medio); text-decoration: underline; text-underline-offset: 2px;
  display: inline-block; box-sizing: border-box; min-height: 24px; padding-block: 4px; margin-block: -4px; }   /* el dedo: 24 px, sin mover la fila */
.vc-maestro__baja { min-height: 24px; }   /* la casilla se pulsa por su etiqueta entera */
vc-maestro tr[data-activo='no'] td { color: var(--vc-tinta-suave); }
@container vc-maestro (max-width: 30rem) {
  .vc-maestro__botones { flex-basis: 100%; }
  .vc-maestro__botones .vc-boton { flex: 1 1 auto; }
}

.vc-config__bloque { display: flex; flex-direction: column; gap: var(--vc-e-3); padding: var(--vc-e-5); background: var(--vc-superficie);
  border: 1px solid var(--vc-borde); border-radius: var(--vc-radio-lg); margin-bottom: var(--vc-e-4); }
.vc-config__bloque h3 { margin: 0; font-size: var(--vc-t-subtitulo); }
.vc-config__seccion-titulo { margin: var(--vc-e-2) 0 0; font-size: var(--vc-t-nota); color: var(--vc-tinta-suave); font-weight: var(--vc-peso-fuerte); }
.vc-config__lista { display: flex; flex-direction: column; margin: 0; padding: 0; list-style: none; }
.vc-config__campo { display: flex; flex-direction: column; gap: var(--vc-e-2); padding: var(--vc-e-3) 0; border-bottom: 1px solid var(--vc-borde); }
.vc-config__campo:last-child { border-bottom: 0; }
.vc-config__cabeza { display: flex; flex-wrap: wrap; align-items: center; gap: var(--vc-e-1) var(--vc-e-2); }
.vc-config__seccion { font-size: var(--vc-t-nota); color: var(--vc-tinta-tenue); }
.vc-config__controles { display: flex; flex-wrap: wrap; align-items: end; gap: var(--vc-e-2) var(--vc-e-5); }
.vc-config__controles .vc-campo { flex: 1 1 16rem; }
.vc-config__controles .vc-campo input { min-height: 2.5rem; padding: var(--vc-e-2) var(--vc-e-3); font: inherit; color: var(--vc-tinta);
  background: var(--vc-superficie); border: 1px solid var(--vc-borde); border-radius: var(--vc-radio-md); width: 100%; box-sizing: border-box; }
.vc-config__vacio { padding: var(--vc-e-3) 0; color: var(--vc-tinta-suave); font-size: var(--vc-t-nota); }
.vc-config__nuevo { padding-top: var(--vc-e-3); border-top: 1px dashed var(--vc-borde); }
.vc-config__nuevo[hidden], .vc-config__retirados-caja[hidden], .vc-config__historial[hidden] { display: none; }
/* Sprint 13: los retirados (D6) y el historial de la ficha. */
.vc-config__retirados-caja { display: flex; flex-direction: column; gap: var(--vc-e-1); padding-top: var(--vc-e-3); border-top: 1px dashed var(--vc-borde); }
.vc-config__retirados .vc-config__campo strong { color: var(--vc-tinta-suave); font-weight: var(--vc-peso-medio); }
.vc-config__cuenta { margin: 0; }
.vc-config__versiones { display: flex; flex-direction: column; gap: var(--vc-e-3); margin: 0; padding: 0; list-style: none; }
.vc-config__version { padding-bottom: var(--vc-e-3); border-bottom: 1px solid var(--vc-borde); }
.vc-config__version:last-child { padding-bottom: 0; border-bottom: 0; }
.vc-config__version-cabeza { margin: 0; font-size: var(--vc-t-nota); color: var(--vc-tinta-suave); overflow-wrap: anywhere; }
.vc-config__version-cabeza strong { color: var(--vc-tinta); }
.vc-config__cambios { margin: var(--vc-e-1) 0 0; padding-left: var(--vc-e-5); overflow-wrap: anywhere; }

/* ══ Lista múltiple (sprint 9, M06) ════════════════════════════════════════════
   <vc-campo tipo="lista" multiple>: una casilla por opción, en una rejilla que se
   reparte el ancho (una columna a 360 px). Lo que viaja: un `hidden` por opción
   elegida, con el mismo `name` (FormData.getAll). */
.vc-campo__varias { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 12rem), 1fr));
  gap: var(--vc-e-2) var(--vc-e-4); margin: 0; padding: 0; border: 0; }
.vc-campo__varias label { display: flex; align-items: center; gap: var(--vc-e-2); min-height: 2.75rem; font-weight: var(--vc-peso-normal, 400); cursor: pointer; }
.vc-campo__varias input[type='checkbox'] { width: 1.15rem; height: 1.15rem; margin: 0; accent-color: var(--vc-primario); flex: none; }
vc-campo[data-vc-lectura][multiple] .vc-campo__varias { display: none; }

/* ══ La caja de contenido (posplan-4, marca-t1; guía §5.25) ═════════════════════
   Para agrupar en cualquier pantalla —también React— lo que hasta hoy era
   `.vc-consola__caja` (solo la consola) o una caja propia con tokens (Aula,
   Taller, Flow). Sin sombra: la sombra es de la tarjeta de acceso. */
.vc-caja { box-sizing: border-box; min-width: 0; display: flex; flex-direction: column; gap: var(--vc-e-3);
  background: var(--vc-superficie); border: 1px solid var(--vc-borde); border-radius: var(--vc-radio-lg);
  padding: var(--vc-e-4); color: var(--vc-tinta); }
.vc-caja--suave { background: var(--vc-superficie-2); border-color: transparent; }
.vc-caja--compacta { padding: var(--vc-e-3); }
.vc-caja__cabecera { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--vc-e-2) var(--vc-e-4); }
.vc-caja__titulo { margin: 0; font-size: var(--vc-t-subtitulo); font-weight: var(--vc-peso-fuerte); overflow-wrap: break-word; min-width: 0; }
.vc-caja__nota { margin: 0; font-size: var(--vc-t-nota); color: var(--vc-tinta-suave); max-width: 65ch; }
.vc-caja__pie { display: flex; flex-wrap: wrap; align-items: center; gap: var(--vc-e-2) var(--vc-e-3); }
